Skip to content

Commit 5ebb0e8

Browse files
More release workflow updates
1 parent 68f8428 commit 5ebb0e8

3 files changed

Lines changed: 56 additions & 109 deletions

File tree

.github/update-hugo.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ https://github.com/gohugoio/hugo/releases/tag/v${LATEST_VERSION}
1414

1515
- [ ] Merge this PR
1616
- [ ] Run `nox -s tag -- v${LATEST_VERSION}` locally to create a signed tag
17-
- [ ] Push the tag: `git push origin v${LATEST_VERSION}`
18-
- [ ] Run `nox -s release -- v${LATEST_VERSION}` to create the GitHub release (or create it manually)
17+
- [ ] Push the tag: `git push origin v${LATEST_VERSION}` — the CD workflow will build and publish the release automatically

.github/workflows/cd.yml

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -432,15 +432,67 @@ jobs:
432432
contents: write # Required to upload signed artifacts to a GitHub release
433433
attestations: write # Required to generate build provenance attestations
434434
runs-on: ubuntu-latest
435-
if: startsWith(github.ref, 'refs/tags/')
435+
if: startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule'
436436

437437
steps:
438+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
439+
with:
440+
persist-credentials: false
441+
fetch-depth: 0
442+
438443
- name: Download all artifacts
439444
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
440445
with:
441446
path: upload/
442447
merge-multiple: true
443448

449+
- name: Generate release notes
450+
env:
451+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
452+
run: |
453+
set -euo pipefail
454+
TAG="${GITHUB_REF_NAME}"
455+
VERSION="${TAG#v}"
456+
457+
# Select template based on whether this is a patch release
458+
PATCH=$(echo "$VERSION" | cut -d. -f3)
459+
if [ "$PATCH" -gt 0 ]; then
460+
TEMPLATE="release_notes/patch.md"
461+
else
462+
TEMPLATE="release_notes/stable.md"
463+
fi
464+
465+
# Find the previous tag
466+
PREVIOUS_TAG=$(git tag --sort=-v:refname | \
467+
awk -v tag="${TAG}" '$0 == tag {found=1; next} found {print; exit}')
468+
if [ -z "$PREVIOUS_TAG" ]; then
469+
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^")
470+
fi
471+
472+
# Extract PR numbers from commits between the two tags
473+
PR_NUMBERS=$(git log "${PREVIOUS_TAG}..${TAG}" --oneline | \
474+
grep -oE '#[0-9]+' | tr -d '#' || true)
475+
476+
# Fetch PR titles and authors, filtering out bot PRs
477+
PR_LINES=""
478+
for NUM in $PR_NUMBERS; do
479+
LINE=$(gh pr view "$NUM" --json title,author \
480+
--jq '"- \(.title) by @\(.author.login) in #'"$NUM"'"' 2>/dev/null || true)
481+
[ -z "$LINE" ] && continue
482+
echo "$LINE" | grep -qE 'dependabot\[bot\]|pre-commit-ci\[bot\]' && continue
483+
PR_LINES="${PR_LINES}${LINE}"$'\n'
484+
done
485+
486+
if [ -n "$PR_LINES" ]; then
487+
CHANGES_SECTION=$'\n## Changes that made it to this release\n\n'"${PR_LINES}"
488+
else
489+
CHANGES_SECTION=""
490+
fi
491+
492+
export VERSION PREVIOUS_TAG CHANGES_SECTION
493+
envsubst '${VERSION} ${PREVIOUS_TAG} ${CHANGES_SECTION}' \
494+
< "$TEMPLATE" > /tmp/release-notes.md
495+
444496
- uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
445497
with:
446498
# Comment this line out to publish to PyPI
@@ -465,10 +517,6 @@ jobs:
465517
env:
466518
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
467519
run: |
468-
# Create a draft release and upload all artifacts (wheels, sdist, and
469-
# Sigstore signatures), then publish — the release becomes immutable
470-
# once it is no longer a draft
471520
gh release create "${GITHUB_REF_NAME}" upload/* \
472-
--draft \
473-
--generate-notes
474-
gh release edit "${GITHUB_REF_NAME}" --draft=false
521+
--title "${GITHUB_REF_NAME}" \
522+
--notes-file /tmp/release-notes.md

noxfile.py

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

33
import re
4-
import string
54
import subprocess
65
from pathlib import Path
76

@@ -46,26 +45,6 @@ def _get_version(session: nox.Session) -> str:
4645
return match.group(1)
4746

4847

49-
def _get_previous_tag(current_tag: str) -> str:
50-
result = subprocess.run(
51-
["git", "tag", "--sort=-v:refname"],
52-
capture_output=True,
53-
text=True,
54-
check=True,
55-
)
56-
tags = result.stdout.strip().splitlines()
57-
for i, t in enumerate(tags):
58-
if t == current_tag and i + 1 < len(tags):
59-
return tags[i + 1]
60-
result = subprocess.run(
61-
["git", "describe", "--tags", "--abbrev=0", f"{current_tag}^"],
62-
capture_output=True,
63-
text=True,
64-
check=True,
65-
)
66-
return result.stdout.strip()
67-
68-
6948
@nox.session(default=False)
7049
def tag(session: nox.Session) -> None:
7150
"""Create a signed, annotated tag for a release.
@@ -103,82 +82,3 @@ def tag(session: nox.Session) -> None:
10382
external=True,
10483
)
10584
session.log(f"Tag {tag_name} created. Push it with: git push origin {tag_name}")
106-
107-
108-
@nox.session(default=False)
109-
def release(session: nox.Session) -> None:
110-
"""Create a GitHub release with formatted release notes.
111-
112-
Usage: nox -s release -- 0.157.0
113-
"""
114-
version = _get_version(session)
115-
tag_name = f"v{version}"
116-
117-
previous_tag = _get_previous_tag(tag_name)
118-
is_patch = int(version.split(".")[2]) > 0
119-
template_name = "patch.md" if is_patch else "stable.md"
120-
template_path = DIR / "release_notes" / template_name
121-
template = string.Template(template_path.read_text())
122-
123-
# Extract PR numbers from merge commits between the two tags
124-
log_output = subprocess.run(
125-
["git", "log", f"{previous_tag}..{tag_name}", "--oneline"],
126-
capture_output=True,
127-
text=True,
128-
check=True,
129-
).stdout.strip()
130-
131-
pr_numbers = re.findall(r"#(\d+)", log_output)
132-
133-
pr_lines = []
134-
for num in pr_numbers:
135-
result = subprocess.run(
136-
[
137-
"gh",
138-
"pr",
139-
"view",
140-
num,
141-
"--json",
142-
"title,author",
143-
"--jq",
144-
'"- \\(.title) by @\\(.author.login) in #' + num + '"',
145-
],
146-
capture_output=True,
147-
text=True,
148-
check=False,
149-
)
150-
if result.returncode != 0:
151-
continue
152-
line = result.stdout.strip()
153-
if "dependabot[bot]" in line or "pre-commit-ci[bot]" in line:
154-
continue
155-
pr_lines.append(line)
156-
157-
pr_log = "\n".join(pr_lines)
158-
159-
if pr_log:
160-
changes_section = f"\n## Changes that made it to this release\n\n{pr_log}\n"
161-
else:
162-
changes_section = ""
163-
164-
substitutions = {
165-
"VERSION": version,
166-
"PREVIOUS_TAG": previous_tag,
167-
"CHANGES_SECTION": changes_section,
168-
}
169-
170-
body = template.substitute(substitutions)
171-
172-
session.log(f"Creating GitHub release for {tag_name}")
173-
session.run(
174-
"gh",
175-
"release",
176-
"create",
177-
tag_name,
178-
"--title",
179-
tag_name,
180-
"--notes",
181-
body,
182-
external=True,
183-
)
184-
session.log(f"Release {tag_name} created!")

0 commit comments

Comments
 (0)