mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-27 23:47:39 +01:00
238 lines
7.1 KiB
Python
238 lines
7.1 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import datetime
|
|
from pathlib import Path
|
|
|
|
# REPO ROOT relative to script dir
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# helpers
|
|
# ----------------------------------------------------------
|
|
|
|
def run(cmd, check=True):
|
|
print(f"$ {cmd}", flush=True)
|
|
subprocess.run(cmd, shell=True, cwd=ROOT, check=check)
|
|
print("", flush=True)
|
|
|
|
|
|
def getenv(name, default=""):
|
|
return os.environ.get(name, default)
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# SHARED
|
|
# ----------------------------------------------------------
|
|
|
|
def short_commit():
|
|
sha = subprocess.check_output(
|
|
"git rev-parse --short HEAD",
|
|
shell=True,
|
|
cwd=ROOT
|
|
).decode().strip()
|
|
return sha
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# VERSION BUMP
|
|
# ----------------------------------------------------------
|
|
|
|
def bump_beta():
|
|
date = datetime.datetime.now(datetime.UTC).strftime("%Y.%m.%d")
|
|
release_channel = getenv("RELEASE_CHANNEL", "beta")
|
|
build_file = ROOT / "build_number.txt"
|
|
|
|
short = subprocess.check_output(
|
|
"git rev-parse --short HEAD",
|
|
shell=True,
|
|
cwd=ROOT
|
|
).decode().strip()
|
|
|
|
def write(num):
|
|
run(
|
|
f"""sed -e "/MARKETING_VERSION = .*/s/$/-{release_channel}.{date}.{num}+{short}/" -i '' {ROOT}/Build.xcconfig"""
|
|
)
|
|
build_file.write_text(f"{date},{num}")
|
|
|
|
if not build_file.exists():
|
|
write(1)
|
|
return
|
|
|
|
last = build_file.read_text().strip().split(",")[1]
|
|
write(int(last) + 1)
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# VERSION EXTRACTION
|
|
# ----------------------------------------------------------
|
|
|
|
def extract_version():
|
|
v = subprocess.check_output(
|
|
"grep MARKETING_VERSION Build.xcconfig | sed -e 's/MARKETING_VERSION = //g'",
|
|
shell=True,
|
|
cwd=ROOT
|
|
).decode().strip()
|
|
return v
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# CLEAN
|
|
# ----------------------------------------------------------
|
|
def clean():
|
|
run("make clean")
|
|
|
|
def clean_derived_data():
|
|
run("rm -rf ~/Library/Developer/Xcode/DerivedData/*", check=False)
|
|
|
|
def clean_spm_cache():
|
|
run("rm -rf ~/Library/Caches/org.swift.swiftpm/*", check=False)
|
|
|
|
# ----------------------------------------------------------
|
|
# BUILD
|
|
# ----------------------------------------------------------
|
|
|
|
def build():
|
|
run("make clean")
|
|
run("rm -rf ~/Library/Developer/Xcode/DerivedData/*", check=False)
|
|
run("mkdir -p build/logs")
|
|
|
|
run(
|
|
"set -o pipefail && "
|
|
"NSUnbufferedIO=YES make -B build "
|
|
"2>&1 | tee -a build/logs/build.log | xcbeautify --renderer github-actions"
|
|
)
|
|
|
|
run("make fakesign | tee -a build/logs/build.log")
|
|
run("make ipa | tee -a build/logs/build.log")
|
|
|
|
run("zip -r -9 ./SideStore.dSYMs.zip ./SideStore.xcarchive/dSYMs")
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# TESTS BUILD
|
|
# ----------------------------------------------------------
|
|
|
|
def tests_build():
|
|
run("mkdir -p build/logs")
|
|
run(
|
|
"NSUnbufferedIO=YES make -B build-tests "
|
|
"2>&1 | tee -a build/logs/tests-build.log | xcbeautify --renderer github-actions"
|
|
)
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# TESTS RUN
|
|
# ----------------------------------------------------------
|
|
|
|
def tests_run():
|
|
run("mkdir -p build/logs")
|
|
run("nohup make -B boot-sim-async </dev/null >> build/logs/tests-run.log 2>&1 &")
|
|
|
|
run("make -B sim-boot-check | tee -a build/logs/tests-run.log")
|
|
|
|
run("make run-tests 2>&1 | tee -a build/logs/tests-run.log")
|
|
|
|
run("zip -r -9 ./test-results.zip ./build/tests")
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# LOG ENCRYPTION
|
|
# ----------------------------------------------------------
|
|
|
|
def encrypt_logs(name):
|
|
pwd = getenv("BUILD_LOG_ZIP_PASSWORD", "12345")
|
|
run(
|
|
f'cd build/logs && zip -e -P "{pwd}" ../../{name}.zip *'
|
|
)
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# RELEASE NOTES
|
|
# ----------------------------------------------------------
|
|
def release_notes(tag):
|
|
run(f"python3 generate_release_notes.py {tag}")
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# PUBLISH SOURCE.JSON
|
|
# ----------------------------------------------------------
|
|
def publish_apps(release_tag, short_commit):
|
|
repo = ROOT / "Dependencies/apps-v2.json"
|
|
|
|
if not repo.exists():
|
|
raise SystemExit("Dependencies/apps-v2.json repo missing")
|
|
|
|
# generate metadata + release notes
|
|
run(
|
|
f"python3 generate_source_metadata.py "
|
|
f"--release-tag {release_tag} "
|
|
f"--short-commit {short_commit}"
|
|
)
|
|
|
|
# update source.json using generated metadata
|
|
run("pushd Dependencies/apps-v2.json", check=False)
|
|
|
|
run("git config user.name 'GitHub Actions'", check=False)
|
|
run("git config user.email 'github-actions@github.com'", check=False)
|
|
|
|
run("python3 ../../scripts/update_source_metadata.py './_includes/source.json'")
|
|
|
|
run("git add --verbose ./_includes/source.json", check=False)
|
|
run(f"git commit -m ' - updated for {short_commit} deployment' || true",check=False)
|
|
run("git push --verbose", check=False)
|
|
|
|
run("popd", check=False)
|
|
|
|
# ----------------------------------------------------------
|
|
# ENTRYPOINT
|
|
# ----------------------------------------------------------
|
|
COMMANDS = {
|
|
"commid-id" : (short_commit, 0, ""),
|
|
"bump-beta" : (bump_beta, 0, ""),
|
|
"version" : (extract_version, 0, ""),
|
|
"clean" : (clean, 0, ""),
|
|
"clean-derived-data" : (clean_derived_data, 0, ""),
|
|
"clean-spm-cache" : (clean_spm_cache, 0, ""),
|
|
"build" : (build, 0, ""),
|
|
"tests-build" : (tests_build, 0, ""),
|
|
"tests-run" : (tests_run, 0, ""),
|
|
"encrypt-build" : (lambda: encrypt_logs("encrypted-build-logs"), 0, ""),
|
|
"encrypt-tests-build": (lambda: encrypt_logs("encrypted-tests-build-logs"), 0, ""),
|
|
"encrypt-tests-run" : (lambda: encrypt_logs("encrypted-tests-run-logs"), 0, ""),
|
|
"release-notes" : (release_notes, 1, "<tag>"),
|
|
"deploy" : (publish_apps, 2, "<release_tag> <short_commit>"),
|
|
}
|
|
|
|
def main():
|
|
def usage():
|
|
lines = ["Available commands:"]
|
|
for name, (_, argc, arg_usage) in COMMANDS.items():
|
|
suffix = f" {arg_usage}" if arg_usage else ""
|
|
lines.append(f" - {name}{suffix}")
|
|
return "\n".join(lines)
|
|
|
|
if len(sys.argv) < 2:
|
|
raise SystemExit(usage())
|
|
|
|
cmd = sys.argv[1]
|
|
|
|
if cmd not in COMMANDS:
|
|
raise SystemExit(
|
|
f"Unknown command '{cmd}'.\n\n{usage()}"
|
|
)
|
|
|
|
func, argc, arg_usage = COMMANDS[cmd]
|
|
|
|
if len(sys.argv) - 2 < argc:
|
|
suffix = f" {arg_usage}" if arg_usage else ""
|
|
raise SystemExit(f"Usage: workflow.py {cmd}{suffix}")
|
|
|
|
args = sys.argv[2:2 + argc]
|
|
func(*args) if argc else func()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |