threadlines 0.1.19 → 0.1.21
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 +21 -5
- package/dist/git/diff.js +2 -60
- package/dist/git/github-diff.js +61 -0
- package/dist/git/gitlab-diff.js +63 -0
- package/dist/git/local-diff.js +53 -0
- package/dist/git/vercel-diff.js +42 -0
- package/dist/utils/context.js +15 -12
- package/dist/utils/environment.js +1 -3
- package/dist/utils/git-diff-executor.js +48 -7
- package/package.json +1 -1
package/dist/commands/check.js
CHANGED
|
@@ -126,11 +126,27 @@ async function checkCommand(options) {
|
|
|
126
126
|
gitDiff = await (0, git_diff_executor_1.getDiffForContext)(context, repoRoot, environment);
|
|
127
127
|
}
|
|
128
128
|
else {
|
|
129
|
-
// Auto-detect
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
// Auto-detect: Use environment-specific implementation
|
|
130
|
+
const envNames = {
|
|
131
|
+
vercel: 'Vercel',
|
|
132
|
+
github: 'GitHub',
|
|
133
|
+
gitlab: 'GitLab',
|
|
134
|
+
local: 'Local'
|
|
135
|
+
};
|
|
136
|
+
console.log(chalk_1.default.gray(`📝 Collecting git changes for ${envNames[environment]}...`));
|
|
137
|
+
gitDiff = await (0, git_diff_executor_1.getDiffForEnvironment)(environment, repoRoot);
|
|
138
|
+
// Create context for metadata collection
|
|
139
|
+
if (environment === 'vercel') {
|
|
140
|
+
context = { type: 'commit', commitSha: process.env.VERCEL_GIT_COMMIT_SHA };
|
|
141
|
+
}
|
|
142
|
+
else if (environment === 'github' || environment === 'gitlab') {
|
|
143
|
+
// GitHub/GitLab: Detect context for metadata (but diff already obtained)
|
|
144
|
+
context = (0, context_1.detectContext)(environment);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// Local: Use local context
|
|
148
|
+
context = { type: 'local' };
|
|
149
|
+
}
|
|
134
150
|
}
|
|
135
151
|
// 3. Collect metadata (commit SHA, commit message, PR title)
|
|
136
152
|
const metadata = await (0, metadata_1.collectMetadata)(context, environment, repoRoot);
|
package/dist/git/diff.js
CHANGED
|
@@ -3,49 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getGitDiff = getGitDiff;
|
|
7
6
|
exports.getBranchDiff = getBranchDiff;
|
|
8
7
|
exports.getCommitMessage = getCommitMessage;
|
|
9
8
|
exports.getCommitDiff = getCommitDiff;
|
|
10
9
|
exports.getPRMRDiff = getPRMRDiff;
|
|
11
10
|
const simple_git_1 = __importDefault(require("simple-git"));
|
|
12
|
-
/**
|
|
13
|
-
* Get diff for staged/unstaged changes (current behavior)
|
|
14
|
-
*/
|
|
15
|
-
async function getGitDiff(repoRoot) {
|
|
16
|
-
const git = (0, simple_git_1.default)(repoRoot);
|
|
17
|
-
// Check if we're in a git repo
|
|
18
|
-
const isRepo = await git.checkIsRepo();
|
|
19
|
-
if (!isRepo) {
|
|
20
|
-
throw new Error('Not a git repository. Threadline requires a git repository.');
|
|
21
|
-
}
|
|
22
|
-
// Get diff (staged changes, or unstaged if no staged)
|
|
23
|
-
const status = await git.status();
|
|
24
|
-
let diff;
|
|
25
|
-
if (status.staged.length > 0) {
|
|
26
|
-
// Use staged changes
|
|
27
|
-
diff = await git.diff(['--cached', '-U200']);
|
|
28
|
-
}
|
|
29
|
-
else if (status.files.length > 0) {
|
|
30
|
-
// Use unstaged changes
|
|
31
|
-
diff = await git.diff(['-U200']);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
// No changes
|
|
35
|
-
return {
|
|
36
|
-
diff: '',
|
|
37
|
-
changedFiles: []
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
// Get list of changed files
|
|
41
|
-
const changedFiles = status.files
|
|
42
|
-
.filter(f => f.working_dir !== ' ' || f.index !== ' ')
|
|
43
|
-
.map(f => f.path);
|
|
44
|
-
return {
|
|
45
|
-
diff: diff || '',
|
|
46
|
-
changedFiles
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
11
|
/**
|
|
50
12
|
* Get diff for a specific branch (all commits vs base branch)
|
|
51
13
|
* Uses git merge-base to find common ancestor, then diffs from there
|
|
@@ -96,29 +58,9 @@ async function getBranchDiff(repoRoot, branchName, baseBranch) {
|
|
|
96
58
|
// Helper function to detect base branch
|
|
97
59
|
// Returns the branch name to use in git commands (may be local or remote)
|
|
98
60
|
// In CI environments, prioritizes remote refs since local branches often don't exist
|
|
61
|
+
// Note: Vercel is excluded here because it uses commit context, not branch context
|
|
99
62
|
async function detectBaseBranch(git, branchName) {
|
|
100
|
-
const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.
|
|
101
|
-
const isVercel = !!process.env.VERCEL;
|
|
102
|
-
// Vercel-specific strategy: Try multiple approaches with clear logging
|
|
103
|
-
// Once we know what works, we'll remove the approaches that don't work
|
|
104
|
-
if (isVercel) {
|
|
105
|
-
console.log(`[DEBUG] Vercel environment detected - trying Vercel-specific base branch detection for '${branchName}'`);
|
|
106
|
-
// Strategy 3: Try using local main (maybe Vercel already has it checked out)
|
|
107
|
-
try {
|
|
108
|
-
console.log(`[DEBUG] Vercel: Checking if local 'main' branch exists...`);
|
|
109
|
-
await git.revparse(['main']);
|
|
110
|
-
console.log(`[DEBUG] Vercel: Found local 'main' branch - using as base`);
|
|
111
|
-
return 'main';
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.log(`[DEBUG] Vercel: Local 'main' branch not found: ${error.message || 'does not exist'}`);
|
|
115
|
-
}
|
|
116
|
-
// All Vercel-specific strategies failed - fail loudly
|
|
117
|
-
throw new Error(`Vercel: Base branch 'main' is not available in the git repository. ` +
|
|
118
|
-
`Vercel CI does not have the base branch checked out or fetched. ` +
|
|
119
|
-
`Tried: local 'main' branch. ` +
|
|
120
|
-
`This is a Vercel CI limitation - the base branch needs to be available for comparison.`);
|
|
121
|
-
}
|
|
63
|
+
const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI);
|
|
122
64
|
// Strategy 1: Try upstream tracking branch (most reliable if set)
|
|
123
65
|
try {
|
|
124
66
|
const upstream = await git.revparse(['--abbrev-ref', '--symbolic-full-name', `${branchName}@{u}`]);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getGitHubDiff = getGitHubDiff;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
/**
|
|
9
|
+
* Get diff for GitHub Actions CI environment
|
|
10
|
+
*
|
|
11
|
+
* GitHub Actions provides environment variables that tell us exactly what to compare:
|
|
12
|
+
* - PR context: GITHUB_BASE_REF (target branch) and GITHUB_HEAD_REF (source branch)
|
|
13
|
+
* - Branch context: GITHUB_REF_NAME (current branch), compare against origin/main
|
|
14
|
+
*
|
|
15
|
+
* This is the ONLY implementation for GitHub - no fallbacks, no alternatives.
|
|
16
|
+
* If this doesn't work, we fail with a clear error.
|
|
17
|
+
*/
|
|
18
|
+
async function getGitHubDiff(repoRoot) {
|
|
19
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
20
|
+
// Check if we're in a git repo
|
|
21
|
+
const isRepo = await git.checkIsRepo();
|
|
22
|
+
if (!isRepo) {
|
|
23
|
+
throw new Error('Not a git repository. Threadline requires a git repository.');
|
|
24
|
+
}
|
|
25
|
+
// Determine context from GitHub environment variables
|
|
26
|
+
const eventName = process.env.GITHUB_EVENT_NAME;
|
|
27
|
+
const baseRef = process.env.GITHUB_BASE_REF;
|
|
28
|
+
const headRef = process.env.GITHUB_HEAD_REF;
|
|
29
|
+
const refName = process.env.GITHUB_REF_NAME;
|
|
30
|
+
// PR context: GitHub provides both base and head branches
|
|
31
|
+
if (eventName === 'pull_request') {
|
|
32
|
+
if (!baseRef || !headRef) {
|
|
33
|
+
throw new Error('GitHub PR context detected but GITHUB_BASE_REF or GITHUB_HEAD_REF is missing. ' +
|
|
34
|
+
'This should be automatically provided by GitHub Actions.');
|
|
35
|
+
}
|
|
36
|
+
// Use the branches GitHub provides directly - no detection needed
|
|
37
|
+
const diff = await git.diff([`origin/${baseRef}...origin/${headRef}`, '-U200']);
|
|
38
|
+
const diffSummary = await git.diffSummary([`origin/${baseRef}...origin/${headRef}`]);
|
|
39
|
+
const changedFiles = diffSummary.files.map(f => f.file);
|
|
40
|
+
return {
|
|
41
|
+
diff: diff || '',
|
|
42
|
+
changedFiles
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Branch context: GitHub provides branch name, compare against origin/main
|
|
46
|
+
if (refName) {
|
|
47
|
+
// For branch pushes, compare against origin/main (standard base branch)
|
|
48
|
+
// GitHub Actions with fetch-depth: 0 should have origin/main available
|
|
49
|
+
const diff = await git.diff([`origin/main...origin/${refName}`, '-U200']);
|
|
50
|
+
const diffSummary = await git.diffSummary([`origin/main...origin/${refName}`]);
|
|
51
|
+
const changedFiles = diffSummary.files.map(f => f.file);
|
|
52
|
+
return {
|
|
53
|
+
diff: diff || '',
|
|
54
|
+
changedFiles
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Neither PR nor branch context available
|
|
58
|
+
throw new Error('GitHub Actions environment detected but no valid context found. ' +
|
|
59
|
+
'Expected GITHUB_EVENT_NAME="pull_request" (with GITHUB_BASE_REF/GITHUB_HEAD_REF) ' +
|
|
60
|
+
'or GITHUB_REF_NAME for branch context.');
|
|
61
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getGitLabDiff = getGitLabDiff;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
/**
|
|
9
|
+
* Get diff for GitLab CI environment
|
|
10
|
+
*
|
|
11
|
+
* GitLab CI provides environment variables that tell us exactly what to compare:
|
|
12
|
+
* - MR context: CI_MERGE_REQUEST_TARGET_BRANCH_NAME (target branch) and CI_MERGE_REQUEST_SOURCE_BRANCH_NAME (source branch)
|
|
13
|
+
* - Branch context: CI_COMMIT_REF_NAME (current branch), compare against origin/main
|
|
14
|
+
*
|
|
15
|
+
* This implementation follows the same pattern as GitHub Actions, using GitLab's equivalent
|
|
16
|
+
* environment variables. This is the ONLY implementation for GitLab - no fallbacks, no alternatives.
|
|
17
|
+
* If this doesn't work, we fail with a clear error.
|
|
18
|
+
*/
|
|
19
|
+
async function getGitLabDiff(repoRoot) {
|
|
20
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
21
|
+
// Check if we're in a git repo
|
|
22
|
+
const isRepo = await git.checkIsRepo();
|
|
23
|
+
if (!isRepo) {
|
|
24
|
+
throw new Error('Not a git repository. Threadline requires a git repository.');
|
|
25
|
+
}
|
|
26
|
+
// Determine context from GitLab CI environment variables
|
|
27
|
+
const mrIid = process.env.CI_MERGE_REQUEST_IID;
|
|
28
|
+
const targetBranch = process.env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME;
|
|
29
|
+
const sourceBranch = process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME;
|
|
30
|
+
const refName = process.env.CI_COMMIT_REF_NAME;
|
|
31
|
+
// MR context: GitLab provides both target and source branches
|
|
32
|
+
if (mrIid) {
|
|
33
|
+
if (!targetBranch || !sourceBranch) {
|
|
34
|
+
throw new Error('GitLab MR context detected but CI_MERGE_REQUEST_TARGET_BRANCH_NAME or ' +
|
|
35
|
+
'CI_MERGE_REQUEST_SOURCE_BRANCH_NAME is missing. ' +
|
|
36
|
+
'This should be automatically provided by GitLab CI.');
|
|
37
|
+
}
|
|
38
|
+
// Use the branches GitLab provides directly - no detection needed
|
|
39
|
+
const diff = await git.diff([`origin/${targetBranch}...origin/${sourceBranch}`, '-U200']);
|
|
40
|
+
const diffSummary = await git.diffSummary([`origin/${targetBranch}...origin/${sourceBranch}`]);
|
|
41
|
+
const changedFiles = diffSummary.files.map(f => f.file);
|
|
42
|
+
return {
|
|
43
|
+
diff: diff || '',
|
|
44
|
+
changedFiles
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Branch context: GitLab provides branch name, compare against origin/main
|
|
48
|
+
if (refName) {
|
|
49
|
+
// For branch pushes, compare against origin/main (standard base branch)
|
|
50
|
+
// GitLab CI with fetch-depth: 0 should have origin/main available
|
|
51
|
+
const diff = await git.diff([`origin/main...origin/${refName}`, '-U200']);
|
|
52
|
+
const diffSummary = await git.diffSummary([`origin/main...origin/${refName}`]);
|
|
53
|
+
const changedFiles = diffSummary.files.map(f => f.file);
|
|
54
|
+
return {
|
|
55
|
+
diff: diff || '',
|
|
56
|
+
changedFiles
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Neither MR nor branch context available
|
|
60
|
+
throw new Error('GitLab CI environment detected but no valid context found. ' +
|
|
61
|
+
'Expected CI_MERGE_REQUEST_IID (with CI_MERGE_REQUEST_TARGET_BRANCH_NAME/CI_MERGE_REQUEST_SOURCE_BRANCH_NAME) ' +
|
|
62
|
+
'or CI_COMMIT_REF_NAME for branch context.');
|
|
63
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getLocalDiff = getLocalDiff;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
/**
|
|
9
|
+
* Get diff for local development environment
|
|
10
|
+
*
|
|
11
|
+
* For local development, we check staged changes first, then unstaged changes.
|
|
12
|
+
* This allows developers to review what they've staged before committing,
|
|
13
|
+
* or review unstaged changes if nothing is staged.
|
|
14
|
+
*
|
|
15
|
+
* This is the ONLY implementation for local - no fallbacks, no alternatives.
|
|
16
|
+
* If this doesn't work, we fail with a clear error.
|
|
17
|
+
*/
|
|
18
|
+
async function getLocalDiff(repoRoot) {
|
|
19
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
20
|
+
// Check if we're in a git repo
|
|
21
|
+
const isRepo = await git.checkIsRepo();
|
|
22
|
+
if (!isRepo) {
|
|
23
|
+
throw new Error('Not a git repository. Threadline requires a git repository.');
|
|
24
|
+
}
|
|
25
|
+
// Get git status to determine what changes exist
|
|
26
|
+
const status = await git.status();
|
|
27
|
+
let diff;
|
|
28
|
+
let changedFiles;
|
|
29
|
+
// Priority 1: Use staged changes if available
|
|
30
|
+
if (status.staged.length > 0) {
|
|
31
|
+
diff = await git.diff(['--cached', '-U200']);
|
|
32
|
+
// status.staged is an array of strings (file paths)
|
|
33
|
+
changedFiles = status.staged;
|
|
34
|
+
}
|
|
35
|
+
// Priority 2: Use unstaged changes if no staged changes
|
|
36
|
+
else if (status.files.length > 0) {
|
|
37
|
+
diff = await git.diff(['-U200']);
|
|
38
|
+
changedFiles = status.files
|
|
39
|
+
.filter(f => f.working_dir !== ' ' || f.index !== ' ')
|
|
40
|
+
.map(f => f.path);
|
|
41
|
+
}
|
|
42
|
+
// No changes at all
|
|
43
|
+
else {
|
|
44
|
+
return {
|
|
45
|
+
diff: '',
|
|
46
|
+
changedFiles: []
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
diff: diff || '',
|
|
51
|
+
changedFiles
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getVercelDiff = getVercelDiff;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
/**
|
|
9
|
+
* Get diff for Vercel CI environment
|
|
10
|
+
*
|
|
11
|
+
* Vercel provides VERCEL_GIT_COMMIT_SHA which contains the commit being deployed.
|
|
12
|
+
* This function gets the diff for that specific commit using git show.
|
|
13
|
+
*
|
|
14
|
+
* This is the ONLY implementation for Vercel - no fallbacks, no alternatives.
|
|
15
|
+
* If this doesn't work, we fail with a clear error.
|
|
16
|
+
*/
|
|
17
|
+
async function getVercelDiff(repoRoot) {
|
|
18
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
19
|
+
// Check if we're in a git repo
|
|
20
|
+
const isRepo = await git.checkIsRepo();
|
|
21
|
+
if (!isRepo) {
|
|
22
|
+
throw new Error('Not a git repository. Threadline requires a git repository.');
|
|
23
|
+
}
|
|
24
|
+
// Get commit SHA from Vercel environment variable
|
|
25
|
+
const commitSha = process.env.VERCEL_GIT_COMMIT_SHA;
|
|
26
|
+
if (!commitSha) {
|
|
27
|
+
throw new Error('VERCEL_GIT_COMMIT_SHA environment variable is not set. ' +
|
|
28
|
+
'This should be automatically provided by Vercel CI.');
|
|
29
|
+
}
|
|
30
|
+
// Get diff using git show - this is the ONLY way we get diff in Vercel
|
|
31
|
+
const diff = await git.show([commitSha, '--format=', '--no-color', '-U200']);
|
|
32
|
+
// Get changed files using git show --name-only
|
|
33
|
+
const commitFiles = await git.show([commitSha, '--name-only', '--format=', '--pretty=format:']);
|
|
34
|
+
const changedFiles = commitFiles
|
|
35
|
+
.split('\n')
|
|
36
|
+
.filter(line => line.trim().length > 0)
|
|
37
|
+
.map(line => line.trim());
|
|
38
|
+
return {
|
|
39
|
+
diff: diff || '',
|
|
40
|
+
changedFiles
|
|
41
|
+
};
|
|
42
|
+
}
|
package/dist/utils/context.js
CHANGED
|
@@ -29,9 +29,6 @@ function detectContext(environment) {
|
|
|
29
29
|
return detectVercelContext();
|
|
30
30
|
case 'local':
|
|
31
31
|
return { type: 'local' };
|
|
32
|
-
case 'azure-devops':
|
|
33
|
-
// Future: return detectAzureDevOpsContext();
|
|
34
|
-
return { type: 'local' };
|
|
35
32
|
default:
|
|
36
33
|
return { type: 'local' };
|
|
37
34
|
}
|
|
@@ -124,22 +121,28 @@ function detectGitLabContext() {
|
|
|
124
121
|
* Environment Variables:
|
|
125
122
|
* - Branch: VERCEL_GIT_COMMIT_REF
|
|
126
123
|
* - Commit: VERCEL_GIT_COMMIT_SHA
|
|
124
|
+
*
|
|
125
|
+
* Vercel Limitation:
|
|
126
|
+
* Vercel performs shallow clones of the repository, typically fetching only the
|
|
127
|
+
* specific commit being deployed. The git repository in Vercel's build environment
|
|
128
|
+
* does not contain the full git history or remote branch references (e.g., origin/main).
|
|
129
|
+
* This means branch-based diff operations (comparing feature branch against base branch)
|
|
130
|
+
* are not possible because the base branch refs are not available in the repository.
|
|
131
|
+
*
|
|
132
|
+
* Solution:
|
|
133
|
+
* We hardcode commit context for Vercel, using VERCEL_GIT_COMMIT_SHA to get a
|
|
134
|
+
* commit-based diff (comparing the commit against its parent). This works within
|
|
135
|
+
* Vercel's constraints since we only need the commit SHA, not branch references.
|
|
127
136
|
*/
|
|
128
137
|
function detectVercelContext() {
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
type: 'branch',
|
|
133
|
-
branchName: process.env.VERCEL_GIT_COMMIT_REF
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
// 2. Check for commit context
|
|
138
|
+
// Hardcode commit context for Vercel due to shallow clone limitations
|
|
139
|
+
// Vercel's git repository doesn't have base branch refs available
|
|
137
140
|
if (process.env.VERCEL_GIT_COMMIT_SHA) {
|
|
138
141
|
return {
|
|
139
142
|
type: 'commit',
|
|
140
143
|
commitSha: process.env.VERCEL_GIT_COMMIT_SHA
|
|
141
144
|
};
|
|
142
145
|
}
|
|
143
|
-
//
|
|
146
|
+
// Fallback to local
|
|
144
147
|
return { type: 'local' };
|
|
145
148
|
}
|
|
@@ -15,8 +15,7 @@ exports.isCIEnvironment = isCIEnvironment;
|
|
|
15
15
|
* 1. Vercel: VERCEL=1
|
|
16
16
|
* 2. GitHub Actions: GITHUB_ACTIONS=1
|
|
17
17
|
* 3. GitLab CI: GITLAB_CI=1 or (CI=1 + CI_COMMIT_SHA)
|
|
18
|
-
* 4.
|
|
19
|
-
* 5. Local: None of the above
|
|
18
|
+
* 4. Local: None of the above
|
|
20
19
|
*/
|
|
21
20
|
function detectEnvironment() {
|
|
22
21
|
if (process.env.VERCEL)
|
|
@@ -25,7 +24,6 @@ function detectEnvironment() {
|
|
|
25
24
|
return 'github';
|
|
26
25
|
if (process.env.GITLAB_CI || (process.env.CI && process.env.CI_COMMIT_SHA))
|
|
27
26
|
return 'gitlab';
|
|
28
|
-
// Future: if (process.env.TF_BUILD) return 'azure-devops';
|
|
29
27
|
return 'local';
|
|
30
28
|
}
|
|
31
29
|
/**
|
|
@@ -2,21 +2,62 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Git Diff Execution
|
|
4
4
|
*
|
|
5
|
-
* Executes the appropriate git diff function based on
|
|
6
|
-
*
|
|
7
|
-
* handle environment-specific details (like base branch detection).
|
|
5
|
+
* Executes the appropriate git diff function based on environment.
|
|
6
|
+
* Each environment has ONE SINGLE IMPLEMENTATION - no fallbacks, no alternatives.
|
|
8
7
|
*/
|
|
9
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getDiffForEnvironment = getDiffForEnvironment;
|
|
10
10
|
exports.getDiffForContext = getDiffForContext;
|
|
11
11
|
exports.getContextDescription = getContextDescription;
|
|
12
12
|
const diff_1 = require("../git/diff");
|
|
13
|
+
const vercel_diff_1 = require("../git/vercel-diff");
|
|
14
|
+
const github_diff_1 = require("../git/github-diff");
|
|
15
|
+
const local_diff_1 = require("../git/local-diff");
|
|
16
|
+
const gitlab_diff_1 = require("../git/gitlab-diff");
|
|
13
17
|
/**
|
|
14
|
-
* Executes the appropriate git diff function based on
|
|
18
|
+
* Executes the appropriate git diff function based on environment.
|
|
15
19
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
20
|
+
* Each environment has a single, specific implementation:
|
|
21
|
+
* - Vercel: Uses VERCEL_GIT_COMMIT_SHA, gets commit diff via git show
|
|
22
|
+
* - GitHub: Uses GITHUB_BASE_REF/GITHUB_HEAD_REF for PRs, GITHUB_REF_NAME for branches
|
|
23
|
+
* - GitLab: Uses CI_MERGE_REQUEST_TARGET_BRANCH_NAME/CI_MERGE_REQUEST_SOURCE_BRANCH_NAME for MRs, CI_COMMIT_REF_NAME for branches
|
|
24
|
+
* - Local: Uses staged changes first, then unstaged changes
|
|
25
|
+
*
|
|
26
|
+
* No fallbacks - if the environment-specific implementation fails, we fail clearly.
|
|
27
|
+
* Each environment is completely isolated - changes to one don't affect others.
|
|
28
|
+
*/
|
|
29
|
+
async function getDiffForEnvironment(environment, repoRoot, context) {
|
|
30
|
+
switch (environment) {
|
|
31
|
+
case 'vercel':
|
|
32
|
+
// Vercel: Single implementation using commit SHA
|
|
33
|
+
return await (0, vercel_diff_1.getVercelDiff)(repoRoot);
|
|
34
|
+
case 'github':
|
|
35
|
+
// GitHub: Single implementation using GitHub-provided environment variables
|
|
36
|
+
return await (0, github_diff_1.getGitHubDiff)(repoRoot);
|
|
37
|
+
case 'gitlab':
|
|
38
|
+
// GitLab: Single implementation using GitLab-provided environment variables
|
|
39
|
+
return await (0, gitlab_diff_1.getGitLabDiff)(repoRoot);
|
|
40
|
+
case 'local':
|
|
41
|
+
// Local: Single implementation using staged/unstaged changes
|
|
42
|
+
return await (0, local_diff_1.getLocalDiff)(repoRoot);
|
|
43
|
+
default:
|
|
44
|
+
const _exhaustive = environment;
|
|
45
|
+
throw new Error(`Unknown environment: ${_exhaustive}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Legacy GitLab-specific diff function (deprecated).
|
|
50
|
+
*
|
|
51
|
+
* This function is kept for backward compatibility but should not be used.
|
|
52
|
+
* GitLab now uses getDiffForEnvironment() which routes to getGitLabDiff().
|
|
53
|
+
*
|
|
54
|
+
* @deprecated Use getDiffForEnvironment('gitlab', repoRoot) instead
|
|
18
55
|
*/
|
|
19
56
|
async function getDiffForContext(context, repoRoot, environment) {
|
|
57
|
+
// This should only be called for GitLab legacy code paths
|
|
58
|
+
if (environment !== 'gitlab') {
|
|
59
|
+
throw new Error(`getDiffForContext() is deprecated. Use getDiffForEnvironment('${environment}', repoRoot) instead.`);
|
|
60
|
+
}
|
|
20
61
|
switch (context.type) {
|
|
21
62
|
case 'pr':
|
|
22
63
|
return await (0, diff_1.getPRMRDiff)(repoRoot, context.sourceBranch, context.targetBranch);
|
|
@@ -27,7 +68,7 @@ async function getDiffForContext(context, repoRoot, environment) {
|
|
|
27
68
|
case 'commit':
|
|
28
69
|
return await (0, diff_1.getCommitDiff)(repoRoot, context.commitSha);
|
|
29
70
|
case 'local':
|
|
30
|
-
|
|
71
|
+
throw new Error('Local context should use getDiffForEnvironment(), not getDiffForContext()');
|
|
31
72
|
default:
|
|
32
73
|
// TypeScript exhaustiveness check - should never reach here
|
|
33
74
|
const _exhaustive = context;
|