Files
flake-hub/docs/publishing-gitea-local-fork.md
Oleks ef13a18b4c
ci/woodpecker/push/arm64 Pipeline failed
ci/woodpecker/push/amd64 Pipeline failed
docs: gitea-local-fork end-to-end publishing flow
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.
2026-05-27 14:36:03 +03:00

175 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```bash
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
```bash
cd ~/projects/nix-customs/flake-hub
just gitea-update
```
Under the hood, `scripts/update-gitea-local-fork.sh`:
1. **Wipes stale unstable tags**`git push oleks :refs/tags/v*-unstable-*`
so `nix-update` sees only clean semver tags (`v1.26.0` etc.) when
constructing the new version.
2. **Bumps the pin**
```bash
nix run nixpkgs#nix-update -- \
--flake gitea-local-fork \
--version=branch=main \
--build
```
Updates `rev`, `vendorHash`, `pnpmDeps` hash, and `version` (formatted
as `<latest-semver-tag>-unstable-<commit-date>`).
3. **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 of
`oleks/main`.
4. **Commits + pushes flake-hub** — the bumped `packages/gitea-local-fork.nix`
lands on `git.oleks.space/oleks/flake-hub` `main`.
### 3. Woodpecker picks up the flake-hub push
Pipeline auto-triggers from `.woodpecker/amd64.yaml` and `.woodpecker/arm64.yaml`
running in parallel. Each workflow:
1. Clones `oleks/flake-hub` using the `gitea_clone_token` secret.
2. Runs `ci/setup.sh` — configures `/etc/hosts` to pin `armer`
directly (bypassing Cloudflare upload-size limits via hairpin NAT)
and writes the trusted substituters / public keys to `/etc/nix/nix.conf`.
3. Runs `ci/build.py <arch>` — for each package (including
`gitea-local-fork` on `x86_64-linux` and `aarch64-linux`):
```bash
nix build .#packages.<arch>.gitea-local-fork --print-build-logs ...
attic push attic-infra-cache-k3s-1 <closure>
```
Authenticates the push with `ATTIC_TOKEN` against
`https://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:
<!-- markdownlint-disable MD013 -->
```bash
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
```
<!-- markdownlint-enable MD013 -->
## Diagram
```text
┌────────────────────────────────────────────────────────────────────────┐
│ 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 for `fetchgit` of
the fork.
- `attic_token` — authenticate `attic push` against
`nix-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 `oleks` remote auth in your
shell; the pre-push hook also runs lint.
- **Step 3 build — first cold build ≈1015 min/arch, later ≈12 min.**
Normal; Go 1.26.3 compiles from source.
- **Step 3 attic — push hangs or 413.** `ci/setup.sh` pins armer in
`/etc/hosts` to bypass the Cloudflare 100 MB upload cap; confirm the
pin survived.
- **Step 5 consume — cache miss, recompile locally.** Check the closure
landed (`attic info` or 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`