# builds.sr.ht manifest for dolt.sr.ht. One linear pipeline: install the cache # helper, assemble the shared SCSS, restore caches, package with abuild, publish # the apk, save caches. # # The reasoning behind every task lives in docs/ci.md, not here: builds.sr.ht # stores the submitted manifest in a varchar(16384), so a manifest over 16 KiB # cannot be submitted at all — and the failure is a branch with no CI, not a red # build. Add paragraphs to docs/ci.md and a pointer here. image: alpine/edge packages: - abuild - curl - go - git - rclone - sassc - minify # For the database suites, not for the package — see docs/ci.md#packages. - postgresql - postgresql-client secrets: # File secret `apk-ci-s3`, installed at ~/.apk-ci.env, containing # APK_CI_S3_ACCESS_KEY / APK_CI_S3_SECRET_KEY for the Garage `repo` bucket. - apk-ci-s3 # S3 credentials for the cacher CI cache (Garage `docker-cache` bucket), # same pair the bencher and ci-cacher builds use. - 7dde4219-0783-4581-a67d-c94749de3600 # ~/.s3-cache-key-id - 0e5b3530-6f19-4f30-9b73-9339dd382e46 # ~/.s3-cache-key-secret sources: - https://git.srht.bigb.es/~bigbes/sr-ht-dolt environment: REPO: sr-ht-dolt APK_REPO: alpine/v3.22/bigbes/x86_64 S3_BUCKET: repo S3_ENDPOINT: https://s3.bigb.es # Must track the srht deployment's SRHT_CORE_VER, or this service's theme # drifts from the rest of the instance. BOOTSTRAP_REV is the submodule commit # core.sr.ht pins at that tag; bump the two together. docs/ci.md#environment. CORE_VER: "0.84.5" BOOTSTRAP_REV: 779ad9f174ea5ab7e755f6df0ec9e5912d67dd16 submitter: git.sr.ht: allow-refs: - refs/heads/master # Tags build too, now that the version task reads them: pushing v0.2.0 is # what produces the 0.2.0 apk. See docs/ci.md#version. - "refs/tags/v*" tasks: # S3-backed CI cache helper; installed first so scss can already use it. # install.sh's PATH export goes to ~/.buildenv, which only the NEXT task # sources — hence two tasks and not one. See docs/ci.md#cacher. - cacher_install: | curl -fsSL https://bigbes.pages.srht.bigb.es/ci-cacher/install.sh | sh - cacher_init: | cacher init \ --endpoint https://s3.bigb.es \ --region garage \ --bucket docker-cache \ --prefix sr-ht-dolt/deps \ --key-file ~/.s3-cache-key-id \ --secret-file ~/.s3-cache-key-secret - scss: | # Assemble the shared sourcehut partials no apk ships, the way # core.sr.ht's `make install-scss` would, cached by the two pins so an # outage at git.sr.ht or github.com can't fail us. --exec runs on a miss # and seeds the cache after; it sees exported vars only, hence the inline # key and the single quotes. See docs/ci.md#scss. cacher dir download "scss/${CORE_VER}-${BOOTSTRAP_REV}.tar.zst" ~/scss --exec ' git clone --depth 1 --branch "$CORE_VER" \ https://git.sr.ht/~sircmpwn/core.sr.ht /tmp/core mkdir -p ~/scss/bootstrap cp /tmp/core/scss/*.scss /tmp/core/scss/*.css ~/scss/ git init -q /tmp/bootstrap git -C /tmp/bootstrap remote add origin https://github.com/twbs/bootstrap git -C /tmp/bootstrap fetch -q --depth 1 origin "$BOOTSTRAP_REV" git -C /tmp/bootstrap checkout -q FETCH_HEAD cp -r /tmp/bootstrap/scss ~/scss/bootstrap/scss ' sudo mkdir -p /usr/share/sourcehut sudo cp -r ~/scss /usr/share/sourcehut/scss - keygen: | # Throwaway signing key, and -i is not optional: docs/ci.md#keygen. SUDO=sudo abuild-keygen -a -n -i -q - version: | # ONE `git describe` decides the apk pkgver: a tag, else tag_git, else # the family's commit count. The raw describe output is not a legal pkgver # and _git sorts AFTER the release: docs/ci.md#version. # # EXPORTED rather than sed-ed into the APKBUILD (which reads $PKGVER), # because rewriting a tracked file would flip the VCS stamp Go records in # every binary to dirty — do not "tidy" it back into a sed. The tree is # printed because this is the last moment it is provably clean. cd "$REPO" desc=$(git describe --tags --always --dirty) base=${desc%-dirty} case "$base" in v*-g*) n=${base%-g*}; ver="${n%-*}"; ver="${ver#v}_git${n##*-}" ;; v*) ver="${base#v}" ;; *) ver="0.0.$(git rev-list --count HEAD)" ;; esac echo "export PKGVER=$ver" >> ~/.buildenv echo "building $ver from $desc" git status --porcelain - cache_restore: | # Go module and build caches keyed by go.sum: the dolt dependency tree # dominates compile time and only changes when go.sum does. --optional # makes a miss a cold build, not an error. abuild re-pins both, since it # redirects the Go caches into its own $tmpdir (docs/ci.md#cache_restore). KEY_MOD=$(cacher key "gomod/{hash}.tar.zst" --hash-from "$REPO/go.sum") KEY_GOC=$(cacher key "gocache/{hash}.tar.zst" --hash-from "$REPO/go.sum") echo "export KEY_MOD=$KEY_MOD KEY_GOC=$KEY_GOC" >> ~/.buildenv cacher dir download "$KEY_MOD" ~/go/pkg/mod --optional cacher dir download "$KEY_GOC" ~/.cache/go-build --optional # Repair block for the HALF-restored module cache — the normal failure # here, not a freak one, and it reads like a code bug. Do not remove and # do not soften to `|| true`: # docs/ci.md#the-half-restored-module-cache. cd "$REPO" chmod -R u+w ~/go/pkg/mod 2>/dev/null || true if ! go mod verify >/dev/null 2>&1; then echo "restored module cache did not verify — discarding it" rm -rf ~/go/pkg/mod fi # `go mod download`, NOT `go mod download all`: `all` resolves the whole # module graph including dependencies' test deps and APPENDS their hashes # to go.sum, which is a modified tracked file and therefore a "-dirty" # apk. Measured. docs/ci.md#go-mod-download-and-the-word-all. go mod download go mod verify # Neither line above may rewrite go.mod or go.sum — a dirty tree here is a # "-dirty" apk, so check rather than trust. docs/ci.md#cache_restore. git status --porcelain - postgres: | # A real Postgres in the VM. Without it db/ skips 9 of its 10 tests and # the build goes green over the whole persistence layer — which is where # this repository had stood since it was written. Every flag below is # load-bearing: docs/ci.md#postgres. sudo install -d -o postgres -g postgres /run/postgresql /var/lib/postgresql/data sudo -u postgres initdb -D /var/lib/postgresql/data sudo -u postgres pg_ctl -D /var/lib/postgresql/data -l /tmp/pg.log -w start \ -o "-k /run/postgresql -h 127.0.0.1 \ -c fsync=off -c full_page_writes=off -c synchronous_commit=off" sudo -u postgres createuser -s "$(id -un)" sudo -u postgres createdb -O "$(id -un)" doltsrht_test echo "export DOLTSRHT_TEST_PG='postgresql://$(id -un)@127.0.0.1/doltsrht_test?sslmode=disable'" \ >> ~/.buildenv - test: | cd "$REPO" # An empty DSN would skip every database suite and leave the build green # over untested code — and options="!check" in the APKBUILD says this task # is where the suites run, so a silent skip here is a package built on a # promise nothing kept. It also catches a reordering of the two tasks. # docs/ci.md#test. if [ -z "$DOLTSRHT_TEST_PG" ]; then echo "DOLTSRHT_TEST_PG is unset: the postgres task did not export it," >&2 echo "so every database suite would skip and this build would lie." >&2 exit 1 fi # `make vet` and `make test` rather than bare go commands: the Makefile is # where -tags gms_pure_go and CGO_ENABLED=0 are named, and a second copy # of those here is a second copy to forget. docs/ci.md#test. make vet make test # Printed, not gated, for the same reason as cache_restore's: this task # runs before abuild, so anything the suites left in the checkout is a # "-dirty" apk, and this is where it would show. docs/ci.md#test. git status --porcelain - build: | cd "$REPO" # -d: makedepends are already installed via `packages:` above. REPODEST=$HOME/packages abuild -d find "$HOME/packages" -name '*.apk' - publish: | # The gate is the honest answer to a build that was handed no secrets, not # a fallback: with ~/.apk-ci.env absent every earlier task has still run # and a signed apk is sitting in $HOME/packages. See docs/ci.md#publish. if [ ! -r ~/.apk-ci.env ]; then echo "no ~/.apk-ci.env: this build has no apk repo credentials" echo "the package was built and signed, and is not published" exit 0 fi set +x # never echo the S3 credentials into the build log . ~/.apk-ci.env export RCLONE_CONFIG_GARAGE_TYPE=s3 export RCLONE_CONFIG_GARAGE_PROVIDER=Other export RCLONE_CONFIG_GARAGE_ENDPOINT="$S3_ENDPOINT" export RCLONE_CONFIG_GARAGE_REGION=garage export RCLONE_CONFIG_GARAGE_FORCE_PATH_STYLE=true export RCLONE_CONFIG_GARAGE_ACCESS_KEY_ID="$APK_CI_S3_ACCESS_KEY" export RCLONE_CONFIG_GARAGE_SECRET_ACCESS_KEY="$APK_CI_S3_SECRET_KEY" set -x # Upload only, never delete. See docs/ci.md#publish. find "$HOME/packages" -name '*.apk' -print | while read -r f; do rclone copyto "$f" "garage:$S3_BUCKET/$APK_REPO/$(basename "$f")" echo "uploaded $(basename "$f")" done echo "published; apk-mirror on phoebe re-indexes within 15 minutes" - cache_save: | # AFTER publish so an S3 hiccup cannot strand a good apk, and fatal on # purpose. Without --force an upload skips a key already there, so no # `cacher exists ||` guard is needed. See docs/ci.md#cache_save. cacher dir upload "$KEY_MOD" ~/go/pkg/mod cacher dir upload "$KEY_GOC" ~/.cache/go-build