@automatify-au/cli 0.1.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/README.md +389 -0
  2. package/dist/automatify.js +4011 -0
  3. package/package.json +59 -0
package/README.md ADDED
@@ -0,0 +1,389 @@
1
+ # @automatify-au/cli
2
+
3
+ Minimal Forge-first CLI for Automatify Jira TestOps.
4
+
5
+ Current product stance:
6
+ - Jira UI is the primary day-to-day surface for most users.
7
+ - The CLI is the primary admin and automation surface for setup, ingestion, diagnostics, reporting, and CI.
8
+ - POC audience: operators, CI, internal support, and customer admins running controlled setup/import flows.
9
+ - Future customer-admin packaging is expected before any broader distribution.
10
+ - Any future all-user CLI requires a different auth/onboarding model than the current project-scoped admin key transport.
11
+
12
+ ## Architecture boundary (must hold)
13
+ - Thin client only.
14
+ - No separate backend.
15
+ - No duplicate domain/business logic in CLI.
16
+ - CLI commands must call shared Forge contracts (resolver/webtrigger paths) as they are introduced.
17
+
18
+ ## MVP non-goals
19
+ - No separate backend.
20
+ - No duplicate domain/business logic in CLI.
21
+ - No replacement of Jira UI as a primary product surface.
22
+ - No backend-assisted/hybrid logic in this phase.
23
+
24
+ ## Install and run
25
+
26
+ ### From npm (published package)
27
+ ```bash
28
+ npm install -g @automatify-au/cli
29
+ automatify --help
30
+ automatify testops --help
31
+ ```
32
+
33
+ ### From repository (development)
34
+ ```bash
35
+ pnpm install
36
+ pnpm --filter @automatify-au/cli build
37
+ pnpm --filter @automatify-au/cli bundle
38
+ ```
39
+
40
+ This produces a single self-contained bundle at `dist/automatify.js` (≈125 KB) with `@automatify/shared-types` inlined. No runtime dependencies.
41
+
42
+ Run built CLI:
43
+ ```bash
44
+ automatify testops --help # if linked globally (npm link)
45
+ node apps/cli/dist/automatify.js --help # direct node run
46
+ ```
47
+
48
+ Dev run (for local iteration):
49
+ ```bash
50
+ pnpm --filter @automatify-au/cli run cli:dev -- --help
51
+ ```
52
+
53
+ ### Bundle and publish
54
+ ```bash
55
+ cd apps/cli
56
+ npm test # optional but recommended local preflight
57
+ npm pack --dry-run # inspect final tarball contents
58
+ npm publish --dry-run --access public # simulate publish against npm
59
+ npm publish --access public # publish to npm
60
+ ```
61
+
62
+ Publish notes:
63
+ - `prepack` now rebuilds `dist/automatify.js` automatically, so `npm pack` and `npm publish` do not rely on a stale bundle.
64
+ - `prepublishOnly` runs the CLI test suite and then rebuilds the bundle before a real publish.
65
+ - Current package target is `@automatify-au/cli`; verify npm auth with `npm whoami` if needed before publishing.
66
+
67
+ ## Required configuration
68
+ Minimum:
69
+ - `JIRA_BASE_URL`
70
+ - At least one of `JIRA_PROJECT_KEY` or `JIRA_ISSUE_KEY`
71
+ - `TESTOPS_FORGE_ENDPOINT` for commands that call Forge contracts (`doctor`, `ingest`, `run`, `sync`)
72
+ - `TESTOPS_FORGE_AUTH_TOKEN` from the one-time token shown in Forge `Operations -> CLI access`
73
+
74
+ Optional:
75
+ - `TESTOPS_FORGE_TIMEOUT_MS`
76
+ - `TESTOPS_FORGE_MAX_RETRIES`
77
+ - `TESTOPS_FORGE_RETRY_DELAY_MS`
78
+ - `TESTOPS_AUTH_MODE`, `JIRA_EMAIL`, `JIRA_API_TOKEN` (when auth mode requires)
79
+
80
+ ## Command reference (MVP)
81
+
82
+ All TestOps commands are invoked as `automatify testops <command>`:
83
+
84
+ - `bdd`
85
+ - `automatify testops bdd scenarios show --id <SCENARIO_ID>`
86
+ - `cases`
87
+ - `automatify testops cases list`
88
+ - `automatify testops cases show --key <TEST_CASE_KEY>`
89
+ - `automatify testops cases bdd list --key <TEST_CASE_KEY>`
90
+ - `automatify testops cases runs list --key <TEST_CASE_KEY>`
91
+ - `config`
92
+ - `automatify testops config show`
93
+ - `automatify testops config validate`
94
+ - `ingest`
95
+ - `automatify testops ingest feature --file <path>` or `--stdin`
96
+ - `run`
97
+ - `automatify testops run upload --file <path>` or `--stdin`
98
+ - `runs`
99
+ - `automatify testops runs show --id <RUN_ID>`
100
+ - `suites`
101
+ - `automatify testops suites list`
102
+ - `automatify testops suites show --key <SUITE_KEY>`
103
+ - `automatify testops suites cases list --key <SUITE_KEY>`
104
+ - `doctor`
105
+ - `automatify testops doctor check`
106
+ - `automatify testops doctor check --json`
107
+ - `sync` (gated)
108
+ - enable with `TESTOPS_ENABLE_SYNC=1`
109
+ - `automatify testops sync status`
110
+ - `automatify testops sync reconcile --confirm RECONCILE`
111
+
112
+ ## `automatify testops auto` (MVP)
113
+ Purpose:
114
+ - deterministic onboarding/import helper for local and CI workflows.
115
+ - thin orchestration only; domain logic stays in Forge contracts/services.
116
+
117
+ Supported commands:
118
+ - `automatify testops auto --dry-run`
119
+ - `automatify testops auto`
120
+
121
+ Required env/config for real upload mode:
122
+ - `JIRA_BASE_URL`
123
+ - `JIRA_PROJECT_KEY` (or `--project-key`)
124
+ - `TESTOPS_FORGE_ENDPOINT`
125
+ - `TESTOPS_FORGE_AUTH_TOKEN` for the repo-owned authenticated webtrigger transport
126
+
127
+ One-time Forge transport setup:
128
+ ```bash
129
+ cd apps/forge
130
+ forge deploy
131
+ forge install --upgrade --site automatify-com-au.atlassian.net --product Jira -e development --confirm-scopes --non-interactive
132
+ forge webtrigger create --functionKey cli-transport-webtrigger --site automatify-com-au.atlassian.net --product Jira -e development
133
+ ```
134
+
135
+ Then open the Jira project page, go to `Operations -> CLI access`, create a CLI key, and copy the token immediately. It is shown once only.
136
+
137
+ Export the webtrigger URL and the one-time token for CLI use:
138
+ ```bash
139
+ export TESTOPS_FORGE_ENDPOINT="<webtrigger-url>"
140
+ export TESTOPS_FORGE_AUTH_TOKEN="<one-time-token-from-forge-ui>"
141
+ export JIRA_BASE_URL="https://automatify-com-au.atlassian.net"
142
+ export JIRA_PROJECT_KEY="DEV"
143
+ ```
144
+
145
+ Transport notes:
146
+ - Bearer auth is required for operator/CI use. Forge stores only the token hash plus metadata.
147
+ - Tokens are project-scoped, shown once at creation time, and can be revoked from the Forge UI.
148
+ - Expired or revoked tokens are rejected by the transport.
149
+
150
+ Scenario automation callback example:
151
+ ```bash
152
+ curl -sS "$TESTOPS_FORGE_ENDPOINT" \
153
+ -H "authorization: Bearer $TESTOPS_FORGE_AUTH_TOKEN" \
154
+ -H "content-type: application/json" \
155
+ -d '{
156
+ "contract":"updateScenarioAutomationStatus",
157
+ "payload":{
158
+ "context":{"projectKey":"DEV"},
159
+ "scenarioId":"manual:checkout:guest-payment",
160
+ "status":"running",
161
+ "externalRunId":"gha-1024",
162
+ "externalRunUrl":"https://github.com/Automatify-Pty-Ltd/automatify-jira-testops/actions/runs/1024",
163
+ "responseStatus":202,
164
+ "responseSnippet":"workflow is running"
165
+ }
166
+ }' | jq
167
+ ```
168
+
169
+ You can also resolve the target by `automationId` or `scenarioRef` instead of `scenarioId`.
170
+
171
+ GitHub Actions callback example:
172
+ ```yaml
173
+ - name: Report scenario automation status to Forge
174
+ if: ${{ always() }}
175
+ env:
176
+ TESTOPS_FORGE_ENDPOINT: ${{ secrets.TESTOPS_FORGE_ENDPOINT }}
177
+ TESTOPS_FORGE_AUTH_TOKEN: ${{ secrets.TESTOPS_FORGE_AUTH_TOKEN }}
178
+ TESTOPS_PROJECT_KEY: DEV
179
+ TESTOPS_SCENARIO_REF: checkout.feature#3
180
+ TESTOPS_STATUS: ${{ job.status == 'success' && 'passed' || job.status == 'cancelled' && 'cancelled' || 'failed' }}
181
+ run: |
182
+ curl -sS "$TESTOPS_FORGE_ENDPOINT" \
183
+ -H "authorization: Bearer $TESTOPS_FORGE_AUTH_TOKEN" \
184
+ -H "content-type: application/json" \
185
+ -d "{
186
+ \"contract\":\"updateScenarioAutomationStatus\",
187
+ \"payload\":{
188
+ \"context\":{\"projectKey\":\"$TESTOPS_PROJECT_KEY\"},
189
+ \"scenarioRef\":\"$TESTOPS_SCENARIO_REF\",
190
+ \"status\":\"$TESTOPS_STATUS\",
191
+ \"externalRunId\":\"${GITHUB_RUN_ID}\",
192
+ \"externalRunUrl\":\"https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\",
193
+ \"responseStatus\":200,
194
+ \"responseSnippet\":\"GitHub Actions callback from ${GITHUB_WORKFLOW}\"
195
+ }
196
+ }"
197
+ ```
198
+
199
+ Azure DevOps callback example:
200
+ ```yaml
201
+ - bash: |
202
+ set -euo pipefail
203
+ if [ "$(Agent.JobStatus)" = "Succeeded" ]; then
204
+ TESTOPS_STATUS="passed"
205
+ elif [ "$(Agent.JobStatus)" = "Canceled" ]; then
206
+ TESTOPS_STATUS="cancelled"
207
+ else
208
+ TESTOPS_STATUS="failed"
209
+ fi
210
+
211
+ curl -sS "$(TESTOPS_FORGE_ENDPOINT)" \
212
+ -H "authorization: Bearer $(TESTOPS_FORGE_AUTH_TOKEN)" \
213
+ -H "content-type: application/json" \
214
+ -d "{
215
+ \"contract\":\"updateScenarioAutomationStatus\",
216
+ \"payload\":{
217
+ \"context\":{\"projectKey\":\"DEV\"},
218
+ \"scenarioRef\":\"checkout.feature#3\",
219
+ \"status\":\"${TESTOPS_STATUS}\",
220
+ \"externalRunId\":\"$(Build.BuildId)\",
221
+ \"externalRunUrl\":\"$(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)\",
222
+ \"responseStatus\":200,
223
+ \"responseSnippet\":\"Azure DevOps callback from $(Build.DefinitionName)\"
224
+ }
225
+ }"
226
+ displayName: Report scenario automation status to Forge
227
+ ```
228
+
229
+ Hierarchy browse examples:
230
+ ```bash
231
+ automatify testops cases list --project-key DEV
232
+ automatify testops cases show --project-key DEV --key TC-1 --json
233
+ automatify testops cases bdd list --project-key DEV --key TC-1 --json
234
+ automatify testops cases runs list --project-key DEV --key TC-1 --json
235
+ automatify testops bdd scenarios show --project-key DEV --id <SCENARIO_ID> --json
236
+ automatify testops runs show --project-key DEV --id <RUN_ID> --json
237
+ automatify testops suites list --project-key DEV --json
238
+ automatify testops suites cases list --project-key DEV --key TS-1
239
+ ```
240
+
241
+ Recommended hierarchy browse flow:
242
+ ```bash
243
+ # 1. Find a case worth inspecting.
244
+ automatify testops cases list --project-key DEV
245
+
246
+ # 2. Inspect one case in detail.
247
+ automatify testops cases show --project-key DEV --key TC-145 --json
248
+
249
+ # 3. Inspect the BDD scenarios linked to that case.
250
+ automatify testops cases bdd list --project-key DEV --key TC-145 --json
251
+
252
+ # 4. Inspect the execution history linked to that case.
253
+ automatify testops cases runs list --project-key DEV --key TC-145 --json
254
+
255
+ # 5. Drill into one scenario or one run as needed.
256
+ automatify testops bdd scenarios show --project-key DEV --id <SCENARIO_ID> --json
257
+ automatify testops runs show --project-key DEV --id <RUN_ID> --json
258
+ ```
259
+
260
+ Coverage and readiness report via the Forge transport:
261
+ ```bash
262
+ curl -sS "$TESTOPS_FORGE_ENDPOINT" \
263
+ -H "authorization: Bearer $TESTOPS_FORGE_AUTH_TOKEN" \
264
+ -H "content-type: application/json" \
265
+ -d '{"contract":"getCoverageReport","payload":{"context":{"projectKey":"DEV"}}}' | jq
266
+ ```
267
+
268
+ Deterministic dry-run preview (human):
269
+ ```bash
270
+ pnpm --filter @automatify-au/cli build
271
+ automatify testops auto \
272
+ --dry-run \
273
+ --root apps/cli/test-fixtures/auto/execution-layout
274
+ ```
275
+
276
+ Deterministic dry-run preview (JSON for CI):
277
+ ```bash
278
+ preview_json="$(automatify testops auto \
279
+ --dry-run \
280
+ --root apps/cli/test-fixtures/auto/execution-layout \
281
+ --output json)"
282
+ echo "$preview_json"
283
+ node -e 'const p=JSON.parse(process.argv[1]); if(!p.preview || !p.preview.mapping){process.exit(2)}' "$preview_json"
284
+ ```
285
+
286
+ Real execution mode (Forge upload path):
287
+ ```bash
288
+ automatify testops auto \
289
+ --root apps/cli/test-fixtures/auto/execution-layout \
290
+ --project-key DEV \
291
+ --force \
292
+ --output json
293
+ ```
294
+
295
+ Recommended CI sequence:
296
+ 1. `automatify testops config validate`
297
+ 2. `automatify testops doctor check --json`
298
+ 3. `automatify testops auto --dry-run --output json ...`
299
+ 4. `automatify testops auto --force --output json ...`
300
+
301
+ `automatify testops auto` MVP limits (explicit):
302
+ - detection scope is Playwright, pytest, cucumber/behave hints only.
303
+ - artifact scope is JUnit XML + Cucumber JSON + `.feature` files.
304
+ - mapping is deterministic MVP only (issue-key and supported exact-name matching).
305
+ - no AI-based matching, no backend-assisted matching, no storage surgery actions.
306
+
307
+ ### `automatify testops auto` pilot adoption checklist
308
+ 1. Run deterministic preview:
309
+ - `automatify testops auto --dry-run --output json --root <repo-root>`
310
+ 2. Confirm preview is actionable:
311
+ - framework mode is not `unknown` unless expected,
312
+ - discovered artifacts count is non-zero for upload scenarios,
313
+ - unmatched diagnostics are reviewed.
314
+ 3. Verify readiness gate:
315
+ - `automatify testops doctor check --json`
316
+ 4. Run first real upload in controlled branch/commit:
317
+ - `automatify testops auto --force --output json --project-key <KEY> --root <repo-root>`
318
+ 5. Record command result and warnings in pilot notes.
319
+
320
+ ## Deterministic exit-code mapping
321
+ - `0` success
322
+ - `1` internal/runtime error
323
+ - `2` usage/argument errors
324
+ - `3` local validation errors
325
+ - `4` Forge service errors (`ok: false` payload)
326
+ - `5` Forge transport/connectivity errors
327
+
328
+ ## CI usage examples
329
+
330
+ Doctor preflight with JSON parsing:
331
+ ```bash
332
+ set -euo pipefail
333
+ pnpm --filter @automatify-au/cli build
334
+ export TESTOPS_FORGE_ENDPOINT="${TESTOPS_FORGE_ENDPOINT:?missing}"
335
+ export JIRA_BASE_URL="${JIRA_BASE_URL:?missing}"
336
+ export JIRA_PROJECT_KEY="${JIRA_PROJECT_KEY:?missing}"
337
+
338
+ doctor_json="$(automatify testops doctor check --json)"
339
+ echo "$doctor_json"
340
+ node -e 'const d=JSON.parse(process.argv[1]); if(!d.status){process.exit(2)}' "$doctor_json"
341
+ ```
342
+
343
+ Feature ingest from file:
344
+ ```bash
345
+ pnpm --filter @automatify-au/cli build
346
+ automatify testops ingest feature \
347
+ --file ./artifacts/checkout.feature \
348
+ --project-key DEV
349
+ ```
350
+
351
+ Run upload from file with CI-friendly branching:
352
+ ```bash
353
+ set +e
354
+ pnpm --filter @automatify-au/cli build
355
+ automatify testops run upload \
356
+ --file ./artifacts/run.json \
357
+ --project-key DEV \
358
+ --json
359
+ code=$?
360
+ set -e
361
+
362
+ case "$code" in
363
+ 0) echo "run upload succeeded" ;;
364
+ 2|3) echo "usage/validation issue, fail fast" ; exit "$code" ;;
365
+ 4) echo "Forge service rejected payload" ; exit "$code" ;;
366
+ 5) echo "Forge connectivity issue, consider retry" ; exit "$code" ;;
367
+ *) echo "unexpected failure" ; exit "$code" ;;
368
+ esac
369
+ ```
370
+
371
+ ## Adoption checklist (MVP)
372
+ 1. Build CLI:
373
+ - `pnpm --filter @automatify-au/cli build && pnpm --filter @automatify-au/cli bundle`
374
+ 2. Validate config:
375
+ - `automatify testops config validate`
376
+ 3. Run doctor preflight:
377
+ - `automatify testops doctor check --json`
378
+ 4. Ingest one sample feature:
379
+ - `automatify testops ingest feature --file ./artifacts/checkout.feature --project-key DEV`
380
+ 5. Upload one sample run:
381
+ - `automatify testops run upload --file ./artifacts/run.json --project-key DEV --json`
382
+ 6. (Optional) Verify sync:
383
+ - `TESTOPS_ENABLE_SYNC=1 automatify testops sync status`
384
+
385
+ ## Runbook integration
386
+ - Pilot onboarding/operator triage snippets:
387
+ - `PILOT_ONBOARDING.md`
388
+ - Release and rollback flow:
389
+ - `RELEASE_RUNBOOK.md`