httpcat-cli 0.2.8-rc.1 → 0.2.9-rc.1

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.
@@ -96,6 +96,18 @@ jobs:
96
96
  if (context.eventName === 'push' && context.payload.before) {
97
97
  console.log(`Analyzing commits in this push (${context.payload.before}..${context.sha})...`);
98
98
  try {
99
+ // First, verify both commits exist
100
+ try {
101
+ await github.rest.repos.getCommit({
102
+ owner: context.repo.owner,
103
+ repo: context.repo.repo,
104
+ ref: context.payload.before
105
+ });
106
+ } catch (e) {
107
+ console.log(`⚠️ Base commit ${context.payload.before} not found (may have been squashed/rebased), falling back to last release`);
108
+ throw new Error(`Base commit not found: ${e.message}`);
109
+ }
110
+
99
111
  const response = await github.rest.repos.compareCommits({
100
112
  owner: context.repo.owner,
101
113
  repo: context.repo.repo,
@@ -117,36 +129,29 @@ jobs:
117
129
  }
118
130
  }
119
131
  } catch (e) {
120
- console.log(`⚠️ Could not compare commits in push, falling back to last release: ${e.message}`);
132
+ console.log(`⚠️ Could not compare commits in push (${e.message}), falling back to last release`);
121
133
  // Fallback to comparing with last release tag
122
134
  if (lastTag) {
123
- let baseSha;
124
135
  try {
125
- const { data: tagData } = await github.rest.git.getRef({
136
+ // Use tag name directly - GitHub API resolves it to commit SHA
137
+ const response = await github.rest.repos.compareCommits({
126
138
  owner: context.repo.owner,
127
139
  repo: context.repo.repo,
128
- ref: `tags/${lastTag}`
140
+ base: lastTag,
141
+ head: context.sha
129
142
  });
130
- baseSha = tagData.object.sha;
143
+ compareData = response.data;
131
144
  } catch (e2) {
132
- try {
133
- const { data: commitData } = await github.rest.repos.getCommit({
134
- owner: context.repo.owner,
135
- repo: context.repo.repo,
136
- ref: lastTag
137
- });
138
- baseSha = commitData.sha;
139
- } catch (e3) {
140
- baseSha = null;
141
- }
145
+ console.log(`⚠️ Tag comparison failed: ${e2.message}, using main branch`);
146
+ // Final fallback to main branch
147
+ const response = await github.rest.repos.compareCommits({
148
+ owner: context.repo.owner,
149
+ repo: context.repo.repo,
150
+ base: 'main',
151
+ head: context.sha
152
+ });
153
+ compareData = response.data;
142
154
  }
143
- const response = await github.rest.repos.compareCommits({
144
- owner: context.repo.owner,
145
- repo: context.repo.repo,
146
- base: baseSha || 'main',
147
- head: context.sha
148
- });
149
- compareData = response.data;
150
155
  } else {
151
156
  // No last tag and push comparison failed - default to patch
152
157
  // We can't reliably determine which commits to analyze without a baseline
@@ -159,33 +164,25 @@ jobs:
159
164
  } else if (lastTag) {
160
165
  // For other events (like workflow_dispatch), compare with last release
161
166
  console.log(`Last release tag: ${lastTag}`);
162
- let baseSha;
163
167
  try {
164
- const { data: tagData } = await github.rest.git.getRef({
168
+ // Use tag name directly - GitHub API resolves it to commit SHA
169
+ const response = await github.rest.repos.compareCommits({
165
170
  owner: context.repo.owner,
166
171
  repo: context.repo.repo,
167
- ref: `tags/${lastTag}`
172
+ base: lastTag,
173
+ head: context.sha
168
174
  });
169
- baseSha = tagData.object.sha;
175
+ compareData = response.data;
170
176
  } catch (e) {
171
- try {
172
- const { data: commitData } = await github.rest.repos.getCommit({
173
- owner: context.repo.owner,
174
- repo: context.repo.repo,
175
- ref: lastTag
176
- });
177
- baseSha = commitData.sha;
178
- } catch (e2) {
179
- baseSha = null;
180
- }
177
+ console.log(`⚠️ Tag comparison failed: ${e.message}, using main branch`);
178
+ const response = await github.rest.repos.compareCommits({
179
+ owner: context.repo.owner,
180
+ repo: context.repo.repo,
181
+ base: 'main',
182
+ head: context.sha
183
+ });
184
+ compareData = response.data;
181
185
  }
182
- const response = await github.rest.repos.compareCommits({
183
- owner: context.repo.owner,
184
- repo: context.repo.repo,
185
- base: baseSha || 'main',
186
- head: context.sha
187
- });
188
- compareData = response.data;
189
186
  } else {
190
187
  // No last tag and not a push event - default to patch
191
188
  // For workflow_dispatch or other events without a tag, we can't reliably
@@ -325,40 +322,103 @@ jobs:
325
322
  const currentTag = 'v${{ steps.version.outputs.version }}';
326
323
 
327
324
  // Get commits since last release
325
+ let commits;
328
326
  let baseSha;
329
- if (lastTag) {
327
+
328
+ // For push events, prefer using context.payload.before if available
329
+ // This ensures we only get commits from the current push/merge
330
+ if (context.eventName === 'push' && context.payload.before) {
331
+ console.log(`Using push event comparison (${context.payload.before}..${context.sha})`);
330
332
  try {
331
- const { data: tagData } = await github.rest.git.getRef({
333
+ const response = await github.rest.repos.compareCommits({
332
334
  owner: context.repo.owner,
333
335
  repo: context.repo.repo,
334
- ref: `tags/${lastTag}`
336
+ base: context.payload.before,
337
+ head: context.sha
335
338
  });
336
- baseSha = tagData.object.sha;
339
+ commits = response.data;
340
+ baseSha = context.payload.before;
341
+ console.log(`Found ${commits.commits.length} commits in this push`);
337
342
  } catch (e) {
338
- // If tag ref doesn't exist, try to get commit from tag
339
- const { data: tagData } = await github.rest.repos.getCommit({
340
- owner: context.repo.owner,
341
- repo: context.repo.repo,
342
- ref: lastTag
343
- });
344
- baseSha = tagData.sha;
343
+ console.log(`⚠️ Push comparison failed: ${e.message}, falling back to tag comparison`);
344
+ // Fall through to tag-based comparison
345
+ }
346
+ }
347
+
348
+ // If push comparison didn't work or wasn't available, try tag-based comparison
349
+ if (!commits) {
350
+ if (lastTag) {
351
+ console.log(`Comparing with last tag ${lastTag}`);
352
+
353
+ try {
354
+ // Use the tag name directly - GitHub API will resolve it to the commit SHA
355
+ // This handles both lightweight and annotated tags correctly
356
+ const response = await github.rest.repos.compareCommits({
357
+ owner: context.repo.owner,
358
+ repo: context.repo.repo,
359
+ base: lastTag, // Use tag name directly, API resolves to commit
360
+ head: context.sha
361
+ });
362
+ commits = response.data;
363
+ baseSha = lastTag; // Store tag name for changelog link
364
+ console.log(`Found ${commits.commits.length} commits since ${lastTag}`);
365
+ } catch (e) {
366
+ console.log(`⚠️ Tag comparison failed: ${e.message}`);
367
+ console.log(`Error details: ${e.response?.data?.message || e.message}`);
368
+
369
+ // Try to get the actual commit SHA from the tag as fallback
370
+ try {
371
+ const { data: commitData } = await github.rest.repos.getCommit({
372
+ owner: context.repo.owner,
373
+ repo: context.repo.repo,
374
+ ref: lastTag
375
+ });
376
+ const tagCommitSha = commitData.sha;
377
+ console.log(`Resolved tag ${lastTag} to commit ${tagCommitSha}, retrying comparison...`);
378
+
379
+ const response = await github.rest.repos.compareCommits({
380
+ owner: context.repo.owner,
381
+ repo: context.repo.repo,
382
+ base: tagCommitSha,
383
+ head: context.sha
384
+ });
385
+ commits = response.data;
386
+ baseSha = tagCommitSha;
387
+ console.log(`Found ${commits.commits.length} commits since ${lastTag}`);
388
+ } catch (e2) {
389
+ console.log(`⚠️ Commit SHA comparison also failed: ${e2.message}`);
390
+ // Fall through to main branch comparison
391
+ }
392
+ }
393
+ }
394
+
395
+ // If tag comparison failed or no tag exists, compare with main branch
396
+ if (!commits) {
397
+ try {
398
+ const { data: branchData } = await github.rest.repos.getBranch({
399
+ owner: context.repo.owner,
400
+ repo: context.repo.repo,
401
+ branch: 'main'
402
+ });
403
+ baseSha = branchData.commit.sha;
404
+ console.log(`Comparing with main branch (${baseSha})`);
405
+
406
+ const response = await github.rest.repos.compareCommits({
407
+ owner: context.repo.owner,
408
+ repo: context.repo.repo,
409
+ base: baseSha,
410
+ head: context.sha
411
+ });
412
+ commits = response.data;
413
+ console.log(`Found ${commits.commits.length} commits since main branch HEAD`);
414
+ } catch (e) {
415
+ console.log(`⚠️ Main branch comparison also failed: ${e.message}`);
416
+ console.log(`Using empty commit list - release notes will be minimal`);
417
+ commits = { commits: [] };
418
+ baseSha = null;
419
+ }
345
420
  }
346
- } else {
347
- // Get the first commit or main branch
348
- const { data: branchData } = await github.rest.repos.getBranch({
349
- owner: context.repo.owner,
350
- repo: context.repo.repo,
351
- branch: 'main'
352
- });
353
- baseSha = branchData.commit.sha;
354
421
  }
355
-
356
- const { data: commits } = await github.rest.repos.compareCommits({
357
- owner: context.repo.owner,
358
- repo: context.repo.repo,
359
- base: baseSha,
360
- head: context.sha
361
- });
362
422
 
363
423
  // Categorize commits
364
424
  const features = [];
@@ -367,21 +427,25 @@ jobs:
367
427
  const chore = [];
368
428
  const breaking = [];
369
429
 
370
- for (const commit of commits.commits) {
371
- const message = commit.commit.message;
372
- const firstLine = message.split('\n')[0];
373
-
374
- if (firstLine.match(/^BREAKING/)) {
375
- breaking.push(`- ${firstLine.replace(/^BREAKING[:\s]+/i, '')}`);
376
- } else if (firstLine.match(/^feat(ure)?[(:]/i)) {
377
- features.push(`- ${firstLine.replace(/^feat(ure)?[(:]\s*/i, '')}`);
378
- } else if (firstLine.match(/^fix[(]/i)) {
379
- fixes.push(`- ${firstLine.replace(/^fix[(]\s*/i, '')}`);
380
- } else if (firstLine.match(/^doc(s)?[(]/i)) {
381
- docs.push(`- ${firstLine.replace(/^doc(s)?[(]\s*/i, '')}`);
382
- } else if (!firstLine.match(/^(chore|ci|test|build)[(:]/i)) {
383
- chore.push(`- ${firstLine}`);
430
+ if (commits && commits.commits && commits.commits.length > 0) {
431
+ for (const commit of commits.commits) {
432
+ const message = commit.commit.message;
433
+ const firstLine = message.split('\n')[0];
434
+
435
+ if (firstLine.match(/^BREAKING/)) {
436
+ breaking.push(`- ${firstLine.replace(/^BREAKING[:\s]+/i, '')}`);
437
+ } else if (firstLine.match(/^feat(ure)?[(:]/i)) {
438
+ features.push(`- ${firstLine.replace(/^feat(ure)?[(:]\s*/i, '')}`);
439
+ } else if (firstLine.match(/^fix[(]/i)) {
440
+ fixes.push(`- ${firstLine.replace(/^fix[(]\s*/i, '')}`);
441
+ } else if (firstLine.match(/^doc(s)?[(]/i)) {
442
+ docs.push(`- ${firstLine.replace(/^doc(s)?[(]\s*/i, '')}`);
443
+ } else if (!firstLine.match(/^(chore|ci|test|build)[(:]/i)) {
444
+ chore.push(`- ${firstLine}`);
445
+ }
384
446
  }
447
+ } else {
448
+ console.log('⚠️ No commits found for release notes - using minimal release notes');
385
449
  }
386
450
 
387
451
  let notes = `## 🎉 Release ${{ steps.version.outputs.version }}\n\n`;
@@ -414,10 +478,13 @@ jobs:
414
478
  notes += `brew upgrade httpcat\n`;
415
479
  notes += `\`\`\`\n\n`;
416
480
  notes += `---\n\n`;
417
- notes += `**Full Changelog**: https://github.com/${{ github.repository }}/compare/${lastTag || 'main'}...${currentTag}`;
481
+
482
+ // Generate changelog link - use lastTag if available, otherwise use main
483
+ const changelogBase = lastTag || 'main';
484
+ notes += `**Full Changelog**: https://github.com/${{ github.repository }}/compare/${changelogBase}...${currentTag}`;
418
485
 
419
486
  core.setOutput('notes', notes);
420
- console.log('Generated release notes');
487
+ console.log('Generated release notes');
421
488
 
422
489
  # Job 2: Build and test
423
490
  test:
@@ -1,13 +1,13 @@
1
1
  name: Sync Version to Develop
2
2
 
3
- # This workflow runs after a release to sync the version from main back to develop
3
+ # This workflow runs after a release to reset develop to match main and sync the version
4
4
  on:
5
5
  release:
6
6
  types: [published]
7
7
 
8
8
  jobs:
9
9
  sync-version:
10
- name: Sync version to develop
10
+ name: Reset develop to match main
11
11
  runs-on: ubuntu-latest
12
12
  permissions:
13
13
  contents: write
@@ -25,32 +25,87 @@ jobs:
25
25
  # Remove 'v' prefix if present
26
26
  VERSION="${VERSION#v}"
27
27
  echo "version=$VERSION" >> $GITHUB_OUTPUT
28
- echo "✅ Version to sync: $VERSION"
28
+ echo "✅ Version from release: $VERSION"
29
29
 
30
30
  - name: Checkout develop branch
31
31
  run: |
32
32
  git checkout develop
33
33
  git pull origin develop
34
34
 
35
- - name: Update package.json version
35
+ - name: Check for new commits in develop
36
+ id: check-commits
36
37
  run: |
37
- VERSION="${{ steps.version.outputs.version }}"
38
- npm version "$VERSION" --no-git-tag-version --allow-same-version
39
- echo " Updated package.json to version $VERSION"
38
+ # Check if develop has commits that aren't in main
39
+ COMMITS_AHEAD=$(git rev-list --count origin/main..HEAD 2>/dev/null || echo "0")
40
+ echo "commits_ahead=$COMMITS_AHEAD" >> $GITHUB_OUTPUT
41
+
42
+ if [ "$COMMITS_AHEAD" -gt 0 ]; then
43
+ echo "ℹ️ Develop has $COMMITS_AHEAD commit(s) not in main"
44
+ echo "These will be preserved by rebasing onto main"
45
+ else
46
+ echo "✅ Develop has no new commits - can fast-forward to main"
47
+ fi
48
+
49
+ - name: Rebase develop onto main
50
+ run: |
51
+ echo "Updating develop to include latest from main..."
52
+ git fetch origin main
53
+
54
+ # Check if we can fast-forward (no new commits in develop)
55
+ COMMITS_AHEAD="${{ steps.check-commits.outputs.commits_ahead }}"
56
+
57
+ if [ "$COMMITS_AHEAD" -eq 0 ]; then
58
+ # Fast-forward: just move develop to main
59
+ echo "Fast-forwarding develop to main..."
60
+ git reset --hard origin/main
61
+ else
62
+ # Rebase: replay develop's commits on top of main
63
+ echo "Rebasing develop onto main..."
64
+ git rebase origin/main || {
65
+ echo "⚠️ Rebase conflict detected - this shouldn't happen if develop was properly merged"
66
+ echo "Falling back to reset (this will discard develop-only commits)"
67
+ git rebase --abort 2>/dev/null || true
68
+ git reset --hard origin/main
69
+ }
70
+ fi
71
+ echo "✅ Develop updated to include latest from main"
72
+
73
+ - name: Verify package.json version
74
+ run: |
75
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
76
+ RELEASE_VERSION="${{ steps.version.outputs.version }}"
77
+
78
+ echo "Current version in package.json: $CURRENT_VERSION"
79
+ echo "Release version: $RELEASE_VERSION"
80
+
81
+ if [ "$CURRENT_VERSION" != "$RELEASE_VERSION" ]; then
82
+ echo "Updating package.json version..."
83
+ npm version "$RELEASE_VERSION" --no-git-tag-version --allow-same-version
84
+ git add package.json
85
+ git commit -m "chore: sync version to $RELEASE_VERSION" || echo "No changes to commit"
86
+ else
87
+ echo "✅ Version already matches"
88
+ fi
40
89
 
41
- - name: Commit and push to develop
90
+ - name: Push to develop
42
91
  run: |
43
- VERSION="${{ steps.version.outputs.version }}"
44
92
  git config user.name "github-actions[bot]"
45
93
  git config user.email "github-actions[bot]@users.noreply.github.com"
46
- git add package.json
47
94
 
48
- # Check if there are changes to commit
49
- if git diff --staged --quiet; then
50
- echo "✅ package.json already at version $VERSION, nothing to commit"
95
+ # Check if there are any changes to push
96
+ if git diff --quiet origin/develop HEAD; then
97
+ echo "✅ No changes to push (develop already up to date)"
51
98
  else
52
- git commit -m "chore: sync version to $VERSION"
53
- git push origin develop
54
- echo "✅ Version synced to develop"
99
+ COMMITS_AHEAD="${{ steps.check-commits.outputs.commits_ahead }}"
100
+ if [ "$COMMITS_AHEAD" -eq 0 ]; then
101
+ # Fast-forward push (no force needed)
102
+ echo "Pushing fast-forward update..."
103
+ git push origin develop
104
+ else
105
+ # Rebase requires force push (but this is safe after rebase)
106
+ echo "Pushing rebased develop branch..."
107
+ git push origin develop --force-with-lease
108
+ fi
109
+ echo "✅ Develop updated and pushed"
55
110
  fi
56
111
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "httpcat-cli",
3
- "version": "0.2.8-rc.1",
3
+ "version": "0.2.9-rc.1",
4
4
  "description": "CLI tool for interacting with httpcat agent - create, buy, and sell tokens with x402 payments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {