eslint-plugin-traceability 1.0.3 → 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 +138 -264
- package/.voder/implementation-progress.md +110 -112
- package/.voder/last-action.md +62 -204
- 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/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
package/cli-integration.js
CHANGED
|
@@ -1,56 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/* eslint-env node */
|
|
3
2
|
/**
|
|
4
|
-
* CLI integration tests for ESLint Traceability Plugin
|
|
3
|
+
* CLI integration tests script for ESLint Traceability Plugin
|
|
5
4
|
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
6
5
|
* @req REQ-PLUGIN-STRUCTURE - Validate plugin registers via CLI
|
|
7
6
|
*/
|
|
8
7
|
const { spawnSync } = require("child_process");
|
|
9
8
|
const path = require("path");
|
|
10
|
-
const configPath = path.resolve(__dirname, "eslint.config.js");
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*/
|
|
17
|
-
function runEslint(code, rule) {
|
|
18
|
-
const eslintPkgDir = path.dirname(require.resolve("eslint/package.json"));
|
|
19
|
-
const eslintCliPath = path.join(eslintPkgDir, "bin", "eslint.js");
|
|
20
|
-
const args = [
|
|
21
|
-
"--no-config-lookup",
|
|
22
|
-
"--config",
|
|
23
|
-
configPath,
|
|
24
|
-
"--stdin",
|
|
25
|
-
"--stdin-filename",
|
|
26
|
-
"foo.js",
|
|
27
|
-
"--rule",
|
|
28
|
-
"no-unused-vars:off",
|
|
29
|
-
"--rule",
|
|
30
|
-
"no-constant-condition:off",
|
|
31
|
-
"--rule",
|
|
32
|
-
"no-empty:off",
|
|
33
|
-
"--rule",
|
|
34
|
-
"traceability/require-story-annotation:off",
|
|
35
|
-
"--rule",
|
|
36
|
-
"traceability/require-req-annotation:off",
|
|
37
|
-
"--rule",
|
|
38
|
-
"traceability/require-branch-annotation:off",
|
|
39
|
-
"--rule",
|
|
40
|
-
"traceability/valid-annotation-format:off",
|
|
41
|
-
"--rule",
|
|
42
|
-
"traceability/valid-story-reference:off",
|
|
43
|
-
"--rule",
|
|
44
|
-
"traceability/valid-req-reference:off",
|
|
45
|
-
"--rule",
|
|
46
|
-
rule,
|
|
47
|
-
];
|
|
48
|
-
return spawnSync(process.execPath, [eslintCliPath, ...args], {
|
|
49
|
-
encoding: "utf-8",
|
|
50
|
-
input: code,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
10
|
+
// Resolve the ESLint CLI binary and configuration path
|
|
11
|
+
const eslintPkgDir = path.dirname(require.resolve("eslint/package.json"));
|
|
12
|
+
const eslintCliPath = path.join(eslintPkgDir, "bin", "eslint.js");
|
|
13
|
+
const configPath = path.resolve(__dirname, "eslint.config.js");
|
|
53
14
|
|
|
15
|
+
// Define CLI integration test scenarios
|
|
54
16
|
const tests = [
|
|
55
17
|
{
|
|
56
18
|
name: "reports error when @story annotation is missing",
|
|
@@ -60,98 +22,82 @@ const tests = [
|
|
|
60
22
|
},
|
|
61
23
|
{
|
|
62
24
|
name: "does not report error when @story annotation is present",
|
|
63
|
-
code:
|
|
64
|
-
/**
|
|
25
|
+
code: `/**
|
|
65
26
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
66
27
|
*/
|
|
67
|
-
function foo() {}
|
|
68
|
-
`,
|
|
28
|
+
function foo() {}`,
|
|
69
29
|
rule: "traceability/require-story-annotation:error",
|
|
70
30
|
expectedStatus: 0,
|
|
71
31
|
},
|
|
72
|
-
{
|
|
73
|
-
name: "reports error when requirement reference is missing",
|
|
74
|
-
code: `/**\n * @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n * @req REQ-NON-EXISTENT\n */\nfunction foo() {}`,
|
|
75
|
-
rule: "traceability/valid-req-reference:error",
|
|
76
|
-
expectedStatus: 1,
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: "reports error when requirement reference uses path traversal",
|
|
80
|
-
code: `/**\n * @story ../docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n * @req REQ-PLUGIN-STRUCTURE\n */\nfunction foo() {}`,
|
|
81
|
-
rule: "traceability/valid-req-reference:error",
|
|
82
|
-
expectedStatus: 1,
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
name: "reports error when requirement reference uses absolute path",
|
|
86
|
-
code: `/**\n * @story /absolute/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md\n * @req REQ-PLUGIN-STRUCTURE\n */\nfunction foo() {}`,
|
|
87
|
-
rule: "traceability/valid-req-reference:error",
|
|
88
|
-
expectedStatus: 1,
|
|
89
|
-
},
|
|
90
32
|
{
|
|
91
33
|
name: "reports error when @req annotation is missing",
|
|
92
|
-
code:
|
|
93
|
-
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
94
|
-
*/\nfunction foo() {}`,
|
|
34
|
+
code: "function bar() {}",
|
|
95
35
|
rule: "traceability/require-req-annotation:error",
|
|
96
36
|
expectedStatus: 1,
|
|
97
37
|
},
|
|
98
38
|
{
|
|
99
|
-
name: "
|
|
39
|
+
name: "reports error when @story annotation uses path traversal and @req annotation uses path traversal",
|
|
100
40
|
code: `/**
|
|
101
|
-
* @story docs/stories/
|
|
102
|
-
* @req REQ-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: "reports error for missing branch annotations",
|
|
109
|
-
code: `if (true) {}`,
|
|
110
|
-
rule: "traceability/require-branch-annotation:error",
|
|
111
|
-
expectedStatus: 1,
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: "does not report error for branch with annotations",
|
|
115
|
-
code: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md\n// @req REQ-BRANCH-DETECTION\nif (true) {}`,
|
|
116
|
-
rule: "traceability/require-branch-annotation:error",
|
|
117
|
-
expectedStatus: 0,
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: "reports invalid annotation format",
|
|
121
|
-
code: `/**\n * @story invalid/path.txt\n * @req INVALID\n */\nfunction foo() {}`,
|
|
122
|
-
rule: "traceability/valid-annotation-format:error",
|
|
41
|
+
* @story ../docs/stories/invalid.story.md
|
|
42
|
+
* @req ../docs/requirements/REQ-INVALID.md
|
|
43
|
+
*/
|
|
44
|
+
function bar() {}`,
|
|
45
|
+
rule: "traceability/valid-req-reference:error",
|
|
123
46
|
expectedStatus: 1,
|
|
124
47
|
},
|
|
125
48
|
{
|
|
126
|
-
name: "
|
|
127
|
-
code:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
code: `/**\n * @story docs/stories/nonexistent.story.md\n */\nfunction foo() {}`,
|
|
134
|
-
rule: "traceability/valid-story-reference:error",
|
|
49
|
+
name: "reports error when @story annotation uses absolute path and @req annotation uses absolute path",
|
|
50
|
+
code: `/**
|
|
51
|
+
* @story /absolute/path/to/story.story.md
|
|
52
|
+
* @req /etc/passwd
|
|
53
|
+
*/
|
|
54
|
+
function baz() {}`,
|
|
55
|
+
rule: "traceability/valid-req-reference:error",
|
|
135
56
|
expectedStatus: 1,
|
|
136
57
|
},
|
|
137
|
-
{
|
|
138
|
-
name: "existing story file reference passes",
|
|
139
|
-
code: `/**\n * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md\n */\nfunction foo() {}`,
|
|
140
|
-
rule: "traceability/valid-story-reference:error",
|
|
141
|
-
expectedStatus: 0,
|
|
142
|
-
},
|
|
143
58
|
];
|
|
144
59
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Run ESLint CLI with given code and rule override
|
|
62
|
+
* @param {string} code Source code to lint via stdin
|
|
63
|
+
* @param {string} rule ESLint rule override e.g. "traceability/require-story-annotation:error"
|
|
64
|
+
* @returns {object} Result of spawnSync call
|
|
65
|
+
*/
|
|
66
|
+
function runEslint(code, rule) {
|
|
67
|
+
const args = [
|
|
68
|
+
"--no-config-lookup",
|
|
69
|
+
"--config",
|
|
70
|
+
configPath,
|
|
71
|
+
"--stdin",
|
|
72
|
+
"--stdin-filename",
|
|
73
|
+
"foo.js",
|
|
74
|
+
"--rule",
|
|
75
|
+
"no-unused-vars:off",
|
|
76
|
+
"--rule",
|
|
77
|
+
rule,
|
|
78
|
+
];
|
|
79
|
+
return spawnSync(process.execPath, [eslintCliPath, ...args], {
|
|
80
|
+
encoding: "utf-8",
|
|
81
|
+
input: code,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Execute tests and report results
|
|
86
|
+
let failures = 0;
|
|
87
|
+
tests.forEach((test) => {
|
|
88
|
+
const result = runEslint(test.code, test.rule);
|
|
89
|
+
const passed = result.status === test.expectedStatus;
|
|
90
|
+
if (passed) {
|
|
91
|
+
console.log(`✓ ${test.name}`);
|
|
92
|
+
} else {
|
|
93
|
+
console.error(`✗ ${test.name}`);
|
|
149
94
|
console.error(
|
|
150
|
-
`
|
|
95
|
+
` Expected exit code ${test.expectedStatus}, got ${result.status}`,
|
|
151
96
|
);
|
|
152
|
-
console.error(
|
|
153
|
-
|
|
97
|
+
if (result.stdout) console.error(` stdout: ${result.stdout}`);
|
|
98
|
+
if (result.stderr) console.error(` stderr: ${result.stderr}`);
|
|
99
|
+
failures++;
|
|
154
100
|
}
|
|
155
101
|
});
|
|
156
102
|
|
|
157
|
-
process.exit(
|
|
103
|
+
process.exit(failures > 0 ? 1 : 0);
|
package/docs/cli-integration.md
CHANGED
|
@@ -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 {};
|