Publish release / publish (push) Successful in 1m7s
The portal repo no longer deploys instances. CI builds once, packages portal + question_lint + site/ into a tarball, and publishes it as a Gitea release tagged build-<shortsha> using the run's ephemeral token. Content repos (uhhm/questions, redoal/questions) now own their instance deploys - env, unit restart, Caddy route - pinned to a release tag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
99 lines
4.8 KiB
YAML
99 lines
4.8 KiB
YAML
name: Publish release
|
|
|
|
# Portal no longer deploys itself. Each content repo (uhhm/questions,
|
|
# redoal/questions) owns its instance - domain, port, env, Caddy route -
|
|
# and its deploy workflow downloads a pinned release published here.
|
|
# Rolling a new portal version out to a site = bumping PORTAL_RELEASE
|
|
# in that site's .gitea/workflows/deploy.yml (an auditable commit).
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
publish:
|
|
runs-on: bare
|
|
env:
|
|
# The bare runner's own systemd service intentionally has a minimal
|
|
# PATH/HOME (no rustup default toolchain in reach) - point it at the
|
|
# shared toolchain install directly rather than assuming an ambient
|
|
# dev shell environment.
|
|
CARGO_HOME: /var/local/cargo
|
|
RUSTUP_HOME: /var/local/rustup
|
|
PATH: /var/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin
|
|
# Shared with interactive dev builds (see ~/.config/fish/config.fish)
|
|
# so a crate compiled once, by either a manual build or CI, is
|
|
# cached for the other - real cache hits, not just a warm toolchain.
|
|
# SCCACHE_SERVER_PORT deliberately differs from the interactive
|
|
# dev shell's (4227): sccache's server is discovered by a fixed
|
|
# TCP port shared by every local user, so if both contexts used
|
|
# the same port, whichever one's server happened to be running
|
|
# would silently "win" and serve build requests it doesn't have
|
|
# filesystem permission for. Separate ports keep each context's
|
|
# own server answering its own requests; the cache directory
|
|
# (not the server process) is what's actually shared.
|
|
SCCACHE_DIR: /var/local/sccache
|
|
SCCACHE_SERVER_PORT: "4228"
|
|
CARGO_TARGET_DIR: /var/local/cargo-target
|
|
# cargo-leptos's own downloaded tools (wasm-bindgen, wasm-opt) cache
|
|
# under $XDG_CACHE_HOME - left at its default that resolves inside
|
|
# this unit's systemd StateDirectory, files it creates there end up
|
|
# owned by the kernel's overflow "nobody" uid instead of the
|
|
# runner's own dynamic uid (a StateDirectory quirk, not something
|
|
# in our control), so a later run can't execute what an earlier run
|
|
# downloaded. Redirecting it to our own known-good shared dir avoids
|
|
# that entirely.
|
|
XDG_CACHE_HOME: /var/local/leptos-cache
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# SITE_NAME is read via option_env! (src/app.rs) - compile-time,
|
|
# not a runtime env var. It is only the last-resort fallback name:
|
|
# each instance's site.yaml (content-driven branding) overrides it,
|
|
# so one artifact serves every site.
|
|
- name: Build
|
|
run: SITE_NAME=${{ vars.PORTAL_SITE_NAME }} cargo leptos build --release
|
|
|
|
# cargo-leptos only builds the leptos bin-target ("portal") - the
|
|
# question-lint utility binary needs its own plain cargo build.
|
|
- name: Build question-lint
|
|
run: cargo build --release --bin question_lint --features ssr
|
|
|
|
- name: Package
|
|
run: |
|
|
set -euo pipefail
|
|
tag="build-$(echo ${{ github.sha }} | cut -c1-7)"
|
|
echo "TAG=$tag" >> "$GITHUB_ENV"
|
|
stage=$(mktemp -d)
|
|
cp "$CARGO_TARGET_DIR/release/portal" "$stage/portal"
|
|
cp "$CARGO_TARGET_DIR/release/question_lint" "$stage/question_lint"
|
|
# site-root ("target/site" in Cargo.toml) is project-relative,
|
|
# not affected by CARGO_TARGET_DIR - only the plain `cargo build`
|
|
# outputs (release/, front/) move with that override.
|
|
cp -r target/site "$stage/site"
|
|
tar -C "$stage" -czf "portal-$tag.tar.gz" portal question_lint site
|
|
rm -rf "$stage"
|
|
|
|
# The run's own ephemeral token has write access to this repo -
|
|
# no long-lived PAT to manage. Re-running a build for the same sha
|
|
# finds the existing release instead of failing on the tag.
|
|
- name: Publish release
|
|
run: |
|
|
set -euo pipefail
|
|
api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
|
|
auth="Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
|
subject=$(git log -1 --format=%s)
|
|
body=$(printf '{"tag_name":"%s","target_commitish":"%s","name":"%s"}' \
|
|
"$TAG" "${{ github.sha }}" "$TAG: $(echo "$subject" | sed 's/"/\\"/g')")
|
|
id=$(curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' \
|
|
-d "$body" "$api/releases" | jq .id) \
|
|
|| id=$(curl -sf -H "$auth" "$api/releases/tags/$TAG" | jq .id)
|
|
# Replace the asset if a re-run already uploaded one.
|
|
for aid in $(curl -sf -H "$auth" "$api/releases/$id/assets" | jq '.[].id'); do
|
|
curl -sf -X DELETE -H "$auth" "$api/releases/$id/assets/$aid"
|
|
done
|
|
curl -sf -X POST -H "$auth" \
|
|
-F "attachment=@portal-$TAG.tar.gz" \
|
|
"$api/releases/$id/assets?name=portal-$TAG.tar.gz" > /dev/null
|
|
echo "published $TAG"
|