From 50127ef212bd1f3a6ca32f9ae824bb710dbd002b Mon Sep 17 00:00:00 2001 From: Anthony Brown Date: Tue, 10 Mar 2026 10:41:17 +0000 Subject: [PATCH 1/2] add retry on resolve digest --- .github/workflows/get-repo-config.yml | 199 ++++++++++++++------------ 1 file changed, 108 insertions(+), 91 deletions(-) diff --git a/.github/workflows/get-repo-config.yml b/.github/workflows/get-repo-config.yml index e9c793b..cc6a926 100644 --- a/.github/workflows/get-repo-config.yml +++ b/.github/workflows/get-repo-config.yml @@ -40,106 +40,123 @@ on: value: ${{ jobs.verify_attestation.outputs.resolved_digest }} jobs: - get_config_values: - runs-on: ubuntu-22.04 - outputs: - tag_format: ${{ steps.load-config.outputs.TAG_FORMAT }} - devcontainer_version: ${{ steps.load-config.outputs.DEVCONTAINER_VERSION }} - devcontainer_image: ${{ steps.load-config.outputs.DEVCONTAINER_IMAGE }} - runtime_docker_image: ${{ steps.load-config.outputs.RUNTIME_DOCKER_IMAGE }} - steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - with: - ref: ${{ env.BRANCH_NAME }} - fetch-depth: 0 + get_config_values: + runs-on: ubuntu-22.04 + outputs: + tag_format: ${{ steps.load-config.outputs.TAG_FORMAT }} + devcontainer_version: ${{ steps.load-config.outputs.DEVCONTAINER_VERSION }} + devcontainer_image: ${{ steps.load-config.outputs.DEVCONTAINER_IMAGE }} + runtime_docker_image: ${{ steps.load-config.outputs.RUNTIME_DOCKER_IMAGE }} + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + ref: ${{ env.BRANCH_NAME }} + fetch-depth: 0 + + - name: Load config value + id: load-config + run: | + TAG_FORMAT=$(yq '.TAG_FORMAT' .github/config/settings.yml) + DEVCONTAINER_IMAGE=$(jq -r '.build.args.IMAGE_NAME' .devcontainer/devcontainer.json) + DEVCONTAINER_VERSION=$(jq -r '.build.args.IMAGE_VERSION' .devcontainer/devcontainer.json) + RUNTIME_DOCKER_IMAGE="${DEVCONTAINER_IMAGE}:githubactions-${DEVCONTAINER_VERSION}" + { + echo "TAG_FORMAT=$TAG_FORMAT" + echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE" + echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION" + echo "RUNTIME_DOCKER_IMAGE=$RUNTIME_DOCKER_IMAGE" + } >> "$GITHUB_OUTPUT" - - name: Load config value - id: load-config - run: | - TAG_FORMAT=$(yq '.TAG_FORMAT' .github/config/settings.yml) - DEVCONTAINER_IMAGE=$(jq -r '.build.args.IMAGE_NAME' .devcontainer/devcontainer.json) - DEVCONTAINER_VERSION=$(jq -r '.build.args.IMAGE_VERSION' .devcontainer/devcontainer.json) - RUNTIME_DOCKER_IMAGE="${DEVCONTAINER_IMAGE}:githubactions-${DEVCONTAINER_VERSION}" - { - echo "TAG_FORMAT=$TAG_FORMAT" - echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE" - echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION" - echo "RUNTIME_DOCKER_IMAGE=$RUNTIME_DOCKER_IMAGE" - } >> "$GITHUB_OUTPUT" + verify_attestation: + runs-on: ubuntu-22.04 + needs: get_config_values + permissions: + contents: read + packages: read + attestations: read + outputs: + pinned_image: ${{ steps.resolve.outputs.pinned_image }} + resolved_digest: ${{ steps.resolve.outputs.resolved_digest }} + steps: + - name: Login to github container registry + if: startsWith(inputs.registry, 'ghcr.io') + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - verify_attestation: - runs-on: ubuntu-22.04 - needs: get_config_values - permissions: - contents: read - packages: read - attestations: read - outputs: - pinned_image: ${{ steps.resolve.outputs.pinned_image }} - resolved_digest: ${{ steps.resolve.outputs.resolved_digest }} - steps: - - name: Login to github container registry - if: startsWith(inputs.registry, 'ghcr.io') - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Resolve digest + id: resolve + shell: bash + env: + RUNTIME_DOCKER_IMAGE: ${{ needs.get_config_values.outputs.runtime_docker_image }} + REGISTRY: ${{ inputs.registry }} + NAMESPACE: ${{ inputs.namespace }} + run: | + set -euo pipefail - - name: Resolve digest - id: resolve - shell: bash - env: - RUNTIME_DOCKER_IMAGE: ${{ needs.get_config_values.outputs.runtime_docker_image }} - REGISTRY: ${{ inputs.registry }} - NAMESPACE: ${{ inputs.namespace }} - run: | - set -euo pipefail + if [[ "$RUNTIME_DOCKER_IMAGE" == *"/"* ]]; then + IMAGE_REF="$RUNTIME_DOCKER_IMAGE" + else + IMAGE_REF="${REGISTRY}/${NAMESPACE}/${RUNTIME_DOCKER_IMAGE}" + fi - if [[ "$RUNTIME_DOCKER_IMAGE" == *"/"* ]]; then - IMAGE_REF="$RUNTIME_DOCKER_IMAGE" - else - IMAGE_REF="${REGISTRY}/${NAMESPACE}/${RUNTIME_DOCKER_IMAGE}" - fi + if [[ "$IMAGE_REF" == *@sha256:* ]]; then + IMAGE_BASE="${IMAGE_REF%@*}" + RESOLVED_DIGEST="${IMAGE_REF#*@}" + else + RESOLVED_DIGEST="" + MAX_ATTEMPTS=5 + for attempt in $(seq 1 "$MAX_ATTEMPTS"); do + if OUTPUT="$(docker buildx imagetools inspect "$IMAGE_REF" 2>&1)"; then + RESOLVED_DIGEST="$(awk '/^Digest:/ {print $2; exit}' <<< "$OUTPUT")" + if [[ -n "$RESOLVED_DIGEST" ]]; then + break + fi + echo "Digest not found in imagetools output (attempt ${attempt}/${MAX_ATTEMPTS})." >&2 + else + echo "Failed to inspect image ${IMAGE_REF} (attempt ${attempt}/${MAX_ATTEMPTS})." >&2 + echo "$OUTPUT" >&2 + fi - if [[ "$IMAGE_REF" == *@sha256:* ]]; then - IMAGE_BASE="${IMAGE_REF%@*}" - RESOLVED_DIGEST="${IMAGE_REF#*@}" - else - RESOLVED_DIGEST="$(docker buildx imagetools inspect "$IMAGE_REF" | awk '/^Digest:/ {print $2; exit}')" - IMAGE_BASE="${IMAGE_REF%:*}" - fi + if [[ "$attempt" -lt "$MAX_ATTEMPTS" ]]; then + sleep $((attempt * 2)) + fi + done + IMAGE_BASE="${IMAGE_REF%:*}" + fi - if [[ -z "$RESOLVED_DIGEST" ]]; then - echo "Could not resolve digest for image: $IMAGE_REF" >&2 - exit 1 - fi + if [[ -z "$RESOLVED_DIGEST" ]]; then + echo "Could not resolve digest for image: $IMAGE_REF" >&2 + exit 1 + fi - PINNED_IMAGE="${IMAGE_BASE}@${RESOLVED_DIGEST}" - echo "resolved_digest=${RESOLVED_DIGEST}" >> "$GITHUB_OUTPUT" - echo "pinned_image=${PINNED_IMAGE}" >> "$GITHUB_OUTPUT" - echo "Resolved image reference: ${IMAGE_REF}" - echo "Resolved digest: ${RESOLVED_DIGEST}" - echo "Resolved image reference: ${PINNED_IMAGE}" + PINNED_IMAGE="${IMAGE_BASE}@${RESOLVED_DIGEST}" + echo "resolved_digest=${RESOLVED_DIGEST}" >> "$GITHUB_OUTPUT" + echo "pinned_image=${PINNED_IMAGE}" >> "$GITHUB_OUTPUT" + echo "Resolved image reference: ${IMAGE_REF}" + echo "Resolved digest: ${RESOLVED_DIGEST}" + echo "Resolved image reference: ${PINNED_IMAGE}" - - name: Verify attestation - shell: bash - env: - GH_TOKEN: ${{ github.token }} - OWNER: ${{ inputs.owner }} - VERIFY_PUBLISHED_FROM_MAIN_IMAGE: ${{ inputs.verify_published_from_main_image }} - PREDICATE_TYPE: ${{ inputs.predicate_type }} - PINNED_IMAGE: ${{ steps.resolve.outputs.pinned_image }} - run: | - set -euo pipefail + - name: Verify attestation + shell: bash + env: + GH_TOKEN: ${{ github.token }} + OWNER: ${{ inputs.owner }} + VERIFY_PUBLISHED_FROM_MAIN_IMAGE: ${{ inputs.verify_published_from_main_image }} + PREDICATE_TYPE: ${{ inputs.predicate_type }} + PINNED_IMAGE: ${{ steps.resolve.outputs.pinned_image }} + run: | + set -euo pipefail - args=("oci://${PINNED_IMAGE}" "--owner" "$OWNER" "--predicate-type" "$PREDICATE_TYPE") + args=("oci://${PINNED_IMAGE}" "--owner" "$OWNER" "--predicate-type" "$PREDICATE_TYPE") - if [[ "$VERIFY_PUBLISHED_FROM_MAIN_IMAGE" == "true" ]]; then - args+=("--source-ref" "refs/heads/main") - fi + if [[ "$VERIFY_PUBLISHED_FROM_MAIN_IMAGE" == "true" ]]; then + args+=("--source-ref" "refs/heads/main") + fi - GH_FORCE_TTY=120 gh attestation verify "${args[@]}" 2>&1 - echo "Verified attestation for ${PINNED_IMAGE}" + GH_FORCE_TTY=120 gh attestation verify "${args[@]}" 2>&1 + echo "Verified attestation for ${PINNED_IMAGE}" From e1876d762047e6115a4024536fda014e2f5f860f Mon Sep 17 00:00:00 2001 From: Anthony Brown Date: Tue, 10 Mar 2026 10:46:21 +0000 Subject: [PATCH 2/2] do not error on vulns for dependabot --- .github/workflows/quality-checks-devcontainer.yml | 5 +++++ .github/workflows/quality-checks.yml | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/quality-checks-devcontainer.yml b/.github/workflows/quality-checks-devcontainer.yml index 8eabed8..6e63b51 100644 --- a/.github/workflows/quality-checks-devcontainer.yml +++ b/.github/workflows/quality-checks-devcontainer.yml @@ -151,19 +151,23 @@ jobs: - name: Check python vulnerabilities if: ${{ steps.check_languages.outputs.uses_poetry == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} run: | make trivy-scan-python - name: Check node vulnerabilities if: ${{ steps.check_languages.outputs.uses_node == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} run: | make trivy-scan-node - name: Check go vulnerabilities if: ${{ steps.check_languages.outputs.uses_go == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} run: | make trivy-scan-go - name: Check java vulnerabilities if: ${{ steps.check_languages.outputs.uses_java == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} run: | make trivy-scan-java - name: Show vulnerability output @@ -304,6 +308,7 @@ jobs: DOCKER_IMAGE: ${{ matrix.docker_image }} - name: Check docker vulnerabilities + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} run: | make trivy-scan-docker env: diff --git a/.github/workflows/quality-checks.yml b/.github/workflows/quality-checks.yml index c4d4fdf..2fed77f 100644 --- a/.github/workflows/quality-checks.yml +++ b/.github/workflows/quality-checks.yml @@ -264,6 +264,7 @@ jobs: - name: Check python vulnerabilities if: ${{ always() && steps.check_languages.outputs.uses_poetry == 'true'}} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 with: scan-type: "fs" @@ -277,6 +278,7 @@ jobs: trivy-config: trivy.yaml - name: Check node vulnerabilities if: ${{ always() && steps.check_languages.outputs.uses_node == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 with: scan-type: "fs" @@ -290,6 +292,7 @@ jobs: trivy-config: trivy.yaml - name: Check go vulnerabilities if: ${{ always() && steps.check_languages.outputs.uses_go == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 with: scan-type: "fs" @@ -302,6 +305,7 @@ jobs: exit-code: "1" - name: Check java vulnerabilities if: ${{ always() && steps.check_languages.outputs.uses_java == 'true' }} + continue-on-error: ${{ github.actor == 'dependabot[bot]' }} uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 with: scan-type: "fs"