From a9f067748d90695c65be1fb1033dfd36dd087760 Mon Sep 17 00:00:00 2001 From: Vyncint Ng <115854244+vyncint@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:54:07 +0700 Subject: [PATCH] ci: remove the termlens-cli publish bootstrap, now that it is unnecessary v0.10.1 published termlens-cli through Trusted Publishing, which is the proof the bootstrap was waiting for. The workflow, its zizmor exemption and the "not linked yet" warning in RELEASING.md all go with it. The teardown deliberately ran after a release rather than as soon as the crates.io link existed: this workflow was the only path that could publish termlens-cli without OIDC, and removing a fallback before the mechanism replacing it has actually run is the wrong order. RELEASING.md keeps the recipe for the next new crate, with that ordering stated. The `CARGO_REGISTRY_TOKEN` secret is the owner's to delete; nothing in the repository reads it any more. Refs #255 Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com> --- .github/workflows/publish-cli.yml | 83 ------------------------------- .github/zizmor.yml | 11 ---- docs/RELEASING.md | 38 +++++++------- 3 files changed, 21 insertions(+), 111 deletions(-) delete mode 100644 .github/workflows/publish-cli.yml diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml deleted file mode 100644 index 3a29820..0000000 --- a/.github/workflows/publish-cli.yml +++ /dev/null @@ -1,83 +0,0 @@ -# One-shot bootstrap: the first `termlens-cli` publish (#255). -# -# Every other publish in this repository is crates.io Trusted Publishing — -# release.yml exchanges a job's OIDC token for a short-lived one and no -# secret is stored. That cannot be used here: Trusted Publishing is -# configured per crate, on a crate that already exists, so the first publish -# of a new name has nothing to configure it against. release.yml therefore -# publishes termlens-cli only when crates.io already knows it, and warns -# otherwise. -# -# This workflow closes that gap exactly once, with a token, from a tag. Once -# it has run: link Trusted Publishing for termlens-cli (crates.io → -# termlens-cli → Settings → Trusted Publishing → GitHub, repository -# vyncint/termlens, workflow release.yml, environment release), then revoke -# the token, delete the CARGO_REGISTRY_TOKEN secret and delete this file. -# Every release after that goes through release.yml with no secret at all. -# -# Deliberately not wired to the `release` environment: that environment -# exists so an OIDC token cannot be minted from a branch, and its policy -# admits only `v*` refs. CARGO_REGISTRY_TOKEN is a repository secret, so the -# environment would add no protection here while blocking the dispatch. -name: publish-cli (bootstrap) - -on: - workflow_dispatch: - inputs: - ref: - description: The tag to publish from. Its version must match the manifest. - required: true - default: v0.10.0 - confirm: - description: Type the crate name to confirm this irreversible publish. - required: true - default: "" - -permissions: - contents: read - -concurrency: - group: publish-cli - cancel-in-progress: false - -jobs: - publish: - name: publish termlens-cli - runs-on: ubuntu-latest - steps: - - name: Refuse an unconfirmed dispatch - env: - CONFIRM: ${{ inputs.confirm }} - run: | - if [ "$CONFIRM" != "termlens-cli" ]; then - echo "::error::type 'termlens-cli' in the confirm box; a publish cannot be undone" - exit 1 - fi - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - ref: ${{ inputs.ref }} - persist-credentials: false - - uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # v1 - with: - toolchain: stable - # The same guard release.yml puts in front of every publish: the crate - # that goes out must be the version the tag names, or the registry gets - # a number that means nothing. - - name: Compare the ref against the crate version - env: - REF: ${{ inputs.ref }} - run: | - tag="${REF#v}" - version="$(cargo metadata --no-deps --format-version 1 \ - | jq -r '.packages[] | select(.name == "termlens-cli") | .version')" - echo "ref=${tag} crate=${version}" - if [ "$tag" != "$version" ]; then - echo "::error::${REF} does not match termlens-cli ${version}" - exit 1 - fi - # --locked so the published crate is the tested tree, not whatever the - # index offers today. The verify build resolves `termlens` from - # crates.io rather than the path, which is what a consumer will do. - - run: cargo publish -p termlens-cli --locked - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 9bbcf87..b6dabed 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -14,14 +14,3 @@ rules: - release.yml - install.yml - windows.yml - - publish-cli.yml - - # Correct advice that this one workflow cannot take, which is the whole - # reason it exists. Trusted Publishing is configured per crate on a crate - # that already exists, so the *first* publish of a new name has nothing to - # configure it against and must use a token. Every other publish here is - # Trusted Publishing (release.yml), and this file is deleted along with the - # secret once crates.io knows termlens-cli. - use-trusted-publishing: - ignore: - - publish-cli.yml diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 7c3fc7d..6601c2d 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -8,14 +8,12 @@ One page, copy-pasteable. Maintainers only. crate**: crates.io → *crate* → Settings → Trusted Publishing → GitHub, repository `vyncint/termlens`, workflow `release.yml`. - `termlens` — linked 2026-08-09. - - `termlens-cli` — **not linked yet**. The crate was first published on - 2026-09-08 by the one-shot `publish-cli.yml` bootstrap (a new name has - no crate to configure Trusted Publishing against, which is the whole - chicken-and-egg). Until it is linked, `release.yml`'s termlens-cli - step will fail on authentication *after* `termlens` has already gone - out — so link it before the next tag. Then delete the - `CARGO_REGISTRY_TOKEN` secret and `.github/workflows/publish-cli.yml`, - and the repository is back to storing no secret at all. + - `termlens-cli` — linked 2026-09-08, and first exercised by v0.10.1. + The crate's own first publish could not use it (a new name has no + crate to configure Trusted Publishing against) and went out through a + one-shot token workflow, since deleted. + + No token or secret is stored for publishing. - The publish job runs in the **`release` GitHub environment**, which only deploys from `v*` tags — an OIDC publish token can never be minted from a branch. (Optionally set the environment name `release` @@ -73,15 +71,21 @@ Pushing the tag runs `release.yml`, which: ## Bootstrapping a brand-new crate Trusted Publishing is configured per crate, on a crate that already -exists, so the *first* publish of a new name cannot use it. -`.github/workflows/publish-cli.yml` is that one-shot path — dispatch-only, -a typed confirmation, a tag rather than a branch, the same -tag-matches-version guard, `--locked` — run once against -`CARGO_REGISTRY_TOKEN`. It published `termlens-cli` 0.10.0 on 2026-09-08. - -Afterwards, always: link Trusted Publishing for the new crate, revoke the -token, delete the secret, delete the workflow. A stored publish token is a -standing risk that this repository otherwise does not carry. +exists, so the *first* publish of a new name cannot use it. The recipe, +used once for `termlens-cli` on 2026-09-08 (see `publish-cli.yml` in that +commit range for the exact shape): + +1. A dispatch-only workflow with a typed confirmation, checking out the + **tag** rather than a branch, carrying `release.yml`'s + tag-matches-version guard, publishing with `--locked` against a + `CARGO_REGISTRY_TOKEN` repository secret. +2. Link Trusted Publishing for the new crate on crates.io. +3. Revoke the token, delete the secret, delete the workflow. + +Step 3 is not optional and comes *after* a release has proved step 2: a +stored publish token is a standing risk this repository otherwise does not +carry, and deleting the only fallback before the mechanism is exercised is +the wrong order. ## If something fails mid-release