Skip to content

fix(ci): don't fail main on a squash message GitHub wrote - #9

Merged
vyncint merged 1 commit into
mainfrom
fix/dco-squash-artifact
Aug 24, 2026
Merged

fix(ci): don't fail main on a squash message GitHub wrote#9
vyncint merged 1 commit into
mainfrom
fix/dco-squash-artifact

Conversation

@vyncint

@vyncint vyncint commented Aug 24, 2026

Copy link
Copy Markdown
Owner

What & why

Closes #8.

Ports vyncint/termlens#160. The
check-dco.sh here was byte-identical to the one that turned termlens's main
permanently red, and this repo has the same COMMIT_MESSAGES squash setting, so
it was one Update branch press away from the same failure. The issue has the
diagnosis and the evidence.

The change

check-dco.sh takes an optional second argument naming the commit GitHub may
have just composed — the tip of the push, passed as github.event.after, empty
on pull_request runs. Exactly that commit is exempted, and only when it looks
like a composed squash merge: web-flow committer, subject ending (#123), no
sign-off at all. It reports a ::notice:: rather than passing silently.

Deliberately narrow:

  • pull_request runs pass no argument, so nothing is exempt there.
  • Every other commit keeps the strict sign-off-email-matches-author check.
  • A web-flow commit without (#123) still fails, even when named.
  • A commit that merely looks composed but is not the named tip still fails.

A contributor cannot reach the exemption. Being the tip of a push to main
means having gone through a pull request, where the strict check already ran and
is a required status check.

Verification

Not just inherited from upstream — the failure shape was synthesised on a
throwaway branch in this repository: an empty commit with committer
noreply@github.com and subject ending (#1), which fails unnamed and passes
when named as the composed tip. actionlint is clean on the workflow, and both
policy scripts pass on this PR's own commit.

Checklist

  • Linked an issue (Closes #8)
  • Tests added/updated — verified behaviourally here; the recipe for both
    paths is in the script header, matching the existing convention
  • All commits are signed off
  • No AI attribution trailers
  • CHANGELOG.md not updated — CI-only, nothing user-facing

GitHub composes the squash-merge message itself, and when the branch
contains a merge commit it emits an empty body -- the trailers of the
commits it squashed go with it. A pull request in which every commit was
signed off then lands on main carrying no Signed-off-by, and
check-dco.sh fails the push. Pressing "Update branch" is enough to cause
it.

That failure cannot be repaired afterwards: main is linear history,
non-fast-forward, and the ruleset has no bypass actors. The commit is
immutable and the run stays red over a policy that was met.

This happened for real in termlens (vyncint/termlens#159), on a pull
request whose own commit-policy run was green. This repository runs a
byte-identical check-dco.sh against the same COMMIT_MESSAGES squash
setting, so it was one merge commit away from the same permanent red.

The fix, as landed in vyncint/termlens#160: name the one commit that
GitHub composed -- the tip of a push to main, passed as
github.event.after -- and exempt only that, and only when it looks like a
composed squash merge (web-flow committer, subject ending "(#123)", no
sign-off at all). It reports a ::notice::, not silence.

Everything else is unchanged. pull_request runs pass no argument and
exempt nothing, every other commit keeps the strict sign-off==author
check, a web-flow commit without a PR number still fails even when
named, and a commit that merely looks composed but is not the named tip
still fails. A contributor cannot reach the exemption: being the tip of a
push to main means having gone through a pull request that already
passed the strict check.

Verified here, not just upstream: the failure shape was synthesised on a
throwaway branch in this repository and fails unnamed, passes named.
actionlint is clean on the workflow.

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
@vyncint
vyncint merged commit 8047aaf into main Aug 24, 2026
1 check passed
@vyncint
vyncint deleted the fix/dco-squash-artifact branch August 24, 2026 05:39
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.

commit-policy can fail on main when GitHub composes a squash message without the trailers

1 participant