Skip to content

fix(ci): deploy docs when the release cuts, not when the job succeeds - #454

Merged
jahvon merged 2 commits into
mainfrom
fix/release-decouple-tap-and-docs
Aug 27, 2026
Merged

fix(ci): deploy docs when the release cuts, not when the job succeeds#454
jahvon merged 2 commits into
mainfrom
fix/release-decouple-tap-and-docs

Conversation

@jahvon

@jahvon jahvon commented Aug 27, 2026

Copy link
Copy Markdown
Member

Summary

The v2.2.0 release failed on a single 403 pushing the Homebrew cask. That credential is now fixed, so this PR no longer touches the tap — but the release exposed two workflow problems that are worth fixing regardless of why that particular step failed.

The original failure, for context
homebrew cask: could not update "Casks/flow.rb":
PUT https://api.github.com/repos/flowexec/homebrew-tap/contents/Casks/flow.rb:
403 Resource not accessible by personal access token

The GitHub release and its 7 assets published fine. Then goreleaser failed on the cask, which failed the job, which cost two unrelated things:

  • ghcr images never publishedpublish release is a serial with failFast: true, and the ghcr step runs after goreleaser. The task summary shows 2 of 4 steps ran.
  • docs never deployedrelease-docs has needs: release-binary, so it was skipped. The last successful Docs run was 2026-05-02, meaning ci: deploy docs as part of a dispatched release #452 was blocked on its first real outing by an unrelated failure and the published schemas stayed exactly as stale as before it merged.

Changes

1. Docs gate on the release existing, not on job success. A Check release published step runs gh release view under if: always() and exports a published job output. release-docs keys off that instead of release-binary's conclusion, so the schemas ship whenever the release actually cut — regardless of what fails after it.

This is the change that would have prevented the v2.2.0 outcome, and it holds for any late-stage failure, not just a tap credential.

2. Create Tag is idempotent — checks local, then origin, then creates. A release that fails partway can now be re-dispatched with the same tag instead of dying at step 7 on tag already exists. Re-running was impossible before, which is why v2.2.0 needed manual recovery.

Not in this PR

An earlier revision moved the cask push out of goreleaser (skip_upload + a continue-on-error step) so a tap failure couldn't abort the release. That's reverted now that the key is fixed — .goreleaser.yaml and .execs/release.flow are untouched relative to main, and the diff is confined to .github/workflows/release.yaml.

One residual coupling is worth naming: a future tap failure will still abort the release job and take the ghcr publish with it, because both live inside the same failFast: true serial. The docs deploy is now protected either way. Happy to decouple ghcr separately if you want it.

Testing

  • Workflow YAML parses; both jobs and all 10 steps resolve.
  • goreleaser check passes against the restored config.
  • Docs deploy verified out-of-band: flowexec.io/schemas/flowfile_schema.json now matches the repo copy and carries the new interpreter field, clearing the staleness that dated to 2026-05-02.

actionlint isn't installed locally, so there was no Actions-specific lint pass. The gate logic itself only runs on a real dispatched release.

Note

Two commits — the second reverts the cask split from the first. Squash on merge.

🤖 Generated with Claude Code

https://claude.ai/code/session_012mnVfKRbSbYV43gdjcdxdX

The v2.2.0 release failed on a single 403 pushing the cask to
flowexec/homebrew-tap. Because goreleaser does the cask push as part of
`goreleaser release`, that one credential problem aborted the whole
release job, which cost two things nobody would expect:

  - the ghcr multi-arch publish never ran (failFast on the serial)
  - release-docs was skipped via `needs: release-binary`, so the JSON
    schemas the site serves stayed frozen at 2026-05-02 - exactly the
    staleness #452 existed to prevent

Three changes:

  - goreleaser generates the cask into dist/ but no longer uploads it
    (skip_upload). The push is a continue-on-error workflow step, so a
    tap credential failure costs the tap only.
  - release-docs now gates on a `published` job output, set by checking
    that the GitHub release exists, rather than on release-binary's
    conclusion. Docs ship whenever the release actually cut.
  - Create Tag is idempotent, so a release that failed partway can be
    re-dispatched with the same tag instead of dying on an existing one.

A failed cask push writes a warning to the job summary so the
non-fatal step cannot fail silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mnVfKRbSbYV43gdjcdxdX
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

The tap credential is fixed, so goreleaser can push the cask again.
Restores .goreleaser.yaml and .execs/release.flow to their previous
state and drops the separate cask-publish step.

The docs gate and the idempotent tag creation stay: neither depends on
the tap, and the docs gate is what stops a late-stage release failure
from skipping the schema deploy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mnVfKRbSbYV43gdjcdxdX
@jahvon jahvon changed the title fix(ci): decouple homebrew tap push from release and docs deploy fix(ci): deploy docs when the release cuts, not when the job succeeds Aug 27, 2026
@jahvon
jahvon merged commit 3485cff into main Aug 27, 2026
33 of 34 checks passed
@jahvon
jahvon deleted the fix/release-decouple-tap-and-docs branch August 27, 2026 16:07
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