chore(ci): report gate result as ci-ok/ci-fail tags + scripts/ci-status.sh
gates / consistency-and-conventions (push) Successful in 45s

This commit is contained in:
he
2026-08-14 17:19:28 -04:00
parent 03dd92370c
commit 8026300005
4 changed files with 91 additions and 0 deletions
+18
View File
@@ -2,6 +2,7 @@ name: gates
on: on:
push: push:
branches: [main]
pull_request: pull_request:
jobs: jobs:
@@ -10,9 +11,26 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run the repo gates (gen drift, check, lint) - name: Run the repo gates (gen drift, check, lint)
id: gates
run: | run: |
set -e set -e
make gen make gen
git diff --exit-code git diff --exit-code
make check make check
make lint make lint
- name: Report gate result as a git tag (ci-ok/<sha> / ci-fail/<sha>)
if: always() && github.event_name == 'push'
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
if [ "${{ steps.gates.conclusion }}" = "success" ]; then
tag="ci-ok/$GITHUB_SHA"
else
tag="ci-fail/$GITHUB_SHA"
fi
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "tag already present: $tag"
else
git tag "$tag" "$GITHUB_SHA"
git push "http://oauth2:${GITEA_TOKEN}@gitea.skink-platy.ts.net:3000/admin/Linux_post_install.git" "refs/tags/$tag"
fi
+1
View File
@@ -122,3 +122,4 @@ summary (newest last).
- **2026-08-14** — Gitea Actions gate added: `.gitea/workflows/lint.yml` runs `make gen` + `git diff --exit-code` (gen-drift) + `make check` + `make lint` on every push/PR. Verified locally the exact four steps pass (gen idempotent, check OK, lint 0 FAIL / 0 WARN). "no CI" lines updated in AGENTS.md (Quick facts → CI bullet, notes a registered act_runner is required) and DEV.md (stub harnesses note: CI runs static gates only, not behaviour suites). Gitea 1.26.4 confirmed reachable; runner registration completed the same day (see the entry above). - **2026-08-14** — Gitea Actions gate added: `.gitea/workflows/lint.yml` runs `make gen` + `git diff --exit-code` (gen-drift) + `make check` + `make lint` on every push/PR. Verified locally the exact four steps pass (gen idempotent, check OK, lint 0 FAIL / 0 WARN). "no CI" lines updated in AGENTS.md (Quick facts → CI bullet, notes a registered act_runner is required) and DEV.md (stub harnesses note: CI runs static gates only, not behaviour suites). Gitea 1.26.4 confirmed reachable; runner registration completed the same day (see the entry above).
- **2026-08-14** — Convention-drift maintenance fix session (completed the audit backlog `MAINTENANCE.md`, M-001..M-023, all VERIFIED; gate `scripts/lint-conventions.sh` + `make lint` now 0 FAIL / 0 WARN; `make gen && make check` green). P0 bugs: M-002/003/004 added `docker-compose docker-vbox network-hotspot` to `INTERACTIVE_CMDS` (stdin/log-pipe prompt swallow); M-005 `install.sh --steps` now expands documented `N-M` ranges via `normalize_steps_spec()` (dry-run verified); M-006 feature-vs-docs decision: `--send`/`--markdown` **not restored** (health is a console-only reporter by design since fe7708f; scheduler `NOTIFY=always` covers delivery) — 5 docs corrected instead; M-007 `lib/notify.sh:57` fallback routed to stderr (stdout-leak on standalone source). P1: M-008..M-014 deps guards moved **before** `-h|--help` in docker-health/docker-ps (converted to `command -v X || err`), network-scan, share-usb-server, media-mp3/mp4 (guards before help with a `--dry-run` pre-scan preserving the documented no-deps preview); system-health documented as the sanctioned graceful-degradation no-guard pattern in DEV.md — lint refined accordingly (`first_guard_line` only matches real guards; `first_line` skips comments; precision fixes, not weakenings); M-015 system-firewall gained `usage()`+`-h|--help` (root-gated first; verified via sudo); M-016 `ffmpeg` added to preinstall PACKAGES. P2: M-017/M-018 autostart + usb-automount gained the feature-template preamble (flags.sh load, usage); M-019 `chmod +x apps/media/scrcpy.sh`; M-020 `SCALE_DIR`/`CONFIG_ENV` `:-` seams in pos-docker-compose (verified via overrides; follow-on fix: `DIM` color var missing from common.sh crashed `pos docker compose config` — added it); M-021 `CONFIG_DIR` centralized as the canonical XDG-aware seam in common.sh, per-file duplicates dropped (standalone-sourced notify.sh/config-ui.sh/matrix+telegram tools keep an identical guarded copy — "no shared lib? inline fallbacks"); M-022 `plugin_*` prefix collision resolved by renaming the internal registry helpers to `ent_plugin_*` (the documented plugin-authoring API `plugin_have`/`plugin_require`/`plugin_load_config`/`plugin_http_json` kept for user plugins); M-023 six tools (pos-config, pos-tree, pos-entertainment-{config,enable,disable,status}) now filename-referenced in DOC/POS.md. Hand-maintained AGENT_Context line-count rows bumped (install.sh 223→248, preinstall 75→76, common.sh 144→151, notify.sh 76→87 stale-corrected, autostart 14→50, usb-automount 134→138); `make lint` target wired in the Makefile. `MAINTENANCE.md` kept as the working record (uncommitted by design). - **2026-08-14** — Convention-drift maintenance fix session (completed the audit backlog `MAINTENANCE.md`, M-001..M-023, all VERIFIED; gate `scripts/lint-conventions.sh` + `make lint` now 0 FAIL / 0 WARN; `make gen && make check` green). P0 bugs: M-002/003/004 added `docker-compose docker-vbox network-hotspot` to `INTERACTIVE_CMDS` (stdin/log-pipe prompt swallow); M-005 `install.sh --steps` now expands documented `N-M` ranges via `normalize_steps_spec()` (dry-run verified); M-006 feature-vs-docs decision: `--send`/`--markdown` **not restored** (health is a console-only reporter by design since fe7708f; scheduler `NOTIFY=always` covers delivery) — 5 docs corrected instead; M-007 `lib/notify.sh:57` fallback routed to stderr (stdout-leak on standalone source). P1: M-008..M-014 deps guards moved **before** `-h|--help` in docker-health/docker-ps (converted to `command -v X || err`), network-scan, share-usb-server, media-mp3/mp4 (guards before help with a `--dry-run` pre-scan preserving the documented no-deps preview); system-health documented as the sanctioned graceful-degradation no-guard pattern in DEV.md — lint refined accordingly (`first_guard_line` only matches real guards; `first_line` skips comments; precision fixes, not weakenings); M-015 system-firewall gained `usage()`+`-h|--help` (root-gated first; verified via sudo); M-016 `ffmpeg` added to preinstall PACKAGES. P2: M-017/M-018 autostart + usb-automount gained the feature-template preamble (flags.sh load, usage); M-019 `chmod +x apps/media/scrcpy.sh`; M-020 `SCALE_DIR`/`CONFIG_ENV` `:-` seams in pos-docker-compose (verified via overrides; follow-on fix: `DIM` color var missing from common.sh crashed `pos docker compose config` — added it); M-021 `CONFIG_DIR` centralized as the canonical XDG-aware seam in common.sh, per-file duplicates dropped (standalone-sourced notify.sh/config-ui.sh/matrix+telegram tools keep an identical guarded copy — "no shared lib? inline fallbacks"); M-022 `plugin_*` prefix collision resolved by renaming the internal registry helpers to `ent_plugin_*` (the documented plugin-authoring API `plugin_have`/`plugin_require`/`plugin_load_config`/`plugin_http_json` kept for user plugins); M-023 six tools (pos-config, pos-tree, pos-entertainment-{config,enable,disable,status}) now filename-referenced in DOC/POS.md. Hand-maintained AGENT_Context line-count rows bumped (install.sh 223→248, preinstall 75→76, common.sh 144→151, notify.sh 76→87 stale-corrected, autostart 14→50, usb-automount 134→138); `make lint` target wired in the Makefile. `MAINTENANCE.md` kept as the working record (uncommitted by design).
- **2026-08-14** — `pos system backup` optional encryption (`--no-encrypt` flag + `BACKUP_ENCRYPT=0` env, flag-or-env — user chose "Flag + env only"): plain path keeps a verified `.tar.gz` with no password prompt (headless/cron safe); encrypt path unchanged (prompt → gpg AES-256 → decrypt-verify; the gpg dep-guard moved into the encrypt branch so plain backups no longer require `gnupg`). Arg parsing rewritten as a loop over `"$@"` so `pos system backup <folder> --no-encrypt` works with the flag after the folder; usage() documents all three forms + the plain artifact name; `# POS_FLAGS: --service --no-encrypt`; `config/system.env` template gains `#BACKUP_ENCRYPT=0`; POS.md row + howto/system.md section updated. Verified: stub suite +2 cases (T18 flag / T19 env: plain .tar.gz artifact, gpg never called via `$GPG_CALLED`, USB copy + sha256 of the plain archive, notify wording) — 65/65 green; `bash -n`, `make gen && make check`, `make lint` 0 FAIL / 0 WARN. - **2026-08-14** — `pos system backup` optional encryption (`--no-encrypt` flag + `BACKUP_ENCRYPT=0` env, flag-or-env — user chose "Flag + env only"): plain path keeps a verified `.tar.gz` with no password prompt (headless/cron safe); encrypt path unchanged (prompt → gpg AES-256 → decrypt-verify; the gpg dep-guard moved into the encrypt branch so plain backups no longer require `gnupg`). Arg parsing rewritten as a loop over `"$@"` so `pos system backup <folder> --no-encrypt` works with the flag after the folder; usage() documents all three forms + the plain artifact name; `# POS_FLAGS: --service --no-encrypt`; `config/system.env` template gains `#BACKUP_ENCRYPT=0`; POS.md row + howto/system.md section updated. Verified: stub suite +2 cases (T18 flag / T19 env: plain .tar.gz artifact, gpg never called via `$GPG_CALLED`, USB copy + sha256 of the plain archive, notify wording) — 65/65 green; `bash -n`, `make gen && make check`, `make lint` 0 FAIL / 0 WARN.
- **2026-08-14** — CI green-check via plain git (no SSH to the runner, no API tokens — user chose "CI tags + git ls-remote" + "scripts/ci-status.sh helper"): `.gitea/workflows/lint.yml` scoped to `on: push: branches: [main]` (tag pushes no longer re-trigger it) and the gate step now reports its own outcome as a lightweight tag — `ci-ok/$GITHUB_SHA` on success / `ci-fail/$GITHUB_SHA` on failure, pushed over HTTP with the jobs automatic `GITEA_TOKEN` to `http://oauth2:${GITEA_TOKEN}@gitea.skink-platy.ts.net:3000/admin/Linux_post_install.git` (runner container already host-maps that hostname to 100.111.241.54); `steps.gates.conclusion` decides ok/fail, `if: always()` (guarded to `push` events) covers failed gate runs, and an existing-tag guard makes re-runs idempotent. New executable `scripts/ci-status.sh [--wait] [<sha>]` reads the tags via `git ls-remote` (origin, `CI_STATUS_REMOTE` override): GREEN (0) / RED (1) / PENDING (2); `--wait` polls every 10s up to 10 min. DEV.md §CI gains a "Checking green without SSH" bullet. Verified: `bash -n`, yaml-parse OK, `make gen && make check`, `make lint` 0 FAIL / 0 WARN; first live-tag verification pending the push (fallback if Gitea clamps token-push: PAT as workflow secret).
+7
View File
@@ -394,6 +394,13 @@ Actions.
like `pos-config` start with `|`, which collated after letters under that like `pos-config` start with `|`, which collated after letters under that
locale, reordering the generated tables). `scripts/gen-docs.sh` sets locale, reordering the generated tables). `scripts/gen-docs.sh` sets
`export LC_ALL=C`; keep that in mind for any new generator. `export LC_ALL=C`; keep that in mind for any new generator.
- **Checking green without SSH** — the workflow reports its own outcome as a
lightweight git tag: `ci-ok/<sha>` on success, `ci-fail/<sha>` on failure
(pushed with the job's automatic `GITEA_TOKEN`; the workflow only triggers on
`push` to `main`, so tag pushes don't re-trigger it). Check from the dev box
with plain git — `scripts/ci-status.sh [--wait] [<sha>]` (reads the tags via
`git ls-remote`, exit 0/1/2 = green/red/pending). No SSH to the runner, no API
tokens.
- **Limits** — CI proves the *static* gates only; it never runs behaviour suites - **Limits** — CI proves the *static* gates only; it never runs behaviour suites
(stub harnesses stay throwaway in `/tmp`). (stub harnesses stay throwaway in `/tmp`).
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env bash
# Report whether the `gates` workflow has finished for a commit, using only
# git against the remote (no SSH to the runner box, no API tokens).
#
# `.gitea/workflows/lint.yml` pushes a lightweight tag `ci-ok/<sha>` when the
# gates pass and `ci-fail/<sha>` when they fail. This script reads those tags
# with `git ls-remote`.
#
# Usage:
# scripts/ci-status.sh [<sha>] # one-shot check (default: current HEAD)
# scripts/ci-status.sh --wait [<sha>] # poll until done (max 10 min)
#
# Exit codes: 0 = green, 1 = red, 2 = still running / not reported.
set -euo pipefail
REMOTE="${CI_STATUS_REMOTE:-origin}"
INTERVAL=10
TIMEOUT=600
sha="${1:-}"
if [ "$sha" = "--wait" ]; then
wait=1
sha="${2:-}"
fi
[ -n "$sha" ] || sha="$(git rev-parse HEAD)"
check() {
local ok="" fail=""
ok="$(git ls-remote "$REMOTE" "refs/tags/ci-ok/$sha" | awk '{print $1}')"
fail="$(git ls-remote "$REMOTE" "refs/tags/ci-fail/$sha" | awk '{print $1}')"
if [ -n "$ok" ]; then
echo "GREEN — gates passed for $sha ($ok)"
return 0
fi
if [ -n "$fail" ]; then
echo "RED — gates failed for $sha ($fail)"
return 1
fi
echo "PENDING — no gate result yet for $sha"
return 2
}
if [ "${wait:-0}" -ne 1 ]; then
if check; then
exit 0
else
rc=$?
exit "$rc"
fi
fi
deadline=$((SECONDS + TIMEOUT))
while :; do
out="$(check 2>&1)" && { echo "$out"; exit 0; }
rc=$?
if [ "$rc" -eq 1 ]; then
echo "$out"
exit 1
fi
if (( SECONDS >= deadline )); then
echo "TIMEOUT after ${TIMEOUT}s — no gate result for $sha"
exit 2
fi
sleep "$INTERVAL"
done