Repository navigation
Description
Problem
main and release/** require four checks on an up-to-date branch (strict). In the 10.2.0 burst on 2026-10-25, eight green PRs had to merge one at a time. Each merge put the next PR behind, so each one cost another full run.
The run is longer than it needs to be. Pack has needs: [ test, integration ], so it starts only once the slowest integration leg and the gate are done. In the last three runs it started at +139 s to +181 s and the wall clock was 261 s to 266 s:
| Run | Test | Slowest integration leg | Gate ends | Pack starts → ends | Wall |
|---|---|---|---|---|---|
| 40181175011 (PR, 10.x) | 110 s | 137 s | +142 s | +144 s → +266 s | 266 s |
| 40181139920 (PR, main) | 107 s | 151 s | +156 s | +158 s → +263 s | 263 s |
| 40181096454 (push, main) | 121 s | 173 s | +179 s | +181 s → +261 s | 261 s |
The gate buys nothing. Pack shares no artifact with Test or Integration. It builds the solution itself and runs its own checks: the README in each package, consumer-smoke-test.sh dist, the SBOMs. A failing test fails the PR through its own required check either way. At release time, release.yml's Verify and pack job builds, runs the whole suite with CI=true, packs, and runs the smoke test against dist before Publish can start. A tag never publishes from the Pack artifact of dotnet.yml.
Change
- Remove
needs: [ test, integration ]frompack, so it runs alongside the other jobs. It still builds, packs, verifies the READMEs, runs./test/consumer-smoke-test.sh distand generates the SBOMs. - The workflow comments say why the gate is not needed.
Expected wall clock: the slowest integration leg plus the gate, about 155 s to 180 s instead of 261 s to 266 s.
Not done: a docs-only fast path
The idea: when a PR changes only docs/** and *.md, the integration legs and Consumer smoke test still report success but skip their steps. Test always runs fully, because OracleCatalogueTests, DocumentedSampleTests and the changelog conventions read the docs.
The mechanics would work. The selection needs no third-party action: on a pull_request run the checkout is the merge commit, so git diff --name-only HEAD^1 HEAD with fetch-depth: 2 lists exactly what the PR changes. Step-level conditions leave every leg success, so the Integration (live PostgreSQL) gate stays correct.
I didn't build it, for two reasons:
- It would weaken a required check.
docs/is not inert for the integration lane.FloatCheckConstraintTestsreads the CHECK constraints from the code block indocs/efcore.mdand runs them against PostgreSQL 16 and 18 (A server-side predicate over a stored NaN or infinite float answers in PostgreSQL's order; only loading throws #232). A PR that broke that SQL would merge green, and only the push run onmainwould catch it. Integration tests read docs/efcore.md and candidates.json as declared inputs, not through the repository root #344 describes exactly this case: the file is read by walking up to the repository root, so it is not an MSBuild input, and no path rule can tell that the lane depends on it. A carve-out fordocs/efcore.mdwould be a hand-kept list that silently goes stale the next time an integration test reads a doc. - It saves almost nothing once
Packis ungated.Packmust still run on a docs-only PR: package READMEs are*.mdand go into the packages, andPackruns the same smoke test in itsdistmode. So a docs-only run would still take as long asTestorPack, whichever is slower (about 105 s to 120 s). Integration is about 155 s to 180 s. The fast path would save about 40 s to 60 s on docs-only PRs. SkippingConsumer smoke testalone saves nothing, becausePackis longer.
The right version of this is #345: a lane map derived from MSBuild, behind the single gate of #341, with #344 making docs/efcore.md a declared input of the integration projects first. Until #344 lands, no docs rule is safe for the integration lane.
Recommendation: release/** strict up-to-date
The ruleset is the maintainer's call; nothing here changes it. With this change one serialized merge costs about 3 minutes instead of 4.5. That helps, but eight PRs are still about 25 minutes of waiting.
Recommended: merge the top of a stack, not each PR. Ports to release/10.x in a burst are usually independent cherry-picks. Stack them (each PR based on the previous one, labelled stacked), let CI run on each, then merge only the top PR into release/10.x. That is one up-to-date run for the batch, and every commit was still tested in a run that contained it. GitHub closes the PRs below as merged when their commits reach the base. The changelog rows conflict at every step of the stack (they always do). They are resolved once, while building the stack, not at every merge.
Alternative: relax strict during a pre-release burst only. Turn off "Require branches to be up to date" on release/** for the burst and turn it back on after the tag. What still guards it: the push run on every merge commit of release/10.x, and #365's release checklist, under which the tag goes only on a commit whose push run is green and release.yml verifies the tag commit again before Publish. The risk is two PRs that pass separately and fail together. That shows up on the push run, after the merge, so it is cheap to find but needs a fix-up PR before the tag. The cost is a setting that has to be turned back on by hand. If it is forgotten, release/10.x stays relaxed.
10.x
release/10.x has its own copy of dotnet.yml, with four integration legs (PostgreSQL 16 and 18 × EF Core floor and newest patch) and the same pack gate. The same change applies there. Is a cherry-pick (-x) to release/10.x wanted? None is opened until it is asked for.
Done when
pack has no needs, the comments say why, and the PR's own run reports its measured wall clock.
Activity
build: run Pack alongside the tests instead of after them (#409)
CaffeinatedCoder commentedon Oct 25, 2026
Measured on PR #410's own run (40181793770, up to date with
main, every check green): 166 s wall clock, down from 261 s to 266 s.Packnow finishes at +103 s. The critical path is the PostgreSQL 18 leg (162 s) plus the gate (2 s).That matches the estimate above, so a serialized merge on a strict branch now costs about 2.8 minutes instead of 4.4. The
release/10.xcopy has four integration legs, so its critical path would be the slowest of those four. In run 40181175011 that was 137 s, which puts it at about 140 s to 145 s with the same change.Still open: should this be cherry-picked to
release/10.x?CaffeinatedCoder commentedon Oct 25, 2026
The 10.x half is PR #412 (cherry-pick
-x, milestone 10.2.0). It's green, at 143 s wall clock on its own run (40182915762), down from 266 s. The critical path is the slowest of the four integration legs (138 s) plus the gate.Pack(122 s) finishes just ahead of it.Closes #409acts only onmain, so #410 closes this issue. #412 needs no separate close.CaffeinatedCoder commentedon Oct 25, 2026
Done on both lines: PR #410 merged into
main(eb81580), and its cherry-pick, PR #412, intorelease/10.x(604b7e1, shipping in 10.3.0). Pack now runs alongside the other jobs on both branches.