Skip to content

release: promote dev to main (bootstrap auto-release + atom/template changes)#244

Merged
charliie-dev merged 22 commits into
mainfrom
dev
Jun 30, 2026
Merged

release: promote dev to main (bootstrap auto-release + atom/template changes)#244
charliie-dev merged 22 commits into
mainfrom
dev

Conversation

@charliie-dev

Copy link
Copy Markdown
Contributor

First promotion of the new auto-release infrastructure to main, breaking the bootstrap deadlock: every @main caller (meta self-release + 13 consumers) needs auto-release.yml to exist on main, but it currently only lives on dev.

Brings to main: auto-release.yml driver (#238), go:install atom deps + facade all sequencing + meta:bump wiring (#240), and meta self-release enablement (#242).

After this merge: @main callers work, consumer go:install atom deps take effect, and future meta releases run via the Self-Release driver. Tag v0.2.5.5 + GitHub Release will be created on the merged main.

charliie-dev and others added 22 commits June 28, 2026 02:30
Release v0.2.5.4

# -----BEGIN SSH SIGNATURE-----
# U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgaF5RSJNGZfKSwGiA4z8/nTW6L8
# j6Kd5+quTw8zADYtoAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
# AAAAQGpkZBUdzRQUoWUxca0WTzyYt56WRAI3VB3Bdq1S7E7SSXk68dKb03+d2djoVLZZ3y
# cSHdACaWZCX4fLAY/oSQM=
# -----END SSH SIGNATURE-----
# Good "git" signature for mail@charliie.dev with ED25519 key SHA256:DdWGvlMmBCptRDumMUS7sUjoD/W0BCOhLTQnF5Iw+m8
Centralizes the one-shot release driver (validate dev -> snapshot -> mise run all
+ license/secret scans -> merge dev→main via signed REST Merges API -> tag +
create Release) as a reusable workflow, so each repo keeps only a thin
workflow_dispatch caller instead of its own copy.

Language-agnostic: no actions/setup-go. The toolchain comes entirely from the
repo's mise.toml [tools] via jdx/mise-action (pinned to match mise-task.yml), and
the build is just `mise run all`. The same driver serves go-service / go-lib /
go-cli / frontend (Node) / python / image repos unchanged.

- inputs: version, dry_run, use_github_token, runs_on, fetch_depth, mise_version
- secrets: ci_read_app_private_key, pre_release_app_private_key (or inherit);
  App client-ids read from org vars
- private-module/submodule fetch via the ci-read App insteadOf rewrite
- HAS_CI_APP env bridge (secrets can't be used in step-level if:)

Real (non-dry-run) releases require the release App in each repo's main/dev
ruleset bypass_actors (org-admin task). dry-run needs neither the App nor bypass.

Refs #237, nics-dp/TMDs#580.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s repo

Copilot review (meta#238):
- pin actions/checkout to v7.0.0 SHA (repo convention; was @v4)
- rename input fetch_depth -> fetch-depth (matches mise-task.yml)

CodeQL actions-injection: pass github.repository via the GH_REPO env var instead
of interpolating ${{ github.repository }} inline in run: blocks — clears the
code-injection alerts (no ${{ }} left inside any run shell body).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a preflight step so a self-hosted runs_on group without GitHub CLI fails
with a clear error instead of an obscure mid-release "gh: command not found".
Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The env var is GH_REPO and run blocks use ${GH_REPO}; the comment said $REPO.
Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- checkout persist-credentials: false — don't leave the token in .git/config
  while `mise run all` runs repo code; private fetch uses the ci-read insteadOf
  rewrite, not the checkout credential (matches go-release/image-release).
- job defaults.run.shell: bash — this driver targets Linux runners; pin bash so
  a differing default shell still works.

Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nners

The token-bearing `url.*insteadOf` git config is written with --global, which
persists across jobs on self-hosted runners that don't reset HOME — risking a
stale/expired token being reused or a token-bearing config lingering.

- self-healing: drop any stale url.*@github.com/nics-dp insteadOf sections before
  writing this run's fresh rewrite
- always() teardown step removes the rewrite at the end

Mirrors go-release.yml. Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The revoke step removed only the trailing-slash section it wrote; reuse the same
regex matcher as the setup self-heal so both slash and no-slash token-bearing
url.*@github.com/nics-dp sections are cleared from a self-hosted runner's global
git config. Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Real releases always go through the release App (in the main/dev ruleset
bypass_actors); a GITHUB_TOKEN-created Release does not trigger release.yml, so
the "real release on a test repo" path it served was broken by design. Validation
is covered by dry_run. Removing it now (no callers yet) simplifies the token
conditionals and removes a foot-gun.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The create-ref and merges calls already POST implicitly (gh switches to POST when
-f fields are present), but the adjacent ref-update call uses an explicit
-X PATCH. Add -X POST to both writes so the HTTP method is unambiguous and
consistent. Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- drop unused `pull-requests: read` permission (no step reads PRs)
- run the insteadOf-revoke teardown unconditionally (always()) instead of only
  when this run minted a ci-read token, so a stale token-bearing config left by a
  prior interrupted self-hosted run is still swept even when this run has no token

Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…typo

The duplicate-tag guard and pre-merge re-check use git/ref/<ref> (singular) — the
"get a single reference" endpoint that 200s if the exact tag exists and 404s if
not, which is correct for an existence check. Add a note so it isn't mistaken for
a typo of the plural git/refs/ (list) endpoint. No behavior change.

Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This workflow makes no local commit (merge is server-side via the REST API), so
git user.name/email are unused — and writing them with --global would clobber a
self-hosted runner's identity across jobs. Remove them (matches go-release.yml).
Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…onse

Capture the merges API response and use its .sha as MAIN_SHA instead of
re-reading refs/heads/main after the call. The re-read could in principle race a
concurrent advance (already bounded by the concurrency group + main ruleset), and
on a 204 (main already contains the snapshot) the re-read still falls back to
main's tip. Tagging the merge commit directly is unambiguous. Add jq to the
preflight since it's now used to parse the response.

Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the merges API returns 204 (main already contains TARGET_BRANCH), main may
have advanced past the snapshot (e.g. a hotfix merged straight to main). Tag the
snapshot commit (TARGET_BRANCH) this run validated instead of main's tip; it is
reachable from main, so the tag is valid. Addresses Copilot review (meta#238).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- snapshot existence/dev SHA reads use singular git/ref/<ref> (exact,
  404 if absent) instead of plural git/refs/<ref>, which prefix-matches
  and could return an array for a longer sibling branch
- drift check uses git status --porcelain so a new untracked file from a
  generate step is caught, not just tracked modifications
Both the duplicate-tag guard and the pre-merge TOCTOU re-check used a
bare `if gh api …; then`, treating every non-2xx (403/5xx/network/
rate-limit) as 'tag absent' and proceeding. A transient failure could
then advance main and only fail at release creation. Capture stderr and
tri-state on the HTTP status: 200 exists (abort), clean 404 absent
(proceed), anything else is a hard error.
ci(auto-release): language-agnostic reusable release driver
Squash of meta#240 (TMDs#239). Three changes:
- 8 go atoms declare depends=[go:install] (fix vendor race at source; mirrors node atoms).
- 4 facade templates: all = sequential init/generate/api-fix then parallel build/test/ci, descriptions clarified.
- init gains depends_post=[meta:bump]; update reworked to run-array with meta:bump as a pre-step (fresh atoms).

Closes #241.
Squash of meta#242 (TMDs#239). Adds [tasks.all]=[iac:actionlint, ci] and .github/workflows/self-release.yml (workflow_dispatch caller of auto-release.yml@main) so meta can dogfood its own release driver. meta [tasks.ci] dropped trivy-license (driver runs it separately). self-release.yml uses least-privilege perms (workflow read + job write).

Closes #243.
@charliie-dev charliie-dev requested review from a team and Copilot June 30, 2026 20:14
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

cancel-in-progress: false

permissions:
contents: write # GITHUB_TOKEN creates the release/<version> or ci/release/<version> snapshot (unprotected)
jobs:
self-release:
permissions:
contents: write # auto-release.yml's GITHUB_TOKEN creates the release snapshot branch + tag/release
self-release:
permissions:
contents: write # auto-release.yml's GITHUB_TOKEN creates the release snapshot branch + tag/release
uses: nics-dp/meta/.github/workflows/auto-release.yml@main
@charliie-dev charliie-dev merged commit fce0120 into main Jun 30, 2026
14 of 15 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

此 PR 將新的自動發版基礎建設(可重用的 auto-release driver)與相關 mise/模板調整從 dev 推進到 main,讓所有 @main 呼叫端(含 meta 自身 self-release 與多個 consumer)能正常使用一致的發版流程與 mise run all 驗證入口。

Changes:

  • 新增可重用的 GitHub Actions auto-release.yml 發版 driver,並加入 meta 的 self-release.yml caller 以啟用 meta 自我發版。
  • meta repo 新增 mise.toml[tasks.all] 作為 auto-release driver 的驗證入口(actionlint + CI scans),並避免與 driver 內的 license/secret scans 重複。
  • 更新 facade templates 的 update/all 執行順序(用 run 分開 invocation 避免 cache clear 競態),以及讓多個 Go tasks 明確依賴 go:install

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
templates/facades/mise.python.toml 調整 update/all 為分段 run,並在 init 後追加 meta:bump
templates/facades/mise.go-service.toml update 改為先 meta:bump 再更新;all 改為先序列 generate/api-fix,再並行 build/test/ci。
templates/facades/mise.go-lib.toml 同步 update/all 執行模型(先 bump 再更新;關鍵步驟序列化)。
templates/facades/mise.frontend.toml update/all 改為分段 run,避免 meta:bump 清 cache 競態。
mise.toml 新增 [tasks.all] 作為 auto-release driver 入口;ci 依賴調整以避免重複掃描。
.mise/tasks/go/test 增加 #MISE depends=["go:install"],確保 vendoring 完成後再測試。
.mise/tasks/go/sast 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/lint-check 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/generate 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/dead-code 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/build 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/audit 增加對 go:install 的依賴,避免 vendoring 競態。
.mise/tasks/go/api-fix 增加對 go:install 的依賴,避免 vendoring 競態。
.github/workflows/self-release.yml 新增 meta 的 self-release caller,呼叫 auto-release.yml@main
.github/workflows/auto-release.yml 新增 reusable auto-release driver(snapshot/validate/merge/tag/release)。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +148 to +155
if err="$(gh api "repos/${GH_REPO}/git/ref/tags/${VERSION}" 2>&1 >/dev/null)"; then
echo "::error::Tag ${VERSION} already exists — refusing to re-release."
exit 1
fi
case "$err" in
*"HTTP 404"*) echo "No existing tag ${VERSION}." ;;
*) echo "::error::tag existence check failed (not a 404, refusing to proceed): ${err}"; exit 1 ;;
esac
Comment on lines +291 to +298
if err="$(gh api "repos/${GH_REPO}/git/ref/tags/${VERSION}" 2>&1 >/dev/null)"; then
echo "::error::Tag ${VERSION} appeared during validation — aborting before touching main."
exit 1
fi
case "$err" in
*"HTTP 404"*) echo "Tag ${VERSION} still absent — proceeding to merge." ;;
*) echo "::error::tag re-check failed (not a 404, refusing to touch main): ${err}"; exit 1 ;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants