tf-plan: report one check run for the whole workflow - #79
Draft
dev-milos wants to merge 1 commit into
Draft
Conversation
The `Terraform plan` check run was created and concluded inside the `terraform-plan` job, which only runs once `validate` has passed. A failed validation therefore skipped both calls and left the head commit with no check at all - a pull request gated on that check waited forever on something that never arrived. The terminal call was also a second `checks.create` rather than an update, so every run left a dangling `in_progress` check beside the completed one, and nothing outside the job could conclude the check when a run was cancelled. Merge `validate` and `terraform-plan` into one job that opens the check run as its first step and reports the outcome as its last, `if: always()`. Skipping the plan on invalid config is what `needs:` bought us, and steps already do that on their own; in exchange the check-run lifecycle is a straight line through a single job, `job.status` and the step outcomes replace the cross-job plumbing, and the run drops three runner allocations and a duplicate checkout. The check keeps the name `Terraform plan` - consumers list it as a required status check - and now carries what happened in its title: validation failed, the plan failed, or the run was cancelled. `skipped` is deliberately never used as a conclusion, since GitHub counts it as passing a required check. The plan comment is posted after the check is resolved and is truncated, so an over-long body cannot strand the merge gate.
dev-milos
force-pushed
the
feature/plan-check-run-bracket
branch
from
August 28, 2026 13:52
05bca1c to
56a6edd
Compare
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.
Problem
The
Terraform plancheck run was created and concluded inside theterraform-planjob, which only runs oncevalidatehas passed. Three things follow:validateproduced no check at all.terraform-planhasneeds: validateand noif:, so both Checks API calls were skipped and the head commit was left with nothing. A pull request gated on that check waits forever on something that never arrives. Reproduced in the test org — run 33066980306:validatefailed,terraform-planskipped, zero check runs on the SHA.checks.createrather than an update — the in-progress run's id was never captured — so each SHA ended up with a completed check run and one stuck atin_progressforever.Change
validateandterraform-planbecome onevalidate-and-planjob that opens the check run as its first step and reports the outcome as its last:Skipping the plan on invalid config is what
needs:bought us, and steps already do that on their own — everything after a failed step is skipped. In exchange the check-run lifecycle is a straight line through a single job:job.statusand the step outcomes replace all the cross-job plumbing (no job outputs, noneeds, no second token), and the run drops three runner allocations and a duplicateCheckout GCSS. On the test org that is 99s → 76s for the happy path.Report resultderives the conclusion in one place:cancelledfirst, then a validation step failure, then anything else that failed, then the existing plan summary on success. It updates the run opened at the top by id, falling back tocreatewhen there is none (the opening step iscontinue-on-error, so a Checks API blip cannot block the plan).The check keeps the name
Terraform plan— consumers list it as a required status check — and now carries what happened in its title: Configuration Validation Failed, Terraform Plan Failed, Terraform Plan Cancelled.skippedis deliberately never used as a conclusion, since GitHub counts it as passing a required check.The PR comment is posted after the check is resolved and is truncated at 65000 chars.
issues.createCommentrejects bodies over 65536, and an unhandled throw there must not be able to strand the merge gate.No consumer change is required — inputs, secrets, and the check name are untouched. The only visible difference is one job in the Actions UI instead of two.
Verification
End-to-end in
milos-org/github-configuration, withmainpointed at this branch.in_progress→successwith the plan summary, same id throughout; comment postedReport resultstill ran →failure/ Configuration Validation Failed. Previously: no check at allSetup terraform and run plan: cancelled,Report result: success→ checkcancelled, not stranded atin_progressCheck runs per SHA,
filter=all— before this change vs after:Also checked before pushing:
actionlintclean, bothgithub-scriptbodies passnode --check, andReport resultwas executed against 13 stubbed environments — including cancellation during validation (must report cancelled, not a validation failure), a failure before validation ran, thecreatefallback, a fork PR with no PR number, and a ~4000-resource plan that truncates both the check text and the comment.