@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.
Files changed (106) hide show
  1. package/README.md +351 -0
  2. package/bin/shiftleft.js +95 -0
  3. package/package.json +57 -0
  4. package/src/commands/doctor.js +208 -0
  5. package/src/commands/init-postman.js +298 -0
  6. package/src/commands/init-rules.js +78 -0
  7. package/src/commands/link.js +172 -0
  8. package/src/commands/protect.js +61 -0
  9. package/src/commands/run-tests.js +182 -0
  10. package/src/commands/setup-pipeline.js +209 -0
  11. package/src/commands/update.js +203 -0
  12. package/src/index.js +4 -0
  13. package/src/utils/copy-tree.js +98 -0
  14. package/src/utils/gitignore.js +26 -0
  15. package/src/utils/logger.js +9 -0
  16. package/src/utils/manifest.js +145 -0
  17. package/src/utils/stack.js +80 -0
  18. package/src/utils/template.js +135 -0
  19. package/templates/AGENTS.md +109 -0
  20. package/templates/CLAUDE.md +3 -0
  21. package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
  22. package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
  23. package/templates/postman/.husky/pre-commit +19 -0
  24. package/templates/postman/.prettierrc.json +5 -0
  25. package/templates/postman/README.md.ejs +147 -0
  26. package/templates/postman/collections/01-core.json.ejs +91 -0
  27. package/templates/postman/config/local.json.ejs +12 -0
  28. package/templates/postman/config/staging.json.ejs +26 -0
  29. package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
  30. package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
  31. package/templates/postman/gitignore +16 -0
  32. package/templates/postman/npmrc +31 -0
  33. package/templates/postman/package.json.ejs +66 -0
  34. package/templates/postman/run-all-shim.sh +16 -0
  35. package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
  36. package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
  37. package/templates/postman/scripts/infra/start-mocks.sh +138 -0
  38. package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
  39. package/templates/postman/scripts/lib/api_coverage.py +1122 -0
  40. package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
  41. package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
  42. package/templates/postman/scripts/lib/report_combined.py +527 -0
  43. package/templates/postman/scripts/lib/report_consolidated.py +363 -0
  44. package/templates/postman/scripts/lib/report_generator.py +121 -0
  45. package/templates/postman/scripts/lib/report_migration.py +156 -0
  46. package/templates/postman/scripts/lib/report_mutation.py +110 -0
  47. package/templates/postman/scripts/lib/report_unit.py +353 -0
  48. package/templates/postman/scripts/lib/report_utils.py +973 -0
  49. package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
  50. package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
  51. package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
  52. package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
  53. package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
  54. package/templates/postman/scripts/run-all.sh +452 -0
  55. package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
  56. package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
  57. package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
  58. package/templates/postman-node/README.md.ejs +26 -0
  59. package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
  60. package/templates/postman-node/config/local.json.ejs +46 -0
  61. package/templates/postman-node/config/staging.json.ejs +31 -0
  62. package/templates/postman-node/local.test.env.ejs +3 -0
  63. package/templates/postman-node/mocks/external.js +14 -0
  64. package/templates/postman-node/package.json.ejs +39 -0
  65. package/templates/postman-node/requirements.txt +1 -0
  66. package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
  67. package/templates/postman-node/scripts/database/run-migrations.js +29 -0
  68. package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
  69. package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
  70. package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
  71. package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
  72. package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
  73. package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
  74. package/templates/postman-node/scripts/lib/start-app.sh +48 -0
  75. package/templates/postman-node/scripts/lib/utils.sh +114 -0
  76. package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
  77. package/templates/postman-node/scripts/run-all.sh +303 -0
  78. package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
  79. package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
  80. package/templates/postman-node/stryker.config.js.ejs +51 -0
  81. package/templates/rules/local-test-setup.mdc +420 -0
  82. package/templates/rules/testing-node.mdc +66 -0
  83. package/templates/rules/testing.mdc +248 -0
  84. package/templates/skills/_shared/postman-standards.md +380 -0
  85. package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
  86. package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
  87. package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
  88. package/templates/skills/review-test-suite/SKILL-java.md +137 -0
  89. package/templates/skills/review-test-suite/SKILL-node.md +78 -0
  90. package/templates/skills/review-test-suite/SKILL.md +9 -0
  91. package/templates/skills/run-test-suite/SKILL-java.md +186 -0
  92. package/templates/skills/run-test-suite/SKILL-node.md +191 -0
  93. package/templates/skills/run-test-suite/SKILL.md +9 -0
  94. package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
  95. package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
  96. package/templates/skills/setup-api-tests/SKILL.md +9 -0
  97. package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
  98. package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
  99. package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
  100. package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
  101. package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
  102. package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
  103. package/templates/skills/write-api-tests/SKILL-java.md +115 -0
  104. package/templates/skills/write-api-tests/SKILL-node.md +83 -0
  105. package/templates/skills/write-api-tests/SKILL.md +9 -0
  106. package/templates/stryker.config.js +50 -0
@@ -0,0 +1,26 @@
1
+ # <%= serviceDisplayName %> — Postman API Tests
2
+
3
+ Node.js/Express integration tests using Newman. Config-driven via `config/local.json` and `config/staging.json`.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ cd postman && npm ci --ignore-scripts
9
+ cd scripts && ./runners/run-tests.sh local
10
+ ```
11
+
12
+ ## Full pipeline (unit + mutation + Postman + coverage + report)
13
+
14
+ ```bash
15
+ cd postman/scripts && ./run-all.sh
16
+ ```
17
+
18
+ ## Structure
19
+
20
+ - `collections/crud/` — numbered Newman collections (bootstrap first, cleanup last)
21
+ - `config/` — environment-specific setup (DB, app, auth)
22
+ - `scripts/runners/run-tests.sh` — unified local/staging runner
23
+ - `scripts/setup-mocks.js` — nock stubs (load when `NODE_ENV=integration-tests`)
24
+ - `mocks/` — per-service nock definitions
25
+
26
+ Reference implementation: `freshapps_api_node`
@@ -0,0 +1,34 @@
1
+ {
2
+ "info": {
3
+ "name": "01-bootstrap",
4
+ "description": "Bootstrap collection — runs first. Sets shared env vars for later collections.",
5
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6
+ },
7
+ "item": [
8
+ {
9
+ "name": "Health - GET /health",
10
+ "request": {
11
+ "method": "GET",
12
+ "header": [],
13
+ "url": {
14
+ "raw": "{{base_url}}/health",
15
+ "host": ["{{base_url}}"],
16
+ "path": ["health"]
17
+ }
18
+ },
19
+ "event": [
20
+ {
21
+ "listen": "test",
22
+ "script": {
23
+ "exec": [
24
+ "pm.test('Status is 200', function () {",
25
+ " pm.response.to.have.status(200);",
26
+ "});"
27
+ ],
28
+ "type": "text/javascript"
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "comment": "Local environment configuration for <%= serviceName %> Postman tests",
3
+ "environment": "local",
4
+ "api_url": "http://localhost:4013",
5
+ "setup": {
6
+ "database": {
7
+ "enabled": false,
8
+ "type": "docker",
9
+ "container_name": "<%= serviceNameLower %>-test-mysql",
10
+ "port": 3309,
11
+ "host": "127.0.0.1",
12
+ "user": "testuser",
13
+ "password": "testpass",
14
+ "database": "<%= serviceNameLower %>"
15
+ },
16
+ "app": {
17
+ "enabled": true,
18
+ "port": 4013,
19
+ "node_env": "integration-tests",
20
+ "env_file": "postman/local.test.env",
21
+ "start_command": "yarn start"
22
+ },
23
+ "migrations": {
24
+ "enabled": false
25
+ }
26
+ },
27
+ "auth": {
28
+ "type": "local",
29
+ "jwt": {
30
+ "secret": "change-me-local-jwt-secret",
31
+ "issuer": "<%= serviceNameLower %>_automation",
32
+ "account_id": "102",
33
+ "product": "freshdesk",
34
+ "expiry": "3600",
35
+ "users": {
36
+ "developer": {
37
+ "user_id": "1001",
38
+ "user_role": "developer",
39
+ "user_email": "developer@example.com",
40
+ "user_name": "Developer User"
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "test_data": {}
46
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "comment": "Staging environment configuration for <%= serviceName %> Postman tests",
3
+ "environment": "staging",
4
+ "api_url": "https://staging.example.com",
5
+ "setup": {
6
+ "database": { "enabled": false },
7
+ "app": { "enabled": false },
8
+ "migrations": { "enabled": false }
9
+ },
10
+ "auth": {
11
+ "type": "aws",
12
+ "aws": {
13
+ "secret_name": "staging_stack_secrets",
14
+ "account_id": "000000000000",
15
+ "region": "us-west-2"
16
+ },
17
+ "jwt": {
18
+ "issuer": "<%= serviceNameLower %>_automation",
19
+ "product": "freshdesk",
20
+ "expiry": "3600",
21
+ "users": {
22
+ "developer": {
23
+ "user_id": "1001",
24
+ "user_role": "developer",
25
+ "user_email": "developer@example.com",
26
+ "user_name": "Developer User"
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,3 @@
1
+ NODE_ENV=integration-tests
2
+ PORT=4013
3
+ LOG_LEVEL=error
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Example external HTTP stubs. Add one file per external dependency.
5
+ */
6
+ function setupExternalMocks(nock) {
7
+ // Replace with your service's external domains
8
+ nock('https://api.example.com')
9
+ .persist()
10
+ .get(/.*/)
11
+ .reply(200, { success: true });
12
+ }
13
+
14
+ module.exports = { setupExternalMocks };
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "<%= serviceName %>-postman-tests",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "Postman API tests for <%= serviceName %>",
6
+ "scripts": {
7
+ "prepare": "cd .. && husky postman/.husky",
8
+ "test:local": "./scripts/runners/run-tests.sh local",<% if (includeStaging) { %>
9
+ "test:staging": "./scripts/runners/run-tests.sh staging",<% } %>
10
+ "report:consolidated": "./scripts/report-generators/generate-consolidated-report.sh",
11
+ "audit": "npm audit --audit-level=high",
12
+ "audit:signatures": "npm audit signatures",
13
+ "security:check": "npm run audit && npm run audit:signatures",
14
+ "format": "prettier --write '**/*.json' '!node_modules/**'",
15
+ "format:check": "prettier --check '**/*.json' '!node_modules/**'"
16
+ },
17
+ "dependencies": {
18
+ "jsonwebtoken": "9.0.2",
19
+ "newman": "6.2.2",
20
+ "newman-reporter-htmlextra": "1.23.1",
21
+ "nock": "13.5.6"
22
+ },
23
+ "devDependencies": {
24
+ "aws-sdk-mock": "6.2.1",
25
+ "husky": "9.1.7",
26
+ "prettier": "3.4.2"
27
+ },
28
+ "overrides": {
29
+ "tunnel-agent": "0.6.0",
30
+ "tough-cookie": "4.1.3",
31
+ "semver": "7.5.4"
32
+ },
33
+ "engines": {
34
+ "node": ">=18.0.0",
35
+ "npm": ">=8.4.0"
36
+ },
37
+ "keywords": ["postman", "api-testing", "newman", "<%= serviceName %>"],
38
+ "license": "UNLICENSED"
39
+ }
@@ -0,0 +1 @@
1
+ defusedxml>=0.7.1
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+ # Cleanup MySQL container
3
+
4
+ CONTAINER_NAME="${MYSQL_CONTAINER_NAME:-integration-test-mysql}"
5
+
6
+ echo "Cleaning up MySQL container..."
7
+
8
+ if podman rm -f "$CONTAINER_NAME" 2>/dev/null; then
9
+ echo "MySQL container '$CONTAINER_NAME' removed"
10
+ else
11
+ echo "No container to remove (already cleaned up)"
12
+ fi
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Database migration stub for local Postman integration tests.
5
+ *
6
+ * Customize this for your ORM (Sequelize, Knex, TypeORM, etc.) or disable
7
+ * migrations in postman/config/local.json: setup.migrations.enabled = false
8
+ *
9
+ * Reference implementation: freshapps_api_node/postman/scripts/database/run-migrations.js
10
+ */
11
+
12
+ const path = require('path');
13
+
14
+ // eslint-disable-next-line no-unused-vars
15
+ const PROJECT_ROOT = path.resolve(__dirname, '../../..');
16
+
17
+ async function runMigrations() {
18
+ console.log('[run-migrations] No migrations configured — customize postman/scripts/database/run-migrations.js');
19
+ console.log('[run-migrations] Or set setup.migrations.enabled to false in postman/config/local.json');
20
+ }
21
+
22
+ if (require.main === module) {
23
+ runMigrations().catch((err) => {
24
+ console.error(err);
25
+ process.exit(1);
26
+ });
27
+ }
28
+
29
+ module.exports = { runMigrations };
@@ -0,0 +1,34 @@
1
+ #!/bin/bash
2
+ # Start ephemeral MySQL container for integration tests
3
+
4
+ set -e
5
+
6
+ CONTAINER_NAME="${MYSQL_CONTAINER_NAME:-integration-test-mysql}"
7
+ MYSQL_PORT="${MYSQL_PORT:-3309}"
8
+ MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-testpass}"
9
+ MYSQL_DATABASE="${MYSQL_DATABASE:-freshapps}"
10
+ MYSQL_USER="${MYSQL_USER:-testuser}"
11
+ MYSQL_PASSWORD="${MYSQL_PASSWORD:-testpass}"
12
+
13
+ echo "Starting MySQL container..."
14
+ echo " Container: $CONTAINER_NAME"
15
+ echo " Port: $MYSQL_PORT"
16
+ echo " Database: $MYSQL_DATABASE"
17
+
18
+ # Remove existing container if it exists
19
+ podman rm -f "$CONTAINER_NAME" 2>/dev/null || true
20
+
21
+ # Start MySQL container
22
+ podman run -d \
23
+ --name "$CONTAINER_NAME" \
24
+ -e MYSQL_ROOT_PASSWORD="$MYSQL_ROOT_PASSWORD" \
25
+ -e MYSQL_DATABASE="$MYSQL_DATABASE" \
26
+ -e MYSQL_USER="$MYSQL_USER" \
27
+ -e MYSQL_PASSWORD="$MYSQL_PASSWORD" \
28
+ -p "$MYSQL_PORT:3306" \
29
+ mysql:8.0 \
30
+ --default-authentication-plugin=mysql_native_password \
31
+ --character-set-server=utf8mb4 \
32
+ --collation-server=utf8mb4_unicode_ci
33
+
34
+ echo "MySQL container started"
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # Wait for MySQL to be ready and grant permissions
3
+
4
+ set -e
5
+
6
+ CONTAINER_NAME="${MYSQL_CONTAINER_NAME:-integration-test-mysql}"
7
+ MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-testpass}"
8
+ MYSQL_USER="${MYSQL_USER:-testuser}"
9
+ MAX_WAIT="${MAX_WAIT:-20}"
10
+ INTERVAL=2
11
+
12
+ echo "Waiting for MySQL to be ready (max ${MAX_WAIT}s)..."
13
+
14
+ elapsed=0
15
+ while [ $elapsed -lt $MAX_WAIT ]; do
16
+ if podman exec "$CONTAINER_NAME" mysqladmin ping -h localhost --silent 2>/dev/null; then
17
+ echo "MySQL is ready! (took ${elapsed}s)"
18
+
19
+ # Grant full privileges to testuser for creating and managing databases
20
+ echo "Granting privileges to ${MYSQL_USER}..."
21
+ podman exec "$CONTAINER_NAME" mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" -e "
22
+ GRANT ALL PRIVILEGES ON *.* TO '${MYSQL_USER}'@'%' WITH GRANT OPTION;
23
+ FLUSH PRIVILEGES;
24
+ " 2>/dev/null || echo "Warning: Could not grant privileges (may already be set)"
25
+
26
+ echo "Database user configured successfully"
27
+ exit 0
28
+ fi
29
+
30
+ sleep $INTERVAL
31
+ elapsed=$((elapsed + INTERVAL))
32
+ echo " Waiting... (${elapsed}s)"
33
+ done
34
+
35
+ echo "ERROR: MySQL did not become ready within ${MAX_WAIT}s"
36
+ exit 1