-
Notifications
You must be signed in to change notification settings - Fork 4
139 lines (117 loc) · 5.69 KB
/
draft-release.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
name: draft-release
on:
workflow_dispatch:
inputs:
version_tag:
description: Semantic version tag for next release. If not provided, it will be determined based on conventional commit history.
required: false
type: string
default: ""
env:
GH_TOKEN: ${{ github.token }}
BRANCH: release-draft
jobs:
draft-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required to include tags
- uses: actions/setup-python@v4
with:
python-version: "3.11"
cache: "pip"
- run: pip install cffconvert>=2.0.0 pyyaml
- name: Get Date
run: |
echo "DATE=$(date +"%Y-%m-%d")" >> "$GITHUB_ENV"
- name: Get current and next versions
id: semver
uses: ietf-tools/semver-action@v1
with:
token: ${{ github.token }}
branch: ${{ github.ref_name }}
- name: Set version variables
shell: python {0}
run: |
import os
import re
import warnings
convco_version = "${{ steps.semver.outputs.next }}"
if "${{ github.event_name }}" == 'workflow_dispatch' and "${{ github.event.inputs.version_tag }}":
next_version = "${{ github.event.inputs.version_tag }}"
if next_version != convco_version:
warnings.warn(f"Manual version ({next_version}) not equal to version determined by conventional commit history ({convco_version})")
else:
next_version = convco_version
with open(os.getenv("GITHUB_ENV"), 'a') as out_env:
out_env.write(f"NEXT_VERSION={next_version}\n")
out_env.write(f"NEXT_STRICT={next_version.strip('v')}\n")
current_version = "${{ steps.semver.outputs.current }}"
# assert semantic version pattern
semver_pattern = 'v(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?'
next_semver = re.match(semver_pattern, next_version)
if not next_semver:
raise ValueError(f"Tag {next_version} does not match semantic versioning guidelines")
# assert next version is only 1 greater than current
current_semver = re.match(semver_pattern, current_version)
groups = ['major', 'minor', 'patch']
greater = sum([next_semver.group(grp) > current_semver.group(grp) for grp in groups])
if not (greater == 1):
raise ValueError(f"Next version must only increment one number at a time. Current version: {current_version}. Proposed next version: {next_version}")
- name: Get release notes, update changelog & version file
shell: python {0}
run: |
import os
latest_version = "${{ steps.semver.outputs.current }}".strip('v')
next_version = "${{ env.NEXT_STRICT }}"
changelog_lines = list()
next_release_lines = list()
for_next = True
with open("CHANGELOG.md", "r") as infile:
for line in infile:
if line.startswith('#') and 'development version' in line:
line = line.replace('development version', next_version)
elif latest_version in line:
for_next = False
changelog_lines.append(line)
if for_next and next_version not in line:
next_release_lines.append(line)
with open(".github/latest-release.md", "w") as outfile:
outfile.writelines(next_release_lines)
with open('CHANGELOG.md', 'w') as outfile:
outfile.writelines(changelog_lines)
with open("VERSION", "w") as outfile:
outfile.write(f"{next_version}\n")
- name: Update citation
shell: python {0}
run: |
from cffconvert.cli.create_citation import create_citation
from cffconvert.cli.validate_or_write_output import validate_or_write_output
import yaml
citation = create_citation('CITATION.cff', None)
citation._implementation.cffobj['version'] = "${{ env.NEXT_VERSION }}"
citation._implementation.cffobj['date-released'] = "${{ env.DATE }}"
with open('CITATION.cff', 'w') as outfile:
outfile.write(yaml.dump(citation._implementation.cffobj, sort_keys=False))
- name: Commit & push to branch
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git push origin --delete ${{ env.BRANCH }} || echo "No ${{ env.BRANCH }} branch to delete"
git switch -c ${{ env.BRANCH }} || git switch ${{ env.BRANCH }}
git merge --ff-only ${{ github.ref_name }}
git add CITATION.cff CHANGELOG.md VERSION
git commit -m 'chore: prepare release ${{ env.NEXT_VERSION }}'
git push --set-upstream origin ${{ env.BRANCH }}
echo "COMMIT_HASH=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
- name: Tag & draft release
run: |
gh release create ${{ env.NEXT_VERSION }} \
--draft \
--notes-file .github/latest-release.md \
--target ${{ env.COMMIT_HASH }} \
--title "${{ github.event.repository.name }} ${{ env.NEXT_STRICT }}"
- name: Next steps
run: |
echo "Next steps: Take a look at the changes in the ${{ env.BRANCH }} branch and the release notes on the web. If everything is correct, publish the release. Otherwise, delete the release draft and cut the release manually."