Skip to content

Commit

Permalink
ci: add custom scripts to upload symbols before repairing wheels
Browse files Browse the repository at this point in the history
  • Loading branch information
wu-vincent committed Jan 4, 2025
1 parent 2b93464 commit 812c0df
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/wheel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ jobs:
- name: Build wheels
uses: pypa/[email protected]
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
CIBW_BUILD: ${{ matrix.python-tag }}-${{ matrix.platform }}
CIBW_BUILD_VERBOSITY: 1
CIBW_ENVIRONMENT_PASS_LINUX: "SENTRY_AUTH_TOKEN"

- uses: actions/upload-artifact@v4
with:
Expand Down
3 changes: 2 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ def validate(self):

if self.settings.arch != "x86_64":
raise ConanInvalidConfiguration(
f"{self.ref} can only be built on x86_64. {self.settings.arch} is not supported.")
f"{self.ref} can only be built on x86_64. {self.settings.arch} is not supported."
)

if self.settings.os == "Windows":
if not compiler == "msvc" or Version(compiler_version) < self._min_msvc_compiler_version:
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ lint.extend-select = ["I"]
skip = ["pp*"]
test-command = "pytest {package}/python/tests"
test-requires = "pytest"
repair-wheel-command = [
"pip install auditwheel sentry-cli",
'python scripts/repair_wheel.py -o endstone -p endstone -w {dest_dir} {wheel}',
]

[tool.cibuildwheel.linux]
manylinux-x86_64-image = "ghcr.io/endstonemc/manylinux_2_31_x86_64"
Expand Down
103 changes: 103 additions & 0 deletions scripts/repair_wheel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import argparse
import os
import platform
import subprocess
import tempfile
from pathlib import Path

from auditwheel.wheeltools import InWheelCtx


def run_command(cmd):
"""Run a shell command and stream its output to the console."""
with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) as p:
for line in p.stdout:
print(line, end="")

p.wait()
if p.returncode != 0:
print(f"Error: Command failed with return code {p.returncode}")
print(f"Command: {' '.join(p.args)}")
raise subprocess.CalledProcessError(p.returncode, p.args)


def upload_and_strip(ctx, org, project, auth_token, strip):
# Use sentry-cli to upload all debug files from the unpacked wheel
cmd = ["sentry-cli", "debug-files", "upload", "-o", org, "-p", project, "--include-sources", str(ctx.path)]
if auth_token:
cmd += ["--auth-token", auth_token]

run_command(cmd)

if strip:
# Remove all .pdb and .dbg files after upload
for root, _, filenames in os.walk(ctx.path):
for file in filenames:
file_path = Path(root) / file
if file_path.suffix in (".pdb", ".dbg"):
print(f"Removing: {file_path}")
os.remove(file_path)


def process_wheel(wheel_file, org, project, auth_token, dest_dir, strip):
system = platform.system().lower()

if system == "windows":
output_wheel = Path(dest_dir) / Path(wheel_file).name
with InWheelCtx(wheel_file, str(output_wheel)) as ctx:
upload_and_strip(ctx, org, project, auth_token, strip)
elif system == "linux":
# Handle Linux: Write stripped wheel to temp dir and repair it
with tempfile.TemporaryDirectory() as temp_dir:
temp_wheel = Path(temp_dir) / Path(wheel_file).name
with InWheelCtx(wheel_file, str(temp_wheel)) as ctx:
upload_and_strip(ctx, org, project, auth_token, strip)

# Repair the stripped wheel
cmd = ["auditwheel", "repair", "-w", dest_dir, str(temp_wheel)]
run_command(cmd)
else:
raise NotImplementedError(f"Unsupported platform: {system}")


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Repair a Python wheel file by uploading symbols and optionally stripping debug files."
)
parser.add_argument("wheel_file", help="Path to the .whl file to process.")
parser.add_argument("-w", "--dest-dir", required=True, help="Destination directory for the repaired wheel.")
parser.add_argument("-o", "--org", help="The organization ID or slug. Defaults to SENTRY_ORG environment variable.")
parser.add_argument(
"-p", "--project", help="The project ID or slug. Defaults to SENTRY_PROJECT environment variable."
)
parser.add_argument(
"--auth-token", help="Use the given Sentry auth token. Defaults to SENTRY_AUTH_TOKEN environment variable."
)
parser.add_argument("-s", "--strip", action="store_true", help="Strip the wheel by removing debug files.")

args = parser.parse_args()
wheel_file_path = Path(args.wheel_file).resolve()
dest_dir_path = Path(args.dest_dir).resolve()

org = args.org or os.getenv("SENTRY_ORG")
project = args.project or os.getenv("SENTRY_PROJECT")
auth_token = args.auth_token or os.getenv("SENTRY_AUTH_TOKEN")

if not org:
print("Error: Organization not set. Provide --org or set SENTRY_ORG environment variable.")
exit(1)

if not project:
print("Error: Project not set. Provide --project or set SENTRY_PROJECT environment variable.")
exit(1)

if not wheel_file_path.exists():
print(f"Error: File {wheel_file_path} does not exist.")
exit(1)

if not dest_dir_path.exists():
print(f"Error: Destination directory {dest_dir_path} does not exist.")
exit(1)

process_wheel(wheel_file_path, org, project, auth_token, dest_dir_path, args.strip)
print(f"Successfully processed the wheel file: {wheel_file_path}")

0 comments on commit 812c0df

Please sign in to comment.