Skip to content

MIP sync: lockfile owns the source repo; share pydevices descriptions - #37

Merged
bdbarnett merged 4 commits into
mainfrom
branch/mip-sync-lockfile-descriptions-c94d
Sep 6, 2026
Merged

MIP sync: lockfile owns the source repo; share pydevices descriptions#37
bdbarnett merged 4 commits into
mainfrom
branch/mip-sync-lockfile-descriptions-c94d

Conversation

@bdbarnett

@bdbarnett bdbarnett commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #35 and #36 in PyDevices/.github only.

#35. synchronize_mip_package.py no longer keeps a second PROFILE_REPOSITORIES map. The expected GitHub repository for a MIP profile comes from pydevices-lock.json.

The lockfile is the single owner of profile → repository, enforced where the overwrite used to happen. reusable-synchronize-mip-package.yml's "Record this release in the lockfile" step now:

  • fails if lock[profile]["repository"] differs from SOURCE_REPOSITORY, naming both values and telling the maintainer to edit pydevices-lock.json on the PyDevices branch to move the profile (as f94ef5e9 did for the audioif/audiocomponents split);
  • otherwise updates ref only and leaves repository untouched.

lockfile_repository() in the script stays as defence in depth. The script-level mismatch test is named and documented as testing the script in isolation; the workflow never presents that case to the script.

A profile the lockfile does not name is still rejected, not auto-created.

This Record-step change is a reusable-workflow contract change. It rides the same publishing-v9 rollout already listed in follow-ups.

#36. pydevices and pydevices-desktop MIP manifests used placeholder descriptions ("PyDevices pydevices"). Both the MIP renderer and the TestPyPI builder now read PYDEVICES_DESCRIPTIONS from scripts/pydevices_package_metadata.py, so the index and TestPyPI cannot drift.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing code/behavior to change)
  • Documentation / Refactoring update

Follow-ups (not in this PR)

These rollout steps from #35 are maintainer-owned and are not done here:

  1. Cut publishing-v9 carrying this change (including the Record-step contract).
  2. Repoint PyDevices/mip's process-mip-publication-request.yml pin from a SHA / publishing-v6 to publishing-v9.
  3. Re-run the two audiocomponents publications.

This PR does not create or move any publishing-v* tag, does not edit any workflow publish or dispatch inputs, and does not edit VERSION files.

Verification & Testing

  • Verified on hardware / simulator (specify board/target interpreter)
  • All unit tests pass cleanly (pytest / local test runner)

cwd: /workspace (this repository). Python 3.12.3.

Record-step unit tests

The Record step's Python is an inline heredoc. Tests extract that heredoc from reusable-synchronize-mip-package.yml and run it against a fixture lockfile, so they exercise the step in isolation rather than a copy of the logic.

After fdc843b:

$ python3 -m unittest discover -s tests -v
test_audiocomponents_dispatch_matches_lockfile ... ok
test_audioeffects_dispatch_matches_lockfile ... ok
test_lockfile_repository_reads_named_entry ... ok
test_missing_lockfile_fails ... ok
test_no_hardcoded_profile_repositories_map ... ok
test_profile_missing_from_lockfile_fails ... ok
test_script_in_isolation_rejects_source_repository_name_that_disagrees_with_lockfile ... ok
test_matching_repository_updates_ref_only ... ok
test_mismatched_repository_fails_without_writing ... ok
test_builder_uses_the_same_descriptions ... ok
test_pydevices_desktop_manifest_uses_shared_description ... ok
test_pydevices_manifest_uses_shared_description ... ok
test_pydevices_profile_writes_shared_descriptions ... ok

Ran 13 tests in 0.245s
OK

Exit code 0.

$ ruff check scripts/ tests/
All checks passed!

Exit code 0.

Earlier prove commands (still valid)

publishing-v8 script vs PyDevices/audiocomponents still exits 1 with profile 'audioinstruments' requires PyDevices/audioif, not PyDevices/audiocomponents. The same dispatch against this branch with a fixture lockfile naming audiocomponents exits 0.

GitHub Checks on fdc843b (run 34066689727)

Passed: unittest, ruff, actionlint, yaml-parse-reusables.

Failed: generator-idempotency. Pre-existing on main since e75671b (run 33878372841). Not a condition for this merge; filed separately on PyDevices/pydevices.

Could not run

  • Did not cut publishing-v9, move any publishing tag, or edit VERSION.
  • Did not edit any workflow publish/dispatch inputs.
  • Did not change PyDevices/mip or re-run the two publications.
  • Did not regenerate sibling sites to clear the pre-existing generator-idempotency failure.
  • No hardware/simulator verification (not a product runtime change).
Open in Web Open in Cursor 

cursoragent and others added 3 commits September 6, 2026 23:01
…file

PROFILE_REPOSITORIES was a second source of truth frozen in the publishing-tools
tag, so a lockfile retarget of audioinstruments and audioeffects to
audiocomponents failed every publication (#35). The expected repository now
comes from pydevices-lock.json in the MIP checkout, matching the record-and-
resync loop. A profile the lockfile does not name is rejected, not created.

Co-authored-by: Brad Barnett <bdbarnett@users.noreply.github.com>
The pydevices MIP profile wrote placeholder descriptions ("PyDevices pydevices")
while the TestPyPI builder already had the real summaries (#36). Both now read
PYDEVICES_DESCRIPTIONS from one module so the index and TestPyPI cannot drift.

Co-authored-by: Brad Barnett <bdbarnett@users.noreply.github.com>
ruff EXE001 flags a shebang on a non-executable test module. unittest discover
does not need it.

Co-authored-by: Brad Barnett <bdbarnett@users.noreply.github.com>
@bdbarnett
bdbarnett marked this pull request as ready for review September 6, 2026 23:04
@bdbarnett

Copy link
Copy Markdown
Contributor Author

Review, 2026-09-06. The #36 half and the tests are good; the unittest job in checks.yml is a welcome addition. One change is needed before this merges, and it is in this repository.

The lockfile check cannot fail where it runs

reusable-synchronize-mip-package.yml runs "Record this release in the lockfile" before "Synchronize every locked source", and that step overwrites the dispatched profile's entry from the caller's own inputs:

lock[profile] = {
    "repository": os.environ["SOURCE_REPOSITORY"],
    "ref": os.environ["SOURCE_REF"],
}

The sync loop then reads the lockfile back and passes each entry's own repository as --source-repository-name. So in the workflow, lockfile_repository(mip_root, profile) and args.source_repository_name always come from the same line of the same file, and test_stale_audioif_caller_is_rejected_when_lockfile_names_audiocomponents describes a situation the workflow can never present to the script. The old PROFILE_REPOSITORIES map was clumsy, but it was the one guard independent of the caller; this PR removes it and puts nothing in its place. Any repository that can dispatch a known profile name now republishes that profile as itself.

The fix, in the same PR

Make the lockfile the single owner of profile → repository, enforced where the overwrite happens. In the "Record this release" step: if lock[profile]["repository"] differs from SOURCE_REPOSITORY, fail with a message naming both and telling the human to edit pydevices-lock.json on the PyDevices branch to move the profile (that is exactly what f94ef5e9 did for the split); otherwise update ref only. The script's lockfile_repository() check can stay as defence in depth, but the test that claims to prove rejection should become a workflow-level statement, or be renamed to say it tests the script in isolation.

That is a reusable-workflow contract change, so it rides the same publishing-v9 the follow-ups already name.

The failing check is not this PR's

generator-idempotency has been red on main since e75671b (four consecutive Checks runs on 2026-09-04): the generator wants to regenerate PyDevices/pydevices docs/ecosystem.md with the audiocomponents, usbif and cameraif rows. Filed separately on PyDevices/pydevices; not a condition for this merge.

The lockfile owns profile to repository. Record this release now fails if
SOURCE_REPOSITORY differs from the locked repository, naming both and telling
the maintainer to edit pydevices-lock.json on the PyDevices branch; otherwise
it updates ref only. The script check remains defence in depth.

Co-authored-by: Brad Barnett <bdbarnett@users.noreply.github.com>
@bdbarnett

Copy link
Copy Markdown
Contributor Author

Change addressed as requested: the record step now refuses a repository move and updates ref only, and the tests run the step's own heredoc rather than a copy of it. Nothing further from review; ready to merge. The rollout that follows (cut publishing-v9 at the merge commit, repoint mip's coordinator to it) is the maintainer's, as the description says.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants