Skip to content

ci: the DCO squash-rewrite equivalence runs both ways - #44

Merged
vyncint merged 1 commit into
mainfrom
ci/dco-squash-rewrite-both-ways
Sep 11, 2026
Merged

vyncint merged 1 commit into
mainfrom
ci/dco-squash-rewrite-both-ways

Conversation

@vyncint

@vyncint vyncint commented Sep 11, 2026

Copy link
Copy Markdown
Owner

main is red, on e1ceae0 (the termlens 0.11 merge):

::error::e1ceae0041bc66c3775cea7d5e43194d7207afa2 lacks a DCO Signed-off-by matching vyncint@icloud.com

Not an attribution problem, and not a missing sign-off. GitHub's squash rewrite pairs an account's real address with its <id>+<login>@users.noreply.github.com form, and which of the two lands in the author field is GitHub's choice. Every merge on this branch before e1ceae0 was authored as the noreply address with the real one in the trailer; e1ceae0 is the same person the other way round:

commit author trailer
4882818 and earlier 115854244+vyncint@users.noreply.github.com vyncint@icloud.com
e1ceae0 vyncint@icloud.com 115854244+vyncint@users.noreply.github.com

The job's own comment already states the rule that covers both — "same person, so a trailer matching the author NAME satisfies it" — but the test read author_email only, so it recognised the rewrite in one direction. The exemption now asks whether either address carries the noreply form, which is the signature of a rewrite, and then requires the names to match. A commit with neither form still needs an exact email match, which is every commit a human makes on a branch.

This widens an exemption, so it was exercised before it was trusted. Six cases against a scratch repository, three of which must fail:

case exit
exact email match 0
noreply author, real trailer (the old rewrite) 0
real author, noreply trailer (the case that broke) 0
a different person's name and address 1
no trailer at all 1
same name, two unrelated addresses, no rewrite marker 1

The amended scan is also green over this repository's entire history.

The alternative — rewriting e1ceae0 — is not available: main is protected and linear, and the next squash merge would reproduce it anyway, since the rewrite is GitHub's behaviour and not something this repository controls.

`main` went red on e1ceae0, the termlens 0.11 merge, with "lacks a DCO
Signed-off-by matching vyncint@icloud.com". Not an attribution problem and
not a missing sign-off: GitHub's squash rewrite pairs an account's real
address with its <id>+<login>@users.noreply.github.com form, and which of
the two lands in the author field is GitHub's choice. Every merge on this
branch before e1ceae0 was authored as the noreply address with the real
one in the trailer; e1ceae0 is the same person the other way round.

The rule the comment already states — same person, so a trailer matching
the author NAME satisfies it — covers both directions. Only the test
assumed one, so it read `author_email` and never the trailer's. The
exemption now asks whether *either* address carries the noreply form,
which is the signature of a rewrite, and then requires the names to match.
A commit with neither form still needs an exact email match, which is
every commit a human makes on a branch.

Exercised against six cases before committing, three of which must fail:
exact match, noreply author with a real trailer, real author with a
noreply trailer (the case that broke), a different person, no trailer at
all, and the same name with two unrelated addresses and no rewrite marker.
The last three exit 1. The amended scan is also green over this
repository's whole history.

Signed-off-by: Vyncint Ng <vyncint@icloud.com>
@vyncint
vyncint merged commit 853a224 into main Sep 11, 2026
14 checks passed
vyncint added a commit that referenced this pull request Sep 13, 2026
…shape (#81)

#44 widened the squash-rewrite exemption by asking whether either address is
the <id>+<login>@users.noreply.github.com form. That shape is a symptom of a
GitHub rewrite, not the rule. An outside contributor's squash landed authored
as <jackchen@haloailabs.com> while every commit they pushed was authored and
signed off as <nightcityblade@gmail.com>: two real addresses, neither a
noreply form, and the exemption could not see it. Two commits on main failed
the scan for this reason, and because the scan walks every reachable commit,
no follow-up commit could clear them.

The signature of a GitHub-composed commit is the committer, which is always
GitHub <noreply@github.com>. The exemption keys on that now, which is the
rule oxidelake and termlens already use.

For such a commit the requirement is that a DCO assertion is present, not
that it matches an address GitHub chose. Matching stays enforced where it
means something: this job runs on every pull request over the contributor's
own commits, which they authored and pushed, and those take the exact-match
branch. A squash cannot reach main without that having passed.

Exercised against crafted commits, each in isolation. Must fail, and does: a
human commit signed by a different person, a human commit with no trailer, a
web-flow commit with no trailer at all, one name with two unrelated addresses
and no web-flow marker, a bot author, an AI co-author trailer, a
generated-with watermark. Must pass, and does: a human commit with a matching
trailer, the contributor-account-address shape, the maintainer-trailer-only
shape, and the owner flip #44 was written for.

What it does not catch is a maintainer dropping a contributor's trailer while
composing a squash body, which is how ca56368 lost mikemikimike's. The
PR-time check is what stands behind the assertion; CONTRIBUTING now says to
carry those trailers.

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
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