From 2558bdf4ff578f0913421972515820ac29ae1242 Mon Sep 17 00:00:00 2001 From: Oliver Meyer Date: Tue, 5 May 2026 11:19:26 +0200 Subject: [PATCH 1/2] fix(docker): add --no-build to uv sync --no-install-project stages External-deps-only stages (--no-install-project) can safely enforce wheel-only installs. Stages that install the local project annotated with NOSONAR since the local build is trusted source code and --frozen already enforces lockfile hash verification. Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index ab056b388..f7dcf49e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ FROM builder AS builder-slim RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev --no-editable + uv sync --frozen --no-build --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching @@ -49,7 +49,7 @@ COPY examples /app/examples # Nothing yet RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --no-editable + uv sync --frozen --no-dev --no-editable # NOSONAR - local project built from trusted source; --frozen enforces lockfile hash verification # The all builder takes in all extras @@ -59,7 +59,7 @@ FROM builder AS builder-all RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --all-extras --no-dev --no-editable + uv sync --frozen --no-build --no-install-project --all-extras --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching @@ -78,7 +78,7 @@ COPY examples /app/examples COPY codegen/out/aignx /app/codegen/out/aignx RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --all-extras --no-dev --no-editable + uv sync --frozen --all-extras --no-dev --no-editable # NOSONAR - local project built from trusted source; --frozen enforces lockfile hash verification # Base of our build targets From 12dd3077992b0e90047610383156fd35b03db29a Mon Sep 17 00:00:00 2001 From: Oliver Meyer Date: Tue, 5 May 2026 11:21:13 +0200 Subject: [PATCH 2/2] fix(ci): add --frozen to uv run commands in CI workflows Makes the lockfile invariant explicit on every uv run call that follows uv sync --frozen, preventing any inadvertent environment update and resolving the SonarQube "unlocked dependency" warnings. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/_claude-code.yml | 2 +- .github/workflows/_package-publish.yml | 4 ++-- .github/workflows/_scheduled-test-daily.yml | 16 ++++++++-------- .github/workflows/_test.yml | 18 +++++++++--------- .github/workflows/publish-release.yml | 4 ++-- Dockerfile | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/_claude-code.yml b/.github/workflows/_claude-code.yml index 322a4da1c..6f99596de 100644 --- a/.github/workflows/_claude-code.yml +++ b/.github/workflows/_claude-code.yml @@ -72,7 +72,7 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/v') }} shell: bash run: | - TOML_VERSION=$(uv run python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") + TOML_VERSION=$(uv run --frozen python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") echo "Development build - Current version in pyproject.toml: $TOML_VERSION" - name: Run Claude Code (Interactive Mode) diff --git a/.github/workflows/_package-publish.yml b/.github/workflows/_package-publish.yml index f2e78ebe4..102862544 100644 --- a/.github/workflows/_package-publish.yml +++ b/.github/workflows/_package-publish.yml @@ -66,7 +66,7 @@ jobs: - name: Validate installation shell: bash run: | - OUTPUT=$(uv run --all-extras --no-dev aignostics --help) + OUTPUT=$(uv run --frozen --all-extras --no-dev aignostics --help) if [[ "$OUTPUT" != *"built with love in Berlin"* ]]; then echo "Output does not contain 'built with love in Berlin'" exit 1 @@ -149,7 +149,7 @@ jobs: - name: Final smoke test shell: bash run: | - uv run --no-dev aignostics --help + uv run --frozen --no-dev aignostics --help - name: Docs shell: bash diff --git a/.github/workflows/_scheduled-test-daily.yml b/.github/workflows/_scheduled-test-daily.yml index 572dd4081..a676abf80 100644 --- a/.github/workflows/_scheduled-test-daily.yml +++ b/.github/workflows/_scheduled-test-daily.yml @@ -76,7 +76,7 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/v') }} shell: bash run: | - TOML_VERSION=$(uv run python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") + TOML_VERSION=$(uv run --frozen python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") echo "Development build - Current version in pyproject.toml: $TOML_VERSION" - name: Create .env file @@ -108,7 +108,7 @@ jobs: continue-on-error: true shell: bash run: | - OUTPUT=$(uv run --no-dev aignostics --help) + OUTPUT=$(uv run --frozen --no-dev aignostics --help) if [[ "$OUTPUT" != *"built with love in Berlin"* ]]; then echo "Output does not contain 'built with love in Berlin'" exit 1 @@ -119,12 +119,12 @@ jobs: continue-on-error: true shell: bash run: | - uv run --no-dev aignostics --help - uv run --all-extras aignostics system info - uv run --all-extras aignostics system health - uv run --all-extras aignostics user whoami --mask-secrets - uv run --all-extras aignostics application list - uv run --all-extras aignostics application run list --verbose --limit 1 + uv run --frozen --no-dev aignostics --help + uv run --frozen --all-extras aignostics system info + uv run --frozen --all-extras aignostics system health + uv run --frozen --all-extras aignostics user whoami --mask-secrets + uv run --frozen --all-extras aignostics application list + uv run --frozen --all-extras aignostics application run list --verbose --limit 1 - name: Test / Unit (multiple Python versions) id: unit diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 85c4b021b..192e91903 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -100,7 +100,7 @@ jobs: shell: bash run: | TAG_VERSION=${GITHUB_REF#refs/tags/v} - TOML_VERSION=$(uv run python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") + TOML_VERSION=$(uv run --frozen python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") if [ "$TAG_VERSION" != "$TOML_VERSION" ]; then echo "Release version mismatch: Tag $TAG_VERSION != pyproject.toml $TOML_VERSION" exit 1 @@ -110,7 +110,7 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/v') }} shell: bash run: | - TOML_VERSION=$(uv run python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") + TOML_VERSION=$(uv run --frozen python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])") echo "Development build - Current version in pyproject.toml: $TOML_VERSION" - name: Create .env file @@ -140,7 +140,7 @@ jobs: - name: Validate installation (single Python version) shell: bash run: | - OUTPUT=$(uv run --no-dev aignostics --help) + OUTPUT=$(uv run --frozen --no-dev aignostics --help) if [[ "$OUTPUT" != *"built with love in Berlin"* ]]; then echo "Output does not contain 'built with love in Berlin'" exit 1 @@ -149,12 +149,12 @@ jobs: - name: Test / Smoke (single Python version) shell: bash run: | - uv run --no-dev aignostics --help - uv run --all-extras aignostics system info - uv run --all-extras aignostics system health - uv run --all-extras aignostics user whoami --mask-secrets - uv run --all-extras aignostics application list - uv run --all-extras aignostics application run list --verbose --limit 1 + uv run --frozen --no-dev aignostics --help + uv run --frozen --all-extras aignostics system info + uv run --frozen --all-extras aignostics system health + uv run --frozen --all-extras aignostics user whoami --mask-secrets + uv run --frozen --all-extras aignostics application list + uv run --frozen --all-extras aignostics application run list --verbose --limit 1 # All test steps use continue-on-error: true so that every test suite # always runs regardless of whether earlier suites failed. This ensures diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 8c91a9c61..d882e2715 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -105,9 +105,9 @@ jobs: PREV_TAG="${{ steps.version.outputs.prev_tag }}" TAG_NAME="${{ steps.version.outputs.tag_name }}" if [ -n "$PREV_TAG" ]; then - uv run git-cliff --tag "$TAG_NAME" --prepend CHANGELOG.md "${PREV_TAG}..HEAD" + uv run --frozen git-cliff --tag "$TAG_NAME" --prepend CHANGELOG.md "${PREV_TAG}..HEAD" else - uv run git-cliff --tag "$TAG_NAME" --output CHANGELOG.md + uv run --frozen git-cliff --tag "$TAG_NAME" --output CHANGELOG.md fi - name: Commit changelog diff --git a/Dockerfile b/Dockerfile index f7dcf49e2..64800218b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,7 @@ COPY examples /app/examples # Nothing yet RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --no-editable # NOSONAR - local project built from trusted source; --frozen enforces lockfile hash verification + uv sync --frozen --no-dev --no-editable # The all builder takes in all extras @@ -78,7 +78,7 @@ COPY examples /app/examples COPY codegen/out/aignx /app/codegen/out/aignx RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --all-extras --no-dev --no-editable # NOSONAR - local project built from trusted source; --frozen enforces lockfile hash verification + uv sync --frozen --all-extras --no-dev --no-editable # Base of our build targets