|
1 | 1 | # Automated release: python-semantic-release analyzes the conventional |
2 | | -# commits on main, and when a release is due it updates CHANGELOG.md, |
3 | | -# commits, tags vX.Y.Z, pushes and creates the GitHub release. hatch-vcs |
4 | | -# derives the package version from that tag, so no version file is bumped. |
5 | | -# Publishing happens in this same run: pushes made with GITHUB_TOKEN do |
6 | | -# not retrigger workflows, so a tag-triggered publish would never fire. |
| 2 | +# commits on main, and when a release is due it bumps the static version in |
| 3 | +# pyproject.toml and CITATION.cff, updates CHANGELOG.md, relocks uv.lock, |
| 4 | +# commits, tags vX.Y.Z, pushes and creates the GitHub release. Publishing |
| 5 | +# happens in this same run: pushes made with GITHUB_TOKEN do not retrigger |
| 6 | +# workflows, so a tag-triggered publish would never fire. |
7 | 7 | # |
8 | 8 | # Filename and environment name are load-bearing: the PyPI trusted |
9 | 9 | # publisher (OIDC) references workflow "on-release-main.yml" and |
10 | | -# environment "pypi". |
| 10 | +# environment "pypi". That same "pypi" environment is also the release |
| 11 | +# gate: it has a required-reviewer protection rule (repo Settings -> |
| 12 | +# Environments -> pypi, configured out-of-repo), so this job pauses right |
| 13 | +# after checkout until a reviewer approves. Reject and nothing is tagged |
| 14 | +# or published. This is the deliberate-release control in place of a |
| 15 | +# staging branch. |
11 | 16 |
|
12 | 17 | name: release-main |
13 | 18 |
|
@@ -36,23 +41,35 @@ jobs: |
36 | 41 | released: ${{ steps.psr.outputs.released }} |
37 | 42 | version: ${{ steps.psr.outputs.version }} |
38 | 43 | steps: |
| 44 | + # The default GITHUB_TOKEN cannot push to a ruleset-protected main |
| 45 | + # (fails with GH013). Mint a short-lived, repo-scoped (Contents: write) |
| 46 | + # GitHub App token instead; the app is on main's branch-protection |
| 47 | + # bypass list, so PSR's release commit and tag push succeed. |
| 48 | + - name: Generate app token |
| 49 | + id: app-token |
| 50 | + uses: actions/create-github-app-token@v1 |
| 51 | + with: |
| 52 | + app-id: ${{ secrets.RELEASE_APP_ID }} |
| 53 | + private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }} |
| 54 | + |
39 | 55 | - name: Check out |
40 | 56 | uses: actions/checkout@v4 |
41 | 57 | with: |
42 | | - # full history: PSR analyzes commits, hatch-vcs needs the tags |
| 58 | + # full history so PSR can analyze commits and tags |
43 | 59 | fetch-depth: 0 |
44 | 60 | # latest main, not the triggering SHA: runs queued behind the |
45 | 61 | # concurrency group must include release commits pushed by the |
46 | 62 | # previous run, or their own push is rejected |
47 | 63 | ref: main |
| 64 | + token: ${{ steps.app-token.outputs.token }} |
48 | 65 |
|
49 | 66 | - name: Set up the environment |
50 | 67 | uses: ./.github/actions/setup-python-env |
51 | 68 |
|
52 | 69 | - name: Version, tag and changelog with python-semantic-release |
53 | 70 | id: psr |
54 | 71 | env: |
55 | | - GH_TOKEN: ${{ github.token }} |
| 72 | + GH_TOKEN: ${{ steps.app-token.outputs.token }} |
56 | 73 | run: | |
57 | 74 | git config user.name "github-actions[bot]" |
58 | 75 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" |
|
0 commit comments