Skip to content

Commit 46dc514

Browse files
ci: Add automated release action based on python-semantic-release / conventional commits
Signed-off-by: Harry Callahan <hcallahan@lowrisc.org>
1 parent 16a9508 commit 46dc514

File tree

3 files changed

+175
-11
lines changed

3 files changed

+175
-11
lines changed

.github/workflows/release.yml

Lines changed: 172 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,193 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5-
name: DVSim Release
5+
# Create a dvsim semantic-release according to conventional-commit directives in changeset
6+
name: Create a dvsim release
7+
68
on:
79
push:
810
branches:
9-
- master
11+
# Branch-protected, only reviewed pull-requests push to master
12+
- "master"
1013

1114
permissions:
12-
contents: write
15+
contents: read
1316

1417
jobs:
18+
1519
release:
20+
name: Tag a new semantic-release and push
1621
runs-on: ubuntu-latest
22+
permissions:
23+
# Push release commit / tag
24+
contents: write
25+
# This is required for requesting the JWT for 'lowrisc_ci_app_get_token.yml'
26+
id-token: write
1727

1828
steps:
19-
- name: Repository checkout
29+
30+
- name: Get an installation access token for the lowrisc-ci app with appropriate permissions
31+
id: get-token
32+
uses: ./.github/actions/lowrisc_ci_app_get_token.yml
33+
34+
- name: Setup | Checkout Repository at PR branch
2035
uses: actions/checkout@v4
2136
with:
37+
token: ${{ steps.get-token.outputs.token }}
38+
ref: ${{ github.ref_name }}
39+
# Full-depth needed for semantic-release to determine version and changelog
2240
fetch-depth: 0
2341

24-
- name: Install python-semantic-release package
25-
run: python3 -m pip install python-semantic-release
42+
- name: Setup | Install uv
43+
uses: astral-sh/setup-uv@v6
44+
45+
- name: Setup | Install Python + the python project with release dependencies
46+
run: |
47+
uv sync --extra release
2648
27-
- name: Versioning and Publishing the release
49+
# Create new release commit that updates CHANGELOG, version strings, creates tag
50+
# Push new commit / tag to remote
51+
# Do not build, that will be done in the next step by invoking uv directly
52+
- name: Release | Create new release metadata, push commit/tag
53+
id: version_release
2854
env:
29-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55+
GH_TOKEN: ${{ steps.get-token.outputs.token }}
56+
run: |
57+
# First time round, just determine the new version and increment the pyproject.toml accordingly.
58+
# Then, we can re-lock uv.lock with the new version, and leave the change staged
59+
uv run semantic-release version --skip-build --no-changelog --no-commit --no-tag --no-push --no-vcs-release
60+
uv lock --upgrade-package 'dvsim'
61+
git add uv.lock
62+
# The second invocation generates all other release metadata, and wraps up the lockfile change
63+
# into the single tagged release commit
64+
uv run semantic-release version --skip-build
65+
66+
- name: Release | Print if not required
67+
if: ${{ steps.version_release.outputs.released == 'false' }}
68+
run: |
69+
echo "### Release Summary - dvsim" >> $GITHUB_STEP_SUMMARY
70+
echo "" >> $GITHUB_STEP_SUMMARY
71+
echo "New release not required as per commits since last release. :ok:" >> $GITHUB_STEP_SUMMARY
72+
# TODO - Add hyperlinks to project documentation for users who were expecting a new release now...
73+
74+
# Forward some outputs from 'semantic-release version' so that subsequent jobs
75+
# can be conditionally run only if a new released has actually been generated.
76+
outputs:
77+
released: ${{ steps.version_release.outputs.released }}
78+
tag: ${{ steps.version_release.outputs.tag }}
79+
80+
###################
81+
# DEPLOYMENT JOBS #
82+
###################
83+
# 1. Separate out the deploy step from the release step to run each step at
84+
# the least amount of token privilege
85+
# 2. Also, deployments can fail, and its better to have a separate job if you need to retry
86+
# and it won't require reversing the release.
87+
88+
build_release_artifacts:
89+
name: Build dist release artifacts, push src + dist assets to GitHub release
90+
needs: release
91+
if: ${{ needs.release.outputs.released == 'true' }}
92+
runs-on: ubuntu-latest
93+
permissions:
94+
# Upload github release artifacts
95+
contents: write
96+
97+
steps:
98+
99+
- name: Setup | Checkout Repository at newly tagged release
100+
uses: actions/checkout@v4
101+
with:
102+
# Can't checkout at the new tag, we need to match one of the configured
103+
# semantic_release.branches for the publish-action to proceed.
104+
# > Detached HEAD state cannot match any release groups; no release will be made
105+
ref: ${{ github.ref_name }}
106+
# Also need the tags for the publish step to work
107+
fetch-tags: true
108+
109+
- name: Setup | Install uv
110+
uses: astral-sh/setup-uv@v6
111+
112+
- name: Setup | Install Python + the python project with build dependencies
113+
run: |
114+
uv sync
115+
116+
# Build the newly-versioned release distribution
117+
- name: Release | Build the release
118+
id: build_release
30119
run: |
31-
semantic-release version --no-changelog
32-
semantic-release publish
120+
uv build
121+
122+
- name: Publish | Create GitHub Release (src + dist)
123+
uses: python-semantic-release/publish-action@v10.4.1
124+
with:
125+
github_token: ${{ secrets.GITHUB_TOKEN }}
126+
tag: ${{ needs.release.outputs.tag }}
127+
128+
- name: Upload | Distribution artifacts to blob store for follow-up jobs
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: distribution-artifacts
132+
path: dist
133+
if-no-files-found: error
134+
135+
- name: Release | Print to summary
136+
run: |
137+
echo "### Release Summary - dvsim" >> $GITHUB_STEP_SUMMARY
138+
echo "" >> $GITHUB_STEP_SUMMARY
139+
echo "New release ${{ needs.release.outputs.tag }} cut and deployed. :airplane:" >> $GITHUB_STEP_SUMMARY
140+
141+
test-pypi-publish:
142+
name: Upload release to test.pypi
143+
needs: build_release_artifacts
144+
runs-on: ubuntu-latest
145+
environment:
146+
name: test.pypi
147+
url: https://test.pypi.org/p/dvsim
148+
permissions:
149+
# IMPORTANT: this permission is mandatory for Trusted Publishing
150+
id-token: write
151+
152+
steps:
153+
154+
- name: Setup | Download dist artifacts from previous job
155+
uses: actions/download-artifact@v4
156+
id: artifact-download
157+
with:
158+
name: distribution-artifacts
159+
path: dist
160+
161+
- name: Publish | Package distribution to TestPyPI
162+
uses: pypa/gh-action-pypi-publish@release/v1
163+
with:
164+
repository-url: https://test.pypi.org/legacy/
165+
packages-dir: dist
166+
print-hash: true
167+
verbose: true
168+
169+
pypi-publish:
170+
name: Upload release to pypi
171+
needs: build_release_artifacts
172+
runs-on: ubuntu-latest
173+
environment:
174+
name: pypi
175+
url: https://pypi.org/p/dvsim
176+
permissions:
177+
# IMPORTANT: this permission is mandatory for Trusted Publishing
178+
id-token: write
179+
180+
steps:
181+
182+
- name: Setup | Download dist artifacts from previous job
183+
uses: actions/download-artifact@v4
184+
id: artifact-download
185+
with:
186+
name: distribution-artifacts
187+
path: dist
188+
189+
- name: Publish | Package distribution to PyPI
190+
uses: pypa/gh-action-pypi-publish@release/v1
191+
with:
192+
packages-dir: dist
193+
print-hash: true
194+
verbose: true

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ norecursedirs = ["*.egg", ".*", "_darcs", "build", "dist", "venv", "scratch", "d
112112
[tool.semantic_release]
113113
commit_parser = "conventional"
114114
version_toml = ["pyproject.toml:project.version"]
115-
commit_message = "Bump v{version}"
115+
commit_author = "semantic-release <actions@github.com>"
116+
commit_message = "Bump version to v{version}"
116117

117118
[tool.semantic_release.commit_parser_options]
118119
minor_tags = ["feat"]

scripts/license_check.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"LICENSE",
2323
"NOTICE",
2424
".python-version",
25+
"CHANGELOG.md",
2526
]
2627

2728
IGNORE_SUFFIXES = [".lock"]

0 commit comments

Comments
 (0)