feat: expose the analysis outcome and make reporting configurable - #3
Draft
javier-godoy wants to merge 7 commits into
Draft
feat: expose the analysis outcome and make reporting configurable#3javier-godoy wants to merge 7 commits into
javier-godoy wants to merge 7 commits into
Conversation
This was referenced Sep 9, 2026
javier-godoy
force-pushed
the
feature/wip-action-required
branch
9 times, most recently
from
September 10, 2026 12:33
890ad04 to
0f2f7a0
Compare
javier-godoy
force-pushed
the
feature/wip-action-required
branch
from
September 10, 2026 17:42
0f2f7a0 to
9cc1e86
Compare
javier-godoy
force-pushed
the
feature/wip-action-required
branch
2 times, most recently
from
September 10, 2026 17:58
b59c6d6 to
df3ebd4
Compare
javier-godoy
force-pushed
the
feature/wip-action-required
branch
5 times, most recently
from
September 11, 2026 16:09
fd3bd27 to
03b07fc
Compare
The action reported its findings only through the log and its own outcome, so a caller could not tell what was found. It now also sets results, which describes every commit as JSON: its header, whether it is valid, WIP or invalid, and the reason when it is invalid. results is set before the check fails, so that it can be read from a step that runs on failure, and on the path where the commits cannot be retrieved, where it is empty. It is the only output: has-errors and has-wip are derivable from results, and the Semantic Versioning level is already exported as the SEMVER_LEVEL environment variable.
core.error creates an annotation on the check run, so the offending commit and the reason why it is invalid are visible on the pull request itself, instead of only in the job log. Only the header is included, so that the annotation is not filled with the body of the commit message.
javier-godoy
force-pushed
the
feature/wip-action-required
branch
3 times, most recently
from
September 11, 2026 23:06
b9ac13c to
b0a1feb
Compare
The action reported the outcome the only way it knew, and a caller could not ask for anything else: an invalid commit message and a Work-in-Progress commit both failed the check with the same red X, though only one of them is a defect. A WIP commit is now a warning rather than a failure, and is listed in the results output, so that a caller can report it as a check of its own and the red X is left to mean what it used to mean alone. An invalid commit message still fails. enforce says whether the action reports at all. With false it becomes a pure analyzer: it produces the result for every commit, exits successfully and writes no annotations, so that the caller can render the conclusions, the wording and the annotations itself, without those being compiled into this action. A value other than true or false fails the action rather than being read as the default, so that a misspelling is not silently a policy.
The bundle is rebuilt from the current sources. It also picks up newer patch versions of the bundled dependencies, which is why the diff is larger than the changes that produced it.
The annotation named the offending commit by its header alone, which does not identify it when the same message appears more than once in a pull request, and leaves nothing to look the commit up by. The abbreviated digest now precedes the header. Reading it needs the commits to carry it: the identifier was discarded when the commits of a pull request were mapped to their message, and the commits of a push carry it as id. Both are now mapped to a message and a sha.
A caller that renders the outcome itself builds its annotations from results, which named every commit by its header alone. The digest is now part of each result, so that such a caller can identify the commit and link to it, and the annotations this action writes are not the only ones that can carry it.
The bundle is rebuilt from the current sources.
javier-godoy
force-pushed
the
feature/wip-action-required
branch
from
September 11, 2026 23:39
b0a1feb to
1d75761
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.
Refs FlowingCode/AddonsInternal#99
WIPcommits are a valid, expected state of an unfinished branch, but they were reportedexactly like a genuinely invalid commit message, so the same red ❌ meant two different
things. Rather than settle that here, this branch exposes what the analysis found and lets
the caller decide how to report it (see FlowingCode/GithubActions#7).
Rebased on master
#7 landed the three commit-retrieval fixes, the
typescriptdevDependency and the bundlerebuild that this branch also carried. It has been rebased onto master, where those five
commits dropped out as already applied. The diff against master is now only what this branch
adds:
Changes
feat: expose the result of the analysis through outputsresults, describing every commit as JSON.feat: report invalid commit messages as annotationscore.errorinstead ofcore.infofor an invalid message, so the offending commit and the reason are visible on the pull request itself rather than only in the job log. Only the header is included, so the annotation is not filled with the body of the message.feat: add enforce input for callers that report the outcome themselvesenforce: falsemakes the action a pure analyzer — it producesresults, exits successfully and writes no annotations — so that a caller can report WIP commits as a check run of their own, which can concludeaction_requiredand be both.build: rebuild the dist bundlefeat: include the commit digest in the error annotationsfeat: expose the commit digest in the results outputresults, so the digest is part of every result too, not only of the annotations this action writes.build: rebuild the dist bundleInterface
results{sha, header, level, reason}, wherelevelisvalid,wiporinvalid.enforcetrue.enforce: true(default)enforce: falseA value other than
trueorfalsefails the action rather than being read as the default,so a misspelling is not silently a policy.
enforceis one boolean rather than a modeenumeration because there are only two behaviours left to choose between: whether the action
reports, or the caller does.
resultsis the only output:has-errorsandhas-wipare derivable from it, and theSemantic Versioning level is already exported as the
SEMVER_LEVELenvironment variable. Itis set before the check fails, so it can be read from an
if: always()step, and on everypath — including the one where the commits cannot be retrieved, where it is an empty array.
That path still fails even with
enforce: false, because not being able to analyse anything isa failure of the action itself rather than a finding about the commits.
The default changes nothing. With
enforce: truea WIP commit still fails, exactly as onmaster, so merging this branch moves no existing caller. FlowingCode/AddonsInternal#99 asks for
a pull request that is blocked and not shown as a failure, and a step cannot be both: its
conclusion comes from its exit code. Only a check run can, by concluding
action_required, andonly a caller can create one. So the answer to #99 is
enforce: falseplus that check run —which is what FlowingCode/GithubActions#7 does — and not a default that would leave a caller
without one merging unfinished code behind a green tick.
README.mdgains a Work in Progress section documenting both, with a caller snippet thatreports WIP commits as a separate check run with the
action_requiredconclusion.Verification
npm testpasses (3/3). The built bundle was also run against synthetic push payloads:enforce::error::🚧 Work-in-Progress (WIP) commits found. They must be squashed before rebasing or merging., exit 1falsetrue::error::🚩 9f8e7d6 broken message : The commit header is not formatted according to Conventional Commits., then::error::🚫 According to the…, exit 1,SEMVER_LEVEL=2, and the sha of all three commits inresultsfalse::error::, exit 0yes::error::🚫 The enforce input must be true or false, not "yes"., exit 1End to end in javier-godoy/test-repo
The test pull requests there run
FlowingCode/GithubActions/.github/workflows/check-commits.yml@feature/wip-action-required—the caller in FlowingCode/GithubActions#7, which calls this branch with
enforce: falseandrenders every conclusion itself.
check-commits / check-commitsis the job's own check run,which GitHub creates and which carries no message;
semver-alignmentandwip-commitsarecreated by the caller and carry the verdict.
The annotations below carry the abbreviated digest ahead of the header: the caller reads
shafrom
results, so the commit that must be amended is named rather than only described.resultsbeing ordered and per-commit is what lets the caller go further than this actioncould. It tells a branch that may be squashed at merge time — exactly one non-WIP commit
followed by WIP commits — apart from one the author has to consolidate, purely from the order
and the levels, and the action knows nothing about that policy. Compare
javier-godoy/test-repo#11 with javier-godoy/test-repo#14 below.
javier-godoy/test-repo#13 — valid commit message — ✅
check-commits / check-commitssemver-alignmentwip-commitsNo annotations.
javier-godoy/test-repo#12 — invalid commit message — ❌
check-commits / check-commitssemver-alignmentwip-commitsjavier-godoy/test-repo#11 — a WIP commit, squashable at merge time —⚠️
check-commits / check-commitssemver-alignmentwip-commitsThe action itself did not fail for the WIP commit: the warning is the action's, the failure is
the caller's, and
wip-commitsis what says which problem it was. The history here is onenon-WIP commit followed by a single WIP one, so the caller asks for a Squash and Merge rather
than sending the author back to rebase — contrast javier-godoy/test-repo#14, which has two
non-WIP commits and therefore cannot be collapsed at merge time.
javier-godoy/test-repo#14 — breaking change without a version bump — ❌ on two checks
check-commits / check-commitssemver-alignmentwip-commitsTwo independent problems, each on its own check run, and the job's failure message names both.
javier-godoy/test-repo#17 — every commit message invalid — ❌, level unknown
check-commits / check-commitssemver-alignmentwip-commitsThe action exits 0 under
enforce: falseand the caller fails the job. No message could beparsed, so the level is unknown rather than
NONEand the version is not verified against it.From a fork
javier-godoy/test-repo#19, javier-godoy/test-repo#20 and javier-godoy/test-repo#21 are the same
cases opened from FlowingCode/test-repo2. They confirm the one limitation of leaving the
reporting to the caller: a
pull_requestfrom a fork gets a read-onlyGITHUB_TOKENwhateverthe
permissions:block asks for, sochecks.createanswers 403 there and only the job's owncheck run exists. The annotations are workflow commands and still appear, and the job still
fails, so the outcome is reported either way — only the checks that carry it separately are
missing.
javier-godoy/test-repo#19 — fork, invalid commit message — ❌
check-commits / check-commitsjavier-godoy/test-repo#20 — fork, WIP commits only — ❌
check-commits / check-commitsjavier-godoy/test-repo#21 — fork, valid commit messages — ✅
check-commits / check-commitsNo annotations.
🤖 Generated with Claude Code