mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-23 23:32:05 +00:00
ci: skip the heavy jobs when nothing but documentation changed
Every push and PR paid the full four-minute job — fmt, clippy, the offline
suite, a release-profile build and the dependency audit — even when the diff
was a README or AGENTS edit, and every master push built and published an
image for a commit that cannot have changed it.
`ci.yml` gains a `changes` gate job: a push or PR whose *entire* diff is
markdown skips `test`, which then reports as *skipped* instead of missing —
the reason this is a gate job and not a workflow-level `paths` filter, which
leaves a required status check waiting for a check run that will never appear.
Anything non-markdown (and an empty diff, e.g. a re-run of the same commit)
runs the full job, so a new directory of code cannot slip through a stale
allowlist. `schedule`/`workflow_dispatch`, which have no `before` commit, also
run it.
`docker.yml`'s `should-build` gate now also skips a branch push that touched
none of the image's inputs (`Dockerfile`, `docker-entrypoint.sh`,
`.dockerignore`, the manifests, `Cargo.lock`, this workflow, anything under
`crates/`); tag pushes always build.
Checked against this repo's real ranges: the docs-only commit 667f523
(AGENTS.md) → `code=false` (test skipped) and skip, a workflow commit →
`code=true` and build, the h2 bump (Cargo.lock) → build.
This commit is contained in:
@@ -4,6 +4,8 @@ name: CI
|
|||||||
# job that exercises the real source sites and the token-gated pixiv tests.
|
# job that exercises the real source sites and the token-gated pixiv tests.
|
||||||
#
|
#
|
||||||
# Layering:
|
# Layering:
|
||||||
|
# changes — decides whether anything but documentation changed; a docs-only
|
||||||
|
# push/PR skips `test` (which then reports as skipped, not missing).
|
||||||
# test — fmt + clippy + the full offline unit suite + a release-profile
|
# test — fmt + clippy + the full offline unit suite + a release-profile
|
||||||
# build + cargo-audit dependency gate. Runs on every push and PR,
|
# build + cargo-audit dependency gate. Runs on every push and PR,
|
||||||
# including forks (it needs no secrets).
|
# including forks (it needs no secrets).
|
||||||
@@ -46,7 +48,53 @@ env:
|
|||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
# Docs-only changes skip the heavy job: a README edit does not need a four
|
||||||
|
# minute Rust build (and it cannot break one). A gate job rather than a
|
||||||
|
# workflow-level `paths` filter — that leaves the run without a `test` check
|
||||||
|
# at all, and a required status check then waits for something that will
|
||||||
|
# never be reported, while a *skipped* job reports as neutral.
|
||||||
|
changes:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
outputs:
|
||||||
|
code: ${{ steps.diff.outputs.code }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # the diff below needs the pushed range
|
||||||
|
- id: diff
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
zero=0000000000000000000000000000000000000000
|
||||||
|
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||||
|
base="origin/${{ github.base_ref }}"
|
||||||
|
git fetch --quiet --no-tags origin "${{ github.base_ref }}"
|
||||||
|
changed="$(git diff --name-only "$base...HEAD")"
|
||||||
|
else
|
||||||
|
before="${{ github.event.before }}"
|
||||||
|
if [ -z "$before" ] || [ "$before" = "$zero" ]; then
|
||||||
|
# New branch or force push: no usable base to compare against,
|
||||||
|
# so the full suite runs. Same for schedule/dispatch, which have
|
||||||
|
# no `before` at all.
|
||||||
|
changed=""
|
||||||
|
else
|
||||||
|
changed="$(git diff --name-only "$before..${{ github.sha }}")"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Only a change that is *entirely* markdown may skip the job;
|
||||||
|
# anything else — and an empty diff, i.e. a re-run of the same
|
||||||
|
# commit — counts as code.
|
||||||
|
code=true
|
||||||
|
if [ -n "$changed" ] && ! grep -qvE '\.md$' <<<"$changed"; then
|
||||||
|
code=false
|
||||||
|
fi
|
||||||
|
echo "changed: ${changed:-<no diff>}"
|
||||||
|
echo "code=$code" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.code == 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Generous on purpose: the release-profile build below is cold on the very
|
# Generous on purpose: the release-profile build below is cold on the very
|
||||||
# first run (thin LTO + codegen-units = 1 across every dependency), and a
|
# first run (thin LTO + codegen-units = 1 across every dependency), and a
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ jobs:
|
|||||||
- id: check
|
- id: check
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
zero=0000000000000000000000000000000000000000
|
||||||
if [ "$GITHUB_REF_TYPE" = "branch" ]; then
|
if [ "$GITHUB_REF_TYPE" = "branch" ]; then
|
||||||
# A branch run can start before the release tag for its commit
|
# A branch run can start before the release tag for its commit
|
||||||
# reaches the remote — pushing master first is the usual way to hit
|
# reaches the remote — pushing master first is the usual way to hit
|
||||||
@@ -87,13 +88,25 @@ jobs:
|
|||||||
# pushing the branch and the tag together
|
# pushing the branch and the tag together
|
||||||
# (`git push origin master vX.Y.Z`) removes it.
|
# (`git push origin master vX.Y.Z`) removes it.
|
||||||
git fetch --tags --force --quiet origin
|
git fetch --tags --force --quiet origin
|
||||||
|
if git tag --points-at "$GITHUB_SHA" | grep -q .; then
|
||||||
|
echo "commit already tagged; the tag run builds the image"
|
||||||
|
echo "build=false" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Nothing the image is made of changed — a documentation or
|
||||||
|
# workflow-only commit — so there is no new image to publish. The
|
||||||
|
# PR trigger's path list plus the crate sources, which the image
|
||||||
|
# compiles into the binary.
|
||||||
|
before="${{ github.event.before }}"
|
||||||
|
if [ -n "$before" ] && [ "$before" != "$zero" ] \
|
||||||
|
&& ! git diff --name-only "$before..$GITHUB_SHA" \
|
||||||
|
| grep -qE '^(Dockerfile|docker-entrypoint\.sh|\.dockerignore|Cargo\.toml|Cargo\.lock|\.github/workflows/docker\.yml|crates/)'; then
|
||||||
|
echo "no build input changed; skipping the image build"
|
||||||
|
echo "build=false" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [ "$GITHUB_REF_TYPE" = "branch" ] && git tag --points-at "$GITHUB_SHA" | grep -q .; then
|
echo "build=true" >> "$GITHUB_OUTPUT"
|
||||||
echo "commit already tagged; the tag run builds the image"
|
|
||||||
echo "build=false" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "build=true" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# No `actions/checkout` here on purpose: `docker/build-push-action` defaults
|
# No `actions/checkout` here on purpose: `docker/build-push-action` defaults
|
||||||
# to the Git context (`https://github.com/<owner>/<repo>.git#<ref>`), so
|
# to the Git context (`https://github.com/<owner>/<repo>.git#<ref>`), so
|
||||||
|
|||||||
Reference in New Issue
Block a user