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.
- package/LICENSE +21 -0
- package/README.md +143 -0
- 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
|
+
}
|