From cdb01dac76318e3d397fa6f68f848851e59f1c2a Mon Sep 17 00:00:00 2001 From: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:19:35 -0600 Subject: [PATCH 1/4] tests: pass the required profile to resolve The installed-wheel checks invoke resolve without its required profile. Select j71b so these tests exercise package independence against the current command contract. Signed-off-by: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> --- tests/test_package_boundaries.py | 2 +- tests/test_runtime.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_package_boundaries.py b/tests/test_package_boundaries.py index c7caee5..323d66d 100644 --- a/tests/test_package_boundaries.py +++ b/tests/test_package_boundaries.py @@ -40,7 +40,7 @@ def find_spec(self, name, path=None, target=None): from orchard_hardware.apple import adt from orchard_cli.command import main sys.argv=['orchard','distros'];main() -sys.argv=['orchard','resolve',MANIFEST];main() +sys.argv=['orchard','resolve',MANIFEST,'--profile','j71b'];main() '''.replace('MANIFEST', repr(str(FIXTURE.resolve()))) with tempfile.TemporaryDirectory() as store: result = subprocess.run([sys.executable, '-I', '-c', script], cwd=store, diff --git a/tests/test_runtime.py b/tests/test_runtime.py index 3db4e5b..0522ca1 100644 --- a/tests/test_runtime.py +++ b/tests/test_runtime.py @@ -308,7 +308,7 @@ def guard(event, args): sys.addaudithook(guard) from orchard_cli.command import main -sys.argv = ['orchard', 'resolve', INPUT] +sys.argv = ['orchard', 'resolve', INPUT, '--profile', 'j71b'] main() '''.replace('BLOCKED', repr([str(path) for path in blocked])).replace('INPUT', repr(str(inputs / 'index.toml'))) env = {**os.environ, 'ORCHARD_HOME': str(self.root / 'isolated-store'), 'PYTHONDONTWRITEBYTECODE': '1'} From f187900caed849777ad54706c8e42409b07f4efc Mon Sep 17 00:00:00 2001 From: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:25:07 -0600 Subject: [PATCH 2/4] tests: resolve installed device fixture paths Python virtualenvs may expose the trusted hardware package through a lib64 link. Resolve the fixture path before checking the package data with the strict local bundle validator. Signed-off-by: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> --- tests/test_manifests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_manifests.py b/tests/test_manifests.py index 2cc41e4..4c5c49f 100644 --- a/tests/test_manifests.py +++ b/tests/test_manifests.py @@ -29,7 +29,8 @@ def rejects(self, document): def test_all_fixtures_validate_with_local_receipts(self): paths = list(DISTRO.glob('*.toml')) + list(MINIMAL.glob('*.toml')) paths += list((CLI / 'tests/fixtures/developer').glob('*.toml')) - paths += [device_path('j71b')] + # An installed package may be reached through a virtualenv lib64 link. + paths += [device_path('j71b').resolve()] for path in paths: with self.subTest(path=path): verify_local_receipts(load(path), path.parent) From 9016fea84da3a1bb9a71771e6bbf17de51756786 Mon Sep 17 00:00:00 2001 From: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> Date: Thu, 29 Oct 2026 16:38:18 -0600 Subject: [PATCH 3/4] tests: import the current Apple source modules Signed-off-by: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> --- tests/test_package_boundaries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_package_boundaries.py b/tests/test_package_boundaries.py index ef6dab4..7068f60 100644 --- a/tests/test_package_boundaries.py +++ b/tests/test_package_boundaries.py @@ -11,7 +11,7 @@ from unittest.mock import Mock, patch from orchard_cli import firmware -from orchard_cli.apple import usb, ipsw +from orchard_cli.apple import usb from orchard_cli.progress import Clock from orchard_cli.state import DeviceState @@ -35,7 +35,7 @@ def find_spec(self, name, path=None, target=None): sys.meta_path.insert(0, NoBoard()) from orchard_cli import downloads, firmware, http, integrity from orchard_cli.transports import ssh -from orchard_cli.apple import adt_tree, adt_capture, macho, osserialize, ipsw, usb, boot +from orchard_cli.apple import adt_tree, adt_capture, macho, osserialize, remote_ipsw, udif, apfs, lzfse, usb, boot from orchard_hardware.apple import adt from orchard_cli.command import main sys.argv=['orchard','distros'];main() From bf785b6725aeed1c447ce95723f3ce8999447881 Mon Sep 17 00:00:00 2001 From: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> Date: Thu, 29 Oct 2026 21:42:44 -0600 Subject: [PATCH 4/4] ci: pair development checks with hardware 0.1.11 CLI main requires hardware 0.1.11, which has not been released. Build a wheel from a pinned hardware revision for pull requests and branch pushes so their package and test jobs use a compatible version. Align the default release tag with the dependency while retaining the existing published-wheel and explicit-artifact release paths. Signed-off-by: Shayne Legault <8741557+shaynelegault@users.noreply.github.com> --- .github/workflows/build.yml | 21 ++++++++++++++++++--- docs/releases.md | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e9e7dec..be26861 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: hardware_tag: description: Hardware version to pair with this CLI required: true - default: v0.1.10 + default: v0.1.11 hardware_run_id: description: Optional hardware workflow run providing the tested wheel before its first release required: false @@ -24,7 +24,7 @@ jobs: package: runs-on: ubuntu-24.04 env: - HARDWARE_TAG: ${{ inputs.hardware_tag || 'v0.1.10' }} + HARDWARE_TAG: ${{ inputs.hardware_tag || 'v0.1.11' }} steps: - uses: actions/checkout@v4 with: @@ -32,8 +32,23 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.12' + # Hardware 0.1.11 is required by the CLI but has not been released yet. + # Development checks use a fixed upstream revision until it is published. + - name: Check out pinned hardware source for development checks + if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref_type == 'branch') + uses: actions/checkout@v4 + with: + repository: OrchardLinux/hardware + ref: ae1457edee7d2e52213e4d979aee02dbbeb90ce0 + path: out/hardware-source + persist-credentials: false + - name: Build the pinned hardware wheel for development checks + if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref_type == 'branch') + run: | + python -m pip install build + python -m build --wheel --outdir "$PWD/out/hardware" out/hardware-source - name: Download pinned released hardware dependency - if: inputs.hardware_run_id == '' + if: github.event_name != 'pull_request' && (github.event_name != 'push' || github.ref_type != 'branch') && inputs.hardware_run_id == '' env: GH_TOKEN: ${{ github.token }} run: | diff --git a/docs/releases.md b/docs/releases.md index 6efe4c5..288a44f 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -4,7 +4,7 @@ The bootstrap installs `releases/latest/download/requirements.txt`. This file se ## GitHub Actions -`.github/workflows/build.yml` tests on Python 3.9 and 3.12 for pull requests and `main`. It downloads a published hardware wheel and verifies its release checksums; no sibling source checkout is used. The default hardware tag is explicit in the workflow and must be updated with the package dependency when selecting a new pair. Manual dispatch also lets you choose a hardware tag. +`.github/workflows/build.yml` tests on Python 3.9 and 3.12 for pull requests and `main`. Until hardware 0.1.11 is published, those development checks build its wheel from a pinned hardware source revision. That source wheel does not include the prebuilt loaders in a published hardware wheel. Tag and manual builds use a published hardware wheel with verified release checksums, or an explicitly selected hardware workflow artifact. They default to hardware v0.1.11, which must be published before a release build can use it. Manual dispatch also lets you choose a hardware tag. A version tag matching `pyproject.toml` creates a **draft** release containing the wheel, sdist, hashed `requirements.txt` and `SHA256SUMS`. Manual builds only retain workflow artifacts for seven days. The hardware release must be published first; cross-repository drafts are not public dependency URLs. Nothing publishes automatically or operates a device.