Skip to content

Commit 27a05f2

Browse files
gh-distribute-toolchain: Remove toolchain packaging code
1 parent ce458b0 commit 27a05f2

File tree

1 file changed

+20
-273
lines changed

1 file changed

+20
-273
lines changed

tools/gh-distribute-toolchain

Lines changed: 20 additions & 273 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import os
99
import sys
1010
import subprocess
11-
import tarfile
1211
import asyncio
1312
import json
1413
from dataclasses import dataclass
@@ -21,11 +20,6 @@ USER_AGENT = "gh-distribute-toolchain by swiftwasm/swiftwasm-build"
2120

2221
@dataclass
2322
class Secrets:
24-
DARWIN_TOOLCHAIN_APPLICATION_CERT: str
25-
DARWIN_TOOLCHAIN_INSTALLER_CERT: str
26-
DARWIN_TOOLCHAIN_NOTARIZE_EMAIL: str
27-
DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID: str
28-
DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD: str
2923
GITHUB_TOKEN: str
3024

3125
@staticmethod
@@ -40,16 +34,6 @@ class Secrets:
4034
github_token = result.stdout.decode("utf-8").strip()
4135

4236
return Secrets(
43-
DARWIN_TOOLCHAIN_APPLICATION_CERT=Secrets.env_value(
44-
"DARWIN_TOOLCHAIN_APPLICATION_CERT"),
45-
DARWIN_TOOLCHAIN_INSTALLER_CERT=Secrets.env_value(
46-
"DARWIN_TOOLCHAIN_INSTALLER_CERT"),
47-
DARWIN_TOOLCHAIN_NOTARIZE_EMAIL=Secrets.env_value(
48-
"DARWIN_TOOLCHAIN_NOTARIZE_EMAIL"),
49-
DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID=Secrets.env_value(
50-
"DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID"),
51-
DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD=Secrets.env_value(
52-
"DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD"),
5337
GITHUB_TOKEN=github_token,
5438
)
5539

@@ -58,130 +42,6 @@ class Secrets:
5842
return os.environ.get(key)
5943

6044

61-
class DarwinToolchainPackaging:
62-
def __init__(self, secrets: Secrets,
63-
dry_run: bool = False, verbose: bool = False):
64-
self.secrets = secrets
65-
self.dry_run = dry_run
66-
self.verbose = verbose
67-
68-
async def package(self, toolchain_dir: str, tag_name: str, pkg_path: str,
69-
swift_source_dir: str):
70-
self.update_info_plist(toolchain_dir)
71-
self.sign_darwin_toolchain(toolchain_dir)
72-
await self.create_installer(toolchain_dir, pkg_path, tag_name, swift_source_dir)
73-
74-
def update_info_plist(self, toolchain_dir: str):
75-
display_name = os.environ.get("DARWIN_TOOLCHAIN_DISPLAY_NAME")
76-
info_plist = f"{toolchain_dir}/Info.plist"
77-
if display_name:
78-
subprocess.check_output([
79-
"/usr/libexec/PlistBuddy",
80-
"-c", f"Set DisplayName {display_name}", info_plist
81-
])
82-
83-
display_name_short = os.environ.get(
84-
"DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT")
85-
if display_name_short:
86-
subprocess.check_output([
87-
"/usr/libexec/PlistBuddy",
88-
"-c", f"Set ShortDisplayName {display_name_short}", info_plist
89-
])
90-
91-
def sign_darwin_toolchain(self, toolchain_dir: str):
92-
if self.secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT is None:
93-
raise Exception("Missing DARWIN_TOOLCHAIN_APPLICATION_CERT")
94-
95-
codesign_args = [
96-
"/usr/bin/codesign",
97-
"--force", "--verify", "--verbose", "--deep",
98-
"--options", "runtime", "--timestamp",
99-
"--sign", self.secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT
100-
]
101-
102-
for root, dirs, files in os.walk(toolchain_dir):
103-
for file in files:
104-
path = os.path.join(root, file)
105-
if not self.is_macho_binary(path):
106-
continue
107-
self.subprocess_run(codesign_args + [path], check=True)
108-
109-
self.subprocess_run(codesign_args + [toolchain_dir], check=True)
110-
111-
async def create_installer(self, toolchain_dir: str, pkg_path: str,
112-
tag_name: str, swift_source_dir: str):
113-
toolchain_name = tag_name
114-
toolchain_installer_package = pkg_path
115-
toolchain_install_location = (
116-
f"/Library/Developer/Toolchains/{toolchain_name}.xctoolchain")
117-
toolchain_version = subprocess.check_output([
118-
"/usr/libexec/PlistBuddy",
119-
"-c", "Print Version string",
120-
f"{toolchain_dir}/Info.plist"
121-
]).decode("utf-8")
122-
toolchain_bundle_identifier = subprocess.check_output([
123-
"/usr/libexec/PlistBuddy",
124-
"-c", "Print CFBundleIdentifier string",
125-
f"{toolchain_dir}/Info.plist"
126-
]).decode("utf-8")
127-
128-
self.subprocess_run([
129-
f"{swift_source_dir}/utils/toolchain-installer", toolchain_dir,
130-
toolchain_bundle_identifier,
131-
self.secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT,
132-
toolchain_installer_package,
133-
toolchain_install_location,
134-
toolchain_version,
135-
f"{swift_source_dir}/utils/darwin-installer-scripts"
136-
], check=True)
137-
138-
await self.check_async_subprocess(
139-
"xcrun", "notarytool", "submit",
140-
toolchain_installer_package,
141-
"--wait",
142-
"--apple-id", self.secrets.DARWIN_TOOLCHAIN_NOTARIZE_EMAIL,
143-
"--team-id", self.secrets.DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID,
144-
"--password", self.secrets.DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD)
145-
146-
self.subprocess_run(["xcrun", "stapler", "staple",
147-
toolchain_installer_package], check=True)
148-
149-
def subprocess_run(self, args, **kwargs):
150-
"""
151-
Run a non-mutating subprocess and print the command if
152-
verbose or dry_run is True.
153-
"""
154-
if self.verbose or self.dry_run:
155-
print(" ".join(args))
156-
return subprocess.run(args, **kwargs)
157-
158-
async def check_async_subprocess(self, program, *args):
159-
if self.verbose or self.dry_run:
160-
print(f"[async] {program} {' '.join(args)}")
161-
if self.dry_run:
162-
return
163-
proc = await asyncio.subprocess.create_subprocess_exec(program, *args)
164-
retcode = await proc.wait()
165-
if retcode != 0:
166-
raise Exception(f"Failed to execute: {' '.join(args)}")
167-
168-
def is_macho_binary(self, file_path):
169-
if not os.path.exists(file_path):
170-
return False
171-
magic_bytes = None
172-
with open(file_path, mode="rb") as f:
173-
magic_bytes = f.read(4)
174-
macho_bytes = [
175-
[0xca, 0xfe, 0xba, 0xbe], # Mach-O Fat Binary
176-
[0xcf, 0xfa, 0xed, 0xfe], # Mach-O 64-bit executable
177-
[0xce, 0xfa, 0xed, 0xfe], # Mach-O 32-bit executable
178-
]
179-
for b in macho_bytes:
180-
if magic_bytes == bytes(b):
181-
return True
182-
return False
183-
184-
18545
class GitHub:
18646
def __init__(self, token: str, repo: str = "swiftwasm/swiftwasm-build"):
18747
self.token = token
@@ -348,13 +208,14 @@ class Distribution:
348208
async def run(self, options):
349209
downloads = []
350210
for artifact in self.toolchain_artifacts(options):
351-
if options.only_swift_sdk:
352-
if not artifact["name"].endswith("-artifactbundle"):
353-
print(f"Skipping {artifact['name']} because it's not an"
354-
" artifactbundle for --only-swift-sdk")
355-
continue
211+
if not artifact["name"].endswith("-artifactbundle"):
212+
print(f"Skipping {artifact['name']} because it's not an"
213+
" artifactbundle for --only-swift-sdk")
214+
continue
215+
356216
_, scheme, _ = derive_platform_suffix_and_scheme(
357217
artifact["name"], options.scheme)
218+
358219
if options.scheme != scheme:
359220
print(f"Skipping {artifact['name']} because it's not scheme {options.scheme}")
360221
# Skip unrelated artifact
@@ -388,22 +249,16 @@ class Distribution:
388249
# Create tag and release on GitHub
389250
if not tag_name:
390251
for artifact, artifact_path in downloaded_paths:
391-
if artifact["name"].endswith("-installable"):
392-
artifact_path = self.unpack_toolchain(artifact_path)
393-
tag_name = self.guess_tag_name(artifact_path)
394-
break
395-
elif artifact["name"].endswith("-artifactbundle"):
396-
platform_suffix, _, target_triple = derive_platform_suffix_and_scheme(
397-
artifact["name"], options.scheme)
398-
bundle_path = await self.unpack_artifactbundle(artifact_path)
399-
dirents = os.listdir(bundle_path)
400-
dirents.remove("info.json")
401-
sdk_artifact_id = dirents[0]
402-
if not platform_suffix:
403-
tag_name = "swift-wasm-" + sdk_artifact_id.removesuffix("-" + target_triple)
404-
else:
405-
tag_name = "swift-wasm-" + sdk_artifact_id.removesuffix("-wasm")
406-
break
252+
if not artifact["name"].endswith("-artifactbundle"):
253+
continue
254+
platform_suffix, _, target_triple = derive_platform_suffix_and_scheme(
255+
artifact["name"], options.scheme)
256+
bundle_path = await self.unpack_artifactbundle(artifact_path)
257+
dirents = os.listdir(bundle_path)
258+
dirents.remove("info.json")
259+
sdk_artifact_id = dirents[0]
260+
tag_name = "swift-wasm-" + sdk_artifact_id.removesuffix("-" + target_triple)
261+
break
407262

408263
if not tag_name:
409264
raise Exception("Could not determine tag name")
@@ -425,10 +280,7 @@ class Distribution:
425280
artifact, artifact_path = downloaded
426281
platform_suffix, scheme, target_triple = derive_platform_suffix_and_scheme(
427282
artifact["name"], options.scheme)
428-
if not platform_suffix:
429-
artifact_format = SDKArtifactFormatV3(target_triple)
430-
else:
431-
artifact_format = SDKArtifactFormatV2(platform_suffix)
283+
artifact_format = SDKArtifactFormatV3(target_triple)
432284
bundle_path = await self.unpack_artifactbundle(artifact_path)
433285
package = await self.package_artifactbundle(
434286
bundle_path, tag_name, artifact_format)
@@ -462,73 +314,6 @@ class Distribution:
462314
self.update_release_notes_with_checksums(
463315
release, swift_version, swiftwasm_build_version)
464316

465-
if options.only_swift_sdk:
466-
return
467-
468-
# Package and upload toolchains
469-
for artifact, artifact_path in downloaded_paths:
470-
import shutil
471-
if not artifact["name"].endswith("-installable"):
472-
continue
473-
474-
platform_suffix, _, _ = derive_platform_suffix_and_scheme(
475-
artifact["name"], options.scheme)
476-
artifact_path = self.unpack_toolchain(artifact_path)
477-
package, artifact_path = await self.package_toolchain(
478-
artifact_path, tag_name, platform_suffix)
479-
if options.dry_run:
480-
print(f"Skip uploading actual artifact \"{package}\"")
481-
continue
482-
self.upload_to_release(package, release)
483-
if options.optimize_disk_footprint:
484-
print(f"Removing {artifact_path} to optimize disk footprint")
485-
shutil.rmtree(artifact_path)
486-
487-
def guess_tag_name(self, path):
488-
return os.path.basename(path)
489-
490-
async def package_toolchain(self, artifact_path: str, tag_name: str,
491-
platform_suffix: str):
492-
print(f"Packaging {artifact_path}")
493-
import shutil
494-
dest_dir = os.path.dirname(artifact_path)
495-
artifacts_path = os.path.dirname(dest_dir)
496-
497-
if os.path.basename(artifact_path) != tag_name:
498-
# e.g.
499-
# dest_dir:
500-
# <run-id>/swift-wasm-DEVELOPMENT-SNAPSHOT-amazonlinux2_x86_64
501-
# artifact_path:
502-
# <dest-dir>/swift-wasm-DEVELOPMENT-SNAPSHOT-2023-6-25-a
503-
# dest_path:
504-
# <dest-dir>/swift-wasm-DEVELOPMENT-SNAPSHOT-2023-6-25-b
505-
print(f"Re-package {artifact_path} as {tag_name}")
506-
dest_path = os.path.join(dest_dir, tag_name)
507-
shutil.rmtree(dest_path, ignore_errors=True)
508-
shutil.move(artifact_path, dest_path)
509-
artifact_path = dest_path
510-
511-
if platform_suffix.startswith("macos_"):
512-
pkg_path = os.path.join(
513-
artifacts_path, f"{tag_name}-{platform_suffix}.pkg")
514-
if os.path.exists(pkg_path):
515-
return [pkg_path, artifact_path]
516-
swift_source_dir = os.path.join(self.checkout_dir, "swift")
517-
await DarwinToolchainPackaging(
518-
self.secrets, self.dry_run, self.verbose
519-
).package(artifact_path, tag_name, pkg_path, swift_source_dir)
520-
return [pkg_path, artifact_path]
521-
else:
522-
tarball_path = os.path.join(
523-
artifacts_path, f"{tag_name}-{platform_suffix}.tar.gz")
524-
if os.path.exists(tarball_path):
525-
return [tarball_path, artifact_path]
526-
tar_args = ["tar", "cfz", tarball_path,
527-
"-C", os.path.dirname(artifact_path),
528-
os.path.basename(artifact_path)]
529-
self.subprocess_run(tar_args, check=True)
530-
return [tarball_path, artifact_path]
531-
532317
async def package_artifactbundle(
533318
self, artifact_path: str, tag_name: str,
534319
artifact_format: SDKArtifactFormat
@@ -624,29 +409,6 @@ class Distribution:
624409
"unzip", "-q", bundlezip_path, "-d", os.path.dirname(bundle_path))
625410
return bundle_path
626411

627-
def unpack_toolchain(self, zip_tarball):
628-
tarball_name, tarball_path = self.unzip_artifact(zip_tarball)
629-
630-
# Remove the .tar.gz extension
631-
tarball_basename = os.path.splitext(
632-
os.path.splitext(tarball_name)[0])[0]
633-
tarball_output_dir = os.path.join(
634-
os.path.dirname(tarball_path), tarball_basename)
635-
if not os.path.exists(tarball_output_dir):
636-
os.makedirs(tarball_output_dir, exist_ok=True)
637-
print(f"Extracting {tarball_path}...")
638-
with tarfile.open(tarball_path, "r:gz") as tar:
639-
tar.extractall(tarball_output_dir)
640-
else:
641-
print(f"Tarball already extracted at {tarball_output_dir}")
642-
643-
dirents = os.listdir(tarball_output_dir)
644-
if len(dirents) != 1:
645-
raise Exception((
646-
f"Unexpected number of files in {tarball_output_dir}:"
647-
f" {len(dirents)} (expected 1)"))
648-
return os.path.join(tarball_output_dir, dirents[0])
649-
650412
async def download_artifact(self, artifact):
651413
if not os.path.exists(self.artifacts_dir):
652414
os.makedirs(self.artifacts_dir, exist_ok=True)
@@ -785,8 +547,7 @@ You can install Swift SDKs for WebAssembly using the following commands:
785547
artifacts = self.github.list_artifacts(self.run_id)
786548
for artifact in artifacts:
787549
artifact_name = artifact["name"]
788-
should_yield = artifact_name.endswith("-artifactbundle") or \
789-
artifact_name.endswith("-installable")
550+
should_yield = artifact_name.endswith("-artifactbundle")
790551
if should_yield:
791552
yield artifact
792553

@@ -830,18 +591,12 @@ def derive_platform_suffix_and_scheme(
830591
e.g.
831592
"main-wasm32-unknown-wasi-artifactbundle", scheme="main"
832593
-> [None, "main", "wasm32-unknown-wasi"]
833-
"macos_x86_64-main-artifactbundle", scheme="main"
834-
-> ["macos_x86_64", "main", "wasm32-unknown-wasi"]
835-
"ubuntu22.04_x86_64-installable", scheme="main"
836-
-> ["ubuntu22.04_x86_64", "main", "wasm32-unknown-wasi"]
837594
"""
838595

839596
# v3 artifact name: <scheme>-<target-triple>-artifactbundle
840-
# v2 artifact name: <platform-suffix>-<scheme>-(installable|artifactbundle)
841-
# v1 artifact name: <platform-suffix>-installable
842597
# Note that <scheme> can contain '-'.
843598
name: str = artifact_name
844-
artifact_suffixes = ("-installable", "-artifactbundle")
599+
artifact_suffixes = ("-artifactbundle")
845600
if not name.endswith(artifact_suffixes):
846601
raise Exception((f"Unexpected artifact name {name}"
847602
f", expected to have one of \"{artifact_suffixes}\""
@@ -857,14 +612,6 @@ def derive_platform_suffix_and_scheme(
857612
target_triple = rest[:-len("-artifactbundle")]
858613
return [None, target_scheme, target_triple]
859614

860-
components = name.split("-")
861-
if len(components) >= 3:
862-
scheme = "-".join(components[1:-1])
863-
return [components[0], scheme, "wasm32-unknown-wasi"]
864-
else:
865-
# Assume legacy representation only used for the main scheme
866-
return [components[0], "main", "wasm32-unknown-wasi"]
867-
868615

869616
def latest_success_run_id(gh: GitHub, workflow_name: str, branch: str, scheme: str):
870617
"""
@@ -879,7 +626,7 @@ def latest_success_run_id(gh: GitHub, workflow_name: str, branch: str, scheme: s
879626
artifacts = gh.list_artifacts(run["id"])
880627
for artifact in artifacts:
881628
artifact_name = artifact["name"]
882-
if not artifact_name.endswith("-installable") and not artifact_name.endswith("-artifactbundle"):
629+
if not artifact_name.endswith("-artifactbundle"):
883630
continue
884631
_, artifact_scheme, _ = derive_platform_suffix_and_scheme(artifact_name, scheme)
885632
if artifact_scheme == scheme:

0 commit comments

Comments
 (0)