Skip to content

feat(mcp): suppress search recommendations covered by recent commitments #56

feat(mcp): suppress search recommendations covered by recent commitments

feat(mcp): suppress search recommendations covered by recent commitments #56

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 gocyclo binary, keyed on its pinned version so a
# bump still triggers a fresh install. It lands in ~/go/bin, which
# setup-go@v6 already adds to PATH. Restored BEFORE the install step so
# the `if: cache-hit != 'true'` guard can short-circuit it on cache-hit
# runs (the `go install` costs ~3-5s even with a warm module cache;
# skipping it is worth the extra `if`).
#
# gosec is deliberately absent here. The gosec pre-commit hook is SKIPped
# in this workflow (see the "Run pre-commit" step), and its binary comes
# from scripts/run-gosec.sh's own version-stamped cache dir, not from
# ~/go/bin. A gosec install step in this job would never execute and its
# version would be a fourth copy of the pin. ci.yml's security-scan job
# and `make security-scan-go` run that script for real.
- name: Cache Go-installed gocyclo
id: cache-go-tools
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/go/bin
key: go-tools-${{ runner.os }}-gocyclo-v0.6.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. The tag is
# mutable in principle, so also assert HEAD resolves to the exact
# commit verified at the time this was written (`git ls-remote
# --tags` against the upstream repo) before trusting it enough to
# `sudo make install`. 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.
env:
GIT_SECRETS_SHA: ad82d68ee924906a0401dfd48de5057731a9bc84
run: |
set -euo pipefail
git clone --depth 1 --branch 1.3.0 https://github.com/awslabs/git-secrets.git /tmp/git-secrets
resolved="$(git -C /tmp/git-secrets rev-parse HEAD)"
if [ "${resolved}" != "${GIT_SECRETS_SHA}" ]; then
echo "git-secrets 1.3.0 tag resolved to ${resolved}, expected ${GIT_SECRETS_SHA}" >&2
exit 1
fi
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
}
- name: Run git-secrets allowlist self-test
# Self-test for the git-secrets allowlist (#1972): asserts, through
# the real pre-commit hook scan path, that secret-shaped fixtures
# are still caught and that the documented false positives still
# scan clean.
run: bash scripts/test-git-secrets-allowlist.sh
# 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` and any other Go-compiling
# hooks reuse compiled object files instead of rebuilding from
# source. The gosec hook is not one of them: it is SKIPped in this
# workflow (see the "Run pre-commit" step), so it never compiles
# anything here. 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, so the per-package scan is redundant
# here, while the dedicated Security Scanning job remains the
# authoritative gosec gate. Both this hook and that job call
# scripts/run-gosec.sh, so they enforce the same version and rule set.
# 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