Files
s3-gateway/docs/multi-version-pipeline.md
William Gill 8814a6e239
build / build (push) Has been cancelled
ci: any Linux runner; build per tag or dispatch, drop cron and matrix
runs-on is now ubuntu-latest (any Linux runner with Docker; toolchain comes from the golang container). The workflow builds one version per run, triggered by a v* tag push or manual workflow_dispatch with a tag input - no scheduled builds. Removes the static matrix (and ci/matrix.sh) and hardens clone-source.sh tag detection to use GITHUB_REF. Docs/README updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 13:29:20 -05:00

4.8 KiB

Multi-version build pipeline

How s3-gateway turns an upstream versitygw release into a de-branded build, and how to keep it tracking new upstream versions. This mirrors the scoutfs-build / scoutfs-notify model, collapsed into one repo because the patch set is small.

CI builds one version per run — triggered by a tag push or a manual dispatch, never on a schedule.

The flow

Each build is four steps, run for a single upstream tag:

  1. ci/clone-source.sh — shallow-clones upstream versitygw at a tag into src/. Tag selection priority:

    1. VGW_TAG (the dispatch input, or a manual run),
    2. the pushed tag (GITHUB_REF = refs/tags/...),
    3. the latest remote vX.Y.Z tag. The checkout forces core.autocrlf=false so the tree is byte-for- byte upstream (LF) and the LF patches apply on any host.
  2. ci/apply-patches.sh — resolves the patch directory for the tag from ci/support-matrix.yaml (patches: field, default = tag name) and applies patches/<dir>/*.patch with git am --whitespace=nowarn --3way, in filename order. The --3way fallback is what lets a series rebase across minor upstream drift.

  3. ci/build.sh — runs goreleaser release --clean --skip=validate,publish in src/, producing binaries + deb/rpm in src/dist/. Because the patch commits sit on top of the tag, HEAD is no longer exactly the tag, so we set GORELEASER_CURRENT_TAG to pin the stamped version and --skip=validate to bypass the dirty/tag checks. Upstream's .goreleaser.yaml is used unmodified — artifact names stay versitygw.

  4. ci/publish-release.sh — creates (or reuses) a Gitea release for the tag in this repo and uploads src/dist/* as assets. Idempotent: re-running for the same tag replaces existing assets.

Patch registry: ci/support-matrix.yaml

versitygw:
  - tag: v1.5.0
    patches: v1.5.0
  • tag — upstream git tag.
  • patches — directory under patches/ to apply (defaults to tag). Point several tags at one directory if the same series applies to a range of upstream releases.

apply-patches.sh consults this to find the patch directory for the tag being built; with the default patches/<tag>/ naming it doubles as a human-readable record of which versions are maintained.

Adding a new upstream version

When upstream releases vX.Y.Z:

  1. Rebase the patch series onto the new tag in a throwaway clone:

    git clone https://github.com/versity/versitygw vgw && cd vgw
    git -c core.autocrlf=false checkout -b debrand vX.Y.Z
    git config user.email you@example.com && git config user.name you
    git am --3way /path/to/s3-gateway/patches/<previous-tag>/*.patch
    # If a hunk conflicts: fix files, `git add -A`, `git am --continue`.
    mkdir -p /path/to/s3-gateway/patches/vX.Y.Z
    git format-patch --binary vX.Y.Z..HEAD \
      -o /path/to/s3-gateway/patches/vX.Y.Z
    

    --binary is required because the series deletes PNG logo assets.

  2. Register it in ci/support-matrix.yaml:

    versitygw:
      - tag: vX.Y.Z
        patches: vX.Y.Z
      - tag: v1.5.0
        patches: v1.5.0
    
  3. Commit and push ci/support-matrix.yaml + patches/vX.Y.Z/.

  4. Build it — either push a vX.Y.Z tag to this repo, or run the build workflow manually and enter vX.Y.Z. CI builds that one version and publishes it.

Sanity-check a series before committing

VGW_REPO_URL="/path/to/local/versitygw" VGW_TAG=vX.Y.Z bash ci/run.sh

A clean git am plus a populated src/dist/ means the series is good.

Removing a version

Delete its patches/<tag>/ directory and its ci/support-matrix.yaml entry. Releases already published in this repo stay until you delete them by hand.

CI configuration

  • Triggers: a v* tag push (builds that tag) or manual dispatch with a tag input (one-shot). No cron.
  • Runner: any Linux runner — runs-on: ubuntu-latest. The Go toolchain comes from the golang:latest container, so the runner only needs Docker; nothing version-specific to install.
  • Container: golang:latest — pure-Go build, GoReleaser's bundled nfpm makes deb/rpm without rpmbuild/dpkg.
  • Secret TOKEN_GITEA: Gitea PAT with write:repository. Used both to clone this repo (the workflow does a manual token-rewritten clone, since a stock container has no Node for actions/checkout) and to publish releases.
  • Variable VGW_REPO_URL (optional): override the upstream URL.

Release tagging

Releases are created in this repo with the upstream tag name (v1.5.0). If you need to ship a rebuild of the same upstream version (e.g. a patch fix), set RELEASE_TAG in ci/publish-release.sh's environment to something like v1.5.0-acg2 to avoid clobbering.