Skip to content

Commit 318f1ba

Browse files
jedudenclaude
andauthored
Remove create-event trigger guard; tag push is sole release trigger (#297)
* fix(release): trigger only on v* tag push; drop unworkable UI-draft path A draft release never creates a git tag, so no push/create event fires and GitHub fires no release event for draft creation — the `create`-triggered "UI draft" path could never run. Make `v*` tag push the sole trigger, remove the trigger-guard job and the check-release-trigger command it invoked, simplify the env/ concurrency/job conditionals, and always publish the draft as the final atomic step. Relocate the shared releaseLookupError into publishrelease.go. Update release.md and release-tooling.md. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz * test(release): cover relocated releaseLookupError; drop dead Op default Deleting triggerguard_test.go removed the only coverage of the relocated releaseLookupError. Every caller now passes a non-empty Op ("lookup"/"publish"), so drop the dead op=="" defaulting and add a direct Error() test for the empty- and non-empty-body branches. Also keep the publish-release command code span on one line in release.md (Copilot review). https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz * ci(codecov): allow 0.2% project threshold for benign deletions Deleting a well-covered file pulls the project-wide average slightly toward the mean, failing the 0%-threshold project gate even when no new code is undertested. patch keeps threshold 0%, so genuinely undertested changed lines still fail. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz * ci(codecov): fix invalid changes-status schema so config applies The changes status block carried target/threshold, which Codecov's schema rejects, so the entire codecov.yml was invalid and Codecov silently fell back to its defaults — the project/patch thresholds (and the new 0.2% project tolerance) never took effect. Reduce the changes gate to the supported `enabled: true`; validated against codecov.io/validate. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent d5d4174 commit 318f1ba

12 files changed

Lines changed: 92 additions & 792 deletions

File tree

.github/workflows/release.yml

Lines changed: 21 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,67 +4,24 @@ on:
44
push:
55
tags:
66
- "v*"
7-
create:
87

98
permissions:
109
contents: read
1110

1211
env:
13-
VERSION: ${{ github.event_name == 'create' && github.event.ref || github.ref_name }}
12+
VERSION: ${{ github.ref_name }}
1413

15-
# Serialize only release-intent runs so two publish jobs cannot mint
16-
# OIDC tokens against the same registry at the same time. Ordinary
17-
# branch-creation `create` events get a per-run group and never queue
18-
# behind a real release. `cancel-in-progress: false` keeps the first
19-
# release going (cancelling mid-publish would leave the scoped
20-
# platform packages out of sync with the root package).
14+
# Serialize release runs so two publish jobs cannot mint OIDC tokens
15+
# against the same registry at the same time. `cancel-in-progress:
16+
# false` keeps the first release going (cancelling mid-publish would
17+
# leave the scoped platform packages out of sync with the root
18+
# package).
2119
concurrency:
22-
group: >-
23-
${{
24-
(github.event_name != 'create' ||
25-
(github.event.ref_type == 'tag' && startsWith(github.event.ref, 'v'))) &&
26-
'release' ||
27-
format('release-nonrelease-{0}-{1}', github.run_id, github.run_attempt)
28-
}}
20+
group: release
2921
cancel-in-progress: false
3022

3123
jobs:
32-
trigger-guard:
33-
# `on: create` also fires for branch creation. Skip the whole job
34-
# (checkout + setup-go + go run) for create events that are not a
35-
# v* tag; downstream jobs gate on should_run and skip in turn.
36-
if: >-
37-
github.event_name != 'create' ||
38-
(github.event.ref_type == 'tag' && startsWith(github.event.ref, 'v'))
39-
runs-on: ubuntu-latest
40-
outputs:
41-
should_run: ${{ steps.decide.outputs.should_run }}
42-
create_release_is_draft: ${{ steps.decide.outputs.create_release_is_draft }}
43-
steps:
44-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
45-
with:
46-
persist-credentials: false
47-
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
48-
with:
49-
go-version-file: go.mod
50-
cache: false
51-
- name: Decide whether this trigger should publish
52-
id: decide
53-
env:
54-
EVENT_NAME: ${{ github.event_name }}
55-
CREATE_REF_TYPE: ${{ github.event.ref_type }}
56-
RELEASE_TAG: ${{ env.VERSION }}
57-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58-
# The runtime logic lives in mdsmith-release per
59-
# docs/development/release-tooling.md. The step itself stays a
60-
# fixed one-liner so no event payload is interpolated into an
61-
# inline shell script (zizmor template-injection finding).
62-
run: go run ./cmd/mdsmith-release check-release-trigger
63-
6424
build:
65-
needs: [trigger-guard]
66-
if: &release_trigger_ok >-
67-
needs.trigger-guard.outputs.should_run == 'true'
6825
strategy:
6926
matrix:
7027
include:
@@ -115,15 +72,13 @@ jobs:
11572
path: ${{ env.bin }}
11673

11774
vscode:
118-
needs: [trigger-guard]
11975
runs-on: ubuntu-latest
12076
# VSCE_PAT and OVSX_PAT are long-lived publisher tokens — see
12177
# docs/development/release.md for why the `release` environment
12278
# gates them and what reviewer rules the maintainer should set
12379
# on it.
12480
if: &release_repo_trigger_ok >-
125-
github.repository == 'jeduden/mdsmith' &&
126-
needs.trigger-guard.outputs.should_run == 'true'
81+
github.repository == 'jeduden/mdsmith'
12782
environment: release
12883
steps:
12984
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -231,7 +186,7 @@ jobs:
231186
path: editors/vscode/mdsmith-*.vsix
232187

233188
npm:
234-
needs: [trigger-guard, build]
189+
needs: [build]
235190
runs-on: ubuntu-latest
236191
# See docs/development/release.md for the canonical description
237192
# of `if:`, `environment:`, OIDC Trusted Publishing scope, and
@@ -309,7 +264,7 @@ jobs:
309264
run: npm publish --access public --provenance
310265

311266
pypi:
312-
needs: [trigger-guard, build]
267+
needs: [build]
313268
runs-on: ubuntu-latest
314269
# See docs/development/release.md for the canonical PyPI Trusted
315270
# Publisher config (workflow + environment scope) and the
@@ -352,7 +307,7 @@ jobs:
352307
packages-dir: python/dist
353308

354309
release:
355-
needs: [trigger-guard, build, vscode]
310+
needs: [build, vscode]
356311
runs-on: ubuntu-latest
357312
# See docs/development/release.md for the rationale on `if:`,
358313
# `environment:`, and the OIDC + attestations permission set.
@@ -420,10 +375,10 @@ jobs:
420375
--bundle checksums.txt.bundle \
421376
checksums.txt
422377
- name: Upload assets to draft release
423-
# Always create/update the release as a draft so every asset
424-
# uploads while the release is still mutable. With immutable
425-
# releases enforced, uploading to an already-published
426-
# release is rejected — the publish must be the final step.
378+
# Create the release as a draft so every asset uploads while
379+
# the release is still mutable. With immutable releases
380+
# enforced, uploading to an already-published release is
381+
# rejected — the publish must be the final step.
427382
env:
428383
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
429384
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
@@ -435,14 +390,10 @@ jobs:
435390
checksums.txt
436391
checksums.txt.bundle
437392
- name: Publish release
438-
# Path A (tag push): create_release_is_draft == 'false', so
439-
# flip the fully-populated draft to published as the final
440-
# atomic step — the result is an immutable release. Path B
441-
# (maintainer's UI-created draft): create_release_is_draft ==
442-
# 'true', so the release is left as a draft for manual
443-
# review and publish. Runtime logic lives in mdsmith-release
444-
# per docs/development/release-tooling.md.
445-
if: needs.trigger-guard.outputs.create_release_is_draft == 'false'
393+
# Flip the fully-populated draft to published as the final
394+
# atomic step, yielding an immutable release. Runtime logic
395+
# lives in mdsmith-release per
396+
# docs/development/release-tooling.md.
446397
env:
447398
RELEASE_TAG: ${{ env.VERSION }}
448399
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -453,8 +404,7 @@ jobs:
453404
# — the npm and PyPI registries can take ~60s to surface a fresh
454405
# publish, so the channel-specific install commands re-run if the
455406
# registry briefly returns the previous version.
456-
needs: [trigger-guard, npm, pypi, release]
457-
if: needs.trigger-guard.outputs.should_run == 'true'
407+
needs: [npm, pypi, release]
458408
strategy:
459409
fail-fast: false
460410
matrix:
@@ -525,18 +475,9 @@ jobs:
525475
runs-on: ubuntu-latest
526476
container: ${{ matrix.container }}
527477
steps:
528-
# The mise channel resolves the binary off the public GitHub
529-
# release (ubi backend). On the UI-draft path the release is
530-
# left as a draft, so its assets are not publicly downloadable
531-
# and mise cannot resolve them — skip mise there. npm/pip are
532-
# registry-backed and unaffected by the GitHub release state.
533478
- name: Install
534-
if: &smoke_channel_active >-
535-
matrix.channel != 'mise' ||
536-
needs.trigger-guard.outputs.create_release_is_draft == 'false'
537479
run: ${{ matrix.install }}
538480
- name: Verify version
539-
if: *smoke_channel_active
540481
run: |
541482
got=$(${{ matrix.run }})
542483
want="mdsmith ${VERSION}"
@@ -557,7 +498,7 @@ jobs:
557498
# boundary for Pages; the per-repo Pages settings choose
558499
# GitHub Actions as the source.
559500
name: Deploy mdsmith.dev to GitHub Pages
560-
needs: [trigger-guard, build]
501+
needs: [build]
561502
if: *release_repo_trigger_ok
562503
runs-on: ubuntu-latest
563504
permissions:

cmd/mdsmith-release/main.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// mdsmith-release build-wheels <artifacts-dir> <out-dir>
1414
// mdsmith-release sync-docs <src-dir> <dst-dir>
1515
// mdsmith-release build-website [--no-fix] [src-dir] [dst-dir]
16-
// mdsmith-release check-release-trigger
1716
// mdsmith-release publish-release
1817
// mdsmith-release check-secret-rotations
1918
// mdsmith-release record-rotation <ENTRY_TITLE> <YYYY-MM-DD>
@@ -44,7 +43,6 @@ Commands:
4443
sync-docs <src> <dst> Snapshot docs/ into a Hugo content tree.
4544
build-website [--no-fix] [src] [dst]
4645
mdsmith fix (unless --no-fix) + sync-docs.
47-
check-release-trigger Emit release trigger guard outputs.
4846
publish-release Flip the tag's draft release to published.
4947
check-secret-rotations Open GitHub issues for secrets due for rotation.
5048
record-rotation <title> <date> Update lastRotated in a per-secret rotation file.
@@ -81,8 +79,6 @@ func run(args []string) int {
8179
return runSyncDocs(root, rest)
8280
case "build-website":
8381
return runBuildWebsite(root, rest)
84-
case "check-release-trigger":
85-
return runCheckReleaseTrigger(root, rest)
8682
case "publish-release":
8783
return runPublishRelease(root, rest)
8884
case "check-secret-rotations":

cmd/mdsmith-release/main_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ func TestRunRejectsBadArity(t *testing.T) {
5959
{"build-wheels without args", []string{"build-wheels"}},
6060
{"build-wheels with one arg", []string{"build-wheels", "art"}},
6161
{"build-website with three positionals", []string{"build-website", "a", "b", "c"}},
62-
{"check-release-trigger with extra arg", []string{"check-release-trigger", "extra"}},
6362
}
6463
for _, c := range cases {
6564
assert.Equal(t, 2, run(c.args), c.name)
@@ -98,7 +97,7 @@ func TestReportFlagParseErrNilReturnsContinue(t *testing.T) {
9897
func TestSubcommandHelpExitsZero(t *testing.T) {
9998
for _, sub := range []string{
10099
"stamp", "check", "build-npm", "build-wheels",
101-
"sync-docs", "build-website", "check-release-trigger",
100+
"sync-docs", "build-website",
102101
} {
103102
assert.Equal(t, 0, run([]string{sub, "--help"}), "%s --help", sub)
104103
}
@@ -109,7 +108,7 @@ func TestSubcommandHelpExitsZero(t *testing.T) {
109108
func TestSubcommandRejectsUnknownFlag(t *testing.T) {
110109
for _, sub := range []string{
111110
"stamp", "check", "build-npm", "build-wheels",
112-
"sync-docs", "build-website", "check-release-trigger",
111+
"sync-docs", "build-website",
113112
} {
114113
assert.Equal(t, 2, run([]string{sub, "--bogus"}), "%s --bogus", sub)
115114
}

cmd/mdsmith-release/triggerguard.go

Lines changed: 0 additions & 70 deletions
This file was deleted.

cmd/mdsmith-release/triggerguard_test.go

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)