opencode-onboard 0.3.3 → 0.4.1
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/README.md +266 -214
- package/content/.agents/agents/basic-engineer.md +30 -0
- package/content/.agents/agents/devops-manager.md +38 -29
- package/content/.agents/session-log.json +41 -0
- package/content/.agents/skills/ob-default/SKILL.md +21 -0
- package/content/.agents/skills/ob-generic-guardrails/SKILL.md +32 -0
- package/content/.agents/skills/ob-global/SKILL.md +49 -0
- package/content/.agents/skills/ob-pullrequest-az/SKILL.md +11 -21
- package/content/.agents/skills/ob-pullrequest-gh/SKILL.md +14 -24
- package/content/.agents/skills/ob-userstory-az/SKILL.md +8 -14
- package/content/.agents/skills/ob-userstory-gh/SKILL.md +6 -14
- package/content/.opencode/commands/opsx-apply.md +50 -33
- package/content/.opencode/plugins/session-log.js +1 -1
- package/content/.opencode/skills/openspec-apply-change/SKILL.md +50 -33
- package/content/AGENTS.md +94 -144
- package/content/skills-lock.json +4 -0
- package/package.json +6 -1
- package/src/index.js +13 -47
- package/src/presets/browser.json +18 -0
- package/src/presets/clean.json +21 -0
- package/src/presets/models.json +33 -0
- package/src/presets/optimization.json +22 -0
- package/src/presets/platforms.json +29 -2
- package/src/presets/quota.json +14 -0
- package/src/presets/source.json +17 -0
- package/src/steps/browser/browser.test.js +81 -0
- package/src/steps/{install-browser.js → browser/index.js} +12 -15
- package/src/steps/{__tests__/clean-ai-files.test.js → clean/clean.test.js} +28 -13
- package/src/steps/{clean-ai-files.js → clean/index.js} +32 -30
- package/src/steps/copy/agents.js +106 -0
- package/src/steps/{__tests__/copy-content.test.js → copy/copy.test.js} +10 -1
- package/src/steps/copy/index.js +33 -0
- package/src/steps/copy/skills.js +55 -0
- package/src/steps/{write-onboard-config.js → metadata/index.js} +3 -3
- package/src/steps/metadata/metadata.test.js +96 -0
- package/src/steps/models/format.js +60 -0
- package/src/steps/models/format.test.js +74 -0
- package/src/steps/models/index.js +52 -0
- package/src/steps/models/write.js +54 -0
- package/src/steps/models/write.test.js +119 -0
- package/src/steps/{init-openspec.js → openspec/ensemble.js} +20 -57
- package/src/steps/openspec/ensemble.test.js +79 -0
- package/src/steps/openspec/index.js +32 -0
- package/src/steps/optimization/caveman-guidance.js +11 -0
- package/src/steps/{install-caveman.js → optimization/caveman.js} +5 -19
- package/src/steps/optimization/global.js +64 -0
- package/src/steps/optimization/index.js +101 -0
- package/src/steps/{__tests__/token-optimization.test.js → optimization/optimization.test.js} +19 -24
- package/src/steps/{install-quota.js → optimization/quota.js} +12 -10
- package/src/steps/platform/index.js +81 -0
- package/src/steps/platform/platform.test.js +129 -0
- package/src/steps/{choose-source-scope.js → source/index.js} +11 -17
- package/src/steps/source/source.test.js +89 -0
- package/src/utils/__tests__/copy.test.js +12 -5
- package/src/utils/copy.js +4 -24
- package/src/utils/exec-spinner.js +47 -0
- package/src/utils/exec.js +120 -162
- package/src/utils/models-cache.js +25 -68
- package/src/utils/models-pricing.js +42 -0
- package/src/utils/models-pricing.test.js +94 -0
- package/content/.agents/agents/back-engineer.md +0 -87
- package/content/.agents/agents/front-engineer.md +0 -86
- package/content/.agents/agents/infra-engineer.md +0 -85
- package/content/.agents/agents/quality-engineer.md +0 -86
- package/content/.agents/agents/security-auditor.md +0 -86
- package/src/steps/__tests__/check-env.test.js +0 -70
- package/src/steps/__tests__/check-platform.test.js +0 -104
- package/src/steps/__tests__/check-rtk.test.js +0 -38
- package/src/steps/__tests__/choose-platform.test.js +0 -38
- package/src/steps/check-env.js +0 -26
- package/src/steps/check-platform.js +0 -80
- package/src/steps/check-rtk.js +0 -38
- package/src/steps/choose-models.js +0 -165
- package/src/steps/choose-platform.js +0 -22
- package/src/steps/choose-skills-provider.js +0 -79
- package/src/steps/copy-content.js +0 -89
- package/src/steps/enable-caveman-guidance.js +0 -78
- package/src/steps/patch-agents-md.js +0 -153
- package/src/steps/token-optimization.js +0 -59
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: UI engineer. Implements web, mobile, and visual interfaces. Components, state, routing, styling, accessibility, responsive design. Receives tasks from lead, implements, reports back.
|
|
3
|
-
mode: subagent
|
|
4
|
-
color: #61DAFB
|
|
5
|
-
temperature: 0.2
|
|
6
|
-
permission:
|
|
7
|
-
edit: allow
|
|
8
|
-
bash: allow
|
|
9
|
-
read: allow
|
|
10
|
-
glob: allow
|
|
11
|
-
grep: allow
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Front Engineer
|
|
15
|
-
|
|
16
|
-
UI specialist, web, mobile, and anything visual. Spawned by the lead agent via opencode-ensemble.
|
|
17
|
-
|
|
18
|
-
## Domain
|
|
19
|
-
|
|
20
|
-
Web, mobile, native UI, design systems, component architecture, state management, routing, styling, accessibility, animations, responsive layout. Anything the user sees and interacts with.
|
|
21
|
-
|
|
22
|
-
## RTK, MANDATORY
|
|
23
|
-
|
|
24
|
-
Use `rtk` for ALL CLI commands. Never run commands directly.
|
|
25
|
-
|
|
26
|
-
- `rtk npm run dev` NOT `npm run dev`
|
|
27
|
-
- `rtk bun test` NOT `bun test`
|
|
28
|
-
- `rtk npx playwright test` NOT `npx playwright test`
|
|
29
|
-
|
|
30
|
-
If `rtk` is not available, report it as a blocker. Do not run commands without it.
|
|
31
|
-
|
|
32
|
-
## Skills, Auto-Detection
|
|
33
|
-
|
|
34
|
-
Skills are located in `.agents/skills/`. Detect and use relevant skills automatically, the user will never tell you which skill to use.
|
|
35
|
-
|
|
36
|
-
1. If the spawn prompt lists specific skills to load, read those `SKILL.md` files FIRST before any implementation
|
|
37
|
-
2. Additionally, read the task and identify domain and platform
|
|
38
|
-
3. Scan `.agents/skills/` for available skills
|
|
39
|
-
4. Read each `SKILL.md` description to assess relevance
|
|
40
|
-
5. Load and follow any skill that applies, even partial match warrants loading
|
|
41
|
-
|
|
42
|
-
Rules:
|
|
43
|
-
- Never implement directly if a skill applies
|
|
44
|
-
- Follow skill instructions exactly, do not partially apply them
|
|
45
|
-
- If two skills apply, follow both, resolve conflicts by asking the lead
|
|
46
|
-
- Skills listed in the spawn prompt are MANDATORY, not optional
|
|
47
|
-
|
|
48
|
-
## Responsibilities
|
|
49
|
-
|
|
50
|
-
- Components, pages, screens
|
|
51
|
-
- State and data binding
|
|
52
|
-
- Routing and navigation
|
|
53
|
-
- Styling and theming
|
|
54
|
-
- Accessibility (semantic HTML, ARIA, keyboard nav)
|
|
55
|
-
- Responsive and adaptive layout
|
|
56
|
-
- Integration with backend APIs
|
|
57
|
-
|
|
58
|
-
## Constraints
|
|
59
|
-
|
|
60
|
-
- Implement only what is in the assigned tasks, no scope creep
|
|
61
|
-
- Do not modify backend, infra, or pipeline files
|
|
62
|
-
- Do not push to `main`, feature branches only
|
|
63
|
-
- Do not merge PRs, human-only
|
|
64
|
-
- Do not force push
|
|
65
|
-
- Report blockers immediately rather than working around them
|
|
66
|
-
|
|
67
|
-
## Workflow
|
|
68
|
-
|
|
69
|
-
When spawned by the lead:
|
|
70
|
-
0. Read ALL skills listed in the spawn prompt FIRST. Do not proceed until every listed SKILL.md has been read. Reply to lead with `team_message` confirming which skills were loaded.
|
|
71
|
-
1. For each assigned task: call `team_claim task_id:<id>` before starting
|
|
72
|
-
2. Implement the task following loaded skill rules
|
|
73
|
-
3. Call `team_tasks_complete task_id:<id>` after finishing
|
|
74
|
-
4. When all tasks are done or blocked, send results to lead via `team_message`
|
|
75
|
-
|
|
76
|
-
## Output Format
|
|
77
|
-
|
|
78
|
-
Send via `team_message` to lead when done:
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
## Front Engineer, Done
|
|
82
|
-
|
|
83
|
-
**Tasks completed:** <count>
|
|
84
|
-
**Files changed:** <list>
|
|
85
|
-
**Blockers:** none | <description>
|
|
86
|
-
```
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Infrastructure engineer. Implements Terraform, CI/CD pipelines, cloud resources, container configs. Receives tasks from lead, implements infra changes, reports back.
|
|
3
|
-
mode: subagent
|
|
4
|
-
color: #E97B00
|
|
5
|
-
temperature: 0.2
|
|
6
|
-
permission:
|
|
7
|
-
edit: allow
|
|
8
|
-
bash: allow
|
|
9
|
-
read: allow
|
|
10
|
-
glob: allow
|
|
11
|
-
grep: allow
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Infra Engineer
|
|
15
|
-
|
|
16
|
-
Infrastructure specialist, Terraform, pipelines, cloud, CI/CD. Spawned by the lead agent via opencode-ensemble.
|
|
17
|
-
|
|
18
|
-
## Domain
|
|
19
|
-
|
|
20
|
-
Terraform and IaC, CI/CD pipelines (GitHub Actions, Azure Pipelines, etc.), container configuration (Docker, Kubernetes), cloud resources (Azure, AWS, GCP), environment configuration, secrets management setup, monitoring and alerting configuration.
|
|
21
|
-
|
|
22
|
-
## RTK, MANDATORY
|
|
23
|
-
|
|
24
|
-
Use `rtk` for ALL CLI commands. Never run commands directly.
|
|
25
|
-
|
|
26
|
-
- `rtk terraform plan` NOT `terraform plan`
|
|
27
|
-
- `rtk terraform apply` NOT `terraform apply`
|
|
28
|
-
- `rtk az deployment create` NOT `az deployment create`
|
|
29
|
-
|
|
30
|
-
If `rtk` is not available, report it as a blocker. Do not run commands without it.
|
|
31
|
-
|
|
32
|
-
## Skills, Auto-Detection
|
|
33
|
-
|
|
34
|
-
Skills are located in `.agents/skills/`. Detect and use relevant skills automatically, the user will never tell you which skill to use.
|
|
35
|
-
|
|
36
|
-
1. If the spawn prompt lists specific skills to load, read those `SKILL.md` files FIRST before any implementation
|
|
37
|
-
2. Additionally, read the task and identify domain and platform
|
|
38
|
-
3. Scan `.agents/skills/` for available skills
|
|
39
|
-
4. Read each `SKILL.md` description to assess relevance
|
|
40
|
-
5. Load and follow any skill that applies, even partial match warrants loading
|
|
41
|
-
|
|
42
|
-
Rules:
|
|
43
|
-
- Never implement directly if a skill applies
|
|
44
|
-
- Follow skill instructions exactly, do not partially apply them
|
|
45
|
-
- If two skills apply, follow both, resolve conflicts by asking the lead
|
|
46
|
-
- Skills listed in the spawn prompt are MANDATORY, not optional
|
|
47
|
-
|
|
48
|
-
## Responsibilities
|
|
49
|
-
|
|
50
|
-
- Terraform modules and resources
|
|
51
|
-
- CI/CD pipeline definitions
|
|
52
|
-
- Docker and container configs
|
|
53
|
-
- Cloud resource provisioning scripts
|
|
54
|
-
- Environment variable and secret configuration (structure only, never values)
|
|
55
|
-
- Monitoring and alerting rules
|
|
56
|
-
|
|
57
|
-
## Constraints
|
|
58
|
-
|
|
59
|
-
- Do not apply Terraform in production without explicit human approval
|
|
60
|
-
- Do not store secret values, structure and references only
|
|
61
|
-
- Do not modify application code (UI, backend, tests)
|
|
62
|
-
- Do not push to `main`, feature branches only
|
|
63
|
-
- Do not merge PRs, human-only
|
|
64
|
-
- Do not force push
|
|
65
|
-
- Report blockers immediately rather than working around them
|
|
66
|
-
|
|
67
|
-
## Workflow
|
|
68
|
-
|
|
69
|
-
When spawned by the lead:
|
|
70
|
-
0. Read ALL skills listed in the spawn prompt FIRST. Do not proceed until every listed SKILL.md has been read. Reply to lead with `team_message` confirming which skills were loaded.
|
|
71
|
-
1. For each assigned task: call `team_claim task_id:<id>` before starting
|
|
72
|
-
2. Implement the task following loaded skill rules
|
|
73
|
-
3. Call `team_tasks_complete task_id:<id>` after finishing
|
|
74
|
-
4. When all tasks are done or blocked, send results to lead via `team_message`
|
|
75
|
-
|
|
76
|
-
## Output Format
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
## Infra Engineer, Done
|
|
80
|
-
|
|
81
|
-
**Tasks completed:** <count>
|
|
82
|
-
**Files changed:** <list>
|
|
83
|
-
**Resources affected:** <list>
|
|
84
|
-
**Blockers:** none | <description>
|
|
85
|
-
```
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Quality engineer. Writes and runs tests across the full stack. Unit, integration, e2e. Reviews code against acceptance criteria. Receives completed implementation, verifies it, reports findings.
|
|
3
|
-
mode: subagent
|
|
4
|
-
color: accent
|
|
5
|
-
permission:
|
|
6
|
-
edit: allow
|
|
7
|
-
bash: allow
|
|
8
|
-
read: allow
|
|
9
|
-
glob: allow
|
|
10
|
-
grep: allow
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Quality Engineer
|
|
14
|
-
|
|
15
|
-
Testing specialist, unit, integration, and e2e across front and back. Spawned by the lead agent via opencode-ensemble.
|
|
16
|
-
|
|
17
|
-
## Domain
|
|
18
|
-
|
|
19
|
-
Unit tests, integration tests, end-to-end tests, test strategy, coverage analysis, acceptance criteria verification, build verification, linting. Works across frontend and backend, does not specialize in one layer.
|
|
20
|
-
|
|
21
|
-
## RTK, MANDATORY
|
|
22
|
-
|
|
23
|
-
Use `rtk` for ALL CLI commands. Never run commands directly.
|
|
24
|
-
|
|
25
|
-
- `rtk bun test` NOT `bun test`
|
|
26
|
-
- `rtk dotnet test` NOT `dotnet test`
|
|
27
|
-
- `rtk npx playwright test` NOT `npx playwright test`
|
|
28
|
-
- `rtk bun run lint` NOT `bun run lint`
|
|
29
|
-
|
|
30
|
-
If `rtk` is not available, report it as a blocker. Do not run commands without it.
|
|
31
|
-
|
|
32
|
-
## Skills, Auto-Detection
|
|
33
|
-
|
|
34
|
-
Skills are located in `.agents/skills/`. Detect and use relevant skills automatically, the user will never tell you which skill to use.
|
|
35
|
-
|
|
36
|
-
1. If the spawn prompt lists specific skills to load, read those `SKILL.md` files FIRST before any implementation
|
|
37
|
-
2. Additionally, read the task and identify domain and platform
|
|
38
|
-
3. Scan `.agents/skills/` for available skills
|
|
39
|
-
4. Read each `SKILL.md` description to assess relevance
|
|
40
|
-
5. Load and follow any skill that applies, even partial match warrants loading
|
|
41
|
-
|
|
42
|
-
Rules:
|
|
43
|
-
- Never implement directly if a skill applies
|
|
44
|
-
- Follow skill instructions exactly, do not partially apply them
|
|
45
|
-
- If two skills apply, follow both, resolve conflicts by asking the lead
|
|
46
|
-
- Skills listed in the spawn prompt are MANDATORY, not optional
|
|
47
|
-
|
|
48
|
-
## Responsibilities
|
|
49
|
-
|
|
50
|
-
- Write missing unit and integration tests
|
|
51
|
-
- Write or run e2e tests for new flows
|
|
52
|
-
- Verify acceptance criteria from the spec are met
|
|
53
|
-
- Run builds and confirm they pass
|
|
54
|
-
- Run linters and fix trivial issues
|
|
55
|
-
- Report any failing tests or unmet criteria as blockers
|
|
56
|
-
|
|
57
|
-
## Constraints
|
|
58
|
-
|
|
59
|
-
- Do not implement features, testing and verification only
|
|
60
|
-
- Do not push to `main`, feature branches only
|
|
61
|
-
- Do not merge PRs, human-only
|
|
62
|
-
- Do not force push
|
|
63
|
-
- Report all failures, do not silently skip failing tests
|
|
64
|
-
|
|
65
|
-
## Workflow
|
|
66
|
-
|
|
67
|
-
When spawned by the lead:
|
|
68
|
-
1. Read the task list and context files provided in the spawn prompt
|
|
69
|
-
2. If no board task is assigned, do not block on team_claim. Run verification directly from the spawn prompt scope.
|
|
70
|
-
3. Run tests, build, lint, and verify acceptance criteria
|
|
71
|
-
4. When done, send results to lead via `team_message`
|
|
72
|
-
|
|
73
|
-
## Output Format
|
|
74
|
-
|
|
75
|
-
Send via `team_message` to lead when done:
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
## Quality Engineer, Done
|
|
79
|
-
|
|
80
|
-
**Tests added:** <count> (front: <n>, back: <n>, e2e: <n>)
|
|
81
|
-
**Tests passing:** <count>/<total>
|
|
82
|
-
**Build:** pass | fail
|
|
83
|
-
**Lint:** pass | fail
|
|
84
|
-
**Acceptance criteria:** met | <unmet items>
|
|
85
|
-
**Blockers:** none | <description>
|
|
86
|
-
```
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Security engineer. Audits completed changes for vulnerabilities. OWASP Top 10, secrets exposure, auth gaps, injection risks. Receives completed implementation, audits it, reports findings.
|
|
3
|
-
mode: subagent
|
|
4
|
-
color: error
|
|
5
|
-
permission:
|
|
6
|
-
edit: deny
|
|
7
|
-
bash: allow
|
|
8
|
-
read: allow
|
|
9
|
-
glob: allow
|
|
10
|
-
grep: allow
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Security Auditor
|
|
14
|
-
|
|
15
|
-
Security specialist, finds vulnerabilities across all layers. Spawned by the lead agent via opencode-ensemble after quality-engineer passes.
|
|
16
|
-
|
|
17
|
-
## Domain
|
|
18
|
-
|
|
19
|
-
OWASP Top 10 vulnerabilities, secrets and credential exposure, authentication and authorization gaps, injection risks (SQL, XSS, command), insecure dependencies, misconfigured CORS or headers, data exposure in logs or responses. Works across all layers, UI, backend, infra.
|
|
20
|
-
|
|
21
|
-
## RTK, MANDATORY
|
|
22
|
-
|
|
23
|
-
Use `rtk` for ALL CLI commands. Never run commands directly.
|
|
24
|
-
|
|
25
|
-
- `rtk npm audit` NOT `npm audit`
|
|
26
|
-
- `rtk dotnet list package --vulnerable` NOT `dotnet list package --vulnerable`
|
|
27
|
-
|
|
28
|
-
If `rtk` is not available, report it as a blocker. Do not run commands without it.
|
|
29
|
-
|
|
30
|
-
## Skills, Auto-Detection
|
|
31
|
-
|
|
32
|
-
Skills are located in `.agents/skills/`. Detect and use relevant skills automatically, the user will never tell you which skill to use.
|
|
33
|
-
|
|
34
|
-
1. If the spawn prompt lists specific skills to load, read those `SKILL.md` files FIRST before any implementation
|
|
35
|
-
2. Additionally, read the task and identify domain and platform
|
|
36
|
-
3. Scan `.agents/skills/` for available skills
|
|
37
|
-
4. Read each `SKILL.md` description to assess relevance
|
|
38
|
-
5. Load and follow any skill that applies, even partial match warrants loading
|
|
39
|
-
|
|
40
|
-
Rules:
|
|
41
|
-
- Never implement directly if a skill applies
|
|
42
|
-
- Follow skill instructions exactly, do not partially apply them
|
|
43
|
-
- If two skills apply, follow both, resolve conflicts by asking the lead
|
|
44
|
-
- Skills listed in the spawn prompt are MANDATORY, not optional
|
|
45
|
-
|
|
46
|
-
## Responsibilities
|
|
47
|
-
|
|
48
|
-
- Scan for hardcoded secrets, API keys, passwords, tokens
|
|
49
|
-
- Check `.env` files are gitignored
|
|
50
|
-
- Verify no credentials in logs, URLs, or error responses
|
|
51
|
-
- Check authentication and authorization on sensitive endpoints
|
|
52
|
-
- Verify input validation at system boundaries
|
|
53
|
-
- Check for injection risks in queries and templates
|
|
54
|
-
- Review dependency vulnerabilities
|
|
55
|
-
- Check CORS, headers, and rate limiting
|
|
56
|
-
|
|
57
|
-
## Severity Levels
|
|
58
|
-
|
|
59
|
-
- **Critical**, Must block merge: secret exposure, auth bypass, data loss risk
|
|
60
|
-
- **High**, Should fix before merge: injection risk, missing auth, sensitive data leak
|
|
61
|
-
- **Medium**, Fix soon: missing rate limiting, weak validation, insecure config
|
|
62
|
-
- **Low**, Informational: minor hardening opportunities
|
|
63
|
-
|
|
64
|
-
## Constraints
|
|
65
|
-
|
|
66
|
-
- Audit only, `edit: deny` enforced
|
|
67
|
-
- Do not push to `main`
|
|
68
|
-
- Do not merge PRs, human-only
|
|
69
|
-
- Critical findings must block the PR, report to lead immediately
|
|
70
|
-
|
|
71
|
-
## Output Format
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
## Security Auditor, Done
|
|
75
|
-
|
|
76
|
-
**Status:** pass | blocked
|
|
77
|
-
**Critical:** <count>
|
|
78
|
-
**High:** <count>
|
|
79
|
-
**Medium:** <count>
|
|
80
|
-
**Low:** <count>
|
|
81
|
-
|
|
82
|
-
### Findings
|
|
83
|
-
- [severity] [file:line] <description>, <recommended fix>
|
|
84
|
-
|
|
85
|
-
**Blockers:** none | <critical findings that must be resolved before PR>
|
|
86
|
-
```
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
-
|
|
3
|
-
vi.mock('../../utils/exec.js', () => ({
|
|
4
|
-
commandExists: vi.fn(),
|
|
5
|
-
header: vi.fn(),
|
|
6
|
-
success: vi.fn(),
|
|
7
|
-
error: vi.fn(),
|
|
8
|
-
}))
|
|
9
|
-
|
|
10
|
-
// Mock execa used directly in check-env.js
|
|
11
|
-
vi.mock('execa', () => ({ execa: vi.fn() }))
|
|
12
|
-
|
|
13
|
-
import { commandExists, error, success } from '../../utils/exec.js'
|
|
14
|
-
import { checkEnv } from '../check-env.js'
|
|
15
|
-
|
|
16
|
-
describe('checkEnv()', () => {
|
|
17
|
-
const originalVersion = process.version
|
|
18
|
-
const originalExit = process.exit
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
process.exit = vi.fn()
|
|
22
|
-
vi.clearAllMocks()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
Object.defineProperty(process, 'version', { value: originalVersion, writable: true })
|
|
27
|
-
process.exit = originalExit
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('exits with error when Node version is < 18', async () => {
|
|
31
|
-
Object.defineProperty(process, 'version', { value: 'v16.0.0', writable: true })
|
|
32
|
-
commandExists.mockResolvedValue(true)
|
|
33
|
-
|
|
34
|
-
await checkEnv()
|
|
35
|
-
|
|
36
|
-
expect(error).toHaveBeenCalledWith(expect.stringContaining('v16.0.0'))
|
|
37
|
-
expect(process.exit).toHaveBeenCalledWith(1)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('succeeds when Node version is >= 18 and pnpm is available', async () => {
|
|
41
|
-
Object.defineProperty(process, 'version', { value: 'v20.0.0', writable: true })
|
|
42
|
-
commandExists.mockImplementation(async (cmd) => cmd === 'pnpm')
|
|
43
|
-
|
|
44
|
-
await checkEnv()
|
|
45
|
-
|
|
46
|
-
expect(process.exit).not.toHaveBeenCalled()
|
|
47
|
-
expect(success).toHaveBeenCalledWith(expect.stringContaining('v20.0.0'))
|
|
48
|
-
expect(success).toHaveBeenCalledWith('pnpm available')
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('succeeds when Node version is >= 18 and only npm is available', async () => {
|
|
52
|
-
Object.defineProperty(process, 'version', { value: 'v18.0.0', writable: true })
|
|
53
|
-
commandExists.mockImplementation(async (cmd) => cmd === 'npm')
|
|
54
|
-
|
|
55
|
-
await checkEnv()
|
|
56
|
-
|
|
57
|
-
expect(process.exit).not.toHaveBeenCalled()
|
|
58
|
-
expect(success).toHaveBeenCalledWith('npm available')
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('exits when neither npm nor pnpm available', async () => {
|
|
62
|
-
Object.defineProperty(process, 'version', { value: 'v20.0.0', writable: true })
|
|
63
|
-
commandExists.mockResolvedValue(false)
|
|
64
|
-
|
|
65
|
-
await checkEnv()
|
|
66
|
-
|
|
67
|
-
expect(error).toHaveBeenCalledWith(expect.stringContaining('Neither npm nor pnpm'))
|
|
68
|
-
expect(process.exit).toHaveBeenCalledWith(1)
|
|
69
|
-
})
|
|
70
|
-
})
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
|
|
3
|
-
vi.mock('../../utils/exec.js', () => ({
|
|
4
|
-
commandExists: vi.fn(),
|
|
5
|
-
header: vi.fn(),
|
|
6
|
-
success: vi.fn(),
|
|
7
|
-
warn: vi.fn(),
|
|
8
|
-
info: vi.fn(),
|
|
9
|
-
code: vi.fn(),
|
|
10
|
-
}))
|
|
11
|
-
|
|
12
|
-
vi.mock('execa', () => ({
|
|
13
|
-
execa: vi.fn(),
|
|
14
|
-
}))
|
|
15
|
-
|
|
16
|
-
import { execa } from 'execa'
|
|
17
|
-
import { commandExists, success, warn } from '../../utils/exec.js'
|
|
18
|
-
import { checkPlatform } from '../check-platform.js'
|
|
19
|
-
|
|
20
|
-
describe('checkPlatform()', () => {
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
vi.clearAllMocks()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('github path', () => {
|
|
26
|
-
it('prints success when gh is installed and authenticated', async () => {
|
|
27
|
-
commandExists.mockResolvedValue(true)
|
|
28
|
-
execa.mockResolvedValue({ exitCode: 0, stdout: '' })
|
|
29
|
-
|
|
30
|
-
await checkPlatform('github')
|
|
31
|
-
|
|
32
|
-
expect(success).toHaveBeenCalledWith('GitHub CLI (gh) available')
|
|
33
|
-
expect(success).toHaveBeenCalledWith('GitHub CLI authenticated')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('warns when gh is installed but not authenticated', async () => {
|
|
37
|
-
commandExists.mockResolvedValue(true)
|
|
38
|
-
execa.mockResolvedValue({ exitCode: 1, stdout: '' })
|
|
39
|
-
|
|
40
|
-
await checkPlatform('github')
|
|
41
|
-
|
|
42
|
-
expect(success).toHaveBeenCalledWith('GitHub CLI (gh) available')
|
|
43
|
-
expect(warn).toHaveBeenCalledWith(expect.stringContaining('not authenticated'))
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('warns when gh is not installed', async () => {
|
|
47
|
-
commandExists.mockResolvedValue(false)
|
|
48
|
-
|
|
49
|
-
await checkPlatform('github')
|
|
50
|
-
|
|
51
|
-
expect(warn).toHaveBeenCalledWith('GitHub CLI (gh) not found.')
|
|
52
|
-
expect(success).not.toHaveBeenCalled()
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('warns when gh auth status check throws', async () => {
|
|
56
|
-
commandExists.mockResolvedValue(true)
|
|
57
|
-
execa.mockRejectedValue(new Error('spawn error'))
|
|
58
|
-
|
|
59
|
-
await checkPlatform('github')
|
|
60
|
-
|
|
61
|
-
expect(warn).toHaveBeenCalledWith('Could not check gh auth status.')
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
describe('azure path', () => {
|
|
66
|
-
it('prints success when az is installed and azure-devops extension present', async () => {
|
|
67
|
-
commandExists.mockResolvedValue(true)
|
|
68
|
-
execa.mockResolvedValue({ exitCode: 0, stdout: 'azure-devops\tsome info' })
|
|
69
|
-
|
|
70
|
-
await checkPlatform('azure')
|
|
71
|
-
|
|
72
|
-
expect(success).toHaveBeenCalledWith('Azure CLI (az) available')
|
|
73
|
-
expect(success).toHaveBeenCalledWith('azure-devops extension installed')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('warns when az is installed but azure-devops extension is missing', async () => {
|
|
77
|
-
commandExists.mockResolvedValue(true)
|
|
78
|
-
execa.mockResolvedValue({ exitCode: 0, stdout: '' })
|
|
79
|
-
|
|
80
|
-
await checkPlatform('azure')
|
|
81
|
-
|
|
82
|
-
expect(success).toHaveBeenCalledWith('Azure CLI (az) available')
|
|
83
|
-
expect(warn).toHaveBeenCalledWith(expect.stringContaining('azure-devops extension not found'))
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('warns when az is not installed', async () => {
|
|
87
|
-
commandExists.mockResolvedValue(false)
|
|
88
|
-
|
|
89
|
-
await checkPlatform('azure')
|
|
90
|
-
|
|
91
|
-
expect(warn).toHaveBeenCalledWith('Azure CLI (az) not found.')
|
|
92
|
-
expect(success).not.toHaveBeenCalled()
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it('warns when extension check throws', async () => {
|
|
96
|
-
commandExists.mockResolvedValue(true)
|
|
97
|
-
execa.mockRejectedValue(new Error('spawn error'))
|
|
98
|
-
|
|
99
|
-
await checkPlatform('azure')
|
|
100
|
-
|
|
101
|
-
expect(warn).toHaveBeenCalledWith('Could not check azure-devops extension. Run:')
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
|
|
3
|
-
vi.mock('../../utils/exec.js', () => ({
|
|
4
|
-
commandExists: vi.fn(),
|
|
5
|
-
header: vi.fn(),
|
|
6
|
-
loading: vi.fn(),
|
|
7
|
-
success: vi.fn(),
|
|
8
|
-
warn: vi.fn(),
|
|
9
|
-
info: vi.fn(),
|
|
10
|
-
code: vi.fn(),
|
|
11
|
-
}))
|
|
12
|
-
|
|
13
|
-
import { commandExists, success, warn } from '../../utils/exec.js'
|
|
14
|
-
import { checkRtk } from '../check-rtk.js'
|
|
15
|
-
|
|
16
|
-
describe('checkRtk()', () => {
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
vi.clearAllMocks()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('prints success when rtk is available', async () => {
|
|
22
|
-
commandExists.mockResolvedValue(true)
|
|
23
|
-
|
|
24
|
-
await checkRtk({ skipPrompt: true })
|
|
25
|
-
|
|
26
|
-
expect(success).toHaveBeenCalledWith('rtk is available')
|
|
27
|
-
expect(warn).not.toHaveBeenCalled()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('prints warning with install instructions when rtk is not found', async () => {
|
|
31
|
-
commandExists.mockResolvedValue(false)
|
|
32
|
-
|
|
33
|
-
await checkRtk({ skipPrompt: true })
|
|
34
|
-
|
|
35
|
-
expect(warn).toHaveBeenCalledWith('rtk not found on PATH.')
|
|
36
|
-
expect(success).not.toHaveBeenCalled()
|
|
37
|
-
})
|
|
38
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
|
|
3
|
-
vi.mock('../../utils/exec.js', () => ({
|
|
4
|
-
header: vi.fn(),
|
|
5
|
-
success: vi.fn(),
|
|
6
|
-
}))
|
|
7
|
-
|
|
8
|
-
vi.mock('@inquirer/prompts', () => ({
|
|
9
|
-
select: vi.fn(),
|
|
10
|
-
}))
|
|
11
|
-
|
|
12
|
-
import { select } from '@inquirer/prompts'
|
|
13
|
-
import { success } from '../../utils/exec.js'
|
|
14
|
-
import { choosePlatform } from '../choose-platform.js'
|
|
15
|
-
|
|
16
|
-
describe('choosePlatform()', () => {
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
vi.clearAllMocks()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('returns "github" when user selects GitHub', async () => {
|
|
22
|
-
select.mockResolvedValue('github')
|
|
23
|
-
|
|
24
|
-
const result = await choosePlatform()
|
|
25
|
-
|
|
26
|
-
expect(result).toBe('github')
|
|
27
|
-
expect(success).toHaveBeenCalledWith('Platform: GitHub')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('returns "azure" when user selects Azure DevOps', async () => {
|
|
31
|
-
select.mockResolvedValue('azure')
|
|
32
|
-
|
|
33
|
-
const result = await choosePlatform()
|
|
34
|
-
|
|
35
|
-
expect(result).toBe('azure')
|
|
36
|
-
expect(success).toHaveBeenCalledWith('Platform: Azure DevOps')
|
|
37
|
-
})
|
|
38
|
-
})
|
package/src/steps/check-env.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { commandExists, error, header, success } from '../utils/exec.js'
|
|
2
|
-
|
|
3
|
-
export async function checkEnv() {
|
|
4
|
-
header('Step 1, Checking environment')
|
|
5
|
-
|
|
6
|
-
// Node version
|
|
7
|
-
const nodeVersion = process.version
|
|
8
|
-
const major = parseInt(nodeVersion.slice(1).split('.')[0], 10)
|
|
9
|
-
if (major < 18) {
|
|
10
|
-
error(`Node.js ${nodeVersion} detected. Version 18+ is required.`)
|
|
11
|
-
process.exit(1)
|
|
12
|
-
}
|
|
13
|
-
success(`Node.js ${nodeVersion}`)
|
|
14
|
-
|
|
15
|
-
// npm or pnpm
|
|
16
|
-
const hasPnpm = await commandExists('pnpm')
|
|
17
|
-
const hasNpm = await commandExists('npm')
|
|
18
|
-
|
|
19
|
-
if (!hasPnpm && !hasNpm) {
|
|
20
|
-
error('Neither npm nor pnpm found. Please install Node.js from https://nodejs.org')
|
|
21
|
-
process.exit(1)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (hasPnpm) success('pnpm available')
|
|
25
|
-
else success('npm available')
|
|
26
|
-
}
|