eslint-plugin-traceability 1.0.3 → 1.0.5
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 +41 -35
- package/.husky/pre-commit +1 -1
- package/.husky/pre-push +1 -1
- package/.prettierignore +5 -1
- package/.releaserc.json +15 -0
- 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 +20 -1
- package/CONTRIBUTING.md +15 -13
- package/README.md +2 -2
- package/cli-integration.js +61 -115
- package/docs/cli-integration.md +3 -1
- package/docs/conventional-commits-guide.md +185 -0
- package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +3 -1
- package/docs/decisions/005-github-actions-validation-tooling.accepted.md +144 -0
- package/docs/decisions/006-semantic-release-for-automated-publishing.accepted.md +227 -0
- package/eslint.config.js +4 -4
- package/package.json +7 -2
- 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/src/index.d.ts +0 -80
- package/lib/src/index.js +0 -58
- package/lib/src/maintenance/batch.d.ts +0 -16
- package/lib/src/maintenance/batch.js +0 -28
- package/lib/src/maintenance/detect.d.ts +0 -6
- package/lib/src/maintenance/detect.js +0 -69
- package/lib/src/maintenance/index.d.ts +0 -14
- package/lib/src/maintenance/index.js +0 -22
- package/lib/src/maintenance/report.d.ts +0 -7
- package/lib/src/maintenance/report.js +0 -17
- package/lib/src/maintenance/update.d.ts +0 -6
- package/lib/src/maintenance/update.js +0 -67
- package/lib/src/maintenance/utils.d.ts +0 -6
- package/lib/src/maintenance/utils.js +0 -64
- package/lib/src/rules/require-branch-annotation.d.ts +0 -7
- package/lib/src/rules/require-branch-annotation.js +0 -111
- package/lib/src/rules/require-req-annotation.d.ts +0 -7
- package/lib/src/rules/require-req-annotation.js +0 -38
- package/lib/src/rules/require-story-annotation.d.ts +0 -7
- package/lib/src/rules/require-story-annotation.js +0 -50
- package/lib/src/rules/valid-annotation-format.d.ts +0 -10
- package/lib/src/rules/valid-annotation-format.js +0 -60
- package/lib/src/rules/valid-req-reference.d.ts +0 -3
- package/lib/src/rules/valid-req-reference.js +0 -104
- package/lib/src/rules/valid-story-reference.d.ts +0 -3
- package/lib/src/rules/valid-story-reference.js +0 -168
- package/lib/tests/basic.test.d.ts +0 -1
- package/lib/tests/basic.test.js +0 -51
- package/lib/tests/fixtures/stale/example.d.ts +0 -0
- package/lib/tests/fixtures/stale/example.js +0 -3
- package/lib/tests/fixtures/update/example.d.ts +0 -0
- package/lib/tests/fixtures/update/example.js +0 -3
- package/lib/tests/fixtures/valid-annotations/example.d.ts +0 -0
- package/lib/tests/fixtures/valid-annotations/example.js +0 -3
- package/lib/tests/index.test.d.ts +0 -1
- package/lib/tests/index.test.js +0 -72
- 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/lib/tests/maintenance/batch.test.d.ts +0 -1
- package/lib/tests/maintenance/batch.test.js +0 -79
- package/lib/tests/maintenance/detect-isolated.test.d.ts +0 -1
- package/lib/tests/maintenance/detect-isolated.test.js +0 -95
- package/lib/tests/maintenance/detect.test.d.ts +0 -1
- package/lib/tests/maintenance/detect.test.js +0 -23
- package/lib/tests/maintenance/report.test.d.ts +0 -1
- package/lib/tests/maintenance/report.test.js +0 -67
- package/lib/tests/maintenance/update-isolated.test.d.ts +0 -1
- package/lib/tests/maintenance/update-isolated.test.js +0 -66
- package/lib/tests/maintenance/update.test.d.ts +0 -1
- package/lib/tests/maintenance/update.test.js +0 -26
- package/lib/tests/rules/require-branch-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-branch-annotation.test.js +0 -253
- package/lib/tests/rules/require-req-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-req-annotation.test.js +0 -41
- package/lib/tests/rules/require-story-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-story-annotation.test.js +0 -36
- package/lib/tests/rules/valid-annotation-format.test.d.ts +0 -1
- package/lib/tests/rules/valid-annotation-format.test.js +0 -58
- package/lib/tests/rules/valid-req-reference.test.d.ts +0 -1
- package/lib/tests/rules/valid-req-reference.test.js +0 -87
- package/lib/tests/rules/valid-story-reference.test.d.ts +0 -1
- package/lib/tests/rules/valid-story-reference.test.js +0 -69
- package/tests/integration/file-validation.test.ts +0 -78
- package/tests/integration/plugin-validation.test.ts +0 -84
- /package/tests/{index.test.ts → plugin-default-export-and-configs.test.ts} +0 -0
|
@@ -1,87 +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
|
-
* Tests for: docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
8
|
-
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
9
|
-
* @req REQ-DEEP-PARSE - Verify valid-req-reference rule enforces existing requirement content
|
|
10
|
-
*/
|
|
11
|
-
const eslint_1 = require("eslint");
|
|
12
|
-
const valid_req_reference_1 = __importDefault(require("../../src/rules/valid-req-reference"));
|
|
13
|
-
const ruleTester = new eslint_1.RuleTester({
|
|
14
|
-
languageOptions: { parserOptions: { ecmaVersion: 2020 } },
|
|
15
|
-
});
|
|
16
|
-
describe("Valid Req Reference Rule (Story 010.0-DEV-DEEP-VALIDATION)", () => {
|
|
17
|
-
ruleTester.run("valid-req-reference", valid_req_reference_1.default, {
|
|
18
|
-
valid: [
|
|
19
|
-
{
|
|
20
|
-
name: "[REQ-DEEP-PARSE] valid requirement reference existing in story file",
|
|
21
|
-
code: `// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
22
|
-
// @req REQ-PLUGIN-STRUCTURE`,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: "[REQ-DEEP-BULLET] valid bullet list requirement existing in bullet story fixture",
|
|
26
|
-
code: `// @story tests/fixtures/story_bullet.md
|
|
27
|
-
// @req REQ-BULLET-LIST`,
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
invalid: [
|
|
31
|
-
{
|
|
32
|
-
name: "[REQ-DEEP-MATCH] missing requirement in story file",
|
|
33
|
-
code: `// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
34
|
-
// @req REQ-NON-EXISTENT`,
|
|
35
|
-
errors: [
|
|
36
|
-
{
|
|
37
|
-
messageId: "reqMissing",
|
|
38
|
-
data: {
|
|
39
|
-
reqId: "REQ-NON-EXISTENT",
|
|
40
|
-
storyPath: "docs/stories/001.0-DEV-PLUGIN-SETUP.story.md",
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "[REQ-DEEP-PARSE] disallow path traversal in story path",
|
|
47
|
-
code: `// @story ../docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
48
|
-
// @req REQ-PLUGIN-STRUCTURE`,
|
|
49
|
-
errors: [
|
|
50
|
-
{
|
|
51
|
-
messageId: "invalidPath",
|
|
52
|
-
data: {
|
|
53
|
-
storyPath: "../docs/stories/001.0-DEV-PLUGIN-SETUP.story.md",
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
name: "[REQ-DEEP-PARSE] disallow absolute path in story path",
|
|
60
|
-
code: `// @story /absolute/path/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
61
|
-
// @req REQ-PLUGIN-STRUCTURE`,
|
|
62
|
-
errors: [
|
|
63
|
-
{
|
|
64
|
-
messageId: "invalidPath",
|
|
65
|
-
data: {
|
|
66
|
-
storyPath: "/absolute/path/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md",
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: "[REQ-DEEP-BULLET] missing bullet list requirement in bullet story fixture",
|
|
73
|
-
code: `// @story tests/fixtures/story_bullet.md
|
|
74
|
-
// @req REQ-MISSING-BULLET`,
|
|
75
|
-
errors: [
|
|
76
|
-
{
|
|
77
|
-
messageId: "reqMissing",
|
|
78
|
-
data: {
|
|
79
|
-
reqId: "REQ-MISSING-BULLET",
|
|
80
|
-
storyPath: "tests/fixtures/story_bullet.md",
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
});
|
|
87
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,69 +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
|
-
* Tests for: docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
8
|
-
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
9
|
-
* @req REQ-FILE-EXISTENCE - Verify valid-story-reference rule enforces existing .story.md files
|
|
10
|
-
*/
|
|
11
|
-
const eslint_1 = require("eslint");
|
|
12
|
-
const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
|
|
13
|
-
const ruleTester = new eslint_1.RuleTester({
|
|
14
|
-
languageOptions: { parserOptions: { ecmaVersion: 2020 } },
|
|
15
|
-
});
|
|
16
|
-
describe("Valid Story Reference Rule (Story 006.0-DEV-FILE-VALIDATION)", () => {
|
|
17
|
-
ruleTester.run("valid-story-reference", valid_story_reference_1.default, {
|
|
18
|
-
valid: [
|
|
19
|
-
{
|
|
20
|
-
name: "[REQ-FILE-EXISTENCE] valid story file reference",
|
|
21
|
-
code: `// @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md`,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: "[REQ-EXTENSION] valid .story.md extension",
|
|
25
|
-
code: `// @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md`,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: "[REQ-PATH-RESOLUTION] valid relative path with ./ prefix",
|
|
29
|
-
code: `// @story ./docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md`,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
invalid: [
|
|
33
|
-
{
|
|
34
|
-
name: "[REQ-PATH-RESOLUTION] missing file",
|
|
35
|
-
code: `// @story docs/stories/missing-file.story.md`,
|
|
36
|
-
errors: [
|
|
37
|
-
{
|
|
38
|
-
messageId: "fileMissing",
|
|
39
|
-
data: { path: "docs/stories/missing-file.story.md" },
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: "[REQ-EXTENSION] invalid extension",
|
|
45
|
-
code: `// @story docs/stories/001.0-DEV-PLUGIN-SETUP.md`,
|
|
46
|
-
errors: [
|
|
47
|
-
{
|
|
48
|
-
messageId: "invalidExtension",
|
|
49
|
-
data: { path: "docs/stories/001.0-DEV-PLUGIN-SETUP.md" },
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: "[REQ-PATH-SECURITY] path traversal",
|
|
55
|
-
code: `// @story ../outside.story.md`,
|
|
56
|
-
errors: [
|
|
57
|
-
{ messageId: "invalidPath", data: { path: "../outside.story.md" } },
|
|
58
|
-
],
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: "[REQ-ABSOLUTE-PATH] absolute path not allowed",
|
|
62
|
-
code: `// @story /etc/passwd.story.md`,
|
|
63
|
-
errors: [
|
|
64
|
-
{ messageId: "invalidPath", data: { path: "/etc/passwd.story.md" } },
|
|
65
|
-
],
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
});
|
|
69
|
-
});
|
|
@@ -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
|