Production assemblies, merged across unit and database suites; '
+ 'shared code is counted once. '
+ f'Download the full HTML coverage report ↗ '
+ '(code-coverage artifact; open index.html).
')
+
+
+def render(results, run, coverage=None):
suites = {}
for path in pathlib.Path(results).rglob("*.trx"):
name = path.stem
@@ -27,22 +49,24 @@ def render(results, run):
sha = html.escape(run["head_sha"][:7])
date = html.escape(run["updated_at"])
conclusion = html.escape(run["conclusion"] or "unknown")
- source = f'
CI run · {sha} · {date} · workflow: {conclusion}. Latest completed master run at deployment time.
'
+ source = f'
CI run · {sha} · {date} · workflow: {conclusion}. Latest completed master run at deployment time.
'
+ coverage_html = render_coverage(coverage, run)
if set(suites) != EXPECTED:
- return source + f'
Incomplete test results: {len(suites)} of {len(EXPECTED)} suites available. Full totals unavailable; inspect the run for failures or missing artifacts.
'
+ return source + f'
Incomplete test results: {len(suites)} of {len(EXPECTED)} suites available. Full totals unavailable; inspect the run for failures or missing artifacts.
' + coverage_html
totals = {key: sum(s[key] for s in suites.values()) for key in ("total", "executed", "passed", "failed")}
totals["skipped"] = totals["total"] - totals["executed"]
totals["other"] = totals["executed"] - totals["passed"] - totals["failed"]
counts = '
' + ''.join(f'
{totals[key]:,}{label}
' for key, label in (("executed", "executed"), ("passed", "passed"), ("failed", "failed"), ("skipped", "skipped / not executed"), ("other", "other outcomes"))) + '
'
- return counts + source
+ return counts + coverage_html + source
if __name__ == "__main__":
- results, metadata, page = sys.argv[1:]
+ results, metadata, page = sys.argv[1:4]
+ coverage = sys.argv[4] if len(sys.argv) > 4 else None
target = pathlib.Path(page)
content = target.read_text(encoding="utf-8")
start = ""
end = ""
before, remainder = content.split(start, 1)
_, after = remainder.split(end, 1)
- target.write_text(before + start + "\n" + render(results, json.loads(pathlib.Path(metadata).read_text(encoding="utf-8"))) + "\n" + end + after, encoding="utf-8")
+ target.write_text(before + start + "\n" + render(results, json.loads(pathlib.Path(metadata).read_text(encoding="utf-8")), coverage) + "\n" + end + after, encoding="utf-8")
diff --git a/.github/scripts/test-homepage-tests.py b/.github/scripts/test-homepage-tests.py
index b39a5acc..9d98862d 100644
--- a/.github/scripts/test-homepage-tests.py
+++ b/.github/scripts/test-homepage-tests.py
@@ -51,10 +51,53 @@ def test_duplicate_suite_rejected(self):
with self.assertRaises(ValueError):
renderer.render(self.root, self.run)
- def test_invalid_counts_rejected(self):
+ def test_invalid_counts_rejected(self):
self.populate(passed=8)
with self.assertRaises(ValueError):
- renderer.render(self.root, self.run)
+ renderer.render(self.root, self.run)
+
+ def coverage(self, lines=75, total=100, branches=2, branch_total=3):
+ path = self.root / 'Cobertura.xml'
+ path.write_text(f'')
+ return path
+
+ def test_merged_coverage_and_report_link(self):
+ self.populate()
+ self.run['coverage_url'] = self.run['html_url'] + '/artifacts/123'
+ result = renderer.render(self.root, self.run, self.coverage())
+ for text in ('75.00%line coverage', '66.67%branch coverage',
+ '75 / 100 covered', '2 / 3 covered', '/artifacts/123', '48executed'):
+ self.assertIn(text, result)
+
+ def test_missing_coverage_preserves_test_results(self):
+ self.populate()
+ result = renderer.render(self.root, self.run, self.root / 'missing.xml')
+ self.assertIn('Code coverage unavailable for this run', result)
+ self.assertIn('48executed', result)
+ self.assertNotIn('0.00%', result)
+
+ def test_zero_branches_is_not_zero_percent(self):
+ result = renderer.render(self.root, self.run, self.coverage(branches=0, branch_total=0))
+ self.assertIn('N/Abranch coverage', result)
+
+ def test_invalid_coverage_rejected(self):
+ for values in ({'lines': 101}, {'lines': -1}, {'total': 0}, {'branches': 4}):
+ with self.subTest(values=values), self.assertRaises(ValueError):
+ renderer.render(self.root, self.run, self.coverage(**values))
+
+ def test_incomplete_tests_still_identify_coverage_source(self):
+ result = renderer.render(self.root, self.run, self.coverage())
+ self.assertIn('Incomplete test results: 0 of 12', result)
+ self.assertIn('75.00%', result)
+ self.assertIn('abc1234', result)
+
+ def test_suite_coverage_is_not_used_as_merged_coverage(self):
+ self.populate()
+ self.coverage()
+ result = renderer.render(self.root, self.run)
+ self.assertIn('Code coverage unavailable', result)
+ self.assertNotIn('75.00%', result)
if __name__ == '__main__':
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 7d3192af..6f319e69 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -44,7 +44,7 @@ jobs:
run: |
python3 -B .github/scripts/build-docs.py --check
python3 -B .github/scripts/verify-docs.py
- - name: Verify test-count renderer
+ - name: Verify test-count and coverage renderer
run: python3 .github/scripts/test-homepage-tests.py
- name: Select latest completed master test run
id: tests
@@ -58,6 +58,14 @@ jobs:
});
const run = data.workflow_runs[0];
if (run) {
+ const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
+ ...context.repo, run_id: run.id, per_page: 100
+ });
+ const coverage = artifacts.find(a => a.name === 'code-coverage' && !a.expired);
+ if (coverage) {
+ run.coverage_url = `${run.html_url}/artifacts/${coverage.id}`;
+ core.setOutput('has-coverage', 'true');
+ }
fs.writeFileSync('ci-run.json', JSON.stringify(run));
core.setOutput('run-id', String(run.id));
}
@@ -69,9 +77,17 @@ jobs:
run-id: ${{ steps.tests.outputs.run-id }}
pattern: test-results-*
path: ci-results
- - name: Render test counts and provenance
+ - name: Download merged coverage from the same run
+ if: steps.tests.outputs.has-coverage == 'true'
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ github.token }}
+ run-id: ${{ steps.tests.outputs.run-id }}
+ name: code-coverage
+ path: ci-coverage
+ - name: Render test counts, coverage and provenance
if: steps.tests.outputs.run-id != ''
- run: python3 .github/scripts/render-homepage-tests.py ci-results ci-run.json docs/index.html
+ run: python3 .github/scripts/render-homepage-tests.py ci-results ci-run.json docs/index.html ci-coverage/Cobertura.xml
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v4
with:
diff --git a/README.md b/README.md
index 321a55b2..39adda22 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[](src/Migrator/DotNetProjects.Migrator.csproj)
[](https://www.mozilla.org/en-US/MPL/1.1/)
-[Homepage](https://dotnetprojects.github.io/Migrator.NET/) · [Documentation](https://dotnetprojects.github.io/Migrator.NET/guide/) · [NuGet](https://www.nuget.org/packages/DotNetProjects.Migrator/) · [Releases](https://github.com/dotnetprojects/Migrator.NET/releases) · [Issues](https://github.com/dotnetprojects/Migrator.NET/issues) · [Feature comparison](https://dotnetprojects.github.io/Migrator.NET/#compare) · [CI test counts](https://dotnetprojects.github.io/Migrator.NET/#test-results)
+[Homepage](https://dotnetprojects.github.io/Migrator.NET/) · [Documentation](https://dotnetprojects.github.io/Migrator.NET/guide/) · [NuGet](https://www.nuget.org/packages/DotNetProjects.Migrator/) · [Releases](https://github.com/dotnetprojects/Migrator.NET/releases) · [Issues](https://github.com/dotnetprojects/Migrator.NET/issues) · [Feature comparison](https://dotnetprojects.github.io/Migrator.NET/#compare) · [CI test results & coverage](https://dotnetprojects.github.io/Migrator.NET/#test-results)
DotNetProjects.Migrator is a fork of [Migrator.NET](https://github.com/migratordotnet/Migrator.NET). Write each schema change as a numbered C# class, commit it alongside your application, and use the runner to bring a database to the required version. The database records which migrations have already been applied.
diff --git a/docs/README.md b/docs/README.md
index 341d9d91..ed1bcd22 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -45,13 +45,18 @@ The comparison distinguishes source capabilities from guarantees about released
The quick start targets .NET 9 and installs the core library and SQLite driver through NuGet. Sample validation uses local project references to catch API drift. The SQLite driver version matches the repository test dependency.
-## Status badges and test counts
+## Status badges, test counts and code coverage
The homepage links to master CI results and NuGet, and identifies the MPL-1.1 license.
Pages also redeploys when master CI completes. During deployment it selects the latest
completed master push run (including failures), downloads its TRX artifacts, and renders
executed/passed/failed/skipped/other counts with the run URL, commit and timestamp.
-Counts are a deployment snapshot, not code coverage or a guarantee about every provider.
+The same run supplies the merged `code-coverage` artifact. Pages displays line and branch
+coverage percentages and covered/total counts for production assemblies, with a link to
+the downloadable HTML report (open `index.html`). Shared code is counted once in the
+merged report; suite percentages are never added or averaged. A missing or expired
+coverage artifact is shown as unavailable, never as 0% or replaced by another run.
+Counts and coverage are a deployment snapshot, not a guarantee about every provider.
Missing suites produce an incomplete-results message, never a partial success total.
The committed/local page shows a fallback link until deployment supplies results.
The renderer only changes the uploaded Pages artifact; it does not commit generated counts. Preserve `TEST_RESULTS_START` and `TEST_RESULTS_END` in `_src/home.html`.
diff --git a/docs/_src/home.html b/docs/_src/home.html
index f8897003..77b8e576 100644
--- a/docs/_src/home.html
+++ b/docs/_src/home.html
@@ -25,8 +25,8 @@
Database changes, written in C#.
FROM EMPTY FOLDER TO FIRST TABLE
Start with one change.
Install the library and your database driver. Add the migration above, wire up the runner, and apply it. SQLite makes a convenient first database.
Capabilities follow the database engine. The provider guide explains aliases, drivers and operation-specific behavior.
-
BUILD AND DATABASE TESTS
Evidence from CI.
The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Counts represent test executions across the matrix; skipped tests are shown separately.
The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Counts represent test executions across the matrix; skipped tests are shown separately. Line and branch coverage measure production code across the combined suites.
Open the manual ↗Contribute on GitHub →
diff --git a/docs/assets/site.css b/docs/assets/site.css
index 7d708b18..65556885 100644
--- a/docs/assets/site.css
+++ b/docs/assets/site.css
@@ -553,7 +553,13 @@ img {
font-size:14px;
color:var(--muted);
}
-.test-counts {
+.coverage-counts small {
+ display: block;
+ margin-top: 6px;
+ color: var(--muted);
+ font-size: 12px;
+}
+.test-counts {
display:flex;
list-style:none;
gap:35px;
diff --git a/docs/guide/altering-tables.html b/docs/guide/altering-tables.html
index 0a3121a9..e0c79ec3 100644
--- a/docs/guide/altering-tables.html
+++ b/docs/guide/altering-tables.html
@@ -1,6 +1,6 @@
-Altering tables · Migrator.NETSkip to content
+Altering tables · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/api-map.html b/docs/guide/api-map.html
index e528c382..a1fa55da 100644
--- a/docs/guide/api-map.html
+++ b/docs/guide/api-map.html
@@ -1,6 +1,6 @@
-Classic / Fluent API map · Migrator.NETSkip to content
+Classic / Fluent API map · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/auto-reversing.html b/docs/guide/auto-reversing.html
index 2fb9913e..308e05f6 100644
--- a/docs/guide/auto-reversing.html
+++ b/docs/guide/auto-reversing.html
@@ -1,6 +1,6 @@
-Automatic reversal · Migrator.NETSkip to content
+Automatic reversal · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/cli.html b/docs/guide/cli.html
index 6c5a989a..fbe17d14 100644
--- a/docs/guide/cli.html
+++ b/docs/guide/cli.html
@@ -1,6 +1,6 @@
-Command-line tool · Migrator.NETSkip to content
+Command-line tool · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/columns.html b/docs/guide/columns.html
index a1d22c48..dc76286d 100644
--- a/docs/guide/columns.html
+++ b/docs/guide/columns.html
@@ -1,6 +1,6 @@
-Columns and data types · Migrator.NETSkip to content
+Columns and data types · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/conditional.html b/docs/guide/conditional.html
index faef06f8..cc49fcf5 100644
--- a/docs/guide/conditional.html
+++ b/docs/guide/conditional.html
@@ -1,6 +1,6 @@
-Conditional logic · Migrator.NETSkip to content
+Conditional logic · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/configuration.html b/docs/guide/configuration.html
index 2cb5b409..6f193739 100644
--- a/docs/guide/configuration.html
+++ b/docs/guide/configuration.html
@@ -1,6 +1,6 @@
-Configuration · Migrator.NETSkip to content
+Configuration · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/connections.html b/docs/guide/connections.html
index 051d4ecb..53dd8f3d 100644
--- a/docs/guide/connections.html
+++ b/docs/guide/connections.html
@@ -1,6 +1,6 @@
-Commands and callbacks · Migrator.NETSkip to content
+Commands and callbacks · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/constraints.html b/docs/guide/constraints.html
index b73378d3..50d5e61f 100644
--- a/docs/guide/constraints.html
+++ b/docs/guide/constraints.html
@@ -1,6 +1,6 @@
-Keys and constraints · Migrator.NETSkip to content
+Keys and constraints · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/contributing.html b/docs/guide/contributing.html
index 0e89a2e0..db6331aa 100644
--- a/docs/guide/contributing.html
+++ b/docs/guide/contributing.html
@@ -1,6 +1,6 @@
-Contributing · Migrator.NETSkip to content
+Contributing · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/creating-tables.html b/docs/guide/creating-tables.html
index cb1d124a..8979ab88 100644
--- a/docs/guide/creating-tables.html
+++ b/docs/guide/creating-tables.html
@@ -1,6 +1,6 @@
-Creating tables · Migrator.NETSkip to content
+Creating tables · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/data.html b/docs/guide/data.html
index 1c0bae90..789dbe03 100644
--- a/docs/guide/data.html
+++ b/docs/guide/data.html
@@ -1,6 +1,6 @@
-Data operations · Migrator.NETSkip to content
+Data operations · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/defaults-collations.html b/docs/guide/defaults-collations.html
index b87739e4..c3f9a452 100644
--- a/docs/guide/defaults-collations.html
+++ b/docs/guide/defaults-collations.html
@@ -1,6 +1,6 @@
-Defaults and collations · Migrator.NETSkip to content
+Defaults and collations · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/dependency-injection.html b/docs/guide/dependency-injection.html
index abcf44a9..4214eca3 100644
--- a/docs/guide/dependency-injection.html
+++ b/docs/guide/dependency-injection.html
@@ -1,6 +1,6 @@
-Dependency injection and logging · Migrator.NETSkip to content
+Dependency injection and logging · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/extensions.html b/docs/guide/extensions.html
index b11e31f8..64fade5f 100644
--- a/docs/guide/extensions.html
+++ b/docs/guide/extensions.html
@@ -1,6 +1,6 @@
-Custom extensions · Migrator.NETSkip to content
+Custom extensions · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/faq.html b/docs/guide/faq.html
index be04b250..0086bcb3 100644
--- a/docs/guide/faq.html
+++ b/docs/guide/faq.html
@@ -1,6 +1,6 @@
-Frequently asked questions · Migrator.NETSkip to content
+Frequently asked questions · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/foreign-keys.html b/docs/guide/foreign-keys.html
index 3075f854..e7f19f7a 100644
--- a/docs/guide/foreign-keys.html
+++ b/docs/guide/foreign-keys.html
@@ -1,6 +1,6 @@
-Foreign keys · Migrator.NETSkip to content
+Foreign keys · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/index.html b/docs/guide/index.html
index 88527ec8..c768b315 100644
--- a/docs/guide/index.html
+++ b/docs/guide/index.html
@@ -1,6 +1,6 @@
-The migration manual · Migrator.NETSkip to content
+The migration manual · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/indexes.html b/docs/guide/indexes.html
index 1618946e..fb483eae 100644
--- a/docs/guide/indexes.html
+++ b/docs/guide/indexes.html
@@ -1,6 +1,6 @@
-Indexes · Migrator.NETSkip to content
+Indexes · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/installation.html b/docs/guide/installation.html
index 0c54c888..ca2d3ef6 100644
--- a/docs/guide/installation.html
+++ b/docs/guide/installation.html
@@ -1,6 +1,6 @@
-Installation · Migrator.NETSkip to content
+Installation · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/maintenance.html b/docs/guide/maintenance.html
index d2ba7e1a..a91c4824 100644
--- a/docs/guide/maintenance.html
+++ b/docs/guide/maintenance.html
@@ -1,6 +1,6 @@
-Maintenance migrations · Migrator.NETSkip to content
+Maintenance migrations · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/mysql.html b/docs/guide/mysql.html
index ae16ef51..e2cb09af 100644
--- a/docs/guide/mysql.html
+++ b/docs/guide/mysql.html
@@ -1,6 +1,6 @@
-MySQL and MariaDB · Migrator.NETSkip to content
+MySQL and MariaDB · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/oracle.html b/docs/guide/oracle.html
index 71e7368d..ef3e56f5 100644
--- a/docs/guide/oracle.html
+++ b/docs/guide/oracle.html
@@ -1,6 +1,6 @@
-Oracle · Migrator.NETSkip to content
+Oracle · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/other-providers.html b/docs/guide/other-providers.html
index 82490556..9f9efcfc 100644
--- a/docs/guide/other-providers.html
+++ b/docs/guide/other-providers.html
@@ -1,6 +1,6 @@
-HANA and additional providers · Migrator.NETSkip to content
+HANA and additional providers · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/postgresql.html b/docs/guide/postgresql.html
index f43f636c..d00d44a6 100644
--- a/docs/guide/postgresql.html
+++ b/docs/guide/postgresql.html
@@ -1,6 +1,6 @@
-PostgreSQL · Migrator.NETSkip to content
+PostgreSQL · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/preview.html b/docs/guide/preview.html
index 789fa53e..2f82ca69 100644
--- a/docs/guide/preview.html
+++ b/docs/guide/preview.html
@@ -1,6 +1,6 @@
-Planning and SQL preview · Migrator.NETSkip to content
+Planning and SQL preview · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/profiles.html b/docs/guide/profiles.html
index 06168c0d..0bdaf7e2 100644
--- a/docs/guide/profiles.html
+++ b/docs/guide/profiles.html
@@ -1,6 +1,6 @@
-Profiles · Migrator.NETSkip to content
+Profiles · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/providers.html b/docs/guide/providers.html
index de6be442..0995b7aa 100644
--- a/docs/guide/providers.html
+++ b/docs/guide/providers.html
@@ -1,6 +1,6 @@
-Provider overview · Migrator.NETSkip to content
+Provider overview · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/quick-start.html b/docs/guide/quick-start.html
index cbc8885b..e5571e0c 100644
--- a/docs/guide/quick-start.html
+++ b/docs/guide/quick-start.html
@@ -1,6 +1,6 @@
-Your first migration · Migrator.NETSkip to content
+Your first migration · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/runners.html b/docs/guide/runners.html
index 9b24761c..e03acd23 100644
--- a/docs/guide/runners.html
+++ b/docs/guide/runners.html
@@ -1,6 +1,6 @@
-Choose a runner · Migrator.NETSkip to content
+Choose a runner · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/schema.html b/docs/guide/schema.html
index 3fce2273..38e5841e 100644
--- a/docs/guide/schema.html
+++ b/docs/guide/schema.html
@@ -1,6 +1,6 @@
-Schema inspection · Migrator.NETSkip to content
+Schema inspection · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/sql-server.html b/docs/guide/sql-server.html
index cec02f87..28c40dd1 100644
--- a/docs/guide/sql-server.html
+++ b/docs/guide/sql-server.html
@@ -1,6 +1,6 @@
-SQL Server · Migrator.NETSkip to content
+SQL Server · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/sql.html b/docs/guide/sql.html
index 2ef5085b..826ffcf5 100644
--- a/docs/guide/sql.html
+++ b/docs/guide/sql.html
@@ -1,6 +1,6 @@
-Execute SQL and scripts · Migrator.NETSkip to content
+Execute SQL and scripts · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/sqlite.html b/docs/guide/sqlite.html
index 4b6922b4..717a9e37 100644
--- a/docs/guide/sqlite.html
+++ b/docs/guide/sqlite.html
@@ -1,6 +1,6 @@
-SQLite · Migrator.NETSkip to content
+SQLite · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/tags.html b/docs/guide/tags.html
index d2046ae7..85bb6f09 100644
--- a/docs/guide/tags.html
+++ b/docs/guide/tags.html
@@ -1,6 +1,6 @@
-Tags · Migrator.NETSkip to content
+Tags · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/testing.html b/docs/guide/testing.html
index 8997e61a..a9890408 100644
--- a/docs/guide/testing.html
+++ b/docs/guide/testing.html
@@ -1,6 +1,6 @@
-Testing and deployment · Migrator.NETSkip to content
+Testing and deployment · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/transactions.html b/docs/guide/transactions.html
index 8d5a9b5a..39f8783d 100644
--- a/docs/guide/transactions.html
+++ b/docs/guide/transactions.html
@@ -1,6 +1,6 @@
-Transactions and locks · Migrator.NETSkip to content
+Transactions and locks · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/upgrading.html b/docs/guide/upgrading.html
index 924d58af..5f64f44c 100644
--- a/docs/guide/upgrading.html
+++ b/docs/guide/upgrading.html
@@ -1,6 +1,6 @@
-Upgrading existing migrations · Migrator.NETSkip to content
+Upgrading existing migrations · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/guide/versioning.html b/docs/guide/versioning.html
index 0502fda3..4fe58989 100644
--- a/docs/guide/versioning.html
+++ b/docs/guide/versioning.html
@@ -1,6 +1,6 @@
-Versioning and scoped history · Migrator.NETSkip to content
+Versioning and scoped history · Migrator.NETSkip to content
m↗Migrator.NET
diff --git a/docs/index.html b/docs/index.html
index c6dfd9cf..18bda1ec 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,6 +1,6 @@
-Database changes, written in C# · Migrator.NETSkip to content
+Database changes, written in C# · Migrator.NETSkip to content
Capabilities follow the database engine. The provider guide explains aliases, drivers and operation-specific behavior.
-
BUILD AND DATABASE TESTS
Evidence from CI.
The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Counts represent test executions across the matrix; skipped tests are shown separately.
The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Counts represent test executions across the matrix; skipped tests are shown separately. Line and branch coverage measure production code across the combined suites.