You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Contributing guide, CI, and automatic releases - #33
PR #32 merged with its notes still under [Unreleased] and no version bump, and that has happened before (3.0.0 and 3.1.0 never reached deno.json; no version was ever tagged). The cause is that nothing said when or how to release, and nothing checked. This PR makes the rule explicit and enforced:
Release per PR. A PR that changes behaviour runs deno task version:bump:<patch|minor|major> (bumps deno.json, dates the changelog section). The new release-gate check refuses the merge otherwise, unless the PR carries the no-release label (docs/CI/refactor). On merge, the Release workflow creates the tag vX.Y.Z and a GitHub Release from the changelog section. No manual tagging.
CI (checks): deno fmt --check, deno lint, deno check, unit tests, with a frozen lockfile.
CONTRIBUTING.md with setup, PR flow, changelog style, bump sizes in this tool's terms, what the gate checks and how to recover when two PRs race to the same version. PR template with the checklist.
Cleanup so CI is green: one format-only commit (deno fmt, markdown line breaks preserved), lint fixes (unused imports/vars, an unused fallback in revert_migration.ts, pinned jsr:/npm: imports), refreshed deno.lock, .deno-version 2.9.7. Two lint rules (no-import-prefix, no-explicit-any) are excluded until their cleanups land.
Scripts:scripts/release-check.sh (the gate, also deno task release:check), bump-version.sh refuses an empty Unreleased block and no longer asks for manual tags, version:show reports the tag state. Dead update-maintainers task removed.
README: "Contributing and Releases" section, task list regenerated from deno.json (the -- -f form was stale), deno task source → source-from-ld.
This PR itself is no-release. The #32 fixes plus these notes ship as 3.4.1 in a follow-up PR that only runs the bump, which also exercises the whole path end to end.
Commits are split by concern: format-only → lint cleanup → scripts/tasks → workflows → docs.
How it was tested
Locally: deno fmt --check, deno lint, deno check --frozen, deno test --frozen (182 tests) all pass.
scripts/release-check.sh exercised on every path: no-release OK, missing bump, lower version, missing heading, non-empty Unreleased, and a throwaway bump passing; bump-version.sh refuses an empty Unreleased block.
Workflow YAML parsed; the real runs are this PR's checks. Toggle the no-release label once to see release-gate fail and pass again.
After merge (maintainer)
Backfill v3.4.0 on d7a606f (the 3.4.0 release merge) so the first automated release gets a compare link.
Extend the "Base ruleset" on main: require a PR, require checks and release-gate, "require branches to be up to date".
Mechanical pass so that `deno fmt --check` can run in CI. Markdown keeps
its line breaks (`fmt.proseWrap: preserve` in deno.json), so changelog
entries stay one line per bullet.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Drop unused imports, variables and catch bindings; remove the unused
fetchFlagViews/findFlagsLinkedToView fallback in revert_migration.ts
(nothing called it); `ask` in migrate is no longer async (it only
calls the synchronous prompt()).
- Pin `jsr:@std/cli` and `npm:jsondiffpatch` in diff-payload to the
versions already in deno.lock; regenerate deno.lock so it matches the
specifiers in the code (CI runs with --frozen).
- deno.json: exclude `no-import-prefix` (the https://deno.land/std
imports; moving them to jsr: is a follow-up) and `no-explicit-any`
(typing cleanup) so `deno lint` can be enforced now.
- .deno-version 2.4.5 -> 2.9.7, the version CI pins to.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… tasks
- scripts/release-check.sh (deno task release:check): the gate CI runs on
every PR. Verifies the version bump against the base branch, that the
tag does not exist yet, that CHANGELOG.md has a dated section for the
new version and nothing left under [Unreleased]. With NO_RELEASE=true
(the no-release label) it only verifies the version is unchanged.
- scripts/bump-version.sh: refuses to release an empty [Unreleased]
block, no longer tells you to create tags by hand (the Release
workflow does that on merge), runs the gate as a self-check.
- scripts/check-version.sh: reports whether the version is tagged and
only mentions unreleased entries when there are some (the heading
alone used to trigger the warning every time).
- deno.json: tasks check, lint, fmt, fmt:check, release:check; the dead
update-maintainers task (its script does not exist) is removed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- ci.yml (check "checks"): deno fmt --check, deno lint, deno check and
the unit tests, with --frozen so lockfile drift fails the build.
- release-gate.yml (check "release-gate"): runs scripts/release-check.sh
against the PR's merge commit; re-runs when the no-release label is
added or removed, which is why it is a separate workflow.
- release.yml: on push to main, when deno.json's version differs from
the previous main commit, creates tag vX.Y.Z and a GitHub Release
whose notes are that version's CHANGELOG.md section (plus a compare
link to the previous tag). Unchanged version: no-op. Version changed
but already tagged (two PRs raced to the same version): fails loudly.
workflow_dispatch allows a retry.
- PR template with the contributing checklist; Dependabot for the
actions themselves (its PRs are labelled no-release).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… notes
- CONTRIBUTING.md: setup, PR flow, changelog style, the release-per-PR
rule and the bump sizes in this tool's terms, what the gate checks,
how to recover when another PR released first, maintainer notes.
- README: "Contributing and Releases" replaces "Version Management";
the Deno tasks section lists every task in deno.json (the snippet
showed a stale `deno task workflow -- -f` form and omitted revert,
source-from-split, diff and the development tasks); `deno task source`
corrected to `source-from-ld`; `.deno-version` mentioned next to the
Deno prerequisite; Support points at CONTRIBUTING.md.
- CHANGELOG: 3.0.1 was released on 2025-10-14, not 2025-01-14; notes for
this change under [Unreleased] (released by the next bump).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
durw4rd
added
no-release
Docs/CI/refactor-only PR: no version bump, no release on merge
and removed
no-release
Docs/CI/refactor-only PR: no version bump, no release on merge
labels
Oct 16, 2026
…al keys
Review on #33 (Copilot) pointed out three recovery gaps in release.yml,
all from deciding on "did this push change the version" (HEAD vs HEAD^1):
a queued run replaced in the concurrency group left a bump untagged, a
manual re-run after a later no-release merge saw an unchanged version
and skipped, and re-running a successful run reported a false collision.
The workflow now reconciles the current version's release state: no tag
-> tag the first-parent main commit that introduced the version and
release; tag without release -> create the release; tag and release
present -> no-op, unless this push changed that version's changelog
section (a second PR merged under an already released version), which
fails loudly; tag pointing elsewhere -> fail. CONTRIBUTING's maintainer
notes updated to match.
examples/workflow-extract-migrate-incremental.yaml: the formatter
dedented the trailing commented-out options to the root, so uncommenting
`dryRun: true` would have been ignored (workflow.ts reads
migration.dryRun). The block now sits inside `migration`, before the
last active key, where the formatter keeps its indentation.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reconcile all outstanding version releases in first-parent order
.github/workflows/release.yml:57
Reconciliation repairs a skipped release only while that version remains current. If a pending 3.4.1 run is replaced by a 3.4.2 merge, or 3.4.1 publication fails before 3.4.2 merges, the surviving run publishes only 3.4.2. Later pushes and manual dispatches on main never revisit 3.4.1. Unlike the repaired no-release-merge case, this leaves an earlier version unpublished. Reconcile outstanding version-introducing commits in first-parent order, using each commit's changelog section.
The collision check compared the version's changelog section between
HEAD^1 and HEAD, which is always a change on the commit that introduced
the version, so re-running that commit's successful release failed as a
collision (Copilot review on #33). The check now applies only to push
events of a commit other than the introducing one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Re Copilot's remaining summary finding ("reconcile all outstanding version releases in first-parent order"): leaving as is. It needs two version bumps to land within the ~15 s a release run takes, with the first run replaced in the queue. With the ruleset's up-to-date requirement, the second PR has to re-run CI after the first merges, which takes longer than that. Noted in CONTRIBUTING under the maintainer section's recovery paths; if it ever happens, a manual bump-and-release PR repairs it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
no-releaseDocs/CI/refactor-only PR: no version bump, no release on merge
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
PR #32 merged with its notes still under
[Unreleased]and no version bump, and that has happened before (3.0.0 and 3.1.0 never reacheddeno.json; no version was ever tagged). The cause is that nothing said when or how to release, and nothing checked. This PR makes the rule explicit and enforced:deno task version:bump:<patch|minor|major>(bumpsdeno.json, dates the changelog section). The newrelease-gatecheck refuses the merge otherwise, unless the PR carries theno-releaselabel (docs/CI/refactor). On merge, theReleaseworkflow creates the tagvX.Y.Zand a GitHub Release from the changelog section. No manual tagging.checks):deno fmt --check,deno lint,deno check, unit tests, with a frozen lockfile.deno fmt, markdown line breaks preserved), lint fixes (unused imports/vars, an unused fallback inrevert_migration.ts, pinnedjsr:/npm:imports), refresheddeno.lock,.deno-version2.9.7. Two lint rules (no-import-prefix,no-explicit-any) are excluded until their cleanups land.scripts/release-check.sh(the gate, alsodeno task release:check),bump-version.shrefuses an empty Unreleased block and no longer asks for manual tags,version:showreports the tag state. Deadupdate-maintainerstask removed.deno.json(the-- -fform was stale),deno task source→source-from-ld.This PR itself is
no-release. The #32 fixes plus these notes ship as 3.4.1 in a follow-up PR that only runs the bump, which also exercises the whole path end to end.Commits are split by concern: format-only → lint cleanup → scripts/tasks → workflows → docs.
How it was tested
deno fmt --check,deno lint,deno check --frozen,deno test --frozen(182 tests) all pass.scripts/release-check.shexercised on every path: no-release OK, missing bump, lower version, missing heading, non-empty Unreleased, and a throwaway bump passing;bump-version.shrefuses an empty Unreleased block.no-releaselabel once to seerelease-gatefail and pass again.After merge (maintainer)
v3.4.0ond7a606f(the 3.4.0 release merge) so the first automated release gets a compare link.main: require a PR, requirechecksandrelease-gate, "require branches to be up to date".🤖 Generated with Claude Code