# builds.sr.ht manifest for bench.sr.ht. One linear pipeline: restore caches, # assemble the shared SCSS, start a Postgres in the VM, test, package with # abuild, publish, then upload both numbers this build has about itself — its # coverage to cov.sr.ht and its benchmarks to bench.sr.ht. # # 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 - go - git # For the dogfooding upload, and for nothing else — see docs/ci.md#packages. - curl - sassc - minify # For the database suites, not for the package — see docs/ci.md#packages. - postgresql - postgresql-client secrets: # All FILE secrets, mode 600. Listing them turns the gated tasks on; each # still runs and still stops without its file. docs/ci.md#secrets. # ~/.srht-token holds a tokens.sr.ht WORKING TOKEN, one secret shared with # cov.sr.ht's pipeline rather than a per-service one. This build needs three # grants in it — bench:upload, cov:upload, artifacts:upload — and cov's build # needs the same three from the same file. A token missing one fails that # service's upload and no other. docs/ci.md#secrets. - c7968415-1a6d-4ca0-a188-150fb7f57b65 # ~/.srht-token sources: - https://git.srht.bigb.es/~bigbes/sr-ht-monorepo#c090ed62d8bd82c0b48d63820fc0684ffb59be69 environment: # A package build must not depend on the workspace. GOWORK=off makes this job # resolve lib/core, lib/ecore and lib/thistle from the pseudo-versions in this # module's own go.mod — the versions the released apk is actually built from — # instead of from whatever is in the tree. It also stops the build writing to # go.work.sum, which is what stamped fedgw's binary -dirty and failed its # check-version. Workspace compatibility is the dispatcher's job: it smoke- # builds every project against the tree on each push. GOWORK: "off" # What ci/lib/*.sh needs to know about this project. REPO: sr-ht-monorepo PROJECT: bench DIR: services/bench PROJDIR: sr-ht-monorepo/services/bench CACHE_NS: sr-ht-bench PG_DB: benchsrht # CORE_VER must track the deployment's SRHT_CORE_VER; BOOTSTRAP_REV is the # submodule commit core.sr.ht pins at that tag. See docs/ci.md#environment. CORE_VER: "0.84.7" BOOTSTRAP_REV: 779ad9f174ea5ab7e755f6df0ec9e5912d67dd16 BENCH_ORIGIN: https://bench.srht.bigb.es BENCH_REPO: "~bigbes/sr-ht-bench" # The other half of the cross: the same repository name on the sibling that # stores coverage, because it is what `sources:` clones. docs/ci.md#coverage. COVER_ORIGIN: https://cov.srht.bigb.es COVER_REPO: "~bigbes/sr-ht-bench" # Where the apk goes, and the only place it goes: one channel of # artifacts.sr.ht holds every sibling's packages. See docs/ci.md#publish. # A branch build tests and does not publish: ci/lib/dispatch.sh rewrites this # to "yes" for a master or tag push and for nothing else. docs/ci.md#publish PUBLISH: "yes" ARTIFACTS_ENDPOINT: https://artifacts.srht.bigb.es ARTIFACTS_CHANNEL: "~bigbes/main" ARTIFACTS_DIST: v3.22 # Literal paths relative to $HOME, and the two upload bodies rather than the apk # — whose name changes every commit. Argued in docs/ci.md#artifacts. artifacts: - bench.txt - cover.out submitter: git.sr.ht: allow-refs: - refs/heads/master # Without this a pushed tag starts no build at all. docs/ci.md#submitter. - "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. See ci/lib/art.sh. - art_install: | "$HOME/$REPO"/ci/lib/art.sh install - art_init: | "$HOME/$REPO"/ci/lib/art.sh init - scss: | "$HOME/$REPO"/ci/lib/scss.sh - keygen: | "$HOME/$REPO"/ci/lib/keygen.sh - version: | "$HOME/$REPO"/ci/lib/version.sh - cache_restore: | "$HOME/$REPO"/ci/lib/cache.sh restore - postgres: | "$HOME/$REPO"/ci/lib/postgres.sh - test: | cd "$PROJDIR" # An empty DSN would skip every Postgres-backed suite and leave the build # green over untested code — the 4.5%-vs-77.2% gap. docs/ci.md#test. if [ -z "$BENCHSRHT_TEST_PG" ]; then echo "BENCHSRHT_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 # A make target and not a bare `go test ./...`: the Makefile names this # repository's -timeout (sr-ht-bench-5b8.44) and a second copy of that # number here is a second copy to forget. `cover` and not `test`: the same # suite, writing the profile the coverage task uploads, in the ONE run # that already exists. $HOME is where artifacts look. docs/ci.md#test. make -s cover COVERPROFILE="$HOME/cover.out" go tool cover -func="$HOME/cover.out" | tail -1 - build: | cd "$PROJDIR" # -d: makedepends come from `packages:`. The APKBUILD runs `make css` # before `make build` and asserts the result twice. docs/ci.md#build. REPODEST=$HOME/packages abuild -d find "$HOME/packages" -name '*.apk' - publish: | "$HOME/$REPO"/ci/lib/publish.sh - cache_save: | "$HOME/$REPO"/ci/lib/cache.sh save - coverage: | # The other half of the dogfooding cross (SPEC ch. 13): this service's own # coverage, uploaded to cov.sr.ht. Before bench and not after, for the # reason docs/ci.md#coverage gives. cd "$PROJDIR" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: this build has no cov.sr.ht credentials" echo "the profile is still this build's cover.out artifact" exit 0 fi # A missing or empty profile is a 400 nobody reads. Say it here instead. test -s "$HOME/cover.out" || { echo "cover.out is missing or empty" >&2; exit 1; } # GIT_REF is absent on a manual build and ref is optional; key is the # idempotency key. Both prefixes: this pipeline builds tags too. # docs/ci.md#the-coverage-request. ref="${GIT_REF#refs/heads/}"; ref="${ref#refs/tags/}" url="$COVER_ORIGIN/api/v1/repos/$COVER_REPO/reports" url="$url?commit=$(git rev-parse HEAD)&ref=$ref&key=$JOB_ID&job_url=$JOB_URL" echo "uploading cover.out to $url" # Tracing off to the end: the header must not reach the log. No # Content-Type — the service sniffs the format. set +x curl -sS --fail-with-body -X POST \ -H "Authorization: Bearer $(cat ~/.srht-token)" \ --data-binary "@$HOME/cover.out" \ "$url" echo - bench: | # Dogfooding (SPEC ch. 13): this service's own benchmarks, uploaded to its # own instance, parsed by the parser in this very commit. Last and a task # of its own on purpose; a VM this small measures a shape rather than a # number. docs/ci.md#bench. cd "$PROJDIR" # BenchmarkSeries needs a database and SKIPS without the DSN, printing no # line at all, so the test task's guard stands here too. # docs/ci.md#the-dsn-guard-and-the-two-greps. if [ -z "$BENCHSRHT_TEST_PG" ]; then echo "BENCHSRHT_TEST_PG is unset: BenchmarkSeries would skip silently," >&2 echo "and this build would upload half a file without saying so." >&2 exit 1 fi # -s so make does not echo the recipe into the body; a redirect and a cat # and NOT `| tee`, which would hand the task tee's exit status and let a # failing benchmark pass. docs/ci.md#bench. make -s bench > "$HOME/bench.txt" cat "$HOME/bench.txt" # Both must be in there: `go test -bench` matching nothing prints ok and # exits 0, and a body with no results is a 400 (SPEC ch. 4.1). grep -q '^BenchmarkIngest' "$HOME/bench.txt" grep -q '^BenchmarkSeries' "$HOME/bench.txt" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: this build has no bench.sr.ht credentials" echo "the benchmarks ran and are above; nothing was uploaded" echo "the file is this build's bench.txt artifact, and can be POSTed by hand" exit 0 fi # GIT_REF is absent on a manual build and ref is optional; key is SPEC # ch. 4.1's idempotency key; visibility acts only on the POST that creates # $BENCH_REPO. See docs/ci.md#the-request. ref="${GIT_REF#refs/heads/}"; ref="${ref#refs/tags/}" url="$BENCH_ORIGIN/api/v1/repos/$BENCH_REPO/runs" url="$url?commit=$(git rev-parse HEAD)&ref=$ref&key=$JOB_ID&job_url=$JOB_URL" url="$url&visibility=public" echo "uploading bench.txt to $url" # Tracing off to the end: the header must not reach the log. # --fail-with-body prints the error and still exits non-zero. set +x curl -sS --fail-with-body -X POST \ -H "Authorization: Bearer $(cat ~/.srht-token)" \ --data-binary "@$HOME/bench.txt" \ "$url" echo