From 7aeba81f027567011823230b45d39ee196aec6af Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 22:51:41 +0300 Subject: [PATCH 1/6] ci(provenance): attest gemini nano demo bundle --- .github/workflows/provenance.yml | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .github/workflows/provenance.yml diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml new file mode 100644 index 0000000..ea1505b --- /dev/null +++ b/.github/workflows/provenance.yml @@ -0,0 +1,126 @@ +name: Provenance + +on: + workflow_dispatch: + push: + branches: + - main + - master + paths: + - ".github/workflows/provenance.yml" + - ".github/workflows/ci.yml" + - "README.md" + - "SETUP.md" + - "mkdocs.yml" + - "docs/**" + - "api-server/**" + - "chrome-bridge/**" + - "chrome-demo/**" + - "python-mediapipe/**" + +permissions: + contents: read + attestations: write + id-token: write + artifact-metadata: write + +jobs: + attest-demo-bundle: + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + attestations: write + id-token: write + artifact-metadata: write + env: + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: api-server/requirements.txt + + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 + with: + node-version: "22" + cache: npm + cache-dependency-path: chrome-bridge/package-lock.json + + - name: Validate api-server + working-directory: api-server + env: + SKIP_INTEGRATION: "1" + run: | + pip install -r requirements.txt + pip install pytest ruff + ruff check . + python -m pytest test_api.py --collect-only -q || true + + - name: Validate chrome-bridge + working-directory: chrome-bridge + run: | + npm ci --ignore-scripts + npm test + + - name: Build docs site + run: | + pip install mkdocs-material + mkdocs build --strict + + - name: Create Gemini Nano demo bundle + run: | + tar -czf "gemini-nano-demo-bundle-${GITHUB_SHA}.tar.gz" \ + README.md \ + SETUP.md \ + mkdocs.yml \ + docs \ + site \ + api-server/server.py \ + api-server/requirements.txt \ + chrome-bridge/server.js \ + chrome-bridge/package.json \ + chrome-bridge/package-lock.json \ + chrome-demo/index.html \ + python-mediapipe/requirements.txt + sha256sum "gemini-nano-demo-bundle-${GITHUB_SHA}.tar.gz" | tee "gemini-nano-demo-bundle-${GITHUB_SHA}.sha256" + + - name: Attest Gemini Nano demo bundle + id: attest + uses: actions/attest@f6bf1532d7d6793fce74eac584813a8eee607999 # v4 + with: + subject-path: "gemini-nano-demo-bundle-${{ github.sha }}.tar.gz" + + - name: Verify current run attestation + run: | + gh attestation verify "gemini-nano-demo-bundle-${GITHUB_SHA}.tar.gz" \ + --repo Coding-Autopilot-System/gemini-nano \ + --signer-workflow Coding-Autopilot-System/gemini-nano/.github/workflows/provenance.yml \ + --source-ref "${GITHUB_REF}" + + - name: Publish Gemini Nano demo bundle + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: gemini-nano-demo-bundle + path: | + gemini-nano-demo-bundle-${{ github.sha }}.tar.gz + gemini-nano-demo-bundle-${{ github.sha }}.sha256 + + - name: Publish Gemini Nano attestation bundle + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: gemini-nano-attestation-bundle + path: ${{ steps.attest.outputs.bundle-path }} + + - name: Write provenance summary + run: | + { + echo "## Gemini Nano Provenance" + echo + echo "- Artifact: \`gemini-nano-demo-bundle-${GITHUB_SHA}.tar.gz\`" + echo "- Attestation: ${{ steps.attest.outputs.attestation-url }}" + echo "- Bundle artifact: \`gemini-nano-attestation-bundle\`" + } >> "$GITHUB_STEP_SUMMARY" From 673b1b59329a4993d2f7b8732ae0ef0e43b09f46 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 22:54:06 +0300 Subject: [PATCH 2/6] fix(provenance): harden gemini nano bundle validation --- .github/workflows/provenance.yml | 7 +++++-- README.md | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index ea1505b..2a500cc 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -58,7 +58,7 @@ jobs: pip install -r requirements.txt pip install pytest ruff ruff check . - python -m pytest test_api.py --collect-only -q || true + python -m pytest test_api.py --collect-only -q - name: Validate chrome-bridge working-directory: chrome-bridge @@ -81,11 +81,14 @@ jobs: site \ api-server/server.py \ api-server/requirements.txt \ + api-server/start.ps1 \ chrome-bridge/server.js \ chrome-bridge/package.json \ chrome-bridge/package-lock.json \ + chrome-bridge/start.ps1 \ chrome-demo/index.html \ - python-mediapipe/requirements.txt + python-mediapipe/requirements.txt \ + python-mediapipe/run_nano.py sha256sum "gemini-nano-demo-bundle-${GITHUB_SHA}.tar.gz" | tee "gemini-nano-demo-bundle-${GITHUB_SHA}.sha256" - name: Attest Gemini Nano demo bundle diff --git a/README.md b/README.md index e644d71..33e2346 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ graph TD cd api-server python -m venv .venv && .venv\Scripts\activate # Windows pip install -r requirements.txt -python app.py +python server.py # → http://localhost:8080 ``` From 7e1d7d4210a7e0589e2c4aa51159a508fa786022 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 22:55:58 +0300 Subject: [PATCH 3/6] ci(provenance): validate attestation workflow on pull requests --- .github/workflows/provenance.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 2a500cc..9b85b46 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -17,6 +17,18 @@ on: - "chrome-bridge/**" - "chrome-demo/**" - "python-mediapipe/**" + pull_request: + paths: + - ".github/workflows/provenance.yml" + - ".github/workflows/ci.yml" + - "README.md" + - "SETUP.md" + - "mkdocs.yml" + - "docs/**" + - "api-server/**" + - "chrome-bridge/**" + - "chrome-demo/**" + - "python-mediapipe/**" permissions: contents: read From 6f4646f2a73e1c106b4ce678679c06e6170ec49a Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 23:04:07 +0300 Subject: [PATCH 4/6] test(api-server): add real provenance-safe unit checks Replace brittle pytest collection on the manual smoke script with a real unit suite for alias resolution and model catalog exposure. Align CI and provenance verification so both workflows use the same non-Ollama Python checks. --- .github/workflows/ci.yml | 7 ++----- .github/workflows/provenance.yml | 2 +- api-server/test_api.py | 2 +- api-server/test_server.py | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 api-server/test_server.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c446f14..a90711e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,15 +36,12 @@ jobs: - name: Lint (ruff) run: ruff check . - - name: Collect tests (no Ollama required) - # test_api.py is an integration smoke test that requires a live Ollama server. - # We collect-only to confirm the file is importable and has no syntax errors. - # Set SKIP_INTEGRATION=1 as a convention for future test guards. + - name: Run unit tests (no Ollama required) env: SKIP_INTEGRATION: "1" run: | pip install pytest - python -m pytest test_api.py --collect-only -q || true + python -m pytest test_server.py -q chrome-bridge: name: chrome-bridge (Node.js) diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 9b85b46..b73a408 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -70,7 +70,7 @@ jobs: pip install -r requirements.txt pip install pytest ruff ruff check . - python -m pytest test_api.py --collect-only -q + python -m pytest test_server.py -q - name: Validate chrome-bridge working-directory: chrome-bridge diff --git a/api-server/test_api.py b/api-server/test_api.py index 26f70bc..16fcf99 100644 --- a/api-server/test_api.py +++ b/api-server/test_api.py @@ -1,4 +1,4 @@ -"""Quick test — calls both models and prints responses.""" +"""Manual integration smoke script for a live local LLM API server.""" import httpx BASE = "http://localhost:9000" diff --git a/api-server/test_server.py b/api-server/test_server.py new file mode 100644 index 0000000..58da31d --- /dev/null +++ b/api-server/test_server.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException +from fastapi.testclient import TestClient + +from server import app, resolve + + +def test_resolve_accepts_documented_aliases() -> None: + assert resolve("nano") == "gemma3:1b" + assert resolve("best") == "gemma3:12b" + assert resolve("qwen") == "qwen3:8b" + + +def test_resolve_rejects_unknown_models() -> None: + try: + resolve("missing-model") + except HTTPException as exc: + assert exc.status_code == 404 + assert "Unknown model" in str(exc.detail) + else: + raise AssertionError("resolve() should reject unknown models") + + +def test_list_models_endpoint_exposes_catalog() -> None: + client = TestClient(app) + + response = client.get("/v1/models") + + assert response.status_code == 200 + payload = response.json() + ids = {model["id"] for model in payload["data"]} + assert payload["object"] == "list" + assert {"gemma3:12b", "qwen3:8b", "gemma3:1b", "phi3:mini"} <= ids From b09f3bbd66444e0b33bda16c4442f806278077e3 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 23:05:52 +0300 Subject: [PATCH 5/6] ci(workflows): refresh deprecated node setup action Update the chrome-bridge CI job to the current setup-node pin already used by the provenance workflow so GitHub stops forcing the deprecated Node 20 action runtime. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a90711e..678e7c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version: "22" cache: npm From 2e4100c2ec9700b0be1d10c2b3c9a3bd959301cd Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 23:07:25 +0300 Subject: [PATCH 6/6] ci(workflows): refresh deprecated python setup action Align the CI Python setup step with the current action pin already used in the provenance workflow to remove the remaining deprecated Node 20 runtime warning. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 678e7c6..763531e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 with: python-version: "3.12" cache: pip