Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 3 additions & 59 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,9 @@
# needed. A value already exported in your shell wins over anything here — the
# file supplies defaults, it does not override an intentional choice.
#
# Everything below is optional *here*. Without it the suite runs in full and the
# checks that need a sibling checkout skip themselves rather than fail. They are the
# *provenance* half of the schema_1 conformance suite: they verify that the vendored
# copies still match their sources. The conformance and coverage checks, which are
# the ones that catch real defects, run regardless.
#
# CI is not optional: it clones both peers at the commits spec_lock.json pins, and
# those checks fail rather than skip when `CI` is set. A skip reads in a summary line
# exactly like a pass, and that is how a stale vendored capture went unnoticed for
# nine days. See DEVELOPMENT.md, "A skip here is not a pass".
#
# These answer one question of two. A sibling checkout answers "do our bytes still
# match the pin?" -- a byte comparison against a producer sitting where spec_lock.json
# says it sits. It cannot answer "has the producer moved past the pin?", because what
# is on your disk knows nothing about what has been pushed or released since.
# `scripts/peer_drift.py` asks that one, over the network and needing no checkout at
# all, and the pre-commit hook runs it on every local commit -- so a producer release
# is noticed on the commit that should have moved the pin, rather than by a scheduled
# job the next morning. CI skips that hook deliberately: a producer's push must not
# fail somebody's pull request. Nothing below configures the check either way -- it
# reads every pin, path and repository out of spec_lock.json.

# A checkout of the eBus specification.
#
# git clone https://github.com/electrification-bus/specification
#
# Enables the byte comparison of `packages/schema-1/spec/catalogs/*.json` against
# the specification's `capabilities/`. Position the checkout at the commit
# `spec_lock.json` pins (`synced_commit`) before believing a failure — a checkout
# on a newer HEAD reports differences that are drift, not corruption.
#EBUS_SPEC_DIR=/path/to/specification

# A checkout of SpanPanel/panelbench, the publisher this parser is developed
# against.
#
# git clone git@github.com:SpanPanel/panelbench.git
#
# Enables verifying the two vendored captures and the recorded peer pins against
# the producer itself. The tree capture is compared byte for byte; the wire
# capture is compared on shape, because its values are perturbed by the
# simulator's `noise_factor` and an advancing clock.
#PANELBENCH_DIR=/path/to/panelbench

# A checkout of the eBus emitter, the producer of the reference tree.
#
# git clone https://github.com/electrification-bus/distribution-enclosure-simulator
#
# The specification's own executable publisher — same organisation, conformed
# against live panel output — so this is the spec in runnable form rather than a
# third-party imitation of it. Position it at the tag `peers.ebus-panel-sim.tag`
# records before believing a failure.
#
# Enables checking that the emitter reads the same specification commit we do,
# and that the checkout is the release `spec_lock.json` says the reference tree
# was captured from. It is also what `scripts/capture_parent_child_reference.py`
# needs to regenerate that capture (the script takes PANEL_SIM_DIR too, and must
# be run from the emitter's own environment — it caps `ebus-sdk` below the
# version this repo installs).
#PANEL_SIM_DIR=/path/to/distribution-enclosure-simulator
# Nothing in the test suite needs this file except the live-panel differential
# below. `uv sync --all-packages` is the whole setup: the schema_1 provenance
# checks compare against the installed `ebus-panel-sim` wheel, and nothing skips.

# ---------------------------------------------------------------------------
# A live SPAN panel running flat firmware (optional, and nothing needs it)
Expand Down
125 changes: 0 additions & 125 deletions .github/actions/peer-checkouts/action.yml

This file was deleted.

10 changes: 9 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ updates:
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 1
# Raised from 1 for `ebus-panel-sim`. It is the producer of the schema_1
# reference capture, so its bump is a wire question and not a tooling one: the
# PR has to re-run scripts/capture_parent_child_reference.py, and the suite is
# what answers whether the wire moved. A limit of 1 let a pytest bump take the
# only slot and hold that question back for a week.
open-pull-requests-limit: 5
allow:
- dependency-type: "all"
# `ebus-panel-sim` is deliberately in none of these groups, and must stay that
# way. A grouped bump arrives as one commit with one review, and a wire change
# buried in a pytest bump is a wire change nobody read.
groups:
# Group development dependencies together
dev-dependencies:
Expand Down
61 changes: 24 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,6 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

# The schema_1 provenance checks compare vendored bytes against the two
# repositories they were copied from, and skip when neither is reachable. They
# skipped in every run this workflow has ever done, which reads in the summary
# line exactly like passing -- see DEVELOPMENT.md, "A skip here is not a pass".
# Cloning both at the commits spec_lock.json pins turns them into a question with
# a deterministic answer: do our vendored bytes match the commit we say they came
# from? Whether the *producer* has moved past that pin is a different question
# with a moving answer, and it lives in peer-drift.yml so it cannot fail a pull
# request for something the author did not do.
#
# CI is set by the runner, and tests/test_schema_one_conformance.py fails rather
# than skips when it is -- so removing this step breaks the build instead of
# quietly switching the checks back off.
- name: Check out the peers the provenance checks verify against
uses: ./.github/actions/peer-checkouts

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
Expand All @@ -58,12 +42,10 @@ jobs:
- name: Install dependencies
run: uv sync --all-packages

# SKIP because `peer-drift` asks whether a *producer* has moved, and that answer
# changes because somebody else pushed — peer-drift.yml is where it is asked, on
# a schedule, so no pull request fails for a push its author did not make.
# The schema_1 provenance checks compare the vendored catalogs against
# `ebus-panel-sim`'s own copies. `uv sync` above is all they need: the emitter is
# a pinned dev dependency, so there is nothing to clone and nothing that can skip.
- name: Run pre-commit hooks
env:
SKIP: peer-drift
run: |
uv run pre-commit run --all-files

Expand Down Expand Up @@ -150,29 +132,34 @@ jobs:
print(f'{wheel}: py.typed present')
"

# Reference captures are test data. They shipped in both wheels until 3.1.0
# -- not through any packaging declaration, but because a directory inside a
# package directory ships -- and no runtime path ever read them. Nothing in
# the manifests would object to that happening again, so the built artifact
# is where it has to be asserted. Every wheel, not the two known ones: an
# adapter added under packages/ is covered the day it exists.
- name: Verify no wheel ships reference payloads
# Each adapter ships the reference capture its consumers test against, so a
# downstream suite reads the bytes its pinned version was built against rather
# than vendoring a copy. Nothing in the manifests declares that -- hatchling
# ships a directory inside a package directory either way -- so the built
# artifact is where it has to be asserted.
- name: Verify each adapter wheel ships its reference capture
run: |
python -c "
import glob, posixpath, sys, zipfile
import glob, sys, zipfile
expected = {
'span_panel_api_schema_0': 'span_panel_api_schema_0/reference/homie_schema.json',
'span_panel_api_schema_1': 'span_panel_api_schema_1/reference/parent_child_tree.json',
}
wheels = glob.glob('dist/*.whl')
if not wheels:
sys.exit('::error::no wheels were built')
seen = set()
for wheel in wheels:
names = zipfile.ZipFile(wheel).namelist()
carried = [
n for n in names
if 'reference_payloads' in n.split('/')
or posixpath.basename(n) in ('homie_schema.json', 'parent_child_tree.json')
]
if carried:
sys.exit(f'::error::{wheel} ships test data: {carried}. Reference captures are fixtures under tests/reference_payloads; a directory inside a package directory ships whether or not the manifest names it.')
print(f'{wheel}: no reference payloads')
for package, path in expected.items():
if any(n.startswith(package + '/') for n in names):
seen.add(package)
if path not in names:
sys.exit(f'::error::{wheel} ships {package} without {path}; downstream test suites read that file out of this wheel')
print(f'{wheel}: {path} present')
missing = sorted(set(expected) - seen)
if missing:
sys.exit(f'::error::no wheel was built for {missing}')
"

# The configuration entry-point discovery exists to support, and the one
Expand Down
Loading
Loading