# builds.sr.ht manifest for diff.sr.ht. One linear pipeline: install the # cache helper, assemble the shared SCSS, restore caches, package with abuild, # publish the apk, save the caches, 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 — 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 # For `make css`, not for the package — see docs/ci.md#packages. - sassc - minify secrets: # A tokens.sr.ht working token, the same secret the sibling services mount. # 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#2c6ed5794996b27b247090e6f823688646d37f43 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: compare DIR: services/compare PROJDIR: sr-ht-monorepo/services/compare CACHE_NS: sr-ht-compare # 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#environment. 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 and not the service's: the daemon was renamed to # diff.sr.ht, the git repository was not. docs/ci.md#coverage, #bench. COVER_ORIGIN: https://cov.srht.bigb.es COVER_REPO: "~bigbes/sr-ht-compare" BENCH_ORIGIN: https://bench.srht.bigb.es BENCH_REPO: "~bigbes/sr-ht-compare" # 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 - "refs/tags/v*" tasks: # The artifacts.sr.ht client, fetched as a published blob from its own # published release. Two tasks and not one: install.sh appends its PATH export # to ~/.buildenv, which only the NEXT task sources. The installer verifies # what it downloads against checksums.txt. 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 - test: | cd "$PROJDIR" # gofmt -l exits 0 whether or not it printed anything, so the only way to # fail on its output is to look at the output; tee keeps the filenames in # the log, where they are the whole diagnosis. See docs/ci.md#test. gofmt -l . | tee /tmp/fmt test ! -s /tmp/fmt || { echo "gofmt would change the files above" >&2; exit 1; } go vet ./... # `make cover` and not a bare `go test ./...`: the test command lives in # one place, and `cover` is `test` with two flags in it. There is no DSN # guard and no service to reach — every suite here is hermetic — so # nothing can skip, and a failure fails this task. That is what the # APKBUILD's `!check` rests on. The profile goes to $HOME, not into the # checkout, which an untracked file would stamp "+dirty". docs/ci.md#test. make cover COVERPROFILE="$HOME/cover.out" - build: | cd "$PROJDIR" # -d: makedepends come from `packages:` above, so skip abuild's own # dependency resolution. The APKBUILD runs `make css` before the compile # and `make check-css` after it, because web/ go:embed-s static/. # 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: | # This build's own coverage, to the instance's cov.sr.ht, 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 header 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 — the diffing path a request is spent in — # to bench.sr.ht. A VM this small measures a shape, not a number. # docs/ci.md#bench. cd "$PROJDIR" # -s keeps the recipe out of 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. $HOME is where artifacts look. make -s bench > "$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. Nothing here can skip. docs/ci.md#the-greps. grep -q '^BenchmarkDiff/' "$HOME/bench.txt" grep -q '^BenchmarkCommitPatch' "$HOME/bench.txt" grep -q '^BenchmarkCutPatch/' "$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