forked from getsentry/sentry-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref: also distribute sentry-cli as a pip package (getsentry#1494)
- Loading branch information
1 parent
52f43ec
commit 2885be5
Showing
7 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,3 +169,47 @@ jobs: | |
with: | ||
name: ${{ github.sha }} | ||
path: '*.tgz' | ||
|
||
python-base: | ||
name: python (base) | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # pin@v1 | ||
with: | ||
toolchain: stable | ||
target: x86_64-unknown-linux-musl | ||
profile: minimal | ||
override: true | ||
- uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
- run: python3 -m pip install build && python3 -m build | ||
- uses: actions/[email protected] | ||
with: | ||
name: ${{ github.sha }}-python-base | ||
path: dist/* | ||
|
||
python: | ||
name: python | ||
runs-on: ubuntu-latest | ||
needs: [linux, macos, macos_universal, windows, python-base] | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
- uses: actions/download-artifact@v3 | ||
with: | ||
name: ${{ github.sha }} | ||
path: binaries | ||
- uses: actions/download-artifact@v3 | ||
with: | ||
name: ${{ github.sha }}-python-base | ||
path: python-base | ||
- run: scripts/wheels --binaries binaries --base python-base --dest dist | ||
- uses: actions/[email protected] | ||
with: | ||
name: ${{ github.sha }} | ||
path: dist/* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
include build.rs Cargo.toml Cargo.lock | ||
recursive-include src * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[build-system] | ||
requires = ["setuptools", "wheel", "setuptools-rust"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
#!/usr/bin/env python3 | ||
import argparse | ||
import base64 | ||
import hashlib | ||
import os.path | ||
import shutil | ||
import tempfile | ||
import zipfile | ||
from typing import NamedTuple | ||
|
||
|
||
class Wheel(NamedTuple): | ||
src: str | ||
plat: str | ||
exe: str = 'sentry-cli' | ||
|
||
|
||
WHEELS = ( | ||
Wheel( | ||
src='sentry-cli-Darwin-arm64', | ||
plat='macos_11_0_arm64', | ||
), | ||
Wheel( | ||
src='sentry-cli-Darwin-universal', | ||
plat='macos_11_0_universal2', | ||
), | ||
Wheel( | ||
src='sentry-cli-Darwin-x86_64', | ||
plat='macos_10_15_x86_64', | ||
), | ||
Wheel( | ||
src='sentry-cli-Linux-aarch64', | ||
plat='manylinux_2_17_aarch64.manylinux2014_aarch64', | ||
), | ||
Wheel( | ||
src='sentry-cli-Linux-armv7', | ||
plat='manylinux_2_17_armv7l.manylinux2014_armv7l', | ||
), | ||
Wheel( | ||
src='sentry-cli-Linux-i686', | ||
plat='manylinux_2_17_i686.manylinux2014_i686', | ||
), | ||
Wheel( | ||
src='sentry-cli-Linux-x86_64', | ||
plat='manylinux_2_17_x86_64.manylinux2014_x86_64', | ||
), | ||
Wheel( | ||
src='sentry-cli-Windows-i686.exe', | ||
plat='win32', | ||
exe='sentry-cli.exe', | ||
), | ||
Wheel( | ||
src='sentry-cli-Windows-x86_64.exe', | ||
plat='win_amd64', | ||
exe='sentry-cli.exe', | ||
), | ||
) | ||
|
||
|
||
def main() -> int: | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('--binaries', required=True) | ||
parser.add_argument('--base', required=True) | ||
parser.add_argument('--dest', required=True) | ||
args = parser.parse_args() | ||
|
||
expected = {wheel.src for wheel in WHEELS} | ||
received = set(os.listdir(args.binaries)) | ||
if expected != received: | ||
raise SystemExit( | ||
f'Unexpected binaries:\n\n' | ||
f'- extra: {", ".join(sorted(received - expected))}\n' | ||
f'- missing: {", ".join(sorted(expected - received))}' | ||
) | ||
|
||
sdist_path = wheel_path = None | ||
for fname in os.listdir(args.base): | ||
if fname.endswith('.tar.gz'): | ||
sdist_path = os.path.join(args.base, fname) | ||
elif fname.endswith('.whl'): | ||
wheel_path = os.path.join(args.base, fname) | ||
else: | ||
raise SystemExit(f'unexpected file in `--base`: {fname}') | ||
|
||
if sdist_path is None or wheel_path is None: | ||
raise SystemExit('expected wheel and sdist in `--base`') | ||
|
||
os.makedirs(args.dest, exist_ok=True) | ||
shutil.copy(sdist_path, args.dest) | ||
|
||
for wheel in WHEELS: | ||
binary_src = os.path.join(args.binaries, wheel.src) | ||
binary_size = os.stat(binary_src).st_size | ||
with open(binary_src, 'rb') as bf: | ||
digest = hashlib.sha256(bf.read()).digest() | ||
digest_b64 = base64.urlsafe_b64encode(digest).rstrip(b'=').decode() | ||
|
||
basename = os.path.basename(wheel_path) | ||
wheelname, _ = os.path.splitext(basename) | ||
name, version, py, abi, plat = wheelname.split('-') | ||
|
||
with tempfile.TemporaryDirectory() as tmp: | ||
with zipfile.ZipFile(wheel_path) as zipf: | ||
zipf.extractall(tmp) | ||
|
||
distinfo = os.path.join(tmp, f'{name}-{version}.dist-info') | ||
scripts = os.path.join(tmp, f'{name}-{version}.data', 'scripts') | ||
|
||
# replace the script binary with our copy | ||
os.remove(os.path.join(scripts, 'sentry-cli')) | ||
shutil.copy(binary_src, os.path.join(scripts, wheel.exe)) | ||
|
||
# rewrite RECORD to include the new file | ||
record_fname = os.path.join(distinfo, 'RECORD') | ||
with open(record_fname) as f: | ||
record_lines = list(f) | ||
|
||
record = f'{name}-{version}.data/scripts/sentry-cli,' | ||
for i, line in enumerate(record_lines): | ||
if line.startswith(record): | ||
record_lines[i] = ( | ||
f'{name}-{version}.data/scripts/{wheel.exe},' | ||
f'sha256={digest_b64},' | ||
f'{binary_size}\n' | ||
) | ||
break | ||
else: | ||
raise SystemExit(f'could not find {record!r} in RECORD') | ||
|
||
with open(record_fname, 'w') as f: | ||
f.writelines(record_lines) | ||
|
||
# rewrite WHEEL to have the new tags | ||
wheel_fname = os.path.join(distinfo, 'WHEEL') | ||
with open(wheel_fname) as f: | ||
wheel_lines = list(f) | ||
|
||
for i, line in enumerate(wheel_lines): | ||
if line.startswith('Tag: '): | ||
wheel_lines[i:i + 1] = [ | ||
f'Tag: {py}-{abi}-{plat}\n' | ||
for plat in wheel.plat.split('.') | ||
] | ||
break | ||
else: | ||
raise SystemExit("could not find 'Tag: ' in WHEEL") | ||
|
||
with open(wheel_fname, 'w') as f: | ||
f.writelines(wheel_lines) | ||
|
||
# write out the final zip | ||
new_basename = f'{name}-{version}-{py}-{abi}-{wheel.plat}.whl' | ||
tmp_new_wheel = os.path.join(tmp, new_basename) | ||
fnames = sorted( | ||
os.path.join(root, fname) | ||
for root, _, fnames in os.walk(tmp) | ||
for fname in fnames | ||
) | ||
with zipfile.ZipFile(tmp_new_wheel, 'w') as zipf: | ||
for fname in fnames: | ||
zinfo = zipfile.ZipInfo(os.path.relpath(fname, tmp)) | ||
if '/scripts/' in zinfo.filename: | ||
zinfo.external_attr = 0o100755 << 16 | ||
with open(fname, 'rb') as fb: | ||
zipf.writestr(zinfo, fb.read()) | ||
|
||
# move into dest | ||
shutil.move(tmp_new_wheel, args.dest) | ||
|
||
return 0 | ||
|
||
|
||
if __name__ == '__main__': | ||
raise SystemExit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[metadata] | ||
name = sentry_cli | ||
description = A command line utility to work with Sentry. | ||
long_description = file: README.md | ||
long_description_content_type = text/markdown | ||
url = https://github.com/getsentry/sentry-cli | ||
author = Sentry | ||
author_email = [email protected] | ||
license = BSD-3-Clause | ||
license_file = LICENSE | ||
classifiers = | ||
License :: OSI Approved :: BSD License | ||
Programming Language :: Python :: 3 | ||
Programming Language :: Python :: 3 :: Only | ||
Programming Language :: Python :: Implementation :: CPython | ||
Programming Language :: Python :: Implementation :: PyPy | ||
|
||
[options] | ||
packages = | ||
py_modules = | ||
python_requires = >=3.7 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from setuptools import setup | ||
from setuptools_rust import RustBin | ||
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel | ||
|
||
with open('Cargo.toml') as f: | ||
for line in f: | ||
if line.startswith('version = "'): | ||
_, VERSION, _ = line.split('"') | ||
break | ||
|
||
|
||
class bdist_wheel(_bdist_wheel): | ||
def finalize_options(self): | ||
super().finalize_options() | ||
self.root_is_pure = False | ||
|
||
def get_tag(self): | ||
_, _, plat = super().get_tag() | ||
return 'py3', 'none', plat | ||
|
||
|
||
setup( | ||
version=VERSION, | ||
rust_extensions=[RustBin("sentry-cli")], | ||
cmdclass={'bdist_wheel': bdist_wheel}, | ||
) |