Document validation findings in design spec and plan
Five things we learned during local validation that the original docs didn't anticipate: - PYTHON_BASEURL needs three %s slots (relocatable-python passes version, version, os-version) - mkdir -m 777 doesn't apply mode to existing dirs; need explicit chmod - --no-unsign disabled relocatable-python's own re-sign step and caused Apple Silicon Gatekeeper SIGKILLs at ensurepip time - Signed pkg must move to outputs/ before cleanup() runs - pyobjc 12.1 requires Python >= 3.10; 3.9 needs holdback to 11.1 Also confirmed all upstream SHAs (relocatable-python, munki-pkg) and all 37 Python package pins are at latest available as of 2026-05-11. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
c06e814a4b
commit
24bd176b9d
@@ -847,3 +847,32 @@ Nothing to commit — these are CI-side actions only. Phase 3 work (archiving th
|
||||
- Phase 3 explicitly excluded: workflow consolidation, runner migration, action bumps, release-trigger change — Task 7 Step 4 includes a deliberate stopgap (long-flag invocation inside the still-duplicated workflows) so CI keeps working in the in-between state.
|
||||
- No placeholders: every code block is concrete; every `Expected:` describes verifiable output.
|
||||
- Type / name consistency: long-flag names (`--python-version`, `--installer-id`, `--application-id`, `--notary-password`, `--xcode-path`) are identical across Tasks 1, 7, and 9.
|
||||
|
||||
---
|
||||
|
||||
## Post-Implementation Notes (2026-05-11)
|
||||
|
||||
Tasks 1–11 are complete on branch `claude`. Task 12 is pending the branch push + merge.
|
||||
|
||||
### Deltas from the original plan text above
|
||||
|
||||
- **Task 1 — Script content has three additional fixes** layered onto the version this plan documents:
|
||||
- `PYTHON_BASEURL` keeps three `%s` slots (not the two-slot literal `macos11` version). Commit `e611fb1`.
|
||||
- `prepare_build_dirs()` explicitly `chmod 777`s `FRAMEWORKDIR` after `mkdir`. Commit `3057706`.
|
||||
- The `--no-unsign` flag was removed from the `make_relocatable_python_framework.py` invocation; it was disabling relocatable-python's ad-hoc re-sign step that satisfies Apple Silicon Gatekeeper. Commit `69af8f1`.
|
||||
- `build_pkg()` now `mv`s the produced `.pkg` to `outputs/` directly so signed-but-unnotarized builds survive `cleanup()`. Commit `29b3a55`.
|
||||
|
||||
See the design spec's "Validation Findings" section for the full reasoning.
|
||||
|
||||
- **Task 7 Step 4 — Workflow `run:` block** now matches the spec exactly; the in-between-window stopgap (long-flag invocation inside the still-duplicated workflows) is in place across all six workflow files. Commits `c10dc22`, `590f478`, `1764c84`.
|
||||
|
||||
- **Task 9 — Release notes** also include a corrected "Recommended flavor" description, since the original `… everything from minimal …` line referenced a flavor that no longer exists. The fix went into the same commit as the final-release notice.
|
||||
|
||||
- **Task 10 — Pin sweep was pulled forward** and merged with the initial 3.13.13 / 3.14.5 validation (commit `1216394`). The cross-version follow-up (commit `f9c0853`) added one holdback: `pyobjc==11.1; python_version < "3.10"`, since `pyobjc 12.1` declares `requires_python >= 3.10` and `pyobjc-core 12.1` lacks a cp39 wheel. Every other native-code package (`cffi`, `charset-normalizer`, `PyYAML`, `tomli`, `xattr`) ships universal2 wheels for cp39 through cp314 at latest.
|
||||
|
||||
- **Task 12 — Still pending.** Branch is local-only; releases will be dispatched after push + merge.
|
||||
|
||||
### Open follow-ups
|
||||
|
||||
- `RP_SHA` is held at `8ee72fe` (latest available). When upstream addresses [gregneagle/relocatable-python#32](https://github.com/gregneagle/relocatable-python/issues/32), revisit whether further bumps are possible.
|
||||
- Phase 3 (CI/CD overhaul) is its own design exercise.
|
||||
|
||||
@@ -192,3 +192,52 @@ Phase 2 is done when:
|
||||
- `build_python_3.14.yml` exists and runs green end-to-end.
|
||||
- 3.9.13 and 3.10.11 each have one final release published with "final release" notes.
|
||||
- `.github/dependabot.yml` is enabled for GitHub Actions.
|
||||
|
||||
## Validation Findings (post-implementation, 2026-05-11)
|
||||
|
||||
The Phase 1 + Phase 2 implementation surfaced four bugs and one design refinement that the earlier sections don't reflect. All are fixed in code; this section is the authoritative record of why each change was made.
|
||||
|
||||
### 1. `PYTHON_BASEURL` needs three `%s` slots, not two
|
||||
|
||||
The URL template must be `https://www.python.org/ftp/python/%s/python-%s-macos%s.pkg`. `relocatable-python`'s `locallibs/get.py` passes (version, version, os-version) into `base_url % (...)`. An earlier refactor that hardcoded `macos11` left only two slots and raised `TypeError: not all arguments converted during string formatting` at framework-download time. Fixed in `e611fb1`.
|
||||
|
||||
### 2. `mkdir -m 777 -p` does not chmod existing directories
|
||||
|
||||
`prepare_build_dirs()` must `mkdir -p` and then `chmod 777` explicitly. The `-m 777` flag only applies to newly created directories; an existing `/Library/ManagedFrameworks/Python/` (from a prior install) keeps its stricter perms, causing `relocatable-python` to fail with `Permission denied` when it ditto-extracts the python.org pkg into the framework. Fixed in `3057706`.
|
||||
|
||||
### 3. `--no-unsign` is incompatible with Apple Silicon Gatekeeper
|
||||
|
||||
The original Phase 1 design kept `--no-unsign` in the `make_relocatable_python_framework.py` invocation to "preserve the python.org signature". In practice, `install_name_tool` invalidates that signature whether the flag is set or not; the flag's only behavioral effect is to *disable* `relocatable-python`'s own `fix_broken_signatures` step (`locallibs/fix.py`), which ad-hoc re-signs the modified binaries before `ensurepip` runs.
|
||||
|
||||
Without that re-sign, Apple Silicon's Gatekeeper SIGKILLs the Python binary when `ensurepip` tries to execute it. This is the upstream issue [gregneagle/relocatable-python#32](https://github.com/gregneagle/relocatable-python/issues/32). Solution: drop `--no-unsign`. The intermediate ad-hoc signature is overwritten by our `codesign_framework()` step at the end, so the final artifact's signature comes from our Developer ID. Fixed in `69af8f1`.
|
||||
|
||||
This problem only manifests on Apple Silicon hosts; prior Intel CI runs masked it because Intel Gatekeeper is more lenient about invalid signatures. Switching the build host architecture is part of what this whole modernization exists to enable.
|
||||
|
||||
### 4. Signed `.pkg` must move to `outputs/` from `build_pkg()`, not `notarize_and_staple()`
|
||||
|
||||
The pre-refactor script moved the produced `.pkg` to `outputs/` unconditionally after `munkipkg` succeeded. The Phase 1 refactor consolidated that `mv` into `notarize_and_staple()`, which early-returns when no notary password is provided — so a signed-but-unnotarized build had its `.pkg` deleted by `cleanup()` before it ever landed in `outputs/`. The move now happens at the end of `build_pkg()`; `notarize_and_staple()` operates on the `.pkg` in its final location. Fixed in `29b3a55`.
|
||||
|
||||
### 5. pyobjc holdback for Python 3.9
|
||||
|
||||
The Phase 2 pin sweep aspirationally bumped every package to PyPI latest. That works for 3.10 → 3.14 universally, but `pyobjc 12.1` declares `requires_python >= 3.10` and `pyobjc-core 12.1` lacks a cp39 wheel — the Python 3.9 final-release build would fail at pip-install time. Resolution in `requirements_recommended.txt`:
|
||||
|
||||
```
|
||||
pyobjc==12.1; python_version >= "3.10"
|
||||
pyobjc==11.1; python_version < "3.10"
|
||||
```
|
||||
|
||||
This is the only holdback discovered. All other native-code packages (`cffi`, `charset-normalizer`, `PyYAML`, `tomli`, `xattr`) ship universal2 wheels for cp39 through cp314 at their latest versions; pure-Python packages install on any Python 3.x. Fixed in `f9c0853`.
|
||||
|
||||
### Acceptance criteria — actual results
|
||||
|
||||
- ✅ `./build_python_framework_pkgs.zsh --python-version 3.13.13` succeeds end-to-end on Apple Silicon, produces an installable framework zip, and the resulting `managed_python3` runs `import objc, xattr, requests, yaml` on arm64.
|
||||
- ✅ Same for 3.14.5.
|
||||
- ⏳ Cross-version validation for 3.9 / 3.10 / 3.11 / 3.12 — pending local runs.
|
||||
- ✅ Five workflow files updated to long-flag invocation; `build_python_3.14.yml` added.
|
||||
- ✅ Dependabot enabled for GitHub Actions.
|
||||
- ⏳ Final releases for 3.9 / 3.10 — pending the manual `workflow_dispatch` after merge.
|
||||
|
||||
### Items rolled over to follow-up work
|
||||
|
||||
- **Bump `RP_SHA` past `8ee72fe`** once upstream addresses the Apple Silicon ensurepip flow (tracked: gregneagle/relocatable-python#32).
|
||||
- **Phase 3 (CI/CD overhaul)** — workflow consolidation, runner migration to `macos-14`, action version bumps, release trigger change, archival of `build_python_3.9.yml` and `build_python_3.10.yml`. Out of scope for this spec.
|
||||
|
||||
Reference in New Issue
Block a user