eslint-plugin-traceability 1.0.2 → 1.0.4
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/.github/workflows/ci-cd.yml +26 -28
- package/.husky/pre-commit +1 -1
- package/.husky/pre-push +1 -1
- package/.prettierignore +5 -1
- package/.voder/history.md +117 -149
- package/.voder/implementation-progress.md +110 -112
- package/.voder/last-action.md +61 -117
- package/.voder/plan.md +10 -10
- package/.voder/progress-chart.png +0 -0
- package/.voder/progress-log-areas.csv +4 -0
- package/.voder/progress-log.csv +4 -0
- package/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/cli-integration.js +61 -115
- package/docs/cli-integration.md +3 -1
- package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +87 -58
- package/docs/decisions/005-github-actions-validation-tooling.accepted.md +144 -0
- package/eslint.config.js +4 -4
- package/lib/tests/{basic.test.js → plugin-setup.test.js} +1 -1
- package/package.json +1 -1
- package/tests/{basic.test.ts → plugin-setup.test.ts} +1 -1
- package/user-docs/migration-guide.md +71 -0
- package/lib/index.d.ts +0 -26
- package/lib/index.js +0 -11
- package/lib/tests/integration/file-validation.test.d.ts +0 -1
- package/lib/tests/integration/file-validation.test.js +0 -71
- package/lib/tests/integration/plugin-validation.test.d.ts +0 -1
- package/lib/tests/integration/plugin-validation.test.js +0 -83
- package/tests/integration/file-validation.test.ts +0 -78
- package/tests/integration/plugin-validation.test.ts +0 -84
- /package/lib/tests/{basic.test.d.ts → plugin-default-export-and-configs.test.d.ts} +0 -0
- /package/lib/tests/{index.test.js → plugin-default-export-and-configs.test.js} +0 -0
- /package/lib/tests/{index.test.d.ts → plugin-setup.test.d.ts} +0 -0
- /package/tests/{index.test.ts → plugin-default-export-and-configs.test.ts} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: "accepted"
|
|
3
|
+
date: 2025-11-17
|
|
4
|
+
decision-makers: [Development Team]
|
|
5
|
+
consulted:
|
|
6
|
+
[
|
|
7
|
+
GitHub Actions Documentation,
|
|
8
|
+
Super-Linter Community,
|
|
9
|
+
actionlint Documentation,
|
|
10
|
+
]
|
|
11
|
+
informed: [Project Contributors, CI/CD Pipeline Maintainers]
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# GitHub Actions Validation Tooling Selection
|
|
15
|
+
|
|
16
|
+
## Context and Problem Statement
|
|
17
|
+
|
|
18
|
+
The project uses GitHub Actions for CI/CD workflows defined in `.github/workflows/`. To prevent broken GitHub Actions files from being pushed to the repository, we need to implement pre-commit validation for GitHub Actions YAML files. This validation should catch syntax errors, invalid action references, and misconfigured job dependencies before they are committed, as broken workflow files could prevent CI/CD from running at all.
|
|
19
|
+
|
|
20
|
+
## Decision Drivers
|
|
21
|
+
|
|
22
|
+
- Need for pre-commit validation to prevent broken GitHub Actions files from being pushed
|
|
23
|
+
- Performance requirements for fast local development workflows
|
|
24
|
+
- Prevention of workflow files that would break CI/CD execution
|
|
25
|
+
- Integration with existing development tools and pre-commit hooks
|
|
26
|
+
- Maintainability and configuration simplicity
|
|
27
|
+
- Resource efficiency for local development environments
|
|
28
|
+
|
|
29
|
+
## Considered Options
|
|
30
|
+
|
|
31
|
+
- actionlint for pre-commit hooks only
|
|
32
|
+
- actionlint for both pre-commit and CI/CD
|
|
33
|
+
- Super-Linter for pre-commit hooks
|
|
34
|
+
- GitHub's built-in validation only
|
|
35
|
+
|
|
36
|
+
## Decision Outcome
|
|
37
|
+
|
|
38
|
+
Chosen option: "actionlint for pre-commit hooks only", because it prevents broken GitHub Actions files from being pushed while maintaining fast local development workflow. Once files reach CI/CD, if the workflow runs successfully, the files are valid by definition.
|
|
39
|
+
|
|
40
|
+
### Consequences
|
|
41
|
+
|
|
42
|
+
- Good, because actionlint provides fast pre-commit validation without container overhead
|
|
43
|
+
- Good, because prevents broken GitHub Actions files from being pushed
|
|
44
|
+
- Good, because specifically designed for GitHub Actions validation
|
|
45
|
+
- Good, because simple configuration and maintenance
|
|
46
|
+
- Good, because no Docker dependencies for local development
|
|
47
|
+
- Good, because excellent performance for pre-commit hooks
|
|
48
|
+
- Good, because integrates seamlessly with existing Husky-based pre-commit hooks
|
|
49
|
+
- Neutral, because CI/CD validation is unnecessary if workflows execute successfully
|
|
50
|
+
- Bad, because limited to GitHub Actions validation only
|
|
51
|
+
- Bad, because no security vulnerability detection in pre-commit phase
|
|
52
|
+
|
|
53
|
+
### Confirmation
|
|
54
|
+
|
|
55
|
+
Implementation compliance will be confirmed through:
|
|
56
|
+
|
|
57
|
+
- actionlint added to Husky pre-commit hook in `.husky/pre-commit`
|
|
58
|
+
- Pre-commit hook blocks commits with GitHub Actions validation errors
|
|
59
|
+
- actionlint configured to validate files in `.github/workflows/`
|
|
60
|
+
- Documentation updated to explain Husky-based pre-commit validation approach
|
|
61
|
+
|
|
62
|
+
### Implementation Approach
|
|
63
|
+
|
|
64
|
+
actionlint will be integrated into existing Husky-based pre-commit hooks by:
|
|
65
|
+
|
|
66
|
+
- Installing actionlint as a development dependency
|
|
67
|
+
- Adding actionlint validation to `.husky/pre-commit` hook
|
|
68
|
+
- Configuring actionlint to check `.github/workflows/*.yml` files
|
|
69
|
+
- Documenting the validation process for contributors
|
|
70
|
+
|
|
71
|
+
## Pros and Cons of the Options
|
|
72
|
+
|
|
73
|
+
### actionlint for pre-commit hooks only
|
|
74
|
+
|
|
75
|
+
Lightweight, focused pre-commit validation to prevent broken GitHub Actions files.
|
|
76
|
+
|
|
77
|
+
- Good, because fast execution without container overhead
|
|
78
|
+
- Good, because specifically designed for GitHub Actions validation
|
|
79
|
+
- Good, because no Docker dependencies for local development
|
|
80
|
+
- Good, because simple configuration and maintenance
|
|
81
|
+
- Good, because excellent performance for pre-commit hooks
|
|
82
|
+
- Good, because prevents broken workflow files from being pushed
|
|
83
|
+
- Good, because minimal tooling - only runs where validation is needed
|
|
84
|
+
- Neutral, because focused scope reduces complexity
|
|
85
|
+
- Neutral, because CI/CD validation unnecessary if workflows execute successfully
|
|
86
|
+
- Bad, because limited to GitHub Actions validation only
|
|
87
|
+
- Bad, because no security vulnerability detection in pre-commit phase
|
|
88
|
+
|
|
89
|
+
### actionlint for both pre-commit and CI/CD
|
|
90
|
+
|
|
91
|
+
Validation in both development and CI/CD environments.
|
|
92
|
+
|
|
93
|
+
- Good, because fast execution in all environments
|
|
94
|
+
- Good, because specifically designed for GitHub Actions
|
|
95
|
+
- Good, because consistent validation across environments
|
|
96
|
+
- Neutral, because focused scope reduces complexity
|
|
97
|
+
- Bad, because unnecessary duplication - CI/CD execution validates workflow correctness
|
|
98
|
+
- Bad, because adds CI/CD overhead for validation that's already proven by execution
|
|
99
|
+
- Bad, because limited to GitHub Actions validation only
|
|
100
|
+
|
|
101
|
+
### Super-Linter for pre-commit hooks
|
|
102
|
+
|
|
103
|
+
Comprehensive linting solution for pre-commit validation.
|
|
104
|
+
|
|
105
|
+
- Good, because comprehensive validation including security checks
|
|
106
|
+
- Good, because validates multiple file types beyond GitHub Actions
|
|
107
|
+
- Neutral, because well-maintained and widely adopted
|
|
108
|
+
- Bad, because container overhead makes pre-commit hooks slow
|
|
109
|
+
- Bad, because heavy resource usage for simple syntax checking
|
|
110
|
+
- Bad, because Docker dependency required for local development
|
|
111
|
+
- Bad, because not optimized for frequent pre-commit execution
|
|
112
|
+
- Bad, because overkill for the specific problem of preventing broken workflow files
|
|
113
|
+
|
|
114
|
+
### GitHub's built-in validation only
|
|
115
|
+
|
|
116
|
+
Rely solely on GitHub's native workflow validation.
|
|
117
|
+
|
|
118
|
+
- Good, because no additional tooling or configuration required
|
|
119
|
+
- Good, because automatically available in GitHub interface
|
|
120
|
+
- Good, because validated by the same system that executes workflows
|
|
121
|
+
- Neutral, because basic validation is always performed
|
|
122
|
+
- Bad, because no pre-commit validation for early error detection
|
|
123
|
+
- Bad, because broken files can be pushed, preventing CI/CD execution
|
|
124
|
+
- Bad, because errors only discovered after push to repository
|
|
125
|
+
- Bad, because no local development feedback
|
|
126
|
+
|
|
127
|
+
## More Information
|
|
128
|
+
|
|
129
|
+
This decision focuses on solving the specific problem of preventing broken GitHub Actions files from being pushed to the repository. If CI/CD workflows execute successfully, the files are validated by definition - there's no need for redundant validation in the CI/CD pipeline itself.
|
|
130
|
+
|
|
131
|
+
actionlint configuration should be added to the existing Husky pre-commit hook in `.husky/pre-commit`, targeting `.github/workflows/*.yml` files to catch syntax and configuration errors before commit.
|
|
132
|
+
|
|
133
|
+
The decision should be re-evaluated if:
|
|
134
|
+
|
|
135
|
+
- Security vulnerability detection becomes a requirement for pre-commit validation
|
|
136
|
+
- Comprehensive multi-language linting becomes necessary for pre-commit
|
|
137
|
+
- Alternative tools with better GitHub Actions-specific features emerge
|
|
138
|
+
- The problem scope expands beyond preventing broken workflow files
|
|
139
|
+
|
|
140
|
+
Related resources:
|
|
141
|
+
|
|
142
|
+
- [actionlint Documentation](https://github.com/rhymond/actionlint)
|
|
143
|
+
- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions)
|
|
144
|
+
- [Husky Documentation](https://typicode.github.io/husky/)
|
package/eslint.config.js
CHANGED
|
@@ -73,9 +73,9 @@ module.exports = [
|
|
|
73
73
|
rules: {
|
|
74
74
|
complexity: "error",
|
|
75
75
|
// Enforce maximum lines per function for maintainability
|
|
76
|
-
"max-lines-per-function": ["error", { max:
|
|
76
|
+
"max-lines-per-function": ["error", { max: 80, skipBlankLines: true, skipComments: true }],
|
|
77
77
|
// Enforce maximum lines per file for maintainability
|
|
78
|
-
"max-lines": ["error", { max:
|
|
78
|
+
"max-lines": ["error", { max: 350, skipBlankLines: true, skipComments: true }],
|
|
79
79
|
},
|
|
80
80
|
},
|
|
81
81
|
{
|
|
@@ -90,9 +90,9 @@ module.exports = [
|
|
|
90
90
|
rules: {
|
|
91
91
|
complexity: "error",
|
|
92
92
|
// Enforce maximum lines per function for maintainability
|
|
93
|
-
"max-lines-per-function": ["error", { max:
|
|
93
|
+
"max-lines-per-function": ["error", { max: 80, skipBlankLines: true, skipComments: true }],
|
|
94
94
|
// Enforce maximum lines per file for maintainability
|
|
95
|
-
"max-lines": ["error", { max:
|
|
95
|
+
"max-lines": ["error", { max: 350, skipBlankLines: true, skipComments: true }],
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
{
|
|
@@ -38,7 +38,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
38
38
|
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
39
39
|
* @req REQ-PLUGIN-STRUCTURE - plugin exports rules and configs
|
|
40
40
|
*/
|
|
41
|
-
const index_1 = __importStar(require("../
|
|
41
|
+
const index_1 = __importStar(require("../src/index"));
|
|
42
42
|
describe("Traceability ESLint Plugin (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
43
43
|
it("[REQ-PLUGIN-STRUCTURE] plugin exports rules and configs", () => {
|
|
44
44
|
expect(index_1.rules).toBeDefined();
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
4
|
* @req REQ-PLUGIN-STRUCTURE - plugin exports rules and configs
|
|
5
5
|
*/
|
|
6
|
-
import plugin, { rules, configs } from "../
|
|
6
|
+
import plugin, { rules, configs } from "../src/index";
|
|
7
7
|
|
|
8
8
|
describe("Traceability ESLint Plugin (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
9
9
|
it("[REQ-PLUGIN-STRUCTURE] plugin exports rules and configs", () => {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Migration Guide from v0.x to v1.x
|
|
2
|
+
|
|
3
|
+
Created autonomously by [voder.ai](https://voder.ai)
|
|
4
|
+
|
|
5
|
+
This guide helps you migrate from versions 0.x of `eslint-plugin-traceability` to 1.x.
|
|
6
|
+
|
|
7
|
+
## 1. Update Dependency
|
|
8
|
+
|
|
9
|
+
Update your development dependency to the latest 1.x release:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install --save-dev eslint-plugin-traceability@^1.0.0
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or with Yarn:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add --dev eslint-plugin-traceability@^1.0.0
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 2. ESLint Configuration Changes
|
|
22
|
+
|
|
23
|
+
- Version 1.x uses ESLint v9 flat config by default. If you currently use `.eslintrc.js`, you can continue using it, but consider migrating to the new flat config format for future upgrades.
|
|
24
|
+
- Update your ESLint config to load the plugin’s recommended settings:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
// eslint.config.js (ESLint v9 flat config)
|
|
28
|
+
import traceability from "eslint-plugin-traceability";
|
|
29
|
+
|
|
30
|
+
export default [traceability.configs.recommended];
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 3. New and Updated Rules
|
|
34
|
+
|
|
35
|
+
- `valid-story-reference` now enforces `.story.md` extensions strictly.
|
|
36
|
+
- `valid-req-reference` rejects path traversal (`../`) and absolute paths (`/etc/passwd`).
|
|
37
|
+
- `valid-annotation-format` enforces correct JSDoc traceability annotation syntax (`@story` and `@req` tags).
|
|
38
|
+
|
|
39
|
+
Review and update your existing annotations accordingly:
|
|
40
|
+
|
|
41
|
+
```diff
|
|
42
|
+
- /** @story docs/stories/001.0-DEV-PLUGIN-SETUP.md */
|
|
43
|
+
+ /** @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md */
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 4. CLI Integration Script
|
|
47
|
+
|
|
48
|
+
Version 1.x includes a new `cli-integration.js` script at the project root to run end-to-end CLI integration tests:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
node ./cli-integration.js
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 5. Test and Validate
|
|
55
|
+
|
|
56
|
+
Run your test suite and the new CLI integration script to confirm everything passes:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm test
|
|
60
|
+
npm run lint -- --max-warnings=0
|
|
61
|
+
npm run format:check
|
|
62
|
+
node ./cli-integration.js
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 6. Update Documentation
|
|
66
|
+
|
|
67
|
+
If you have custom documentation or examples that reference old rule names or file paths, update them to match the new conventions introduced in v1.x.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
If you encounter any issues during migration, please file an issue at https://github.com/voder-ai/eslint-plugin-traceability/issues.
|
package/lib/index.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ESLint Traceability Plugin
|
|
3
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
|
-
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
5
|
-
*/
|
|
6
|
-
export declare const rules: Record<string, unknown>;
|
|
7
|
-
export declare const configs: {
|
|
8
|
-
recommended: {
|
|
9
|
-
rules: {};
|
|
10
|
-
}[];
|
|
11
|
-
strict: {
|
|
12
|
-
rules: {};
|
|
13
|
-
}[];
|
|
14
|
-
};
|
|
15
|
-
declare const _default: {
|
|
16
|
-
rules: Record<string, unknown>;
|
|
17
|
-
configs: {
|
|
18
|
-
recommended: {
|
|
19
|
-
rules: {};
|
|
20
|
-
}[];
|
|
21
|
-
strict: {
|
|
22
|
-
rules: {};
|
|
23
|
-
}[];
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
export default _default;
|
package/lib/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ESLint Traceability Plugin
|
|
4
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
5
|
-
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
6
|
-
*/
|
|
7
|
-
const plugin = require("./src/index.js");
|
|
8
|
-
|
|
9
|
-
module.exports = plugin;
|
|
10
|
-
module.exports.rules = plugin.rules;
|
|
11
|
-
module.exports.configs = plugin.configs;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
/**
|
|
7
|
-
* Integration tests for file-validation rules via ESLint CLI
|
|
8
|
-
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
9
|
-
* @req REQ-PERFORMANCE-OPTIMIZATION - Verify CLI integration of valid-story-reference and valid-req-reference rules
|
|
10
|
-
*/
|
|
11
|
-
const child_process_1 = require("child_process");
|
|
12
|
-
const path_1 = __importDefault(require("path"));
|
|
13
|
-
// Ensure ESLint CLI uses built plugin
|
|
14
|
-
const eslintBin = path_1.default.resolve(__dirname, "../../node_modules/.bin/eslint");
|
|
15
|
-
const configPath = path_1.default.resolve(__dirname, "../../eslint.config.js");
|
|
16
|
-
describe("File and Req Validation CLI Integration (Story 006.0-DEV-FILE-VALIDATION)", () => {
|
|
17
|
-
function runLint(code, rules) {
|
|
18
|
-
const ruleArgs = ["--rule", "no-unused-vars:off"];
|
|
19
|
-
for (const r of rules) {
|
|
20
|
-
ruleArgs.push("--rule", r);
|
|
21
|
-
}
|
|
22
|
-
return (0, child_process_1.spawnSync)("node", [
|
|
23
|
-
eslintBin,
|
|
24
|
-
"--no-config-lookup",
|
|
25
|
-
"--config",
|
|
26
|
-
configPath,
|
|
27
|
-
"--stdin",
|
|
28
|
-
"--stdin-filename",
|
|
29
|
-
"foo.js",
|
|
30
|
-
...ruleArgs,
|
|
31
|
-
], {
|
|
32
|
-
encoding: "utf-8",
|
|
33
|
-
input: code,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
it("[REQ-FILE-EXISTENCE] reports missing story file via CLI", () => {
|
|
37
|
-
// Arrange
|
|
38
|
-
const code = "// @story docs/stories/missing-file.story.md";
|
|
39
|
-
// Act
|
|
40
|
-
const res = runLint(code, ["traceability/valid-story-reference:error"]);
|
|
41
|
-
// Assert
|
|
42
|
-
expect(res.status).toBe(1);
|
|
43
|
-
expect(res.stdout).toContain("Story file");
|
|
44
|
-
});
|
|
45
|
-
it("[REQ-EXTENSION] reports invalid extension via CLI", () => {
|
|
46
|
-
// Arrange
|
|
47
|
-
const code = "// @story docs/stories/001.0-DEV-PLUGIN-SETUP.md";
|
|
48
|
-
// Act
|
|
49
|
-
const res = runLint(code, ["traceability/valid-story-reference:error"]);
|
|
50
|
-
// Assert
|
|
51
|
-
expect(res.status).toBe(1);
|
|
52
|
-
expect(res.stdout).toContain("Invalid story file extension");
|
|
53
|
-
});
|
|
54
|
-
it("[REQ-DEEP-PARSE] reports missing requirement via CLI", () => {
|
|
55
|
-
// Arrange
|
|
56
|
-
const code = "// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n// @req REQ-UNKNOWN";
|
|
57
|
-
// Act
|
|
58
|
-
const res = runLint(code, ["traceability/valid-req-reference:error"]);
|
|
59
|
-
// Assert
|
|
60
|
-
expect(res.status).toBe(1);
|
|
61
|
-
expect(res.stdout).toContain("Requirement 'REQ-UNKNOWN' not found");
|
|
62
|
-
});
|
|
63
|
-
it("[REQ-DEEP-MATCH] valid story and requirement via CLI", () => {
|
|
64
|
-
// Arrange
|
|
65
|
-
const code = "// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n// @req REQ-PLUGIN-STRUCTURE";
|
|
66
|
-
// Act
|
|
67
|
-
const res = runLint(code, ["traceability/valid-req-reference:error"]);
|
|
68
|
-
// Assert
|
|
69
|
-
expect(res.status).toBe(0);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
/**
|
|
7
|
-
* Integration tests for ESLint plugin via CLI
|
|
8
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
9
|
-
* @req REQ-PLUGIN-STRUCTURE - Validate plugin registers via CLI
|
|
10
|
-
*/
|
|
11
|
-
/* eslint-env node, jest */
|
|
12
|
-
const child_process_1 = require("child_process");
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
// Ensure ESLint CLI uses built plugin
|
|
15
|
-
const eslintBin = path_1.default.resolve(__dirname, "../../node_modules/.bin/eslint");
|
|
16
|
-
const configPath = path_1.default.resolve(__dirname, "../../eslint.config.js");
|
|
17
|
-
describe("ESLint CLI Integration (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
18
|
-
/**
|
|
19
|
-
* Helper to run ESLint CLI with the traceability plugin and custom rule
|
|
20
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
21
|
-
* @req REQ-PLUGIN-STRUCTURE - Invoke ESLint CLI for integration testing
|
|
22
|
-
*/
|
|
23
|
-
function runEslint(code, rule) {
|
|
24
|
-
const args = [
|
|
25
|
-
"--no-config-lookup",
|
|
26
|
-
"--config",
|
|
27
|
-
configPath,
|
|
28
|
-
"--stdin",
|
|
29
|
-
"--stdin-filename",
|
|
30
|
-
"foo.js",
|
|
31
|
-
"--rule",
|
|
32
|
-
"no-unused-vars:off",
|
|
33
|
-
"--rule",
|
|
34
|
-
rule,
|
|
35
|
-
];
|
|
36
|
-
return (0, child_process_1.spawnSync)("node", [eslintBin, ...args], {
|
|
37
|
-
encoding: "utf-8",
|
|
38
|
-
input: code,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
it("[REQ-PLUGIN-STRUCTURE] reports error when @story annotation is missing", () => {
|
|
42
|
-
// Arrange
|
|
43
|
-
const code = "function foo() {}";
|
|
44
|
-
const rule = "traceability/require-story-annotation:error";
|
|
45
|
-
// Act
|
|
46
|
-
const result = runEslint(code, rule);
|
|
47
|
-
// Assert
|
|
48
|
-
expect(result.status).toBe(1);
|
|
49
|
-
expect(result.stdout).toMatch(/require-story-annotation/);
|
|
50
|
-
});
|
|
51
|
-
it("[REQ-PLUGIN-STRUCTURE] does not report error when @story annotation is present", () => {
|
|
52
|
-
// Arrange
|
|
53
|
-
const code = `/**
|
|
54
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
55
|
-
*/
|
|
56
|
-
function foo() {}`;
|
|
57
|
-
const rule = "traceability/require-story-annotation:error";
|
|
58
|
-
// Act
|
|
59
|
-
const result = runEslint(code, rule);
|
|
60
|
-
// Assert
|
|
61
|
-
expect(result.status).toBe(0);
|
|
62
|
-
});
|
|
63
|
-
it("[REQ-REQ-CLI] reports error when @req annotation is missing", () => {
|
|
64
|
-
// Arrange
|
|
65
|
-
const code = "function foo() {}";
|
|
66
|
-
const rule = "traceability/require-req-annotation:error";
|
|
67
|
-
// Act
|
|
68
|
-
const result = runEslint(code, rule);
|
|
69
|
-
// Assert
|
|
70
|
-
expect(result.status).toBe(1);
|
|
71
|
-
expect(result.stdout).toMatch(/require-req-annotation/);
|
|
72
|
-
});
|
|
73
|
-
it("[REQ-BRANCH-CLI] reports error when branch annotations missing", () => {
|
|
74
|
-
// Arrange
|
|
75
|
-
const code = "if (true) {}";
|
|
76
|
-
const rule = "traceability/require-branch-annotation:error";
|
|
77
|
-
// Act
|
|
78
|
-
const result = runEslint(code, rule);
|
|
79
|
-
// Assert
|
|
80
|
-
expect(result.status).toBe(1);
|
|
81
|
-
expect(result.stdout).toMatch(/require-branch-annotation/);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for file-validation rules via ESLint CLI
|
|
3
|
-
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
4
|
-
* @req REQ-PERFORMANCE-OPTIMIZATION - Verify CLI integration of valid-story-reference and valid-req-reference rules
|
|
5
|
-
*/
|
|
6
|
-
import { spawnSync } from "child_process";
|
|
7
|
-
import path from "path";
|
|
8
|
-
|
|
9
|
-
// Ensure ESLint CLI uses built plugin
|
|
10
|
-
const eslintBin = path.resolve(__dirname, "../../node_modules/.bin/eslint");
|
|
11
|
-
const configPath = path.resolve(__dirname, "../../eslint.config.js");
|
|
12
|
-
|
|
13
|
-
describe("File and Req Validation CLI Integration (Story 006.0-DEV-FILE-VALIDATION)", () => {
|
|
14
|
-
function runLint(code: string, rules: string[]) {
|
|
15
|
-
const ruleArgs = ["--rule", "no-unused-vars:off"];
|
|
16
|
-
for (const r of rules) {
|
|
17
|
-
ruleArgs.push("--rule", r);
|
|
18
|
-
}
|
|
19
|
-
return spawnSync(
|
|
20
|
-
"node",
|
|
21
|
-
[
|
|
22
|
-
eslintBin,
|
|
23
|
-
"--no-config-lookup",
|
|
24
|
-
"--config",
|
|
25
|
-
configPath,
|
|
26
|
-
"--stdin",
|
|
27
|
-
"--stdin-filename",
|
|
28
|
-
"foo.js",
|
|
29
|
-
...ruleArgs,
|
|
30
|
-
],
|
|
31
|
-
{
|
|
32
|
-
encoding: "utf-8",
|
|
33
|
-
input: code,
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
it("[REQ-FILE-EXISTENCE] reports missing story file via CLI", () => {
|
|
39
|
-
// Arrange
|
|
40
|
-
const code = "// @story docs/stories/missing-file.story.md";
|
|
41
|
-
// Act
|
|
42
|
-
const res = runLint(code, ["traceability/valid-story-reference:error"]);
|
|
43
|
-
// Assert
|
|
44
|
-
expect(res.status).toBe(1);
|
|
45
|
-
expect(res.stdout).toContain("Story file");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("[REQ-EXTENSION] reports invalid extension via CLI", () => {
|
|
49
|
-
// Arrange
|
|
50
|
-
const code = "// @story docs/stories/001.0-DEV-PLUGIN-SETUP.md";
|
|
51
|
-
// Act
|
|
52
|
-
const res = runLint(code, ["traceability/valid-story-reference:error"]);
|
|
53
|
-
// Assert
|
|
54
|
-
expect(res.status).toBe(1);
|
|
55
|
-
expect(res.stdout).toContain("Invalid story file extension");
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("[REQ-DEEP-PARSE] reports missing requirement via CLI", () => {
|
|
59
|
-
// Arrange
|
|
60
|
-
const code =
|
|
61
|
-
"// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n// @req REQ-UNKNOWN";
|
|
62
|
-
// Act
|
|
63
|
-
const res = runLint(code, ["traceability/valid-req-reference:error"]);
|
|
64
|
-
// Assert
|
|
65
|
-
expect(res.status).toBe(1);
|
|
66
|
-
expect(res.stdout).toContain("Requirement 'REQ-UNKNOWN' not found");
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("[REQ-DEEP-MATCH] valid story and requirement via CLI", () => {
|
|
70
|
-
// Arrange
|
|
71
|
-
const code =
|
|
72
|
-
"// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n// @req REQ-PLUGIN-STRUCTURE";
|
|
73
|
-
// Act
|
|
74
|
-
const res = runLint(code, ["traceability/valid-req-reference:error"]);
|
|
75
|
-
// Assert
|
|
76
|
-
expect(res.status).toBe(0);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for ESLint plugin via CLI
|
|
3
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
|
-
* @req REQ-PLUGIN-STRUCTURE - Validate plugin registers via CLI
|
|
5
|
-
*/
|
|
6
|
-
/* eslint-env node, jest */
|
|
7
|
-
import { spawnSync, SpawnSyncReturns } from "child_process";
|
|
8
|
-
import path from "path";
|
|
9
|
-
|
|
10
|
-
// Ensure ESLint CLI uses built plugin
|
|
11
|
-
const eslintBin = path.resolve(__dirname, "../../node_modules/.bin/eslint");
|
|
12
|
-
const configPath = path.resolve(__dirname, "../../eslint.config.js");
|
|
13
|
-
|
|
14
|
-
describe("ESLint CLI Integration (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
15
|
-
/**
|
|
16
|
-
* Helper to run ESLint CLI with the traceability plugin and custom rule
|
|
17
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
18
|
-
* @req REQ-PLUGIN-STRUCTURE - Invoke ESLint CLI for integration testing
|
|
19
|
-
*/
|
|
20
|
-
function runEslint(code: string, rule: string): SpawnSyncReturns<string> {
|
|
21
|
-
const args = [
|
|
22
|
-
"--no-config-lookup",
|
|
23
|
-
"--config",
|
|
24
|
-
configPath,
|
|
25
|
-
"--stdin",
|
|
26
|
-
"--stdin-filename",
|
|
27
|
-
"foo.js",
|
|
28
|
-
"--rule",
|
|
29
|
-
"no-unused-vars:off",
|
|
30
|
-
"--rule",
|
|
31
|
-
rule,
|
|
32
|
-
];
|
|
33
|
-
return spawnSync("node", [eslintBin, ...args], {
|
|
34
|
-
encoding: "utf-8",
|
|
35
|
-
input: code,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
it("[REQ-PLUGIN-STRUCTURE] reports error when @story annotation is missing", () => {
|
|
40
|
-
// Arrange
|
|
41
|
-
const code = "function foo() {}";
|
|
42
|
-
const rule = "traceability/require-story-annotation:error";
|
|
43
|
-
// Act
|
|
44
|
-
const result = runEslint(code, rule);
|
|
45
|
-
// Assert
|
|
46
|
-
expect(result.status).toBe(1);
|
|
47
|
-
expect(result.stdout).toMatch(/require-story-annotation/);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("[REQ-PLUGIN-STRUCTURE] does not report error when @story annotation is present", () => {
|
|
51
|
-
// Arrange
|
|
52
|
-
const code = `/**
|
|
53
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
54
|
-
*/
|
|
55
|
-
function foo() {}`;
|
|
56
|
-
const rule = "traceability/require-story-annotation:error";
|
|
57
|
-
// Act
|
|
58
|
-
const result = runEslint(code, rule);
|
|
59
|
-
// Assert
|
|
60
|
-
expect(result.status).toBe(0);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("[REQ-REQ-CLI] reports error when @req annotation is missing", () => {
|
|
64
|
-
// Arrange
|
|
65
|
-
const code = "function foo() {}";
|
|
66
|
-
const rule = "traceability/require-req-annotation:error";
|
|
67
|
-
// Act
|
|
68
|
-
const result = runEslint(code, rule);
|
|
69
|
-
// Assert
|
|
70
|
-
expect(result.status).toBe(1);
|
|
71
|
-
expect(result.stdout).toMatch(/require-req-annotation/);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("[REQ-BRANCH-CLI] reports error when branch annotations missing", () => {
|
|
75
|
-
// Arrange
|
|
76
|
-
const code = "if (true) {}";
|
|
77
|
-
const rule = "traceability/require-branch-annotation:error";
|
|
78
|
-
// Act
|
|
79
|
-
const result = runEslint(code, rule);
|
|
80
|
-
// Assert
|
|
81
|
-
expect(result.status).toBe(1);
|
|
82
|
-
expect(result.stdout).toMatch(/require-branch-annotation/);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|