# builds.sr.ht manifest for tokens.sr.ht. One linear pipeline: restore caches, # start a Postgres in the VM, test, package with abuild, publish, and upload # this build's own coverage and benchmarks to cov.sr.ht and 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. Add paragraphs to docs/ci.md and a pointer here. image: alpine/edge packages: - abuild - curl - go - git # For the stylesheet, which is compiled here and embedded in the binary. - sassc - minify # For the database suites, not for the package — see docs/ci.md#packages. - postgresql - postgresql-client secrets: # A tokens.sr.ht working token — one this daemon itself issued, which is what # makes the three uploads below dogfooding rather than integration. It must # carry artifacts:upload (publish), cov:upload (coverage) and # bench:upload (bench); missing one fails that upload and no other. # See docs/ci.md#secrets. - c7968415-1a6d-4ca0-a188-150fb7f57b65 # ~/.srht-token sources: - https://git.srht.bigb.es/~bigbes/sr-ht-monorepo#ed91e78236153e042fca4722812191969e86ae0f 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: tokens DIR: services/tokens PROJDIR: sr-ht-monorepo/services/tokens CACHE_NS: sr-ht-tokens PG_DB: tokenssrht # Where the apk goes, and the only place it goes: one channel of # artifacts.sr.ht holds the packages of every sibling service, so a consumer # adds one repository line. 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: "no" ARTIFACTS_ENDPOINT: https://artifacts.srht.bigb.es ARTIFACTS_CHANNEL: "~bigbes/main" ARTIFACTS_DIST: v3.22 # 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#scss. CORE_VER: "0.84.7" BOOTSTRAP_REV: 779ad9f174ea5ab7e755f6df0ec9e5912d67dd16 # Where this build reports on itself. Both repository names are the one on the # `sources:` line above. docs/ci.md#coverage, #bench. COVER_ORIGIN: https://cov.srht.bigb.es COVER_REPO: "~bigbes/sr-ht-tokens" BENCH_ORIGIN: https://bench.srht.bigb.es BENCH_REPO: "~bigbes/sr-ht-tokens" # `go test -count` for the bench task. Ten is the family's number: bench's # confidence interval for a point becomes finite at six repetitions and a # comparison becomes significant at four. docs/ci.md#bench. BENCH_COUNT: "10" # Literal paths relative to $HOME; `artifacts:` has no globbing, which is why # the apk is not here. See docs/ci.md#artifacts. artifacts: - cover.out - bench.txt submitter: git.sr.ht: allow-refs: - refs/heads/master # Tags build too, now that the version task reads them: pushing v0.9.0 is # what produces the 0.9.0 apk. See docs/ci.md#version. - "refs/tags/v*" tasks: # S3-backed CI cache helper. install.sh's PATH export goes to ~/.buildenv, # which only the NEXT task sources — hence two tasks. 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 database suite and leave the build green # over untested code. docs/ci.md#test. if [ -z "$TOKENSSRHT_TEST_PG" ]; then echo "TOKENSSRHT_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 gofmt -l . | tee /tmp/fmt test ! -s /tmp/fmt || { echo "gofmt would change the files above" >&2; exit 1; } go vet ./... # -covermode=atomic (real hit counts, and this is a concurrent HTTP # server) and $HOME, which is where artifacts: looks — and, more to the # point, NOT the checkout: an untracked cover.out here would stamp every # binary built afterwards "+dirty". docs/ci.md#test. go test -covermode=atomic -coverprofile="$HOME/cover.out" ./... go tool cover -func="$HOME/cover.out" | tail -1 - build: | cd "$PROJDIR" # -d: makedepends come from `packages:`. See 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 profile the test task wrote, to the instance's cov.sr.ht. Near-last # on purpose, and nothing after it depends on it. docs/ci.md#coverage. cd "$PROJDIR" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: nothing uploaded; the profile is this build's" echo "cover.out artifact" exit 0 fi # GIT_REF is absent on a manual submission and ref is optional; key is the # idempotency key. BOTH prefixes are stripped — tags build too. 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" # set +x so the token never reaches the log; no Content-Type (the service # sniffs); --fail-with-body prints the JSON error AND exits non-zero. # docs/ci.md#the-request. set +x curl -sS --fail-with-body -X POST \ -H "Authorization: Bearer $(cat ~/.srht-token)" \ --data-binary "@$HOME/cover.out" \ "$url" echo - bench: | # This build's own benchmarks — minting, hashing, validation — to the # instance's bench.sr.ht. A VM this small measures a shape, not a number. # docs/ci.md#bench. cd "$PROJDIR" # `go test` inline, like the test task above: this repository has no # Makefile target CI runs. A redirect and a cat and NOT `| tee`, which # would hand the task tee's exit status and let a failing benchmark pass. # -timeout because ten counts of every benchmark can outrun go test's 10m # default on a VM. $HOME is where artifacts look. go test -run='^$' -bench=. -benchmem -count="$BENCH_COUNT" -timeout 20m ./... \ > "$HOME/bench.txt" cat "$HOME/bench.txt" # `go test -bench` that matches NOTHING prints "ok" and exits 0, and an # empty file is valid benchfmt: without these a renamed benchmark uploads # nothing and reports success. One name per package that has any, and none # of them can skip — no benchmark here needs the DSN. # docs/ci.md#the-greps. grep -q '^BenchmarkHashToken' "$HOME/bench.txt" grep -q '^BenchmarkParentVerify/' "$HOME/bench.txt" grep -q '^BenchmarkExchange/' "$HOME/bench.txt" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: the benchmarks ran and are above; nothing was" echo "uploaded. The file is this build's bench.txt artifact." exit 0 fi # visibility acts only on the POST that creates $BENCH_REPO. 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" set +x curl -sS --fail-with-body -X POST \ -H "Authorization: Bearer $(cat ~/.srht-token)" \ --data-binary "@$HOME/bench.txt" \ "$url" echo