mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:07:03 +01:00
The run that added the hook-environment cache could not benefit from it: its key is a hash of .pre-commit-config.yaml, which that same commit changed, so it logged "Cache not found" and then saved. Six hook environments were still built from scratch -- including pylint's, which pulls a dozen extra packages -- and that is most of the 126s hook step. Without a dispatch there is no way to re-run the job on an unchanged tree to see the cached number, so the saving could only be asserted, not measured. Now it can be measured. Confirmed in the same log that the previous commit landed: "pytest with coverage enforcement....Skipped". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
128 lines
5.9 KiB
YAML
128 lines
5.9 KiB
YAML
name: Pre-commit checks
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
# Manual runs: this job's cost is dominated by whether the pre-commit hook
|
|
# environments are cached, and without a dispatch there is no way to
|
|
# re-run it on an unchanged tree to confirm a cache actually helps.
|
|
workflow_dispatch: {}
|
|
|
|
jobs:
|
|
pre-commit:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
# See the note in python-tests.yml: caches the pip download cache,
|
|
# keyed on the real meta/ path rather than the root symlink.
|
|
cache: pip
|
|
cache-dependency-path: meta/requirements.txt
|
|
|
|
# zsh backs the zsh-syntax hook. apt does not let a patch release be
|
|
# selected, so this is pinned only to what the runner image provides;
|
|
# the version is echoed so a jump shows up in the log rather than as a
|
|
# mystery parse difference. Local machines compare on major.minor only.
|
|
- name: Install system dependencies
|
|
run: |
|
|
set -euo pipefail
|
|
sudo apt-get update && sudo apt-get install -y zsh librsvg2-bin
|
|
zsh --version
|
|
rsvg-convert --version
|
|
|
|
# Pin shellcheck instead of inheriting whatever ubuntu-latest ships.
|
|
#
|
|
# The runner image carried 0.9.0 while developer machines have 0.11.0
|
|
# from pacman, and the shellcheck hook is `language: system` -- so it
|
|
# used whichever binary happened to be on PATH. The two versions
|
|
# disagree (0.11.0 demoted SC2002 and several SC2015/SC2119 cases as
|
|
# noise), which meant a commit could pass every local check and still
|
|
# fail CI on findings the developer could not reproduce. That is exactly
|
|
# what kept this workflow red from b83ce5d onward.
|
|
#
|
|
# Keep SHELLCHECK_VERSION in step with the version developers install;
|
|
# the verification below fails loudly rather than silently drifting.
|
|
- name: Install shellcheck (pinned)
|
|
env:
|
|
SHELLCHECK_VERSION: v0.11.0
|
|
SHELLCHECK_SHA256: 8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198
|
|
run: |
|
|
set -euo pipefail
|
|
tarball="shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz"
|
|
curl -fsSL -o "$tarball" \
|
|
"https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/${tarball}"
|
|
echo "${SHELLCHECK_SHA256} ${tarball}" | sha256sum --check --strict
|
|
tar -xJf "$tarball"
|
|
sudo install -m 0755 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" /usr/local/bin/shellcheck
|
|
# Fail here, not 40 hooks later, if PATH still resolves to another copy.
|
|
installed="$(shellcheck --version | awk '/^version:/ { print $2 }')"
|
|
expected="${SHELLCHECK_VERSION#v}"
|
|
if [ "$installed" != "$expected" ]; then
|
|
echo "::error::shellcheck on PATH is ${installed}, expected ${expected}" >&2
|
|
command -v -a shellcheck >&2
|
|
exit 1
|
|
fi
|
|
echo "shellcheck ${installed} pinned and on PATH"
|
|
|
|
# prettier and shfmt do NOT run in this job -- prettier is a pre-push
|
|
# hook and shfmt runs from the local pre-commit git hook. They are
|
|
# pinned here anyway so this file stays the single place that records
|
|
# the expected version of every `language: system` tool, and so a future
|
|
# workflow that does run them inherits the pin instead of re-deriving
|
|
# it. Their real divergence risk is between developers: both REWRITE
|
|
# files, so two versions reformat the repo back and forth.
|
|
- name: Install prettier and shfmt (pinned)
|
|
env:
|
|
PRETTIER_VERSION: 3.9.5
|
|
SHFMT_VERSION: v3.13.1
|
|
SHFMT_SHA256: fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1
|
|
run: |
|
|
set -euo pipefail
|
|
npm install --global --no-fund --no-audit "prettier@${PRETTIER_VERSION}"
|
|
|
|
curl -fsSL -o shfmt \
|
|
"https://github.com/mvdan/sh/releases/download/${SHFMT_VERSION}/shfmt_${SHFMT_VERSION}_linux_amd64"
|
|
echo "${SHFMT_SHA256} shfmt" | sha256sum --check --strict
|
|
sudo install -m 0755 shfmt /usr/local/bin/shfmt
|
|
|
|
# Assert what PATH actually resolves to, not what was just written:
|
|
# a copy earlier on PATH would otherwise win silently.
|
|
prettier_installed="$(prettier --version)"
|
|
shfmt_installed="$(shfmt --version)"
|
|
if [ "$prettier_installed" != "$PRETTIER_VERSION" ]; then
|
|
echo "::error::prettier on PATH is ${prettier_installed}, expected ${PRETTIER_VERSION}" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$shfmt_installed" != "$SHFMT_VERSION" ]; then
|
|
echo "::error::shfmt on PATH is ${shfmt_installed}, expected ${SHFMT_VERSION}" >&2
|
|
exit 1
|
|
fi
|
|
echo "prettier ${prettier_installed} and shfmt ${shfmt_installed} pinned and on PATH"
|
|
|
|
# pre-commit builds a virtualenv per hook repo on first use, which is
|
|
# slower than the pip install itself. Keyed on the hook definitions, so
|
|
# it invalidates exactly when a hook's repo or rev changes.
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/pre-commit
|
|
key: pre-commit-${{ runner.os }}-py3.12-${{ hashFiles('.pre-commit-config.yaml') }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
pip install pre-commit
|
|
|
|
- name: Run pre-commit hooks
|
|
# SKIP=pytest-coverage: the Python tests workflow already runs the
|
|
# whole suite with the same 100% coverage gate, so running it again
|
|
# here doubled the cost of this job for no extra signal. It is the
|
|
# only hook skipped, and it is skipped because it is DUPLICATED, not
|
|
# because it is slow -- if that workflow is ever removed, drop this.
|
|
run: SKIP=pytest-coverage pre-commit run --all-files --show-diff-on-failure
|