Skip to content

Commit baced38

Browse files
committed
tweak scripts for release
1 parent 8ceb3e6 commit baced38

File tree

7 files changed

+358
-27
lines changed

7 files changed

+358
-27
lines changed
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
name: CLI Release Prod
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version_type:
7+
description: 'Version bump type'
8+
required: true
9+
default: 'patch'
10+
type: choice
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
16+
concurrency:
17+
group: cli-prod-release
18+
cancel-in-progress: false
19+
20+
permissions:
21+
contents: write
22+
23+
jobs:
24+
prepare-and-commit-prod:
25+
runs-on: ubuntu-latest
26+
outputs:
27+
new_version: ${{ steps.bump_version.outputs.new_version }}
28+
steps:
29+
- uses: actions/checkout@v4
30+
with:
31+
token: ${{ secrets.GITHUB_TOKEN }}
32+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
33+
34+
- uses: ./.github/actions/setup-project
35+
36+
- name: Calculate prod version
37+
id: bump_version
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.CODEBUFF_GITHUB_TOKEN }}
40+
GITHUB_API_URL: https://api.github.com/repos/CodebuffAI/codebuff-community
41+
run: |
42+
cd cli/release
43+
44+
BASE_VERSION=$(bun -e "console.log(require('./package.json').version)")
45+
echo "Base version: $BASE_VERSION"
46+
47+
echo "Fetching latest CLI prerelease from GitHub..."
48+
RELEASES_JSON=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
49+
"${GITHUB_API_URL}/releases?per_page=100")
50+
51+
LATEST_TAG=$(echo "$RELEASES_JSON" | jq -r '.[] | select(.prerelease == true and (.name // "" | test("Codebuff CLI v"))) | .tag_name' | sort -V | tail -n 1)
52+
53+
if [ "$LATEST_TAG" = "null" ] || [ -z "$LATEST_TAG" ]; then
54+
echo "No existing CLI prerelease found via releases, falling back to tags..."
55+
LATEST_TAG=$(git ls-remote --tags origin "v${BASE_VERSION}-beta.*" | awk '{print $2}' | sed 's@refs/tags/@@' | sort -V | tail -n 1)
56+
fi
57+
58+
if [ -n "$LATEST_TAG" ] && [[ "$LATEST_TAG" != v* ]]; then
59+
LATEST_TAG="v${LATEST_TAG}"
60+
fi
61+
62+
if [ -n "$LATEST_TAG" ]; then
63+
echo "Latest CLI beta tag: $LATEST_TAG"
64+
LATEST_VERSION=${LATEST_TAG#v}
65+
LATEST_BASE=$(echo "$LATEST_VERSION" | sed 's/-beta\..*$//')
66+
LATEST_BETA_NUM=$(echo "$LATEST_VERSION" | sed 's/.*-beta\.//')
67+
68+
if [ "$LATEST_BASE" = "$BASE_VERSION" ]; then
69+
NEXT=$((LATEST_BETA_NUM + 1))
70+
NEW_VERSION="${BASE_VERSION}-beta.${NEXT}"
71+
else
72+
echo "Base version changed since last prerelease, resetting counter"
73+
NEW_VERSION="${BASE_VERSION}-beta.1"
74+
fi
75+
else
76+
echo "No existing CLI beta tags found, starting with beta.1"
77+
NEW_VERSION="${BASE_VERSION}-beta.1"
78+
fi
79+
80+
echo "New prod version: $NEW_VERSION"
81+
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
82+
83+
bun -e "
84+
const fs = require('fs');
85+
const path = require('path');
86+
const version = '$NEW_VERSION';
87+
const prodPath = path.join(process.cwd(), 'package.json');
88+
const prodPkg = JSON.parse(fs.readFileSync(prodPath, 'utf8'));
89+
prodPkg.version = version;
90+
fs.writeFileSync(prodPath, JSON.stringify(prodPkg, null, 2) + '\n');
91+
const rootPkgPath = path.join(process.cwd(), '..', 'package.json');
92+
const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, 'utf8'));
93+
rootPkg.version = version;
94+
fs.writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2) + '\n');
95+
"
96+
97+
- name: Configure git
98+
run: |
99+
git config --global user.name "github-actions[bot]"
100+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
101+
102+
- name: Commit prod release snapshot
103+
run: |
104+
git add -A
105+
git commit -m "Prod CLI Release v${{ steps.bump_version.outputs.new_version }}
106+
107+
Captures the staged state for the CLI prerelease, including the version bump.
108+
109+
🤖 Generated with Codebuff
110+
Co-Authored-By: Codebuff <noreply@codebuff.com>"
111+
112+
- name: Create and push prod tag
113+
run: |
114+
git tag "v${{ steps.bump_version.outputs.new_version }}"
115+
git push origin "v${{ steps.bump_version.outputs.new_version }}"
116+
117+
- name: Upload prod metadata
118+
uses: actions/upload-artifact@v4
119+
with:
120+
name: cli-prod-metadata
121+
path: cli/release/
122+
123+
build-prod-binaries:
124+
needs: prepare-and-commit-prod
125+
uses: ./.github/workflows/cli-release-build.yml
126+
with:
127+
binary-name: codebuff
128+
new-version: ${{ needs.prepare-and-commit-prod.outputs.new_version }}
129+
artifact-name: cli-prod-metadata
130+
checkout-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
131+
env-overrides: '{"NEXT_PUBLIC_CB_ENVIRONMENT":"prod"}'
132+
secrets: inherit
133+
134+
create-prod-release:
135+
needs: [prepare-and-commit-prod, build-prod-binaries]
136+
runs-on: ubuntu-latest
137+
steps:
138+
- uses: actions/checkout@v4
139+
with:
140+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
141+
142+
- name: Clean up old CLI prereleases
143+
env:
144+
GITHUB_API_URL: https://api.github.com/repos/CodebuffAI/codebuff-community
145+
run: |
146+
ONE_WEEK_AGO=$(date -d '7 days ago' -u +%Y-%m-%dT%H:%M:%SZ)
147+
echo "Removing CLI prereleases older than: $ONE_WEEK_AGO"
148+
149+
RELEASES=$(curl -s -H "Authorization: token ${{ secrets.CODEBUFF_GITHUB_TOKEN }}" \
150+
"${GITHUB_API_URL}/releases?per_page=100")
151+
152+
if echo "$RELEASES" | jq -e 'type == "array"' >/dev/null 2>&1; then
153+
OLD=$(echo "$RELEASES" | jq -r --arg cutoff "$ONE_WEEK_AGO" '.[] | select(.prerelease == true and .created_at < $cutoff and (.tag_name | test("^v[0-9].*-beta\\.[0-9]+$"))) | "\(.id):\(.tag_name)"')
154+
155+
if [ -n "$OLD" ]; then
156+
echo "Deleting old prereleases:"
157+
echo "$OLD"
158+
echo "$OLD" | while IFS=: read -r RELEASE_ID TAG_NAME; do
159+
curl -s -X DELETE \
160+
-H "Authorization: token ${{ secrets.CODEBUFF_GITHUB_TOKEN }}" \
161+
"${GITHUB_API_URL}/releases/$RELEASE_ID"
162+
done
163+
else
164+
echo "No stale prereleases found."
165+
fi
166+
else
167+
echo "Failed to parse releases response:"
168+
echo "$RELEASES" | head -20
169+
fi
170+
171+
- name: Download all binary artifacts
172+
uses: actions/download-artifact@v4
173+
with:
174+
path: binaries/
175+
176+
- name: Download prod metadata
177+
uses: actions/download-artifact@v4
178+
with:
179+
name: cli-prod-metadata
180+
path: cli/release/
181+
182+
- name: Create GitHub Release
183+
uses: softprops/action-gh-release@v1
184+
with:
185+
tag_name: v${{ needs.prepare-and-commit-prod.outputs.new_version }}
186+
name: Codebuff v${{ needs.prepare-and-commit-prod.outputs.new_version }} (Prod)
187+
prerelease: true
188+
body: |
189+
## Codebuff v${{ needs.prepare-and-commit-prod.outputs.new_version }} (Prod)
190+
191+
### Included Binaries
192+
- `codebuff-linux-x64.tar.gz`
193+
- `codebuff-linux-arm64.tar.gz`
194+
- `codebuff-darwin-x64.tar.gz`
195+
- `codebuff-darwin-arm64.tar.gz`
196+
- `codebuff-win32-x64.tar.gz`
197+
198+
After downloading, extract the tarball, add the binary to your PATH, and run `codebuff --help` for usage.
199+
files: |
200+
binaries/*/codebuff-*
201+
repository: CodebuffAI/codebuff-community
202+
token: ${{ secrets.CODEBUFF_GITHUB_TOKEN }}
203+
204+
publish-prod-npm:
205+
needs:
206+
[
207+
prepare-and-commit-prod,
208+
build-prod-binaries,
209+
create-prod-release,
210+
]
211+
runs-on: ubuntu-latest
212+
permissions:
213+
contents: read
214+
id-token: write
215+
steps:
216+
- uses: actions/checkout@v4
217+
with:
218+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
219+
220+
- name: Download CLI prod package
221+
uses: actions/download-artifact@v4
222+
with:
223+
name: cli-prod-metadata
224+
path: cli/release/
225+
226+
- name: Set up Node.js with npm registry
227+
uses: actions/setup-node@v4
228+
with:
229+
node-version: '20'
230+
registry-url: 'https://registry.npmjs.org'
231+
232+
- name: Publish codebuff prod package to npm
233+
run: |
234+
cd cli/release
235+
npm publish --access public
236+
env:
237+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"build:sdk": "cd ../sdk && bun run build",
2222
"build:sdk-types": "cd ../sdk && bun run build:types",
2323
"build:binary": "bun ./scripts/build-binary.ts codecane $npm_package_version",
24+
"release": "bun run scripts/release.ts",
2425
"start": "bun run dist/index.js",
2526
"test": "bun test",
2627
"test:tmux-poc": "bun run src/__tests__/tmux-poc.ts",

cli/release/index.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const zlib = require('zlib')
99

1010
const tar = require('tar')
1111

12-
const packageName = 'codecane'
12+
const packageName = 'codebuff'
1313

1414
function createConfig(packageName) {
1515
const homeDir = os.homedir()
@@ -163,6 +163,12 @@ function getCurrentVersion() {
163163
function compareVersions(v1, v2) {
164164
if (!v1 || !v2) return 0
165165

166+
// Always update if the current version is not a valid semver
167+
// e.g. 1.0.420-beta.1
168+
if (!v1.match(/^\d+(\.\d+)*$/)) {
169+
return -1
170+
}
171+
166172
const parseVersion = (version) => {
167173
const parts = version.split('-')
168174
const mainParts = parts[0].split('.').map(Number)
@@ -324,7 +330,7 @@ async function downloadBinary(version) {
324330
}
325331

326332
term.clearLine()
327-
console.log('Download complete! Starting Codecane...')
333+
console.log('Download complete! Starting Codebuff...')
328334
}
329335

330336
async function ensureBinaryExists() {
@@ -344,7 +350,7 @@ async function ensureBinaryExists() {
344350
await downloadBinary(version)
345351
} catch (error) {
346352
term.clearLine()
347-
console.error('❌ Failed to download codecane:', error.message)
353+
console.error('❌ Failed to download codebuff:', error.message)
348354
console.error('Please check your internet connection and try again')
349355
process.exit(1)
350356
}
@@ -398,14 +404,6 @@ async function checkForUpdates(runningProcess, exitListener) {
398404
}
399405

400406
async function main() {
401-
console.log('\x1b[1m\x1b[91m' + '='.repeat(60) + '\x1b[0m')
402-
console.log('\x1b[1m\x1b[93m❄️ CODECANE STAGING ENVIRONMENT ❄️\x1b[0m')
403-
console.log(
404-
'\x1b[1m\x1b[91mFOR TESTING PURPOSES ONLY - NOT FOR PRODUCTION USE\x1b[0m',
405-
)
406-
console.log('\x1b[1m\x1b[91m' + '='.repeat(60) + '\x1b[0m')
407-
console.log('')
408-
409407
await ensureBinaryExists()
410408

411409
const child = spawn(CONFIG.binaryPath, process.argv.slice(2), {

cli/release/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
2-
"name": "codecane",
3-
"version": "1.0.420",
4-
"description": "AI coding agent CLI (staging)",
2+
"name": "codebuff",
3+
"version": "1.0.511",
4+
"description": "AI coding agent",
55
"license": "MIT",
66
"bin": {
7-
"codecane": "index.js"
7+
"codebuff": "index.js",
8+
"cb": "index.js"
89
},
910
"scripts": {
10-
"preuninstall": "node -e \"const fs = require('fs'); const path = require('path'); const os = require('os'); const binaryPath = path.join(os.homedir(), '.config', 'manicode', process.platform === 'win32' ? 'codecane.exe' : 'codecane'); try { fs.unlinkSync(binaryPath) } catch (e) { /* ignore if file doesn't exist */ }\""
11+
"preuninstall": "node -e \"const fs = require('fs'); const path = require('path'); const os = require('os'); const binaryPath = path.join(os.homedir(), '.config', 'manicode', process.platform === 'win32' ? 'codebuff.exe' : 'codebuff'); try { fs.unlinkSync(binaryPath) } catch (e) { /* ignore if file doesn't exist */ }\""
1112
},
1213
"files": [
1314
"index.js",

0 commit comments

Comments
 (0)