Single-label runs-on; document Gitea quirks
This commit is contained in:
@@ -77,9 +77,13 @@ on:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- ${{ inputs.host }}
|
||||
# Single-label `runs-on` (not the [self-hosted, <host>] array form). In
|
||||
# Gitea/act_runner, the array is matched loosely — a runner advertising
|
||||
# only `self-hosted` will pick up jobs intended for a specific host. Using
|
||||
# the bare host label routes deterministically to the correct runner.
|
||||
# Every runner advertises both `self-hosted` and its host short name (see
|
||||
# Charlie/runners envs/<host>.env GITEA_RUNNER_LABELS).
|
||||
runs-on: ${{ inputs.host }}
|
||||
steps:
|
||||
- name: Resolve stack path and ref
|
||||
id: resolve
|
||||
|
||||
+70
-5
@@ -56,6 +56,8 @@ credentials.
|
||||
|
||||
## Caller patterns
|
||||
|
||||
> The `uses:` URL has to be the **absolute** form with a PAT prefix. The relative form (`Charlie/project-charlie/...`) makes act default to github.com; the unauthenticated absolute form fails because Gitea has `REQUIRE_SIGNIN_VIEW=true`. See [Gitea quirks](#gitea-quirks-leave-them-here-for-the-next-time-this-bites) below for the full story.
|
||||
|
||||
### Single-host stack, with secrets
|
||||
|
||||
```yaml
|
||||
@@ -68,23 +70,27 @@ on:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
uses: Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
uses: https://sys-gitea-runner:${{ secrets.RUNNER_REPO_PAT }}@gitea.alexandru.macocian.me/Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
with:
|
||||
host: morgott
|
||||
decrypt: |
|
||||
secrets/env.sops.yaml -> .env
|
||||
secrets: inherit
|
||||
```
|
||||
|
||||
`RUNNER_REPO_PAT` is set as a `Charlie` org-level secret (Settings -> Actions -> Secrets); every stack repo inherits it via `secrets: inherit`. PAT belongs to the LDAP-backed `sys-gitea-runner` service account with read on the `Charlie` org.
|
||||
|
||||
### Single-host stack, no secrets
|
||||
|
||||
Just drop the `decrypt:` input.
|
||||
Just drop the `decrypt:` input. `secrets: inherit` is still required so the called workflow can clone its sibling actions.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy:
|
||||
uses: Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
uses: https://sys-gitea-runner:${{ secrets.RUNNER_REPO_PAT }}@gitea.alexandru.macocian.me/Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
with:
|
||||
host: morgott
|
||||
secrets: inherit
|
||||
```
|
||||
|
||||
### Multiple secrets / non-`.env` formats
|
||||
@@ -110,11 +116,12 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
host: [morgott, melina, mohg, miquella]
|
||||
uses: Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
uses: https://sys-gitea-runner:${{ secrets.RUNNER_REPO_PAT }}@gitea.alexandru.macocian.me/Charlie/project-charlie/.gitea/workflows/deploy-stack.yml@main
|
||||
with:
|
||||
host: ${{ matrix.host }}
|
||||
decrypt: |
|
||||
secrets/${{ matrix.host }}.env.sops.yaml -> envs/${{ matrix.host }}.env
|
||||
secrets: inherit
|
||||
```
|
||||
|
||||
`deploy-stack.yml` then resolves compose files per
|
||||
@@ -140,13 +147,15 @@ with:
|
||||
|
||||
| Input | Required | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `host` | yes | — | Self-hosted runner label. The runner with `[self-hosted, <host>]` picks up the job. |
|
||||
| `host` | yes | — | Runner label. Bare label, **not** a `[self-hosted, <host>]` array — see [Gitea quirks](#gitea-quirks-leave-them-here-for-the-next-time-this-bites). |
|
||||
| `stack-path` | no | `/mnt/nas/stacks/<repo-name>` | Absolute working-tree path on the host. Must already be a `git` repo. |
|
||||
| `decrypt` | no | `""` | Multi-line `src -> dst` SOPS decrypt list. Skipped if empty. |
|
||||
| `compose-args` | no | `""` | Extra args appended to `docker compose ... up -d`. Use sparingly. |
|
||||
| `pull` | no | `true` | Run `docker compose ... pull` before `up -d`. |
|
||||
| `ref` | no | The branch the workflow ran on | Git ref to check out into the working tree. |
|
||||
|
||||
Requires the `RUNNER_REPO_PAT` secret to be in scope (set at org level; callers pass via `secrets: inherit`).
|
||||
|
||||
## Inputs reference — `sops-decrypt`
|
||||
|
||||
| Input | Required | Default | Description |
|
||||
@@ -217,6 +226,62 @@ sudo rm -f .env
|
||||
|
||||
Same as above, minus the decrypt and the `rm -f .env` lines.
|
||||
|
||||
## Gitea quirks (leave them here for the next time this bites)
|
||||
|
||||
Hard-won lessons from getting the first end-to-end pipeline working. Worth re-reading before debugging anything in this area.
|
||||
|
||||
### Cross-repo `uses:` needs absolute URL with PAT
|
||||
|
||||
The relative form `Charlie/project-charlie/...@main` makes `act` default to GitHub. The absolute form without auth fails because Gitea has `REQUIRE_SIGNIN_VIEW=true` instance-wide. So every `uses:` referencing a sibling repo has to be:
|
||||
|
||||
```
|
||||
uses: https://sys-gitea-runner:${{ secrets.RUNNER_REPO_PAT }}@gitea.alexandru.macocian.me/Charlie/<repo>/...@<ref>
|
||||
```
|
||||
|
||||
This applies **transitively** \u2014 inside `deploy-stack.yml`, the `uses:` for the `sops-decrypt` composite action also has to be absolute-URL form, otherwise act tries github.com from inside the workflow.
|
||||
|
||||
The PAT belongs to the LDAP-backed `sys-gitea-runner` service account (LDAP -> synced into Gitea via Authentik OAuth -> placed in a `runners` team in the `Charlie` org with read on all repos). PAT itself is set as a `Charlie` org-level secret so every stack repo inherits it. Callers must include `secrets: inherit` so the called workflow sees the secret.
|
||||
|
||||
References:
|
||||
- https://github.com/go-gitea/gitea/issues/25929 \u2014 the canonical issue
|
||||
- https://github.com/go-gitea/gitea/pull/36173 \u2014 the fix that landed in Gitea 1.27 (we pre-date it; the PAT-in-URL workaround is needed)
|
||||
|
||||
### `runs-on` array form matches loosely
|
||||
|
||||
A workflow with `runs-on: [self-hosted, morgott]` will sometimes get picked up by melina's runner (which advertises `self-hosted, melina`). The `[label_a, label_b]` array is supposed to mean "AND" per GitHub semantics, but Gitea's matching is loose in our version.
|
||||
|
||||
Use the bare-string form to route deterministically:
|
||||
|
||||
```yaml
|
||||
runs-on: ${{ inputs.host }}
|
||||
```
|
||||
|
||||
Every runner advertises both `self-hosted` and its host short name (see `Charlie/runners/envs/<host>.env` `GITEA_RUNNER_LABELS=self-hosted,<host>`). The bare host label is unique to one runner, so routing is unambiguous.
|
||||
|
||||
### `act` aggressively caches reusable workflows / composite actions
|
||||
|
||||
After pushing a fix to `Charlie/project-charlie`, the runner still uses the old version because act caches at `/root/.cache/act/Charlie-project-charlie@main`. The cache key is the ref string, not the commit. To force a refresh after pushing a fix:
|
||||
|
||||
```bash
|
||||
sudo docker exec runner rm -rf /root/.cache/act
|
||||
```
|
||||
|
||||
Long-term fix: stop using `@main` for cross-repo refs. Pin to specific tags (`@v1`, `@<sha>`). New ref string -> new cache entry -> automatic refresh. We've left this for later (until the contract stabilises).
|
||||
|
||||
### `safe.directory` for bind-mounted working trees
|
||||
|
||||
The runner runs as root inside the container, but `/mnt/nas/stacks/<stack>/` is owned by your user account on the host. Git refuses to operate on it ("dubious ownership"). The runner image's [`charlie-entrypoint.sh`](https://gitea.alexandru.macocian.me/amacocian/gitea-runner/src/branch/main/charlie-entrypoint.sh) sets:
|
||||
|
||||
```
|
||||
git config --global --add safe.directory '/mnt/nas/stacks/*'
|
||||
```
|
||||
|
||||
at container start. If you ever rebuild the runner image and forget this, `Sync working tree` will fail the same way every stack hit during the pilot.
|
||||
|
||||
### Workflow logs collapse
|
||||
|
||||
The Gitea Actions UI shows everything happening in `Set up job` rather than separate cards per step. Cosmetic; doesn't reflect the actual step structure. The full chronological log inside `Set up job` is what to scroll through. Suspected to be a Gitea / act_runner UI bug; not impacting correctness.
|
||||
|
||||
## Adding new reusable parts
|
||||
|
||||
If you find yourself copying logic across stack workflows, pull it in here.
|
||||
|
||||
Reference in New Issue
Block a user