From cc1b252b49a4054e5d0780305a63fd076ae2bba3 Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sat, 24 Oct 2026 07:23:52 -0700 Subject: [PATCH 1/3] Add manual no-cache rebuild to CI workflow The docker build uses the GHA layer cache, so Debian security fixes (e.g. libbrotli1 for CVE-2026-111497) are not picked up unless the apt layer changes. Add a workflow_dispatch trigger with a no_cache input (default true) that rebuilds from a fresh base image and pushes. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81baea0d..778cb8fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,13 @@ on: branches: [main] pull_request: branches: [main] + # Manual rebuild, e.g. to pick up Debian security updates when nothing in the repo changed + workflow_dispatch: + inputs: + no_cache: + description: "Build without layer cache (re-runs apt-get upgrade)" + type: boolean + default: true env: POETRY_VERSION: "2.5.1" @@ -173,8 +180,8 @@ jobs: docker-build-push: name: Build and Push Docker Image runs-on: ubuntu-24.04-arm - # Run on push to main (build+push) and on PRs (build only) - if: github.event_name == 'push' || github.event_name == 'pull_request' + # Run on push to main (build+push), manual dispatch (build+push) and on PRs (build only) + if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' # For main/PR, wait for CI checks to pass needs: [ci-success] permissions: @@ -187,7 +194,7 @@ jobs: - name: Determine push eligibility id: can-push run: | - if [ "${{ github.event_name }}" == "push" ]; then + if [ "${{ github.event_name }}" == "push" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "push=true" >> $GITHUB_OUTPUT elif [ "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]; then echo "push=true" >> $GITHUB_OUTPUT @@ -269,6 +276,8 @@ jobs: tags: | ${{ steps.docker-tag.outputs.image }} provenance: false + no-cache: ${{ inputs.no_cache == true }} + pull: ${{ inputs.no_cache == true }} cache-from: type=gha,scope=arm64 cache-to: type=gha,mode=max,scope=arm64 From 17c2d7c7c5a8707d56a04e2eed8949c60fe36521 Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sat, 24 Oct 2026 07:27:36 -0700 Subject: [PATCH 2/3] Fix stale venv cache and move actions to Node 24 - Key the Poetry and venv caches on the full Python version from setup-python. The runner moved to 3.14.8 and the old py3.14 key restored a venv with a broken interpreter link, so lint/test failed. - Bump checkout v7, cache v6, setup-python v7, codecov v7, setup-buildx v4, build-push v7, configure-aws-credentials v6 to remove Node 20 deprecation warnings. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 55 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 778cb8fb..d7c1e0c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,19 +25,20 @@ jobs: if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Set up Python - uses: actions/setup-python@v5 + id: setup-python + uses: actions/setup-python@v7 with: python-version: "3.14" - name: Load cached Poetry installation id: cached-poetry - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }} + key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - name: Install Poetry if: steps.cached-poetry.outputs.cache-hit != 'true' @@ -49,12 +50,12 @@ jobs: - name: Load cached venv id: cached-venv - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: .venv - key: venv-lint-${{ runner.os }}-py3.14-${{ hashFiles('poetry.lock') }} + key: venv-lint-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} restore-keys: | - venv-lint-${{ runner.os }}-py3.14- + venv-lint-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}- - name: Install dependencies if: steps.cached-venv.outputs.cache-hit != 'true' @@ -73,19 +74,20 @@ jobs: if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Set up Python 3.14 - uses: actions/setup-python@v5 + id: setup-python + uses: actions/setup-python@v7 with: python-version: "3.14" - name: Load cached Poetry installation id: cached-poetry - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }} + key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - name: Install Poetry if: steps.cached-poetry.outputs.cache-hit != 'true' @@ -97,12 +99,12 @@ jobs: - name: Load cached venv id: cached-venv - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: .venv - key: venv-test-${{ runner.os }}-py3.14-${{ hashFiles('poetry.lock') }} + key: venv-test-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} restore-keys: | - venv-test-${{ runner.os }}-py3.14- + venv-test-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}- - name: Install dependencies if: steps.cached-venv.outputs.cache-hit != 'true' @@ -123,7 +125,7 @@ jobs: SECRET_KEY: test-secret-key-for-ci - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v7 with: files: ./src/coverage.xml fail_ci_if_error: false @@ -136,19 +138,20 @@ jobs: if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Set up Python 3.14 - uses: actions/setup-python@v5 + id: setup-python + uses: actions/setup-python@v7 with: python-version: "3.14" - name: Load cached Poetry installation id: cached-poetry - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }} + key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - name: Install Poetry if: steps.cached-poetry.outputs.cache-hit != 'true' @@ -160,12 +163,12 @@ jobs: - name: Load cached venv id: cached-venv - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: .venv - key: venv-security-${{ runner.os }}-py3.14-${{ hashFiles('poetry.lock') }} + key: venv-security-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} restore-keys: | - venv-security-${{ runner.os }}-py3.14- + venv-security-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}- - name: Install dependencies if: steps.cached-venv.outputs.cache-hit != 'true' @@ -189,7 +192,7 @@ jobs: contents: read # Required to checkout code steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Determine push eligibility id: can-push @@ -249,13 +252,13 @@ jobs: echo "Building for ${{ steps.docker-tag.outputs.environment }} with image: ${{ steps.docker-tag.outputs.image }}" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 with: platforms: linux/arm64 - name: Configure AWS credentials if: steps.can-push.outputs.push == 'true' - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHubActions-DockerBuild-${{ steps.docker-tag.outputs.environment }} @@ -267,7 +270,7 @@ jobs: uses: aws-actions/amazon-ecr-login@v2 - name: Build and push Docker image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . target: runtime From e607f08e97fd340dd69302d034ebd53889ce5970 Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sat, 24 Oct 2026 07:29:12 -0700 Subject: [PATCH 3/3] Install Poetry with pipx instead of snok/install-poetry Removes an unpinned third-party action from the supply chain. pipx is preinstalled on GitHub-hosted runners. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 45 ++++++---------------------------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7c1e0c7..3f17d76e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,20 +33,9 @@ jobs: with: python-version: "3.14" - - name: Load cached Poetry installation - id: cached-poetry - uses: actions/cache@v6 - with: - path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - + # pipx is preinstalled on GitHub runners; avoids a third-party install action - name: Install Poetry - if: steps.cached-poetry.outputs.cache-hit != 'true' - uses: snok/install-poetry@v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: true - virtualenvs-in-project: true + run: pipx install "poetry==${{ env.POETRY_VERSION }}" --python "${{ steps.setup-python.outputs.python-path }}" - name: Load cached venv id: cached-venv @@ -82,20 +71,9 @@ jobs: with: python-version: "3.14" - - name: Load cached Poetry installation - id: cached-poetry - uses: actions/cache@v6 - with: - path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - + # pipx is preinstalled on GitHub runners; avoids a third-party install action - name: Install Poetry - if: steps.cached-poetry.outputs.cache-hit != 'true' - uses: snok/install-poetry@v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: true - virtualenvs-in-project: true + run: pipx install "poetry==${{ env.POETRY_VERSION }}" --python "${{ steps.setup-python.outputs.python-path }}" - name: Load cached venv id: cached-venv @@ -146,20 +124,9 @@ jobs: with: python-version: "3.14" - - name: Load cached Poetry installation - id: cached-poetry - uses: actions/cache@v6 - with: - path: ~/.local - key: poetry-${{ env.POETRY_VERSION }}-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }} - + # pipx is preinstalled on GitHub runners; avoids a third-party install action - name: Install Poetry - if: steps.cached-poetry.outputs.cache-hit != 'true' - uses: snok/install-poetry@v1 - with: - version: ${{ env.POETRY_VERSION }} - virtualenvs-create: true - virtualenvs-in-project: true + run: pipx install "poetry==${{ env.POETRY_VERSION }}" --python "${{ steps.setup-python.outputs.python-path }}" - name: Load cached venv id: cached-venv