govgate 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -0
  3. package/package.json +41 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HatStack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # govgate
2
+
3
+ Pipeline-step CLI for the MT Testing Tool: parses standard test output (JUnit XML),
4
+ maps tests to test cases, reports a run, and **gates the release** via its exit code.
5
+ No SDK in application code — only the pipeline YAML changes.
6
+
7
+ ```
8
+ npx govgate report test-results/junit.xml --env uat
9
+ ```
10
+
11
+ Works identically in GitHub Actions and Azure DevOps. .NET is covered without a NuGet
12
+ package: `dotnet test --logger "junit"` (JunitXml.TestLogger) and point the CLI at the
13
+ output. Jest/Vitest/Playwright/pytest/NUnit/xUnit all emit JUnit XML natively or via a
14
+ standard reporter.
15
+
16
+ ## Commands
17
+
18
+ ### `govgate report <files-or-globs...>`
19
+
20
+ | Flag | Default | Meaning |
21
+ |---|---|---|
22
+ | `--url <url>` | `MT_TESTING_TOOL_URL` | Tool deployment URL |
23
+ | `--api-key <key>` | `MT_TESTING_TOOL_API_KEY` | API key (env var strongly preferred) |
24
+ | `--config <path>` | `.mt-testing.json` searched upward | Config file |
25
+ | `--suite <slug>` | config `suite` | Target suite |
26
+ | `--env <slug>` | config `defaultEnvironment` | Environment for the run |
27
+ | `--name <name>` | derived from CI context | Run name |
28
+ | `--build-version <v>` | short commit SHA from CI | Build version |
29
+ | `--external-url <url>` | CI build URL | "Build ↗" link on the run page |
30
+ | `--format junit` | `junit` | Input format (v1: junit only) |
31
+ | `--run-id <uuid>` | — | Append to an existing run (multi-job) |
32
+ | `--no-complete` | completes | Leave run in progress; skip the gate |
33
+ | `--fail-on <list>` | `fail` | Gate: `fail` or `fail,blocked` |
34
+ | `--min-executed <pct>` | — | Gate: minimum executed percentage |
35
+ | `--actor <label>` | `govgate` | Tested-by label |
36
+ | `--dry-run` | — | Parse + map + print; post nothing |
37
+
38
+ ### `govgate complete --run-id <uuid> [--fail-on ...] [--min-executed ...]`
39
+
40
+ Completes a run left open by `--no-complete` and evaluates the gate over **all** results
41
+ in the run (including those posted by other jobs).
42
+
43
+ ## Exit codes
44
+
45
+ | Code | Meaning |
46
+ |---|---|
47
+ | 0 | Success / gate passed |
48
+ | 1 | **Gate violated** — fail the pipeline step |
49
+ | 2 | Usage or configuration error |
50
+ | 3 | API / network error |
51
+
52
+ Unmapped tests and unknown case numbers are loud warnings, never non-zero exits.
53
+
54
+ ## Mapping tests to cases
55
+
56
+ Resolution per test (results are unioned):
57
+
58
+ 1. **Tags**: any `@mt-<caseNumber>` in the test name or classname —
59
+ `it("completes checkout @mt-2", ...)`.
60
+ 2. **Method-name tokens** (v0.2.0+): for identifier-style names (no whitespace — i.e.
61
+ what .NET JUnit loggers emit), an underscore-delimited `Mt<n>` token maps the test:
62
+ `Mt5_DuplicateEmail_Rejected`, `Profiles_Mt12_NotFound`, `Delete_Resolves_MT28`.
63
+ Embedded substrings (`GMT5_…`, `Format2_…`) do not match.
64
+ 3. **Config patterns** in `.mt-testing.json`:
65
+
66
+ ```jsonc
67
+ {
68
+ "suite": "checkout-regression",
69
+ "defaultEnvironment": "dev",
70
+ "mappings": {
71
+ "4": ["checkout.spec.ts::pays with saved card"],
72
+ "7": ["auth/*.spec.ts::*expired session*", "Login flow > redirects*"],
73
+ "12": ["*newsletter*"]
74
+ }
75
+ }
76
+ ```
77
+
78
+ Pattern grammar: `*` is the only wildcard; matching is case-insensitive against the
79
+ bare test name, or against the full `file::name` id when the pattern contains `::`.
80
+
81
+ Aggregation per case is worst-status-wins: any failing mapped test → `fail`; otherwise
82
+ any passing → `pass`; all skipped → the case is not posted (stays pending — a skipped
83
+ test is a non-observation). Suite cases with no mapped tests stay pending and are
84
+ listed as "uncovered" in the summary.
85
+
86
+ Use the `map-tests` Claude Code skill (in the
87
+ [Maersk-Training/mt-testing-tool](https://github.com/Maersk-Training/mt-testing-tool)
88
+ repo under `skills/`) to generate the mapping semi-automatically, and `--dry-run` to
89
+ validate it.
90
+
91
+ ## .NET specifics (learned the hard way)
92
+
93
+ - **Emit JUnit**: `dotnet add package JunitXml.TestLogger`, then
94
+ `dotnet test --logger "junit;LogFilePath=test-results/junit.xml"`.
95
+ - **The logger writes method names, not `DisplayName`s** — `@mt` tags in DisplayNames
96
+ never reach the XML. Use `Mt<n>` method tokens (above) or `mappings` patterns, and
97
+ keep method names unique across the project. Verify with `--dry-run`.
98
+ - **Two-tier pattern**: `[Trait("Category","Unit")]` (mocked; build-pipeline gate) vs
99
+ `[Trait("Category","Smoke")]` (HTTP against the deployed env; release pipeline,
100
+ after deploy). Filter with `--filter "Category=Unit"` /
101
+ `--TestCaseFilter:"Category=Smoke"`.
102
+ - **Classic Release has no source checkout**: `dotnet publish` the test project into
103
+ the build artifact (`drop/tests/`) and run it with the ".NET Core" task using
104
+ Command `custom` + `vstest` — the `run` command does NOT execute arbitrary commands.
105
+ - The full ADO runbook (variable groups, stage scoping, exact task configs) lives in
106
+ `skills/onboard-repo/reference.md` in the
107
+ [Maersk-Training/mt-testing-tool](https://github.com/Maersk-Training/mt-testing-tool)
108
+ repo — or run the `onboard-repo` skill.
109
+
110
+ ## Multi-job pipelines
111
+
112
+ ```bash
113
+ # job A — creates the run, leaves it open
114
+ govgate report unit-results.xml --no-complete # emits MT_RUN_ID (GH output / ADO variable)
115
+
116
+ # job B — appends to the same run
117
+ govgate report e2e-results.xml --run-id $MT_RUN_ID --no-complete
118
+
119
+ # final job — completes + gates over everything
120
+ govgate complete --run-id $MT_RUN_ID --fail-on fail --min-executed 80
121
+ ```
122
+
123
+ See `docs/examples/github-actions-ci-report.yml` and
124
+ `docs/examples/azure-devops-ci-report.yml` in the
125
+ [Maersk-Training/mt-testing-tool](https://github.com/Maersk-Training/mt-testing-tool)
126
+ repo for full pipelines.
127
+
128
+ ## Registry
129
+
130
+ Published **publicly on npmjs** as `govgate` — it contains no secrets or org-specific
131
+ logic, so any pipeline can `npx govgate …` with **zero registry config and zero
132
+ tokens**. (This deliberately replaced the earlier private GitHub Packages setup, which
133
+ taxed every consuming repo with `.npmrc` + `read:packages` token wiring.)
134
+
135
+ Releasing: push a `v<version>` tag (or run the *Publish* workflow manually). The
136
+ workflow authenticates to npm via **Trusted Publishing (OIDC)** — there is **no
137
+ `NPM_TOKEN` secret**; GitHub Actions mints a short-lived identity per run. One-time
138
+ setup: configure this repo + `publish-cli.yml` as a trusted publisher on the npm
139
+ package's *Settings → Trusted Publishing* page.
140
+
141
+ **No registry at all** (local/dev): run straight from a checkout —
142
+ `node <path-to>/govGate/dist/index.js report …` — or
143
+ `npm exec --package=<path-to>.tgz -- govgate …` after `npm pack`.
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "govgate",
3
+ "version": "0.2.0",
4
+ "description": "Governance gate for releases: report CI test results (JUnit XML) to your testing tool and gate promotion on the outcome.",
5
+ "license": "MIT",
6
+ "author": "HatStack",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Sejersen92/govGate.git"
10
+ },
11
+ "homepage": "https://github.com/Sejersen92/govGate#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/Sejersen92/govGate/issues"
14
+ },
15
+ "type": "module",
16
+ "bin": {
17
+ "govgate": "./dist/index.js"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20"
24
+ },
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "test": "vitest run",
28
+ "typecheck": "tsc --noEmit"
29
+ },
30
+ "dependencies": {
31
+ "commander": "^14.0.2",
32
+ "fast-xml-parser": "^5.3.4",
33
+ "tinyglobby": "^0.2.15"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.19.43",
37
+ "tsup": "^8.5.1",
38
+ "typescript": "^5.9.3",
39
+ "vitest": "^3.2.4"
40
+ }
41
+ }