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.
Files changed (94) hide show
  1. package/.github/workflows/ci-cd.yml +41 -35
  2. package/.husky/pre-commit +1 -1
  3. package/.husky/pre-push +1 -1
  4. package/.prettierignore +5 -1
  5. package/.releaserc.json +15 -0
  6. package/.voder/history.md +138 -264
  7. package/.voder/implementation-progress.md +110 -112
  8. package/.voder/last-action.md +62 -204
  9. package/.voder/plan.md +10 -10
  10. package/.voder/progress-chart.png +0 -0
  11. package/.voder/progress-log-areas.csv +4 -0
  12. package/.voder/progress-log.csv +4 -0
  13. package/CHANGELOG.md +20 -1
  14. package/CONTRIBUTING.md +15 -13
  15. package/README.md +2 -2
  16. package/cli-integration.js +61 -115
  17. package/docs/cli-integration.md +3 -1
  18. package/docs/conventional-commits-guide.md +185 -0
  19. package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +3 -1
  20. package/docs/decisions/005-github-actions-validation-tooling.accepted.md +144 -0
  21. package/docs/decisions/006-semantic-release-for-automated-publishing.accepted.md +227 -0
  22. package/eslint.config.js +4 -4
  23. package/package.json +7 -2
  24. package/tests/{basic.test.ts → plugin-setup.test.ts} +1 -1
  25. package/user-docs/migration-guide.md +71 -0
  26. package/lib/index.d.ts +0 -26
  27. package/lib/index.js +0 -11
  28. package/lib/src/index.d.ts +0 -80
  29. package/lib/src/index.js +0 -58
  30. package/lib/src/maintenance/batch.d.ts +0 -16
  31. package/lib/src/maintenance/batch.js +0 -28
  32. package/lib/src/maintenance/detect.d.ts +0 -6
  33. package/lib/src/maintenance/detect.js +0 -69
  34. package/lib/src/maintenance/index.d.ts +0 -14
  35. package/lib/src/maintenance/index.js +0 -22
  36. package/lib/src/maintenance/report.d.ts +0 -7
  37. package/lib/src/maintenance/report.js +0 -17
  38. package/lib/src/maintenance/update.d.ts +0 -6
  39. package/lib/src/maintenance/update.js +0 -67
  40. package/lib/src/maintenance/utils.d.ts +0 -6
  41. package/lib/src/maintenance/utils.js +0 -64
  42. package/lib/src/rules/require-branch-annotation.d.ts +0 -7
  43. package/lib/src/rules/require-branch-annotation.js +0 -111
  44. package/lib/src/rules/require-req-annotation.d.ts +0 -7
  45. package/lib/src/rules/require-req-annotation.js +0 -38
  46. package/lib/src/rules/require-story-annotation.d.ts +0 -7
  47. package/lib/src/rules/require-story-annotation.js +0 -50
  48. package/lib/src/rules/valid-annotation-format.d.ts +0 -10
  49. package/lib/src/rules/valid-annotation-format.js +0 -60
  50. package/lib/src/rules/valid-req-reference.d.ts +0 -3
  51. package/lib/src/rules/valid-req-reference.js +0 -104
  52. package/lib/src/rules/valid-story-reference.d.ts +0 -3
  53. package/lib/src/rules/valid-story-reference.js +0 -168
  54. package/lib/tests/basic.test.d.ts +0 -1
  55. package/lib/tests/basic.test.js +0 -51
  56. package/lib/tests/fixtures/stale/example.d.ts +0 -0
  57. package/lib/tests/fixtures/stale/example.js +0 -3
  58. package/lib/tests/fixtures/update/example.d.ts +0 -0
  59. package/lib/tests/fixtures/update/example.js +0 -3
  60. package/lib/tests/fixtures/valid-annotations/example.d.ts +0 -0
  61. package/lib/tests/fixtures/valid-annotations/example.js +0 -3
  62. package/lib/tests/index.test.d.ts +0 -1
  63. package/lib/tests/index.test.js +0 -72
  64. package/lib/tests/integration/file-validation.test.d.ts +0 -1
  65. package/lib/tests/integration/file-validation.test.js +0 -71
  66. package/lib/tests/integration/plugin-validation.test.d.ts +0 -1
  67. package/lib/tests/integration/plugin-validation.test.js +0 -83
  68. package/lib/tests/maintenance/batch.test.d.ts +0 -1
  69. package/lib/tests/maintenance/batch.test.js +0 -79
  70. package/lib/tests/maintenance/detect-isolated.test.d.ts +0 -1
  71. package/lib/tests/maintenance/detect-isolated.test.js +0 -95
  72. package/lib/tests/maintenance/detect.test.d.ts +0 -1
  73. package/lib/tests/maintenance/detect.test.js +0 -23
  74. package/lib/tests/maintenance/report.test.d.ts +0 -1
  75. package/lib/tests/maintenance/report.test.js +0 -67
  76. package/lib/tests/maintenance/update-isolated.test.d.ts +0 -1
  77. package/lib/tests/maintenance/update-isolated.test.js +0 -66
  78. package/lib/tests/maintenance/update.test.d.ts +0 -1
  79. package/lib/tests/maintenance/update.test.js +0 -26
  80. package/lib/tests/rules/require-branch-annotation.test.d.ts +0 -1
  81. package/lib/tests/rules/require-branch-annotation.test.js +0 -253
  82. package/lib/tests/rules/require-req-annotation.test.d.ts +0 -1
  83. package/lib/tests/rules/require-req-annotation.test.js +0 -41
  84. package/lib/tests/rules/require-story-annotation.test.d.ts +0 -1
  85. package/lib/tests/rules/require-story-annotation.test.js +0 -36
  86. package/lib/tests/rules/valid-annotation-format.test.d.ts +0 -1
  87. package/lib/tests/rules/valid-annotation-format.test.js +0 -58
  88. package/lib/tests/rules/valid-req-reference.test.d.ts +0 -1
  89. package/lib/tests/rules/valid-req-reference.test.js +0 -87
  90. package/lib/tests/rules/valid-story-reference.test.d.ts +0 -1
  91. package/lib/tests/rules/valid-story-reference.test.js +0 -69
  92. package/tests/integration/file-validation.test.ts +0 -78
  93. package/tests/integration/plugin-validation.test.ts +0 -84
  94. /package/tests/{index.test.ts → plugin-default-export-and-configs.test.ts} +0 -0
@@ -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
- * Helper to execute ESLint CLI integration tests for the traceability plugin
14
- * @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
15
- * @req REQ-PLUGIN-STRUCTURE - Utility for invoking ESLint with flat config in integration tests
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: "does not report error when @req annotation is present",
39
+ name: "reports error when @story annotation uses path traversal and @req annotation uses path traversal",
100
40
  code: `/**
101
- * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
102
- * @req REQ-ANNOTATION-REQUIRED
103
- */\nfunction foo() {}`,
104
- rule: "traceability/require-req-annotation:error",
105
- expectedStatus: 0,
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: "valid annotation format passes",
127
- code: `/**\n * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md\n * @req REQ-FORMAT-SPECIFICATION\n */\nfunction foo() {}`,
128
- rule: "traceability/valid-annotation-format:error",
129
- expectedStatus: 0,
130
- },
131
- {
132
- name: "reports missing story file reference",
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
- let exitCode = 0;
146
- tests.forEach(({ name, code, rule, expectedStatus }) => {
147
- const result = runEslint(code, rule);
148
- if (result.status !== expectedStatus) {
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
- `Test "${name}" failed. Expected status ${expectedStatus}, got ${result.status}.`,
95
+ ` Expected exit code ${test.expectedStatus}, got ${result.status}`,
151
96
  );
152
- console.error("stdout:", result.stdout);
153
- exitCode = 1;
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(exitCode);
103
+ process.exit(failures > 0 ? 1 : 0);
@@ -74,9 +74,11 @@ Current test scenarios:
74
74
 
75
75
  ## Usage
76
76
 
77
+ Note: The script lives at the project root.
78
+
77
79
  ```bash
78
80
  # Run CLI integration tests
79
- node cli-integration.js
81
+ node ./cli-integration.js
80
82
  ```
81
83
 
82
84
  ## Integration into CI
@@ -0,0 +1,185 @@
1
+ # Conventional Commits Guide
2
+
3
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/) to enable automated semantic versioning and changelog generation through semantic-release.
4
+
5
+ ## Commit Message Format
6
+
7
+ ```
8
+ <type>[optional scope]: <description>
9
+
10
+ [optional body]
11
+
12
+ [optional footer(s)]
13
+ ```
14
+
15
+ ## Types and Version Impact
16
+
17
+ ### `feat`: New Features (Minor Version)
18
+
19
+ - Adds new functionality
20
+ - Results in a **minor** version increment (e.g., 1.0.0 → 1.1.0)
21
+
22
+ Examples:
23
+
24
+ ```bash
25
+ feat: add new validation rule for story references
26
+ feat(rules): implement require-branch-annotation rule
27
+ feat: add CLI integration for batch processing
28
+ ```
29
+
30
+ ### `fix`: Bug Fixes (Patch Version)
31
+
32
+ - Fixes existing functionality
33
+ - Results in a **patch** version increment (e.g., 1.0.0 → 1.0.1)
34
+
35
+ Examples:
36
+
37
+ ```bash
38
+ fix: resolve annotation parsing for multiline comments
39
+ fix(validation): handle edge case in reference checking
40
+ fix: prevent false positives in story reference detection
41
+ ```
42
+
43
+ ### Breaking Changes (Major Version)
44
+
45
+ - Any commit with `!` after the type or `BREAKING CHANGE:` in footer
46
+ - Results in a **major** version increment (e.g., 1.0.0 → 2.0.0)
47
+
48
+ Examples:
49
+
50
+ ```bash
51
+ feat!: change API interface for rule configuration
52
+ fix!: remove deprecated annotation format support
53
+
54
+ feat: add new validation options
55
+
56
+ BREAKING CHANGE: The `allowUnresolved` option has been removed.
57
+ Use `strict: false` instead.
58
+ ```
59
+
60
+ ### Other Types (No Version Change)
61
+
62
+ These don't trigger releases but appear in changelog:
63
+
64
+ - `docs`: Documentation changes
65
+ - `style`: Code style changes (formatting, etc.)
66
+ - `refactor`: Code refactoring without functional changes
67
+ - `test`: Adding or updating tests
68
+ - `chore`: Build process, auxiliary tools, or maintenance
69
+ - `perf`: Performance improvements
70
+ - `ci`: CI/CD configuration changes
71
+
72
+ Examples:
73
+
74
+ ```bash
75
+ docs: update README with installation instructions
76
+ test: add unit tests for validation rules
77
+ chore: update dependencies to latest versions
78
+ ci: configure semantic-release for automated publishing
79
+ ```
80
+
81
+ ## Scopes (Optional)
82
+
83
+ Use scopes to specify what part of the codebase is affected:
84
+
85
+ - `rules`: ESLint rule implementations
86
+ - `maintenance`: Maintenance scripts and utilities
87
+ - `cli`: Command-line integration tools
88
+ - `config`: Configuration and setup files
89
+ - `deps`: Dependency updates
90
+
91
+ Examples:
92
+
93
+ ```bash
94
+ feat(rules): add valid-annotation-format rule
95
+ fix(maintenance): resolve batch processing memory leak
96
+ docs(config): add ESLint 9 setup guide
97
+ ```
98
+
99
+ ## Best Practices
100
+
101
+ ### Commit Message Guidelines
102
+
103
+ 1. **Use imperative mood**: "add feature" not "added feature"
104
+ 2. **Keep subject under 50 characters**: For better git log readability
105
+ 3. **Capitalize the subject line**: Start with capital letter
106
+ 4. **No period at the end**: Of the subject line
107
+ 5. **Explain what and why**: In the body, not how
108
+
109
+ ### When to Use Each Type
110
+
111
+ **Use `feat` when:**
112
+
113
+ - Adding new ESLint rules
114
+ - Adding new maintenance utilities
115
+ - Adding new configuration options
116
+ - Adding new CLI commands or features
117
+
118
+ **Use `fix` when:**
119
+
120
+ - Fixing rule logic or false positives/negatives
121
+ - Fixing crashes or runtime errors
122
+ - Fixing configuration issues
123
+ - Fixing documentation errors
124
+
125
+ **Use `refactor` when:**
126
+
127
+ - Improving code structure without changing behavior
128
+ - Renaming variables or functions
129
+ - Extracting common functionality
130
+ - Simplifying complex logic
131
+
132
+ **Use `docs` when:**
133
+
134
+ - Updating README, guides, or API documentation
135
+ - Adding code comments or JSDoc
136
+ - Updating examples or migration guides
137
+
138
+ ### Example Workflow
139
+
140
+ ```bash
141
+ # New feature
142
+ git commit -m "feat(rules): add require-story-annotation rule
143
+
144
+ Implements validation to ensure all functions have @story annotations
145
+ linking them to user stories for traceability.
146
+
147
+ Resolves: #123"
148
+
149
+ # Bug fix
150
+ git commit -m "fix: resolve false positive in annotation parsing
151
+
152
+ The regex pattern was incorrectly matching inline comments.
153
+ Updated to only match block comments that start at beginning of line."
154
+
155
+ # Breaking change
156
+ git commit -m "feat!: change rule configuration schema
157
+
158
+ BREAKING CHANGE: Rule options now use 'patterns' instead of 'pattern'.
159
+ Update your ESLint config:
160
+ - Before: { "pattern": "REQ-*" }
161
+ + After: { "patterns": ["REQ-*"] }"
162
+ ```
163
+
164
+ ## Integration with semantic-release
165
+
166
+ semantic-release analyzes commit messages to:
167
+
168
+ 1. **Determine version bump**: Based on feat/fix/breaking change types
169
+ 2. **Generate changelog**: From commit messages and pull request information
170
+ 3. **Create git tags**: For each release
171
+ 4. **Publish to npm**: Only when changes warrant a release
172
+
173
+ ## Validation
174
+
175
+ Pre-commit hooks will validate your commit messages follow the conventional format. If you need to bypass validation temporarily (not recommended), use:
176
+
177
+ ```bash
178
+ git commit --no-verify -m "your message"
179
+ ```
180
+
181
+ ## Resources
182
+
183
+ - [Conventional Commits Specification](https://www.conventionalcommits.org/)
184
+ - [semantic-release Documentation](https://semantic-release.gitbook.io/)
185
+ - [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format)
@@ -1,5 +1,5 @@
1
1
  ---
2
- status: "proposed"
2
+ status: "superseded"
3
3
  date: 2025-11-17
4
4
  decision-makers: [Development Team]
5
5
  consulted:
@@ -9,6 +9,8 @@ consulted:
9
9
  Semantic Versioning Specification,
10
10
  ]
11
11
  informed: [Project Stakeholders, CI/CD Pipeline Maintainers]
12
+ superseded-by: "006-semantic-release-for-automated-publishing"
13
+ superseded-date: "2025-11-17"
12
14
  ---
13
15
 
14
16
  # Automated Version Bumping for CI/CD Publishing
@@ -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/)