Skip to content

ci: check the five publishing credentials without publishing anything - #381

Merged
fstubner merged 1 commit into
mainfrom
ci/publish-preflight
Sep 8, 2026
Merged

ci: check the five publishing credentials without publishing anything#381
fstubner merged 1 commit into
mainfrom
ci/publish-preflight

Conversation

@fstubner

@fstubner fstubner commented Sep 8, 2026

Copy link
Copy Markdown
Owner

publish.yml pushes to each registry the moment that job succeeds and AUR has no review step — its own concurrency note warns that a run dying halfway "leaves some registries on the new version and some on the old, with no record of which".

A credential that expired quietly between releases is the likeliest way to get there. These secrets were last set 2026-05-03, GitHub PATs commonly carry a 90-day expiry, and releases here are months apart. 3 of the last 5 publish runs failed.

What it does

workflow_dispatch, no inputs, contents: read. Every request is a read:

Credential Check
CARGO_REGISTRY_TOKEN GET /api/v1/me
HOMEBREW_TAP_TOKEN GET /user + permissions.push on the tap
SCOOP_BUCKET_TOKEN GET /user + permissions.push on the bucket
WINGET_TOKEN GET /user (nobody has push on winget-pkgs; the action forks)
AUR_SSH_PRIVATE_KEY AUR's own read-only list-repos over SSH

Nothing is created, forked, pushed or tagged. No secret value is echoed — the report carries HTTP status codes and exit codes only.

One step rather than five, and set -uo pipefail without -e, so a bad credential doesn't stop the rest from being checked. Learning in one run which of the five are fine is the point.

The AUR check needed hardening

Tested with a deliberately invalid key, it passed, listing two repos — ssh had fallen through to the agent and ~/.ssh/config and authenticated with an ambient key. -F /dev/null, IdentitiesOnly=yes and IdentityAgent=none are what make it depend on the key it was actually given.

A credential check that can succeed without the credential is worse than none, because it reports green.

Verification, both directions

  • Invalid values for all five → five failure rows, exit 1, no check skipped
  • Real AUR key → lists netscli-bin and netscli-gui-bin, exit 0
  • Real GitHub token/user 200 and permissions.push true on both repos, so the extraction is right (jq is preinstalled on ubuntu-latest)

PUBLISHING.md's checklist now opens with it, since credentials are the slowest thing to fix and the only ones that fail mid-release.

publish.yml pushes to each registry the moment that job succeeds and AUR has
no review step, so its own concurrency note warns that a run dying halfway
"leaves some registries on the new version and some on the old, with no
record of which". A credential that expired quietly between releases is the
likeliest way to get there: these secrets were last set 2026-05-03, GitHub
PATs commonly carry a 90-day expiry, and releases here are months apart.
3 of the last 5 publish runs failed.

New workflow_dispatch workflow, no inputs, contents: read. Every request is a
read: /api/v1/me for crates.io, /user plus a permissions.push check on the
tap and the bucket, /user for winget (nobody has push on winget-pkgs, the
action forks), and AUR's own read-only `list-repos` over SSH. Nothing is
created, forked, pushed or tagged. No secret value is echoed -- the report
carries HTTP status codes and exit codes only.

One step rather than five, and `set -uo pipefail` without `-e`, so a bad
credential does not stop the rest from being checked. Finding out in one run
which of the five are fine is the point.

The AUR check needed hardening after testing. With a deliberately invalid key
it PASSED, listing two repos: ssh had fallen through to the agent and to
~/.ssh/config and authenticated with an ambient key. `-F /dev/null`,
`IdentitiesOnly=yes` and `IdentityAgent=none` are what make it depend on the
key it was given. A credential check that can succeed without the credential
is worse than none, because it reports green.

Verified in both directions rather than only the happy one:
- invalid values for all five: five failure rows, exit 1, no check skipped
- real AUR key: lists netscli-bin and netscli-gui-bin, exit 0
- real GitHub token: /user 200 and permissions.push true on both repos, so
  the extraction is right (jq is preinstalled on ubuntu-latest)

PUBLISHING.md's checklist now opens with it, since credentials are the
slowest thing to fix and the only ones that fail mid-release.
@fstubner
fstubner merged commit f2a285a into main Sep 8, 2026
15 checks passed
@fstubner
fstubner deleted the ci/publish-preflight branch September 8, 2026 02:46
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.

1 participant