~bigbes/sr-ht-spec

b6931bdad118348d1e174299d960b1d0a6ee2189 — Eugene Blikh 26 days ago c8533be
build: package spec.sr.ht as an apk and wire push->build->mirror

Deploy the service from our own apk repo instead of cloning and
compiling this tree inside the srht stack's Dockerfile.

- APKBUILD: build css then static binaries (CGO_ENABLED=0), install
  under ASSETS=/usr/share/sourcehut so specsrht-migrate resolves schema
  and migrations at the real runtime path. pkgver rewritten by CI to
  0.0.<commit-count> for a monotonic, pinnable version.
- .build.yml: builds.sr.ht manifest — assemble the shared sourcehut
  scss partials (core.sr.ht CORE_VER + pinned Bootstrap submodule),
  throwaway per-build signing key, abuild, publish *.apk to the Garage
  repo bucket (append-only; apk-mirror on phoebe re-indexes and signs).
- .sourcecraft/webhooks.yaml: push webhook to the phoebe gitsync
  service so the git.srht.bigb.es mirror updates in seconds, which is
  what makes the push -> apk build fire immediately.
3 files changed, 144 insertions(+), 0 deletions(-)

A .build.yml
A .sourcecraft/webhooks.yaml
A APKBUILD
A .build.yml => .build.yml +82 -0
@@ 0,0 1,82 @@
image: alpine/edge
packages:
  - abuild
  - go
  - git
  - rclone
  - sassc
  - minify
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
sources:
  - https://git.srht.bigb.es/~bigbes/sr-ht-spec
environment:
  REPO: sr-ht-spec
  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.
  CORE_VER: "0.83.8"
  BOOTSTRAP_REV: 779ad9f174ea5ab7e755f6df0ec9e5912d67dd16
submitter:
  git.sr.ht:
    allow-refs:
      - refs/heads/master
tasks:
  - scss: |
      # No apk ships the shared sourcehut SCSS partials, so assemble them the
      # way core.sr.ht's `make install-scss` would: its own scss/ plus the
      # Bootstrap 4 submodule. `make css` runs sassc -I against this tree.
      git clone --depth 1 --branch "$CORE_VER" \
        https://git.sr.ht/~sircmpwn/core.sr.ht /tmp/core
      sudo mkdir -p /usr/share/sourcehut/scss/bootstrap
      sudo cp /tmp/core/scss/*.scss /tmp/core/scss/*.css /usr/share/sourcehut/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
      sudo cp -r /tmp/bootstrap/scss /usr/share/sourcehut/scss/bootstrap/scss
  - keygen: |
      # abuild insists on signing what it builds, but this key is deliberately
      # throwaway: generated per build, dies with the VM, trusted by nothing.
      # Clients verify against the index instead, which is rebuilt and signed on
      # phoebe by the garage stack's apk-mirror service — it indexes this repo
      # with --allow-untrusted precisely because of this.
      #
      # -i installs the public half into /etc/apk/keys. Without it abuild's own
      # final "update the local repository index" step dies with UNTRUSTED
      # signature, after having built the package perfectly well.
      SUDO=sudo abuild-keygen -a -n -i -q
  - version: |
      cd "$REPO"
      ver="0.0.$(git rev-list --count HEAD)"
      sed -i "s/^pkgver=.*/pkgver=$ver/" APKBUILD
      echo "export PKGVER=$ver" >> ~/.buildenv
      echo "building $ver"
  - build: |
      cd "$REPO"
      # -d: makedepends are already installed via `packages:` above.
      REPODEST=$HOME/packages abuild -d
      find "$HOME/packages" -name '*.apk'
  - publish: |
      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. Old versions stay so a pinned deployment can
      # always be rebuilt — the same reason the upstream mirror is append-only.
      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"

A .sourcecraft/webhooks.yaml => .sourcecraft/webhooks.yaml +24 -0
@@ 0,0 1,24 @@
# Notifies the lab's gitsync service that this repo has moved, so the mirror on
# our self-hosted sourcehut updates within seconds instead of waiting for its
# hourly safety-net poll. That matters beyond the mirror itself: builds.sr.ht CI
# (see .build.yml) only fires once the commit lands on the sourcehut side, so
# this webhook is what makes push -> apk build feel immediate.
#
# The receiver verifies the HMAC-SHA256 in X-Src-Signature over the request
# body. The signing key is generated by SourceCraft, is not part of this file,
# and is read once from Автоматизации -> Вебхуки into the gitsync stack's .env.
#
# The slug is unique per repository, but the receiver serves all three repos and
# maps slug -> signing key, so it must be unique ACROSS them too — hence the
# suffix rather than a plain "gitsync".
webhooks:
  hooks:
    - slug: gitsync-spec
      name: "gitsync mirror trigger"
      description: "Triggers the phoebe gitsync service to mirror sr-ht-spec to git.srht.bigb.es"
      url: "https://gitsync.bigb.es/hook"
      ssl_verification: true
      active: true
  on:
    push:
      - hooks: ["gitsync-spec"]

A APKBUILD => APKBUILD +38 -0
@@ 0,0 1,38 @@
# Maintainer: bigbes <bigbes@gmail.com>
#
# Built by builds.sr.ht (.build.yml) and published to our own apk repo at
# repo.bigb.es/alpine/v3.22/bigbes. The srht deployment installs it from there
# instead of cloning and compiling this repo inside its Dockerfile.
#
# pkgver is rewritten by CI to 0.0.<commit count> before abuild runs — a
# monotonic, unique-per-commit version that the deployment can pin.
pkgname=spec.sr.ht
pkgver=0.0.0
pkgrel=0
pkgdesc="Reviewable document storage for humans and agents"
url="https://sourcecraft.dev/bigbes/sr-ht-spec"
arch="x86_64"
license="MIT"
# !check      — tests want a live Postgres and a git work area
# !tracedeps  — CGO_ENABLED=0, so the binaries are static
options="!check !tracedeps"

source=""
builddir="$startdir"

build() {
	cd "$builddir"
	# CSS strictly before the binaries: web/ go:embed-s static/, so a
	# stylesheet built afterwards would never make it into the binary. The
	# shared scss partials are assembled by CI at ASSETS/scss (no apk ships
	# them).
	make css ASSETS=/usr/share/sourcehut
	CGO_ENABLED=0 make build GOFLAGS="-trimpath"
}

package() {
	cd "$builddir"
	# This Makefile honours DESTDIR; ASSETS must stay the real runtime path so
	# migrations and schema land where specsrht-migrate resolves them.
	make install DESTDIR="$pkgdir" PREFIX=/usr ASSETS=/usr/share/sourcehut
}