From 3f9aeb229b03cedba95ff00a413fe0b2a0c0d552 Mon Sep 17 00:00:00 2001 From: Anso Date: Fri, 10 Apr 2026 14:19:15 -0400 Subject: [PATCH] ci: cut action-minute waste on bot PRs and non-docs pushes (#486) Skip the backend, frontend, docker-validate, and e2e jobs on the chore/refresh-screenshots auto-PR opened by the update-screenshots job. Screenshot PRs only touch docs/images/ and cannot affect build, lint, or test surfaces, so running the full PR CI suite on them burns ~6 action minutes per release for zero signal. This mirrors the existing release-please--branches--main--components--sencho skip. Also short-circuit sync-docs: when a push to main does not touch any file under docs/, skip the clone, rsync, and commit steps. rsync --delete would be a no-op anyway, but spinning up the runner and cloning sencho-docs still burns ~30s per non-docs merge, which adds up across multiple merges per day. Requires fetch-depth: 2 so the detect step can diff HEAD~1 HEAD. Finally, correct the scan-build comment in docker-publish.yml: the push-build's amd64 leg reuses layers from the buildkit daemon's in-memory cache (same job, same daemon), not from the shared registry buildcache. The cache-from pull is a cold-start fallback for the first-ever run. --- .github/workflows/ci.yml | 31 ++++++++++++++++++++++++++++ .github/workflows/docker-publish.yml | 10 ++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9f0bf94..ec383971 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,9 +30,13 @@ jobs: name: Backend (Build, Test, Lint) runs-on: ubuntu-latest timeout-minutes: 10 + # Skip on bot PRs that only touch version metadata (release-please) or + # doc screenshots. Neither changes the backend surface, so running the + # full build+test+lint+audit stack is pure action-minute waste. if: >- github.event_name == 'pull_request' && github.head_ref != 'release-please--branches--main--components--sencho' + && github.head_ref != 'chore/refresh-screenshots' steps: - name: Checkout Code uses: actions/checkout@v6 @@ -68,9 +72,11 @@ jobs: name: Frontend (Build, Lint) runs-on: ubuntu-latest timeout-minutes: 10 + # See backend job rationale: skip bot PRs that cannot affect the frontend. if: >- github.event_name == 'pull_request' && github.head_ref != 'release-please--branches--main--components--sencho' + && github.head_ref != 'chore/refresh-screenshots' steps: - name: Checkout Code uses: actions/checkout@v6 @@ -102,9 +108,11 @@ jobs: name: Docker Build & Scan runs-on: ubuntu-latest timeout-minutes: 15 + # See backend job rationale. if: >- github.event_name == 'pull_request' && github.head_ref != 'release-please--branches--main--components--sencho' + && github.head_ref != 'chore/refresh-screenshots' steps: - name: Checkout Code uses: actions/checkout@v6 @@ -141,9 +149,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 needs: [backend, frontend] + # See backend job rationale. if: >- github.event_name == 'pull_request' && github.head_ref != 'release-please--branches--main--components--sencho' + && github.head_ref != 'chore/refresh-screenshots' steps: - name: Checkout Code uses: actions/checkout@v6 @@ -224,8 +234,27 @@ jobs: uses: actions/checkout@v6 with: path: sencho + # Need the previous commit to diff against for the docs-change gate. + fetch-depth: 2 + + # Skip the clone/rsync/commit work entirely when the push doesn't touch + # docs/. rsync --delete is a no-op in that case anyway, but spinning up + # the runner + cloning sencho-docs + computing the diff still burns + # ~30s of action minutes per non-docs push to main. With multiple + # non-docs merges per day this adds up fast. + - name: Detect docs changes + id: detect + working-directory: sencho + run: | + if git diff --name-only HEAD~1 HEAD -- docs/ | grep -q .; then + echo "changed=true" >> "$GITHUB_OUTPUT" + else + echo "changed=false" >> "$GITHUB_OUTPUT" + echo "No changes under docs/ in this commit; skipping sync." + fi - name: Clone or init sencho-docs + if: steps.detect.outputs.changed == 'true' env: DOCS_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }} run: | @@ -245,9 +274,11 @@ jobs: fi - name: Copy /docs into sencho-docs root + if: steps.detect.outputs.changed == 'true' run: rsync -av --delete --exclude='.git' sencho/docs/ sencho-docs/ - name: Commit and push to sencho-docs + if: steps.detect.outputs.changed == 'true' working-directory: sencho-docs run: | git config user.email "docs-bot@sencho.io" diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index b69d3fdb..765c538f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -66,9 +66,13 @@ jobs: # Build an amd64-only variant into the local daemon first so Trivy can # scan the exact release artifact before it is tagged and pushed. This # keeps vulnerable releases out of the `latest` and semver tags that - # users actually pull. The scan-build inherits layers from the shared - # buildcache so the amd64 leg of the subsequent push-build is mostly a - # cache hit; we intentionally do NOT write `cache-to` here because the + # users actually pull. Because the push-build step that follows runs in + # the same job against the same buildkit daemon, it reuses this build's + # layers from the daemon's in-memory cache (observed wall-time: the + # push-build typically finishes faster than the scan-build despite + # producing multi-arch output). The `cache-from` pull is just a + # cold-start fallback for the first-ever run or when the buildkit daemon + # is fresh; we intentionally do NOT write `cache-to` here because the # push-build below writes a strictly better (multi-arch, mode=max) # cache entry moments later. The tag lives in the `localhost/` namespace # so a future `push: false` -> `push: true` mistake cannot publish it.