LGTM Devlog 34: GitHub 문제에 게시하는 캐릭터

오늘 여러 가지가 합쳐지면서 몇 가지 큰 변화가 생겼습니다! 대부분의 작업은 이제 stages 모듈에 있으며 이 냄비에 대한 코드는 커밋0e67f0d에 있습니다.

지연 단계



시간 제한 이벤트에 작업 대기열 시스템을 사용하는 대신 시간 지연을 적용하는 퀘스트 단계DelayStage를 추가하기로 결정했습니다. 이것은 인프라의 일부를 녹아웃하여 복잡성을 줄이고 기존 인프라를 고려하여 작성하기가 놀라울 정도로 쉬웠습니다.

class DelayStage(Stage):
    """ For enacting a time delay """

    @property
    @abstractmethod
    def delay(cls) -> timedelta:
        """ how much time to delay """
        return NotImplemented

    def prepare(self) -> None:
        """ On first run, insert datetime """
        if self.get_stage_data() is None:
            now = datetime.now().timestamp()
            logger.info(f"Delay stage prepare", now=now)
            self.set_stage_data(now)

    def condition(self) -> bool:
        """ Calculate whether that has elapsed """
        target = datetime.utcfromtimestamp(self.get_stage_data(0)) + self.delay
        now = datetime.now()
        logger.info(f"Delay stage prepare", now=now, target=target)
        return now > target


DelayStage는 prepare() 이벤트를 사용하여 대상 타임스탬프와 조건이 다음에 실행될 때 해당 단계 저장소(단계별 데이터를 저장하기 위해 퀘스트 데이터 저장소 모델에 추가한 새로운 자유 형식 dict 값)에 기록합니다. , 이 시간에 도달했는지 또는 초과했는지 테스트합니다! 매우 간단합니다.

문제 만들기



이제 github 메시지를 게시할 문자 코드가 있으므로 사용자 포크에 새 문제를 생성하는 CreateIssueStage()를 추가할 수 있습니다. 다음과 같습니다.


class CreateIssueStage(Stage):
    """ This stage posts a new issue to a user's fork """

    @property
    @abstractmethod
    def character(cls) -> Character:
        """ Which character will post the issue """
        return NotImplemented

    @property
    @abstractmethod
    def issue_title(cls) -> str:
        """ Issue title """
        return NotImplemented

    @property
    @abstractmethod
    def issue_body(cls) -> str:
        """ Issue main body """
        return NotImplemented

    # variable to store resulting issue ID in for later
    issue_id_variable: Optional[int] = None

    def execute(self) -> None:
        """ Post the issue to the fork """
        game = self.quest.quest_page.game
        game.load()
        fork_url = game.data.fork_url

        logger.info("Creating issue", title=self.issue_title, fork_url=fork_url)
        issue_id = self.character.issue_create(
            fork_url, self.issue_title, self.issue_body
        )

        if self.issue_id_variable:
            logger.info(
                "Storing issue Id in variable",
                issue_id=issue_id,
                variable=self.issue_id_variable,
            )
            setattr(self.quest.quest_data, self.issue_id_variable, issue_id)


캐릭터, 이슈 제목 등에 대한 몇 가지 추상 속성이 있습니다. 클래스의 비즈니스 부분은 지난 번에 정의된 패키지의 일부인 character.isseu_create()를 호출합니다. 나머지execute() 이벤트는 fork_url을 가져오고 선택한 위치에 결과를 저장하여 다른 단계에서 사용할 수 있도록 생성된 문제 ID를 단계에서 출력할 수 있도록 처리합니다.

사용법은 다음과 같습니다.

class IntroQuest(Quest):
    class QuestDataModel(QuestBaseModel):
        issue_id: Optional[str] = None
        last_comment: Optional[datetime] = None

    version = VersionInfo.parse("0.1.0")
    difficulty = Difficulty.BEGINNER
    description = "The intro quest"

    class Start(CreateIssueStage):
        children = ["CheckNumber1"]
        character = character_garry
        issue_id_variable = "issue_id"
        issue_title = "Welcome, can you give me a hand?"
        issue_body = """\
            Hello therre!
        """

"""\의 이유는 여러 줄 문자열에 대한 소스 코드에서 의도를 더 멋지게 유지하는 pythonsdedent 방법을 사용하기 때문입니다.

Start 이벤트가 발생하면 character_garry로 정의된 문자를 사용하여 주어진 문제 제목 및 본문과 함께 문제를 플레이어의 포크로 보냅니다. 또한 다음 단계에서 재사용할 수 있도록 quest 데이터 모델issue_id 키에 issue_id를 저장합니다.

테스트



테스트를 위해 공개된 데이터 스팸을 피하기 위해 비공개 github 저장소에 대한 포크를 위조하도록 테스트 파일을 덮어썼습니다. 이것은 일반적으로 정상적인 흐름 중에 GitHub에서 불가능하지만 우리 시스템은 구별하지 않으므로 기꺼이 테스트의 일부로 받아들입니다.



이미 테스트 사용자의 게임을 삭제하고 새 게임을 시작하여 첫 번째 문제의 생성을 테스트하기 위해 이미 github_webhook_listener에 있는 테스트를 실행할 수 있습니다. test_main_tick에 이미 정의된 테스트를 사용하여 후속 단계를 테스트할 수도 있습니다.

좋은 웹페이지 즐겨찾기