mirror of
https://github.com/SideStore/SideStore.git
synced 2026-03-27 21:05:39 +01:00
CI: full rewrite - moved logic into ci.py and kept workflow scripts mostly dummy
This commit is contained in:
255
scripts/ci.py
Normal file
255
scripts/ci.py
Normal file
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# helpers
|
||||
# ----------------------------------------------------------
|
||||
|
||||
def run(cmd, check=True):
|
||||
print(f"$ {cmd}", flush=True)
|
||||
subprocess.run(cmd, shell=True, cwd=ROOT, check=check)
|
||||
|
||||
|
||||
def output(name, value):
|
||||
print(f"{name}={value}")
|
||||
out = os.environ.get("GITHUB_OUTPUT")
|
||||
if out:
|
||||
with open(out, "a") as f:
|
||||
f.write(f"{name}={value}\n")
|
||||
|
||||
|
||||
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()
|
||||
|
||||
output("short_commit", sha)
|
||||
return sha
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# VERSION BUMP
|
||||
# ----------------------------------------------------------
|
||||
|
||||
def bump_beta():
|
||||
date = datetime.datetime.utcnow().strftime("%Y.%m.%d")
|
||||
release_channel = getenv("RELEASE_CHANNEL", "beta")
|
||||
|
||||
build_file = ROOT / "build_number.txt"
|
||||
xcconfig = ROOT / "Build.xcconfig"
|
||||
|
||||
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 '' 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()
|
||||
|
||||
output("version", v)
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# CLEAN
|
||||
# ----------------------------------------------------------
|
||||
def clean():
|
||||
run("make clean")
|
||||
clean_derived_data()
|
||||
|
||||
def clean_derived_data():
|
||||
run("rm -rf ~/Library/Developer/Xcode/DerivedData/*", 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):
|
||||
last = subprocess.check_output(
|
||||
"gh run list --branch $(git branch --show-current) "
|
||||
"--status success --json headSha --jq '.[0].headSha'",
|
||||
shell=True,
|
||||
cwd=ROOT
|
||||
).decode().strip()
|
||||
|
||||
if not last or last == "null":
|
||||
last = subprocess.check_output(
|
||||
"git rev-list --max-parents=0 HEAD",
|
||||
shell=True,
|
||||
cwd=ROOT
|
||||
).decode().strip()
|
||||
|
||||
run(f"python3 update_release_notes.py {last} {tag}")
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# PUBLISH SOURCE.JSON
|
||||
# ----------------------------------------------------------
|
||||
|
||||
def publish_apps(short_commit):
|
||||
repo = ROOT / "SideStore/apps-v2.json"
|
||||
|
||||
run("git config user.name 'GitHub Actions'", check=False)
|
||||
run("git config user.email 'github-actions@github.com'", check=False)
|
||||
|
||||
run("python3 scripts/update_apps.py './_includes/source.json'", check=False)
|
||||
|
||||
run("git add ./_includes/source.json", check=False)
|
||||
run(
|
||||
f"git commit -m ' - updated for {short_commit} deployment' || true",
|
||||
check=False
|
||||
)
|
||||
run("git push", check=False)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# ENTRYPOINT
|
||||
# ----------------------------------------------------------
|
||||
|
||||
def main():
|
||||
cmd = sys.argv[1]
|
||||
|
||||
if cmd == "commid-id":
|
||||
short_commit()
|
||||
|
||||
elif cmd == "bump-beta":
|
||||
bump_beta()
|
||||
|
||||
elif cmd == "version":
|
||||
extract_version()
|
||||
|
||||
elif cmd == "clean":
|
||||
clean()
|
||||
|
||||
elif cmd == "cleanDerivedData":
|
||||
clean_derived_data()
|
||||
|
||||
elif cmd == "build":
|
||||
build()
|
||||
|
||||
elif cmd == "tests-build":
|
||||
tests_build()
|
||||
|
||||
elif cmd == "tests-run":
|
||||
tests_run()
|
||||
|
||||
elif cmd == "encrypt-build":
|
||||
encrypt_logs("encrypted-build-logs")
|
||||
|
||||
elif cmd == "encrypt-tests-build":
|
||||
encrypt_logs("encrypted-tests-build-logs")
|
||||
|
||||
elif cmd == "encrypt-tests-run":
|
||||
encrypt_logs("encrypted-tests-run-logs")
|
||||
|
||||
elif cmd == "release-notes":
|
||||
release_notes(sys.argv[2])
|
||||
|
||||
elif cmd == "publish":
|
||||
publish_apps(sys.argv[2])
|
||||
|
||||
else:
|
||||
raise SystemExit(f"Unknown command {cmd}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user