From 43874233ae41a3dfe6482db59a7ad4918395e87b Mon Sep 17 00:00:00 2001 From: Nick DiZazzo <728690+ndizazzo@users.noreply.github.com> Date: Thu, 30 Jul 2026 07:34:12 -0400 Subject: [PATCH] fix(ci): route central workflow changes through SDK validation (#1121) --- .../manage-ci/references/current-inventory.md | 5 +++++ .github/actions/compute-changes/action.yml | 2 +- ci/ci.md | 4 ++++ scripts/tests/test_ci_artifact_actions.py | 20 ++++++++++++++----- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.agents/skills/manage-ci/references/current-inventory.md b/.agents/skills/manage-ci/references/current-inventory.md index 1deaee0b7..dfa24190a 100644 --- a/.agents/skills/manage-ci/references/current-inventory.md +++ b/.agents/skills/manage-ci/references/current-inventory.md @@ -116,6 +116,11 @@ results, duplicate plan entries, and required IDs outside its needs graph, making that one non-matrix check the workflow's stable branch-protection target. +Changes to the central PR/main/release workflow callers or to +`compute-changes` itself fail open to the SDK producer/smoke graph. This keeps +caller-owned mode, timeout, artifact, and trust-policy edits from skipping the +reusable Swift, Kotlin, or Rust SDK contracts they change. + Local actions: - `.github/actions/compute-changes` owns path, crate, backend, SDK, UI, website, diff --git a/.github/actions/compute-changes/action.yml b/.github/actions/compute-changes/action.yml index 3116055cd..3f13396c8 100644 --- a/.github/actions/compute-changes/action.yml +++ b/.github/actions/compute-changes/action.yml @@ -343,7 +343,7 @@ runs: if [[ "${{ inputs.event_name }}" == "workflow_dispatch" ]]; then SDK_SMOKE_REQUIRED="true" elif [[ -n "$CHANGED_FILES" ]]; then - DIRECT_SDK_INPUTS=$(echo "$CHANGED_FILES" | grep -E '(^sdk/|^Package\.swift$|^scripts/ci-(rust|kotlin|swift)-sdk-smoke\.sh$|^scripts/ci-prepare-native-runtime\.sh$|^scripts/ci-sdk-fixture\.sh$|^scripts/(check-sdk-contract|package-sdk-console-assets|restore-native-sdk-input|restore-static-abi-input|verify-sdk-console-assets|verify-swift-privacy-manifest|verify-swift-release-artifact|prepare-llama|build-llama)\.sh$|^scripts/(package-native-sdk|package-native-sdk-crate|verify-native-sdk-package|verify-checksum-sidecar|verify-static-abi-build-stamp|safe-extract-(tar|zip)|verify-swift-xcframework)\.(sh|py)$|^\.github/actions/(prepare-native-sdk-input|prepare-static-abi-input|resolve-native-toolchain-epoch|restore-smoke-inputs)/|^\.github/workflows/(native-sdk-artifact|sdk-smoke|static-abi-artifact|swift-sdk-artifact)\.yml$)' || true) + DIRECT_SDK_INPUTS=$(echo "$CHANGED_FILES" | grep -E '(^sdk/|^Package\.swift$|^scripts/ci-(rust|kotlin|swift)-sdk-smoke\.sh$|^scripts/ci-prepare-native-runtime\.sh$|^scripts/ci-sdk-fixture\.sh$|^scripts/(check-sdk-contract|package-sdk-console-assets|restore-native-sdk-input|restore-static-abi-input|verify-sdk-console-assets|verify-swift-privacy-manifest|verify-swift-release-artifact|prepare-llama|build-llama)\.sh$|^scripts/(package-native-sdk|package-native-sdk-crate|verify-native-sdk-package|verify-checksum-sidecar|verify-static-abi-build-stamp|safe-extract-(tar|zip)|verify-swift-xcframework)\.(sh|py)$|^\.github/actions/(compute-changes|prepare-native-sdk-input|prepare-static-abi-input|resolve-native-toolchain-epoch|restore-smoke-inputs)/|^\.github/workflows/(ci|native-sdk-artifact|pr_builds|release|sdk-smoke|static-abi-artifact|swift-sdk-artifact)\.yml$)' || true) if [[ -n "$DIRECT_SDK_INPUTS" ]]; then SDK_SMOKE_REQUIRED="true" elif echo "$AFFECTED_CRATES" | jq -e 'index("mesh-llm-client") or index("mesh-llm-api-client") or index("mesh-llm-api-server") or index("mesh-llm-config") or index("mesh-llm-console-server") or index("mesh-llm-ffi") or index("mesh-llm-native-runtime") or index("mesh-llm-protocol") or index("mesh-llm-routing") or index("mesh-llm-types")' >/dev/null; then diff --git a/ci/ci.md b/ci/ci.md index 1335c5025..fb183b9ee 100644 --- a/ci/ci.md +++ b/ci/ci.md @@ -257,6 +257,10 @@ flowchart TD public website docs/example update under `website/src/docs/pages/` or `website/src/_includes/`, with `website/src/docs/pages/CLI.md` as the primary command reference. +- Changes to `compute-changes` or the central PR/main/release workflow callers + fail open to the SDK producer and smoke graph. Caller-owned mode, timeout, + artifact, and trust-policy edits therefore cannot skip the reusable SDK + contracts they modify. - `pr_builds.yml` is named **PR Builds** and owns PR target jobs plus integration and smoke validation. Linux and macOS CPU artifact jobs upload the binaries that downstream smoke jobs consume before long validation groups finish. diff --git a/scripts/tests/test_ci_artifact_actions.py b/scripts/tests/test_ci_artifact_actions.py index 200233d66..b1caa6166 100644 --- a/scripts/tests/test_ci_artifact_actions.py +++ b/scripts/tests/test_ci_artifact_actions.py @@ -694,6 +694,14 @@ class CiArtifactActionTests(unittest.TestCase): ".github/actions/restore-smoke-inputs/action.yml", direct_sdk_pattern, ) + for contract_path in ( + ".github/actions/compute-changes/action.yml", + ".github/workflows/ci.yml", + ".github/workflows/pr_builds.yml", + ".github/workflows/release.yml", + ): + with self.subTest(contract_path=contract_path): + self.assertRegex(contract_path, direct_sdk_pattern) smoke_scripts = ( ROOT / "scripts" / "ci-rust-sdk-smoke.sh", ROOT / "scripts" / "ci-kotlin-sdk-smoke.sh", @@ -1311,11 +1319,13 @@ class CiArtifactActionTests(unittest.TestCase): self.assertLess(mkdir_index, move_index) self.assertIn("safe-extract-(tar|zip)", routing) self.assertIn("verify-swift-xcframework", routing) - self.assertIn( - "(native-sdk-artifact|sdk-smoke|static-abi-artifact|" - "swift-sdk-artifact)", - routing, - ) + for workflow in ( + "native-sdk-artifact", + "sdk-smoke", + "static-abi-artifact", + "swift-sdk-artifact", + ): + self.assertIn(workflow, routing) def test_swift_sdk_cache_is_mode_independent_and_target_specific( self,