Add thin Shoal compatibility metapackage - #111
Conversation
Convert the sharkbite distribution to metadata-only packaging with an exact Shoal implementation dependency and guarded Trusted Publishing automation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR converts the sharkbite distribution into a metadata-only compatibility package that pins and delegates all installed Python/native artifacts to the Shoal-owned implementation (shoal-sharkbite==0.5.0), while adding verification, smoke testing, and a protected Trusted Publishing release workflow.
Changes:
- Replace the legacy build/extension setup with a setuptools/PEP 621 metadata-only package (
packages = []) that depends exactly onshoal-sharkbite==0.5.0. - Add a metapackage verification script plus release policy docs to enforce “no installed files” and release ordering.
- Add CI workflow coverage for build/twine checks, sdist/wheel ownership validation, offline install/import smoke tests via a local stub implementation, and release-time attestation + PyPI publish.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/stub_implementation/src/sharkbite/init.py | Stub sharkbite package for offline smoke testing via a local fixture. |
| tests/stub_implementation/src/pysharkbite/init.py | Stub pysharkbite package mirroring version import behavior for the fixture. |
| tests/stub_implementation/pyproject.toml | Minimal build config for the local shoal-sharkbite fixture wheel. |
| setup.py | Reduced to a minimal shim (setup()) consistent with pyproject-driven builds. |
| scripts/verify_metapackage.py | Adds wheel/sdist verification to ensure the compatibility package installs no non-metadata files and pins exactly one dependency. |
| RELEASE.md | Documents compatibility-package release ordering and ownership/verification requirements. |
| PYTHONREADME.md | Updates Python README to reflect the new compatibility-metapackage architecture. |
| pyproject.toml | Defines the metadata-only sharkbite project and pins shoal-sharkbite==0.5.0. |
| MANIFEST.in | Excludes historical implementation sources from sdists while keeping required release docs/metadata. |
| .github/workflows/publish-pypi.yml | Adds build/verify/smoke-test pipeline plus release-time attestation and Trusted Publishing to PyPI. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Validate full archive-relative paths so nested historical files cannot pass based on an allowed basename. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
scripts/verify_metapackage.py:56
verify_sdist()only inspects regular files (member.isfile()), so an sdist could still include symlinks/hardlinks (or other special tar entries) without being flagged. For a strict "no historical implementation content" guard, fail the check if any non-file, non-directory members are present.
files = [
member.name.split("/", 1)[-1]
for member in archive.getmembers()
if member.isfile()
]
scripts/verify_metapackage.py:69
require_pypi_release()assumes the requirement string is exactlyname==versionand will generate an invalid PyPI URL if the dependency ever gains extras or environment markers (e.g.; python_version >= ...). Since this script is enforcing an "exact pin" contract, explicitly reject markers/extras and normalize whitespace before constructing the URL.
def require_pypi_release(requirement: str) -> None:
name, version = requirement.split("==", 1)
url = f"https://pypi.org/pypi/{name}/{version}/json"
Upload verified distributions and SHA-256 checksums to the intentional GitHub release after Trusted Publishing succeeds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second review of 146325b (earlier resolved sdist-basename finding excluded). No blocking defect found in the intended design; the items below are ordered by release-safety impact. Dependency/version guarantees
Package file ownership
Release safety / Trusted Publishing
Items 1, 2, 5, 6, and 8 are the ones I would fix before the release blockers are cleared. Say the word and I will implement them in this PR. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
scripts/verify_metapackage.py:74
require_pypi_release()only convertsHTTPErrorinto anAssertionError. Transient network failures (DNS, timeouts, TLS issues) raiseURLErrorand will currently bubble up as an unhelpful stack trace in CI. CatchURLErrortoo and raise a clear assertion so the failure mode is actionable.
try:
with urllib.request.urlopen(url, timeout=30) as response:
payload = json.load(response)
except urllib.error.HTTPError as error:
raise AssertionError(f"{requirement} is not published on PyPI") from error
scripts/verify_metapackage.py:56
verify_sdist()only inspects members wheremember.isfile()is true, so symlink/hardlink/other non-regular tar entries are ignored and could slip into the sdist without being detected. Since this script is acting as a release gate to prevent shipping historical implementation files, it should explicitly reject any non-file/non-directory members before applying the allowlist.
with tarfile.open(path, "r:*") as archive:
files = [
member.name.split("/", 1)[-1]
for member in archive.getmembers()
if member.isfile()
]
Clarify that the package is only an install-name bridge and that issue 108 remains open until all four live Accumulo rows pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Confirmed. d2c40a1's additions to PYTHONREADME.md, RELEASE.md, and pyproject.toml (Migration URL) state this is packaging/install-name evidence only, that the implementation already lives in Shoal, and that #108 stays open until its four live Accumulo rows pass — consistent with issue #108's current revision-56 state (394 required / 390 satisfied / 4 remaining, all live-Accumulo). No claim of completion or duplication of the Shoal implementation is made anywhere in the diff. |
Use 1.3.0 for both distributions, enforce exact same-version metadata, and verify Shoal release hashes, provenance, native ABI, ownership, and pip health before publishing the bridge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@copilot please perform the next substantive review of commit 52fb475. Verify the four latest release-safety fixes and look for any new correctness, dependency/version, artifact integrity, metadata-only ownership, Trusted Publishing, or CI defects. Ignore suppressed/minimized comments. If no new unsuppressed findings remain, state that explicitly. |
Reviewed 52fb475. All four fixes verified:
No new correctness, dependency/version, artifact-integrity, ownership, Trusted Publishing, or CI defects found in this commit. |
Make iterator and validation headers self-contained for current Ubuntu compilers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bb63dd55-8d79-4fb2-b809-6d865e062cd8
|
@copilot please review current HEAD 2edf8c2. The only changes after the prior clean round are direct |
Reviewed 2edf8c2. Confirmed the diff is exactly the three |
The compatibility distribution is metadata-only, so preserve native compilation for changes to historical C++ surfaces without gating packaging-only commits on unrelated compiler debt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bb63dd55-8d79-4fb2-b809-6d865e062cd8
Clarify that metadata-only releases use the packaging workflow while legacy native CI remains scoped to native source changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bb63dd55-8d79-4fb2-b809-6d865e062cd8
|
@copilot please perform the final substantive review of current HEAD 2d8c802. Review the complete PR, including the legacy native workflow path scoping and release-policy clarification. Check for any new unsuppressed correctness, CI coverage, release-safety, dependency/version, artifact-integrity, metadata-only ownership, or Trusted Publishing findings. Ignore suppressed/minimized comments and state explicitly if none remain. |
Co-authored-by: phrocker <1781585+phrocker@users.noreply.github.com>
Reviewed 2d8c802 in full. Found one real regression: b228c93 ("Scope legacy native CI to native changes") inadvertently reverted the Everything else checks out:
No other new unsuppressed correctness, CI coverage, release-safety, dependency/version, artifact-integrity, ownership, or Trusted Publishing findings remain. |
|
@copilot please perform one final review of exact HEAD 38e2eb5 after your restored |
Reviewed exact HEAD 38e2eb5. Confirmed the diff from 2d8c802 is only the four restored |
Co-authored-by: phrocker <1781585+phrocker@users.noreply.github.com>
Remove accidentally committed egg-info output and ignore future local distribution metadata and build artifacts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bb63dd55-8d79-4fb2-b809-6d865e062cd8
|
@copilot please review exact HEAD b262099 after removal of the accidentally committed generated |
Reviewed exact HEAD b262099. Confirmed the diff from 38e2eb5 only removes the accidentally-committed |
Summary
sharkbitedistribution to a metadata-only install-name/release bridge1.3.0selected as unused and above historicalsharkbite1.2.0.3)shoal-sharkbite==1.3.0)Architecture
PyPI
sharkbite==VERSIONinstalls no modules or native files. It depends onshoal-sharkbite==VERSION, the sole owner of the existingsharkbite,pysharkbite, and bundled native C ABI implementation. The thin wheel owns only its distinctsharkbite-VERSION.dist-info.Authoritative migration gate
#108 remains authoritative. This bridge is packaging evidence only and does not complete/displace Shoal compatibility. Revision 56 is 394 required / 390 satisfied. The four live rows remain
SB-SCAN-022,SB-SCAN-026,SB-XCUT-015, andSB-XCUT-016.Validation
pip checkactionlint1.7.7--no-depsimplementation install, both imports, bundled native ownership, ABI/capabilities, then the local bridge wheelCoordinated release ordering and blockers
f36bf2a)b02ff55)1.3.01.3.0v1.3.0/shoal-sharkbite==1.3.0sharkbite==1.3.0This PR remains draft. No production release has been published. Merging/publishing it does not close #108.