# builds.sr.ht manifest for sr-ht-core: lint, build, test with a coverage # profile, then publish that profile to cov.sr.ht and this library's own # benchmarks to bench.sr.ht. # # One manifest at the repository root rather than a .builds/ directory: # builds.sr.ht has no matrix syntax, and when a repository carries several # manifests it submits at most four of them, chosen arbitrarily — so a directory # of manifests is a lottery over which tasks a push actually runs. Every sibling # service in this family uses a single root manifest for that reason, and this # repository has nothing to spread across a matrix. # # alpine/edge, not a pinned release. A pin reads like the safer choice and this # manifest carried alpine/3.22 for exactly that reason — but this instance does # not provision it: job #493 died before its first task with "Image 'alpine/3.22' # is not available for arch 'x86_64'". edge is what every sibling manifest here # uses and the only one known to boot. The pin was not discoverable as wrong # until now because the manifest it lived in had never run: every task began # `cd core-go`, a directory the fork removed when it moved the module to the # repository root, so the build failed on its first line and never reached the # image. image: alpine/edge packages: - curl - git - go # golangci-lint is NOT taken from apk: ci/lib/golangci.sh builds the pinned # version from source, so every project lints with the same one and the # linter is always built by the toolchain that compiles the code. sources: - https://git.srht.bigb.es/~bigbes/sr-ht-monorepo#70490f67726ffdf27f975a35ce32cc9849352be5 secrets: # A tokens.sr.ht working token shared with the sibling pipelines rather than # minted per repository: it already carries cov:upload and bench:upload, which # is everything this manifest asks for. A build submitted without secrets # still runs — the two upload tasks say so and stop, they do not fail. - c7968415-1a6d-4ca0-a188-150fb7f57b65 # ~/.srht-token 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: core DIR: lib/core PROJDIR: sr-ht-monorepo/lib/core # The fork moved this module to what was its repository root, and the monorepo # moved that to lib/core; there is no core-go/ subdirectory to descend into, # and a task that tries fails on its first line. PROJDIR above is the path. COVER_ORIGIN: https://cov.srht.bigb.es COVER_REPO: "~bigbes/sr-ht-core" BENCH_ORIGIN: https://bench.srht.bigb.es BENCH_REPO: "~bigbes/sr-ht-core" # Literal paths relative to $HOME, which is why the test and bench tasks write # there and not into the checkout. They are what is left when a build runs # without the token secret, not a substitute for the uploads. artifacts: - cover.out - bench.txt submitter: git.sr.ht: allow-refs: - refs/heads/master # Without this a pushed tag starts no build at all. - "refs/tags/v*" tasks: - lint: | # The same install as every other project's: one pinned version, built # from source. This task used to take whatever golangci-lint apk had, # which meant core and api could be linted by different versions and # disagree about findings — and they did. "$HOME/$REPO"/ci/lib/golangci.sh install cd "$PROJDIR" golangci-lint run - build: | cd "$PROJDIR" go build ./... - test: | cd "$PROJDIR" # -covermode=atomic gives real hit counts instead of a set/unset bit, # which is what cov.sr.ht's line counts are made of. go test -covermode=atomic -coverprofile="$HOME/cover.out" ./... go tool cover -func="$HOME/cover.out" | tail -1 - coverage: | cd "$PROJDIR" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: this build runs without cov.sr.ht credentials" echo "the profile is still available as this build's cover.out artifact" exit 0 fi # GIT_REF is absent on a manually submitted build, and ref is optional for # the API. key is the idempotency key. Both prefixes are stripped because # this pipeline builds tags too, and a tag build would otherwise report # ref=refs/tags/v0.1.0. 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 of the task: the Authorization header must not # reach the log. No Content-Type — the service sniffs the body. # --fail-with-body prints the JSON error and still exits non-zero. set +x curl -sS --fail-with-body -X POST \ -H "Authorization: Bearer $(cat ~/.srht-token)" \ --data-binary "@$HOME/cover.out" \ "$url" echo - bench: | cd "$PROJDIR" # A redirect and a cat, not `| tee`: tee's exit status would let a failing # benchmark pass. -run '^$' so no test runs a second time here, -benchmem # because the allocation counts are half of what these benchmarks are for. # # -count=10 because bench.sr.ht's confidence interval only becomes finite # at six repetitions and a comparison significant at four, so anything # under six uploads points the service can only mark "low n". -benchtime # pays for those ten repetitions: this suite has ~50 cases, and ten # repetitions at the default second apiece is a quarter of an hour on a # shared builder. 300ms still leaves millions of iterations for the # sub-microsecond cases and thousands for the Ed25519 ones. go test -run '^$' -bench . -benchmem -benchtime=300ms -count=10 \ -timeout 20m ./... > "$HOME/bench.txt" cat "$HOME/bench.txt" # `go test -bench` that matches nothing still prints ok and exits 0, and a # file with no result lines is valid benchfmt — it would upload nothing # and report success. Name one benchmark per package that has any, so a # package losing its benchmarks stops this build. grep -q '^BenchmarkDecodeBearerToken' "$HOME/bench.txt" grep -q '^BenchmarkBearerHMAC' "$HOME/bench.txt" grep -q '^BenchmarkCursorMarshalGQL' "$HOME/bench.txt" grep -q '^BenchmarkColumns' "$HOME/bench.txt" - benchmarks: | cd "$PROJDIR" if [ ! -r ~/.srht-token ]; then echo "no ~/.srht-token: this build runs without bench.sr.ht credentials" echo "the benchmarks ran and are in the bench task's log above" echo "the file is this build's bench.txt artifact, and can be POSTed by hand" exit 0 fi # visibility acts only on the POST that first creates $BENCH_REPO; on # every later run it is ignored. 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