-
Notifications
You must be signed in to change notification settings - Fork 1
149 lines (132 loc) · 6.32 KB
/
release.yml
File metadata and controls
149 lines (132 loc) · 6.32 KB
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
140
141
142
143
144
145
146
147
148
149
# =============================================================================
# .github/workflows/release.yml — Semantic Release + PyPI + Docs
# =============================================================================
# Triggers on every push to main. Tests are NOT run here — they are gated on
# PRs by ci.yml (the required fast check) and nightly (full suite).
# 1. release job: semantic-release checks conventional commits — if a
# releasable change is found (feat:, fix:, etc.) it bumps version,
# publishes to PyPI, and creates a GitHub release.
# 2. docs job: delegates to the reusable quarto-build.yml workflow, which
# builds and deploys the quartodoc documentation to GitHub Pages
# (serialized against manual docs.yml runs via the shared
# gh-pages-deploy concurrency group).
# =============================================================================
name: Release
on:
push:
branches: [main]
permissions: read-all
concurrency:
group: release
cancel-in-progress: false
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
if: "!contains(github.event.head_commit.message, 'chore(release)')"
steps:
# ── Checkout ──────────────────────────────────────────────────────
# ssh-key: the protect-main ruleset blocks direct pushes to main, with
# a bypass for deploy keys. Checking out with the DEPLOY_KEY secret
# makes git operate over SSH as that deploy key, so semantic-release's
# chore(release) push (see repositoryUrl in .releaserc.json) bypasses
# the ruleset. GITHUB_TOKEN stays for the GitHub API (release creation).
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ssh-key: ${{ secrets.DEPLOY_KEY }}
# ── Python + uv ──────────────────────────────────────────────────
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
cache-dependency-glob: |
uv.lock
pyproject.toml
- name: Install dependencies
run: uv sync --extra dev
# ── Semantic Release ──────────────────────────────────────────────
# NOTE: tests are intentionally NOT run here. The fast suite is the
# required check on every PR to main (ci.yml) and the full suite runs
# nightly, so re-running them on the merge commit only duplicated cost
# without adding signal. This pipeline publishes; it does not re-test.
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
- name: Semantic Release
id: release
uses: cycjimmy/semantic-release-action@16ca923e6ccbb50770c415a0ccd43709a8c5f7a4 # v4.2.2
with:
extra_plugins: |
@semantic-release/git@10
@semantic-release/changelog@6
@semantic-release/exec@6
conventional-changelog-conventionalcommits@8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ── Publish to PyPI (only when a new version was released) ────────
# NOTE: cycjimmy/semantic-release-action exposes its outputs with
# underscores (``new_release_published``), not hyphens. The previous
# ``new-release-published`` reference was always empty, so this step was
# silently skipped for every release since the action was adopted —
# which is why 0.11.x/0.12.x never reached PyPI.
- name: Publish to PyPI
if: steps.release.outputs.new_release_published == 'true'
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
packages-dir: dist/
skip-existing: true
# ── Back-merge main into develop ──────────────────────────────────────
# After a release on main, merge main back into develop so that
# CHANGELOG.md and pyproject.toml stay in sync (same job as in
# spotforecast2/spotforecast2-safe release.yml). Without it, develop
# silently falls behind after every release (e.g. 0.12.9 lived only on
# main until a manual fast-forward on 2026-06-07).
back-merge:
name: Sync main into develop
runs-on: ubuntu-latest
needs: release
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
# Same deploy-key auth as the release job: develop is unprotected,
# but the key guarantees push rights independent of token policy.
ssh-key: ${{ secrets.DEPLOY_KEY }}
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Merge main into develop
run: |
git fetch origin
git checkout develop
# -X theirs: when CHANGELOG.md / pyproject.toml conflict (both were
# updated from the same base), keep main's final release version.
git merge origin/main -X theirs --no-ff \
-m "chore: sync main into develop [skip ci]"
git push origin develop
# ── Documentation (reusable workflow, shared with docs.yml) ───────────
# Builds from `main` rather than the triggering commit: by the time this
# job starts, semantic-release has already pushed its "chore(release)"
# version-bump commit, so the rendered docs show the just-released version
# (same behavior as the old in-place render after the bump).
docs:
name: Documentation
needs: release
uses: ./.github/workflows/quarto-build.yml
with:
deploy: true
ref: main
permissions:
contents: write
secrets: inherit