Skip to content

feat(check-commits): report WIP commits as a separate check - #7

Draft
javier-godoy wants to merge 3 commits into
mainfrom
feature/wip-action-required
Draft

feat(check-commits): report WIP commits as a separate check#7
javier-godoy wants to merge 3 commits into
mainfrom
feature/wip-action-required

Conversation

@javier-godoy

@javier-godoy javier-godoy commented Sep 9, 2026

Copy link
Copy Markdown
Member

Refs FlowingCode/AddonsInternal#99
Depends on FlowingCode/action-conventional-commits#3

A Pull Request with WIP commits must not be merged, but that is an expected state of an
unfinished branch rather than an error. Reporting it with the same failure as an invalid
commit message made the two indistinguishable.

WIP commits no longer fail the conventional commits step. They are reported as a separate
wip-commits check run with the action_required conclusion, which keeps the merge blocked
without marking the Pull Request as failing.

As a side effect, the version and Semantic Versioning checks now run for Pull Requests that
contain WIP commits, where previously the WIP failure skipped them.

Before merging

  • Add wip-commits to the required status checks of the protected branches, otherwise
    action_required does not block the merge.
  • Decide what to do about Pull Requests from forks (see below).
  • Drop the WIP: commit that points uses: at
    FlowingCode/action-conventional-commits@feature/wip-action-required, and restore
    @master once fix: set VERSION as maven project version instead first version found #3 is merged.

Validated on javier-godoy/test-repo#11

Scenario Result
Valid commit + WIP: commit check-commits success, wip-commits action_required, mergeable_state=unstable
Same, with wip-commits required on the protected branch mergeable_state= blocked
WIP commit squashed away wip-commits success, mergeable_state=clean

So action_required does block the merge when the check is required, and it clears on its own
once the branch is consolidated. The run also confirms that contents: read + checks: write
declared on the caller is enough on a repository whose default workflow permission is
read-only, and that the version and Semantic Versioning steps now run on Pull Requests that
contain WIP commits (previously the WIP failure skipped them).

The caveat above holds: mergeable_state is unstable, not clean, so GitHub still counts
action_required as a non-successful check and the Pull Request reads "Some checks were not
successful"
rather than being green.

Notes for the reviewer

action_required may not fully deliver the requested UX. GitHub's status-check
documentation puts action_required in the failed bucket alongside failure and
timed_out. So this buys a distinct check name and an "Action required" label instead of
"Failing", but the Pull Request rollup will most likely still read "Some checks were not
successful"
. The alternative that does render neutral is a commit status with state
pending (the mechanism the WIP app uses), which is a one-call
swap: checks.createrepos.createCommitStatus, action_requiredpending. Worth
testing both on a scratch PR before we commit to either.

Fork Pull Requests get a read-only token, so checks.create returns 403 regardless of the
permissions: block, the job goes red, and a required wip-commits would leave the Pull
Request stuck on "Expected — waiting for status". The fix is a pull_request_target
companion workflow that reads the commit messages through the API and never checks out the
head of the Pull Request. Until then, do not require wip-commits on repositories that take
contributions from forks.

The permissions: block is a tightening. This job currently inherits the repository
default, which is write on every scope; from now on it gets only contents: read and
checks: write. Both are sufficient for the steps in this workflow, and no caller needs
changes while the callers keep the write default. Note that any future step needing another
scope (e.g. commenting on the Pull Request) must add it explicitly.

checks: write can green a required check. A required status check is satisfied by the
most recent check run of that name, so anything running in this job could fabricate one. That
is inherent to the approach, but it raises the value of pinning
FlowingCode/action-conventional-commits@master to a tag or SHA — happy to do that here if
you want it in the same Pull Request.

🤖 Generated with Claude Code

The check run that GitHub creates for this job cannot carry a message: its
conclusion is derived from the job outcome and its output is empty, so a
pull request showed a failing check without saying why, and a WIP commit was
reported exactly like an invalid commit message.

The action is now asked not to report anything, and this workflow renders the
outcome instead. The offending commits become annotations, the presence of
WIP commits is reported as a check of its own, and the job fails if either
check failed, so that the pull request is marked as failing while the checks
themselves say which one it was.

Nothing here is specific to pull requests: check runs attach to any commit,
so the checks are also reported for the commits of other events.

A pull request from a fork is the exception: it runs with a read-only token
whatever the permissions block asks for, so no check run can be created for
it. Rather than answering 403, the checks are skipped there. The annotations
are workflow commands and still work, and the job still fails, so the outcome
is reported either way; only the checks that carry it separately are missing,
which is why they must not be required on a repository that takes
contributions from forks.
The consistency between the version in the POM and the level of semantic
versioning change described by the commit messages was enforced by failing
this job, which made it indistinguishable from an invalid commit message.
It is now reported as a check of its own, with the version and the level in
its title, and it joins the other checks in failing the job.

Both of its inputs are reported as unknown rather than assumed. The version
is read with if: always(), because reading it does not depend on the commit
check. The level is read from the SEMVER_LEVEL environment variable that the
action exports, and it counts as unknown in two cases: when the action could
not analyse the commit messages at all, which it signals by failing, and
when no commit message could be parsed, because only a valid commit raises
the level and NONE is also what an unparseable pull request leaves behind.
The WIP check is reported as unknown on the first of those paths too,
because an empty result is not evidence of consolidated commits.
The report input is not on action-conventional-commits master yet, so the
workflow has to reference the feature branch for the new behaviour to be
testable from a consumer repository. This commit must be dropped before
merging.
@javier-godoy
javier-godoy force-pushed the feature/wip-action-required branch from 489c90d to 446876c Compare September 10, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant