threadlines 0.1.19 → 0.1.20

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.
@@ -126,11 +126,21 @@ 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 context based on environment
130
- context = (0, context_1.detectContext)(environment);
131
- const contextDesc = (0, git_diff_executor_1.getContextDescription)(context);
132
- console.log(chalk_1.default.gray(`📝 Collecting git changes for ${contextDesc}...`));
133
- gitDiff = await (0, git_diff_executor_1.getDiffForContext)(context, repoRoot, environment);
129
+ // Auto-detect: Use environment-specific implementation
130
+ if (environment === 'vercel') {
131
+ // Vercel: Direct environment-based routing (single implementation)
132
+ console.log(chalk_1.default.gray(`📝 Collecting git changes for Vercel commit...`));
133
+ gitDiff = await (0, git_diff_executor_1.getDiffForEnvironment)(environment, repoRoot);
134
+ // Vercel uses commit context, but we don't need to create it explicitly
135
+ context = { type: 'commit', commitSha: process.env.VERCEL_GIT_COMMIT_SHA };
136
+ }
137
+ else {
138
+ // Other environments: Use context-based routing (legacy)
139
+ context = (0, context_1.detectContext)(environment);
140
+ const contextDesc = (0, git_diff_executor_1.getContextDescription)(context);
141
+ console.log(chalk_1.default.gray(`📝 Collecting git changes for ${contextDesc}...`));
142
+ gitDiff = await (0, git_diff_executor_1.getDiffForContext)(context, repoRoot, environment);
143
+ }
134
144
  }
135
145
  // 3. Collect metadata (commit SHA, commit message, PR title)
136
146
  const metadata = await (0, metadata_1.collectMetadata)(context, environment, repoRoot);
package/dist/git/diff.js CHANGED
@@ -96,29 +96,9 @@ async function getBranchDiff(repoRoot, branchName, baseBranch) {
96
96
  // Helper function to detect base branch
97
97
  // Returns the branch name to use in git commands (may be local or remote)
98
98
  // In CI environments, prioritizes remote refs since local branches often don't exist
99
+ // Note: Vercel is excluded here because it uses commit context, not branch context
99
100
  async function detectBaseBranch(git, branchName) {
100
- const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.VERCEL || process.env.GITLAB_CI);
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
- }
101
+ const isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI);
122
102
  // Strategy 1: Try upstream tracking branch (most reliable if set)
123
103
  try {
124
104
  const upstream = await git.revparse(['--abbrev-ref', '--symbolic-full-name', `${branchName}@{u}`]);
@@ -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
+ }
@@ -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
- // 1. Check for branch context
130
- if (process.env.VERCEL_GIT_COMMIT_REF) {
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
- // 3. Fallback to local
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. Azure DevOps: TF_BUILD=1 (future)
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,19 +2,49 @@
2
2
  /**
3
3
  * Git Diff Execution
4
4
  *
5
- * Executes the appropriate git diff function based on review context.
6
- * This is environment-agnostic - the git diff functions themselves
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
+ /**
15
+ * Executes the appropriate git diff function based on environment.
16
+ *
17
+ * Each environment has a single, specific implementation:
18
+ * - Vercel: Uses VERCEL_GIT_COMMIT_SHA, gets commit diff via git show
19
+ * - GitHub: Uses branch/PR context with base branch detection
20
+ * - GitLab: Uses branch/MR context with base branch detection
21
+ * - Local: Uses staged/unstaged changes
22
+ *
23
+ * No fallbacks - if the environment-specific implementation fails, we fail clearly.
24
+ */
25
+ async function getDiffForEnvironment(environment, repoRoot, context) {
26
+ switch (environment) {
27
+ case 'vercel':
28
+ // Vercel: Single implementation using commit SHA
29
+ return await (0, vercel_diff_1.getVercelDiff)(repoRoot);
30
+ case 'github':
31
+ case 'gitlab':
32
+ case 'local':
33
+ // For other environments, use context-based routing (legacy, will be refactored)
34
+ if (!context) {
35
+ throw new Error(`Context required for ${environment} environment`);
36
+ }
37
+ return await getDiffForContext(context, repoRoot, environment);
38
+ default:
39
+ const _exhaustive = environment;
40
+ throw new Error(`Unknown environment: ${_exhaustive}`);
41
+ }
42
+ }
13
43
  /**
14
44
  * Executes the appropriate git diff function based on context.
15
45
  *
46
+ * This is the legacy context-based routing. New code should use getDiffForEnvironment().
16
47
  * This function maps context types to their corresponding git diff functions.
17
- * The actual git diff functions handle environment-specific details internally.
18
48
  */
19
49
  async function getDiffForContext(context, repoRoot, environment) {
20
50
  switch (context.type) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadlines",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Threadline CLI - AI-powered linter based on your natural language documentation",
5
5
  "main": "dist/index.js",
6
6
  "bin": {