CI-12 round 2: INFRA_READ_TOKEN for admin/goodwe; the pin tracks release/1.0
checks / unit (pull_request) Failing after 3s
infra-pin / fresh (pull_request) Failing after 1s

- checks.yml's infra checkout and infra-pin.yml's admin/goodwe ls-remote use
  the INFRA_READ_TOKEN secret; the self fetch keeps GITHUB_TOKEN.
- infra-pin.yml compares against admin/goodwe refs/heads/release/1.0; STALE
  message, comments and README follow.
- test_control.py / test_alloc.py: drop the claim that CI cannot reach
  admin/goodwe.
- .gitea/infra-pin is DELIBERATELY one release/1.0 merge behind (d84ac01) for
  the "infra-pin / fresh goes red" proof; the next commit sets it to HEAD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
glenn schrooyen
2026-09-25 16:08:55 +02:00
co-authored by Claude Opus 5.5
parent 6e3399322a
commit fe80047235
6 changed files with 24 additions and 24 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
# The admin/goodwe commit CI tests against. Bump: set to the full SHA of admin/goodwe master HEAD (README.md, "CI and the infra pin").
a783602ea131d49bc0c904333c1ccb101aac02d0
# The admin/goodwe commit CI tests against. Bump: set to the full SHA of admin/goodwe release/1.0 HEAD (README.md, "CI and the infra pin").
d84ac01b09c53af5de8029c1125bd4d4cfc7b3cd
+2 -1
View File
@@ -494,7 +494,8 @@ jobs:
- name: check out admin/goodwe at the pin in .gitea/infra-pin
env:
URL: ${{ github.server_url }}/admin/goodwe.git
TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Read access to admin/goodwe only; this job's own token cannot see it.
TOKEN: ${{ secrets.INFRA_READ_TOKEN }}
run: |
set -eu
PIN=$(grep -v '^#' "$WS/goodwe-addon/.gitea/infra-pin" | tr -d '[:space:]')
+10 -8
View File
@@ -1,5 +1,6 @@
# CI-12: goes red when admin/goodwe master has moved past .gitea/infra-pin, so
# the pin cannot go stale silently. Deliberately NOT a required check: it
# CI-12: goes red when admin/goodwe release/1.0 has moved past .gitea/infra-pin.
# It runs on add-on activity only; admin/goodwe's own `addon-pin` workflow
# covers a move of release/1.0 there. Deliberately NOT a required check: it
# reports; `checks / unit` stays the only gate. How to bump: README.md,
# "CI and the infra pin".
name: infra-pin
@@ -14,25 +15,26 @@ jobs:
runs-on: [self-hosted, goodwe-rig]
timeout-minutes: 30 # seconds of work; the rest is queueing for the shared slot
steps:
- name: compare .gitea/infra-pin with admin/goodwe master
- name: compare .gitea/infra-pin with admin/goodwe release/1.0
env:
SELF: ${{ github.server_url }}/${{ github.repository }}.git
INFRA: ${{ github.server_url }}/admin/goodwe.git
TOKEN: ${{ secrets.GITHUB_TOKEN }}
INFRA_TOKEN: ${{ secrets.INFRA_READ_TOKEN }} # admin/goodwe is private
run: |
set -eu
auth() { echo "$1" | sed "s#://#://x-access-token:${TOKEN}@#"; }
auth() { echo "$1" | sed "s#://#://x-access-token:${2:-$TOKEN}@#"; }
D=$(mktemp -d) && cd "$D"
git init -q . && git remote add origin "$(auth "$SELF")"
# The pin of the commit this event is about (the PR head, or the push).
git fetch -q --depth 1 origin "$GITHUB_SHA"
PIN=$(git show FETCH_HEAD:.gitea/infra-pin | grep -v '^#' | tr -d '[:space:]')
HEAD=$(git ls-remote "$(auth "$INFRA")" refs/heads/master | cut -f1)
HEAD=$(git ls-remote "$(auth "$INFRA" "$INFRA_TOKEN")" refs/heads/release/1.0 | cut -f1)
cd / && rm -rf "$D"
test -n "$HEAD" || { echo "FAIL: could not read admin/goodwe master."; exit 1; }
test -n "$HEAD" || { echo "FAIL: could not read admin/goodwe release/1.0."; exit 1; }
if [ "$PIN" != "$HEAD" ]; then
echo "STALE: .gitea/infra-pin is $PIN but admin/goodwe master is $HEAD."
echo "STALE: .gitea/infra-pin is $PIN but admin/goodwe release/1.0 is $HEAD."
echo " Test against $HEAD and bump the pin (README.md, \"CI and the infra pin\")."
exit 1
fi
echo "OK: .gitea/infra-pin $PIN is admin/goodwe master HEAD."
echo "OK: .gitea/infra-pin $PIN is admin/goodwe release/1.0 HEAD."
+2 -1
View File
@@ -108,7 +108,8 @@ on real hardware, and the comments in `control.py` say which.
### CI and the infra pin
CI (`.gitea/workflows/checks.yml`) runs every `test_*.py`, with `admin/goodwe` checked out next to this repo at the commit in `.gitea/infra-pin`, so `test_freeze.py` grades against the real `sim/hwsim.py`. If that checkout fails, the job fails. The local stub is used only in local runs, and it prints `STUB USED` when it is.
**Bump the pin** whenever `infra-pin / fresh` is red, which happens once `admin/goodwe` master has moved past the pin. Set `.gitea/infra-pin` to the new master SHA (`git ls-remote <gitea>/admin/goodwe.git refs/heads/master`) in a PR, and let `checks / unit` grade the tests against it.
The pin tracks `admin/goodwe` **release/1.0**, not master. Two non-required checks go red when release/1.0 has moved past the pin: `infra-pin / fresh` here, on any add-on PR or push to release/1.0, and `addon-pin / fresh` in `admin/goodwe`, on every push to its release/1.0.
**Bump the pin** whenever either is red. Set `.gitea/infra-pin` to the new release/1.0 SHA (`git ls-remote <gitea>/admin/goodwe.git refs/heads/release/1.0`) in a PR, and let `checks / unit` grade the tests against it. CI reads `admin/goodwe` with the Actions secret `INFRA_READ_TOKEN`.
## Compatibility
+3 -5
View File
@@ -10,12 +10,10 @@ IN FULL.
⚠️ WHAT THIS FILE CAN AND CANNOT CLAIM, SAID BEFORE THE FIRST CHECK.
The two-master rig lives in admin/goodwe (TEST-19, `sim/sitesim.py`), where
`compute()` closes the loop against `plantsim.Plant` with the firmware's own
encoder on the wire. That repository is PRIVATE and this repository's CI token
is minted for this one, so the rig is not reachable from the gate - and a test
file that needed it would either fail the gate or, like test_freeze.py's hwsim
section, pass SILENTLY having checked nothing.
encoder on the wire. CI checks admin/goodwe out at `.gitea/infra-pin` (CI-12),
but this file does not import the rig.
So the split is deliberate:
The split:
* `tools/alloc_sim.py` drives the REAL rig, and its output is quoted in the
pull request. It is where "no limit cycle" is a claim about the shipped
+5 -7
View File
@@ -990,13 +990,11 @@ check("⭐ RESTORING slew_w 1000 AT max_w 5000 IS FASTER THAN THE PLANT, and by
#
# ⚠️ THE PLANT BELOW IS MODELLED HERE AND IS NOT THE RIG. admin/goodwe's
# `plantsim.Plant` is the battery model this project grades control changes
# against, and this repository's CI cannot reach it - that repository is private
# and this job's token is minted for this one (see .gitea/workflows/checks.yml).
# So the rig evidence lives in `tools/slew_sim.py`, is quoted in the pull
# request and in DECISIONS/SAFETY-39-slew-against-the-rail.md, and what runs
# HERE is a first-order lag with the time constant that reproduces §5.10's
# measured ~18 s to the deadband. test_alloc.py makes the same split for the
# same reason and says so in the same words.
# against. CI checks admin/goodwe out at `.gitea/infra-pin` (CI-12), but this
# file does not import `plantsim`. The rig evidence lives in `tools/slew_sim.py`,
# is quoted in the pull request and in DECISIONS/SAFETY-39-slew-against-the-rail.md,
# and what runs HERE is a first-order lag with the time constant that reproduces
# §5.10's measured ~18 s to the deadband. test_alloc.py makes the same split.
#
# ⚠️ AND IT CANNOT SHOW A BATTERY ABOVE ITS RATING, WHICH IS SAID BEFORE THE
# RESULT RATHER THAN AFTER IT. Neither this model nor `plantsim.Plant` lets the