def process(self): if not self.__gitflow.is_release(): raise NoBranchSelected('Checkout to release branch before') if not self.__git.is_clean_working_tree(): raise NotCleanWorkingTree() self.__pull_master() if self.__git.is_branch_ahead(self.__config_handler.master(), self.__name): Log.error(""" {fg_fail}{list}{reset_fg} """.format( fg_fail=Fg.FAIL.value, list=self.__git.list_commit_diff( self.__config_handler.master(), self.__name), reset_fg=Fg.RESET.value, )) self.__checkout_current_release() raise BranchHaveDiverged(""" {fg_fail}{message}{reset_fg} """.format( fg_fail=Fg.FAIL.value, message='Oups !!! Master:' + self.__config_handler.master() + ' have commit ahead ' + self.__name + ' merge before', reset_fg=Fg.RESET.value, )) self.__pull_develop().__finish_release()
def __attach(self) -> bool: topic_number: int if self.__would_attach_topics(): for topic_number in self.__topics_number(): request_topic: FlexioTopic = FlexioTopic().with_number( topic_number) try: Log.info('waiting... from Flexio... Topic : ' + str(topic_number)) topic: FlexioTopic = self.__get_topic_with_number( request_topic) CommonTopic.print_resume_topic(topic) self.__topics.append(topic) except FileNotFoundError: Log.error(Fg.FAIL.value + 'Topic not found : retry' + Fg.RESET.value) self.__topics = [] return self.process() return True else: return False
def process(self): if not self.__git.is_clean_working_tree(): raise NotCleanWorkingTree() if not self.__gitflow.is_feature(): raise BranchNotExist(self.__config_handler.feature()) self.__pull_develop() if self.__git.is_branch_ahead(self.__config_handler.develop(), self.__current_branch_name): Log.error(""" {fg_fail}{list}{reset_fg} """.format( fg_fail=Fg.FAIL.value, list=self.__git.list_commit_diff( self.__config_handler.develop(), self.__current_branch_name), reset_fg=Fg.RESET.value, )) self.__checkout_current_feature() raise BranchHaveDiverged(""" {fg_fail}{message}{reset_fg} """.format( fg_fail=Fg.FAIL.value, message='Oups !!! Develop have commit ahead ' + self.__current_branch_name + ' merge before', reset_fg=Fg.RESET.value, )) self.__finish_feature()
def __merge_develop(self) -> Finish: self.__checkout_current_feature() message: Message = Message(message=''.join([ "'Finish feature ` ", self.__current_branch_name, " ` for dev: ", self.__state_handler.version_as_str() ]), issue=self.__issue) message_str: str = '' if self.__close_issue: message_str = message.with_close() else: message_str = message.message self.__git.commit(message_str, ['--allow-empty']).try_to_push() self.__git.checkout(self.__config_handler.develop( )).merge_with_version_message_from_branch_name( branch=self.__current_branch_name, message=Message(message='', issue=self.__issue).with_ref(), ).try_to_push() if self.__git.has_conflict(): Log.error(""" {fg_fail}CONFLICT : resolve conflict, and remove your feature branch manually{reset_fg} """.format( fg_fail=Fg.FAIL.value, reset_fg=Fg.RESET.value, )) raise GitMergeConflictError(self.__config_handler.develop(), self.__git.get_conflict()) return self
def comment_issue_with_topic(self, topic: Topic) -> IssueBuilder: if self.__issue is not None: Log.info('Waiting... Comment issue with topics : ' + str(topic.number)) self.__issuer.comment(self.__issue, 'Topic : ' + topic.url()) return self
def create_branch_from(self, target_branch_name: str, source: str) -> GitCmd: source_branch_name: str = self.get_branch_name_from_git(source) self.__exec(['git', 'checkout', '-b', target_branch_name, source_branch_name]) try: self.__state_handler.load_file_config() except FileNotFoundError as e: Log.error(str(e)) return self
def init_repo(cls, version: str) -> StateHandler: cls.clean_workdir() cls.mount_workdir_and_clone() state_handler: StateHandler = StateHandler(cls.DIR_PATH_TEST) state_handler.state = cls.fake_state(version) Git(state_handler).build_branch(Branches.DEVELOP).with_action( Actions.INIT).process() Log.info('init repo : ' + str(version)) return state_handler
def clean_remote_repo(cls, version: Version = Version(0, 0, 0)): git: GitCmd = GitCmd( state_handler=StateHandler(TestGitFlowHelper.DIR_PATH_TEST)) git.checkout(Branches.MASTER).reset_to_tag(cls.TAG_INIT) \ .push_force() \ .delete_remote_branch_from_name(Branches.DEVELOP.value) \ .delete_tag(str(version), remote=True) \ .delete_tag('-'.join([str(version.next_minor()), Level.DEV.value]), remote=True) Log.info('clean remote repo : ' + str(version))
def ensure_develop_branch(self) -> GitFlowCmd: Log.info('Ensure have Develop branch : ' + self.__config_handler.develop()) if not self.__git.branch_exists(self.__config_handler.develop()): self.__git.checkout( self.__config_handler.master()).create_branch_from( self.__config_handler.develop(), self.__config_handler.master()).try_to_set_upstream( ).try_to_push() return self
def process(self): Log.info('Start unstable version precheck') scheme: Schemes for scheme in self.state_handler.state.schemes: Log.info('Precheck for : ' + scheme.value) sc: Scheme = SchemeBuilder.create(scheme, self.state_handler) dev_dependencies: Dependencies = sc.release_precheck() print(dev_dependencies.__dict__()) if len(dev_dependencies): raise HaveDevDependencyException(dev_dependencies)
def __list_topics(self, count: int): Log.info('waiting... Flexio... last 100 Topics') records: List[dict] = self.__get_last_100_records() for t_d in records: t: FlexioTopic t = FlexioTopic.build_from_api(t_d) print( '{fg_cyan}{topic_number!s} : {topic_title!s}{reset_fg}'.format( fg_cyan=Fg.INFO.value, reset_fg=Fg.RESET.value, topic_number=t.number, topic_title=t.title)) return self.__topics_number()
def has_repo(self) -> bool: has_repo: bool = False try: repo: Repo = GitCmd(self.state_handler, self.options.debug).with_config_handler( self.config_handler).get_repo() has_repo = True except ValueError as e: if self.options.debug: print(e) Log.info('GithubIssuer have not repo') finally: return has_repo
def __ensure_stash_start(self): if not self.options.auto_stash and not self.options.default: if self.options.no_cli is not True: auto_stash: str = input(' Stash your working tree Y/N : ' + Fg.SUCCESS.value + 'N' + Fg.RESET.value + ' ') auto_stash_b = True if auto_stash.capitalize( ) == 'Y' else False self.options.auto_stash = auto_stash_b if self.options.auto_stash: self.version_control.stash_start() Log.info('Working tree stashed')
def find_issue_from_branch_name(self) -> IssueBuilder: if self.__issuer is not None: issue_number: Optional[ int] = self.__version_control.get_issue_number() if issue_number is not None: self.__issue = self.__issuer.issue_builder().with_number( issue_number) if self.__issue is not None: Log.info('Issue number ' + str(self.__issue.number) + ' found') else: Log.info('No Issue found') return self
def is_clean_working_tree(self) -> bool: if len(self.__exec_for_stdout(['git', 'rev-parse', '--verify', 'HEAD'])) == 0: return False self.__exec(['git', 'update-index', '-q', '--ignore-submodules', '--refresh']) if len(self.__exec_for_stdout(['git', 'diff-files', '--ignore-submodules'])) > 0: Log.error("Working tree contains unstaged changes. Aborting.") return False if len(self.__exec_for_stdout( ['git', 'diff-index', '--cached', '--ignore-submodules', 'HEAD'])) > 0: Log.error("Index contains uncommited changes. Aborting.") return False return True
def find_topic_from_branch_name(self) -> TopicBuilder: if self.__topicer is not None: topics_number: Optional[List[int]] = self.__version_control.get_topics_number() if topics_number is not None and len(topics_number) > 0: self.__topics = [] for number in topics_number: self.__topics.append(self.__topicer.topic_builder().with_number(number)) if self.__topics is not None and len(self.__topics) > 0: for topic in self.__topics: Log.info('Topic number ' + str(topic.number) + ' found') else: Log.info('No Topic found') return self
class UserController: def __init__(self): self.logger = Log("AdminController") self.STATES = dict() self.NEXT_STATES = dict() def update_create_user(self, chat): try: user = User.objects.filter(chat_id=chat.id).first() if user: user.last_checked_bot = timezone.now() user.state = self.NEXT_STATES[user.state] user.save(force_update=True) return user else: self.logger.info("New User start subX : \n{}".format(chat)) username = chat.username last_name = chat.last_name first_name = chat.first_name new_user = User(chat_id=chat.id, username=username, first_name=first_name, last_name=last_name, chat_type=chat.type) new_user.save(force_insert=True) return user except Exception as e: self.logger.error("update_create_user : {}".format(e)) def update_user_state(self, chat_id, user=None): if user is None: user = User.objects.filter(chat_id=chat_id).first() if not user: raise NotImplementedError( "user {} not implemented".format(chat_id)) user.state = self.NEXT_STATES[user.state] user.save(force_update=True) return user.state @staticmethod def get_user_state(chat_id): return User.filter.objects(chat_id=chat_id).first().state def set_states(self, states): self.STATES = states def set_next_states_dict(self, next_states): self.NEXT_STATES = next_states
def __input_topics(self) -> Init: if self.config_handler.has_topicer(): self.__topicer: Optional[Topicer] = TopicerHandler( self.state_handler, self.config_handler).topicer() self.__topics: List[Topic] = self.__topicer.attach_or_create() self.state_handler.state.topics = [] for topic in self.__topics: self.state_handler.state.topics.append( DefaultTopic().with_number(topic.number)) else: Log.info('No topicer found') self.state_handler.state.topics = None return self
def __merge_develop(self) -> Finish: self.__checkout_current_hotfix() self.__state_handler.next_dev_minor() self.__state_handler.set_dev() self.__state_handler.write_file() UpdateSchemeVersion.from_state_handler(self.__state_handler) self.__git.commit( Message(message=''.join([ "'Finish hotfix for dev: ", self.__state_handler.version_as_str() ]), issue=self.__issue).with_ref()).try_to_push() self.__git.checkout( self.__config_handler.develop()).merge_with_version_message( branch=self.__config_handler.hotfix(), message=Message(message='', issue=self.__issue).with_ref()).try_to_push() if (self.__git.has_conflict()): Log.error(""" {fg_fail}CONFLICT : resolve conflict, and remove your hotfix branch manually{reset_fg} """.format( fg_fail=Fg.FAIL.value, reset_fg=Fg.RESET.value, )) raise GitMergeConflictError(self.__config_handler.develop(), self.__git.get_conflict()) self.__git.checkout(self.__config_handler.develop()).merge_with_theirs( branch=self.__config_handler.master()).try_to_push() if (self.__git.has_conflict()): Log.error(""" {fg_fail}CONFLICT : resolve conflict, and remove your hotfix branch manually{reset_fg} """.format( fg_fail=Fg.FAIL.value, reset_fg=Fg.RESET.value, )) raise GitMergeConflictError(self.__config_handler.develop(), self.__git.get_conflict()) return self
def __merge_master(self) -> Finish: self.__git.checkout(self.__config_handler.hotfix()) self.__state_handler.set_stable() self.__state_handler.write_file() UpdateSchemeVersion.from_state_handler(self.__state_handler) message: Message = Message(message=''.join([ "'Finish hotfix for master: ", self.__state_handler.version_as_str() ]), issue=self.__issue) message_str: str = '' if self.__close_issue: message_str = message.with_close() else: message_str = message.message self.__git.commit(message_str).try_to_push() self.__git.checkout( self.__config_handler.master()).merge_with_version_message( branch=self.__config_handler.hotfix(), message=Message(message='', issue=self.__issue).with_ref(), options=['--no-ff']).tag( self.__state_handler.version_as_str(), ' '.join([ "'From Finished hotfix : ", self.__git.get_branch_name_from_git( self.__config_handler.hotfix()), 'tag : ', self.__state_handler.version_as_str(), "'" ])).try_to_push_tag( self.__state_handler.version_as_str()).try_to_push() if (self.__git.has_conflict()): Log.error(""" {fg_fail}CONFLICT : resolve conflict, merge into develop and remove your hotfix branch manually{reset_fg} """.format( fg_fail=Fg.FAIL.value, reset_fg=Fg.RESET.value, )) raise GitMergeConflictError(self.__config_handler.master(), self.__git.get_conflict()) return self
def __merge_master(self) -> Finish: message: Message = Message(message='Merge ' + self.__name + 'into ' + self.__config_handler.master(), issue=self.__issue) message_str: str = '' if self.__close_issue: message_str = message.with_close() else: message_str = message.message self.__git.commit(message_str, ['--allow-empty']) self.__git.checkout( self.__config_handler.master()).merge_with_version_message( branch=self.__config_handler.release(), message=message_str, options=['--no-ff', '--strategy-option', 'theirs']) if self.__git.has_conflict(): raise GitMergeConflictError(self.__config_handler.master(), self.__git.get_conflict()) tag: str = self.__state_handler.version_as_str() if tag != self.__version_check: Log.error('Version have diverged during merge : ' + tag + 'should be ' + self.__version_check) raise GitMergeConflictError(self.__config_handler.master()) self.__git.tag( tag, ' '.join( ["'From Finished release : ", self.__name, 'tag : ', tag, "'"])).try_to_push_tag(tag).try_to_push() self.__git.checkout(self.__config_handler.release( )).merge_with_version_message_from_branch_name( branch=tag, message=Message(message='Merge ' + tag + ' tag into ' + self.__name, issue=self.__issue).with_ref(), options=['--no-ff']) return self
def __init_develop(self) -> Init: version: str = '-'.join( [str(self.__state_handler.state.version), Level.DEV.value]) self.__git.checkout_without_refresh_state( self.__config_handler.develop()) self.__state_handler.write_file() UpdateSchemeVersion.from_state_handler(self.__state_handler) self.__git.add_all().commit(''.join([ "'Init develop as branch name: ", self.__config_handler.develop(), " at version:", version, "'" ])).try_to_set_upstream() Log.info('Init develop as branch name: ' + self.__config_handler.develop() + ' at version: ' + version) return self
def process(self): if self.action is IssueActions.READ: issuer_builder: issuer_builder = IssueBuilder( self.version_control, self.state_handler, self.config_handler, None, self.options) issue: Optional[ AbstractIssue] = issuer_builder.find_issue_from_branch_name( ).issue() if issue is not None: Log.info('waiting... from github...') read_issue: Optional[AbstractIssue] = issuer_builder.issuer( ).read_issue_by_number(issue.number) if read_issue is not None: pprint(read_issue.__dict__()) elif self.action is IssueActions.COMMENT: raise NotImplementedError
def __attach(self) -> bool: if self.__would_attach_issue(): issue_number = self.__number_issue() issue: IssueGithub = IssueGithub().with_number(issue_number) try: Log.info('waiting... from Github... Issue : ' + str(issue_number)) r: Response = self.__read_issue(issue) self.__issue: IssueGithub = IssueGithub.from_api_dict(r.json()) CommonIssue.print_resume_issue(self.__issue) except FileNotFoundError: Log.error(Fg.FAIL.value + 'Issue not found : retry' + Fg.RESET.value) return self.process() return True else: return False
def try_ensure_topic(self) -> TopicBuilder: if self.__config_handler.has_topicer() and self.__topicer is not None: if self.__state_handler.has_default_topic(): Log.info('waiting for... default Topics...') self.__build_default() Log.info(str(len(self.__topics)) + ' Topics found') if self.__topics is not None: for topic in self.__topics: CommonTopic.print_resume_topic(topic) if not self.__options.default: use_default_topic: str = input( 'Use these topics ' + Fg.SUCCESS.value + 'y' + Fg.RESET.value + '/n : ') if use_default_topic.lower() == 'n': self.__topics = None else: Log.info('No default Topic found') if self.__topics is None and not self.__options.default: self.__topics: List[Topic] = self.__topicer.attach_or_create() return self
def is_local_remote_equal(self, branch: str) -> bool: if not self.branch_exists(branch): raise BranchNotExist(branch) local_branch: str = self.local_branch_name(branch) remote_branch: str = self.remote_branch_name(branch) compare_refs: int = self.compare_refs(local_branch, remote_branch) if compare_refs > 0: print("Branches '{local_branch!s}' and '{remote_branch!s}' have diverged.".format(local_branch=local_branch, remote_branch=remote_branch)) if compare_refs == 1: print("And branch '{local_branch!s}' may be fast-forwarded.".format(local_branch=local_branch)) elif compare_refs == 2: print("And local branch '{local_branch!s}' is ahead of '{remote_branch!s}'.".format( local_branch=local_branch, remote_branch=remote_branch )) else: Log.warning("Branches need merging first.") return False return True
def __ensure_is_major(self, branch: Branch) -> Branch: if self.branch is Branches.RELEASE: if not self.version_control.is_current_branch_develop(): raise NoBranchSelected('Checkout to develop branch before') is_major_b: bool = False if self.options.major is None and not self.options.default: if self.options.no_cli is not True: is_major: str = input(' Is major Release Y/N : ' + Fg.SUCCESS.value + 'N' + Fg.RESET.value + ' ') is_major_b = True if is_major.capitalize( ) == 'Y' else False self.options.major = is_major_b else: is_major_b = self.options.major is True if is_major_b: Log.info('Release option Major set from options') branch.with_major(is_major=is_major_b) return branch
def process(self): if self.action is TopicActions.READ: topic_builder: TopicBuilder = TopicBuilder(self.version_control, self.state_handler, self.config_handler, None, self.options) topics: Optional[List[ AbstractTopic]] = topic_builder.find_topic_from_branch_name( ).topics() if topics is not None and len(topics) > 0: for topic in topics: Log.info('waiting... from flexio...') read_topic: Optional[ AbstractTopic] = topic_builder.topicer( ).read_topic_by_number(int(topic.number)) if read_topic is not None: CommonTopic.print_resume_topic(read_topic) else: Log.warning('No Topic found')
def ensure_master_branch(self) -> GitFlowCmd: Log.info('Ensure have Master branch : ' + self.__config_handler.master()) if not self.__git.local_branch_exists(self.__config_handler.master()): if not self.__git.remote_branch_exists( self.__config_handler.master()): Log.warning(self.__config_handler.master() + ' not exists') create: str = input('Create ' + self.__config_handler.master() + ' from current branch ? y/' + Fg.SUCCESS.value + 'n' + Fg.RESET.value + ' : ') if create == 'y': self.__git.create_branch_from( self.__config_handler.master(), self.__git.get_current_branch_name() ).try_to_set_upstream().try_to_push() self.ensure_master_branch() else: raise BranchNotExist(self.__config_handler.master()) else: Log.error('Remote branch : ' + self.__config_handler.master() + ' already exists, pull before') return self
def __ensure_stash_end(self): if self.options.auto_stash: self.version_control.stash_end() Log.info('Stashed work restored ')