release-publish-trigger¶
Prüft jeden Pre-Publish-Gate lokal und dispatched dann release-publish.yml für den offenen Release-Drafter-Draft auf develop.
Validates every release-automation pre-publish gate locally, then dispatches release-publish.yml via gh workflow run for the open release-drafter draft on develop, per the canonical-language file under spec/project/release-skill-layer/ §\"Skill B — Release publish trigger\". Verifies that exactly one open draft exists, the draft tag is reachable from the develop tip, version-bearing files align under their declared transform, every required status check on develop is SUCCESS, and .github/workflows/release-publish.yml exists. Refuses to dispatch on any failed gate; routes red checks to workflow-health triage. Never calls gh release edit --draft=false directly. Invoke when the user asks to \"publish the release\", \"trigger release publish\", \"ship the release\", or the German \"veröffentliche das Release\", \"stoße den Release-Publish an\", \"ship das Release\". Typically called by sprint-review's opt-in chain, not directly after sprint closure.
- Plugin:
nolte-shared - Phase: 7 Close & Release (
close-release) - Tags:
release - Quelle: skills/release-publish-trigger/SKILL.md
Anwenden wenn¶
- you want to publish the open release-drafter draft
- you want to ship the release after every gate is green
- you want pre-publish gate verification + workflow_dispatch in one step
Nicht anwenden wenn¶
- You want to curate the release notes rather than publish →
release-notes-curate - You want to triage a red required check that blocks the gate →
workflow-health-triage
Siehe auch¶
Referenziert von¶
Release Publish Trigger¶
Operationalises spec/project/release-skill-layer/<canonical_language>.md §"Skill B — Release publish trigger": validates every release-automation §Pre-publish verification gate locally, then dispatches release-publish.yml via gh workflow run. The workflow remains the audit-trail point for the Draft → Published transition; this skill is the local pre-flight plus dispatch.
Why this is a skill, not an agent¶
- Externally-visible mutation gates on user confirmation —
gh workflow run release-publish.ymltriggers an external publish chain (release published →release-cd-refresh-master.yml→mainfast-forward → packaging workflows); mid-flow operator gating is core to the contract and would be lost in an agent's fire-and-forget shape. - Output flows back into the main conversation — the gate-by-gate validation report, the dispatch URL, and the post-dispatch status all surface in the conversation so the operator can decide.
- Orchestrator that routes to other skills on failure — red required checks route to
workflow-healthtriage; the skill-orchestrates pattern (perskill-vs-agent) defaults the orchestrator to skill form. - Counter-dimension considered: a tool-restricted agent (read + a single
ghBash) could perform the verification half cleanly, but the dispatch decision needs the operator in the loop and the skill stays in the conversation to surface the run URL and follow-up status — keeping the whole flow in one skill is simpler than a forced split.
User-language policy¶
Detect the operator's language and respond in it. All git, gh api, and gh workflow run invocations stay English so that release-publish.yml's job summary, release-drafter's draft body, and downstream automation stay consistent across the portfolio.
Preconditions¶
Before doing anything:
- Confirm the working directory is a git repository (
git rev-parse --is-inside-work-tree) and the remote resolves to a GitHub repository. - Confirm
ghis authenticated (gh auth status). - Locate
spec/project/release-skill-layer/andspec/project/release-automation/— either in the target repo or via thenolte-sharedplugin install path. Stop and ask if neither is reachable. - Confirm the repo's default branch (
gh repo view --json defaultBranchRef --jq .defaultBranchRef.name) is the integration branch the spec applies to (typicallydevelop).
Operations¶
Operation 1 resolves the open draft and Operation 1b detects the project type (the index into release-automation §Version-bearing files, shared with Skill A per the spec's §Skill split and shared shape MUST). Operations 2 to 4 then form a Plan-validate-execute cycle: Operation 2 walks every pre-publish gate, Operation 3 surfaces the validated state for explicit operator confirmation, and Operation 4 dispatches release-publish.yml. Operation 5 verifies the dispatch landed and reports the run URL without polling to completion (unless wait mode is opted in).
1. Resolve the open draft¶
- Run
gh release list --json isDraft,tagName,targetCommitish,createdAt,name. - Filter to drafts whose
targetCommitishequals the default branch. - Refuse and report when zero drafts match (operator should run
release-drafter.ymlfirst) or when more than one matches without an explicit--tagargument from the operator (no "newest wins" heuristic, perrelease-automation§Operational contract).
1b. Detect project type¶
Per spec/project/release-skill-layer/ §Skill split and shared shape (MUST), both release-layer skills follow the same six project-type detection signals used by github-issue-templates-apply and by release-notes-curate (Skill A). Walk these six signals in order and stop at the first match. Read the files via the standard read tools — never via filename heuristics alone:
- Claude Code plugin —
.claude-plugin/plugin.jsonexists; top-levelskills/and / oragents/folder present. - Python application —
pyproject.tomldeclares[project.scripts](or equivalent application entry point), no library distribution metadata. - Python library —
pyproject.tomldeclares a distributable package without an application entry point. - Node / TypeScript library or app —
package.jsonexists;main/exportsindicates library,bin/scripts.startindicates app. - CLI tool — declared CLI entry point in
pyproject.toml([project.scripts]),package.json(bin), orCargo.toml([[bin]]). - Documentation-only repo —
mkdocs.yml,docusaurus.config.*, or similar exists with no application source.
When .github/release-skill-layer.yml declares an explicit project_type: value, use it instead of the autodetection (override path) — the same override that Skill A honours.
When no signal matches, stop and ask the operator to declare the project type manually. Never proceed with a generic fallback.
The detected type is the index into release-automation §Version-bearing files: gate 2b uses it to select the correct default version-bearing-file rows for this repo (Claude Code plugin, Python package, Node.js package, HACS integration, etc.) before reading and comparing each file.
2. Validate every pre-publish gate¶
Walk these gates in order. The skill MUST NOT proceed past a failed gate; surface the gate name, the failure detail, and the remediation path.
2a. Draft tag reachable from develop¶
git fetch origin develop.- Resolve the draft's
targetCommitishSHA. - Run
git merge-base --is-ancestor <target-sha> origin/develop. - Failure: the draft is stale relative to
develop. Remediation: re-runrelease-drafter.ymlto refresh the draft target.
2b. Version-bearing files aligned¶
- Read the version-bearing file list per
release-automation§Version-bearing files: select the default-table rows for the project type detected in step 1b, or use the override at.github/release-automation.ymlwhen the repo declares one. - For every declared file, read the value at the
target-sha(git show <target-sha>:<path>plus the spec's selector) and compare against the target tag under the file's value transform (typically "strip leadingv" if the existing convention omits it). - Failure: any file whose value does not equal the target tag under transform. Remediation: open a
chore(release): <tag>PR (fallback path) or wait for the workflow-driven primary path to land its alignment commit.
2c. Alignment commit present¶
- Identify the most recent commit on
developthat touched any version-bearing file:git log -1 --pretty=%s --follow -- <path>. - Verify the subject prefix starts with
chore(release): <tag>(the prefix-match accepts the(#N)suffix GitHub appends on squash-merge, perrelease-automation§Pre-publish verification). - Failure: no
chore(release): <tag>commit on the path. Remediation: same as 2b.
2d. Required status checks SUCCESS on develop tip¶
- Read the required check list from
.github/settings.yml(branches[name=develop].protection.required_status_checks.contexts). - For the develop tip SHA, query
gh api repos/<owner>/<repo>/commits/<sha>/check-runsand confirm every required context appears withconclusion=success. - Failure: any required check is
failure,cancelled,timed_out, or stillin_progress. Remediation: - red checks → route to
workflow-healthtriage (classify asdefect/flake/infra/stale pin/secret drift/other); never retry the dispatch blindly. - pending checks → stop and ask the operator to wait, or opt in to wait mode (see "Wait mode" below).
2e. Workflow file present¶
- Confirm
.github/workflows/release-publish.ymlexists in the repo. - Failure: the operator should adopt
release-automationfirst; this skill stops and reports.
3. Disclose the validated state and confirm¶
Before dispatch, surface to the operator as a single block:
- target tag and
target_commitishSHA; - result of each gate (PASS / FAIL with detail);
- version-bearing-file diff summary (file, current value, target value);
- audience-coverage summary when the draft body carries the
release-skill-layer:project-context-startmarker (Skill A has run); a non-blocking note offering to dispatchrelease-notes-curatefirst when the marker is absent; - the exact
gh workflow runinvocation that will be issued.
Block the dispatch until the operator confirms.
4. Dispatch¶
On confirmation:
- Run
gh workflow run release-publish.yml --ref develop -f tag=<tag>. Thetaginput is mandatory regardless of how many drafts are open (perrelease-automation§Operational contract — no "newest wins" heuristic in the workflow either). - When the operator opts in to
--dry-run, dispatch with-f dry_run=trueso the workflow validates without flippingdraft: false. - Never call
gh release edit --draft=false,gh api -X PATCH /repos/.../releases/<id>withdraft=false, or any other body that flips the draft state from this skill. The workflow is the only path.
5. Verify the dispatch landed¶
Immediately after gh workflow run returns:
- Find the new run:
gh run list --workflow=release-publish.yml --limit 1 --json databaseId,status,conclusion,url,headSha. The match is the run whoseheadShaequals the draft's target SHA and whosestatusisqueuedorin_progress. - Report the run URL plus the current status to the operator.
- Default behaviour is single-shot: the skill does not poll to completion. The operator re-invokes (or opens the URL) once the run finishes.
- Wait mode is the explicit opt-in (via
--waitargument or unambiguous prompt phrasing like "warte bis der Publish durch ist"): re-checkgh run view <id> --json status,conclusionat the configured interval (≥60 s) untilstatus=completedor the configured wall-clock timeout (≤15 min) is reached. Bound caps mirrorpull-request-merge's wait mode (interval default 90 s, timeout default 10 min, max retries 10, visible status line per round, failure short-circuits toworkflow-healthtriage).
After the run completes (single-shot or wait mode):
- On
conclusion=success: confirm with the operator that the release is now published (gh release view <tag> --json isDraftreturns{"isDraft": false}) and thatrelease-cd-refresh-master.ymlhas started a downstream run (gh run list --workflow=release-cd-refresh-master.yml --limit 1); both checks are part ofrelease-automation's acceptance criteria. - On
conclusion=failure: do not retry. Route toworkflow-healthtriage — classify perspec/project/workflow-health/. The most common cause is amerge_failedfrompascalgn/automerge-actionwhenrelease-publish.ymlitself usesautomerge-action; check the run logs formergeResult: 'merge_failed'perpull-request-mergestep 7b and route as a stale-pin incident if so.
Wait mode¶
Activated by --wait or unambiguous operator phrasing. Caps mirror pull-request-merge:
- Interval ≥ 60 s (default 90 s).
- Wall-clock timeout ≤ 15 min (default 10 min).
- Max retries ≤ 10.
- Visible status line per round.
- Failure short-circuits to
workflow-health.
The single-shot default exists because the prompt-cache TTL is 5 min; unbounded polling burns the cache. Caps balance: short waits stay cache-warm, long waits accept one cache miss but never balloon.
Gotchas¶
pascalgn/automerge-action(used by somerelease-publish.ymlimplementations downstream) exits 0 even onmergeResult: 'merge_failed'. A greenrelease-publish.ymlrun is not proof the publish happened. Always re-verifygh release view <tag> --json isDraftafter asuccessconclusion.- The
taginput is mandatory becauserelease-automationforbids the workflow's "newest wins" heuristic. Even when only one draft is open, this skill passes-f tag=<tag>explicitly. - A red required check on
develop's tip blocks publish but is not always recoverable by re-running. The triage path isworkflow-health, not "retry until green." release-cd-refresh-master.ymlshould fire automatically afterrelease-publish.ymlsucceeds. When it doesn't fire (the known-platform-constraint case whererelease: publishedfromGITHUB_TOKENdoesn't cascade to a fresh workflow run, perworkflow-health§Known platform constraints), surface this and route to manual fast-forward ofmainperbranching-model§Release flow.- The skill never runs
gh release edit --draft=falseeven as a fallback — that flag is reserved for incident response and remains a manual operator action documented inrelease-automation§Non-Goals.
Examples¶
- Read
examples/01-clean-dispatch-all-gates-pass.mdwhen all pre-publish gates pass and the skill dispatches the release workflow cleanly. - Read
examples/02-version-bearing-files-misaligned.mdwhen version-bearing files are out of sync and the gate blocks dispatch. - Read
examples/03-required-checks-red-route-to-workflow-health.mdwhen a required check ondevelop's tip is red and triage routes toworkflow-health.
Hard rules¶
- Never dispatch when any pre-publish gate fails. Failures route to
workflow-healthtriage. - Never call
gh release edit --draft=false,gh api -X PATCH .../releases/<id>withdraft=false, or any other body that flips the draft state. The workflow is the only publish path. - Never use a
--refother than the default branch (typicallydevelop). - Never poll to completion outside an explicit operator opt-in to wait mode; default behaviour is single-shot.
- Never retry a failed
release-publish.ymlrun blindly. Triage classifies the failure first. - Never proceed without explicit operator confirmation of the disclosed validation state.
- When
spec/project/release-skill-layer/orspec/project/release-automation/disagrees with this skill's instructions, the spec wins. Propose updating this skill rather than silently diverging.