From 389400c2c881c379086295a2417ad0b6b48aeefb Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 21 Oct 2026 04:18:46 +0900 Subject: [PATCH 1/5] ci: prepare isolation and verify exact released versions --- .github/tools/check_version_pins.sh | 2 +- .github/tools/run_published_arm64_cn.sh | 12 ++-- .github/workflows/ci-arm64-published-cn.yml | 4 +- .github/workflows/ci-fresh-install.yml | 47 +++++++++++-- .github/workflows/ci.yml | 1 + .../test_release_install_verification.py | 69 +++++++++++++++++++ 6 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 tests/scripts/test_release_install_verification.py diff --git a/.github/tools/check_version_pins.sh b/.github/tools/check_version_pins.sh index aa6e3ced6..7ec089b66 100755 --- a/.github/tools/check_version_pins.sh +++ b/.github/tools/check_version_pins.sh @@ -123,7 +123,7 @@ done # literal: if grep -qE "MCPP_PIN:[[:space:]]*['\"]?[0-9]" .github/workflows/ci-fresh-install.yml; then bad "ci-fresh-install.yml hardcodes MCPP_PIN again — it must stay derived from - wait-index's releases-API lookup, or the index guard and the install jobs + resolve-version's releases-API lookup, or the index guard and the install jobs can once more disagree about which version is under test (#265)" fi diff --git a/.github/tools/run_published_arm64_cn.sh b/.github/tools/run_published_arm64_cn.sh index 2114900f8..40863af34 100755 --- a/.github/tools/run_published_arm64_cn.sh +++ b/.github/tools/run_published_arm64_cn.sh @@ -3,7 +3,7 @@ set -euo pipefail version=${1:?exact published mcpp version} repo=${2:?checkout holding these tools and the canonical client pin} -backend=${3:-proot} +backend=${3:-bwrap} [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || exit 2 [[ "$(uname -m)" == aarch64 ]] || exit 2 [[ "$backend" == proot || "$backend" == bwrap ]] || exit 2 @@ -43,17 +43,17 @@ xl="$base/bootstrap/xlings-$xl_version-linux-aarch64/bin/xlings" "$xl" update cp "$base/data/xim-pkgindex/.xlings-index-cache.json" "$base/reports/outer-published-index.json" # Native backend is provided by distro infrastructure, never labeled an xim -# ARM package. The published bwrap package is x86-only. The client locates the -# system proot directly; bwrap's current locator needs this explicit private -# system-backend directory. Record the symlink and actual distro version. +# ARM package. Record its distro version and use the published client's +# documented isolation setup, which prepares a root-owned bwrap and a narrow +# AppArmor profile when needed, without disabling the host's restriction. backend_package="$backend" [[ "$backend" != bwrap ]] || backend_package=bubblewrap dpkg-query -W "$backend_package" | tee "$base/reports/backend-version.txt" command -v "$backend" | tee "$base/reports/backend-path.txt" sha256sum "$(command -v "$backend")" > "$base/reports/backend.sha256" if [[ "$backend" == bwrap ]]; then - mkdir -p "$base/data/xpkgs/xim-x-bwrap/ci-system-backend/bin" - ln -s /usr/bin/bwrap "$base/data/xpkgs/xim-x-bwrap/ci-system-backend/bin/bwrap" + "$xl" self doctor --isolation --fix -y | tee "$base/reports/isolation-doctor.txt" + "$xl" self doctor --isolation --json > "$base/reports/isolation-doctor.json" fi # Independently prove the exact mcpp archive is available through public CN. mcpp_archive="mcpp-$version-linux-aarch64.tar.gz" diff --git a/.github/workflows/ci-arm64-published-cn.yml b/.github/workflows/ci-arm64-published-cn.yml index 59c036051..c6a40a7ed 100644 --- a/.github/workflows/ci-arm64-published-cn.yml +++ b/.github/workflows/ci-arm64-published-cn.yml @@ -10,8 +10,8 @@ on: description: Native distro backend used only as CI isolation infrastructure required: true type: choice - default: proot - options: [proot, bwrap] + default: bwrap + options: [bwrap, proot] permissions: contents: read concurrency: diff --git a/.github/workflows/ci-fresh-install.yml b/.github/workflows/ci-fresh-install.yml index 4935b8e7e..88e3594ac 100644 --- a/.github/workflows/ci-fresh-install.yml +++ b/.github/workflows/ci-fresh-install.yml @@ -67,10 +67,10 @@ jobs: # Convert the race into a bounded wait: poll the index's mcpp.lua until # it carries the released version (<=15 min), then let every job run. # Non-workflow_run triggers (manual, cron, PR) skip the wait. - wait-index: + resolve-version: runs-on: ubuntu-latest if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} - timeout-minutes: 20 + timeout-minutes: 5 outputs: version: ${{ steps.resolve.outputs.version }} steps: @@ -91,10 +91,19 @@ jobs: esac echo "version=$VER" >> "$GITHUB_OUTPUT" echo "version under test: $VER" + + wait-index: + needs: resolve-version + runs-on: ubuntu-latest + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + timeout-minutes: 20 + outputs: + version: ${{ needs.resolve-version.outputs.version }} + steps: - name: Wait for the PUBLISHED index artifact to track the released mcpp if: ${{ github.event_name == 'workflow_run' }} env: - VER: ${{ steps.resolve.outputs.version }} + VER: ${{ needs.resolve-version.outputs.version }} run: | # Poll the ARTIFACT, not the git file. # @@ -537,7 +546,10 @@ jobs: # from BOTH sides: refused before `brew trust`, accepted after. macos-brew-fresh: name: macOS fresh install (Homebrew, ${{ matrix.image }}) + needs: resolve-version if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + env: + MCPP_PIN: ${{ needs.resolve-version.outputs.version }} # Same two images as macos-fresh: the formula declares `depends_on macos: # :sonoma` + arm64, macos-14 is the oldest image satisfying it, and # xcode-27 is macOS 27, the newest release. @@ -561,6 +573,27 @@ jobs: [ "$(sw_vers -productVersion | cut -d. -f1)" = 27 ] || { echo "::error::xcode-27 delivered macOS $(sw_vers -productVersion), not 27"; exit 1; } fi + # The tap's update is asynchronous, independently of the xlings index. + # Read its published formula without tapping, so the one-liner below + # still exercises a machine that has never added this tap. + - name: Wait for the tap to carry the version under test + run: | + set -euo pipefail + deadline=$((SECONDS + 600)) + ready=false + while (( SECONDS < deadline )); do + formula=$(curl -fsSL --retry 2 --retry-all-errors --max-time 30 \ + https://raw.githubusercontent.com/mcpp-community/homebrew-mcpp/main/Formula/mcpp-m.rb 2>/dev/null || true) + version=$(printf '%s\n' "$formula" | sed -nE 's/^[[:space:]]*version "([^"]+)".*/\1/p' | head -1) + if [ "$version" = "$MCPP_PIN" ]; then + ready=true + break + fi + echo "Waiting for tap: expected $MCPP_PIN, observed ${version:-unavailable}" + sleep 15 + done + [ "$ready" = true ] || { echo "::error::the tap never published mcpp $MCPP_PIN"; exit 1; } + # ① The command README.md documents, on a machine that has never tapped. # Fully qualified, so Homebrew treats it as explicit intent. - name: "Documented one-liner installs" @@ -570,8 +603,8 @@ jobs: # runtime, so a bare symlink into the Cellar would make MCPP_HOME the # versioned Cellar dir and `brew upgrade` would drop every installed # toolchain. Assert the binary on PATH is brew's and reports the - # version the FORMULA declares — not a hardcoded one, which would go - # stale on every release. + # exact release selected for every installation job. Agreement with + # an old formula alone does not validate the new release. - name: "Installed binary is brew's, and agrees with the formula" run: | set -euo pipefail @@ -583,8 +616,9 @@ jobs: formula_version="$(brew info --json=v2 mcpp-community/mcpp/mcpp-m \ | python3 -c 'import json,sys; print(json.load(sys.stdin)["formulae"][0]["versions"]["stable"])')" echo "formula declares: $formula_version" + test "$formula_version" = "$MCPP_PIN" mcpp --version - mcpp --version | grep -Fq "$formula_version" + test "$(mcpp --version)" = "mcpp $MCPP_PIN" # ③ THE TRUST GATE, from the failing side first. # @@ -621,6 +655,7 @@ jobs: brew uninstall --force mcpp-m brew install mcpp-community/mcpp/mcpp # the `mcpp` alias brew upgrade mcpp-m || true # no-op when current; must not be refused + test "$(mcpp --version)" = "mcpp $MCPP_PIN" # ⑤ The only assertion a user actually cares about: it builds and runs. # Exercises the launcher's MCPP_HOME/MCPP_VENDORED_XLINGS pinning, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d3d1afbc..d3e92dc49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,6 +114,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: | python3 tests/scripts/test_check_workflow_assertions.py + python3 tests/scripts/test_release_install_verification.py python3 .github/tools/check_workflow_assertions.py --check-open - name: The release canary runner runs each command under the named bash diff --git a/tests/scripts/test_release_install_verification.py b/tests/scripts/test_release_install_verification.py new file mode 100644 index 000000000..666410f60 --- /dev/null +++ b/tests/scripts/test_release_install_verification.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Run the real Homebrew verification step against controlled command results. + +An old formula and its matching old binary must not validate a newer release. +""" +from __future__ import annotations + +import importlib.util +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[2] +WORKFLOW = ROOT / ".github/workflows/ci-fresh-install.yml" +spec = importlib.util.spec_from_file_location( + "release_ci_assertions", ROOT / ".github/tools/check_workflow_assertions.py" +) +parser = importlib.util.module_from_spec(spec) +sys.modules[spec.name] = parser +spec.loader.exec_module(parser) + + +def run_guard(formula: str, binary: str) -> subprocess.CompletedProcess[str]: + workflow = parser.parse(WORKFLOW) + job = next(j for j in workflow.jobs if j.key == "macos-brew-fresh") + step = next(s for s in job.steps if s.name.startswith("Installed binary is brew's")) + with tempfile.TemporaryDirectory() as directory: + prefix = Path(directory) / "brew" + bins = prefix / "bin" + bins.mkdir(parents=True) + (bins / "brew").write_text(r'''#!/bin/sh +case "$1" in + --prefix) printf '%s\n' "$CI_STUB_PREFIX" ;; + info) printf '{"formulae":[{"versions":{"stable":"%s"}}]}\n' "$CI_STUB_FORMULA" ;; + *) exit 99 ;; +esac +''') + (bins / "mcpp").write_text(r'''#!/bin/sh +[ "$1" = --version ] || exit 99 +printf 'mcpp %s\n' "$CI_STUB_BINARY" +''') + for name in ("brew", "mcpp"): + (bins / name).chmod(0o755) + env = dict(os.environ, PATH=str(bins) + os.pathsep + os.environ["PATH"], + CI_STUB_PREFIX=str(prefix), CI_STUB_FORMULA=formula, + CI_STUB_BINARY=binary, MCPP_PIN="2026.10.21.1") + return subprocess.run(["bash", "-c", step.run], env=env, + capture_output=True, text=True, check=False) + + +class ReleasedHomebrewVersion(unittest.TestCase): + def test_matching_old_formula_and_binary_do_not_validate_the_new_release(self): + result = run_guard("2026.10.19.1", "2026.10.19.1") + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_the_requested_release_passes(self): + result = run_guard("2026.10.21.1", "2026.10.21.1") + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + + def test_a_wrong_binary_is_rejected_even_with_the_new_formula(self): + result = run_guard("2026.10.21.1", "2026.10.19.1") + self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr) + + +if __name__ == "__main__": + unittest.main() From 8c975656ab84513e83908639650b59a1b0c28552 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 21 Oct 2026 04:20:23 +0900 Subject: [PATCH 2/5] ci: keep Homebrew upgrade failures visible --- .github/workflows/ci-fresh-install.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-fresh-install.yml b/.github/workflows/ci-fresh-install.yml index 88e3594ac..bfe7f28cf 100644 --- a/.github/workflows/ci-fresh-install.yml +++ b/.github/workflows/ci-fresh-install.yml @@ -654,7 +654,7 @@ jobs: brew install mcpp-m # short form brew uninstall --force mcpp-m brew install mcpp-community/mcpp/mcpp # the `mcpp` alias - brew upgrade mcpp-m || true # no-op when current; must not be refused + brew upgrade mcpp-m # no-op when current; must not be refused test "$(mcpp --version)" = "mcpp $MCPP_PIN" # ⑤ The only assertion a user actually cares about: it builds and runs. From b9fb81f22a59274cfc3e334cd475c01402fc7dae Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 21 Oct 2026 04:32:31 +0900 Subject: [PATCH 3/5] ci: keep released consumers in the SubOS-owned workspace --- .../check_published_arm64_cn_ecosystem.sh | 19 +++++++++++++++---- .github/tools/run_published_arm64_cn.sh | 15 ++++++++++----- .github/workflows/ci-arm64-published-cn.yml | 10 +++++----- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.github/tools/check_published_arm64_cn_ecosystem.sh b/.github/tools/check_published_arm64_cn_ecosystem.sh index 7b5680767..0fb4bf5cd 100755 --- a/.github/tools/check_published_arm64_cn_ecosystem.sh +++ b/.github/tools/check_published_arm64_cn_ecosystem.sh @@ -3,17 +3,27 @@ set -euo pipefail phase="${1:?usage: ecosystem-cn.sh release VERSION}" version="${2:?mcpp version under test required}" -base="${XLINGS_HOME:?explicit isolated XLINGS_HOME required}" +controller="${XLINGS_HOME:?explicit isolated XLINGS_HOME required}" +probes="${CN_PROBE_ROOT:?instance-owned probe root required}" +[[ "$probes" == "$controller/subos/cn-arm64-published/probes" ]] || exit 1 +base="$probes/client-home" +[[ ! -e "$base" ]] || { echo 'consumer client home must be cold'; exit 1; } [[ "$(uname -m)" == aarch64 ]] || { echo "native ARM64 required"; exit 1; } [[ "$phase" == release ]] || { echo "published release only"; exit 1; } [[ ! -d "${CN_HOST_CHECKOUT:?host checkout path required}" ]] || { echo 'host checkout must not be visible in the SubOS'; exit 1; } xl="${CN_PUBLISHED_XLINGS:?published client path required}" -work="${CN_PROBE_RUN_DIR:-$base/probes/runs/$phase-$version-$(date +%Y%m%dT%H%M%S)}" -[[ "$work" == "$base/probes/runs/"* ]] || exit 1 +work="${CN_PROBE_RUN_DIR:-$probes/runs/$phase-$version-$(date +%Y%m%dT%H%M%S)}" +[[ "$work" == "$probes/runs/"* ]] || exit 1 mkdir -p "$work" exec > >(tee -a "$work/probe.log") 2>&1 +export XLINGS_HOME="$base" +# A fresh client inside the namespace must not inherit its controller's +# project, active instance, or shim dispatch context. Filesystem isolation +# remains enforced by the already-entered SubOS, including the check above. +unset XLINGS_PROJECT_DIR XLINGS_ACTIVE_SUBOS XLINGS_ROOT_INSTANCE XLINGS_ROOT_LOGIN +unset XLINGS_SHIM_DEPTH XLINGS_SUBOS_LIB XLINGS_BIN printf 'phase=%s version=%s XLINGS_HOME=%s sandbox_HOME=%s\n' "$phase" "$version" "$base" "$HOME" cat /proc/self/mountinfo > "$work/subos-mountinfo.txt" export MCPP_HOME="$work/mcpp-home" @@ -21,6 +31,7 @@ export MCPP_VENDORED_XLINGS="$xl" export MCPP_E2E_MIRROR=CN MCPP_E2E_LLVM_VERSION=23.1.3 MCPP_E2E_EXPECT_ARCH=aarch64 unset LD_LIBRARY_PATH LD_PRELOAD MCPP_TOOLCHAIN "$xl" config --mirror CN +"$xl" update "$xl" install "mcpp@$version" -g -y -u MCPP="$base/data/xpkgs/xim-x-mcpp/$version/bin/mcpp" [[ -x "$MCPP" ]] || { echo "mcpp not executable: $MCPP"; exit 1; } @@ -157,5 +168,5 @@ for target in x86_64-linux-gnu aarch64-macos x86_64-windows-gnu; do done echo 'RELEASE BUILD PASS: CN install/default/new/build/run/pack, native openkal, four consumers and three target artifacts.' cp "$work/openkal-source-sha.txt" "$work/cross/source-sha.txt" -printf '%s\n' "$work" > "$base/probes/last-run.txt" +printf '%s\n' "$work" > "$probes/last-run.txt" echo 'Foreign target execution is pending the three target-system jobs.' diff --git a/.github/tools/run_published_arm64_cn.sh b/.github/tools/run_published_arm64_cn.sh index 40863af34..819e7e28d 100755 --- a/.github/tools/run_published_arm64_cn.sh +++ b/.github/tools/run_published_arm64_cn.sh @@ -9,7 +9,7 @@ backend=${3:-bwrap} [[ "$backend" == proot || "$backend" == bwrap ]] || exit 2 base=${XLINGS_HOME:?cold isolated home required} [[ ! -e "$base" ]] || { echo 'home must be cold'; exit 1; } -mkdir -p "$base/bootstrap" "$base/probes" "$base/reports" +mkdir -p "$base/bootstrap" "$base/reports" cd "$base" # Derive the client version from the repository's existing single pin. xl_version=$(python3 - "$repo/src/provider/xlings/xlings.cppm" <<'PY' @@ -69,15 +69,20 @@ mcpp_binary_sha=$(sha256sum "${archive_binaries[0]}" | cut -d ' ' -f 1) printf '%s\n' "$mcpp_binary_sha" > "$base/reports/mcpp-cn-binary.sha256" "$xl" subos new cn-arm64-published "$xl" subos runtime glibc@2.44.3 cn-arm64-published -cp "$repo/.github/tools/check_published_arm64_cn_ecosystem.sh" "$base/probes/ecosystem.sh" -printf -v command 'CN_HOST_CHECKOUT=%q CN_EXPECTED_BINARY_SHA=%q CN_PUBLISHED_XLINGS=%q bash %q release %q' "$repo" "$mcpp_binary_sha" "$xl" "$base/probes/ecosystem.sh" "$version" +# The controller home is read-only inside a real SubOS. The selected instance +# owns its writable workspace; its consumer uses a separate cold client home. +probes="$base/subos/cn-arm64-published/probes" +mkdir -p "$probes" +cp "$repo/.github/tools/check_published_arm64_cn_ecosystem.sh" "$probes/ecosystem.sh" +printf -v command 'CN_HOST_CHECKOUT=%q CN_EXPECTED_BINARY_SHA=%q CN_PUBLISHED_XLINGS=%q CN_PROBE_ROOT=%q bash %q release %q' "$repo" "$mcpp_binary_sha" "$xl" "$probes" "$probes/ecosystem.sh" "$version" "$xl" subos use cn-arm64-published --sandbox "$backend" --cmd "$command" -work=$(cat "$base/probes/last-run.txt") -[[ "$work" == "$base/probes/runs/"* ]] || exit 1 +work=$(cat "$probes/last-run.txt") +[[ "$work" == "$probes/runs/"* ]] || exit 1 cmp "$base/reports/release-tag-sha.txt" "$work/mcpp-source-sha.txt" cp "$base/reports/release-tag-sha.txt" "$work/cross/engine-release-sha.txt" cp "$work/mcpp-home/registry/data/xim-pkgindex/.xlings-index-cache.json" "$base/reports/inner-published-index.json" cp "$work/mcpp-home/registry/.xlings.json" "$base/reports/inner-config.json" +cp "$probes/client-home/.xlings.json" "$base/reports/consumer-client-config.json" cp "$base/.xlings.json" "$base/reports/outer-config.json" echo "CN_REPORT=$base/reports" >> "$GITHUB_ENV" echo "CN_CONSUMER_REPORT=$work" >> "$GITHUB_ENV" diff --git a/.github/workflows/ci-arm64-published-cn.yml b/.github/workflows/ci-arm64-published-cn.yml index c6a40a7ed..84246c474 100644 --- a/.github/workflows/ci-arm64-published-cn.yml +++ b/.github/workflows/ci-arm64-published-cn.yml @@ -56,11 +56,11 @@ jobs: ${{ env.XLINGS_HOME }}/reports/*.json ${{ env.XLINGS_HOME }}/reports/*.txt ${{ env.XLINGS_HOME }}/reports/*.sha256 - ${{ env.XLINGS_HOME }}/probes/runs/*/probe.log - ${{ env.XLINGS_HOME }}/probes/runs/*/*.txt - ${{ env.XLINGS_HOME }}/probes/runs/*/*.sha256 - ${{ env.XLINGS_HOME }}/probes/runs/*/*.log - ${{ env.XLINGS_HOME }}/probes/runs/*/members.tsv + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/probe.log + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.txt + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.sha256 + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.log + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/members.tsv if-no-files-found: warn target-run: needs: consume From d66ddde626d34700e78ad3839ab6c15ffa33e540 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 21 Oct 2026 04:42:37 +0900 Subject: [PATCH 4/5] ci: assert structured ARM default toolchain facts --- .../tools/check_published_arm64_cn_ecosystem.sh | 16 ++++++++++++++-- .github/workflows/ci-arm64-published-cn.yml | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/tools/check_published_arm64_cn_ecosystem.sh b/.github/tools/check_published_arm64_cn_ecosystem.sh index 0fb4bf5cd..f9e1764e4 100755 --- a/.github/tools/check_published_arm64_cn_ecosystem.sh +++ b/.github/tools/check_published_arm64_cn_ecosystem.sh @@ -54,8 +54,20 @@ project="${CN_PROBE_PROJECT:-hello}" "$MCPP" new "$project" cd "$work/$project" "$MCPP" build 2>&1 | tee "$work/native-default-build.log" -grep -q 'Resolved llvm@23.1.3' "$work/native-default-build.log" -grep -Eq 'aarch64-(unknown-)?linux-gnu' "$work/native-default-build.log" +# Cold automatic provisioning and warm resolution have different progress +# messages. Assert the documented build facts instead of a human log banner. +"$MCPP" emit build-database --format json > "$work/native-build-database.json" +python3 - "$work/native-build-database.json" "$project" "$MCPP_HOME" <<'PYDEFAULT' +import json,pathlib,sys +envelope=json.load(open(sys.argv[1])) +assert envelope['kind']=='mcpp.build-database',envelope +database=envelope['data']['database'] +selected=next(s for s in database['sets'] if s['name']==sys.argv[2]) +toolchain=database['ide']['toolchains'][selected['ide']['toolchain']] +assert toolchain['family']=='clang' and toolchain['version']=='23.1.3',toolchain +assert toolchain['target'] in ('aarch64-linux-gnu','aarch64-unknown-linux-gnu'),toolchain +pathlib.Path(toolchain['driver']).resolve().relative_to(pathlib.Path(sys.argv[3]).resolve()) +PYDEFAULT mapfile -t native_bins < <(find target -type f -path "*/bin/$project") [[ "${#native_bins[@]}" == 1 ]] || exit 1 readelf -hW "${native_bins[0]}" | tee "$work/native-header.txt" diff --git a/.github/workflows/ci-arm64-published-cn.yml b/.github/workflows/ci-arm64-published-cn.yml index 84246c474..1ca49acd8 100644 --- a/.github/workflows/ci-arm64-published-cn.yml +++ b/.github/workflows/ci-arm64-published-cn.yml @@ -58,6 +58,7 @@ jobs: ${{ env.XLINGS_HOME }}/reports/*.sha256 ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/probe.log ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.txt + ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.json ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.sha256 ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/*.log ${{ env.XLINGS_HOME }}/subos/cn-arm64-published/probes/runs/*/members.tsv From 6f51b9ebe1518cfc12341c9370daec96e3dfe864 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 21 Oct 2026 04:53:08 +0900 Subject: [PATCH 5/5] ci: use the native macOS artifact checksum tool --- .github/workflows/ci-arm64-published-cn.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-arm64-published-cn.yml b/.github/workflows/ci-arm64-published-cn.yml index 1ca49acd8..f0fdfa5b3 100644 --- a/.github/workflows/ci-arm64-published-cn.yml +++ b/.github/workflows/ci-arm64-published-cn.yml @@ -91,7 +91,11 @@ jobs: run: | set -euo pipefail cd art - sha256sum -c SHA256SUMS + if [ "$TARGET_SYSTEM" = macos ]; then + shasum -a 256 -c SHA256SUMS + else + sha256sum -c SHA256SUMS + fi grep -Eq '^[0-9a-f]{40}$' source-sha.txt grep -Eq '^[0-9a-f]{40}$' engine-release-sha.txt grep -Eq '^[0-9a-f]{40}$' index-source-sha.txt