👷 Add Gitea release page to CI
The publish job now opens a Gitea release for the tag, using the matching Keep-a-Changelog section as the body via scripts/release-notes.sh. It runs before npm publish so a broken page fails CI without burning an npm version; npm publish stays the last step. Uses the first-party gitea-release-action (the older actions/release-action is deprecated and requires asset files) and contents: write for the run's automatic token.
This commit is contained in:
1 parent
7216c418d0
commit
a865b466bd
4 files changed
+85
-3
No files matched your search
@@ -52,6 +52,10 @@ jobs:
|
||||
if: startsWith(gitea.ref, 'refs/tags/')
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
# The release page is created with the run's automatic Gitea token
|
||||
# (`github.token`), not `NPM_TOKEN`, so it needs `contents: write`.
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
# Double-gate: publish only runs on a tag *and* aborts here if NPM_TOKEN
|
||||
# is unset, so a tag push never silently no-ops (or half-publishes). Set
|
||||
@@ -76,6 +80,19 @@ jobs:
|
||||
path: dist/
|
||||
- run: npm run publish:publint
|
||||
- run: npm run publish:attw
|
||||
# The Gitea release page is created *before* `npm publish` on
|
||||
# purpose: a broken page then fails CI without burning an npm
|
||||
# version. The page is cheap to retry, a published version is not.
|
||||
# The body is the matching Keep-a-Changelog section; an unknown tag
|
||||
# makes the extractor exit non-zero, so the page can never go up
|
||||
# empty.
|
||||
- name: Extract release notes from CHANGELOG.md
|
||||
env:
|
||||
TAG_REF: ${{ gitea.ref }}
|
||||
run: ./scripts/release-notes.sh "${TAG_REF#refs/tags/}" > release-notes.md
|
||||
- uses: https://gitea.com/actions/gitea-release-action@v1
|
||||
with:
|
||||
body_path: release-notes.md
|
||||
- run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
+2
-2
@@ -55,7 +55,7 @@ The tools are organized into a feedback ladder. Each tier catches different thin
|
||||
| `npm run maintain` | manual / CI (advisory) | `maintain:knip` + `maintain:outdated` (whole-project + network scans) | ~10s |
|
||||
| CI build (auto) | on push to `main` | `build` job (build + correctness + packaging) — see [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml) | ~30s+ |
|
||||
| CI maintain (auto, non-blocking) | on push to `main` | `npm run maintain` — reports, never fails the build | ~10s |
|
||||
| CI publish (auto) | on tag | `publish:publint` + `publish:attw`, then `npm publish` | ~10s |
|
||||
| CI publish (auto) | on tag | Gitea release page (body from CHANGELOG) + `publish:publint` + `publish:attw`, then `npm publish` | ~15s |
|
||||
|
||||
### Why these splits?
|
||||
|
||||
@@ -96,4 +96,4 @@ Publishing is CI-only by policy. Local `npm publish` is not supported. The maint
|
||||
1. All intended changes are merged to `main` and passing CI.
|
||||
2. The maintainer runs `npm run create:release` — an interactive prompt suggests a version (based on the latest CHANGELOG entry); the maintainer confirms or edits it.
|
||||
3. `scripts/release.sh` creates a single release commit (changelog + package.json bump, amended into one commit), tags it, and pushes everything to Gitea.
|
||||
4. CI runs on the push (the `build` and `maintain` jobs); the `publish` job then fires on the tag, consuming the `dist/` artifact the `build` job produced. The job graph lives in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml) — keep that file, not this list, as the source of truth. The publish-tier checks must pass before the artifact is published.
|
||||
4. CI runs on the push (the `build` and `maintain` jobs); the `publish` job then fires on the tag, consuming the `dist/` artifact the `build` job produced. The job graph lives in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml) — keep that file, not this list, as the source of truth. The publish-tier checks must pass before the artifact is published. The `publish` job also creates the Gitea release page from the matching Keep-a-Changelog section (`scripts/release-notes.sh`); it runs _before_ `npm publish` so a broken page fails CI without consuming a version, and `npm publish` stays the last step.
|
||||
+2
-1
@@ -5,7 +5,8 @@ Backlog and tracking for tiny-pattern-ts. Managed in vscode-todotasks format.
|
||||
---
|
||||
|
||||
Setup:
|
||||
☐ Add gitea release page in CI @high
|
||||
✔ Add gitea release page in CI @high @done
|
||||
☐ Manually verify the Gitea release page on a real tag push (needs main) @high
|
||||
☐ Split off template into separate package => pi --session 01a07dde-7050-7054-bb36-1606d7eb2bc3 @high
|
||||
|
||||
v1.0:
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
# Print the Keep-a-Changelog section for a release tag, so CI can use it as the
|
||||
# body of the Gitea release page without re-implementing CHANGELOG parsing.
|
||||
#
|
||||
# Run as `scripts/release-notes.sh <tag>`. A leading `v` is tolerated so both
|
||||
# `v1.2.3` and `1.2.3` match the `## [1.2.3]` heading. Prints to stdout and
|
||||
# exits non-zero when the tag has no section, so a release can never publish
|
||||
# with an empty body.
|
||||
|
||||
TAG="${1:-}"
|
||||
CHANGELOG="${CHANGELOG:-CHANGELOG.md}"
|
||||
|
||||
if [ -z "${TAG}" ]; then
|
||||
echo "Error: usage: $0 <tag>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${CHANGELOG}" ]; then
|
||||
echo "Error: ${CHANGELOG} not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# `v1.2.3` and `1.2.3` are the same release; the heading only ever uses the
|
||||
# bare version.
|
||||
VERSION="${TAG#v}"
|
||||
|
||||
awk -v version="${VERSION}" '
|
||||
# A new section ends the one we are printing (or is the one we want).
|
||||
/^## \[/ {
|
||||
if (found) exit
|
||||
heading = $0
|
||||
sub(/^## \[/, "", heading)
|
||||
sub(/\].*$/, "", heading)
|
||||
if (heading == version) found = 1
|
||||
next
|
||||
}
|
||||
|
||||
# Link-reference definitions live at the bottom of the file and are never
|
||||
# part of the section body. Stopping here keeps the last release notes
|
||||
# from picking them up (there is no following heading to stop at).
|
||||
/^\[[^]]+\]:/ { exit }
|
||||
|
||||
found {
|
||||
if ($0 ~ /^[[:space:]]*$/) {
|
||||
# Buffer blank lines so trailing ones at the end of the section
|
||||
# are dropped instead of leaking into the release body.
|
||||
if (started) pending = pending $0 "\n"
|
||||
} else {
|
||||
printf "%s%s\n", pending, $0
|
||||
pending = ""
|
||||
started = 1
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (!found) {
|
||||
printf "Error: no CHANGELOG section for [%s].\n", version > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
' "${CHANGELOG}"
|
||||
Reference in new issue
Block a user