Skip to content

fix(cli): parse CSV Count and EstimatedSavings strictly #3058

fix(cli): parse CSV Count and EstimatedSavings strictly

fix(cli): parse CSV Count and EstimatedSavings strictly #3058

Workflow file for this run

name: pre-commit
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
jobs:
pre-commit:
name: Run pre-commit hooks
runs-on: ubuntu-latest
# 35 minutes accommodates the 3-attempt retry wrapper on the
# `Run pre-commit` step below (3 attempts * 10 min per-attempt
# timeout + 2 * 90 s retry waits = 33 min worst case) plus a
# small margin for setup/install steps. Without the bump, the
# job-level cap killed any retry attempt before it could start,
# making the retry policy ineffective (CR finding on #697).
timeout-minutes: 35
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
# Read from go.mod rather than a hardcoded string, matching
# aws_sanity / azure_sanity / database-migration. One fewer place the
# Go version has to be bumped by hand (issue #1833).
go-version-file: go.mod
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "24"
# Cache the installed tool binaries (gosec, gocyclo). Keyed on the
# pinned version strings so a tool-version bump still triggers a
# fresh install. Both binaries land in ~/go/bin which setup-go@v6
# already adds to PATH. Restored BEFORE the install steps so the
# `if: cache-hit != 'true'` guards below can short-circuit them on
# cache-hit runs (the `go install` invocations cost ~3-5s each
# even when the module cache is warm; skipping them on cache-hit
# is worth the extra `if`).
- name: Cache Go-installed tools (gosec, gocyclo)
id: cache-go-tools
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/go/bin
key: go-tools-${{ runner.os }}-gosec-v2.28.0-gocyclo-v0.6.0
- name: Install gosec
if: steps.cache-go-tools.outputs.cache-hit != 'true'
# Pinned to the same version ci.yml's `securego/gosec` Action uses,
# so an upstream gosec release with rule changes can't silently
# downgrade the gate between the two workflows.
run: go install github.com/securego/gosec/v2/cmd/gosec@v2.28.0
- name: Install gocyclo
if: steps.cache-go-tools.outputs.cache-hit != 'true'
# Pinned to match ci.yml — security tool installs must not use
# @latest; that's exactly the supply-chain weakness this PR is
# closing for Dockerfile FROMs.
run: go install github.com/fzipp/gocyclo/cmd/gocyclo@v0.6.0
- name: Install Trivy
# Pinned to v0.69.3 (the latest release with published GitHub-release
# tarballs as of writing). Tags exist for v0.58 onwards but several
# mid-range releases skipped publishing assets to the Releases page;
# the install.sh script fetches via GitHub Releases, so picking one
# of those tags makes install bail silently after detecting the
# version. v0.69.3 ships the standard `trivy_<ver>_Linux-64bit.tar.gz`
# asset.
#
# The installer itself is fetched from the same pinned release tag
# (not the mutable `main` branch) and downloaded to a file before
# execution: a malicious or
# accidental change to install.sh on main can't silently execute
# on this CI runner, and `curl -fsSL` makes transport errors fail
# loudly instead of piping an HTML error page into sh.
env:
TRIVY_VERSION: v0.69.3
run: |
set -euo pipefail
curl -fsSL -o /tmp/trivy-install.sh \
"https://raw.githubusercontent.com/aquasecurity/trivy/${TRIVY_VERSION}/contrib/install.sh"
sh /tmp/trivy-install.sh -b /usr/local/bin "${TRIVY_VERSION}"
- name: Install git-secrets
# Pinned to a release tag rather than master HEAD. After install
# we register the AWS pattern set and ASSERT at least one pattern
# was registered — without the assert, a registration failure
# produces a patternless scanner that exits 0 unconditionally,
# leaving the gate silently downgraded.
run: |
set -euo pipefail
git clone --depth 1 --branch 1.3.0 https://github.com/awslabs/git-secrets.git /tmp/git-secrets
sudo make -C /tmp/git-secrets install
git secrets --register-aws --global
git secrets --list --global | grep -q '.' || {
echo "git-secrets registration produced no patterns — gate would be silently disabled"
exit 1
}
# Note: the local `hadolint` hook in .pre-commit-config.yaml (search for
# `id: hadolint`; no line number, because this comment has already gone
# stale twice as that file shifted) runs ghcr.io/hadolint/hadolint pinned
# by digest. The version lives in that entry and is the single source of
# truth; do not restate it here, or this comment rots again. We do NOT
# install a host binary here — it would be dead code (never invoked by
# the hook) AND a supply-chain hole (latest tag, no checksum). Note:
# an earlier version of this comment claimed the hook already pinned
# the image to v2.14.0 via the hook repo's `rev:` -- it did not; that
# `rev:` only pins hadolint's *hook definition*, whose upstream entry
# (`ghcr.io/hadolint/hadolint hadolint`) has no image tag and floats to
# `:latest`. See the digest pin in .pre-commit-config.yaml for the fix.
# If a future change switches the hook to a host binary, install a
# pinned + sha256-verified binary here.
- name: Install pre-commit
run: pip install 'pre-commit==4.0.1'
# Cache pre-commit's per-hook environments (Go, Python, Node, etc.
# virtualenvs it builds on first run). Keyed on the hook config
# because pre-commit will rebuild any env whose pinned rev changes.
# Saves ~30-60s per cache-hit run; safe because pre-commit verifies
# env integrity on use.
- name: Cache pre-commit environments
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-${{ runner.os }}-
# Cache the Go build cache so `go vet`, `gosec`, and any other
# Go-compiling hooks reuse compiled object files instead of
# rebuilding from source. setup-go@v6 caches ~/go/pkg/mod
# (modules) but NOT ~/.cache/go-build (compiled output) — this
# step covers the latter. Keyed on go.sum so a dep upgrade still
# invalidates the cache and gets clean builds.
- name: Cache Go build cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cache/go-build
key: go-build-${{ runner.os }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
go-build-${{ runner.os }}-
- name: Run pre-commit
# SKIP the local per-changed-package gosec hook in CI: --all-files
# feeds every Go file at once, while the dedicated Security Scanning
# job remains the authoritative per-module gosec v2.28.0 gate.
# nick-fields/retry wraps the run with up to 3 attempts and a
# 90-second wait so transient flakes do not require a manual rerun.
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
env:
SKIP: gosec
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
timeout_minutes: 10
max_attempts: 3
retry_wait_seconds: 90
command: pre-commit run --all-files