diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6aaa5ea28..14d67f45d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,17 +24,20 @@ jobs: uses: actions/setup-python@v3 with: python-version: "3.10" + - run: pip install PyGithub - name: Gather Release Information id: release_info run: | echo "::set-output name=release_title::$(git show --format=%s --no-patch | head -1)" echo "::set-output name=release_version::$(TZ=Asia/Shanghai date +'v%Y%m%d%H%M')" - changelog=$(python scripts/parse-changelog.py CHANGE_LOGS.md) + changelog=$(python scripts/parse-changelog.py -t ${{ github.ref }} siyuan-note/siyuan) changelog="${changelog//'%'/'%25'}" changelog="${changelog//$'\n'/'%0A'}" changelog="${changelog//$'\r'/'%0D'}" echo "::set-output name=release_body::$changelog" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Extract version from package.json uses: sergeysova/jq-action@v2 @@ -50,7 +53,7 @@ jobs: with: release_name: ${{ steps.release_info.outputs.release_version }} tag_name: ${{ github.ref }} - body: ${{ github.ref }} + body: ${{ steps.release_info.outputs.release_body }} draft: false prerelease: true diff --git a/scripts/parse-changelog.py b/scripts/parse-changelog.py index 1eb1e0d35..6646a4a28 100644 --- a/scripts/parse-changelog.py +++ b/scripts/parse-changelog.py @@ -1,32 +1,95 @@ -#!/usr/bin/env python3 -from pathlib import Path +import os +import re from argparse import ArgumentParser +from collections import defaultdict + +import github + +docmap = { + "Enhancement": "改进功能", + "Document": "文档相关", + "Refactor": "开发重构", + "Bug": "修复缺陷", + "Features": "引入特性", + "Abolishments": "移除功能" +} -def parse_latest_changelog(text: str) -> str: - """Read the contents between the first `##` and the second `##`""" - recording = False - contents: list[str] = [] - for line in text.splitlines(): - if line.strip().startswith("## ") and recording is False: - recording = True - elif line.strip().startswith("## ") and recording is True: - break - if recording: - contents.append(line) +def generate_msg_from_repo(repo_name, tag_name): + """Generate changelog messages from repository and tag name. - return "\n".join(contents[1:]) + Envs: + GITHUB_HOST: the custom github host. + GITHUB_TOKEN: the github access token. + + Args: + repo_name (str): The repository name + tag_name (str): the tag name + """ + hostname = os.getenv("GITHUB_HOST") or "api.github.com" + token = os.getenv("GITHUB_TOKEN") + desc_mapping = defaultdict(list) + + gh = github.Github(token, base_url=f"https://{hostname}") + repo = gh.get_repo(repo_name) + milestone = find_milestone(repo, tag_name) + + for issue in repo.get_issues(state="closed", milestone=milestone): + desc_mapping[get_issue_first_label(issue)].append( + {"title": issue.title, "url": issue.url} + ) + generate_msg(desc_mapping) -def get_changelog() -> str: - parser = ArgumentParser(description="Get the latest change log from CHANG_LOGS.md") - parser.add_argument("changelog_file", help="The path of CHANGE_LOGS.md") +def find_milestone(repo, title): + """Find the milestone in a repository that is similar to milestone title + + Args: + repo (github.repository.Repository): The repository to search + title (str): the title to match + + Returns: + The milestone which title matches the given argument. + If no milestone matches, it will return None + """ + pat = re.search("v([0-9.]+)", title) + if not pat: + return None + version = pat.group(1) + for milestone in repo.get_milestones(): + if version in milestone.title: + return milestone + + +def get_issue_first_label(issue): + """Get the first label from issue, if no labels, return empty string.""" + for label in issue.get_labels(): + if label.name in docmap: + return label.name + return "" + + +def generate_msg(desc_mapping): + """Print changelogs from direction.""" + print() + for header in docmap: + if not desc_mapping[header]: + continue + print(f"### {docmap[header]}\n") + for item in desc_mapping[header]: + print(f"* [{item['title']}]({item['url']})") + print() + + +if __name__ == "__main__": + parser = ArgumentParser( + description="Automaticly generate information from issues by tag." + ) + parser.add_argument("-t", "--tag", help="the tag to filter issues.") + parser.add_argument("repo", help="The repository name") args = parser.parse_args() - with Path(args.changelog_file).open() as f: - return f.read() - -if __name__ == '__main__': - changelog = get_changelog() - latest_changelog = parse_latest_changelog(changelog) - print(latest_changelog) + try: + generate_msg_from_repo(args.repo, args.tag) + except AssertionError: + print(args.tag)