faf-taf-git 2.4.1 → 2.4.2

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 (50) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +1 -1
  3. package/package.json +14 -1
  4. package/project.faf +2 -2
  5. package/.faf-dna +0 -95
  6. package/.fafignore +0 -41
  7. package/.github/dependabot.yml +0 -10
  8. package/.github/workflows/ci.yml +0 -53
  9. package/.github/workflows/claude-code-review.yml +0 -36
  10. package/.github/workflows/claude.yml +0 -39
  11. package/.github/workflows/homebrew.yml +0 -19
  12. package/.taf +0 -98
  13. package/CLAUDE.md +0 -30
  14. package/CODE_OF_CONDUCT.md +0 -21
  15. package/CONTRIBUTING.md +0 -289
  16. package/SECURITY.md +0 -19
  17. package/action.yml +0 -50
  18. package/agent.fafa +0 -53
  19. package/badge.svg +0 -21
  20. package/dist/bundle/index.js +0 -36554
  21. package/dist/index.js +0 -42827
  22. package/dist/index.js.map +0 -1
  23. package/dist/licenses.txt +0 -126
  24. package/dist/sourcemap-register.js +0 -1
  25. package/docs/RELEASE-NOTES.md +0 -200
  26. package/docs/USER-GUIDE.md +0 -301
  27. package/jest.config.js +0 -13
  28. package/src/badge.ts +0 -138
  29. package/src/cli.ts +0 -311
  30. package/src/index.ts +0 -201
  31. package/src/parsers/bun.ts +0 -103
  32. package/src/parsers/index.ts +0 -50
  33. package/src/parsers/jest.ts +0 -104
  34. package/src/parsers/junit.ts +0 -110
  35. package/src/parsers/vitest.ts +0 -65
  36. package/src/parsers/wjttc.ts +0 -160
  37. package/src/taf-core.ts +0 -139
  38. package/test-mcp.ts +0 -83
  39. package/test-standalone.ts +0 -87
  40. package/tests/action-bundle.test.ts +0 -34
  41. package/tests/action-parse-error.test.ts +0 -47
  42. package/tests/badge.test.ts +0 -260
  43. package/tests/bun-parser.test.ts +0 -173
  44. package/tests/cli-version.test.ts +0 -31
  45. package/tests/jest-parser.test.ts +0 -122
  46. package/tests/junit-parser.test.ts +0 -109
  47. package/tests/vitest-parser.test.ts +0 -112
  48. package/tests/wjttc-parser.test.ts +0 -116
  49. package/tests/wjttc-taf.test.ts +0 -470
  50. package/tsconfig.json +0 -18
@@ -1,301 +0,0 @@
1
- # FAF TAF Action - User Guide
2
-
3
- ## Introduction
4
-
5
- The FAF TAF Action automatically maintains a `.taf` (Testing Activity Feed) file that tracks your test runs over time. This creates a permanent, git-tracked record of your project's test quality.
6
-
7
- ### The Golden Triangle
8
-
9
- ```
10
- .faf
11
- (WHAT IT IS)
12
- / \
13
- / \
14
- / \
15
- repo ←→ .taf
16
- (IMPLEMENTATION) (PROOF IT WORKS)
17
- ```
18
-
19
- - **.faf** - Project DNA that tells AI what your project is
20
- - **repo** - Your actual implementation (code doesn't lie)
21
- - **.taf** - Permanent proof that your code works (formats don't negotiate)
22
-
23
- ## Prerequisites
24
-
25
- ### 1. Install FAF CLI
26
-
27
- ```bash
28
- npm install -g faf-cli
29
- # or
30
- brew install faf-cli
31
- ```
32
-
33
- ### 2. Initialize .taf File
34
-
35
- In your project root:
36
-
37
- ```bash
38
- faf taf init
39
- ```
40
-
41
- This creates a `.taf` file that tracks your testing timeline.
42
-
43
- ### 3. Commit .taf to Git
44
-
45
- ```bash
46
- git add .taf
47
- git commit -m "feat: add testing timeline"
48
- ```
49
-
50
- ## Basic Setup
51
-
52
- ### Minimal Configuration
53
-
54
- Add to `.github/workflows/test.yml`:
55
-
56
- ```yaml
57
- name: Tests
58
-
59
- on: [push, pull_request]
60
-
61
- jobs:
62
- test:
63
- runs-on: ubuntu-latest
64
-
65
- steps:
66
- - uses: actions/checkout@v4
67
-
68
- - name: Setup Node
69
- uses: actions/setup-node@v4
70
- with:
71
- node-version: '20'
72
-
73
- - name: Install dependencies
74
- run: npm ci
75
-
76
- - name: Run tests and update .taf
77
- uses: Wolfe-Jam/faf-taf-action@v1
78
- ```
79
-
80
- That's it! The action will:
81
- 1. Run `npm test` (default)
82
- 2. Parse Jest output
83
- 3. Update `.taf` file
84
- 4. Commit changes automatically
85
-
86
- ## Advanced Configuration
87
-
88
- ### Custom Test Command
89
-
90
- ```yaml
91
- - uses: Wolfe-Jam/faf-taf-action@v1
92
- with:
93
- test-command: 'npm run test:coverage'
94
- ```
95
-
96
- ### Custom Commit Message
97
-
98
- ```yaml
99
- - uses: Wolfe-Jam/faf-taf-action@v1
100
- with:
101
- commit-message: 'test: update .taf timeline [skip ci]'
102
- ```
103
-
104
- ### Disable Auto-Commit
105
-
106
- Handle commits yourself:
107
-
108
- ```yaml
109
- - uses: Wolfe-Jam/faf-taf-action@v1
110
- id: taf
111
- with:
112
- auto-commit: false
113
-
114
- - name: Custom commit logic
115
- if: steps.taf.outputs.taf-updated == 'true'
116
- run: |
117
- git add .taf
118
- git commit -m "test: $(date +'%Y-%m-%d') test results"
119
- git push
120
- ```
121
-
122
- ## Using Outputs
123
-
124
- The action provides several outputs you can use:
125
-
126
- ```yaml
127
- - uses: Wolfe-Jam/faf-taf-action@v1
128
- id: taf
129
-
130
- - name: Check test results
131
- run: |
132
- echo "Result: ${{ steps.taf.outputs.result }}"
133
- echo "Tests: ${{ steps.taf.outputs.passed }}/${{ steps.taf.outputs.total }}"
134
-
135
- - name: Fail if tests failed
136
- if: steps.taf.outputs.result == 'FAILED'
137
- run: exit 1
138
-
139
- - name: Celebrate improvement
140
- if: steps.taf.outputs.result == 'IMPROVED'
141
- run: echo "Tests are improving!"
142
- ```
143
-
144
- ### Available Outputs
145
-
146
- - `result` - PASSED, FAILED, IMPROVED, or DEGRADED
147
- - `passed` - Number of passing tests
148
- - `failed` - Number of failing tests
149
- - `total` - Total test count
150
- - `taf-updated` - Whether .taf was modified
151
-
152
- ## Workflow Patterns
153
-
154
- ### Skip CI on .taf Updates
155
-
156
- Prevent infinite loops:
157
-
158
- ```yaml
159
- - uses: Wolfe-Jam/faf-taf-action@v1
160
- with:
161
- commit-message: 'test: update .taf [skip ci]'
162
- ```
163
-
164
- ### Only Update on Main Branch
165
-
166
- ```yaml
167
- - uses: Wolfe-Jam/faf-taf-action@v1
168
- if: github.ref == 'refs/heads/main'
169
- ```
170
-
171
- ### Different Commands per Environment
172
-
173
- ```yaml
174
- - uses: Wolfe-Jam/faf-taf-action@v1
175
- with:
176
- test-command: ${{ matrix.os == 'ubuntu-latest' && 'npm test' || 'npm run test:unit' }}
177
- ```
178
-
179
- ### Combine with Coverage
180
-
181
- ```yaml
182
- - name: Run tests with coverage
183
- uses: Wolfe-Jam/faf-taf-action@v1
184
- with:
185
- test-command: 'npm run test:coverage'
186
-
187
- - name: Upload coverage
188
- uses: codecov/codecov-action@v3
189
- if: always()
190
- ```
191
-
192
- ## Permissions
193
-
194
- For auto-commit to work, ensure your workflow has write permissions:
195
-
196
- ```yaml
197
- permissions:
198
- contents: write
199
- ```
200
-
201
- If using a fine-grained PAT:
202
-
203
- ```yaml
204
- - uses: actions/checkout@v4
205
- with:
206
- token: ${{ secrets.GITHUB_TOKEN }}
207
-
208
- - uses: Wolfe-Jam/faf-taf-action@v1
209
- ```
210
-
211
- ## Troubleshooting
212
-
213
- ### "No .taf file found"
214
-
215
- Run `faf taf init` in your project root and commit the file.
216
-
217
- ### "Could not parse test output"
218
-
219
- Currently only Jest is supported. Check that your test command outputs Jest format.
220
-
221
- ### Tests pass but action fails
222
-
223
- Check the action logs for parsing errors. The action needs the standard Jest summary line:
224
-
225
- ```
226
- Tests: 173 passed, 173 total
227
- ```
228
-
229
- ### Commits not pushing
230
-
231
- 1. Verify `permissions: contents: write` in workflow
232
- 2. Check that `.taf` is not in `.gitignore`
233
- 3. Ensure git is configured properly in the workflow
234
-
235
- ### Action shows "up to date" but .taf wasn't updated
236
-
237
- The action may have determined there were no changes. Check:
238
- - Did tests actually run?
239
- - Was there Jest output to parse?
240
- - Check action logs for details
241
-
242
- ## Best Practices
243
-
244
- ### 1. Run on Every Push
245
-
246
- Keep your .taf file current:
247
-
248
- ```yaml
249
- on: [push, pull_request]
250
- ```
251
-
252
- ### 2. Use [skip ci] for .taf Commits
253
-
254
- Prevent infinite loops:
255
-
256
- ```yaml
257
- commit-message: 'test: update .taf [skip ci]'
258
- ```
259
-
260
- ### 3. Track .taf in Git
261
-
262
- Never add `.taf` to `.gitignore`. It's meant to be tracked!
263
-
264
- ### 4. Review .taf Changes
265
-
266
- When reviewing PRs, check .taf changes to see test quality trends.
267
-
268
- ### 5. Combine with .faf
269
-
270
- Use both `.faf` (project context) and `.taf` (proof of quality) together for maximum value.
271
-
272
- ## Philosophy
273
-
274
- ### You Don't Negotiate with a Format
275
-
276
- .taf files are structured data, not prose. They describe themselves. No interpretation needed.
277
-
278
- ### Software Accountability
279
-
280
- Every test run becomes permanent, git-tracked proof that your code works (or doesn't). No hiding, no forgetting.
281
-
282
- ### The Format Describes Itself
283
-
284
- Open your `.taf` file. You'll immediately understand what it tracks and why it matters.
285
-
286
- ## Learn More
287
-
288
- - [.taf Format Specification](https://faf.one/docs/taf)
289
- - [FAF CLI Documentation](https://faf.one/docs)
290
- - [Example .taf Files](https://github.com/Wolfe-Jam/faf-cli/blob/main/.taf)
291
- - [GitHub Discussions](https://github.com/Wolfe-Jam/faf/discussions)
292
-
293
- ## Support
294
-
295
- - Report issues: [GitHub Issues](https://github.com/Wolfe-Jam/faf-taf-action/issues)
296
- - Ask questions: [GitHub Discussions](https://github.com/Wolfe-Jam/faf/discussions)
297
- - Email: team@faf.one
298
-
299
- ## License
300
-
301
- MIT - Free forever, no strings attached.
package/jest.config.js DELETED
@@ -1,13 +0,0 @@
1
- module.exports = {
2
- preset: 'ts-jest',
3
- testEnvironment: 'node',
4
- roots: ['<rootDir>/tests'],
5
- testMatch: ['**/*.test.ts'],
6
- collectCoverageFrom: [
7
- 'src/**/*.ts',
8
- '!src/**/*.d.ts',
9
- ],
10
- coverageDirectory: 'coverage',
11
- coverageReporters: ['text', 'lcov', 'html'],
12
- verbose: true,
13
- };
package/src/badge.ts DELETED
@@ -1,138 +0,0 @@
1
- /**
2
- * Badge Generator for faf-taf-git
3
- *
4
- * Generates shields.io-style SVG badges from .taf test history.
5
- * Self-contained SVG with Verdana font, no external dependencies.
6
- */
7
-
8
- import * as fs from 'fs';
9
- import * as yaml from 'yaml';
10
-
11
- export interface BadgeOptions {
12
- tafPath?: string;
13
- label?: string;
14
- }
15
-
16
- export interface BadgeResult {
17
- success: boolean;
18
- svg?: string;
19
- error?: string;
20
- }
21
-
22
- interface LatestRun {
23
- passed: number;
24
- total: number;
25
- failed: number;
26
- skipped: number;
27
- }
28
-
29
- const COLOR_PASS = '#003366'; // Navy blue (deep — white-text contrast; cyan was too light)
30
- const COLOR_FAIL = '#E32400'; // Red
31
- const COLOR_NONE = '#9F9F9F'; // Gray
32
-
33
- /**
34
- * Render a shields.io flat-style SVG badge.
35
- */
36
- export function renderBadgeSvg(label: string, value: string, color: string): string {
37
- // Approximate text widths using Verdana 11px (6.5px per char average)
38
- const charWidth = 6.5;
39
- const padding = 10;
40
- const labelWidth = Math.round(label.length * charWidth + padding * 2);
41
- const valueWidth = Math.round(value.length * charWidth + padding * 2);
42
- const totalWidth = labelWidth + valueWidth;
43
- const height = 20;
44
-
45
- const labelX = labelWidth / 2;
46
- const valueX = labelWidth + valueWidth / 2;
47
-
48
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="${height}" role="img" aria-label="${label}: ${value}">
49
- <title>${label}: ${value}</title>
50
- <linearGradient id="s" x2="0" y2="100%">
51
- <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
52
- <stop offset="1" stop-opacity=".1"/>
53
- </linearGradient>
54
- <clipPath id="r">
55
- <rect width="${totalWidth}" height="${height}" rx="3" fill="#fff"/>
56
- </clipPath>
57
- <g clip-path="url(#r)">
58
- <rect width="${labelWidth}" height="${height}" fill="#555"/>
59
- <rect x="${labelWidth}" width="${valueWidth}" height="${height}" fill="${color}"/>
60
- <rect width="${totalWidth}" height="${height}" fill="url(#s)"/>
61
- </g>
62
- <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
63
- <text x="${labelX}" y="14" fill="#010101" fill-opacity=".3">${label}</text>
64
- <text x="${labelX}" y="13" fill="#fff">${label}</text>
65
- <text x="${valueX}" y="14" fill="#010101" fill-opacity=".3">${value}</text>
66
- <text x="${valueX}" y="13" fill="#fff">${value}</text>
67
- </g>
68
- </svg>`;
69
- }
70
-
71
- /**
72
- * Read a .taf file and extract the latest test run.
73
- */
74
- function getLatestRun(tafPath: string): LatestRun | null {
75
- if (!fs.existsSync(tafPath)) {
76
- return null;
77
- }
78
-
79
- const content = fs.readFileSync(tafPath, 'utf-8');
80
-
81
- // Handle YAML document separators (same logic as taf-core.ts)
82
- const lines = content.split('\n');
83
- const yamlLines: string[] = [];
84
- for (const line of lines) {
85
- if (line.trim() === '---' && yamlLines.length > 0) break;
86
- if (line.trim() === '---' && yamlLines.length === 0) continue;
87
- yamlLines.push(line);
88
- }
89
-
90
- const parsed = yaml.parse(yamlLines.join('\n'));
91
-
92
- if (!parsed || typeof parsed !== 'object') return null;
93
- if (!Array.isArray(parsed.test_history) || parsed.test_history.length === 0) return null;
94
-
95
- const latest = parsed.test_history[parsed.test_history.length - 1];
96
- if (!latest.tests || typeof latest.tests.total !== 'number') return null;
97
-
98
- return {
99
- passed: latest.tests.passed ?? 0,
100
- total: latest.tests.total,
101
- failed: latest.tests.failed ?? 0,
102
- skipped: latest.tests.skipped ?? 0,
103
- };
104
- }
105
-
106
- /**
107
- * Generate a badge SVG from a .taf file.
108
- */
109
- export function generateBadge(options: BadgeOptions = {}): BadgeResult {
110
- const label = options.label || 'TAF';
111
- const tafPath = options.tafPath || '.taf';
112
-
113
- try {
114
- const run = getLatestRun(tafPath);
115
-
116
- if (!run) {
117
- return {
118
- success: true,
119
- svg: renderBadgeSvg(label, 'no data', COLOR_NONE),
120
- };
121
- }
122
-
123
- const skippedSuffix = run.skipped > 0 ? ` (${run.skipped} skipped)` : '';
124
- const displayPassed = run.failed === 0 ? run.total : run.passed;
125
- const value = `${displayPassed}/${run.total} passing${skippedSuffix}`;
126
- const color = run.failed === 0 ? COLOR_PASS : COLOR_FAIL;
127
-
128
- return {
129
- success: true,
130
- svg: renderBadgeSvg(label, value, color),
131
- };
132
- } catch (error) {
133
- return {
134
- success: false,
135
- error: error instanceof Error ? error.message : 'Failed to generate badge',
136
- };
137
- }
138
- }