Add duplicate run detection to skip redundant builds#253
Open
Biont wants to merge 6 commits into
Open
Conversation
Introduce a `Check if already built for this SHA` step that inspects the remote build branch before any toolchain setup. If the current commit SHA is already embedded in `style.css` (themes) or the main plugin PHP file (plugins), the entire compilation pipeline is skipped and the workflow proceeds directly to packaging the existing build branch content. Key changes: - New early-exit step reads `SHA:` header from the remote build branch and sets `SKIP_BUILD=true` when a match is found, bypassing install, compile, and commit steps - All subsequent build steps are guarded with `SKIP_BUILD != 'true'` conditions - `Determine package type` and `Prepare WordPress *` steps moved earlier (before npm/composer install) so the SHA can be embedded before compilation - SHA field handling changed from a plain replace to an upsert: inserts a new `SHA:` line after `Version:` when the field is absent, replaces it when present - Downstream jobs remain unaffected; the artifact output is always populated regardless of whether the build was fresh or reused - Library projects do not embed a `SHA:` field and always rebuild - Trailing whitespace cleaned up throughout the file
tyrann0us
approved these changes
Jun 4, 2026
tyrann0us
left a comment
Member
There was a problem hiding this comment.
A new "Check if already built for this SHA" step runs immediately before the build branch is checked out. It reads the remote build branch without checking it out (
fetch-depth: 0makes all remote objects available) and looks for the current commit SHA in […]:
I was about to ask you to update the PR description, since the current approach no longer uses fetch-depth, but then I checked your original commit bbdeb88 (this PR), and it doesn't use it either. 😆
But in any case, the description is outdated anyway because my changes bbdeb88..9ea6215 (this PR) moved and merged steps.
I'm approving, but it would be great if you could update the description to avoid confusion later. Thanks! 🙏🏽
tyrann0us
reviewed
Jun 4, 2026
Co-authored-by: Philipp Bammes <8144115+tyrann0us@users.noreply.github.com> Signed-off-by: Moritz Meißelbach <arbelzapf@gmail.com>
Prevent duplicate builds when the same SHA is triggered more than once (e.g., push + manual dispatch racing). By setting `cancel-in-progress: false`, a queued second run will detect the already-built artifact and resolve without repeating the full build. - Add `concurrency` group scoped to SHA + branch name on the job - Update docs to reflect the new serialization behavior and recommend `cancel-in-progress: false` in caller workflows
…un-detection' into feature/build-n-dist-duplicate-run-detection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Skip redundant builds in
build-and-distributewhen SHA is already compiledSkip the entire compilation pipeline when the build branch already contains a build for the current commit SHA, saving several minutes of Node/PHP setup on duplicate workflow runs (re-runs, race conditions between concurrent triggers, or any other scenario where the same SHA is built more than once).
Rationale
The intent of build&distribute was always to maintain the build branch as the stable source of truth. It gives us a traceable, clean artifact that is not buried in a million GHA executions and it does not expire after 90 days.
What we see in practice though is that the coupling between
dev/foo(<- the source branch) andfoo(<- the build branch) is a surprisingly annoying obstacle to overcome when building reliable CI pipelines.So there has always been an incentive to keep workflow artifacts around as a side-channel to the build-branch-commit (also because it offers a stable plugin/theme subfolder which we do not have on feature branches).
dev/foo, we cannot call e2e tests that require a built package since we push to the dev branchfoobecause that has no direct connection to the dev branch: It will execute, but failures will not show up on the PR, so they'd be an costly, easy-to-miss optional signal that does not actually help QA effortsworkflow_runtrigger, the handover of the build branch checkout is still not trivialA clean solution would be that indeed every consumer runs build&distribute and then uses the artifact it produces. But as I said this is redundant and wasteful.
This PR attempts to make it less wasteful and thereby enable this as a clean pattern.
Ideally, it would turn a ~5min execution into a <1min execution that does not add any noise to the actual build branch, so it would be safe to call it repeatedly.
Please check if the PR fulfills these requirements
What kind of change does this PR introduce?
Feature / optimization
What is the current behavior?
Every workflow run performs a full build regardless of whether the build branch already contains compiled assets for the triggering commit. Two runs for the same SHA produce identical output but consume identical runner time.
What is the new behavior?
Duplicate run detection
A new "Check if already built for this SHA" step runs immediately before the build branch is checked out. It reads the remote build branch without checking it out and looks for the current commit SHA in:
SHA:header instyle.css— WordPress themesSHA:header in the main plugin PHP file — WordPress pluginsIf the SHA is found,
SKIP_BUILD=trueis set and all compilation steps are skipped. The workflow then checks out the existing build branch (without wiping it) and proceeds directly to artifact packaging and upload, so theartifactoutput is always populated for downstream jobs.Library projects (no theme or plugin header) are unaffected and always rebuild.
SHA upsert
The
SHA:field is now written into plugin/theme headers even when it is absent from the source file. Previously thesedsubstitution was a no-op if the field did not exist, which would prevent the skip gate from ever firing. The new behaviour insertsSHA: <hash>after theVersion:line on the first build, enabling duplicate detection for all subsequent runs.Earlier preparation steps
"Determine package type" and "Prepare WordPress Plugin/Theme" have been moved to immediately after the source checkout, before any PHP or Node toolchain setup. This means a skip-gate hit now short-circuits the run before the most expensive steps (PHP setup, Composer install, Node setup,
npm ci,npm run build) are even reached.Does this PR introduce a breaking change?
No. The
artifactoutput and build branch push behaviour are unchanged for normal (non-duplicate) runs.Changes
.github/workflows/build-and-distribute.yml:SKIP_BUILD=true: checks out the existing build branch without wiping itif: SKIP_BUILD != 'true'sedin both Prepare steps to upsert: replaces existingSHA:line or inserts afterVersion:if absentif: ${{ env.SKIP_BUILD != 'true' }}to every build/compile step from "Check for composer.json" through "Git add, commit, and push"; artifact steps are left unconditionaldocs/build-and-distribute.md:SHA:behaviour in "Version Management" subsection