@freshworks/shiftleft-tools 1.1.8
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 +351 -0
- package/bin/shiftleft.js +95 -0
- package/package.json +57 -0
- package/src/commands/doctor.js +208 -0
- package/src/commands/init-postman.js +298 -0
- package/src/commands/init-rules.js +78 -0
- package/src/commands/link.js +172 -0
- package/src/commands/protect.js +61 -0
- package/src/commands/run-tests.js +182 -0
- package/src/commands/setup-pipeline.js +209 -0
- package/src/commands/update.js +203 -0
- package/src/index.js +4 -0
- package/src/utils/copy-tree.js +98 -0
- package/src/utils/gitignore.js +26 -0
- package/src/utils/logger.js +9 -0
- package/src/utils/manifest.js +145 -0
- package/src/utils/stack.js +80 -0
- package/src/utils/template.js +135 -0
- package/templates/AGENTS.md +109 -0
- package/templates/CLAUDE.md +3 -0
- package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
- package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
- package/templates/postman/.husky/pre-commit +19 -0
- package/templates/postman/.prettierrc.json +5 -0
- package/templates/postman/README.md.ejs +147 -0
- package/templates/postman/collections/01-core.json.ejs +91 -0
- package/templates/postman/config/local.json.ejs +12 -0
- package/templates/postman/config/staging.json.ejs +26 -0
- package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
- package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
- package/templates/postman/gitignore +16 -0
- package/templates/postman/npmrc +31 -0
- package/templates/postman/package.json.ejs +66 -0
- package/templates/postman/run-all-shim.sh +16 -0
- package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
- package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
- package/templates/postman/scripts/infra/start-mocks.sh +138 -0
- package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
- package/templates/postman/scripts/lib/api_coverage.py +1122 -0
- package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
- package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
- package/templates/postman/scripts/lib/report_combined.py +527 -0
- package/templates/postman/scripts/lib/report_consolidated.py +363 -0
- package/templates/postman/scripts/lib/report_generator.py +121 -0
- package/templates/postman/scripts/lib/report_migration.py +156 -0
- package/templates/postman/scripts/lib/report_mutation.py +110 -0
- package/templates/postman/scripts/lib/report_unit.py +353 -0
- package/templates/postman/scripts/lib/report_utils.py +973 -0
- package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
- package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
- package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
- package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
- package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
- package/templates/postman/scripts/run-all.sh +452 -0
- package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
- package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
- package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
- package/templates/postman-node/README.md.ejs +26 -0
- package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
- package/templates/postman-node/config/local.json.ejs +46 -0
- package/templates/postman-node/config/staging.json.ejs +31 -0
- package/templates/postman-node/local.test.env.ejs +3 -0
- package/templates/postman-node/mocks/external.js +14 -0
- package/templates/postman-node/package.json.ejs +39 -0
- package/templates/postman-node/requirements.txt +1 -0
- package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
- package/templates/postman-node/scripts/database/run-migrations.js +29 -0
- package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
- package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
- package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
- package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
- package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
- package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
- package/templates/postman-node/scripts/lib/start-app.sh +48 -0
- package/templates/postman-node/scripts/lib/utils.sh +114 -0
- package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
- package/templates/postman-node/scripts/run-all.sh +303 -0
- package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
- package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
- package/templates/postman-node/stryker.config.js.ejs +51 -0
- package/templates/rules/local-test-setup.mdc +420 -0
- package/templates/rules/testing-node.mdc +66 -0
- package/templates/rules/testing.mdc +248 -0
- package/templates/skills/_shared/postman-standards.md +380 -0
- package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
- package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
- package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
- package/templates/skills/review-test-suite/SKILL-java.md +137 -0
- package/templates/skills/review-test-suite/SKILL-node.md +78 -0
- package/templates/skills/review-test-suite/SKILL.md +9 -0
- package/templates/skills/run-test-suite/SKILL-java.md +186 -0
- package/templates/skills/run-test-suite/SKILL-node.md +191 -0
- package/templates/skills/run-test-suite/SKILL.md +9 -0
- package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
- package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
- package/templates/skills/setup-api-tests/SKILL.md +9 -0
- package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
- package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
- package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
- package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
- package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
- package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
- package/templates/skills/write-api-tests/SKILL-java.md +115 -0
- package/templates/skills/write-api-tests/SKILL-node.md +83 -0
- package/templates/skills/write-api-tests/SKILL.md +9 -0
- package/templates/stryker.config.js +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# shiftleft-tools
|
|
2
|
+
|
|
3
|
+
CLI for setting up Cursor rules, AI skills, and Postman/Newman test infrastructure across Freshworks **Java Spring Boot** and **Node.js/Express** services.
|
|
4
|
+
|
|
5
|
+
Works with both **Cursor IDE** and **Claude Code**.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Install the CLI (one-time) — see Installation below
|
|
11
|
+
npm install -g @freshworks/shiftleft-tools
|
|
12
|
+
|
|
13
|
+
# 2. Navigate to your service repo
|
|
14
|
+
cd /path/to/your-service
|
|
15
|
+
|
|
16
|
+
# 3. Initialize rules and skills (auto-detects Java or Node)
|
|
17
|
+
shiftleft init-rules
|
|
18
|
+
|
|
19
|
+
# 4. Initialize Postman tests (auto-detects stack from pom.xml or package.json)
|
|
20
|
+
shiftleft init-postman --name your-service --with-staging
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
After setup, use skills in Cursor or Claude Code:
|
|
24
|
+
- `/setup-test-pipeline` — full test pipeline from scratch
|
|
25
|
+
- `/setup-api-tests` — set up Postman test infrastructure
|
|
26
|
+
- `/write-api-tests GET /apps` — write tests for a specific endpoint
|
|
27
|
+
- `/run-test-suite` — run unit, mutation, or API tests
|
|
28
|
+
- `/review-test-suite` — validate test suite quality
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
**Requirements:** Node.js ≥ 18 and **bash ≥ 4** (`shiftleft test` runs scripts
|
|
33
|
+
that use associative arrays / `${x^^}` / `mapfile`). macOS ships bash 3.2 — install
|
|
34
|
+
a newer one with `brew install bash`. `shiftleft test` locates a bash ≥ 4
|
|
35
|
+
automatically and fails with a clear message if none is found.
|
|
36
|
+
|
|
37
|
+
The CLI is published to the public npm registry as the scoped package
|
|
38
|
+
[`@freshworks/shiftleft-tools`](https://www.npmjs.com/package/@freshworks/shiftleft-tools):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install -g @freshworks/shiftleft-tools
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> **CI / build agents** need the package installed globally too (the `run-all.sh`
|
|
45
|
+
> shim execs `shiftleft test`). Bake it into the agent image, or install it in the
|
|
46
|
+
> pipeline. The provided `Jenkinsfile-{java,node}` templates include an idempotent
|
|
47
|
+
> `ensureShiftleftCli()` step. Example pipeline step:
|
|
48
|
+
>
|
|
49
|
+
> ```groovy
|
|
50
|
+
> sh '''#!/bin/bash --login
|
|
51
|
+
> command -v shiftleft >/dev/null 2>&1 || npm install -g @freshworks/shiftleft-tools
|
|
52
|
+
> '''
|
|
53
|
+
> ```
|
|
54
|
+
> Run this before any stage that calls `run-all.sh` / `shiftleft test` / `stage-scripts`.
|
|
55
|
+
|
|
56
|
+
### Local development
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/freshdesk/shiftleft-tools.git
|
|
60
|
+
cd dev-tools
|
|
61
|
+
npm install
|
|
62
|
+
npm link
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Verify installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
shiftleft --version
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Usage
|
|
72
|
+
|
|
73
|
+
### Claude Code skills: install the plugin (once per machine)
|
|
74
|
+
|
|
75
|
+
Claude Code skills are delivered as a **plugin**, not copied into each repo — so
|
|
76
|
+
they update everywhere when you update the plugin, with no per-repo step.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# in Claude Code
|
|
80
|
+
/plugin install https://github.com/freshdesk/shiftleft-tools
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Initialize Cursor Rules & Skills
|
|
84
|
+
|
|
85
|
+
Cursor reads `.cursor/`, so `init-rules` **symlinks** that repo's Cursor skills
|
|
86
|
+
and rules to the installed `@freshworks/shiftleft-tools` package. A
|
|
87
|
+
`npm i -g @freshworks/shiftleft-tools@latest` then updates every linked repo at once.
|
|
88
|
+
The symlinks are gitignored (machine-local pointers), so each developer runs
|
|
89
|
+
`shiftleft link` (or `init-rules`) once after cloning.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
cd your-service
|
|
93
|
+
shiftleft init-rules
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Options:
|
|
97
|
+
- `--force, -f` - Overwrite existing `CLAUDE.md` / `AGENTS.md`
|
|
98
|
+
- `--skip-skills` - Link rules only, not Cursor skills
|
|
99
|
+
- `--stack <java|node>` - Project stack (auto-detected from `pom.xml` or `package.json`)
|
|
100
|
+
- `--copy` - Copy assets instead of symlinking (locked-down environments / Windows without symlink permission)
|
|
101
|
+
|
|
102
|
+
This creates:
|
|
103
|
+
```
|
|
104
|
+
.cursor/
|
|
105
|
+
├── rules/
|
|
106
|
+
│ ├── testing.mdc -> (symlink) package rule for your stack
|
|
107
|
+
│ └── local-test-setup.mdc -> (symlink) Java only
|
|
108
|
+
└── skills/ -> (symlink) package skills directory
|
|
109
|
+
CLAUDE.md # Skill invocation instructions for Claude Code (real file)
|
|
110
|
+
AGENTS.md # Agent routing and guardrails (real file)
|
|
111
|
+
.gitignore # symlink paths added here (not committed)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
> Migrating from an older version? A committed `.claude/skills/` directory is no
|
|
115
|
+
> longer needed — install the plugin and delete it. `shiftleft doctor` flags it.
|
|
116
|
+
|
|
117
|
+
### Link / relink Cursor assets
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
shiftleft link # (re)create the Cursor symlinks
|
|
121
|
+
shiftleft link --copy # copy instead of symlink
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Initialize Postman Test Infrastructure
|
|
125
|
+
|
|
126
|
+
Set up Postman/Newman testing for your project:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
cd your-service
|
|
130
|
+
|
|
131
|
+
# Auto-detect stack (pom.xml → Java, package.json → Node)
|
|
132
|
+
shiftleft init-postman
|
|
133
|
+
|
|
134
|
+
# Explicit stack
|
|
135
|
+
shiftleft init-postman --stack java --with-staging
|
|
136
|
+
shiftleft init-postman --stack node --with-staging
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Options:
|
|
140
|
+
- `--force, -f` - Overwrite existing files
|
|
141
|
+
- `--name, -n <name>` - Service name (inferred from `pom.xml` or `package.json` if not provided)
|
|
142
|
+
- `--stack <java|node>` - Project stack (auto-detected if omitted)
|
|
143
|
+
- `--with-staging` - Include staging environment, JWT scripts, and AWS config
|
|
144
|
+
|
|
145
|
+
**Committed (repo-owned scaffold + entrypoint):**
|
|
146
|
+
```
|
|
147
|
+
postman/
|
|
148
|
+
├── package.json
|
|
149
|
+
├── collections/ # your test collections
|
|
150
|
+
├── config/local.json # URLs, ports, auth — yours to edit
|
|
151
|
+
├── environments/
|
|
152
|
+
├── mocks/ # Node: nock stubs (repo-owned)
|
|
153
|
+
└── scripts/
|
|
154
|
+
├── run-all.sh # thin shim → `shiftleft test` (do not edit)
|
|
155
|
+
├── setup-mocks.js # Node: app-runtime mocks (repo-owned)
|
|
156
|
+
└── wiremock/mappings/ # Java: your WireMock stubs
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Staged from the package (gitignored, machine-local cache):**
|
|
160
|
+
```
|
|
161
|
+
postman/scripts/
|
|
162
|
+
├── .run-all-impl.sh # the real orchestrator
|
|
163
|
+
├── lib/ runners/ report-generators/
|
|
164
|
+
├── auth/ infra/ # Java
|
|
165
|
+
└── database/ # Node
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The library scripts are *not vendored*: `shiftleft test` (and the `run-all.sh`
|
|
169
|
+
shim) re-stages them from the installed package before every run, so
|
|
170
|
+
`npm i -g @freshworks/shiftleft-tools@latest` changes test behavior in every repo
|
|
171
|
+
with no repo commits. CI agents need the package installed globally.
|
|
172
|
+
|
|
173
|
+
Also at repo root for Node: `stryker.config.js`, `requirements.txt`
|
|
174
|
+
|
|
175
|
+
Reference Node implementation: `freshapps_api_node`
|
|
176
|
+
|
|
177
|
+
### Run the test suite
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
shiftleft test # stage latest scripts + run everything
|
|
181
|
+
shiftleft test --skip-unit --no-delay # all orchestrator flags pass through
|
|
182
|
+
postman/scripts/run-all.sh --env local # same thing, via the committed shim
|
|
183
|
+
shiftleft stage-scripts # stage only (before calling staged scripts directly)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Protect a customized library script
|
|
187
|
+
|
|
188
|
+
Staging overwrites library scripts from the package on every run. If your repo
|
|
189
|
+
has customized one (e.g. a service-specific `runners/run-tests-local.sh`), mark
|
|
190
|
+
it **protected** so staging leaves it alone:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
shiftleft protect runners/run-tests-local.sh runners/run-tests-staging.sh
|
|
194
|
+
shiftleft protect --list # show protected paths
|
|
195
|
+
shiftleft protect --remove runners/run-tests-local.sh
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Protected paths (relative to `postman/scripts/`) are recorded under `protected`
|
|
199
|
+
in `.shiftleft.json` and excluded from `shiftleft test` / `stage-scripts`. Keep
|
|
200
|
+
the protected files **committed** (or gitignore-excepted) so they survive a fresh
|
|
201
|
+
clone — staging won't recreate them. `shiftleft doctor` lists them.
|
|
202
|
+
|
|
203
|
+
### Update to Latest Version
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
shiftleft update # Update everything
|
|
207
|
+
shiftleft update --rules # Rules only
|
|
208
|
+
shiftleft update --skills # Skills only
|
|
209
|
+
shiftleft update --postman # Postman scripts only
|
|
210
|
+
shiftleft update --force # Overwrite locally-edited files too
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Updates are tracked in a `.shiftleft.json` manifest (committed). Files you've
|
|
214
|
+
edited locally are never silently overwritten — `update` writes a
|
|
215
|
+
`<file>.shiftleft-new` beside them instead. Repo-owned scaffold (config,
|
|
216
|
+
collections, environments) is left untouched unless you pass `--force`.
|
|
217
|
+
|
|
218
|
+
For repos set up before the staged-scripts model, `update --postman` converts
|
|
219
|
+
the committed `run-all.sh` to the shim, prunes the now-unvendored library
|
|
220
|
+
scripts from the manifest, and adds the cache paths to `postman/.gitignore`.
|
|
221
|
+
The old committed library files keep working until you `git rm -r` them.
|
|
222
|
+
|
|
223
|
+
### Check for drift
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
shiftleft doctor # Report version/file drift vs. latest
|
|
227
|
+
shiftleft doctor --check # Exit 1 if stale/drifted (for CI)
|
|
228
|
+
shiftleft doctor --json # Machine-readable report
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Audit & Scaffold Pipeline
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
shiftleft setup-pipeline # Audit gaps and copy missing scripts
|
|
235
|
+
shiftleft setup-pipeline -y # Skip confirmation
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## What's Included
|
|
239
|
+
|
|
240
|
+
### Cursor Rules
|
|
241
|
+
|
|
242
|
+
| Rule | Stack | Description |
|
|
243
|
+
|------|-------|-------------|
|
|
244
|
+
| `testing.mdc` | Java | PIT mutation survival, strong JUnit assertions |
|
|
245
|
+
| `testing.mdc` | Node | Stryker survival, strong Chai assertions (from `testing-node.mdc`) |
|
|
246
|
+
| `local-test-setup.mdc` | Java | H2 config, WireMock, Flyway for local tests |
|
|
247
|
+
|
|
248
|
+
### Skills (Cursor IDE + Claude Code)
|
|
249
|
+
|
|
250
|
+
| Skill | Invoke | Description |
|
|
251
|
+
|-------|--------|-------------|
|
|
252
|
+
| `setup-test-pipeline` | `/setup-test-pipeline` | Full pipeline: unit, coverage, mutation, Postman, Jenkins |
|
|
253
|
+
| `setup-api-tests` | `/setup-api-tests` | Postman/Newman infrastructure from scratch |
|
|
254
|
+
| `write-api-tests` | `/write-api-tests [METHOD /path]` | Write Postman tests for specific endpoints |
|
|
255
|
+
| `setup-mutation-tests` | `/setup-mutation-tests` | PIT (Java) or Stryker (Node) |
|
|
256
|
+
| `run-test-suite` | `/run-test-suite` | Run unit, mutation, Postman, or API coverage |
|
|
257
|
+
| `review-test-suite` | `/review-test-suite` | 20-point test maturity checklist |
|
|
258
|
+
| `enhance-test-pipeline` | `/enhance-test-pipeline` | Audit existing repo and fill gaps |
|
|
259
|
+
|
|
260
|
+
Skills auto-detect stack from `pom.xml` (Java) or `package.json` (Node).
|
|
261
|
+
|
|
262
|
+
## Test Commands
|
|
263
|
+
|
|
264
|
+
### Java (Spring Boot)
|
|
265
|
+
|
|
266
|
+
| Command | Description |
|
|
267
|
+
|---------|-------------|
|
|
268
|
+
| `mvn test` | Unit tests |
|
|
269
|
+
| `cd postman/scripts && ./runners/run-tests-local.sh` | Postman API tests (local) |
|
|
270
|
+
| `./postman/scripts/report-generators/java-api-coverage-matrix.sh` | API coverage report |
|
|
271
|
+
| `./postman/scripts/report-generators/mutation-report.sh` | PIT mutation testing (target: 80%+) |
|
|
272
|
+
| `cd postman/scripts && ./run-all.sh` | Full test suite |
|
|
273
|
+
|
|
274
|
+
### Node.js (Express)
|
|
275
|
+
|
|
276
|
+
| Command | Description |
|
|
277
|
+
|---------|-------------|
|
|
278
|
+
| `yarn unit-tests` | Unit tests + nyc coverage |
|
|
279
|
+
| `yarn mutation-tests` | Stryker (changed files vs origin/master) |
|
|
280
|
+
| `yarn mutation-tests:full` | Stryker full scan (CI) |
|
|
281
|
+
| `cd postman/scripts && ./runners/run-tests.sh local` | Postman API tests (local) |
|
|
282
|
+
| `./postman/scripts/report-generators/node-api-coverage-matrix.sh ./src/controllers ./postman` | API coverage |
|
|
283
|
+
| `cd postman/scripts && ./run-all.sh` | Full test suite |
|
|
284
|
+
|
|
285
|
+
### Before Merge Checklist
|
|
286
|
+
|
|
287
|
+
**Java:**
|
|
288
|
+
```bash
|
|
289
|
+
mvn test
|
|
290
|
+
cd postman/scripts && ./runners/run-tests-local.sh
|
|
291
|
+
./postman/scripts/report-generators/java-api-coverage-matrix.sh
|
|
292
|
+
./postman/scripts/report-generators/mutation-report.sh
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Node:**
|
|
296
|
+
```bash
|
|
297
|
+
yarn unit-tests
|
|
298
|
+
cd postman/scripts && ./runners/run-tests.sh local
|
|
299
|
+
./postman/scripts/report-generators/node-api-coverage-matrix.sh ./src/controllers ./postman
|
|
300
|
+
yarn mutation-tests:full
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Or run everything at once (either stack):
|
|
304
|
+
```bash
|
|
305
|
+
cd postman/scripts && ./run-all.sh
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## What Cursor Learns from Rules
|
|
309
|
+
|
|
310
|
+
The rules teach Cursor to:
|
|
311
|
+
|
|
312
|
+
1. **Write strong unit tests** — No weak assertions (`assertNotNull()`, `expect(x).to.exist` without value checks)
|
|
313
|
+
2. **Survive mutation testing** — PIT (Java) or Stryker (Node); weak tests that pass with mutated code are flagged
|
|
314
|
+
3. **Test all output fields** — If a method returns 5 fields, assert on all 5
|
|
315
|
+
4. **Follow Postman best practices** — Single status assertion per test, cover query params, document skips
|
|
316
|
+
|
|
317
|
+
## Development
|
|
318
|
+
|
|
319
|
+
### Building
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
npm install
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Testing Locally
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
npm link
|
|
329
|
+
cd /path/to/test/project
|
|
330
|
+
shiftleft init-rules
|
|
331
|
+
shiftleft init-postman
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Distributing a new version
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
npm version patch|minor|major
|
|
338
|
+
npm pack
|
|
339
|
+
# Generates: freshworks-shiftleft-tools-x.x.x.tgz
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Requirements
|
|
343
|
+
|
|
344
|
+
- Node.js 18+ and npm 8.4+ (for the CLI and Postman/Newman runner)
|
|
345
|
+
- **Java projects:** Java 21+, Maven
|
|
346
|
+
- **Node projects:** Yarn (recommended), Mocha, nyc, Stryker
|
|
347
|
+
- AWS CLI (for staging Postman tests with JWT from Secrets Manager)
|
|
348
|
+
|
|
349
|
+
## License
|
|
350
|
+
|
|
351
|
+
UNLICENSED - Internal use only
|
package/bin/shiftleft.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import { initRules } from '../src/commands/init-rules.js';
|
|
5
|
+
import { initPostman } from '../src/commands/init-postman.js';
|
|
6
|
+
import { update } from '../src/commands/update.js';
|
|
7
|
+
import { doctor } from '../src/commands/doctor.js';
|
|
8
|
+
import { link } from '../src/commands/link.js';
|
|
9
|
+
import { runTests, stageScriptsCommand } from '../src/commands/run-tests.js';
|
|
10
|
+
import { protect } from '../src/commands/protect.js';
|
|
11
|
+
import { setupPipeline } from '../src/commands/setup-pipeline.js';
|
|
12
|
+
import { readFileSync } from 'fs';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { dirname, join } from 'path';
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.name('shiftleft')
|
|
22
|
+
.description('CLI for managing Cursor rules/skills and Postman test infrastructure')
|
|
23
|
+
.version(pkg.version);
|
|
24
|
+
|
|
25
|
+
program
|
|
26
|
+
.command('init-rules')
|
|
27
|
+
.description('Link Cursor rules/skills and create CLAUDE.md / AGENTS.md')
|
|
28
|
+
.option('-f, --force', 'Overwrite existing CLAUDE.md / AGENTS.md', false)
|
|
29
|
+
.option('--skip-skills', 'Do not link Cursor skills', false)
|
|
30
|
+
.option('--copy', 'Copy Cursor assets instead of symlinking (locked-down environments)', false)
|
|
31
|
+
.option('--stack <stack>', 'Project stack: java or node (auto-detected if omitted)')
|
|
32
|
+
.action(initRules);
|
|
33
|
+
|
|
34
|
+
program
|
|
35
|
+
.command('init-postman')
|
|
36
|
+
.description('Initialize Postman/Newman test infrastructure')
|
|
37
|
+
.option('-f, --force', 'Overwrite existing files', false)
|
|
38
|
+
.option('-n, --name <name>', 'Service name for the tests')
|
|
39
|
+
.option('--stack <stack>', 'Project stack: java or node (auto-detected if omitted)')
|
|
40
|
+
.option('--with-staging', 'Include staging environment support (JWT, AWS)', false)
|
|
41
|
+
.action(initPostman);
|
|
42
|
+
|
|
43
|
+
program
|
|
44
|
+
.command('update')
|
|
45
|
+
.description('Update rules/skills/postman to latest version')
|
|
46
|
+
.option('--rules', 'Update only rules', false)
|
|
47
|
+
.option('--skills', 'Update only skills', false)
|
|
48
|
+
.option('--postman', 'Update only postman scripts', false)
|
|
49
|
+
.option('-f, --force', 'Overwrite without prompting', false)
|
|
50
|
+
.action(update);
|
|
51
|
+
|
|
52
|
+
program
|
|
53
|
+
.command('test')
|
|
54
|
+
.description('Stage the latest library scripts and run the test orchestrator (all flags pass through)')
|
|
55
|
+
.allowUnknownOption(true)
|
|
56
|
+
.helpOption(false) // forward -h/--help to the orchestrator too
|
|
57
|
+
.argument('[args...]', 'Arguments forwarded to the orchestrator (e.g. --skip-unit --no-delay)')
|
|
58
|
+
.action((args, _options, command) => runTests(command.args));
|
|
59
|
+
|
|
60
|
+
program
|
|
61
|
+
.command('stage-scripts')
|
|
62
|
+
.description('Stage the packaged library scripts into postman/scripts (gitignored cache)')
|
|
63
|
+
.option('--stack <stack>', 'Project stack: java or node (auto-detected if omitted)')
|
|
64
|
+
.action(stageScriptsCommand);
|
|
65
|
+
|
|
66
|
+
program
|
|
67
|
+
.command('protect')
|
|
68
|
+
.description('Mark a library script (relative to postman/scripts/) as repo-owned so staging never overwrites it')
|
|
69
|
+
.argument('[paths...]', 'Paths under postman/scripts (e.g. runners/run-tests-local.sh)')
|
|
70
|
+
.option('--list', 'List protected paths', false)
|
|
71
|
+
.option('--remove', 'Remove the given paths from the protected list', false)
|
|
72
|
+
.action((paths, options) => protect(paths, options));
|
|
73
|
+
|
|
74
|
+
program
|
|
75
|
+
.command('link')
|
|
76
|
+
.description('Link Cursor skills/rules to the installed shiftleft-tools package (symlinks, gitignored)')
|
|
77
|
+
.option('--copy', 'Copy instead of symlinking (locked-down environments)', false)
|
|
78
|
+
.option('--stack <stack>', 'Project stack: java or node (auto-detected if omitted)')
|
|
79
|
+
.action(link);
|
|
80
|
+
|
|
81
|
+
program
|
|
82
|
+
.command('doctor')
|
|
83
|
+
.description('Report whether managed files are up to date, drifted, or missing')
|
|
84
|
+
.option('--check', 'Exit with code 1 if the repo is stale, drifted, or has broken symlinks', false)
|
|
85
|
+
.option('--json', 'Emit a machine-readable report', false)
|
|
86
|
+
.action(doctor);
|
|
87
|
+
|
|
88
|
+
program
|
|
89
|
+
.command('setup-pipeline')
|
|
90
|
+
.description('Audit and scaffold test pipeline (unit, mutation, Postman, coverage, quality report)')
|
|
91
|
+
.option('-f, --force', 'Overwrite existing scripts', false)
|
|
92
|
+
.option('-y, --yes', 'Skip confirmation prompt', false)
|
|
93
|
+
.action(setupPipeline);
|
|
94
|
+
|
|
95
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@freshworks/shiftleft-tools",
|
|
3
|
+
"version": "1.1.8",
|
|
4
|
+
"description": "CLI for managing Cursor rules/skills and Postman test infrastructure across Java Spring Boot and Node.js/Express projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"shiftleft": "./bin/shiftleft.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node --test",
|
|
12
|
+
"lint": "eslint src bin",
|
|
13
|
+
"format": "prettier --write ."
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"cursor",
|
|
17
|
+
"rules",
|
|
18
|
+
"skills",
|
|
19
|
+
"postman",
|
|
20
|
+
"newman",
|
|
21
|
+
"java",
|
|
22
|
+
"spring-boot",
|
|
23
|
+
"testing"
|
|
24
|
+
],
|
|
25
|
+
"author": "Freshworks Developer Platform Team",
|
|
26
|
+
"license": "UNLICENSED",
|
|
27
|
+
"private": false,
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"chalk": "^5.3.0",
|
|
33
|
+
"commander": "^12.0.0",
|
|
34
|
+
"ejs": "^3.1.10",
|
|
35
|
+
"fs-extra": "^11.2.0",
|
|
36
|
+
"inquirer": "^9.2.15",
|
|
37
|
+
"ora": "^8.0.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"eslint": "^8.57.0",
|
|
41
|
+
"prettier": "^3.2.5"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/freshdesk/shiftleft-tools.git"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"registry": "https://registry.npmjs.org/",
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"bin/",
|
|
53
|
+
"src/",
|
|
54
|
+
"templates/",
|
|
55
|
+
"templates/postman-node/"
|
|
56
|
+
]
|
|
57
|
+
}
|