🎨 更新 parse-changelog 工作流 (#11289)

This commit is contained in:
绛亽 2024-05-07 22:13:59 +08:00 committed by GitHub
parent 291a083378
commit 5095d836c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 135 additions and 74 deletions

View file

@ -29,10 +29,10 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"
- run: pip install PyGithub
- id: thislatestR
- id: thisLatestRelease
uses: pozetroninc/github-action-get-latest-release@master
with:
# owner: siyuan-note
@ -46,9 +46,11 @@ jobs:
run: |
echo "release_title=$(git show --format=%s --no-patch | head -1)" >> $GITHUB_OUTPUT
echo "release_version=$(TZ=Asia/Shanghai date +'v%Y%m%d%H%M')" >> $GITHUB_OUTPUT
changelog=$(python scripts/parse-changelog.py -t ${{ github.ref }} -b ${{ steps.thislatestR.outputs.release }} ${{ env.repo_owner }}/${{ env.repo_name }})
changelog_header=$(python scripts/parse-changelog-HEAD.py -t ${{ github.ref }} -b ${{ steps.thisLatestRelease.outputs.release }} ${{ env.repo_owner }}/${{ env.repo_name }})
changelog=$(python scripts/parse-changelog.py -t ${{ github.ref }} ${{ env.repo_owner }}/${{ env.repo_name }})
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "release_body<<$EOF" >> $GITHUB_ENV
echo "$changelog_header" >> $GITHUB_ENV
echo "$changelog" >> $GITHUB_ENV
echo "$EOF" >> $GITHUB_ENV
env:

3
.gitignore vendored
View file

@ -38,3 +38,6 @@ lerna-debug.log*
# NPM Package
package-lock.json
yarn.lock
# workflows
**/__pycache__

19
scripts/_pkg/Const.py Normal file
View file

@ -0,0 +1,19 @@
docmap_siyuan = {
"Feature": "Feature",
"Enhancement": "Enhancement",
"Bug": "Bugfix",
"Document": "Document",
"Refactor": "Refactor",
"Abolishment": "Abolishment",
"Development": "Development",
}
repo_siyuan = "siyuan-note/siyuan"
hostname = "api.github.com"
HEADER_siyuan = '''
'''
HEADER = {
"siyuan-note/siyuan": HEADER_siyuan,
}

61
scripts/_pkg/Utils.py Normal file
View file

@ -0,0 +1,61 @@
import re
def find_milestone(repo, title, len=0):
"""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
len: 版本号长度限制默认 0 不限制
Returns:
The milestone which title matches the given argument.
If no milestone matches, it will return None
"""
thisRelease = title.split("/")[-1]
pat = re.search("v([0-9.]+)", thisRelease)
if not pat:
return None
if len > 0:
version = ".".join(pat.group(1).split(".")[:len])
else:
version = ".".join(pat.group(1).split(".")[:])
# REF https://docs.github.com/en/rest/issues/milestones?apiVersion=2022-11-28#list-milestones
for milestone in repo.get_milestones(state="all"):
if version in milestone.title:
return milestone
def generate_msg(desc_mapping, docmap):
"""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()
def get_issue_first_label(issue, docmap):
"""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_header_from_repo(repo_name, tag_name, lastestRelease, action_file, HEADER=''):
thisRelease = tag_name.split("/")[-1]
pat = re.search("v([0-9.]+)", thisRelease)
if not pat:
return None
return f'''
---
<p align="center">
<a href="https://github.com/{repo_name}/actions/workflows/{action_file}"><img src="https://img.shields.io/github/actions/workflow/status/{repo_name}/{action_file}?logo=github&label={action_file}%20Action" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
<a href="https://github.com/{repo_name}/releases/{thisRelease}/"><img src="https://img.shields.io/github/downloads/{repo_name}/{thisRelease}/total?logo=github" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
<img alt="GitHub commits difference between two branches/tags/commits" src="https://img.shields.io/github/commits-difference/{repo_name}?base={lastestRelease}&head={thisRelease}&logo=git" style="cursor:pointer;height: 30px;margin: 3px auto;"/>
</p>
{HEADER}'''

8
scripts/_pkg/__init__.py Normal file
View file

@ -0,0 +1,8 @@
import os,sys
if os.path.abspath(os.path.dirname(__file__)) not in sys.path:
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
PY_DIR = os.path.abspath(os.path.dirname(sys.executable))
PYSPP = os.path.abspath(os.path.join(PY_DIR,'Lib', 'site-packages'))
if PY_DIR not in sys.path:
sys.path.append(PY_DIR)
sys.path.append(PYSPP)

View file

@ -0,0 +1,29 @@
import os
import re
from argparse import ArgumentParser
from _pkg import Const as C
from _pkg import Utils as U
def generate_msg_from_repo(repo_name, tag_name, lastestRelease):
thisRelease = tag_name.split("/")[-1]
pat = re.search("v([0-9.]+)", thisRelease)
if not pat:
return None
action_file = "cd.yml"
print(U.generate_header_from_repo(repo_name, tag_name, lastestRelease, action_file, C.HEADER[repo_name]))
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("-b", "--lastestRelease", help="lastest Release")
parser.add_argument("repo", help="The repository name")
args = parser.parse_args()
try:
generate_msg_from_repo(args.repo, args.tag, args.lastestRelease)
except AssertionError:
print(args.tag)

View file

@ -2,21 +2,11 @@ import os
import re
from argparse import ArgumentParser
from collections import defaultdict
from _pkg import Const as C
from _pkg import Utils as U
import github # type: ignore # pip install PyGithub
import github # pip install PyGithub
# ensure the milestone is open before run this
docmap = {
"Feature": "Feature",
"Enhancement": "Enhancement",
"Bug": "Bugfix",
"Document": "Document",
"Refactor": "Refactor",
"Abolishment": "Abolishment",
"Development": "Development",
}
def generate_msg_from_repo(repo_name, tag_name, lastestRelease):
def generate_msg_from_repo(repo_name, tag_name):
"""Generate changelog messages from repository and tag name.
Envs:
@ -27,81 +17,30 @@ def generate_msg_from_repo(repo_name, tag_name, lastestRelease):
repo_name (str): The repository name
tag_name (str): the tag name
"""
hostname = os.getenv("GITHUB_HOST") or "api.github.com"
hostname = os.getenv("GITHUB_HOST") or C.hostname
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, lastestRelease)
milestone = U.find_milestone(repo, tag_name)
for issue in repo.get_issues(state="closed", milestone=milestone): # type: ignore
# REF https://pygithub.readthedocs.io/en/latest/github_objects/Issue.html#github.Issue.Issue
desc_mapping[get_issue_first_label(issue)].append(
desc_mapping[U.get_issue_first_label(issue, C.docmap_siyuan)].append(
{"title": issue.title, "url": issue.html_url}
)
generate_msg(desc_mapping)
def find_milestone(repo, title, lastestRelease):
"""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)
thisRelease = title.split("/")[-1]
if not pat:
return None
version = pat.group(1)
print(f'''
<p>
<a href="https://github.com/siyuan-note/siyuan/actions/workflows/cd.yml"><img src="https://img.shields.io/github/actions/workflow/status/siyuan-note/siyuan/cd.yml?event=push&label=cd.yml%20Action&logo=github" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
<a href="https://github.com/siyuan-note/siyuan/releases/{thisRelease}/"><img src="https://img.shields.io/github/downloads/siyuan-note/siyuan/{thisRelease}/total?logo=github" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
<img alt="GitHub commits difference between two branches/tags/commits" src="https://img.shields.io/github/commits-difference/siyuan-note/siyuan?base={lastestRelease}&head={thisRelease}&logo=git" style="cursor:pointer;height: 30px;margin: 3px auto;"/>
</p>
''')
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()
U.generate_msg(desc_mapping, C.docmap_siyuan)
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("-b", "--lastestRelease", help="lastest Release")
parser.add_argument("repo", help="The repository name")
args = parser.parse_args()
try:
generate_msg_from_repo(args.repo, args.tag, args.lastestRelease)
generate_msg_from_repo(args.repo, args.tag)
except AssertionError:
print(args.tag)