# Multi-version build pipeline How s3-gateway turns an upstream [versitygw](https://github.com/versity/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//*.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` ```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//` 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: ```bash 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//*.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`: ```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 ```bash 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//` 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.