threadlines 0.2.4 → 0.2.6
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/commands/check.js +97 -138
- package/dist/git/bitbucket.js +259 -0
- package/dist/git/repo.js +1 -1
- package/dist/types/git.js +5 -0
- package/dist/utils/context.js +42 -0
- package/dist/utils/environment.js +4 -1
- package/package.json +1 -1
- package/dist/git/context.js +0 -55
- package/dist/git/github-diff.js +0 -116
- package/dist/git/gitlab-diff.js +0 -86
- package/dist/git/local-diff.js +0 -53
- package/dist/git/vercel-diff.js +0 -42
- package/dist/utils/git-diff-executor.js +0 -65
- package/dist/utils/metadata.js +0 -290
package/dist/utils/metadata.js
DELETED
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Metadata Collection
|
|
4
|
-
*
|
|
5
|
-
* Collects environment-specific metadata for review context:
|
|
6
|
-
* - Commit SHA (from env vars or git)
|
|
7
|
-
* - Commit message (from git)
|
|
8
|
-
* - PR/MR title (from env vars or API)
|
|
9
|
-
*
|
|
10
|
-
* Metadata collection is environment-specific because each CI platform
|
|
11
|
-
* provides different environment variables.
|
|
12
|
-
*/
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
-
var ownKeys = function(o) {
|
|
31
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
-
var ar = [];
|
|
33
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
-
return ar;
|
|
35
|
-
};
|
|
36
|
-
return ownKeys(o);
|
|
37
|
-
};
|
|
38
|
-
return function (mod) {
|
|
39
|
-
if (mod && mod.__esModule) return mod;
|
|
40
|
-
var result = {};
|
|
41
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
-
__setModuleDefault(result, mod);
|
|
43
|
-
return result;
|
|
44
|
-
};
|
|
45
|
-
})();
|
|
46
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
47
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
48
|
-
};
|
|
49
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.collectMetadata = collectMetadata;
|
|
51
|
-
const diff_1 = require("../git/diff");
|
|
52
|
-
const fs = __importStar(require("fs"));
|
|
53
|
-
const simple_git_1 = __importDefault(require("simple-git"));
|
|
54
|
-
/**
|
|
55
|
-
* Collects metadata for the given context and environment.
|
|
56
|
-
*
|
|
57
|
-
* This function knows how to extract metadata from each environment's
|
|
58
|
-
* specific environment variables and git commands.
|
|
59
|
-
*/
|
|
60
|
-
async function collectMetadata(context, environment, repoRoot) {
|
|
61
|
-
const metadata = {};
|
|
62
|
-
// Collect commit SHA (environment-specific)
|
|
63
|
-
metadata.commitSha = getCommitSha(context, environment);
|
|
64
|
-
// Collect commit message and author (environment-specific)
|
|
65
|
-
if (metadata.commitSha) {
|
|
66
|
-
const message = await (0, diff_1.getCommitMessage)(repoRoot, metadata.commitSha);
|
|
67
|
-
if (message) {
|
|
68
|
-
metadata.commitMessage = message;
|
|
69
|
-
}
|
|
70
|
-
// Get commit author - environment-specific approach (fails loudly if unavailable)
|
|
71
|
-
const author = await getCommitAuthorForEnvironment(environment, repoRoot, metadata.commitSha);
|
|
72
|
-
metadata.commitAuthorName = author.name;
|
|
73
|
-
metadata.commitAuthorEmail = author.email;
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
// For local environment without explicit commit SHA:
|
|
77
|
-
// Use git config (who will commit staged/unstaged changes)
|
|
78
|
-
// No fallbacks - if git config fails, the error propagates and fails the check
|
|
79
|
-
const author = await getGitConfigUser(repoRoot);
|
|
80
|
-
metadata.commitAuthorName = author.name;
|
|
81
|
-
metadata.commitAuthorEmail = author.email;
|
|
82
|
-
}
|
|
83
|
-
// Collect PR/MR title (environment-specific)
|
|
84
|
-
metadata.prTitle = getPRTitle(context, environment);
|
|
85
|
-
return metadata;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Extracts commit SHA from context and environment.
|
|
89
|
-
*/
|
|
90
|
-
function getCommitSha(context, environment) {
|
|
91
|
-
// If context already has commit SHA, use it
|
|
92
|
-
if (context.type === 'commit') {
|
|
93
|
-
return context.commitSha;
|
|
94
|
-
}
|
|
95
|
-
// For branch contexts, try to get commit SHA from environment variables
|
|
96
|
-
if (context.type === 'branch') {
|
|
97
|
-
switch (environment) {
|
|
98
|
-
case 'github':
|
|
99
|
-
return process.env.GITHUB_SHA;
|
|
100
|
-
case 'gitlab':
|
|
101
|
-
return process.env.CI_COMMIT_SHA;
|
|
102
|
-
case 'vercel':
|
|
103
|
-
return process.env.VERCEL_GIT_COMMIT_SHA;
|
|
104
|
-
default:
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// For PR/MR contexts, commit SHA might be available in env vars
|
|
109
|
-
if (context.type === 'pr' || context.type === 'mr') {
|
|
110
|
-
switch (environment) {
|
|
111
|
-
case 'github':
|
|
112
|
-
// For PRs, GITHUB_SHA is a merge commit, might want GITHUB_HEAD_SHA instead
|
|
113
|
-
return process.env.GITHUB_HEAD_SHA || process.env.GITHUB_SHA;
|
|
114
|
-
case 'gitlab':
|
|
115
|
-
return process.env.CI_COMMIT_SHA;
|
|
116
|
-
default:
|
|
117
|
-
return undefined;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Gets commit author information using environment-specific methods.
|
|
124
|
-
*
|
|
125
|
-
* Each environment has a single, isolated strategy:
|
|
126
|
-
* - GitHub: Reads from GITHUB_EVENT_PATH JSON file (fails loudly if unavailable)
|
|
127
|
-
* - GitLab: Uses CI_COMMIT_AUTHOR environment variable (fails loudly if unavailable)
|
|
128
|
-
* - Vercel: Uses VERCEL_GIT_COMMIT_AUTHOR_NAME + git log (fails loudly if unavailable)
|
|
129
|
-
* - Local: Uses git config (handled separately in collectMetadata, fails loudly if unavailable)
|
|
130
|
-
*
|
|
131
|
-
* No fallbacks - each environment is completely isolated.
|
|
132
|
-
*/
|
|
133
|
-
async function getCommitAuthorForEnvironment(environment, repoRoot, commitSha) {
|
|
134
|
-
if (environment === 'github') {
|
|
135
|
-
// GitHub: Read from GITHUB_EVENT_PATH JSON file
|
|
136
|
-
// This is more reliable than git commands, especially in shallow clones
|
|
137
|
-
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
138
|
-
if (!eventPath) {
|
|
139
|
-
throw new Error('GitHub Actions: GITHUB_EVENT_PATH environment variable is not set. ' +
|
|
140
|
-
'This should be automatically provided by GitHub Actions.');
|
|
141
|
-
}
|
|
142
|
-
if (!fs.existsSync(eventPath)) {
|
|
143
|
-
throw new Error(`GitHub Actions: GITHUB_EVENT_PATH file does not exist: ${eventPath}. ` +
|
|
144
|
-
'This should be automatically provided by GitHub Actions.');
|
|
145
|
-
}
|
|
146
|
-
try {
|
|
147
|
-
const eventData = JSON.parse(fs.readFileSync(eventPath, 'utf-8'));
|
|
148
|
-
// For push events, use head_commit.author
|
|
149
|
-
if (eventData.head_commit?.author) {
|
|
150
|
-
return {
|
|
151
|
-
name: eventData.head_commit.author.name,
|
|
152
|
-
email: eventData.head_commit.author.email
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
// For PR events, use commits[0].author (first commit in the PR)
|
|
156
|
-
if (eventData.commits && eventData.commits.length > 0 && eventData.commits[0].author) {
|
|
157
|
-
return {
|
|
158
|
-
name: eventData.commits[0].author.name,
|
|
159
|
-
email: eventData.commits[0].author.email
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
// Fallback to pull_request.head.commit.author for PR events
|
|
163
|
-
if (eventData.pull_request?.head?.commit?.author) {
|
|
164
|
-
return {
|
|
165
|
-
name: eventData.pull_request.head.commit.author.name,
|
|
166
|
-
email: eventData.pull_request.head.commit.author.email
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
// If we get here, the event JSON doesn't contain author info
|
|
170
|
-
throw new Error(`GitHub Actions: GITHUB_EVENT_PATH JSON does not contain commit author information. ` +
|
|
171
|
-
`Event type: ${eventData.action || 'unknown'}. ` +
|
|
172
|
-
`This should be automatically provided by GitHub Actions.`);
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
// If JSON parsing fails, fail loudly
|
|
176
|
-
if (error instanceof Error && error.message.includes('GitHub Actions:')) {
|
|
177
|
-
throw error; // Re-throw our own errors
|
|
178
|
-
}
|
|
179
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
180
|
-
throw new Error(`GitHub Actions: Failed to read or parse GITHUB_EVENT_PATH JSON: ${errorMessage}. ` +
|
|
181
|
-
'This should be automatically provided by GitHub Actions.');
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if (environment === 'gitlab') {
|
|
185
|
-
// GitLab: Use CI_COMMIT_AUTHOR environment variable
|
|
186
|
-
// Format: "name <email>" (e.g., "ngrootscholten <niels.grootscholten@gmail.com>")
|
|
187
|
-
// This is more reliable than git commands, especially in shallow clones
|
|
188
|
-
const commitAuthor = process.env.CI_COMMIT_AUTHOR;
|
|
189
|
-
if (!commitAuthor) {
|
|
190
|
-
throw new Error('GitLab CI: CI_COMMIT_AUTHOR environment variable is not set. ' +
|
|
191
|
-
'This should be automatically provided by GitLab CI.');
|
|
192
|
-
}
|
|
193
|
-
// Parse "name <email>" format
|
|
194
|
-
const match = commitAuthor.match(/^(.+?)\s*<(.+?)>$/);
|
|
195
|
-
if (!match) {
|
|
196
|
-
throw new Error(`GitLab CI: CI_COMMIT_AUTHOR format is invalid. ` +
|
|
197
|
-
`Expected format: "name <email>", got: "${commitAuthor}". ` +
|
|
198
|
-
`This should be automatically provided by GitLab CI in the correct format.`);
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
name: match[1].trim(),
|
|
202
|
-
email: match[2].trim()
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
if (environment === 'vercel') {
|
|
206
|
-
// Vercel: Use VERCEL_GIT_COMMIT_AUTHOR_NAME for name, git log for email
|
|
207
|
-
// Vercel provides author name but not email in environment variables
|
|
208
|
-
// git log works reliably in Vercel's build environment
|
|
209
|
-
const authorName = process.env.VERCEL_GIT_COMMIT_AUTHOR_NAME;
|
|
210
|
-
if (!authorName) {
|
|
211
|
-
throw new Error('Vercel: VERCEL_GIT_COMMIT_AUTHOR_NAME environment variable is not set. ' +
|
|
212
|
-
'This should be automatically provided by Vercel.');
|
|
213
|
-
}
|
|
214
|
-
// Get email from git log - fail loudly if this doesn't work
|
|
215
|
-
const gitAuthor = await (0, diff_1.getCommitAuthor)(repoRoot, commitSha);
|
|
216
|
-
if (!gitAuthor || !gitAuthor.email) {
|
|
217
|
-
throw new Error(`Vercel: Failed to get commit author email from git log for commit ${commitSha}. ` +
|
|
218
|
-
`This should be available in Vercel's build environment.`);
|
|
219
|
-
}
|
|
220
|
-
return {
|
|
221
|
-
name: authorName.trim(),
|
|
222
|
-
email: gitAuthor.email.trim()
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
// Local environment should not reach here - it's handled separately in collectMetadata
|
|
226
|
-
// when commitSha is undefined. If we get here with 'local', it means commitSha was set
|
|
227
|
-
// (e.g., --commit flag), so we can use git log.
|
|
228
|
-
if (environment === 'local') {
|
|
229
|
-
const gitAuthor = await (0, diff_1.getCommitAuthor)(repoRoot, commitSha);
|
|
230
|
-
if (!gitAuthor || !gitAuthor.email) {
|
|
231
|
-
throw new Error(`Local: Failed to get commit author from git log for commit ${commitSha}. ` +
|
|
232
|
-
'This should be available in your local git repository.');
|
|
233
|
-
}
|
|
234
|
-
return {
|
|
235
|
-
name: gitAuthor.name,
|
|
236
|
-
email: gitAuthor.email
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
// Unknown environment - this should never happen due to TypeScript exhaustiveness
|
|
240
|
-
const _exhaustive = environment;
|
|
241
|
-
throw new Error(`Unknown environment: ${_exhaustive}`);
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Gets git user info from git config (for local uncommitted changes).
|
|
245
|
-
* This represents who is currently working on the changes and will commit them.
|
|
246
|
-
*
|
|
247
|
-
* No fallbacks - if git config is not set or fails, throws an error.
|
|
248
|
-
*/
|
|
249
|
-
async function getGitConfigUser(repoRoot) {
|
|
250
|
-
const git = (0, simple_git_1.default)(repoRoot);
|
|
251
|
-
try {
|
|
252
|
-
const name = await git.getConfig('user.name');
|
|
253
|
-
const email = await git.getConfig('user.email');
|
|
254
|
-
if (!name.value || !email.value) {
|
|
255
|
-
throw new Error('Git config user.name or user.email is not set. ' +
|
|
256
|
-
'Run: git config user.name "Your Name" && git config user.email "your.email@example.com"');
|
|
257
|
-
}
|
|
258
|
-
return {
|
|
259
|
-
name: name.value.trim(),
|
|
260
|
-
email: email.value.trim()
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
catch (error) {
|
|
264
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
265
|
-
throw new Error(`Failed to get git config user: ${errorMessage}`);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Extracts PR/MR title from context and environment.
|
|
270
|
-
*
|
|
271
|
-
* Note: GitHub Actions doesn't provide PR title as an env var by default.
|
|
272
|
-
* It would need to be passed from the workflow YAML or fetched via API.
|
|
273
|
-
*/
|
|
274
|
-
function getPRTitle(context, environment) {
|
|
275
|
-
// Only PR/MR contexts have titles
|
|
276
|
-
if (context.type !== 'pr' && context.type !== 'mr') {
|
|
277
|
-
return undefined;
|
|
278
|
-
}
|
|
279
|
-
// GitLab CI provides MR title as env var
|
|
280
|
-
if (context.type === 'mr' && environment === 'gitlab') {
|
|
281
|
-
return context.prTitle;
|
|
282
|
-
}
|
|
283
|
-
// GitHub Actions doesn't provide PR title as env var
|
|
284
|
-
// Would need to be passed from workflow: PR_TITLE: ${{ github.event.pull_request.title }}
|
|
285
|
-
// or fetched via GitHub API
|
|
286
|
-
if (context.type === 'pr' && environment === 'github') {
|
|
287
|
-
return process.env.PR_TITLE; // Only if passed from workflow
|
|
288
|
-
}
|
|
289
|
-
return undefined;
|
|
290
|
-
}
|