tenseleyflow/shithub / de4f850

Browse files

docs/actions: add operator smoke guide

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
de4f8503e7d06aba3a85000130c5bf78535b8738
Parents
44f779f
Tree
3127fae

6 changed files

StatusFile+-
M bench/fixtures/README.md 8 0
A bench/fixtures/actions/smoke-run-only.yml 10 0
M docs/internal/actions-schema.md 12 6
M docs/internal/runbooks/actions.md 130 0
M docs/public/SUMMARY.md 1 0
A docs/public/user/actions.md 92 0
bench/fixtures/README.mdmodified
@@ -38,3 +38,11 @@ fixtures used by `make bench-small`. That's enough to catch
3838
 regressions in the harness itself plus the small-scale handler
3939
 latency floor; the big-fixture targets in S36's "Definition of
4040
 done" land with the generators above.
41
+
42
+## Actions smoke fixture
43
+
44
+`actions/smoke-run-only.yml` is the canonical first end-to-end Actions
45
+workflow fixture. Copy it into `.shithub/workflows/smoke.yml` in a
46
+repository with a registered `ubuntu-latest` runner. It intentionally uses only
47
+`run:` steps because the current executor rejects reserved `uses:` aliases
48
+until checkout and artifact execution are implemented.
bench/fixtures/actions/smoke-run-only.ymladded
@@ -0,0 +1,10 @@
1
+name: smoke
2
+on: [push, workflow_dispatch]
3
+jobs:
4
+  hello:
5
+    runs-on: ubuntu-latest
6
+    env:
7
+      RUN_ID: ${{ shithub.run_id }}
8
+    steps:
9
+      - run: echo "hello from shithub actions"
10
+      - run: test -n "$RUN_ID"
docs/internal/actions-schema.mdmodified
@@ -130,19 +130,25 @@ v1 supports four triggers — anything else is a parse error.
130130
 
131131
 ### `uses:` allowlist
132132
 
133
-Exactly three aliases, no exceptions:
133
+Exactly three aliases are reserved at parse time, no exceptions:
134134
 
135
-| Alias                            | What it does                              |
136
-| -------------------------------- | ----------------------------------------- |
137
-| `actions/checkout@v4`            | Clones the repo into the workspace        |
138
-| `shithub/upload-artifact@v1`     | Uploads files to `workflow_artifacts`     |
139
-| `shithub/download-artifact@v1`   | Pulls artifacts back in a downstream job  |
135
+| Alias                            | Parser status | Runner status                              |
136
+| -------------------------------- | ------------- | ------------------------------------------ |
137
+| `actions/checkout@v4`            | accepted      | rejected until checkout support lands      |
138
+| `shithub/upload-artifact@v1`     | accepted      | rejected until artifact upload lands       |
139
+| `shithub/download-artifact@v1`   | accepted      | rejected until artifact download lands     |
140140
 
141141
 Any other `uses:` value (community actions, Docker images, composite
142142
 actions) is an Error-severity diagnostic. The marketplace problem is
143143
 explicitly out of scope for v1; revisit only if a real demand exists
144144
 and we have an answer for supply-chain trust.
145145
 
146
+The current Docker executor runs `run:` steps only. It fails a reserved
147
+`uses:` alias deliberately instead of pretending checkout/artifact
148
+semantics exist. This keeps the first end-to-end smoke path honest:
149
+`run:`-only workflows are executable now, while repository checkout and
150
+artifact transfer remain explicit follow-up work.
151
+
146152
 ### File-size + parser caps
147153
 
148154
 - **64 KB** workflow file size cap (`workflow.MaxWorkflowFileBytes`).
docs/internal/runbooks/actions.mdmodified
@@ -1,5 +1,72 @@
11
 # Actions runbook
22
 
3
+This is the operator runbook for shithub Actions. Host provisioning lives in
4
+[runner-deploy.md](./runner-deploy.md), and runner protocol details live in
5
+[actions-runner-api.md](../actions-runner-api.md).
6
+
7
+## Shape
8
+
9
+```text
10
+git push / workflow_dispatch / schedule / pull_request
11
+        |
12
+        v
13
+workflow:trigger worker job
14
+        |
15
+        v
16
+workflow_runs + workflow_jobs + workflow_steps + check_runs
17
+        |
18
+        v
19
+registered runner heartbeat claims a matching queued job
20
+        |
21
+        v
22
+containerized run: steps -> log chunks -> step/job status -> run rollup
23
+```
24
+
25
+The v1 executor supports containerized `run:` steps. The parser reserves
26
+`actions/checkout@v4`, `shithub/upload-artifact@v1`, and
27
+`shithub/download-artifact@v1`, but the Docker runner rejects `uses:` steps
28
+until checkout metadata and artifact transfer are wired end to end. Do not use
29
+`actions/checkout@v4` in production smoke workflows yet.
30
+
31
+## First smoke
32
+
33
+1. Confirm migrations are applied and the web process can enqueue workers.
34
+2. Register one runner with a label that matches the workflow:
35
+
36
+```sh
37
+shithubd admin runner register \
38
+  --name smoke-runner-1 \
39
+  --labels self-hosted,linux,ubuntu-latest \
40
+  --capacity 1
41
+```
42
+
43
+3. Start `shithubd-runner` with the printed token. For production hosts, use
44
+   the Ansible/systemd path in [runner-deploy.md](./runner-deploy.md).
45
+4. Push a `run:`-only workflow:
46
+
47
+```yaml
48
+name: smoke
49
+on: [push, workflow_dispatch]
50
+jobs:
51
+  hello:
52
+    runs-on: ubuntu-latest
53
+    env:
54
+      RUN_ID: ${{ shithub.run_id }}
55
+    steps:
56
+      - run: echo "hello from shithub actions"
57
+      - run: test -n "$RUN_ID"
58
+```
59
+
60
+5. Expected result:
61
+
62
+- `workflow:trigger` enqueues a workflow run.
63
+- A runner heartbeat claims the queued job within one idle poll interval.
64
+- The Actions run page streams step logs while the job is running.
65
+- The matching check run completes with `success`.
66
+- `/{owner}/{repo}/actions.atom` includes the completed run.
67
+
68
+Repeat with `exit 1`; the check should complete with `failure`.
69
+
370
 ## Live log tail
471
 
572
 Step log pages open an SSE stream at:
@@ -44,3 +111,66 @@ contains that route and reload Caddy:
44111
 ```sh
45112
 sudo caddy reload --config /etc/caddy/Caddyfile
46113
 ```
114
+
115
+## Runner health
116
+
117
+On the runner host:
118
+
119
+```sh
120
+systemctl status shithubd-runner
121
+journalctl -u shithubd-runner -n 100 --no-pager
122
+```
123
+
124
+On the app host, inspect runner registration and heartbeat state:
125
+
126
+```sh
127
+shithubd admin actions runner list
128
+```
129
+
130
+Important metrics:
131
+
132
+- `shithub_actions_runner_heartbeats_total{result="claimed|no_job"}`
133
+- `shithub_actions_runner_jwt_total{result="issued|rejected|replay"}`
134
+- `shithub_actions_jobs_cancelled_total{reason="user|concurrency|timeout"}`
135
+- `shithub_actions_log_scrub_replacements_total{location="server"}`
136
+- `shithub_actions_step_timeouts_total`
137
+
138
+## Emergency cancel
139
+
140
+Start with a dry run:
141
+
142
+```sh
143
+shithubd admin actions cancel-all --dry-run --limit 100
144
+```
145
+
146
+Scope to one repository when possible:
147
+
148
+```sh
149
+shithubd admin actions cancel-all --dry-run --repo-id 42
150
+```
151
+
152
+Then confirm:
153
+
154
+```sh
155
+shithubd admin actions cancel-all --confirm --repo-id 42
156
+```
157
+
158
+Queued jobs are marked cancelled immediately. Running jobs receive
159
+`cancel_requested=true`; the runner sees that through `/cancel-check`, kills the
160
+active container, and reports terminal `cancelled`.
161
+
162
+## Common failures
163
+
164
+- **Run never appears:** confirm the workflow file is under
165
+  `.shithub/workflows/`, parse it with `shithubd admin actions parse <file>`,
166
+  and verify the trigger event matches `on:`.
167
+- **Run stays queued:** confirm a runner is registered with matching labels and
168
+  capacity, then inspect runner journal output and heartbeat metrics.
169
+- **Step logs buffer:** verify the Caddy route above and confirm the SSE route
170
+  is still mounted outside compression and short timeouts.
171
+- **`uses:` step fails:** expected for now. Replace with a `run:` step until
172
+  checkout/artifact support lands.
173
+- **Secrets appear masked inconsistently:** check
174
+  `shithub_actions_log_scrub_replacements_total{location="server"}` and confirm
175
+  the job was claimed after the secret was created or rotated. Mask snapshots
176
+  are captured at claim time.
docs/public/SUMMARY.mdmodified
@@ -13,6 +13,7 @@
1313
 - [Issues](./user/issues.md)
1414
 - [Pull requests](./user/pull-requests.md)
1515
   - [Branch protection & reviews](./user/branch-protection.md)
16
+- [Actions](./user/actions.md)
1617
 - [Notifications](./user/notifications.md)
1718
 - [Webhooks](./user/webhooks.md)
1819
 - [Search](./user/search.md)
docs/public/user/actions.mdadded
@@ -0,0 +1,92 @@
1
+# Actions
2
+
3
+shithub Actions runs CI workflows from `.shithub/workflows/*.yml`.
4
+The workflow format intentionally follows the parts of GitHub Actions that are
5
+useful for ordinary repository CI, while keeping the runner surface small enough
6
+to secure.
7
+
8
+## Minimal workflow
9
+
10
+```yaml
11
+name: smoke
12
+on: [push, workflow_dispatch]
13
+jobs:
14
+  hello:
15
+    runs-on: ubuntu-latest
16
+    env:
17
+      RUN_ID: ${{ shithub.run_id }}
18
+    steps:
19
+      - run: echo "hello from shithub actions"
20
+      - run: test -n "$RUN_ID"
21
+```
22
+
23
+Commit that file as `.shithub/workflows/smoke.yml` and push to the repository.
24
+The run appears under the repository's Actions tab and its job also appears as
25
+a check run on matching pull requests.
26
+
27
+## What works today
28
+
29
+- `push`, `pull_request`, `schedule`, and `workflow_dispatch` triggers
30
+- `run:` steps executed in the operator-configured runner image
31
+- `runs-on:` label matching against registered runners
32
+- workflow, job, and step `env:`
33
+- `${{ secrets.NAME }}`, `${{ vars.NAME }}`, `${{ env.NAME }}`, and
34
+  `${{ shithub.* }}` expressions
35
+- `needs:`, `if:`, `timeout-minutes:`, and concurrency groups
36
+- live step logs, cancel, re-run, check-run sync, and the Actions Atom feed
37
+
38
+`runs-on: ubuntu-latest` is a runner label, not a promise that shithub downloads
39
+a hosted Ubuntu image for you. The site operator decides which image a matching
40
+runner uses. On shithub.sh, use the labels published by the instance operator.
41
+
42
+## Current limit
43
+
44
+Use `run:` steps for now. The parser accepts these reserved aliases:
45
+
46
+- `actions/checkout@v4`
47
+- `shithub/upload-artifact@v1`
48
+- `shithub/download-artifact@v1`
49
+
50
+The runner does not execute them yet. A workflow containing those `uses:` steps
51
+will fail until checkout and artifact execution land. If you need repository
52
+files in a smoke workflow today, keep the command self-contained or fetch what
53
+you need explicitly inside a `run:` step.
54
+
55
+## Expressions
56
+
57
+Use the shithub namespace:
58
+
59
+```yaml
60
+env:
61
+  REF: ${{ shithub.ref }}
62
+  SHA: ${{ shithub.sha }}
63
+  RUN_ID: ${{ shithub.run_id }}
64
+```
65
+
66
+The `github.*` namespace is accepted as a compatibility alias for the fields
67
+shithub exposes, but new workflows should use `shithub.*`.
68
+
69
+Event payload values such as `${{ shithub.event.pull_request.title }}` are
70
+treated as untrusted. The runner passes them through temporary environment
71
+bindings instead of splicing them directly into shell command text.
72
+
73
+## Secrets and variables
74
+
75
+Repository and organization settings expose Actions secrets and variables.
76
+Secrets are encrypted at rest and are redacted from logs. Variables are
77
+plaintext configuration and are suitable for non-secret values such as tool
78
+versions or feature flags.
79
+
80
+Repo-scoped values shadow organization-scoped values with the same name.
81
+
82
+## Migrating from GitHub Actions
83
+
84
+Most simple CI files need three edits:
85
+
86
+1. Move the workflow file from `.github/workflows/` to `.shithub/workflows/`.
87
+2. Replace `uses:` actions with equivalent `run:` commands.
88
+3. Confirm `runs-on:` matches a label registered by your shithub operator.
89
+
90
+Marketplace actions, Docker actions, composite actions, hosted runner images,
91
+matrix expansion, service containers, and built-in checkout are not part of the
92
+current v1 runner.