Rescued from the second flake-hub checkout (~/projects/flake-hub) before that working copy was removed. Documents the path from local Gitea fork to the attic binary cache.
8.6 KiB
Publishing gitea-local-fork
End-to-end flow for taking a change in Oleks's local gitea fork
(/home/oleks/projects/gitea, branch oleks/main) all the way to a
binary in the attic-infra-cache-k3s-1 cache, ready for any consumer
to fetch instead of recompiling Go 1.26.3 locally.
Step-by-step
1. Develop in the gitea fork
cd ~/projects/gitea
# work on oleks/main (the fork integration tip)
git commit -m "..."
git push oleks oleks/main:main
Lands on git.oleks.space/oleks/gitea at refs/heads/main.
This step alone does not trigger any CI on flake-hub — the binding contract is the flake-hub pin commit in step 2.
2. Bump the pin in flake-hub
cd ~/projects/nix-customs/flake-hub
just gitea-update
Under the hood, scripts/update-gitea-local-fork.sh:
-
Wipes stale unstable tags —
git push oleks :refs/tags/v*-unstable-*sonix-updatesees only clean semver tags (v1.26.0etc.) when constructing the new version. -
Bumps the pin —
nix run nixpkgs#nix-update -- \ --flake gitea-local-fork \ --version=branch=main \ --buildUpdates
rev,vendorHash,pnpmDepshash, andversion(formatted as<latest-semver-tag>-unstable-<commit-date>). -
Tags the gitea fork at the new rev with
v<version>and pushes the tag. This is the load-bearing step: the tag makes the rev reachable forever, surviving any future rebase / force-push ofoleks/main. -
Commits + pushes flake-hub — the bumped
packages/gitea-local-fork.nixlands ongit.oleks.space/oleks/flake-hubmain.
3. Woodpecker picks up the flake-hub push
Pipeline auto-triggers from .woodpecker/amd64.yaml and .woodpecker/arm64.yaml
running in parallel. Each workflow:
-
Clones
oleks/flake-hubusing thegitea_clone_tokensecret. -
Runs
ci/setup.sh— configures/etc/hoststo pinarmerdirectly (bypassing Cloudflare upload-size limits via hairpin NAT) and writes the trusted substituters / public keys to/etc/nix/nix.conf. -
Runs
ci/build.py <arch>— for each package (includinggitea-local-forkonx86_64-linuxandaarch64-linux):nix build .#packages.<arch>.gitea-local-fork --print-build-logs ... attic push attic-infra-cache-k3s-1 <closure>Authenticates the push with
ATTIC_TOKENagainsthttps://nix-cache-upload.oleks.space.
4. Closure lives in attic
After both arch workflows succeed, the closure is queryable from:
- Cache URL:
https://nix-cache-custom.oleks.space/attic-infra-cache-k3s-1 - Public key:
attic-infra-cache-k3s-1:qYSNK3DmttQXCFqn1t50qoWGtQNPRFWq9mgQjD05DeU=
5. Consume from cache
Anyone (or any host) can pull the binary instead of building:
just gitea-run
# or, equivalently:
nix run \
--extra-substituters "https://nix-cache-custom.oleks.space/attic-infra-cache-k3s-1" \
--extra-trusted-public-keys "attic-infra-cache-k3s-1:qYSNK3DmttQXCFqn1t50qoWGtQNPRFWq9mgQjD05DeU=" \
git+https://git.oleks.space/oleks/flake-hub#gitea-local-fork
Diagram
┌────────────────────────────────────────────────────────────────────────┐
│ 1. ~/projects/gitea (branch oleks/main) │
│ ─ git push oleks oleks/main:main ─► oleks/gitea refs/heads/main │
└────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 2. ~/projects/nix-customs/flake-hub │
│ ─ just gitea-update │
│ a. wipe v*-unstable-* tags on fork │
│ b. nix-update → bump rev/hashes/version │
│ c. tag fork at new rev: v<version> ─► push │
│ d. commit + push flake-hub origin/main │
└────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 3. ci.oleks.space pipeline auto-fires │
│ amd64 + arm64 (parallel): │
│ clone → ci/setup.sh → ci/build.py <arch> │
│ ─ nix build .#packages.<arch>.gitea-local-fork │
│ ─ attic push attic-infra-cache-k3s-1 <closure> │
└────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 4. attic-infra-cache-k3s-1 │
│ URL: https://nix-cache-custom.oleks.space/attic-infra-cache-k3s-1 │
└────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 5. Consumer: just gitea-run / nix run …#gitea-local-fork │
│ ─ closure pulled from cache, no recompile │
└────────────────────────────────────────────────────────────────────────┘
Secrets
Both are Woodpecker repo secrets on oleks/flake-hub (never in code):
gitea_clone_token— clone flake-hub source; netrc forfetchgitof the fork.attic_token— authenticateattic pushagainstnix-cache-upload.oleks.space.
Why the dance with tags in step 2c
The fork's oleks/main branch is rebaseable. fetchgit in the
derivation resolves by rev, so the rev must remain reachable from
some ref on the remote. Tags are immutable. The
v<version> tag created at update time becomes the load-bearing
reference: even if oleks/main later gets force-pushed and the rev
falls off the branch, the tag keeps it alive (and Gitea won't GC it).
Failure points to watch
- Step 2c — tag push rejected. Check
oleksremote auth in your shell; the pre-push hook also runs lint. - Step 3 build — first cold build ≈10–15 min/arch, later ≈1–2 min. Normal; Go 1.26.3 compiles from source.
- Step 3 attic — push hangs or 413.
ci/setup.shpins armer in/etc/hoststo bypass the Cloudflare 100 MB upload cap; confirm the pin survived. - Step 5 consume — cache miss, recompile locally. Check the closure
landed (
attic infoor browse the cache URL) and that the public key matches.
Reference
- Derivation:
packages/gitea-local-fork.nix - Flake attr:
flake.nix→packages.<system>.gitea-local-fork - Update script:
scripts/update-gitea-local-fork.sh(untracked, local-only) - Pipelines:
.woodpecker/amd64.yaml,.woodpecker/arm64.yaml - Build driver:
ci/build.py - Justfile recipes:
just gitea-build,just gitea-update,just gitea-run