Gitea workflow: sparse checkout, diagnostic step removed
Build Kvitt images / build (push) Successful in 6m7s

Checkout is a cone-mode sparse checkout of server and infra/backup (the
two build contexts), which makes actions/checkout fetch with
--filter=blob:none. fetch-depth stays 0: with depth 1, fetch-tags only
auto-follows tags on the fetched commit, and the version step needs
every v1.0.* tag. The temporary secrets diagnostic step is gone and the
header names kvitt_cicd as the owner's user-level secret.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
2026-10-19 20:37:27 +02:00
parent b1f4c10a3d
commit 3820f9c3c3
2 changed files with 25 additions and 25 deletions
+15 -21
View File
@@ -6,8 +6,8 @@
# plain HTTP), each tagged with the version vMAJOR.MINOR.PATCH and `latest`, then pushes the git tag of that version.
# On the Kvitt Pi: /opt/kvitt/deploy.sh <version>.
#
# Secret: `kvitt_cicd`, a repository secret holding a Gitea access token with scope write:package of the user that
# pushes (owner step, infra/README.md). It is used only for `docker login`; the git tag push at the end goes through
# Secret: `kvitt_cicd`, a user-level secret of the repository owner (Gitea gives a repository its owner's secrets)
# holding a Gitea access token with scope write:package of the user that pushes (owner step, infra/README.md). It is used only for `docker login`; the git tag push at the end goes through
# the credentials actions/checkout stored (the job's own token), not this secret, so it needs no write:repository.
#
# RISK: the runner is a Raspberry Pi 3 with 1 GB RAM and the server image compiles about 232 Rust crates
@@ -44,25 +44,6 @@ jobs:
steps:
- name: Install Git and Docker CLI
run: apk add --no-cache git docker-cli docker-cli-buildx
# TEMPORARY (D-120 follow-up): remove this step once the cause of the empty `kvitt_cicd` secret is known.
# Prints only lengths (0 = absent or empty) and non-secret context values, never a secret value.
# Gitea stores secret names upper-cased and the expression lookup is case-insensitive; the upper-case line
# tests that on this runner. babymonitor_cicd is the owner's known-working user-level secret (control).
# GITEA_TOKEN and github.token are the job's automatic token.
- name: Diagnose secrets (temporary, D-120 follow-up)
run: |
A='${{ secrets.kvitt_cicd }}'; printf 'secrets.kvitt_cicd length: %s\n' "${#A}"
A='${{ secrets.KVITT_CICD }}'; printf 'secrets.KVITT_CICD length: %s\n' "${#A}"
A='${{ secrets.babymonitor_cicd }}'; printf 'secrets.babymonitor_cicd length: %s\n' "${#A}"
A='${{ secrets.GITEA_TOKEN }}'; printf 'secrets.GITEA_TOKEN length: %s\n' "${#A}"
A='${{ github.token }}'; printf 'github.token length: %s\n' "${#A}"
unset A
printf 'github.repository: %s\n' '${{ github.repository }}'
printf 'github.repository_owner: %s\n' '${{ github.repository_owner }}'
printf 'github.actor: %s\n' '${{ github.actor }}'
printf 'github.event_name: %s\n' '${{ github.event_name }}'
printf 'github.ref: %s\n' '${{ github.ref }}'
printf 'github.server_url: %s\n' '${{ github.server_url }}'
- name: Log in to Gitea Container Registry
# The owner's proven form: the secret interpolated into the run line (act_runner masks it in the log).
# The env-based form (env: REGISTRY_TOKEN: ${{ secrets.kvitt_cicd }}) came through empty on act_runner 0.6.1.
@@ -84,6 +65,18 @@ jobs:
with:
# Tells the action to use the local 'git' binary installed above
set-safe-directory: 'true'
# Only the two build contexts: server/Dockerfile copies its own context (server/, Cargo workspace,
# migrations and the import's category table included) and infra/backup/Dockerfile copies backup.sh and
# healthcheck.sh. Cone mode also checks out the files at the root and directly in infra/. A sparse
# checkout makes the action fetch with --filter=blob:none, so only the blobs of these paths are downloaded
# (not the Android screenshot goldens).
sparse-checkout: |
server
infra/backup
sparse-checkout-cone-mode: true
# Full commit and tag history (trees and commits only, no blobs, because of the filter above): "Determine
# Version" needs every v1.0.* tag. With fetch-depth 1, fetch-tags: true only drops --no-tags, so git
# fetches just the tags that point at the fetched commit, not the older v1.0.N.
fetch-depth: 0
- name: Determine Version
run: |
@@ -132,6 +125,7 @@ jobs:
rm -f "/tmp/kvitt-$name.metadata.json"
done
- name: Tag and Push Version
# The tag points at HEAD, which the remote already has; works with the sparse, blob-filtered checkout.
run: |
git tag "$VERSION"
git push origin "$VERSION"
+10 -4
View File
@@ -241,10 +241,16 @@ fresh start and after a run, red at 26 h. (The Caddy and cert-sync rehearsals of
### Gitea Actions workflow (`.gitea/workflows/build-images.yaml`)
Same setup as the owner's working example: `runs-on: host`, `sh` steps, `apk add git docker-cli docker-cli-buildx`,
`docker login gitea.lan` with the repository secret `kvitt_cicd` (created by the owner) and `${{ github.actor }}`,
a buildx builder whose `buildkitd.toml` sets `http = true` for `gitea.lan` (created once and reused, so its cache
survives), `actions/checkout@v4` with `set-safe-directory` and `fetch-depth: 0`, the version from the newest
`v1.0.*` git tag plus one, and the git tag pushed after the build. That version is what `deploy.sh` takes.
`docker login gitea.lan` with `kvitt_cicd` (a user-level secret of the repository owner, created by the owner;
Gitea gives a repository its owner's secrets) and `${{ github.actor }}`, a buildx builder whose `buildkitd.toml`
sets `http = true` for `gitea.lan` (created once and reused, so its cache survives), `actions/checkout@v4` with
`set-safe-directory` and `fetch-depth: 0`, the version from the newest `v1.0.*` git tag plus one, and the git tag
pushed after the build. That version is what `deploy.sh` takes.
The checkout is a cone-mode sparse checkout of `server` and `infra/backup` only, the two build contexts (neither
Dockerfile copies anything outside its context), so the action fetches with `--filter=blob:none` and writes only
those files instead of all 2118 (52 MB of Android screenshot goldens among them; about 95 s on the first runs).
`fetch-depth: 0` stays because the version needs every `v1.0.*` tag (commits and trees only, no blobs): with
`fetch-depth: 1`, `fetch-tags: true` brings only tags that point at the fetched commit.
The token is interpolated into the login step's `run` line (`printf '%s' "${{ secrets.kvitt_cicd }}" | docker login
...`), the owner's proven form: the first run on the runner (2026-10-19) got an empty token from the env-based form
(`env: REGISTRY_TOKEN: ${{ secrets.kvitt_cicd }}`) on act_runner 0.6.1 and failed with "password is empty";