Skip to content

mutation-diff charges a stacked unit the whole unmerged chain #1923

Description

@easonLiangWorldedtech

Problem

mutation-diff resolves its base as the merge commit's first parent, which is the base branch tip. For a stacked unit that base is main, so every unmerged ancestor is charged to the unit. The gate measures the chain, not the unit.

Measured on the file-safety chain against main (9af6f87e tip, extension package entry, cap 500):

unit own delta measured against main result
U1 #1910 203 210 green
U2 #1911 27 237 red
U3 #1912 12 250 red
U4 #1913 37 287 red
U5 #1914 225 512 red
U8 #1916 215 727 red
U6 #1915 52 783 red
U7 #1918 33 815 red
U9 #1917 12 827 red

Every unit is individually compliant. The red is a measurement artifact, and it makes the check ineffective for stacked PRs: it reports nothing about the unit under review, and it forces work (further splitting) that would not be needed if the gate measured the unit.

Failure evidence, run for f8d2a8d06:

HEAD_SHA: 12aee9c3ca02263ea3ac6357e0f3495d3ee4852d   # GitHub merge commit, not the PR head
Mutation gate failed: extension has 512 changed executable lines (limit 500).

Design

The merge commit's second parent is the pull request head. When that head's own parent is the head of another open pull request, the pull request is a stacked unit, and that parent is its real base. The diff then contains only the unit's delta.

  • Detection is by graph, not by a label or a mapping file: the parent commit is only accepted when it is another open pull request's head.
  • A pull request whose parent is not another pull request head keeps the event base, so a multi-commit pull request is never charged only its last commit.
  • An unparsable stacked map degrades to the event base instead of throwing.
  • The job summary records which base was used, so a reviewer can tell whether the number is the unit or the chain.
  • The merge-queue enforcement is unchanged: when a unit enters the queue its base is main, so the cumulative cap is still checked at the moment it matters.

With this, all nine units measure their own delta and pass.

Second requirement: reviewer filtering

A reviewer cannot tell a stacked unit apart from a standalone PR in the PR list, so the reconcile
workflow also applies a stacked label to a unit. That half is specified and tracked in #1945 and
delivered by #1925, so this issue is judged against the measurement work only. The label is not a
detection signal here: the gate detects a unit from the commit graph, as specified above.

This issue is closed only after both PRs land.

Implementation

PR: #1924

  • scripts/stryker-diff.mjs — resolveStackedUnitBase + parseStackedMap, wired into the ci command through an optional --stacked-map.
  • .github/workflows/mutation-testing.yml — pull-requests: read, builds the open pull request map with gh api, passes --stacked-map.
  • scripts/stryker-diff.test.mjs — three new cases (stacked parent, non-stacked parent keeps the event base, unparsable map) plus workflow-shape assertions.

Local run: node --test scripts/stryker-diff.test.mjs — 47 tests, 0 fail.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions