faf-taf-git 2.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/.faf +126 -0
- package/.faf-dna +95 -0
- package/.fafignore +41 -0
- package/.taf +21 -0
- package/CHANGELOG.md +208 -0
- package/CLAUDE.md +30 -0
- package/CONTRIBUTING.md +286 -0
- package/LICENSE +21 -0
- package/README.md +496 -0
- package/action.yml +42 -0
- package/dist/bundle/index.js +36554 -0
- package/dist/cli.d.ts +31 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +380 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36560 -0
- package/dist/index.js.map +1 -0
- package/dist/licenses.txt +148 -0
- package/dist/main.d.ts +7 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +147 -0
- package/dist/main.js.map +1 -0
- package/dist/parsers/jest.d.ts +38 -0
- package/dist/parsers/jest.d.ts.map +1 -0
- package/dist/parsers/jest.js +87 -0
- package/dist/parsers/jest.js.map +1 -0
- package/dist/sourcemap-register.js +1 -0
- package/dist/taf-core.d.ts +12 -0
- package/dist/taf-core.d.ts.map +1 -0
- package/dist/taf-core.js +136 -0
- package/dist/taf-core.js.map +1 -0
- package/docs/RELEASE-NOTES.md +200 -0
- package/docs/USER-GUIDE.md +301 -0
- package/jest.config.js +13 -0
- package/package.json +47 -0
- package/project.faf +259 -0
- package/src/cli.ts +393 -0
- package/src/index.ts +131 -0
- package/src/parsers/jest.ts +104 -0
- package/src/taf-core.ts +139 -0
- package/test-mcp.ts +83 -0
- package/test-standalone.ts +87 -0
- package/tests/jest-parser.test.ts +122 -0
- package/tests/wjttc-taf.test.ts +470 -0
- package/tsconfig.json +18 -0
package/dist/taf-core.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TAF Core - Simplified for GitHub Action
|
|
4
|
+
*
|
|
5
|
+
* Pure functions for reading, parsing, and updating .taf files
|
|
6
|
+
* Derived from faf-cli TAF implementation (MCP-portable)
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.updateTafFile = updateTafFile;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const yaml = __importStar(require("yaml"));
|
|
45
|
+
/**
|
|
46
|
+
* Update .taf file with new test results
|
|
47
|
+
* Creates the file if it doesn't exist
|
|
48
|
+
*/
|
|
49
|
+
function updateTafFile(tafPath, testResults) {
|
|
50
|
+
try {
|
|
51
|
+
let taf;
|
|
52
|
+
// Check if .taf exists, create if not
|
|
53
|
+
if (fs.existsSync(tafPath)) {
|
|
54
|
+
const content = fs.readFileSync(tafPath, 'utf-8');
|
|
55
|
+
taf = parseTAF(content);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Create new .taf file
|
|
59
|
+
const projectName = require('path').basename(require('path').dirname(tafPath));
|
|
60
|
+
taf = createTAF(projectName);
|
|
61
|
+
}
|
|
62
|
+
// Create test run entry
|
|
63
|
+
const run = {
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
result: testResults.result,
|
|
66
|
+
tests: {
|
|
67
|
+
total: testResults.total,
|
|
68
|
+
passed: testResults.passed,
|
|
69
|
+
failed: testResults.failed,
|
|
70
|
+
skipped: testResults.skipped,
|
|
71
|
+
},
|
|
72
|
+
trigger: 'github-actions',
|
|
73
|
+
};
|
|
74
|
+
// Append to history
|
|
75
|
+
taf.test_history.push(run);
|
|
76
|
+
// Serialize and write back
|
|
77
|
+
const updated = serializeTAF(taf);
|
|
78
|
+
fs.writeFileSync(tafPath, updated, 'utf-8');
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error('Failed to update .taf file:', error);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create a new TAF file structure
|
|
88
|
+
*/
|
|
89
|
+
function createTAF(projectName) {
|
|
90
|
+
return {
|
|
91
|
+
format_version: '1.0.0',
|
|
92
|
+
project: projectName,
|
|
93
|
+
created: new Date().toISOString(),
|
|
94
|
+
last_updated: new Date().toISOString(),
|
|
95
|
+
test_history: [],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse .taf file content
|
|
100
|
+
*/
|
|
101
|
+
function parseTAF(content) {
|
|
102
|
+
// Split on document separator and take only first document
|
|
103
|
+
const lines = content.split('\n');
|
|
104
|
+
const yamlLines = [];
|
|
105
|
+
for (const line of lines) {
|
|
106
|
+
// Stop at document separator (but skip initial one if present)
|
|
107
|
+
if (line.trim() === '---' && yamlLines.length > 0) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
// Skip initial document separator
|
|
111
|
+
if (line.trim() === '---' && yamlLines.length === 0) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
yamlLines.push(line);
|
|
115
|
+
}
|
|
116
|
+
const parsed = yaml.parse(yamlLines.join('\n'));
|
|
117
|
+
// Basic validation
|
|
118
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
119
|
+
throw new Error('Invalid .taf file: not a valid YAML object');
|
|
120
|
+
}
|
|
121
|
+
if (!parsed.test_history || !Array.isArray(parsed.test_history)) {
|
|
122
|
+
throw new Error('Invalid .taf file: missing or invalid test_history');
|
|
123
|
+
}
|
|
124
|
+
return parsed;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Serialize TAF object back to YAML
|
|
128
|
+
* Uses yaml library to maintain existing format
|
|
129
|
+
*/
|
|
130
|
+
function serializeTAF(taf) {
|
|
131
|
+
// Update last_updated timestamp
|
|
132
|
+
taf.last_updated = new Date().toISOString();
|
|
133
|
+
// Use yaml.stringify to preserve format
|
|
134
|
+
return yaml.stringify(taf);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=taf-core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taf-core.js","sourceRoot":"","sources":["../src/taf-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Release Notes
|
|
2
|
+
|
|
3
|
+
## v1.0.0 - Initial Release (2025-10-27)
|
|
4
|
+
|
|
5
|
+
### The Golden Triangle is Complete
|
|
6
|
+
|
|
7
|
+
First stable release of the FAF TAF Action - automatic .taf file updates for permanent, git-tracked test quality records.
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
**Core Functionality:**
|
|
12
|
+
- Automatic .taf file updates from CI/CD pipelines
|
|
13
|
+
- Jest output parsing (173/173 tests validated)
|
|
14
|
+
- Git integration with auto-commit support
|
|
15
|
+
- Configurable test commands and commit messages
|
|
16
|
+
|
|
17
|
+
**Outputs:**
|
|
18
|
+
- Test result status (PASSED, FAILED, IMPROVED, DEGRADED)
|
|
19
|
+
- Test counts (total, passed, failed)
|
|
20
|
+
- Update confirmation
|
|
21
|
+
|
|
22
|
+
**Architecture:**
|
|
23
|
+
- MCP-portable core (374 lines of TypeScript)
|
|
24
|
+
- Zero external dependencies for TAF operations
|
|
25
|
+
- Championship-grade validation
|
|
26
|
+
- Strict TypeScript throughout
|
|
27
|
+
|
|
28
|
+
### Supported Test Frameworks
|
|
29
|
+
|
|
30
|
+
- Jest (all output formats)
|
|
31
|
+
|
|
32
|
+
Coming soon:
|
|
33
|
+
- Mocha
|
|
34
|
+
- Vitest
|
|
35
|
+
- Pytest
|
|
36
|
+
- Go test
|
|
37
|
+
|
|
38
|
+
### Installation
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
- uses: Wolfe-Jam/faf-taf-action@v1
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Prerequisites
|
|
45
|
+
|
|
46
|
+
1. Install FAF CLI: `npm install -g faf-cli` or `brew install faf-cli`
|
|
47
|
+
2. Initialize .taf: `faf taf init`
|
|
48
|
+
3. Commit .taf to git
|
|
49
|
+
|
|
50
|
+
### Quick Start
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
name: Tests
|
|
54
|
+
|
|
55
|
+
on: [push, pull_request]
|
|
56
|
+
|
|
57
|
+
jobs:
|
|
58
|
+
test:
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
- uses: Wolfe-Jam/faf-taf-action@v1
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Testing
|
|
66
|
+
|
|
67
|
+
**Unit Tests:**
|
|
68
|
+
- 7/7 tests passing
|
|
69
|
+
- Jest parser validation
|
|
70
|
+
- All output formats covered
|
|
71
|
+
|
|
72
|
+
**Integration Tests:**
|
|
73
|
+
- Validated with faf-cli (173 tests)
|
|
74
|
+
- Validated with claude-faf-mcp (15 tests)
|
|
75
|
+
- Format consistency verified
|
|
76
|
+
|
|
77
|
+
**WJTTC Certification:**
|
|
78
|
+
- 1 bug found during testing (format mismatch)
|
|
79
|
+
- Fixed immediately
|
|
80
|
+
- Championship standards maintained
|
|
81
|
+
|
|
82
|
+
### Philosophy
|
|
83
|
+
|
|
84
|
+
This release implements the Golden Triangle vision:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
.faf
|
|
88
|
+
(WHAT IT IS)
|
|
89
|
+
/ \
|
|
90
|
+
/ \
|
|
91
|
+
/ \
|
|
92
|
+
repo ←→ .taf
|
|
93
|
+
(IMPLEMENTATION) (PROOF IT WORKS)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Format Authority:**
|
|
97
|
+
You don't negotiate with a format. The format describes itself.
|
|
98
|
+
|
|
99
|
+
**Software Accountability:**
|
|
100
|
+
Every test run becomes permanent, git-tracked proof that your code works.
|
|
101
|
+
|
|
102
|
+
### Known Limitations
|
|
103
|
+
|
|
104
|
+
- Jest only (for now)
|
|
105
|
+
- No test trend analysis yet
|
|
106
|
+
- No failure pattern detection
|
|
107
|
+
- Simple result detection (no history comparison)
|
|
108
|
+
|
|
109
|
+
These are planned for v1.1.0+
|
|
110
|
+
|
|
111
|
+
### Breaking Changes
|
|
112
|
+
|
|
113
|
+
None (initial release)
|
|
114
|
+
|
|
115
|
+
### Migration Guide
|
|
116
|
+
|
|
117
|
+
Not applicable (initial release)
|
|
118
|
+
|
|
119
|
+
### Documentation
|
|
120
|
+
|
|
121
|
+
- [README.md](../README.md) - Quick start guide
|
|
122
|
+
- [USER-GUIDE.md](USER-GUIDE.md) - Comprehensive documentation
|
|
123
|
+
- [CLAUDE.md](../CLAUDE.md) - Project DNA
|
|
124
|
+
|
|
125
|
+
### Links
|
|
126
|
+
|
|
127
|
+
- Repository: https://github.com/Wolfe-Jam/faf-taf-action
|
|
128
|
+
- Issues: https://github.com/Wolfe-Jam/faf-taf-action/issues
|
|
129
|
+
- Discussions: https://github.com/Wolfe-Jam/faf/discussions
|
|
130
|
+
- FAF Website: https://faf.one
|
|
131
|
+
|
|
132
|
+
### Credits
|
|
133
|
+
|
|
134
|
+
Built methodically with championship standards by the FAF team.
|
|
135
|
+
|
|
136
|
+
"We break things so others never know they were broken." - WJTTC Philosophy
|
|
137
|
+
|
|
138
|
+
### License
|
|
139
|
+
|
|
140
|
+
MIT - Free forever
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Roadmap
|
|
145
|
+
|
|
146
|
+
### v1.1.0 (Planned)
|
|
147
|
+
|
|
148
|
+
**Additional Test Frameworks:**
|
|
149
|
+
- Mocha support
|
|
150
|
+
- Vitest support
|
|
151
|
+
- Pytest support
|
|
152
|
+
|
|
153
|
+
**Enhanced Analysis:**
|
|
154
|
+
- Test trend detection
|
|
155
|
+
- Failure pattern recognition
|
|
156
|
+
- Flaky test identification
|
|
157
|
+
|
|
158
|
+
**Improved Outputs:**
|
|
159
|
+
- Pass rate trends
|
|
160
|
+
- Duration tracking
|
|
161
|
+
- Historical comparison
|
|
162
|
+
|
|
163
|
+
### v1.2.0 (Planned)
|
|
164
|
+
|
|
165
|
+
**Advanced Features:**
|
|
166
|
+
- Custom result detection rules
|
|
167
|
+
- .faf integration scoring
|
|
168
|
+
- Automated issue creation on degradation
|
|
169
|
+
- Slack/Discord notifications
|
|
170
|
+
|
|
171
|
+
**Performance:**
|
|
172
|
+
- Faster parsing
|
|
173
|
+
- Incremental updates
|
|
174
|
+
- Caching support
|
|
175
|
+
|
|
176
|
+
### v2.0.0 (Future)
|
|
177
|
+
|
|
178
|
+
**Framework Agnostic:**
|
|
179
|
+
- Generic test output parser
|
|
180
|
+
- Custom format support
|
|
181
|
+
- Multi-framework projects
|
|
182
|
+
|
|
183
|
+
**Enterprise Features:**
|
|
184
|
+
- Team dashboards
|
|
185
|
+
- Quality gates
|
|
186
|
+
- Compliance reporting
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Support
|
|
191
|
+
|
|
192
|
+
Report bugs, request features, or ask questions:
|
|
193
|
+
|
|
194
|
+
- GitHub Issues: https://github.com/Wolfe-Jam/faf-taf-action/issues
|
|
195
|
+
- GitHub Discussions: https://github.com/Wolfe-Jam/faf/discussions
|
|
196
|
+
- Email: team@faf.one
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
**Championship-grade engineering. F1-inspired performance. Built with care.**
|
|
@@ -0,0 +1,301 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
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/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "faf-taf-git",
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"description": "Platform-agnostic TAF (Testing Activity Feed) updater - works in ANY CI/CD",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"faf-taf-git": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"package": "ncc build src/index.ts -o dist --source-map --license licenses.txt"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/Wolfe-Jam/faf-taf-git.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"testing",
|
|
20
|
+
"taf",
|
|
21
|
+
"ci-cd",
|
|
22
|
+
"github-actions",
|
|
23
|
+
"gitlab-ci",
|
|
24
|
+
"bitbucket-pipelines",
|
|
25
|
+
"test-automation",
|
|
26
|
+
"jest",
|
|
27
|
+
"faf",
|
|
28
|
+
"git",
|
|
29
|
+
"platform-agnostic"
|
|
30
|
+
],
|
|
31
|
+
"author": "wolfejam",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@actions/core": "^1.10.1",
|
|
35
|
+
"@actions/exec": "^1.1.1",
|
|
36
|
+
"@actions/github": "^6.0.0",
|
|
37
|
+
"yaml": "^2.3.4"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/jest": "^29.5.11",
|
|
41
|
+
"@types/node": "^20.10.6",
|
|
42
|
+
"@vercel/ncc": "^0.38.1",
|
|
43
|
+
"jest": "^29.7.0",
|
|
44
|
+
"ts-jest": "^29.1.1",
|
|
45
|
+
"typescript": "^5.3.3"
|
|
46
|
+
}
|
|
47
|
+
}
|