Skip to content

Stop an AUR outage from masking release verification - #600

Merged
jeremy merged 5 commits into
mainfrom
aur-isolate
Aug 3, 2026
Merged

Stop an AUR outage from masking release verification#600
jeremy merged 5 commits into
mainfrom
aur-isolate

Conversation

@jeremy

@jeremy jeremy commented Aug 3, 2026

Copy link
Copy Markdown
Member

What happened

During the v0.8.0 release, aur.archlinux.org was down for maintenance:

Cloning into '/tmp/tmp.HmGroNAEYj/aur'...
The AUR is down due to maintenance. We will be back soon.
fatal: Could not read from remote repository.
Error: Process completed with exit code 128.

AUR publishing was a step inside the release job, positioned after both
GoReleaser (:241) and attestation (:264). So the step failed with the release
already published, which turned the job red — and took all four verification
jobs with it, skipped because they are needs: [release]:

Job Outcome for v0.8.0
Verify Windows signing skipped
Verify macOS signing skipped
Verify Nix flake skipped
Sync skills skipped

An unreachable third party silently cost us every signing verification on a
release that had already shipped. nix-verify and sync-skills were already
continue-on-error, but that does nothing when the job they depend on fails.

The fix

Split AUR into its own continue-on-error job. The release job now ends at
attestation, so its conclusion reflects only what we control, and the four
verification jobs run regardless of whether the AUR is reachable.

  • Three attempts with backoff absorb brief blips.
  • A failure opens an issue (mirroring the existing sync-skills idiom) instead of
    passing quietly, and always emits a ::error:: annotation.

Add aur-publish.yml, a workflow_dispatch recovery path for outages longer
than retries can cover. scripts/publish-aur.sh builds the PKGBUILD entirely from
the published GitHub release assets and no-ops when the AUR copy is already
current, so republishing an existing version is idempotent and needs no new tag.
It refuses versions that are not actually published, so a typo cannot push a
PKGBUILD pointing at assets that were never built.

Note on the alternative

Step-level continue-on-error would have been a smaller diff, but it leaves a
failed AUR publish sitting inside an otherwise-green job — it reads as a clean
release unless someone opens the job. A separate job keeps the failure visible on
its own.

Verification

  • bin/ci exit 0, actionlint clean, zizmor reports no findings.
  • v0.8.0's signing was verified locally in the meantime, so this PR is about
    preventing recurrence, not recovering that release.

Summary by cubic

Isolates AUR publishing into a continue-on-error job so AUR outages can’t block or hide release verification, and adds manual recovery workflows for AUR and skills sync.

  • New Features
    • Moved AUR publish to an aur-publish job; the release job now ends at attestation so macOS/Windows signing, Nix flake, and skills verification always run.
    • Added 3 attempts with backoff; on failure, open an issue and emit a workflow error annotation.
    • Added aur-publish.yml (workflow_dispatch) to republish a released version; verifies the version exists, refuses downgrades by checking the current AUR version via RPC (fails closed), preserves newer AUR pkgrel (handles dotted revisions via sort -V), and shares a concurrency group with the automatic publisher to prevent races; uses scripts/publish-aur.sh (idempotent, no new tag).
    • Added sync-skills.yml (workflow_dispatch) to mirror the skills/ tree from a release tag into basecamp/skills; requires the latest stable tag, checks out the tag and records the tagged SHA, and supports an honest dry_run (remote clone with read-only token).

Written for commit 1d59858. Summary will update on new commits.

Review in cubic

The AUR publish ran as a step inside the release job, sitting after both
GoReleaser and attestation. When aur.archlinux.org went down for maintenance
during v0.8.0, that step failed with the release already published — turning
the job red and taking macos-verify, windows-verify, nix-verify and sync-skills
down with it, all four skipped because they are `needs: [release]`.

So an unreachable third party could silently cost us every signing
verification on a release that had already shipped.

Split AUR into its own continue-on-error job. The release job now ends at
attestation, so its conclusion reflects only what we control, and the
verification jobs run regardless of the AUR's availability. Three attempts with
backoff absorb brief blips, and a failure opens an issue rather than passing
quietly.

Add an aur-publish workflow_dispatch workflow for the longer outages retries
cannot cover. publish-aur.sh builds the PKGBUILD from the published release
assets and no-ops when the AUR copy is current, so republishing an existing
version is idempotent and needs no new tag. It refuses versions that are not
actually published, so a typo cannot point the PKGBUILD at assets that were
never built.
Copilot AI review requested due to automatic review settings August 3, 2026 10:04
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Sensitive Change Detection (shadow mode)

This PR modifies control-plane files:

  • .github/workflows/aur-publish.yml
  • .github/workflows/release.yml
  • .github/workflows/sync-skills.yml

Shadow mode — this check is informational only. When activated, changes to these paths will require approval from a maintainer.

@github-actions github-actions Bot added the ci CI/CD workflows label Aug 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cec366f187

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/aur-publish.yml
The AUR outage also skipped sync-skills, and basecamp/skills is now stale
against v0.8.0 — the skills tree changed by +375/-54 lines since v0.7.2, so
this is a real gap, not a no-op.

release.yml no longer fails that way, but a sync that is skipped or fails on
its own still needs a way back that does not involve cutting a new tag.

Checks out the tag rather than main, so the sync mirrors the skills tree as it
was released even after main moves on, and resolves the tagged commit for
provenance instead of trusting github.sha, which points at the dispatching ref.
Carries the script's DRY_RUN=local mode through as a preview toggle.
Copilot AI review requested due to automatic review settings August 3, 2026 10:09
@jeremy

jeremy commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

Pushed a second commit — the same outage left a second gap.

sync-skills is also needs: [release], so it was skipped too, and
basecamp/skills is now genuinely stale against v0.8.0. Its last commit is
Sync skills from basecamp-cli v0.7.0, and the skills tree has changed by
+375/−54 since v0.7.2:

skills/basecamp-doctor/SKILL.md |  29 +++
skills/basecamp/SKILL.md        | 400 ++++++++++++++++++++++++++++++++++------

So this is a real gap, not a no-op sync. Added sync-skills.yml as a
workflow_dispatch recovery path mirroring aur-publish.yml.

Two details worth review:

  • It checks out the tag, not main, so the sync mirrors the skills tree as
    it was released even after main moves on.
  • It resolves the tagged commit for SOURCE_SHA rather than using
    github.sha, which on a workflow_dispatch points at the dispatching ref
    (main) and would record the wrong provenance.

bin/ci exit 0, actionlint clean, zizmor no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f1eb5bd04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/sync-skills.yml Outdated
Comment thread .github/workflows/sync-skills.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (2)

.github/workflows/release.yml:295

  • Unlike the sync-skills job (which sets a job-level concurrency: group: sync-skills that matches the manual sync-skills.yml workflow), this aur-publish job has no concurrency group, while the new manual aur-publish.yml uses group: aur-publish. Because concurrency groups only coordinate when the group names match, the release-time AUR publish and a manually-dispatched aur-publish.yml run can execute simultaneously, both cloning and pushing to the same AUR git repo. scripts/publish-aur.sh has no non-fast-forward retry (unlike sync-skills.sh), so a concurrent push would fail and open a needless failure issue. Add the matching group here to serialize AUR pushes across both workflows.
    continue-on-error: true
    runs-on: ubuntu-latest

.github/workflows/sync-skills.yml:46

  • The manual sync tag validation accepts prerelease tags (the optional (-[a-zA-Z0-9.]+)? group), but the automated release-time sync job never syncs prereleases — release.yml:520 gates it on !contains(github.ref_name, '-'), and the sibling manual aur-publish.yml (line 45) also rejects any - suffix. Since this workflow's stated purpose is to recover a shipped release sync that the automated flow missed, accepting a prerelease tag here has no recovery use and could push prerelease skills into the basecamp/skills distribution repo. Consider tightening the regex to reject prereleases so it matches the automated policy. (Optional — confirm the intended behavior.)
          if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then

Checking that the requested tag has a published release was not enough.
publish-aur.sh rewrites pkgver unconditionally, so dispatching an older but
perfectly valid release — after a newer one had already reached the AUR —
would push every Arch user backwards.

Compare against what is actually in the AUR via its RPC rather than against
GitHub's release list, since the AUR is the thing being protected and may lag
or lead for unrelated reasons. sort -V does the comparison so 0.10.0 ranks
above 0.9.0 instead of below it.

Fails closed when the RPC is unreachable: publishing blind risks a silent
downgrade for every Arch user, while re-dispatching once the AUR responds
costs nothing. Republishing the current version stays a permitted no-op, which
is the ordinary recovery case.
Copilot AI review requested due to automatic review settings August 3, 2026 10:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dbe790477f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/aur-publish.yml Outdated
Comment thread .github/workflows/aur-publish.yml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

.github/workflows/release.yml:294

  • Optional: the two skills-sync paths are serialized against each other — the release-time sync-skills job (line 522) and the manual sync-skills.yml (line 30) share the concurrency group sync-skills. The two AUR paths are not: this aur-publish job has no concurrency block, while the manual aur-publish.yml uses group aur-publish. Since both AUR paths push to the same aur@aur.archlinux.org/basecamp-cli.git repo, a manual recovery dispatched while a release-time publish is running can race on the AUR push. The retry loop re-clones, so a transient non-fast-forward would usually self-heal, but adding a matching concurrency group here would make the two AUR paths serialize the same way the sync-skills paths already do.
  aur-publish:
    name: Publish to AUR
    needs: [release]
    if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-')
    continue-on-error: true

Four more holes in the manual recovery workflows, all reachable:

Preserve newer AUR packaging revisions. Comparing only pkgver meant an AUR-side
packaging fix at 0.8.0-2 counted as "same version", and publish-aur.sh, which
hardcodes pkgrel=1, would then quietly replace it with 0.8.0-1. Refuse when the
published revision is above -1; republishing over -1 stays the permitted no-op.

Serialize the two publishers. The recovery workflow's concurrency group covered
only itself, so a recovery that had already passed its version check could clone
after a newer automatic publish landed and push the older PKGBUILD as a
fast-forward. Both now share the aur-publish group.

Require the latest stable tag when syncing skills. The tag pattern accepted
prereleases, which release.yml deliberately excludes, and older stable tags,
which would roll the distribution repo back — sync-skills.sh mirrors the tree
wholesale. Unlike the AUR there is no independent record of what basecamp/skills
holds, and the only reason to run this by hand is that the newest release failed
to sync, so require exactly that release.

Make the dry run honest. DRY_RUN=local never clones the target and diffs against
an empty repo, so every skill reads as newly added and the deletions a real sync
would make never appear — the opposite of what a preview is for. Use the script's
remote mode, which clones the real target and stops before pushing, and scope the
token to read for dry runs so the preview cannot write regardless.
Copilot AI review requested due to automatic review settings August 3, 2026 10:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 139b1fcb0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/aur-publish.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

.github/workflows/release.yml:347

  • Optional (maintainability): the AUR SSH/git config setup and the identical 3-attempt retry loop are now duplicated verbatim between this job and .github/workflows/aur-publish.yml (lines 118-135). Any future change to the backoff, attempt count, or SSH host config has to be made in both places or they will drift. Since publish-aur.sh already no-ops when the PKGBUILD is current, consider moving the retry/backoff into scripts/publish-aur.sh (and optionally a small shared setup snippet) so both callers just invoke the script once.
          for attempt in 1 2 3; do
            if scripts/publish-aur.sh "$VERSION"; then
              exit 0
            fi
            if [ "$attempt" -lt 3 ]; then
              echo "AUR publish attempt ${attempt} failed; retrying in $((attempt * 60))s"
              sleep $((attempt * 60))
            fi
          done
          echo "AUR publish failed after 3 attempts"
          exit 1

PKGBUILD(5) permits a dotted subrelease, so pkgrel can be 1.1. `[ -gt ]` rejects
that as a non-integer and exits 2 — and the 2>/dev/null guarding the test turned
that error into a silent "not greater", so the clobber the previous commit set
out to prevent went through anyway for exactly the revisions most likely to
carry a hand-made packaging fix.

Compare with sort -V instead, which orders dotted revisions correctly and cannot
fail open: 1.10 ranks above 1.1, and anything other than a bare 1 is refused.
Copilot AI review requested due to automatic review settings August 3, 2026 10:39
@jeremy
jeremy merged commit b801e60 into main Aug 3, 2026
25 checks passed
@jeremy
jeremy deleted the aur-isolate branch August 3, 2026 10:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci CI/CD workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants