🎨 更新 parse-changelog 工作流 (#11289)
This commit is contained in:
parent
291a083378
commit
5095d836c0
7 changed files with 135 additions and 74 deletions
10
.github/workflows/cd.yml
vendored
10
.github/workflows/cd.yml
vendored
|
@ -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
3
.gitignore
vendored
|
@ -38,3 +38,6 @@ lerna-debug.log*
|
|||
# NPM Package
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# workflows
|
||||
**/__pycache__
|
||||
|
|
19
scripts/_pkg/Const.py
Normal file
19
scripts/_pkg/Const.py
Normal 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
61
scripts/_pkg/Utils.py
Normal 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
8
scripts/_pkg/__init__.py
Normal 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)
|
29
scripts/parse-changelog-HEAD.py
Normal file
29
scripts/parse-changelog-HEAD.py
Normal 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)
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue