threadlines 0.2.9 → 0.2.11
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/dist/git/github.js +43 -109
- package/package.json +2 -1
package/dist/git/github.js
CHANGED
|
@@ -12,47 +12,14 @@
|
|
|
12
12
|
* - commitAuthor: { name: string; email: string }
|
|
13
13
|
* - prTitle?: string
|
|
14
14
|
*/
|
|
15
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
-
}
|
|
21
|
-
Object.defineProperty(o, k2, desc);
|
|
22
|
-
}) : (function(o, m, k, k2) {
|
|
23
|
-
if (k2 === undefined) k2 = k;
|
|
24
|
-
o[k2] = m[k];
|
|
25
|
-
}));
|
|
26
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
-
}) : function(o, v) {
|
|
29
|
-
o["default"] = v;
|
|
30
|
-
});
|
|
31
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
-
var ownKeys = function(o) {
|
|
33
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
-
var ar = [];
|
|
35
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
-
return ar;
|
|
37
|
-
};
|
|
38
|
-
return ownKeys(o);
|
|
39
|
-
};
|
|
40
|
-
return function (mod) {
|
|
41
|
-
if (mod && mod.__esModule) return mod;
|
|
42
|
-
var result = {};
|
|
43
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
-
__setModuleDefault(result, mod);
|
|
45
|
-
return result;
|
|
46
|
-
};
|
|
47
|
-
})();
|
|
48
15
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
49
16
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
50
17
|
};
|
|
51
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
19
|
exports.getGitHubContext = getGitHubContext;
|
|
53
20
|
const simple_git_1 = __importDefault(require("simple-git"));
|
|
54
|
-
const fs = __importStar(require("fs"));
|
|
55
21
|
const diff_1 = require("./diff");
|
|
22
|
+
const logger_1 = require("../utils/logger");
|
|
56
23
|
/**
|
|
57
24
|
* Gets all GitHub context
|
|
58
25
|
*/
|
|
@@ -69,8 +36,13 @@ async function getGitHubContext(repoRoot) {
|
|
|
69
36
|
const branchName = await getBranchName();
|
|
70
37
|
const context = detectContext();
|
|
71
38
|
const commitSha = getCommitSha(context);
|
|
72
|
-
//
|
|
73
|
-
|
|
39
|
+
// Validate commit SHA is available (should always be set in GitHub Actions)
|
|
40
|
+
if (!commitSha) {
|
|
41
|
+
throw new Error('GitHub Actions: GITHUB_SHA environment variable is not set. ' +
|
|
42
|
+
'This should be automatically provided by GitHub Actions.');
|
|
43
|
+
}
|
|
44
|
+
// Get commit author using git commands (same approach as Bitbucket/Local)
|
|
45
|
+
const commitAuthor = await (0, diff_1.getCommitAuthor)(repoRoot, commitSha);
|
|
74
46
|
// Get commit message if we have a SHA
|
|
75
47
|
let commitMessage;
|
|
76
48
|
if (commitSha) {
|
|
@@ -81,6 +53,11 @@ async function getGitHubContext(repoRoot) {
|
|
|
81
53
|
}
|
|
82
54
|
// Get PR title if in PR context
|
|
83
55
|
const prTitle = getPRTitle(context);
|
|
56
|
+
// Validate commit author was found
|
|
57
|
+
if (!commitAuthor) {
|
|
58
|
+
throw new Error(`GitHub Actions: Failed to get commit author from git log for commit ${commitSha || 'HEAD'}. ` +
|
|
59
|
+
'This should be automatically available in the git repository.');
|
|
60
|
+
}
|
|
84
61
|
return {
|
|
85
62
|
diff,
|
|
86
63
|
repoName,
|
|
@@ -96,29 +73,37 @@ async function getGitHubContext(repoRoot) {
|
|
|
96
73
|
* Gets diff for GitHub Actions CI environment
|
|
97
74
|
*
|
|
98
75
|
* Strategy:
|
|
99
|
-
* - PR context:
|
|
76
|
+
* - PR context: Fetch base branch on-demand, compare base vs HEAD (full PR diff)
|
|
100
77
|
* - Any push (main or feature branch): Compare last commit only (HEAD~1...HEAD)
|
|
101
78
|
*
|
|
102
|
-
* Note:
|
|
103
|
-
*
|
|
104
|
-
* for pull_request events, even with the default shallow clone (fetch-depth: 1).
|
|
105
|
-
* The refs `origin/${GITHUB_BASE_REF}` and `origin/${GITHUB_HEAD_REF}` are available
|
|
106
|
-
* immediately after checkout.
|
|
79
|
+
* Note: GitHub Actions does shallow clones by default (fetch-depth: 1), so we fetch
|
|
80
|
+
* the base branch on-demand. HEAD points to the merge commit which contains all PR changes.
|
|
107
81
|
*/
|
|
108
82
|
async function getDiff(repoRoot) {
|
|
109
83
|
const git = (0, simple_git_1.default)(repoRoot);
|
|
110
84
|
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
111
85
|
const baseRef = process.env.GITHUB_BASE_REF;
|
|
112
|
-
|
|
113
|
-
// PR Context: Compare source vs target branch
|
|
114
|
-
// No fetch needed - GitHub Actions provides both refs automatically
|
|
86
|
+
// PR Context: Only pull_request events have GITHUB_BASE_REF set
|
|
115
87
|
if (eventName === 'pull_request') {
|
|
116
|
-
if (!baseRef
|
|
117
|
-
throw new Error('GitHub PR context detected but GITHUB_BASE_REF
|
|
88
|
+
if (!baseRef) {
|
|
89
|
+
throw new Error('GitHub PR context detected but GITHUB_BASE_REF is missing. ' +
|
|
118
90
|
'This should be automatically provided by GitHub Actions.');
|
|
119
91
|
}
|
|
120
|
-
|
|
121
|
-
|
|
92
|
+
// Fetch base branch on-demand (works with shallow clones)
|
|
93
|
+
logger_1.logger.debug(`Fetching base branch: origin/${baseRef}`);
|
|
94
|
+
try {
|
|
95
|
+
await git.fetch(['origin', `${baseRef}:refs/remotes/origin/${baseRef}`, '--depth=1']);
|
|
96
|
+
}
|
|
97
|
+
catch (fetchError) {
|
|
98
|
+
throw new Error(`Failed to fetch base branch origin/${baseRef}. ` +
|
|
99
|
+
`This is required for PR diff comparison. Error: ${fetchError instanceof Error ? fetchError.message : 'Unknown error'}`);
|
|
100
|
+
}
|
|
101
|
+
logger_1.logger.debug(`PR context, using origin/${baseRef}..HEAD (two dots for direct comparison)`);
|
|
102
|
+
// Use two dots (..) instead of three dots (...) for direct comparison
|
|
103
|
+
// Three dots requires finding merge base which can fail with shallow clones
|
|
104
|
+
// Two dots shows all changes in HEAD that aren't in origin/${baseRef}
|
|
105
|
+
const diff = await git.diff([`origin/${baseRef}..HEAD`, '-U200']);
|
|
106
|
+
const diffSummary = await git.diffSummary([`origin/${baseRef}..HEAD`]);
|
|
122
107
|
const changedFiles = diffSummary.files.map(f => f.file);
|
|
123
108
|
return {
|
|
124
109
|
diff: diff || '',
|
|
@@ -126,13 +111,15 @@ async function getDiff(repoRoot) {
|
|
|
126
111
|
};
|
|
127
112
|
}
|
|
128
113
|
// Any push (main or feature branch): Review last commit only
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
114
|
+
// Use git show HEAD - works with shallow clones and shows the commit diff
|
|
115
|
+
const diff = await git.show(['HEAD', '--format=', '--no-color', '-U200']);
|
|
116
|
+
// Extract changed files from git show
|
|
117
|
+
const showNameOnly = await git.show(['HEAD', '--name-only', '--format=', '--pretty=format:']);
|
|
118
|
+
const changedFiles = showNameOnly
|
|
119
|
+
.split('\n')
|
|
120
|
+
.filter(line => line.trim().length > 0)
|
|
121
|
+
.map(line => line.trim());
|
|
122
|
+
return { diff: diff || '', changedFiles };
|
|
136
123
|
}
|
|
137
124
|
/**
|
|
138
125
|
* Gets repository name for GitHub Actions
|
|
@@ -201,59 +188,6 @@ function getCommitSha(context) {
|
|
|
201
188
|
}
|
|
202
189
|
return undefined;
|
|
203
190
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Gets commit author for GitHub Actions
|
|
206
|
-
* Reads from GITHUB_EVENT_PATH JSON file (most reliable)
|
|
207
|
-
* Note: commitSha parameter not used - GitHub provides author info in event JSON
|
|
208
|
-
*/
|
|
209
|
-
async function getCommitAuthor() {
|
|
210
|
-
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
211
|
-
if (!eventPath) {
|
|
212
|
-
throw new Error('GitHub Actions: GITHUB_EVENT_PATH environment variable is not set. ' +
|
|
213
|
-
'This should be automatically provided by GitHub Actions.');
|
|
214
|
-
}
|
|
215
|
-
if (!fs.existsSync(eventPath)) {
|
|
216
|
-
throw new Error(`GitHub Actions: GITHUB_EVENT_PATH file does not exist: ${eventPath}. ` +
|
|
217
|
-
'This should be automatically provided by GitHub Actions.');
|
|
218
|
-
}
|
|
219
|
-
try {
|
|
220
|
-
const eventData = JSON.parse(fs.readFileSync(eventPath, 'utf-8'));
|
|
221
|
-
// For push events, use head_commit.author
|
|
222
|
-
if (eventData.head_commit?.author) {
|
|
223
|
-
return {
|
|
224
|
-
name: eventData.head_commit.author.name,
|
|
225
|
-
email: eventData.head_commit.author.email
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
// For PR events, use commits[0].author (first commit in the PR)
|
|
229
|
-
if (eventData.commits && eventData.commits.length > 0 && eventData.commits[0].author) {
|
|
230
|
-
return {
|
|
231
|
-
name: eventData.commits[0].author.name,
|
|
232
|
-
email: eventData.commits[0].author.email
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
// Fallback to pull_request.head.commit.author for PR events
|
|
236
|
-
if (eventData.pull_request?.head?.commit?.author) {
|
|
237
|
-
return {
|
|
238
|
-
name: eventData.pull_request.head.commit.author.name,
|
|
239
|
-
email: eventData.pull_request.head.commit.author.email
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
// If we get here, the event JSON doesn't contain author info
|
|
243
|
-
throw new Error(`GitHub Actions: GITHUB_EVENT_PATH JSON does not contain commit author information. ` +
|
|
244
|
-
`Event type: ${eventData.action || 'unknown'}. ` +
|
|
245
|
-
`This should be automatically provided by GitHub Actions.`);
|
|
246
|
-
}
|
|
247
|
-
catch (error) {
|
|
248
|
-
// If JSON parsing fails, fail loudly
|
|
249
|
-
if (error instanceof Error && error.message.includes('GitHub Actions:')) {
|
|
250
|
-
throw error; // Re-throw our own errors
|
|
251
|
-
}
|
|
252
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
253
|
-
throw new Error(`GitHub Actions: Failed to read or parse GITHUB_EVENT_PATH JSON: ${errorMessage}. ` +
|
|
254
|
-
'This should be automatically provided by GitHub Actions.');
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
191
|
/**
|
|
258
192
|
* Gets PR title for GitHub Actions
|
|
259
193
|
* Note: GitHub Actions doesn't provide PR title as an env var by default.
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "threadlines",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "Threadlines CLI - AI-powered linter based on your natural language documentation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
+
"threadlines": "./bin/threadline",
|
|
7
8
|
"threadline": "./bin/threadline"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|