threadlines 0.2.3 → 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.
@@ -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
- }