From ebf79b502b9e2d02a9eb72eae7917f0b66922349 Mon Sep 17 00:00:00 2001 From: Chisanan232 Date: Fri, 29 May 2026 12:16:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20(ci):=20Install=20protoc=20i?= =?UTF-8?q?n=20maturin=20wheel=20builds=20(Linux=20+=20macOS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v0.0.1-alpha.2 dry-run surfaced this in the manylinux wheel build for x86_64 and aarch64: error: failed to run custom build command for `aa-proto v0.0.1 ...` Caused by: Could not find `protoc`. If `protoc` is installed, try setting the `PROTOC` environment variable to the path of the `protoc` binary. To install it on Debian, run `apt-get install protobuf-compiler`. `aa-proto` (a git dependency on agent-assembly) has a build.rs that uses prost-build, which requires the protoc compiler. The manylinux2014 image (CentOS 7-based; manylinux_2_28+ uses Rocky/Alma) and the GitHub macOS runners do not ship protoc by default. Fix: * Linux (manylinux: auto): `before-script-linux: yum install -y protobuf-compiler || dnf install ...` Runs inside the manylinux container before maturin invokes cargo. yum covers manylinux2014; dnf covers manylinux_2_28+. * macOS (macos-14 / macos-13 runners): A regular `run: brew install protobuf` step before the maturin-action invocation. macOS doesn't have docker, so before-script-linux is not applicable. Both x86_64 and aarch64 Linux variants, plus both macOS variants, are patched uniformly. Tracked: AAASM-2109 --- .github/workflows/release-python.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index 15531c0..b0e2c4c 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -74,6 +74,13 @@ jobs: command: build args: --release --out dist --interpreter ${{ env.PYTHON_VERSION }} manylinux: auto + # The manylinux2014 image (CentOS 7-based) lacks protoc; aa-proto's + # build.rs needs it via prost-build. Install before maturin runs. + before-script-linux: | + yum install -y protobuf-compiler || ( + # Fallback for manylinux_2_28+ (Rocky Linux / AlmaLinux based) + dnf install -y protobuf-compiler + ) - name: Upload wheel artifact uses: actions/upload-artifact@v7 with: @@ -108,6 +115,9 @@ jobs: command: build args: --release --out dist --interpreter ${{ env.PYTHON_VERSION }} manylinux: auto + # See linux-x86_64 above for rationale. + before-script-linux: | + yum install -y protobuf-compiler || dnf install -y protobuf-compiler - name: Upload wheel artifact uses: actions/upload-artifact@v7 with: @@ -135,6 +145,8 @@ jobs: else echo "::warning::aasm-macos-arm64 not yet published by $AASM_REPO — wheel will ship without bundled binary" fi + - name: Install protoc (macOS) + run: brew install protobuf - name: Build wheel uses: PyO3/maturin-action@v1 with: @@ -168,6 +180,8 @@ jobs: else echo "::warning::aasm-macos-x86_64 not yet published by $AASM_REPO — wheel will ship without bundled binary" fi + - name: Install protoc (macOS) + run: brew install protobuf - name: Build wheel uses: PyO3/maturin-action@v1 with: From b841666fa5cceb4044a8ffd5c72d66930f829f50 Mon Sep 17 00:00:00 2001 From: Chisanan232 Date: Fri, 29 May 2026 12:41:22 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=90=9B=20(ci):=20Use=20protoc=20binar?= =?UTF-8?q?y=20download=20instead=20of=20broken=20yum=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Local verification surfaced a bug in my prior fix: the CentOS 7-based manylinux2014 image's `protobuf-compiler` package ships protoc 2.5.0 which only supports proto2 syntax. aa-proto's .proto files use proto3, producing: test.proto:1:10: Unrecognized syntax identifier "proto3". This parser only recognizes "proto2". Fix: download the official protoc binary release (v32.1) from GitHub in the before-script-linux block instead of relying on the OS package. Works for both x86_64 and aarch64 manylinux variants. Verified locally inside `quay.io/pypa/manylinux2014_x86_64:latest`: * curl + unzip protoc-32.1-linux-x86_64.zip → libprotoc 32.1 * proto3 sample compile → ✓ OK The macOS step (`brew install protobuf`) was already correct — homebrew tracks latest protoc. Tracked: AAASM-2189 --- .github/workflows/release-python.yml | 40 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index b0e2c4c..478c148 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -75,12 +75,25 @@ jobs: args: --release --out dist --interpreter ${{ env.PYTHON_VERSION }} manylinux: auto # The manylinux2014 image (CentOS 7-based) lacks protoc; aa-proto's - # build.rs needs it via prost-build. Install before maturin runs. + # build.rs needs it via prost-build for proto3 syntax. The yum/dnf + # `protobuf-compiler` package on CentOS 7 ships protoc 2.5.0 which + # ONLY understands proto2 ("Unrecognized syntax identifier 'proto3'"), + # so we download the official protoc binary release instead. before-script-linux: | - yum install -y protobuf-compiler || ( - # Fallback for manylinux_2_28+ (Rocky Linux / AlmaLinux based) - dnf install -y protobuf-compiler - ) + set -euo pipefail + (command -v unzip >/dev/null) || (yum install -y unzip || dnf install -y unzip) + PROTOC_VERSION="32.1" + ARCH=$(uname -m) + case "$ARCH" in + x86_64) PROTOC_ARCH="x86_64" ;; + aarch64) PROTOC_ARCH="aarch_64" ;; + *) echo "::error::unsupported manylinux arch: $ARCH"; exit 1 ;; + esac + curl -sSLf \ + "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" \ + -o /tmp/protoc.zip + unzip -o /tmp/protoc.zip -d /usr/local >/dev/null + protoc --version - name: Upload wheel artifact uses: actions/upload-artifact@v7 with: @@ -115,9 +128,22 @@ jobs: command: build args: --release --out dist --interpreter ${{ env.PYTHON_VERSION }} manylinux: auto - # See linux-x86_64 above for rationale. + # See linux-x86_64 above for rationale. Same protoc binary download. before-script-linux: | - yum install -y protobuf-compiler || dnf install -y protobuf-compiler + set -euo pipefail + (command -v unzip >/dev/null) || (yum install -y unzip || dnf install -y unzip) + PROTOC_VERSION="32.1" + ARCH=$(uname -m) + case "$ARCH" in + x86_64) PROTOC_ARCH="x86_64" ;; + aarch64) PROTOC_ARCH="aarch_64" ;; + *) echo "::error::unsupported manylinux arch: $ARCH"; exit 1 ;; + esac + curl -sSLf \ + "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" \ + -o /tmp/protoc.zip + unzip -o /tmp/protoc.zip -d /usr/local >/dev/null + protoc --version - name: Upload wheel artifact uses: actions/upload-artifact@v7 with: From e1b0424272a8a966d41bafcc463c85633d0f35a4 Mon Sep 17 00:00:00 2001 From: Chisanan232 Date: Mon, 1 Jun 2026 12:44:52 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=92=20(ci):=20Harden=20protoc=20do?= =?UTF-8?q?wnload=20with=20SHA256=20verification=20+=20retry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supply-chain hardening per senior code review: * SHA256 verification: refuse to install protoc if the downloaded zip doesn't match the expected SHA256 (cross-verified against the GitHub release API's `digest` field on v32.1 assets). * Retry: --retry 3 --retry-delay 5 on curl so a single network blip doesn't fail the build. * Centralized env: PROTOC_VERSION + PROTOC_SHA256_X86_64 + PROTOC_SHA256_AARCH_64 all at workflow level. Bumping protoc is one edit (update version + 2 SHAs at the top). * GH expression interpolation (`${{ env.X }}`) instead of shell `$VAR` references. Substitutes at workflow-parse time before the script reaches the manylinux container, so we don't rely on maturin-action propagating env vars through `docker run`. Without this gate, the previous commit downloaded an arbitrary binary and ran it as root inside CI with no integrity check. Verified locally end-to-end in quay.io/pypa/manylinux2014_x86_64: * good SHA → install succeeds, protoc --version returns libprotoc 32.1 * tampered zip → rejected before install (exit 1, no execution) * bad SHA in script → exit 1, no install SHAs: protoc-32.1-linux-x86_64.zip : e9c129c176bb7df02546c4cd6185126ca53c89e7d2f09511e209319704b5dd7e protoc-32.1-linux-aarch_64.zip: 4a802ed23d70f7bad7eb19e5a3e724b3aa967250d572cadfd537c1ba939aee6a (macOS path remains brew install protobuf — that's a separate trust boundary handled by homebrew's own signing model. Further hardening to also use a binary download on macOS is a follow-up if needed.) Tracked: AAASM-2189 --- .github/workflows/release-python.yml | 36 +++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index 478c148..402f51c 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -25,6 +25,12 @@ env: # inside the wheel (matches runtime.py's WHEEL_BUNDLED_BIN search path). AASM_BINARY_RELEASE_REPO: AI-agent-assembly/agent-assembly PYTHON_VERSION: '3.12' + # protoc binary version + per-arch SHA256 sums (cross-verified against + # the GitHub release API's `digest:` field on the v32.1 release assets). + # Bump in one place when upgrading protoc. + PROTOC_VERSION: '32.1' + PROTOC_SHA256_X86_64: 'e9c129c176bb7df02546c4cd6185126ca53c89e7d2f09511e209319704b5dd7e' + PROTOC_SHA256_AARCH_64: '4a802ed23d70f7bad7eb19e5a3e724b3aa967250d572cadfd537c1ba939aee6a' jobs: build-sdist: @@ -79,19 +85,25 @@ jobs: # `protobuf-compiler` package on CentOS 7 ships protoc 2.5.0 which # ONLY understands proto2 ("Unrecognized syntax identifier 'proto3'"), # so we download the official protoc binary release instead. + # + # SECURITY: the zip is downloaded over HTTPS from GitHub's release + # CDN AND verified against a hardcoded SHA256 cross-checked against + # the GitHub release API's `digest` field. Without the SHA check we'd + # be installing an arbitrary binary as root with no integrity gate. before-script-linux: | set -euo pipefail (command -v unzip >/dev/null) || (yum install -y unzip || dnf install -y unzip) - PROTOC_VERSION="32.1" ARCH=$(uname -m) case "$ARCH" in - x86_64) PROTOC_ARCH="x86_64" ;; - aarch64) PROTOC_ARCH="aarch_64" ;; + x86_64) PROTOC_ARCH="x86_64"; EXPECTED_SHA="${{ env.PROTOC_SHA256_X86_64 }}" ;; + aarch64) PROTOC_ARCH="aarch_64"; EXPECTED_SHA="${{ env.PROTOC_SHA256_AARCH_64 }}" ;; *) echo "::error::unsupported manylinux arch: $ARCH"; exit 1 ;; esac - curl -sSLf \ - "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" \ + curl -sSLf --retry 3 --retry-delay 5 \ + "https://github.com/protocolbuffers/protobuf/releases/download/v${{ env.PROTOC_VERSION }}/protoc-${{ env.PROTOC_VERSION }}-linux-${PROTOC_ARCH}.zip" \ -o /tmp/protoc.zip + echo "${EXPECTED_SHA} /tmp/protoc.zip" | sha256sum --check --status \ + || { echo "::error::protoc-${{ env.PROTOC_VERSION }}-linux-${PROTOC_ARCH}.zip SHA256 mismatch — refusing to install"; sha256sum /tmp/protoc.zip; exit 1; } unzip -o /tmp/protoc.zip -d /usr/local >/dev/null protoc --version - name: Upload wheel artifact @@ -128,20 +140,22 @@ jobs: command: build args: --release --out dist --interpreter ${{ env.PYTHON_VERSION }} manylinux: auto - # See linux-x86_64 above for rationale. Same protoc binary download. + # See linux-x86_64 above for rationale + security model. Same + # SHA-verified protoc binary download. before-script-linux: | set -euo pipefail (command -v unzip >/dev/null) || (yum install -y unzip || dnf install -y unzip) - PROTOC_VERSION="32.1" ARCH=$(uname -m) case "$ARCH" in - x86_64) PROTOC_ARCH="x86_64" ;; - aarch64) PROTOC_ARCH="aarch_64" ;; + x86_64) PROTOC_ARCH="x86_64"; EXPECTED_SHA="${{ env.PROTOC_SHA256_X86_64 }}" ;; + aarch64) PROTOC_ARCH="aarch_64"; EXPECTED_SHA="${{ env.PROTOC_SHA256_AARCH_64 }}" ;; *) echo "::error::unsupported manylinux arch: $ARCH"; exit 1 ;; esac - curl -sSLf \ - "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" \ + curl -sSLf --retry 3 --retry-delay 5 \ + "https://github.com/protocolbuffers/protobuf/releases/download/v${{ env.PROTOC_VERSION }}/protoc-${{ env.PROTOC_VERSION }}-linux-${PROTOC_ARCH}.zip" \ -o /tmp/protoc.zip + echo "${EXPECTED_SHA} /tmp/protoc.zip" | sha256sum --check --status \ + || { echo "::error::protoc-${{ env.PROTOC_VERSION }}-linux-${PROTOC_ARCH}.zip SHA256 mismatch — refusing to install"; sha256sum /tmp/protoc.zip; exit 1; } unzip -o /tmp/protoc.zip -d /usr/local >/dev/null protoc --version - name: Upload wheel artifact