Skip to content

ci: preview builds for the team to install and test - #80

Merged
alukach merged 4 commits into
mainfrom
feat/staging-build
Nov 8, 2026
Merged

alukach merged 4 commits into
mainfrom
feat/staging-build

Conversation

@alukach

@alukach alukach commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Team members can now install a build of any branch without building it. Run the workflow with the branch, an optional name, and the features to build with, then install with one line:

gh workflow run "Preview build" -f ref=my-branch                         # name "staging", --features staging
gh workflow run "Preview build" -f ref=my-branch -f name=search-ui       # a preview of its own: source-coop-search-ui
gh workflow run "Preview build" -f ref=my-branch -f name=prod-check -f features=production
curl -LsSf https://github.com/source-cooperative/source-coop-cli/releases/download/staging/install.sh | sh   # install or update a preview (here, "staging")
source-coop-staging auth login                                          # a staging build keeps its own login

How it behaves

  • Inputs (Actions › Preview build › Run workflow, or gh workflow run):
    • ref: the branch, tag or commit. A first job pins it to one commit, so every build and the release are of that commit even if the branch moves during the run.
    • name (default staging): the preview's pre-release tag and the command it installs, source-coop-NAME. Up to 40 lowercase letters, digits and hyphens, not starting with a digit or with v and a digit, so it can never be taken for a version. It's checked before anything is built.
    • features: a dropdown of the Cargo features, staging (the default: staging's sign-in, proxy and API) or production (the release's defaults).
  • Builds with cargo build --release --locked --features FEATURES for aarch64-apple-darwin, x86_64-apple-darwin, x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu, on the stable toolchain as CI uses.
  • Publishes to a pre-release tagged NAME, whenever the workflow is run by hand, from any branch. Each run deletes that preview's pre-release (and a tag a failed run left behind) and creates it again on the commit, with the binaries and the installer. Its title starts "Preview NAME (not a release)" and names the ref, commit and features; its notes give the install line. A preview publishes one run at a time and is never cancelled half-way; previews with other names don't wait.
  • Installs beside production. preview/install.sh is one script for every preview: publishing sets its name in that preview's copy. It downloads the platform's build to a file and renames it into ~/.local/bin (or SOURCE_COOP_PREVIEW_DIR) as source-coop-NAME, so previews with different names sit side by side, and a running copy is never written over.
  • Stays out of the way of real releases. A preview's pre-release is never marked latest, so the release installers and Homebrew keep installing the real release. The Release workflow only runs for version tags. The pre-release is made with the workflow's own token, which doesn't trigger other workflows, and Docs also skips any release whose tag isn't a version.
  • Least privilege: only the publish job can write to the repository; the builds, which compile the ref's code, get read access.
  • On a PR that changes the workflow or the installer, it only builds the default preview, in a group of its own: a newer push cancels an older PR build, and PR builds never wait on or replace a publish.

CONTRIBUTING.md documents it for the team, including how to remove a preview (gh release delete NAME --cleanup-tag). AGENTS.md points there.

Not in this PR

  • Removing old previews automatically. Named previews stay until deleted by hand. Worth a scheduled clean-up if they pile up.
  • Windows. No one has asked for it. It's one more matrix entry plus a PowerShell installer when someone needs it.
  • A version that names the build. --version still says the version in Cargo.toml. The pre-release's title and notes name the commit instead.

Testing

  • Locally: built on Apple silicon, packaged as source-coop-search-ui as the workflow does, and served from a local folder. The installer, with its name set the way publishing sets it, installed it as source-coop-search-ui, whose help uses that name. A missing build fails with curl's 404. shellcheck passes. The name rule accepts staging, search-ui, pr-80 and vector-tiles, and refuses v1.2.3, v2-test, 1x and Bad_Name.
  • On GitHub: this PR's Preview build run builds all four targets. The publish job only runs when the workflow is run by hand, so the first run after merge is its real test.
  • Not run: actionlint (my environment couldn't download it).

🤖 Generated with Claude Code

The "Staging build" workflow builds a branch with `--features staging`
for macOS and Linux, as `source-coop-staging`, and replaces the binaries
on one rolling "staging" pre-release, never marked latest. A one-line
install script installs or updates it beside the production CLI.
CONTRIBUTING.md says how to run it and install it.

The Docs workflow now skips releases whose tag isn't a version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Docs preview: https://source-cooperative.github.io/source-coop-cli/pr-preview/pr-80/

Built from 1177526. It goes live a minute or two after the Docs deploy run, and is removed when the PR closes.

github-actions Bot added a commit that referenced this pull request Nov 8, 2026
@claude

claude Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Claude finished @alukach's task in 25s —— View job


✅ No blocking issues — safe to merge.

I read preview-build.yml, preview/install.sh and the docs.yml change. I didn't run anything, including actionlint.

Nothing here needs fixing before merge. NAME is limited to [a-z0-9-], so it is safe in the sed and the heredoc. REF only reaches shell as a quoted env var. Only the publish job gets contents: write, and it never builds the ref's code. The docs.yml guard works.

Non-blocking points:

  • Queued runs get dropped. preview-build.yml sets concurrency with cancel-in-progress: false, but GitHub keeps only one pending run per group. A third dispatch with the same name cancels the second one while it is still queued. If that matters, the description's "one run at a time" should say so. Otherwise it is fine for a team tool.
  • Brief install gap. preview-build.yml deletes the release and then recreates it, so for a few seconds install.sh returns a 404. The installer fails cleanly (curl -f), so retrying works.
  • No integrity check. The installer downloads an unsigned tarball over HTTPS with no checksum. That is acceptable for an internal preview, but worth knowing.
  • Names can match existing tags or branches. A name like main or nightly passes validation. If a non-preview tag with that name exists, the run deletes it (--cleanup-tag). The version-like rule protects release tags, but other tags are not protected.

Simplify (ponytail)

  • preview-build.yml, "Check the name": the second grep ^v?[0-9] is mostly redundant, because the first already rejects a leading digit. Cut it to ^v[0-9] as part of the first pattern, for example grep -Eq '^[a-z0-9]...' && ! grep -Eq '^v[0-9]', or a single [[ ]] test.
  • preview-build.yml, "Replace the preview's pre-release": the gh release view guard and the separate gh api tag lookup can become gh release delete "$NAME" --yes --cleanup-tag || true followed by gh api -X DELETE "repos/$GITHUB_REPOSITORY/git/refs/tags/$NAME" || true. This drops two if blocks.
  • preview/install.sh: the SOURCE_COOP_PREVIEW_URL override exists for local testing only. That is fine, but it is the one knob nobody else needs.
    · branch feat/staging-build

💰 Estimated review cost: $0.15 · 0m25s · 4 turns

alukach and others added 2 commits November 7, 2026 17:59
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the review of #80:
- A resolve job pins the ref to one commit; every build and the release
  use it, even if the branch moves during the run.
- The installer comes from the workflow's own commit, not the built one.
- Only the publish job can write; builds get read access.
- Publishes queue one at a time; a PR's builds have their own group.
- The release is replaced without hiding errors, and created on the
  commit with --target instead of force-pushing a tag.
- Builds use the stable toolchain, as CI does.
- install.sh downloads to a file before extracting, and renames the new
  binary into place instead of writing over a running one.
- CONTRIBUTING.md warns not to load source-coop-staging's completions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alukach alukach changed the title ci: staging builds for the team to install and test ci: preview builds for the team to install and test Nov 8, 2026
"Staging build" becomes "Preview build", with two more inputs: `name`
(default "staging"), the pre-release's tag and the command it installs,
source-coop-NAME; and `features`, a choice of the Cargo features to build
with (staging or production, default staging). Previews with different
names publish independently and install side by side. The name is
checked before anything is built, and can't look like a version.

preview/install.sh is the same script for every preview: publishing sets
its name in that preview's copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alukach
alukach merged commit abb8ec0 into main Nov 8, 2026
18 checks passed
@alukach
alukach deleted the feat/staging-build branch November 8, 2026 01:47
github-actions Bot added a commit that referenced this pull request Nov 8, 2026
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