Skip to content

Commit 27d3fc9

Browse files
committed
Merge remote-tracking branch 'origin/main' into bugfix/settingssave
2 parents cc47997 + 5d17f56 commit 27d3fc9

File tree

246 files changed

+15356
-13095
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

246 files changed

+15356
-13095
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# These owners will be the default owners for everything in the repo
2-
* @mrubens @cte @jr
2+
* @mrubens @cte @jr @hannesrudolph @daniel-lxs

.github/workflows/cli-release.yml

Lines changed: 390 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,390 @@
1+
name: CLI Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version to release (e.g., 0.1.0). Leave empty to use package.json version.'
8+
required: false
9+
type: string
10+
dry_run:
11+
description: 'Dry run (build and test but do not create release).'
12+
required: false
13+
type: boolean
14+
default: false
15+
16+
jobs:
17+
# Build CLI for each platform.
18+
build:
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- os: macos-latest
24+
platform: darwin-arm64
25+
runs-on: macos-latest
26+
- os: ubuntu-latest
27+
platform: linux-x64
28+
runs-on: ubuntu-latest
29+
30+
runs-on: ${{ matrix.runs-on }}
31+
32+
steps:
33+
- name: Checkout code
34+
uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0
37+
38+
- name: Setup Node.js and pnpm
39+
uses: ./.github/actions/setup-node-pnpm
40+
41+
- name: Get version
42+
id: version
43+
run: |
44+
if [ -n "${{ inputs.version }}" ]; then
45+
VERSION="${{ inputs.version }}"
46+
else
47+
VERSION=$(node -p "require('./apps/cli/package.json').version")
48+
fi
49+
echo "version=$VERSION" >> $GITHUB_OUTPUT
50+
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
51+
echo "Using version: $VERSION"
52+
53+
- name: Build extension bundle
54+
run: pnpm bundle
55+
56+
- name: Build CLI
57+
run: pnpm --filter @roo-code/cli build
58+
59+
- name: Create release tarball
60+
id: tarball
61+
env:
62+
VERSION: ${{ steps.version.outputs.version }}
63+
PLATFORM: ${{ matrix.platform }}
64+
run: |
65+
RELEASE_DIR="roo-cli-${PLATFORM}"
66+
TARBALL="roo-cli-${PLATFORM}.tar.gz"
67+
68+
# Clean up any previous build.
69+
rm -rf "$RELEASE_DIR"
70+
rm -f "$TARBALL"
71+
72+
# Create directory structure.
73+
mkdir -p "$RELEASE_DIR/bin"
74+
mkdir -p "$RELEASE_DIR/lib"
75+
mkdir -p "$RELEASE_DIR/extension"
76+
77+
# Copy CLI dist files.
78+
echo "Copying CLI files..."
79+
cp -r apps/cli/dist/* "$RELEASE_DIR/lib/"
80+
81+
# Create package.json for npm install.
82+
echo "Creating package.json..."
83+
node -e "
84+
const pkg = require('./apps/cli/package.json');
85+
const newPkg = {
86+
name: '@roo-code/cli',
87+
version: '$VERSION',
88+
type: 'module',
89+
dependencies: {
90+
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
91+
'@trpc/client': pkg.dependencies['@trpc/client'],
92+
'commander': pkg.dependencies.commander,
93+
'fuzzysort': pkg.dependencies.fuzzysort,
94+
'ink': pkg.dependencies.ink,
95+
'p-wait-for': pkg.dependencies['p-wait-for'],
96+
'react': pkg.dependencies.react,
97+
'superjson': pkg.dependencies.superjson,
98+
'zustand': pkg.dependencies.zustand
99+
}
100+
};
101+
console.log(JSON.stringify(newPkg, null, 2));
102+
" > "$RELEASE_DIR/package.json"
103+
104+
# Copy extension bundle.
105+
echo "Copying extension bundle..."
106+
cp -r src/dist/* "$RELEASE_DIR/extension/"
107+
108+
# Add package.json to extension directory for CommonJS.
109+
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
110+
111+
# Find and copy ripgrep binary.
112+
echo "Looking for ripgrep binary..."
113+
RIPGREP_PATH=$(find node_modules -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
114+
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
115+
echo "Found ripgrep at: $RIPGREP_PATH"
116+
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
117+
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
118+
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
119+
mkdir -p "$RELEASE_DIR/bin"
120+
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
121+
chmod +x "$RELEASE_DIR/bin/rg"
122+
else
123+
echo "Warning: ripgrep binary not found"
124+
fi
125+
126+
# Create the wrapper script
127+
echo "Creating wrapper script..."
128+
printf '%s\n' '#!/usr/bin/env node' \
129+
'' \
130+
"import { fileURLToPath } from 'url';" \
131+
"import { dirname, join } from 'path';" \
132+
'' \
133+
'const __filename = fileURLToPath(import.meta.url);' \
134+
'const __dirname = dirname(__filename);' \
135+
'' \
136+
'// Set environment variables for the CLI' \
137+
"process.env.ROO_CLI_ROOT = join(__dirname, '..');" \
138+
"process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');" \
139+
"process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');" \
140+
'' \
141+
'// Import and run the actual CLI' \
142+
"await import(join(__dirname, '..', 'lib', 'index.js'));" \
143+
> "$RELEASE_DIR/bin/roo"
144+
145+
chmod +x "$RELEASE_DIR/bin/roo"
146+
147+
# Create empty .env file.
148+
touch "$RELEASE_DIR/.env"
149+
150+
# Create tarball.
151+
echo "Creating tarball..."
152+
tar -czvf "$TARBALL" "$RELEASE_DIR"
153+
154+
# Clean up release directory.
155+
rm -rf "$RELEASE_DIR"
156+
157+
# Create checksum.
158+
if command -v sha256sum &> /dev/null; then
159+
sha256sum "$TARBALL" > "${TARBALL}.sha256"
160+
elif command -v shasum &> /dev/null; then
161+
shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
162+
fi
163+
164+
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
165+
echo "Created: $TARBALL"
166+
ls -la "$TARBALL"
167+
168+
- name: Verify tarball
169+
env:
170+
PLATFORM: ${{ matrix.platform }}
171+
run: |
172+
TARBALL="roo-cli-${PLATFORM}.tar.gz"
173+
174+
# Create temp directory for verification.
175+
VERIFY_DIR=$(mktemp -d)
176+
177+
# Extract and verify structure.
178+
tar -xzf "$TARBALL" -C "$VERIFY_DIR"
179+
180+
echo "Verifying tarball contents..."
181+
ls -la "$VERIFY_DIR/roo-cli-${PLATFORM}/"
182+
183+
# Check required files exist.
184+
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/bin/roo" || { echo "Missing bin/roo"; exit 1; }
185+
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/lib/index.js" || { echo "Missing lib/index.js"; exit 1; }
186+
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/package.json" || { echo "Missing package.json"; exit 1; }
187+
test -d "$VERIFY_DIR/roo-cli-${PLATFORM}/extension" || { echo "Missing extension directory"; exit 1; }
188+
189+
echo "Tarball verification passed!"
190+
191+
# Cleanup.
192+
rm -rf "$VERIFY_DIR"
193+
194+
- name: Upload artifact
195+
uses: actions/upload-artifact@v4
196+
with:
197+
name: cli-${{ matrix.platform }}
198+
path: |
199+
roo-cli-${{ matrix.platform }}.tar.gz
200+
roo-cli-${{ matrix.platform }}.tar.gz.sha256
201+
retention-days: 7
202+
203+
# Create GitHub release with all platform artifacts.
204+
release:
205+
needs: build
206+
runs-on: ubuntu-latest
207+
if: ${{ !inputs.dry_run }}
208+
permissions:
209+
contents: write
210+
211+
steps:
212+
- name: Checkout code
213+
uses: actions/checkout@v4
214+
215+
- name: Get version
216+
id: version
217+
run: |
218+
if [ -n "${{ inputs.version }}" ]; then
219+
VERSION="${{ inputs.version }}"
220+
else
221+
VERSION=$(node -p "require('./apps/cli/package.json').version")
222+
fi
223+
echo "version=$VERSION" >> $GITHUB_OUTPUT
224+
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
225+
226+
- name: Download all artifacts
227+
uses: actions/download-artifact@v4
228+
with:
229+
path: artifacts
230+
231+
- name: Prepare release files
232+
run: |
233+
mkdir -p release
234+
find artifacts -name "*.tar.gz" -exec cp {} release/ \;
235+
find artifacts -name "*.sha256" -exec cp {} release/ \;
236+
ls -la release/
237+
238+
- name: Extract changelog
239+
id: changelog
240+
env:
241+
VERSION: ${{ steps.version.outputs.version }}
242+
run: |
243+
CHANGELOG_FILE="apps/cli/CHANGELOG.md"
244+
245+
if [ -f "$CHANGELOG_FILE" ]; then
246+
# Extract content between version headers.
247+
CONTENT=$(awk -v version="$VERSION" '
248+
BEGIN { found = 0; content = ""; target = "[" version "]" }
249+
/^## \[/ {
250+
if (found) { exit }
251+
if (index($0, target) > 0) { found = 1; next }
252+
}
253+
found { content = content $0 "\n" }
254+
END { print content }
255+
' "$CHANGELOG_FILE")
256+
257+
if [ -n "$CONTENT" ]; then
258+
echo "Found changelog content"
259+
echo "content<<EOF" >> $GITHUB_OUTPUT
260+
echo "$CONTENT" >> $GITHUB_OUTPUT
261+
echo "EOF" >> $GITHUB_OUTPUT
262+
else
263+
echo "No changelog content found for version $VERSION"
264+
echo "content=" >> $GITHUB_OUTPUT
265+
fi
266+
else
267+
echo "No changelog file found"
268+
echo "content=" >> $GITHUB_OUTPUT
269+
fi
270+
271+
- name: Generate checksums summary
272+
id: checksums
273+
run: |
274+
echo "checksums<<EOF" >> $GITHUB_OUTPUT
275+
cat release/*.sha256 >> $GITHUB_OUTPUT
276+
echo "EOF" >> $GITHUB_OUTPUT
277+
278+
- name: Check for existing release
279+
id: check_release
280+
env:
281+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
282+
TAG: ${{ steps.version.outputs.tag }}
283+
run: |
284+
if gh release view "$TAG" &> /dev/null; then
285+
echo "exists=true" >> $GITHUB_OUTPUT
286+
else
287+
echo "exists=false" >> $GITHUB_OUTPUT
288+
fi
289+
290+
- name: Delete existing release
291+
if: steps.check_release.outputs.exists == 'true'
292+
env:
293+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
294+
TAG: ${{ steps.version.outputs.tag }}
295+
run: |
296+
echo "Deleting existing release $TAG..."
297+
gh release delete "$TAG" --yes || true
298+
git push origin ":refs/tags/$TAG" || true
299+
300+
- name: Create GitHub Release
301+
env:
302+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
303+
VERSION: ${{ steps.version.outputs.version }}
304+
TAG: ${{ steps.version.outputs.tag }}
305+
CHANGELOG_CONTENT: ${{ steps.changelog.outputs.content }}
306+
CHECKSUMS: ${{ steps.checksums.outputs.checksums }}
307+
run: |
308+
NOTES_FILE=$(mktemp)
309+
310+
if [ -n "$CHANGELOG_CONTENT" ]; then
311+
echo "## What's New" >> "$NOTES_FILE"
312+
echo "" >> "$NOTES_FILE"
313+
echo "$CHANGELOG_CONTENT" >> "$NOTES_FILE"
314+
echo "" >> "$NOTES_FILE"
315+
fi
316+
317+
echo "## Installation" >> "$NOTES_FILE"
318+
echo "" >> "$NOTES_FILE"
319+
echo '```bash' >> "$NOTES_FILE"
320+
echo "curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
321+
echo '```' >> "$NOTES_FILE"
322+
echo "" >> "$NOTES_FILE"
323+
echo "Or install a specific version:" >> "$NOTES_FILE"
324+
echo '```bash' >> "$NOTES_FILE"
325+
echo "ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
326+
echo '```' >> "$NOTES_FILE"
327+
echo "" >> "$NOTES_FILE"
328+
echo "## Requirements" >> "$NOTES_FILE"
329+
echo "" >> "$NOTES_FILE"
330+
echo "- Node.js 20 or higher" >> "$NOTES_FILE"
331+
echo "- macOS Apple Silicon (M1/M2/M3/M4) or Linux x64" >> "$NOTES_FILE"
332+
echo "" >> "$NOTES_FILE"
333+
echo "## Usage" >> "$NOTES_FILE"
334+
echo "" >> "$NOTES_FILE"
335+
echo '```bash' >> "$NOTES_FILE"
336+
echo "# Run a task" >> "$NOTES_FILE"
337+
echo 'roo "What is this project?"' >> "$NOTES_FILE"
338+
echo "" >> "$NOTES_FILE"
339+
echo "# See all options" >> "$NOTES_FILE"
340+
echo "roo --help" >> "$NOTES_FILE"
341+
echo '```' >> "$NOTES_FILE"
342+
echo "" >> "$NOTES_FILE"
343+
echo "## Platform Support" >> "$NOTES_FILE"
344+
echo "" >> "$NOTES_FILE"
345+
echo "This release includes binaries for:" >> "$NOTES_FILE"
346+
echo '- `roo-cli-darwin-arm64.tar.gz` - macOS Apple Silicon (M1/M2/M3)' >> "$NOTES_FILE"
347+
echo '- `roo-cli-linux-x64.tar.gz` - Linux x64' >> "$NOTES_FILE"
348+
echo "" >> "$NOTES_FILE"
349+
echo "## Checksums" >> "$NOTES_FILE"
350+
echo "" >> "$NOTES_FILE"
351+
echo '```' >> "$NOTES_FILE"
352+
echo "$CHECKSUMS" >> "$NOTES_FILE"
353+
echo '```' >> "$NOTES_FILE"
354+
355+
gh release create "$TAG" \
356+
--title "Roo Code CLI v$VERSION" \
357+
--notes-file "$NOTES_FILE" \
358+
--prerelease \
359+
release/*
360+
361+
rm -f "$NOTES_FILE"
362+
echo "Release created: https://github.com/${{ github.repository }}/releases/tag/$TAG"
363+
364+
# Summary job for dry runs
365+
summary:
366+
needs: build
367+
runs-on: ubuntu-latest
368+
if: ${{ inputs.dry_run }}
369+
370+
steps:
371+
- name: Download all artifacts
372+
uses: actions/download-artifact@v4
373+
with:
374+
path: artifacts
375+
376+
- name: Show build summary
377+
run: |
378+
echo "## Dry Run Complete" >> $GITHUB_STEP_SUMMARY
379+
echo "" >> $GITHUB_STEP_SUMMARY
380+
echo "The following artifacts were built:" >> $GITHUB_STEP_SUMMARY
381+
echo "" >> $GITHUB_STEP_SUMMARY
382+
find artifacts -name "*.tar.gz" | while read f; do
383+
SIZE=$(ls -lh "$f" | awk '{print $5}')
384+
echo "- $(basename $f) ($SIZE)" >> $GITHUB_STEP_SUMMARY
385+
done
386+
echo "" >> $GITHUB_STEP_SUMMARY
387+
echo "### Checksums" >> $GITHUB_STEP_SUMMARY
388+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
389+
cat artifacts/*/*.sha256 >> $GITHUB_STEP_SUMMARY
390+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)