From d8300d8bb36b876e24c912a3508bcb8cd365f271 Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 13:47:20 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=90=9B=20ci(uv):=20lock=20resolved=20?= =?UTF-8?q?versions=20and=20disable=20source=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SonarCloud flagged 72 findings (githubactions:S8544/S8541) across the uv sync/run invocations in verify-python, verify-all-samples, and verify-scenarios: none asserted --locked against uv.lock or passed --no-build, so a stale lockfile or a malicious sdist build script could silently change what gets installed in CI. Adds --locked --no-build to every uv sync/uv run call, with one documented exception: python/semantic-kernel-tool-policy can't use --no-build because its transitive dep pybars4 ships no wheel on PyPI (sdist only). Also regenerates python/haystack-tool-policy/uv.lock, which was stale relative to its pyproject.toml constraint (>=2.31.0,<3.0 -> <4.0); no dependency versions changed, only the recorded constraint metadata. --- .github/workflows/verify-all-samples.yml | 17 ++++-- .github/workflows/verify-live.yml | 4 +- .github/workflows/verify-python.yml | 75 ++++++++++++------------ .github/workflows/verify-scenarios.yml | 14 ++--- python/haystack-tool-policy/uv.lock | 2 +- 5 files changed, 61 insertions(+), 51 deletions(-) diff --git a/.github/workflows/verify-all-samples.yml b/.github/workflows/verify-all-samples.yml index 326c704..f3957f6 100644 --- a/.github/workflows/verify-all-samples.yml +++ b/.github/workflows/verify-all-samples.yml @@ -99,14 +99,21 @@ jobs: ENTRY: ${{ matrix.sample.entry }} run: | set -euo pipefail + # `--no-build` is omitted for python/semantic-kernel-tool-policy: its + # transitive dep pybars4 ships no wheel on PyPI (sdist only), so it + # must be built from source. `--locked` still applies everywhere. + no_build_flag="--no-build" + if [[ "$PWD" == *"semantic-kernel-tool-policy"* ]]; then + no_build_flag="" + fi case "$RUNNER" in uv-pytest) - uv sync --extra dev - uv run pytest tests/ -v + uv sync --extra dev --locked $no_build_flag + uv run --locked $no_build_flag pytest tests/ -v ;; uv-main) - uv sync --extra dev - uv run python "$ENTRY" --mock + uv sync --extra dev --locked $no_build_flag + uv run --locked $no_build_flag python "$ENTRY" --mock ;; py-script) python "$ENTRY" @@ -149,7 +156,7 @@ jobs: set -euo pipefail case "$RUNNER" in pnpm-test) - pnpm install + pnpm install --ignore-scripts pnpm test ;; node-script) diff --git a/.github/workflows/verify-live.yml b/.github/workflows/verify-live.yml index 4243831..913cfbc 100644 --- a/.github/workflows/verify-live.yml +++ b/.github/workflows/verify-live.yml @@ -79,7 +79,7 @@ jobs: python-version: "3.13" # cp313 wheel gap (AAASM-4446) is part of what this lane must catch - name: Install the real published SDK (no shim) - run: pip install --pre "agent-assembly==0.0.1rc6" + run: "pip install --pre --only-binary=:all: 'agent-assembly==0.0.1rc6'" - name: Install and start the real aasm gateway run: bash .github/scripts/start-aasm.sh @@ -115,7 +115,7 @@ jobs: - name: Install the real published SDK (no stub) working-directory: scenarios/live-core-enforcement/node-agent - run: pnpm install + run: pnpm install --ignore-scripts - name: Install and start the real aasm gateway run: bash .github/scripts/start-aasm.sh diff --git a/.github/workflows/verify-python.yml b/.github/workflows/verify-python.yml index 9ae5021..ddc0ae0 100644 --- a/.github/workflows/verify-python.yml +++ b/.github/workflows/verify-python.yml @@ -32,10 +32,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v custom-tool-policy: name: custom-tool-policy @@ -51,10 +51,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v llamaindex-tool-policy: name: llamaindex-tool-policy @@ -70,10 +70,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v openai-agents-sdk: name: openai-agents-sdk @@ -89,10 +89,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v langchain-research-agent: name: langchain-research-agent @@ -108,10 +108,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v crewai-research-crew: name: crewai-research-crew @@ -127,10 +127,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v langgraph: name: langgraph @@ -146,10 +146,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v pydantic-ai: name: pydantic-ai @@ -165,10 +165,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v microsoft-agent-framework-tool-policy: name: microsoft-agent-framework-tool-policy @@ -187,13 +187,13 @@ jobs: # so CI installs `dev` only. The smoke tests importorskip it and the mock # demo runs without it — the offline path this repo's CI is meant to verify. - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v - name: Run offline mock demo - run: uv run python src/main.py --mock + run: uv run --locked --no-build python src/main.py --mock google-adk: name: google-adk @@ -209,10 +209,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v smolagents-tool-policy: name: smolagents-tool-policy @@ -228,10 +228,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v agno-tool-policy: name: agno-tool-policy @@ -247,10 +247,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v haystack-tool-policy: name: haystack-tool-policy @@ -266,10 +266,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v autogen-tool-policy: name: autogen-tool-policy @@ -285,13 +285,13 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v - name: Run offline demo - run: uv run python src/main.py + run: uv run --locked --no-build python src/main.py semantic-kernel-tool-policy: name: semantic-kernel-tool-policy @@ -307,13 +307,16 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + # `--no-build` (S8541) can't be used here: pybars4 (a transitive dep + # of semantic-kernel's templating) ships no wheel on PyPI, sdist only, + # so it must be built from source. `--locked` (S8544) still applies. + run: uv sync --extra dev --locked - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked pytest tests/ -v - name: Run offline demo - run: uv run python src/main.py + run: uv run --locked python src/main.py strands-agents-tool-policy: name: strands-agents-tool-policy @@ -329,10 +332,10 @@ jobs: version: "latest" - name: Install dependencies - run: uv sync --extra dev + run: uv sync --extra dev --locked --no-build - name: Run smoke tests - run: uv run pytest tests/ -v + run: uv run --locked --no-build pytest tests/ -v - name: Run offline demo - run: uv run python src/main.py + run: uv run --locked --no-build python src/main.py diff --git a/.github/workflows/verify-scenarios.yml b/.github/workflows/verify-scenarios.yml index 0424a65..c1f7447 100644 --- a/.github/workflows/verify-scenarios.yml +++ b/.github/workflows/verify-scenarios.yml @@ -155,7 +155,7 @@ jobs: with: python-version: "3.12" - name: Install PyYAML for policy validation - run: pip install pyyaml + run: "pip install --only-binary=:all: 'pyyaml==6.0.3'" - name: Validate example code + policy shape (no gateway required) run: python scenarios/live-core-enforcement/scripts/check-offline.py - name: Validate docker-compose config @@ -246,8 +246,8 @@ jobs: run: | if [ -d "scenarios/policy-enforcement/python" ]; then cd scenarios/policy-enforcement/python - uv sync --extra dev - uv run pytest tests/ -v + uv sync --extra dev --locked --no-build + uv run --locked --no-build pytest tests/ -v else echo "scenarios/policy-enforcement/python not yet present — skipping" fi @@ -273,7 +273,7 @@ jobs: run: | if [ -d "scenarios/policy-enforcement/node" ]; then cd scenarios/policy-enforcement/node - pnpm install + pnpm install --ignore-scripts pnpm run build else echo "scenarios/policy-enforcement/node not yet present — skipping" @@ -324,8 +324,8 @@ jobs: run: | if [ -d "scenarios/approval-gates/python" ]; then cd scenarios/approval-gates/python - uv sync --extra dev - uv run pytest tests/ -v + uv sync --extra dev --locked --no-build + uv run --locked --no-build pytest tests/ -v else echo "scenarios/approval-gates/python not yet present — skipping" fi @@ -351,7 +351,7 @@ jobs: run: | if [ -d "scenarios/approval-gates/node" ]; then cd scenarios/approval-gates/node - pnpm install + pnpm install --ignore-scripts pnpm run build else echo "scenarios/approval-gates/node not yet present — skipping" diff --git a/python/haystack-tool-policy/uv.lock b/python/haystack-tool-policy/uv.lock index f1e4675..ee7cf9d 100644 --- a/python/haystack-tool-policy/uv.lock +++ b/python/haystack-tool-policy/uv.lock @@ -285,7 +285,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "agent-assembly", specifier = "==0.0.1rc6" }, - { name = "haystack-ai", specifier = ">=2.31.0,<3.0" }, + { name = "haystack-ai", specifier = ">=2.31.0,<4.0" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.1.1" }, { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.15.1" }, ] From c053e493ea7b84f818bd9d9e90fc4567bf5610d0 Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 13:47:37 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=90=9B=20ci(node):=20pass=20--ignore-?= =?UTF-8?q?scripts=20to=20pnpm=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SonarCloud flagged 6 findings (githubactions:S6505) in verify-node.yml: pnpm install ran without --ignore-scripts, letting a compromised dependency's lifecycle script (preinstall/install/postinstall) execute arbitrary code during CI. Verified none of the 6 node examples rely on a lifecycle script (no preinstall/install/postinstall/prepare entries in any package.json) and that install/typecheck/test still pass with the flag added. --- .github/workflows/verify-node.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/verify-node.yml b/.github/workflows/verify-node.yml index eadfcf8..c163e8a 100644 --- a/.github/workflows/verify-node.yml +++ b/.github/workflows/verify-node.yml @@ -37,7 +37,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck @@ -63,7 +63,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck @@ -89,7 +89,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck @@ -115,7 +115,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck @@ -141,7 +141,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck @@ -167,7 +167,7 @@ jobs: node-version: "20" - name: Install dependencies - run: pnpm install + run: pnpm install --ignore-scripts - name: Type-check run: pnpm typecheck From 99fce6e2bb89a9174b7265b46eb078720db8eaf5 Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 13:49:04 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=90=9B=20config(docker):=20verify=20r?= =?UTF-8?q?ustup=20checksum=20and=20pin+lock=20pip=20installs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SonarCloud flagged 3 findings (docker:S8482/S8541/S8544) in the live-core-enforcement python-agent Dockerfile: - line 15 piped curl straight to sh to install rustup with no verification of what was being executed (S8482); - line 24 installed maturin and agent-assembly unpinned and without --only-binary=:all:, allowing an sdist build script to run (S8541/S8544). Fixes: download rustup-init and its published sha256 digest separately, verify with sha256sum -c before chmod+exec (resolving the arch via TARGETARCH so both amd64 and arm64 runners work); pin maturin==1.14.1 and agent-assembly==0.0.1rc6 with --only-binary=:all: (both already ship wheels for this platform, so no build behavior changes). Verified end-to-end with a local docker build — the native agent_assembly._core extension still loads correctly in the built image. --- .../python-agent/Dockerfile | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scenarios/live-core-enforcement/python-agent/Dockerfile b/scenarios/live-core-enforcement/python-agent/Dockerfile index a83d4b5..6252086 100644 --- a/scenarios/live-core-enforcement/python-agent/Dockerfile +++ b/scenarios/live-core-enforcement/python-agent/Dockerfile @@ -8,11 +8,24 @@ FROM python:3.12-slim # Build deps for the native (PyO3) extension built by maturin, plus the Rust -# toolchain it needs — installed in one layer. +# toolchain it needs — installed in one layer. The rustup-init binary is +# fetched over TLS and its checksum verified against rustup's published +# SHA-256 digest before execution, rather than piping curl straight to sh. +ARG TARGETARCH RUN apt-get update \ && apt-get install -y --no-install-recommends build-essential curl protobuf-compiler \ && rm -rf /var/lib/apt/lists/* \ - && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + && case "$TARGETARCH" in \ + amd64) RUST_ARCH=x86_64-unknown-linux-gnu ;; \ + arm64) RUST_ARCH=aarch64-unknown-linux-gnu ;; \ + *) echo "unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; \ + esac \ + && curl --proto '=https' --tlsv1.2 -sSfO "https://static.rust-lang.org/rustup/dist/${RUST_ARCH}/rustup-init" \ + && curl --proto '=https' --tlsv1.2 -sSfO "https://static.rust-lang.org/rustup/dist/${RUST_ARCH}/rustup-init.sha256" \ + && sha256sum -c rustup-init.sha256 \ + && chmod +x rustup-init \ + && ./rustup-init -y \ + && rm rustup-init rustup-init.sha256 ENV PATH="/root/.cargo/bin:${PATH}" # Install maturin (builds the native extension) and the published SDK in one @@ -20,8 +33,10 @@ ENV PATH="/root/.cargo/bin:${PATH}" # agent-assembly` is enough; against a source checkout, build the extension with # maturin. We install from PyPI here and rely on the platform wheel's native # layer; if you are developing against a local checkout, mount it and run -# `maturin develop` instead (see README). -RUN pip install --no-cache-dir maturin "agent-assembly==0.0.1rc6" +# `maturin develop` instead (see README). Versions are pinned and +# `--only-binary=:all:` forces wheel-only installs (both ship wheels for this +# platform), so no arbitrary sdist build script runs during install. +RUN pip install --no-cache-dir --only-binary=:all: "maturin==1.14.1" "agent-assembly==0.0.1rc6" WORKDIR /app COPY agent.py /app/agent.py From c8e0500faf1eea769299bc0cb5071731937e760b Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 13:51:12 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=94=A7=20config(sonarcloud):=20exclud?= =?UTF-8?q?e=20intentional=20example=20duplication=20from=20CPD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This repo's SonarCloud project shows 6% duplicated lines (org threshold <3%), almost entirely from per-example policy.py/policy.ts/policy.go (plus a few main.py/index.ts/test_smoke.py) files that are deliberately duplicated across ~13 independent example subprojects — this is a tutorials repo where each example must be self-contained and copy-paste-able, so extracting a shared module would break that goal. Adds .sonarcloud.properties (not sonar-project.properties, which Automatic Analysis ignores) with sonar.cpd.exclusions listing the exact 30 duplicated files from the current duplication report — this property disallows wildcard patterns, so no repo has no sonar-scanner CI step; analysis runs via SonarCloud's Automatic Analysis, confirmed via the scanner context's sonar.autoscan.enabled=true. --- .sonarcloud.properties | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .sonarcloud.properties diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 0000000..55a0f77 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1,36 @@ +# SonarCloud Automatic Analysis configuration. +# NOTE: Automatic Analysis ignores sonar-project.properties; only this file +# (and wildcard-free literal paths, per SonarCloud's own restriction on this +# specific file) is honored. See docs: "Automatic analysis" > "Advanced +# configuration". + +# Path to sources +# sonar.sources= + +# Path to tests +# sonar.tests= + +# Source encoding +# sonar.sourceEncoding= + +# Exclusions for copy-paste detection. +# +# This is a tutorials/examples repo: every example under python/*, node/*, +# go/*, and snippets/* is intentionally self-contained and copy-paste-able, +# so each one re-implements its own local `policy.py` / `policy.ts` / +# `policy.go` (and a handful of `main.py` / `index.ts` / `test_smoke.py` +# files that follow the same per-framework template). That duplication is +# BY DESIGN — extracting a shared policy module would break the "copy one +# example directory and it just works" contract this repo exists to +# demonstrate. It is not a code smell to fix; it is excluded here rather +# than left to inflate the project's duplication rating. List is exact +# files (this property disallows wildcard patterns), taken from the +# duplication report as of 2026-07-23. +sonar.cpd.exclusions=go/langchaingo/policy.go,go/tool-policy/policy.go,node/custom-tool-policy/src/index.ts,node/custom-tool-policy/src/policy.ts,node/langchain-js-basic-agent/src/policy.ts,node/langgraph-js/src/policy.ts,node/mastra/src/policy.ts,node/openai-node-tool-policy/src/index.ts,node/openai-node-tool-policy/src/policy.ts,node/vercel-ai/src/policy.ts,python/agno-tool-policy/src/main.py,python/autogen-tool-policy/src/policy.py,python/crewai-research-crew/src/main.py,python/crewai-research-crew/src/policy.py,python/google-adk/src/policy.py,python/google-adk/tests/test_smoke.py,python/haystack-tool-policy/src/main.py,python/langchain-basic-agent/src/policy.py,python/langchain-research-agent/src/policy.py,python/langgraph/src/policy.py,python/microsoft-agent-framework-tool-policy/tests/test_smoke.py,python/pydantic-ai/src/policy.py,python/pydantic-ai/tests/test_smoke.py,python/semantic-kernel-tool-policy/src/policy.py,python/strands-agents-tool-policy/src/policy.py,snippets/node/custom-tool-policy.ts,snippets/node/openai-node-tool-policy.ts,snippets/python/agno-tool-policy.py,snippets/python/crewai-research-crew.py,snippets/python/haystack-tool-policy.py + +# Python version (for python projects only) +# sonar.python.version= + +# C++ standard version (for C++ projects only) +# If not specified, it defaults to the latest supported standard +# sonar.cfamily.reportingCppStandardOverride=c++98|c++11|c++14|c++17|c++20 From 462ddd8d4a660ed644abcabd610d2ae35f3edb6f Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 14:53:52 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20ci(uv):=20make=20the?= =?UTF-8?q?=20semantic-kernel=20--no-build=20exception=20self-contained?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous fix built the uv flag as $no_build_flag (empty string for semantic-kernel-tool-policy, "--no-build" otherwise) and interpolated it into the case statement. SonarCloud's static analysis can't follow that indirection and re-flagged the interpolated call sites as if --no-build were always missing (githubactions:S8541, re-triggered on this PR's diff). Split into two literal case statements instead — one for semantic-kernel-tool-policy (no --no-build, documented why) and one for everything else (always --no-build) — so every call site is a static, directly-scannable command. --- .github/workflows/verify-all-samples.yml | 34 +++++++++++++++++------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-all-samples.yml b/.github/workflows/verify-all-samples.yml index f3957f6..3dc60c8 100644 --- a/.github/workflows/verify-all-samples.yml +++ b/.github/workflows/verify-all-samples.yml @@ -99,21 +99,37 @@ jobs: ENTRY: ${{ matrix.sample.entry }} run: | set -euo pipefail - # `--no-build` is omitted for python/semantic-kernel-tool-policy: its - # transitive dep pybars4 ships no wheel on PyPI (sdist only), so it - # must be built from source. `--locked` still applies everywhere. - no_build_flag="--no-build" + # `--no-build` is skipped only for python/semantic-kernel-tool-policy: + # its transitive dep pybars4 ships no wheel on PyPI (sdist only), so + # it must be built from source. `--locked` still applies everywhere. if [[ "$PWD" == *"semantic-kernel-tool-policy"* ]]; then - no_build_flag="" + case "$RUNNER" in + uv-pytest) + uv sync --extra dev --locked + uv run --locked pytest tests/ -v + ;; + uv-main) + uv sync --extra dev --locked + uv run --locked python "$ENTRY" --mock + ;; + py-script) + python "$ENTRY" + ;; + *) + echo "::error::unknown python runner: $RUNNER" + exit 1 + ;; + esac + exit 0 fi case "$RUNNER" in uv-pytest) - uv sync --extra dev --locked $no_build_flag - uv run --locked $no_build_flag pytest tests/ -v + uv sync --extra dev --locked --no-build + uv run --locked --no-build pytest tests/ -v ;; uv-main) - uv sync --extra dev --locked $no_build_flag - uv run --locked $no_build_flag python "$ENTRY" --mock + uv sync --extra dev --locked --no-build + uv run --locked --no-build python "$ENTRY" --mock ;; py-script) python "$ENTRY" From f96ea12edd3103d1b7fada5e6a39bbbf42a40b91 Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Thu, 23 Jul 2026 15:16:58 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20ci(uv):=20drop=20dead?= =?UTF-8?q?=20uv-main/py-script=20branches=20for=20semantic-kernel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit discover_samples.py always classifies python/semantic-kernel-tool-policy as uv-pytest (it has a tests/ dir), so the uv-main/py-script cases inside its --no-build exception branch were unreachable — but SonarCloud's static analysis flagged them anyway (githubactions:S8541) since it scans every literal command, reachable or not. Collapses the exception to the one path that's actually taken, with a guard that fails loudly if discovery's classification ever changes. --- .github/workflows/verify-all-samples.yml | 27 ++++++++---------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/verify-all-samples.yml b/.github/workflows/verify-all-samples.yml index 3dc60c8..78fb1ac 100644 --- a/.github/workflows/verify-all-samples.yml +++ b/.github/workflows/verify-all-samples.yml @@ -101,25 +101,16 @@ jobs: set -euo pipefail # `--no-build` is skipped only for python/semantic-kernel-tool-policy: # its transitive dep pybars4 ships no wheel on PyPI (sdist only), so - # it must be built from source. `--locked` still applies everywhere. + # it must be built from source. `--locked` still applies. That + # example has a tests/ dir, so discover_samples.py always classifies + # it as `uv-pytest` — there is no `uv-main`/`py-script` case for it. if [[ "$PWD" == *"semantic-kernel-tool-policy"* ]]; then - case "$RUNNER" in - uv-pytest) - uv sync --extra dev --locked - uv run --locked pytest tests/ -v - ;; - uv-main) - uv sync --extra dev --locked - uv run --locked python "$ENTRY" --mock - ;; - py-script) - python "$ENTRY" - ;; - *) - echo "::error::unknown python runner: $RUNNER" - exit 1 - ;; - esac + if [[ "$RUNNER" != "uv-pytest" ]]; then + echo "::error::semantic-kernel-tool-policy runner changed to $RUNNER — update this exception" + exit 1 + fi + uv sync --extra dev --locked + uv run --locked pytest tests/ -v exit 0 fi case "$RUNNER" in