continuedev/continue
30 workflows · maturity 67% · 12 patterns · GitHub ↗
Practices
✓ Matrix✓ Permissions○ Security scan○ AI review✓ Cache✓ Concurrency✓ Reusable workflows
Detected patterns
Security dimensions
Workflows (30)
auto-assign-issue .github/workflows/auto-assign-issue.yaml
View raw YAML
name: Issue assignment
on:
issues:
types: [opened]
jobs:
auto-assign:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: "Auto-assign issue"
uses: pozil/auto-assign-issue@v2
with:
repo-token: ${{ secrets.CI_GITHUB_TOKEN }}
assignees: Patrick-Erichsen,tomasz-stefaniak,RomneyDa,tingwai,uinstinct
numOfAssignee: 1
# - name: "Add default labels"
# uses: actions-ecosystem/action-add-labels@v1
# with:
# github_token: ${{ secrets.GITHUB_TOKEN }}
# labels: |
# "needs-triage"
auto-fix-failed-tests perms .github/workflows/auto-fix-failed-tests.yml
View raw YAML
name: Auto Fix Failed Tests
on:
workflow_run:
workflows: ["PR Checks", "CLI PR Checks"]
types:
- completed
permissions:
contents: write
pull-requests: write
issues: write
actions: read
jobs:
fix-failed-tests:
# Only run if the workflow failed
# DISABLED: Remove 'false && ' on the next line to enable auto-fixing
if: false && github.event.workflow_run.conclusion == 'failure'
runs-on: ubuntu-latest
steps:
- name: Get workflow run details
id: workflow-details
uses: actions/github-script@v8
with:
script: |
const workflowRun = context.payload.workflow_run;
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: workflowRun.id
});
// Find all failed jobs since we're only monitoring specific test workflows
const failedJobs = jobs.jobs.filter(job => job.conclusion === 'failure');
if (failedJobs.length === 0) {
core.info('No failed jobs found');
return null;
}
core.setOutput('has_failed_tests', 'true');
core.setOutput('workflow_name', workflowRun.name);
core.setOutput('workflow_run_id', workflowRun.id);
core.setOutput('head_branch', workflowRun.head_branch);
core.setOutput('head_sha', workflowRun.head_sha);
core.setOutput('failed_jobs', JSON.stringify(failedJobs.map(j => j.name)));
return failedJobs;
- name: Get job logs for failed tests
if: steps.workflow-details.outputs.has_failed_tests == 'true'
id: get-logs
uses: actions/github-script@v8
with:
script: |
const workflowRunId = ${{ github.event.workflow_run.id }};
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: workflowRunId
});
let errorLogs = '';
for (const job of jobs.jobs) {
if (job.conclusion === 'failure') {
try {
const { data: logData } = await github.rest.actions.downloadJobLogsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
job_id: job.id
});
errorLogs += `\n\n=== Job: ${job.name} ===\n`;
errorLogs += logData;
} catch (error) {
core.warning(`Could not fetch logs for job ${job.name}: ${error.message}`);
}
}
}
// Store logs in environment file for next step
const fs = require('fs');
fs.writeFileSync('/tmp/test_failure_logs.txt', errorLogs);
core.setOutput('has_logs', errorLogs.length > 0 ? 'true' : 'false');
- name: Checkout repository
if: steps.workflow-details.outputs.has_failed_tests == 'true'
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: ${{ steps.workflow-details.outputs.head_sha }}
- name: Setup Node.js
if: steps.workflow-details.outputs.has_failed_tests == 'true'
uses: actions/setup-node@v6
with:
node-version: "20"
- name: Install Continue CLI globally
if: steps.workflow-details.outputs.has_failed_tests == 'true'
run: npm i -g @continuedev/cli
- name: Start remote session to fix failed tests
if: steps.workflow-details.outputs.has_failed_tests == 'true'
id: remote-session
env:
CONTINUE_API_KEY: ${{ secrets.CONTINUE_API_KEY }}
run: |
# Create a detailed prompt for fixing the failed tests
cat > /tmp/fix_tests_prompt.txt << 'PROMPT_EOF'
🔧 **Auto Test Fix Request**
The following tests failed in workflow "${{ steps.workflow-details.outputs.workflow_name }}" (Run ID: ${{ steps.workflow-details.outputs.workflow_run_id }}):
**Failed Jobs:** ${{ steps.workflow-details.outputs.failed_jobs }}
**Branch:** ${{ steps.workflow-details.outputs.head_branch }}
**Commit:** ${{ steps.workflow-details.outputs.head_sha }}
**Your Task:**
1. Analyze the test failure logs and error messages
2. Identify the root cause of the test failures
3. Fix the failing tests by updating the test code or the underlying implementation
4. Ensure all tests pass after your changes
5. Commit your fixes with a descriptive message
**Test Failure Context:**
Please examine the repository structure, run the failing tests locally to understand the errors, and implement appropriate fixes.
Focus on:
- Understanding what the tests are trying to validate
- Identifying why they're failing (code changes, environment issues, test logic errors)
- Making minimal, targeted fixes that address the root cause
- Ensuring the fixes don't break other functionality
Please start by examining the failing tests and their error messages, then proceed with the necessary fixes.
PROMPT_EOF
echo "Starting Continue CLI remote session for test fixes..."
echo "Prompt content:"
cat /tmp/fix_tests_prompt.txt
# Start remote session and capture JSON output
SESSION_OUTPUT=$(cat /tmp/fix_tests_prompt.txt | cn remote -s --branch ${{ steps.workflow-details.outputs.head_branch }})
echo "Raw session output: $SESSION_OUTPUT"
# Extract URL from JSON output
SESSION_URL=$(echo "$SESSION_OUTPUT" | jq -r '.url // empty')
if [ -z "$SESSION_URL" ] || [ "$SESSION_URL" = "null" ]; then
echo "Failed to extract session URL from output: $SESSION_OUTPUT"
exit 1
fi
echo "session_url=$SESSION_URL" >> $GITHUB_OUTPUT
echo "✅ Started remote session: $SESSION_URL"
- name: Log session details
if: steps.workflow-details.outputs.has_failed_tests == 'true'
run: |
echo "✅ Successfully started auto-fix session for failed tests"
echo "Workflow: ${{ steps.workflow-details.outputs.workflow_name }}"
echo "Run ID: ${{ steps.workflow-details.outputs.workflow_run_id }}"
echo "Branch: ${{ steps.workflow-details.outputs.head_branch }}"
echo "Session URL: ${{ steps.remote-session.outputs.session_url }}"
echo "Failed jobs: ${{ steps.workflow-details.outputs.failed_jobs }}"
auto-release .github/workflows/auto-release.yml
View raw YAML
name: Create Automatic Release
on:
push:
branches:
- nate/auto-main-release-draft
# Not using this now because making drafts was just noisy. Will be useful when we are ready for automated releases.
# schedule:
# - cron: "0 17 * * 1,3,5" # Run at 9am PST (17:00 UTC) on Monday, Wednesday, Friday
workflow_dispatch: # Keep manual trigger option
jobs:
create-vscode-release:
runs-on: ubuntu-latest
permissions:
contents: write # Needed for creating releases
steps:
- uses: actions/checkout@v6
- name: Get version from package.json
id: get_version
run: |
# Read version from package.json and add -vscode suffix
version=$(node -p "require('./extensions/vscode/package.json').version")
new_version="v${version}-vscode"
echo "New version will be: $new_version"
echo "NEW_VERSION=$new_version" >> $GITHUB_ENV
- name: Create Release
env:
GH_TOKEN: ${{ github.token }}
run: |
# Create a new draft release with auto-generated release notes
gh release create "$NEW_VERSION" \
--generate-notes \
--title "$NEW_VERSION" \
--draft \
--latest \
--prerelease
create-jetbrains-release:
runs-on: ubuntu-latest
permissions:
contents: write # Needed for creating releases
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get version from gradle.properties
id: get_version
run: |
# Read version from gradle.properties and add -jetbrains suffix
version=$(grep '^pluginVersion=' extensions/intellij/gradle.properties | cut -d'=' -f2)
new_version="v${version}-jetbrains"
echo "New version will be: $new_version"
echo "NEW_VERSION=$new_version" >> $GITHUB_ENV
- name: Create Release
env:
GH_TOKEN: ${{ github.token }}
run: |
# Create a new draft release with auto-generated release notes
gh release create "$NEW_VERSION" \
--generate-notes \
--title "$NEW_VERSION" \
--draft \
--latest \
--prerelease
cla perms .github/workflows/cla.yaml
View raw YAML
name: "CLA Assistant"
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, closed, synchronize]
permissions:
actions: write
contents: write
pull-requests: write
statuses: write
jobs:
CLAAssistant:
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
steps:
- name: "CLA Assistant"
if: (contains(github.event.comment.body, 'recheck') || contains(github.event.comment.body, 'I have read the CLA Document and I hereby sign the CLA')) || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
path-to-signatures: "signatures/version1/cla.json"
path-to-document: "https://github.com/continuedev/continue/blob/main/CLA.md"
branch: cla-signatures
# Bots and CLAs signed outside of GitHub
allowlist: dependabot[bot],fbricon,panyamkeerthana,Jazzcort,owtaylor,halfline,agent@continue.dev,action@github.com,continue[bot],snyk-bot,noreply@continue.dev,google-labs-jules[bot]
signed-commit-message: "CLA signed in $pullRequestNo"
cli-pr-checks matrix perms .github/workflows/cli-pr-checks.yml
View raw YAML
name: CLI PR Checks
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
track-rerun:
runs-on: ubuntu-latest
if: github.run_attempt > 1
steps:
- uses: actions/checkout@v6
- name: Track workflow rerun
uses: ./.github/actions/track-rerun
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
cache: "npm"
cache-dependency-path: extensions/cli/package-lock.json
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Build core
run: |
cd core
npm run build
- name: Install dependencies
run: |
cd extensions/cli
npm ci --include=optional
- name: Run linting
run: |
cd extensions/cli
npm run lint
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22, 24]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
- name: Cache CLI node_modules
uses: actions/cache@v5
with:
path: extensions/cli/node_modules
key: ${{ runner.os }}-node${{ matrix.node-version }}-cli-modules-${{ hashFiles('extensions/cli/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node${{ matrix.node-version }}-cli-modules-
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Build core
run: |
cd core
npm run build
- name: Install dependencies
run: |
cd extensions/cli
npm ci --include=optional
- name: Build
run: |
cd extensions/cli
npm run build
- name: Run smoke tests
run: |
cd extensions/cli
npm run test:smoke
- name: Run tests
run: |
cd extensions/cli
npm test
# e2e tests are failing on Windows specifically - likely due to stdout flush issues
- name: Run e2e tests
if: matrix.os != 'windows-latest'
run: |
cd extensions/cli
npm run test:e2e
smoke-api:
# Only runs when secrets are available (not on fork PRs)
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
cache: "npm"
cache-dependency-path: extensions/cli/package-lock.json
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Build core
run: |
cd core
npm run build
- name: Install dependencies
run: |
cd extensions/cli
npm ci --include=optional
- name: Build
run: |
cd extensions/cli
npm run build
- name: Run smoke API tests
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CONTINUE_API_KEY: ${{ secrets.CONTINUE_API_KEY }}
run: |
cd extensions/cli
npm run test:smoke-api
# GitHub does not have a way of requiring that all checks pass (you must manually select each job)
# This action at least lets us manage the list of required tests via source control
# so that creators of new jobs can add them to this list
require-all-checks-to-pass-cli:
if: always()
runs-on: ubuntu-latest
needs:
- lint
- test
- smoke-api
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
# smoke-api is allowed to skip for fork PRs that lack secrets
allowed-skips: smoke-api
jobs: ${{ toJSON(needs) }}
continue-agents matrix perms .github/workflows/continue-agents.yml
View raw YAML
name: Continue Agents
on:
workflow_call:
inputs:
agents-path:
description: 'Path to agents folder'
required: false
default: '.continue/agents'
type: string
secrets:
ANTHROPIC_API_KEY:
description: 'Anthropic API key for Claude'
required: true
permissions:
contents: write
checks: write
pull-requests: write
jobs:
discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.discover.outputs.matrix }}
has-agents: ${{ steps.discover.outputs.has_agents }}
steps:
- uses: actions/checkout@v6
- name: Discover agents
id: discover
run: |
AGENTS_DIR="${{ inputs.agents-path }}"
if [ -d "$AGENTS_DIR" ]; then
# Use -sc for compact single-line JSON (required for GitHub Actions output)
FILES=$(find "$AGENTS_DIR" -name "*.md" -type f 2>/dev/null | jq -R . | jq -sc .)
COUNT=$(echo "$FILES" | jq 'length')
HAS_AGENTS=$([[ $COUNT -gt 0 ]] && echo "true" || echo "false")
else
FILES="[]"
COUNT=0
HAS_AGENTS="false"
fi
echo "matrix=$FILES" >> $GITHUB_OUTPUT
echo "has_agents=$HAS_AGENTS" >> $GITHUB_OUTPUT
echo "Found $COUNT agent(s)"
run-agent:
needs: discover
if: needs.discover.outputs.has-agents == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
agent: ${{ fromJson(needs.discover.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
- name: Install Continue CLI
run: npm i -g @continuedev/cli
- name: Extract agent name
id: agent-name
run: |
AGENT_FILE="${{ matrix.agent }}"
AGENT_NAME=$(basename "$AGENT_FILE" .md)
echo "name=$AGENT_NAME" >> $GITHUB_OUTPUT
- name: Create Check Run
id: check
uses: actions/github-script@v8
env:
AGENT_NAME: ${{ steps.agent-name.outputs.name }}
with:
script: |
const { data: check } = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: `Continue: ${process.env.AGENT_NAME}`,
head_sha: context.sha,
status: 'in_progress',
started_at: new Date().toISOString(),
});
core.setOutput('id', check.id);
- name: Run agent
id: run
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ github.token }}
run: |
AGENT_FILE="${{ matrix.agent }}"
# Run agent in non-interactive mode (-p flag)
if OUTPUT=$(cn -p --agent "$AGENT_FILE" 2>&1); then
echo "success=true" >> $GITHUB_OUTPUT
echo "output<<EOF" >> $GITHUB_OUTPUT
echo "$OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "✅ Agent completed successfully"
echo ""
echo "--- Agent Output ---"
echo "$OUTPUT"
else
echo "success=false" >> $GITHUB_OUTPUT
echo "error<<EOF" >> $GITHUB_OUTPUT
echo "$OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "❌ Agent failed"
echo ""
echo "--- Agent Output ---"
echo "$OUTPUT"
fi
- name: Write job summary
if: always()
env:
AGENT_OUTPUT: ${{ steps.run.outputs.output }}
AGENT_ERROR: ${{ steps.run.outputs.error }}
AGENT_SUCCESS: ${{ steps.run.outputs.success }}
AGENT_NAME: ${{ steps.agent-name.outputs.name }}
run: |
echo "## 🤖 Agent: $AGENT_NAME" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$AGENT_SUCCESS" == "true" ]; then
echo "✅ **Status:** Completed successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Output" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
printf '%s\n' "$AGENT_OUTPUT" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
else
echo "❌ **Status:** Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Error" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
printf '%s\n' "$AGENT_ERROR" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
- name: Fail if agent failed
if: steps.run.outputs.success != 'true'
run: exit 1
- name: Update Check Run
if: always()
uses: actions/github-script@v8
env:
AGENT_OUTPUT: ${{ steps.run.outputs.output }}
AGENT_ERROR: ${{ steps.run.outputs.error }}
AGENT_SUCCESS: ${{ steps.run.outputs.success }}
CHECK_RUN_ID: ${{ steps.check.outputs.id }}
with:
script: |
const success = process.env.AGENT_SUCCESS === 'true';
const output = process.env.AGENT_OUTPUT || '';
const error = process.env.AGENT_ERROR || '';
await github.rest.checks.update({
owner: context.repo.owner,
repo: context.repo.repo,
check_run_id: parseInt(process.env.CHECK_RUN_ID, 10),
status: 'completed',
conclusion: success ? 'success' : 'failure',
completed_at: new Date().toISOString(),
output: {
title: success ? 'Agent completed' : 'Agent failed',
summary: success
? `Agent completed successfully.\n\n<details><summary>Output</summary>\n\n\`\`\`\n${output.slice(0, 60000)}\n\`\`\`\n</details>`
: `Agent failed.\n\n\`\`\`\n${error.slice(0, 60000)}\n\`\`\``,
},
});
delete-stale-branches perms .github/workflows/delete-stale-branches.yaml
View raw YAML
name: Delete Stale Branches
on:
schedule:
- cron: "0 6 * * 1-5"
workflow_dispatch:
permissions:
issues: write
contents: write
jobs:
stale_branches:
runs-on: ubuntu-latest
steps:
- name: Stale Branches
uses: crs-k/stale-branches@v8.2.2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
days-before-stale: 59
days-before-delete: 60
pr-check: true
ignore-issue-interaction: true
branches-filter-regex: "^(?!cla-signatures$).*"
jetbrains-release matrix .github/workflows/jetbrains-release.yaml
View raw YAML
# GitHub Actions Workflow created for handling the release process based on the draft release prepared with the Build workflow.
# Running the publishPlugin task requires all following secrets to be provided: PUBLISH_TOKEN, PRIVATE_KEY, PRIVATE_KEY_PASSWORD, CERTIFICATE_CHAIN.
# See https://plugins.jetbrains.com/docs/intellij/plugin-signing.html for more information.
name: JetBrains Release
on:
release:
types: [prereleased]
workflow_dispatch:
inputs:
build_only:
description: "If true, only build the extension for the given channels, don't publish"
required: true
default: "true"
eap_channel:
description: "If true, build/publish the extension to the EAP channel"
required: true
default: "true"
stable_channel:
description: "If true, build/publish the extension to the Stable channel"
required: true
default: "true"
defaults:
run:
working-directory: extensions/intellij
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
check_release_name:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: check
working-directory: .
run: |
if [[ "${{ github.event.release.tag_name }}" == v1.0.*-jetbrains ]]; then
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi
# bump-version:
# runs-on: ubuntu-latest
# needs:
# - check_release_name
# if: github.event_name != 'workflow_dispatch' || github.event.inputs.eap_channel == 'true' || github.event.inputs.stable_channel == 'true'
# permissions:
# contents: write
# pull-requests: write
# steps:
# # 0. Setup git
# - name: Checkout
# uses: actions/checkout@v6
# - name: Set up Git
# run: |
# git config --local user.email "action@github.com"
# git config --local user.name "GitHub Action"
# - name: Create PR branch
# run: |
# BRANCH_NAME="chore/bump-jetbrains-version-$(date +%Y%m%d-%H%M%S)"
# git checkout -b $BRANCH_NAME
# echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
# - name: Bump version in gradle.properties
# run: |
# awk '/pluginVersion=/{split($0,a,"="); split(a[2],b,"."); b[3]+=1; printf "%s=%s.%s.%s\n",a[1],b[1],b[2],b[3];next}1' gradle.properties > tmp && mv tmp gradle.properties
# rm -rf tmp
# NEW_VERSION=$(grep 'pluginVersion=' gradle.properties | cut -d'=' -f2)
# echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
# - name: Create Pull Request
# uses: peter-evans/create-pull-request@v7
# with:
# token: ${{ secrets.CI_GITHUB_TOKEN }}
# commit-message: "chore: bump jetbrains extension version to ${{ env.NEW_VERSION }}"
# title: "chore: bump jetbrains extension version to ${{ env.NEW_VERSION }}"
# body: |
# Automated PR to bump the JetBrains extension version after successful pre-release publication.
# - Bumped version in extensions/intellij/gradle.properties to ${{ env.NEW_VERSION }}
# branch: ${{ env.BRANCH_NAME }}
# base: main
# delete-branch: true
# Prepare and publish the plugin to JetBrains Marketplace repository
build:
needs: check_release_name
if: needs.check_release_name.outputs.should_run == 'true' || github.event_name == 'workflow_dispatch'
name: Build Plugin
runs-on: macos-latest
permissions:
contents: write
pull-requests: write
steps:
# Check out current repository
- name: Fetch Sources
uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
- name: Import Apple certificate
uses: apple-actions/import-codesign-certs@v6
with:
keychain: ${{ github.run_id }}
keychain-password: ${{ github.run_id }}
p12-file-base64: ${{ secrets.APPLE_CERT_DATA }}
p12-password: ${{ secrets.APPLE_CERT_PASSWORD }}
# Validate wrapper
- name: Gradle Wrapper Validation
uses: gradle/actions/wrapper-validation@v6
# # Set up Java environment for the next steps
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 17
# # Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
gradle-home-cache-cleanup: true
# Set environment variables
- name: Export Properties
id: properties
shell: bash
run: |
PROPERTIES="$(./gradlew properties --console=plain -q)"
VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
# CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
CHANGELOG=""
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "pluginVerifierHomeDir=~/.pluginVerifier" >> $GITHUB_OUTPUT
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
./gradlew printProductsReleases # prepare list of IDEs for Plugin Verifier
# # Setup Node.js
- name: Use Node.js from .nvmrc
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Cache core node_modules
uses: actions/cache@v5
with:
path: core/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('core/package-lock.json') }}
- name: Cache binary node_modules
uses: actions/cache@v5
with:
path: binary/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('binary/package-lock.json') }}
- name: Cache gui node_modules
uses: actions/cache@v5
with:
path: gui/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('gui/package-lock.json') }}
- name: Build packages (Unix)
run: cd ../.. && node ./scripts/build-packages.js
# npm install core
- name: Install core node_modules
run: |
cd ../../core
npm ci
# npm install gui
- name: Install gui node_modules and build
run: |
cd ../../gui
npm ci
npm run build
env:
NODE_OPTIONS: "--max-old-space-size=8192"
# Run prepackage.js script
- name: Run prepackage script
run: |
cd ../../extensions/vscode
npm ci
npm run prepackage
env:
# https://github.com/microsoft/vscode-ripgrep/issues/9#issuecomment-643965333
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }}
# npm install binary
- name: Install binary node_modules
run: |
cd ../../binary
npm ci
# Build binaries
- name: Build the binaries
run: |
cd ../../binary
npm run build
# - name: Code sign darwin binaries
# run: |
# echo "Signing executable with keychain: ${{ github.run_id }}"
# codesign --sign - ../../binary/bin/darwin-x64/continue-binary
# codesign --sign - ../../binary/bin/darwin-arm64/continue-binary
# - name: Sign darwin-arm64 binary
# uses: lando/code-sign-action@v2
# with:
# file: ./binary/bin/darwin-arm64/continue-binary
# certificate-data: ${{ secrets.APPLE_CERT_DATA }}
# certificate-password: ${{ secrets.APPLE_CERT_PASSWORD }}
# apple-notary-user: ${{ secrets.APPLE_NOTARY_USER }}
# apple-notary-password: ${{ secrets.APPLE_NOTARY_PASSWORD }}
# apple-notary-tool: altool
# apple-team-id: 43XFLY66ZD
# apple-product-id: dev.continue.continue-binary
# options: --options runtime --entitlements entitlements.xml
# Build the plugin if not publishing
- name: Build EAP Plugin (no publish)
if: github.event_name != 'release' && github.event.inputs.eap_channel == 'true' && github.event.inputs.build_only == 'true'
env:
PUBLISH_TOKEN: ${{ secrets.JETBRAINS_PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
RELEASE_CHANNEL: eap
run: ./gradlew buildPlugin --info --stacktrace
- name: Build Stable Plugin (no publish)
if: github.event_name != 'release' && github.event.inputs.stable_channel == 'true' && github.event.inputs.build_only == 'true'
env:
PUBLISH_TOKEN: ${{ secrets.JETBRAINS_PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
RELEASE_CHANNEL: default
run: ./gradlew buildPlugin --info --stacktrace
# Publish the plugin to JetBrains Marketplace
- name: Publish EAP Plugin
if: github.event_name == 'release' || (github.event.inputs.eap_channel == 'true' && github.event.inputs.build_only != 'true')
continue-on-error: true
env:
PUBLISH_TOKEN: ${{ secrets.JETBRAINS_PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
RELEASE_CHANNEL: eap
run: ./gradlew publishPlugin --info --stacktrace
- name: Publish Stable Plugin
if: github.event_name == 'release' || (github.event.inputs.stable_channel == 'true' && github.event.inputs.build_only != 'true')
continue-on-error: true
env:
PUBLISH_TOKEN: ${{ secrets.JETBRAINS_PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
RELEASE_CHANNEL: default
run: ./gradlew publishPlugin --info --stacktrace
# Prepare plugin archive content for creating artifact
- name: Prepare Plugin Artifact
id: artifact
shell: bash
run: |
cd ../../extensions/intellij/build/distributions
echo "Contents of distributions folder:"
ls
echo "---"
FILENAME=$(ls continue-intellij-extension-*.zip | head -1)
echo "Filename=${FILENAME}"
unzip "$FILENAME" -d content
echo "filename=${FILENAME%.????}" >> $GITHUB_OUTPUT
# Store already-built plugin as an artifact for downloading
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: ${{ steps.artifact.outputs.filename }}
path: ./extensions/intellij/build/distributions/content/*/*
# Upload binaries as artifacts
- name: Upload artifact (darwin-arm64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-darwin-arm64
path: ./binary/bin/darwin-arm64/
- name: Upload artifact (darwin-x64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-darwin-x64
path: ./binary/bin/darwin-x64/
- name: Upload artifact (win32-x64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-win32-x64
path: ./binary/bin/win32-x64/
- name: Upload artifact (win32-arm64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-win32-arm64
path: ./binary/bin/win32-arm64/
- name: Upload artifact (linux-arm64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-linux-arm64
path: ./binary/bin/linux-arm64/
- name: Upload artifact (linux-x64)
uses: actions/upload-artifact@v7
with:
name: continue-binary-linux-x64
path: ./binary/bin/linux-x64/
test-binaries:
needs: build
strategy:
matrix:
include:
- os: windows-latest
platform: win32
arch: x64
npm_config_arch: x64
- os: ubuntu-latest
platform: linux
arch: x64
npm_config_arch: x64
# arm64 not actually supported by GitHub
# - os: ubuntu-latest
# platform: linux
# arch: arm64
# npm_config_arch: arm64
- os: macos-12
platform: darwin
arch: x64
npm_config_arch: x64
- os: macos-latest
platform: darwin
arch: arm64
npm_config_arch: arm64
runs-on: ${{ matrix.os }}
steps:
# 1. Check-out repository
- name: Check-out repository
uses: actions/checkout@v6
# 2. Install npm dependencies
- name: Use Node.js from .nvmrc
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Cache core node_modules
uses: actions/cache@v5
with:
path: core/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('core/package-lock.json') }}
- name: Cache binary node_modules
uses: actions/cache@v5
with:
path: binary/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('binary/package-lock.json') }}
- name: Install Core Dependencies
run: |
cd ../../core
npm ci
- name: Install Binary Dependencies
run: |
cd ../../binary
npm ci
# Download the binary artifact
- name: Download binary artifact
uses: actions/download-artifact@v8
with:
name: continue-binary-${{ matrix.platform }}-${{ matrix.arch }}
path: ./binary/bin/${{ matrix.platform }}-${{ matrix.arch }}/
# Set execute permissions for the binary (non-Windows)
- name: Set execute permissions
run: |
cd ../../binary/bin/${{ matrix.platform }}-${{ matrix.arch }}
chmod +x continue-binary
chmod +x build/Release/node_sqlite3.node
chmod +x index.node
if: ${{ matrix.platform }} != 'win32'
# Run tests for binary
- name: Run binary tests
run: |
cd ../../binary
npm run test
- name: Upload logs
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: core-logs-${{ matrix.platform }}-${{ matrix.arch }}
path: ~/.continue/logs/core.log
# Run tests and upload a code coverage report
test:
name: Test
needs: [build]
runs-on: ubuntu-latest
steps:
# Check out current repository
- name: Fetch Sources
uses: actions/checkout@v6
# Set up Java environment for the next steps
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 17
# Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
gradle-home-cache-cleanup: true
# Run tests
- name: Run Tests
run: ./gradlew check
# Collect Tests Result of failed tests
- name: Collect Tests Result
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: tests-result
path: ${{ github.workspace }}/extensions/intellij/build/reports/tests
# Run Qodana inspections and provide report
inspectCode:
if: false
name: Inspect code
needs: [build]
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
pull-requests: write
steps:
# Free GitHub Actions Environment Disk Space
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
large-packages: false
# Check out current repository
- name: Fetch Sources
uses: actions/checkout@v6
# Set up Java environment for the next steps
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 17
# Run Qodana inspections
- name: Qodana - Code Inspection
uses: JetBrains/qodana-action@v2025.3.2
with:
cache-default-branch-only: true
# Run plugin structure verification along with IntelliJ Plugin Verifier
verify:
if: false
name: Verify plugin
needs: [build]
runs-on: ubuntu-latest
steps:
# Free GitHub Actions Environment Disk Space
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
large-packages: false
# Check out current repository
- name: Fetch Sources
uses: actions/checkout@v6
# Set up Java environment for the next steps
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 17
# Setup Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
gradle-home-cache-cleanup: true
# Cache Plugin Verifier IDEs
- name: Setup Plugin Verifier IDEs Cache
uses: actions/cache@v5
with:
path: ${{ needs.build.outputs.pluginVerifierHomeDir }}/ides
key: plugin-verifier-${{ hashFiles('build/printProductsReleases.txt') }}
# Run Verify Plugin task and IntelliJ Plugin Verifier tool
- name: Run Plugin Verification tasks
run: ./gradlew runPluginVerifier -Dplugin.verifier.home.dir=${{ needs.build.outputs.pluginVerifierHomeDir }}
# Collect Plugin Verifier Result
- name: Collect Plugin Verifier Result
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: pluginVerifier-result
path: ${{ github.workspace }}/build/reports/pluginVerifier
upload-release:
if: false
name: Upload Release
needs:
- build
- test-binaries
- test
runs-on: ubuntu-latest
steps:
# # Update Unreleased section with the current release note
# - name: Patch Changelog
# if: ${{ steps.properties.outputs.changelog != '' }}
# env:
# CHANGELOG: ${{ steps.properties.outputs.changelog }}
# run: |
# ./gradlew patchChangelog --release-note="$CHANGELOG"
- name: Download the plugin
uses: actions/download-artifact@v8
with:
name: ${{ steps.artifact.outputs.filename }}
path: ./build/distributions/
# Upload artifact as a release asset
# - name: Upload Release Asset
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*
# Publish the plugin to JetBrains Marketplace
- name: Publish Plugin
env:
PUBLISH_TOKEN: ${{ secrets.JETBRAINS_PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.JETBRAINS_CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.JETBRAINS_PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.JETBRAINS_PRIVATE_KEY_PASSWORD }}
run: ./gradlew publishPlugin
# Create a pull request
- name: Create Pull Request
if: ${{ steps.properties.outputs.changelog != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ github.event.release.tag_name }}"
BRANCH="changelog-update-$VERSION"
LABEL="release changelog"
git config user.email "action@github.com"
git config user.name "GitHub Action"
git checkout -b $BRANCH
git commit -am "Changelog update - $VERSION"
git push --set-upstream origin $BRANCH
gh label create "$LABEL" \
--description "Pull requests with release changelog update" \
--force \
|| true
gh pr create \
--title "Changelog update - \`$VERSION\`" \
--body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
--label "$LABEL" \
--head $BRANCH
label-merged-prs .github/workflows/label-merged-prs.yml
View raw YAML
name: Label Merged PRs
on:
pull_request:
types: [closed]
jobs:
label-pr:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Check if author is in tier list
id: check-author
run: |
USERS=(
"TyDunn"
"jpoly1219"
"bdougie"
"uinstinct"
"sestinj"
"tingwai"
"tomasz-stefaniak"
"RomneyDa"
"Patrick-Erichsen"
)
PR_AUTHOR="${{ github.event.pull_request.user.login }}"
SHOULD_LABEL="false"
for user in "${USERS[@]}"; do
if [[ "$PR_AUTHOR" == "$user" ]]; then
SHOULD_LABEL="true"
break
fi
done
echo "should_label=$SHOULD_LABEL" >> $GITHUB_OUTPUT
- name: Determine and apply tier label
if: steps.check-author.outputs.should_label == 'true'
uses: actions/github-script@v8
with:
script: |
const pr = context.payload.pull_request;
// Check if PR already has a tier label
const existingLabels = pr.labels.map(l => l.name);
if (existingLabels.some(label => label.match(/^tier [1-3]$/))) {
console.log('PR already has a tier label, skipping');
return;
}
// Function to extract conventional commit prefix
function getConventionalPrefix(title) {
const match = title.match(/^([a-z]+)(\s|$|:)/);
return match ? match[1] : '';
}
// Function to determine tier
function determineTier(pr) {
const additions = pr.additions;
const deletions = pr.deletions;
const changedFiles = pr.changed_files;
const title = pr.title;
const body = pr.body || '';
const prefix = getConventionalPrefix(title);
// If no conventional commit prefix, skip
if (!prefix) {
console.log('No conventional commit format, skipping');
return null;
}
// Tier 4 (unlabeled): fix, test, docs, style, refactor, perf, build, ci, revert, improve
const tier4Prefixes = ['fix', 'test', 'docs', 'style', 'refactor', 'perf', 'build', 'ci', 'revert', 'chore', 'improve'];
if (tier4Prefixes.includes(prefix)) {
console.log('Tier 4 prefix detected, will remain unlabeled');
return null;
}
const totalChanges = additions + deletions;
// Tier 1: Major features (1000+ lines changed, or 20+ files, or feat with large scope)
if (totalChanges > 1000 || changedFiles > 20 ||
(prefix === 'feat' && totalChanges > 800) ||
title.match(/(major|milestone|launch)/)) {
return 'tier 1';
}
// Tier 2: Important features (500+ lines changed, or 10+ files, or standard feat)
if (totalChanges > 500 || changedFiles > 10 || prefix === 'feat') {
return 'tier 2';
}
// Tier 3: Smaller improvements
return 'tier 3';
}
const tier = determineTier(pr);
if (tier) {
console.log(`Assigning ${tier} label to PR #${pr.number}`);
console.log(`Title: ${pr.title}`);
console.log(`Changes: +${pr.additions} -${pr.deletions} (${pr.changed_files} files)`);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: [tier]
});
console.log(`✓ Label '${tier}' added successfully`);
}main matrix .github/workflows/main.yaml
View raw YAML
name: Publish Extension
on:
release:
types: [released]
workflow_dispatch:
inputs:
publish_build:
description: "Whether or not to publish the built extension to the VS Code marketplace"
required: true
default: "false"
jobs:
check_release_name:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: check
working-directory: .
run: |
if [[ "${{ github.event.release.tag_name }}" == v1.2.*-vscode ]]; then
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi
check-version:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0 # This ensures all tags are fetched
- name: Checkout tag
run: git checkout ${GITHUB_REF#refs/tags/}
- name: Make sure version isn't odd
run: |
cd extensions/vscode
node scripts/versionCheck.js
build:
needs: [check_release_name, check-version]
if: needs.check_release_name.outputs.should_run == 'true' || github.event_name == 'workflow_dispatch'
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-latest
platform: win32
arch: x64
npm_config_arch: x64
- os: windows-latest
platform: win32
arch: arm64
npm_config_arch: arm
- os: ubuntu-latest
platform: linux
arch: x64
npm_config_arch: x64
- os: ubuntu-latest
platform: linux
arch: arm64
npm_config_arch: arm64
- os: ubuntu-latest
platform: linux
arch: armhf
npm_config_arch: arm
- os: ubuntu-latest
platform: alpine
arch: x64
npm_config_arch: x64
- os: macos-latest
platform: darwin
arch: x64
npm_config_arch: x64
- os: macos-latest
platform: darwin
arch: arm64
npm_config_arch: arm64
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- uses: ./.github/actions/build-vscode-extension
with:
platform: ${{ matrix.platform }}
arch: ${{ matrix.arch }}
npm_config_arch: ${{ matrix.npm_config_arch }}
pre-release: false
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload .vsix artifact
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.platform }}-${{ matrix.arch }}-vsix
path: "extensions/vscode/*.vsix"
release:
permissions:
contents: write
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Download the .vsix artifacts
- uses: actions/download-artifact@v8
with:
pattern: "*-vsix"
path: vsix-artifacts
merge-multiple: true
- name: Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
files: |
vsix-artifacts/*.vsix
token: ${{ secrets.CI_GITHUB_TOKEN }}
repository: continuedev/continue
publish:
runs-on: ubuntu-latest
needs:
- build
if: github.event_name != 'workflow_dispatch' || github.event.inputs.publish_build == 'true'
permissions:
contents: write
steps:
# 0. Setup git
- name: Checkout
uses: actions/checkout@v6
- name: Set up Git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- name: Pull latest changes from release
run: git fetch origin ${{ github.ref }} && git checkout ${{ github.ref }}
# 1. Download the artifacts
- uses: actions/download-artifact@v8
with:
pattern: "*-vsix"
path: vsix-artifacts
merge-multiple: true
# 2. Publish the extension to VS Code Marketplace
- name: Publish to VS Code Marketplace
run: |
cd extensions/vscode
npx @vscode/vsce publish --packagePath ../../vsix-artifacts/*.vsix
env:
VSCE_PAT: ${{ secrets.VSCE_TOKEN }}
# 3. Publish the extension to Open VSX Registry
- name: Publish (Open VSX Registry)
continue-on-error: true
run: |
cd extensions/vscode
npx ovsx publish -p ${{ secrets.VSX_REGISTRY_TOKEN }} --packagePath ../../vsix-artifacts/*.vsix
main-build matrix .github/workflows/main-build.yaml
View raw YAML
name: Main Branch Build
# Download and republish VS Code extension artifacts when code is merged to main
on:
push:
branches:
- main
workflow_dispatch:
inputs:
test_pr_number:
description: "PR number to test with"
required: true
jobs:
republish-pr-artifacts:
runs-on: ubuntu-latest
strategy:
matrix:
platform: [Linux, macOS]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2 # Get the last 2 commits to find the merge commit
- name: Get merged PR number
id: get-pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get PR number for the current commit using GitHub API
COMMIT_SHA=$(git rev-parse HEAD)
echo "Getting PR for commit: $COMMIT_SHA"
PR_NUMBER=$(curl -s -H "Authorization: token $GH_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/commits/$COMMIT_SHA/pulls" \
| jq -r '.[0].number // empty')
if [ -z "$PR_NUMBER" ]; then
echo "❌ Could not find PR for commit $COMMIT_SHA"
exit 1
fi
echo "Found PR number: $PR_NUMBER"
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
- name: Find PR workflow run
id: find-run
env:
PR_NUMBER: ${{ steps.get-pr.outputs.pr_number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🔍 Getting branch name for PR #$PR_NUMBER..."
# Get the branch name for the PR
BRANCH_NAME=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json headRefName --jq '.headRefName')
if [ -z "$BRANCH_NAME" ]; then
echo "❌ Could not find PR #$PR_NUMBER"
exit 1
fi
echo "Branch name: $BRANCH_NAME"
# Get the latest successful workflow run for the branch
RUN_ID=$(gh run list \
--repo "${{ github.repository }}" \
--workflow="pr_checks.yaml" \
--branch="$BRANCH_NAME" \
--json databaseId,status,conclusion \
--jq ".[] | select(.status == \"completed\" and .conclusion == \"success\") | .databaseId" \
| head -1)
if [ -z "$RUN_ID" ]; then
echo "❌ No successful workflow run found for PR #$PR_NUMBER (branch: $BRANCH_NAME)"
exit 1
fi
echo "Found successful workflow run: $RUN_ID"
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
- name: Download PR artifact
env:
RUN_ID: ${{ steps.find-run.outputs.run_id }}
PLATFORM: ${{ matrix.platform }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "📥 Downloading vscode-extension-build-$PLATFORM artifact from run $RUN_ID..."
# Create temporary directory for download
mkdir -p ./temp-download
# Download the artifact from the PR workflow run
if ! gh run download "$RUN_ID" \
--repo "${{ github.repository }}" \
--name "vscode-extension-build-$PLATFORM" \
--dir "./temp-download"; then
echo "❌ Failed to download artifact vscode-extension-build-$PLATFORM from run $RUN_ID"
exit 1
fi
echo "✅ Successfully downloaded artifact"
- name: Republish as main branch artifact
uses: actions/upload-artifact@v7
with:
name: vscode-extension-build-${{ matrix.platform }}
path: ./temp-download/*
metrics perms .github/workflows/metrics.yaml
View raw YAML
name: Monthly issue metrics
on:
workflow_dispatch:
schedule:
# Runs every Monday at 9:00 AM PST (17:00 UTC)
- cron: "0 17 * * 1"
push:
branches:
- nate/metrics-action
permissions:
contents: read
jobs:
build:
name: issue metrics
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
permissions:
issues: write
pull-requests: read
steps:
- name: Get dates for last month
shell: bash
run: |
# Calculate the first day of the previous month
first_day=$(date -d "last month" +%Y-%m-01)
# Calculate the last day of the previous month
last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d)
#Set an environment variable with the date range
echo "$first_day..$last_day"
echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV"
- name: Run issue-metrics tool
uses: github/issue-metrics@v3
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SEARCH_QUERY: 'repo:continuedev/continue created:${{ env.last_month }} -reason:"not planned"'
- name: Read metrics file content
id: read-metrics
run: |
content=$(cat ./issue_metrics.md)
# This prepares the content in a way that can be used in GitHub Actions
content="${content//'%'/'%25'}"
content="${content//$'\n'/'%0A'}"
# content="${content//$'\r'/'%0D'}"
echo "metrics_content=$content" >> "$GITHUB_OUTPUT"
- name: Post a message in a channel
uses: slackapi/slack-github-action@v3.0.1
with:
webhook: ${{ secrets.ISSUE_PR_METRICS_SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "Issue / PR Metrics Report"
blocks:
- type: "header"
text:
type: "plain_text"
text: "Monthly Issue Metrics Report"
emoji: true
- type: "section"
text:
type: "mrkdwn"
text: |
${{ steps.read-metrics.outputs.metrics_content }}
- name: Upload metrics report as artifact
uses: actions/upload-artifact@v7
with:
name: issue-metrics-report
path: ./issue_metrics.md
pr-build-upload-vsix matrix .github/workflows/pr-build-upload-vsix.yaml
View raw YAML
name: PR Build And Upload VSIX
# Builds and uploads VSIX artifacts for the `oneper` script across Linux, Windows, and macOS ARM platforms
on:
pull_request:
branches:
- main
jobs:
build-and-upload-vsix:
runs-on: ${{ matrix.runner }}
timeout-minutes: 10
strategy:
matrix:
include:
- platform: linux
arch: x64
runner: ubuntu-latest
- platform: win32
arch: x64
runner: windows-latest
- platform: darwin
arch: arm64
runner: macos-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Build VS Code extension
uses: ./.github/actions/build-vscode-extension
with:
platform: ${{ matrix.platform }}
arch: ${{ matrix.arch }}
npm_config_arch: ${{ matrix.arch }}
pre-release: false
commit-sha: ${{ github.sha }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload build artifact
uses: actions/upload-artifact@v7
with:
name: vscode-extension-build-${{ matrix.platform }}-${{ matrix.arch }}
path: extensions/vscode/build
- name: Upload .vsix artifact
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.platform }}-${{ matrix.arch }}-vsix
path: "extensions/vscode/*.vsix"
pr-checks matrix .github/workflows/pr-checks.yaml
View raw YAML
name: PR Checks
# PR Checks run on all PRs to the main branch and must pass before merging.
on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
track-rerun:
runs-on: ubuntu-latest
if: github.run_attempt > 1
steps:
- uses: actions/checkout@v6
- name: Track workflow rerun
uses: ./.github/actions/track-rerun
prettier-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- uses: actions/cache@v5
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-root-node-modules-${{ hashFiles('package-lock.json') }}
- name: Install root dependencies
if: steps.root-cache.outputs.cache-hit != 'true'
run: npm ci
- name: Check code formatting with Prettier
run: npx prettier --check "**/*.{js,jsx,ts,tsx,json,css,md}" --ignore-path .gitignore --ignore-path .prettierignore
core-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Needed for git diff to work
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Check if LLM-related files changed
id: llm-changes
uses: ./.github/actions/check-llm-changes
with:
is_fork: ${{ github.event.pull_request.head.repo.fork == true }}
is_dependabot: ${{ github.actor == 'dependabot[bot]' }}
- name: Type check and lint
run: |
cd core
npx tsc --noEmit
npm run lint
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
- name: Run tests
run: |
cd core
npm test
npm run vitest
env:
IGNORE_API_KEY_TESTS: ${{ steps.llm-changes.outputs.ignore_api_tests }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
gui-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Setup gui component
uses: ./.github/actions/setup-component
with:
component: gui
include-packages: false
env:
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }}
- name: Type check and lint
run: |
cd gui
npx tsc --noEmit
npm run lint
- name: Run tests
run: |
cd gui
npm test
binary-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Setup binary component
uses: ./.github/actions/setup-component
with:
component: binary
include-packages: false
- name: Type check
run: |
cd binary
npx tsc --noEmit
vscode-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Setup vscode component
uses: ./.github/actions/setup-component
with:
component: vscode
include-packages: false
env:
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }}
- name: Type check and lint
run: |
cd extensions/vscode
npm run write-build-timestamp
npx tsc --noEmit
npm run lint
- name: Run vitest tests
run: |
cd extensions/vscode
npm run vitest
get-packages-matrix:
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.get-packages.outputs.packages }}
steps:
- uses: actions/checkout@v6
- name: Get package list
id: get-packages
run: |
packages=$(find packages/ -maxdepth 1 -type d -not -path packages/ -exec basename {} \; | sort | jq -R -s -c 'split("\n")[:-1]')
echo "packages=$packages" >> $GITHUB_OUTPUT
echo "Found packages: $packages"
packages-checks:
needs: get-packages-matrix
runs-on: ubuntu-latest
strategy:
matrix:
package: ${{ fromJson(needs.get-packages-matrix.outputs.packages) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Needed for git diff to work
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Check if LLM-related files changed
id: llm-changes
uses: ./.github/actions/check-llm-changes
with:
is_fork: ${{ github.event.pull_request.head.repo.fork == true }}
is_dependabot: ${{ github.actor == 'dependabot[bot]' }}
- name: Test and check ${{ matrix.package }}
run: |
cd packages/${{ matrix.package }}
npm ci
npm test
env:
IGNORE_API_KEY_TESTS: ${{ steps.llm-changes.outputs.ignore_api_tests }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
vscode-get-test-file-matrix:
runs-on: ubuntu-latest
outputs:
test_file_matrix: ${{ steps.vscode-get-test-file-matrix.outputs.test_file_matrix }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Cache npm
uses: actions/cache@v5
with:
path: ~/.npm
key: ${{ runner.os }}-npm-cache-matrix-${{ hashFiles('core/package-lock.json', 'extensions/vscode/package-lock.json') }}
- name: Cache packages node_modules
uses: actions/cache@v5
with:
path: |
packages/*/node_modules
key: ${{ runner.os }}-packages-node-modules-${{ hashFiles('packages/*/package-lock.json') }}
- name: Cache core node modules
uses: actions/cache@v5
with:
path: core/node_modules
key: ${{ runner.os }}-core-node-modules-${{ hashFiles('core/package-lock.json') }}
- name: Cache vscode extension node modules
uses: actions/cache@v5
id: vscode-cache
with:
path: extensions/vscode/node_modules
key: ${{ runner.os }}-vscode-node-modules-${{ hashFiles('extensions/vscode/package-lock.json') }}
- name: Build packages and get test files
id: vscode-get-test-file-matrix
run: |
node ./scripts/build-packages.js
cd extensions/vscode
npm ci
npm run e2e:compile
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" || "${{ github.actor }}" == "dependabot[bot]" ]]; then
# Exclude SSH tests for forks
FILES=$(ls -1 e2e/_output/tests/*.test.js | grep -v "SSH" | jq -R . | jq -s .)
else
# Include all tests for non-forks
FILES=$(ls -1 e2e/_output/tests/*.test.js | jq -R . | jq -s .)
fi
echo "test_file_matrix<<EOF" >> $GITHUB_OUTPUT
echo "$FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
env:
# https://github.com/microsoft/vscode-ripgrep/issues/9#issuecomment-643965333
GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }}
- name: Debug Outputs
run: |
echo "Test files: ${{ steps.vscode-get-test-file-matrix.outputs.test_file_matrix }}"
vscode-package-extension-linux:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Build VS Code extension
uses: ./.github/actions/build-vscode-extension
with:
platform: linux
arch: x64
npm_config_arch: x64
pre-release: false
commit-sha: ${{ github.sha }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload build artifact
uses: actions/upload-artifact@v7
with:
name: vscode-extension-build-Linux
path: extensions/vscode/build
vscode-e2e-tests:
name: ${{ matrix.test_file || 'unknown' }} (${{ matrix.command }})
needs: [vscode-get-test-file-matrix, vscode-package-extension-linux]
runs-on: ubuntu-latest
timeout-minutes: 15
# Tests requiring secrets need approval from maintainers
strategy:
fail-fast: false
matrix:
test_file: ${{ fromJson(needs.vscode-get-test-file-matrix.outputs.test_file_matrix) }}
command: ["e2e:ci:run", "e2e:ci:run-yaml"]
steps:
- uses: actions/checkout@v6
- name: Run VS Code E2E test
uses: ./.github/actions/run-vscode-e2e-test
with:
test_file: ${{ matrix.test_file }}
command: ${{ matrix.command }}
ssh_key: ${{ secrets.GH_ACTIONS_SSH_TEST_KEY_PEM }}
ssh_host: ${{ secrets.GH_ACTIONS_SSH_TEST_DNS_NAME }}
is_fork: ${{ github.event.pull_request.head.repo.fork == true || github.actor == 'dependabot[bot]' }}
github_token: ${{ secrets.CI_GITHUB_TOKEN }}
jetbrains-tests:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@main
with:
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: false
docker-images: true
swap-storage: true
- uses: actions/checkout@v6
- name: Run JetBrains tests
uses: ./.github/actions/run-jetbrains-tests
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
ci-github-token: ${{ secrets.CI_GITHUB_TOKEN }}
# GitHub does not have a way of requiring that all checks pass (you must manually select each job)
# This action at least lets us manage the list of required tests via source control
# so that creators of new jobs can add them to this list
require-all-checks-to-pass:
if: always()
runs-on: ubuntu-latest
needs:
- prettier-check
- core-checks
- gui-checks
- binary-checks
- vscode-checks
- get-packages-matrix
- packages-checks
- vscode-get-test-file-matrix
- vscode-package-extension-linux
- vscode-e2e-tests
- jetbrains-tests
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
preview matrix .github/workflows/preview.yaml
View raw YAML
name: Publish Pre-release Extension
on:
release:
types: [prereleased]
workflow_dispatch:
inputs:
publish_build:
description: "Whether or not to publish the built extension to the VS Code marketplace"
required: true
default: "false"
jobs:
check_release_name:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: check
working-directory: .
run: |
if [[ "${{ github.event.release.tag_name }}" == v1.3.*-vscode ]]; then
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi
build:
needs: check_release_name
if: needs.check_release_name.outputs.should_run == 'true' || github.event_name == 'workflow_dispatch'
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: windows-latest
platform: win32
arch: x64
npm_config_arch: x64
- os: windows-latest
platform: win32
arch: arm64
npm_config_arch: arm
- os: ubuntu-latest
platform: linux
arch: x64
npm_config_arch: x64
- os: ubuntu-latest
platform: linux
arch: arm64
npm_config_arch: arm64
- os: ubuntu-latest
platform: linux
arch: armhf
npm_config_arch: arm
- os: ubuntu-latest
platform: alpine
arch: x64
npm_config_arch: x64
- os: macos-latest
platform: darwin
arch: x64
npm_config_arch: x64
- os: macos-latest
platform: darwin
arch: arm64
npm_config_arch: arm64
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- uses: ./.github/actions/build-vscode-extension
with:
platform: ${{ matrix.platform }}
arch: ${{ matrix.arch }}
npm_config_arch: ${{ matrix.npm_config_arch }}
pre-release: true
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload .vsix artifact
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.platform }}-${{ matrix.arch }}-vsix
path: "extensions/vscode/*.vsix"
release:
permissions:
contents: write
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Download the .vsix artifacts
- uses: actions/download-artifact@v8
with:
pattern: "*-vsix"
path: vsix-artifacts
merge-multiple: true
- name: Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
files: |
vsix-artifacts/*.vsix
token: ${{ secrets.CI_GITHUB_TOKEN }}
repository: continuedev/continue
prerelease: true
publish:
runs-on: ubuntu-latest
needs:
- build
if: github.event_name != 'workflow_dispatch' || github.event.inputs.publish_build == 'true'
steps:
- name: Checkout
uses: actions/checkout@v6
# 1. Download the artifacts
- uses: actions/download-artifact@v8
with:
pattern: "*-vsix"
path: vsix-artifacts
merge-multiple: true
# 2. Publish the extension to VS Code Marketplace
- name: Publish to VS Code Marketplace
run: |
cd extensions/vscode
npx @vscode/vsce publish --pre-release --packagePath ../../vsix-artifacts/*.vsix
env:
VSCE_PAT: ${{ secrets.VSCE_TOKEN }}
# 3. Publish the extension to Open VSX Registry
- name: Publish (Open VSX Registry)
continue-on-error: true
run: |
cd extensions/vscode
npx ovsx publish --pre-release -p ${{ secrets.VSX_REGISTRY_TOKEN }} --packagePath ../../vsix-artifacts/*.vsix
release-config-yaml perms .github/workflows/release-config-yaml.yml
View raw YAML
name: Release @continuedev/config-yaml
on:
push:
branches:
- main
paths:
- "packages/config-yaml/**"
- ".github/workflows/release-config-yaml.yml"
- ".github/workflows/reusable-release.yml"
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
uses: ./.github/workflows/reusable-release.yml
with:
package-name: "config-yaml"
package-path: "packages/config-yaml"
secrets:
SEMANTIC_RELEASE_GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
SEMANTIC_RELEASE_NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
release-fetch perms .github/workflows/release-fetch.yml
View raw YAML
name: Release @continuedev/fetch
on:
push:
branches:
- main
paths:
- "packages/fetch/**"
- ".github/workflows/release-fetch.yml"
- ".github/workflows/reusable-release.yml"
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
uses: ./.github/workflows/reusable-release.yml
with:
package-name: "fetch"
package-path: "packages/fetch"
secrets:
SEMANTIC_RELEASE_GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
SEMANTIC_RELEASE_NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
release-llm-info perms .github/workflows/release-llm-info.yml
View raw YAML
name: Release @continuedev/llm-info
on:
push:
branches:
- main
paths:
- "packages/llm-info/**"
- ".github/workflows/release-llm-info.yml"
- ".github/workflows/reusable-release.yml"
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
uses: ./.github/workflows/reusable-release.yml
with:
package-name: "llm-info"
package-path: "packages/llm-info"
secrets:
SEMANTIC_RELEASE_GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
SEMANTIC_RELEASE_NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
release-openai-adapters perms .github/workflows/release-openai-adapters.yml
View raw YAML
name: Release @continuedev/openai-adapters
on:
push:
branches:
- main
paths:
- "packages/openai-adapters/**"
- ".github/workflows/release-openai-adapters.yml"
- ".github/workflows/reusable-release.yml"
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
uses: ./.github/workflows/reusable-release.yml
with:
package-name: "openai-adapters"
package-path: "packages/openai-adapters"
secrets:
SEMANTIC_RELEASE_GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
SEMANTIC_RELEASE_NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
reusable-release perms .github/workflows/reusable-release.yml
View raw YAML
name: Reusable Release Workflow
on:
workflow_call:
inputs:
package-name:
required: true
type: string
package-path:
required: true
type: string
secrets:
SEMANTIC_RELEASE_GITHUB_TOKEN:
required: true
SEMANTIC_RELEASE_NPM_TOKEN:
required: true
OPENAI_API_KEY:
required: false
ANTHROPIC_API_KEY:
required: false
GEMINI_API_KEY:
required: false
MISTRAL_API_KEY:
required: false
AZURE_OPENAI_API_KEY:
required: false
AZURE_FOUNDRY_CODESTRAL_API_KEY:
required: false
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY:
required: false
AZURE_OPENAI_GPT41_API_KEY:
required: false
VOYAGE_API_KEY:
required: false
RELACE_API_KEY:
required: false
INCEPTION_API_KEY:
required: false
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
name: Release ${{ inputs.package-name }}
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.package-path }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Use Node.js from .nvmrc
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run tests
run: npm test
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
AZURE_FOUNDRY_CODESTRAL_API_KEY: ${{ secrets.AZURE_FOUNDRY_CODESTRAL_API_KEY }}
AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY: ${{ secrets.AZURE_FOUNDRY_MISTRAL_SMALL_API_KEY }}
AZURE_OPENAI_GPT41_API_KEY: ${{ secrets.AZURE_OPENAI_GPT41_API_KEY }}
VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }}
RELACE_API_KEY: ${{ secrets.RELACE_API_KEY }}
INCEPTION_API_KEY: ${{ secrets.INCEPTION_API_KEY }}
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }}
run: npx semantic-release
run-continue-agent .github/workflows/run-continue-agent.yml
View raw YAML
name: Run Continue Agent
on:
workflow_call:
inputs:
prompt:
description: "Additional prompting to send to the Continue agent"
required: false
type: string
default: ""
agent:
description: "The agent to use (e.g., continuedev/github-pr-agent)"
required: true
type: string
default: "continuedev/github-pr-agent"
branch_name:
description: "The base branch name to work from"
required: false
type: string
default: "main"
secrets:
CONTINUE_API_KEY:
required: true
jobs:
run-agent:
runs-on: ubuntu-latest
steps:
- name: Call agents endpoint
env:
PROMPT: ${{ inputs.prompt }}
AGENT: ${{ inputs.agent }}
BRANCH_NAME: ${{ inputs.branch_name }}
REPO_URL: https://github.com/${{ github.repository }}
CONTINUE_API_KEY: ${{ secrets.CONTINUE_API_KEY }}
run: |
# Use jq to properly construct JSON with safe escaping
json_body=$(jq -n \
--arg prompt "$PROMPT" \
--arg agent "$AGENT" \
--arg branchName "$BRANCH_NAME" \
--arg repoUrl "$REPO_URL" \
'{prompt: $prompt, agent: $agent, branchName: $branchName, repoUrl: $repoUrl}')
response=$(curl -f -X POST https://api.continue.dev/agents \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CONTINUE_API_KEY" \
-d "$json_body")
id=$(echo $response | jq -r '.id')
echo "https://continue.dev/hub?type=agents/$id"
similar-issues .github/workflows/similar-issues.yml
View raw YAML
name: Similar Issue Search & Discussion Suggestion
on:
issues:
types: [opened]
pull_request:
types: [opened]
jobs:
analyze:
# Disabling for now due to bugs
if: false
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Checkout deja-view
uses: actions/checkout@v6
with:
repository: "bdougie/deja-view"
# Option 1: Pin to specific commit (most secure)
ref: "45e7696" # Pin to specific commit for stability
# Option 2: Use a tag (recommended after creating releases)
# ref: 'v1.0.0'
# Option 3: Use main branch (least secure, gets latest changes)
# ref: 'main'
path: deja-view
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install dependencies
run: |
cd deja-view
pip install -r requirements.txt
- name: Index repository if needed
env:
CHROMA_API_KEY: ${{ secrets.CHROMA_CLOUD_API_KEY }}
CHROMA_TENANT: ${{ secrets.CHROMA_TENANT }}
CHROMA_DATABASE: ${{ secrets.CHROMA_DATABASE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd deja-view
# Index the repository (this will update existing index)
python cli.py index "${{ github.repository }}" --max-issues 200 || true
- name: Search for similar issues
id: search
env:
CHROMA_API_KEY: ${{ secrets.CHROMA_CLOUD_API_KEY }}
CHROMA_TENANT: ${{ secrets.CHROMA_TENANT }}
CHROMA_DATABASE: ${{ secrets.CHROMA_DATABASE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd deja-view
# Determine if this is an issue or PR
if [ "${{ github.event_name }}" = "pull_request" ]; then
ISSUE_URL="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
THRESHOLD="0.85"
TOP_K="5"
else
ISSUE_URL="https://github.com/${{ github.repository }}/issues/${{ github.event.issue.number }}"
THRESHOLD="0.7"
TOP_K="5"
fi
# Create a Python script to search and format as JSON
cat << 'PYTHON_SCRIPT' > search_similar.py
import sys
import json
import os
from github_similarity_service import SimilarityService
issue_url = sys.argv[1]
threshold = float(sys.argv[2])
top_k = int(sys.argv[3])
# Parse issue number from URL
issue_number = int(issue_url.split('/')[-1])
repo_parts = issue_url.split('/')
owner = repo_parts[3]
repo = repo_parts[4]
service = SimilarityService()
# Find similar issues
similar = service.find_similar_issues(
owner=owner,
repo=repo,
issue_number=issue_number,
top_k=top_k,
min_similarity=threshold
)
# Format as JSON
print(json.dumps(similar))
PYTHON_SCRIPT
# Search for similar issues
SIMILAR_ISSUES=$(python search_similar.py "$ISSUE_URL" "$THRESHOLD" "$TOP_K")
# Save to output
echo "similar_issues<<EOF" >> $GITHUB_OUTPUT
echo "$SIMILAR_ISSUES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Check if any similar issues found
if [ "$(echo "$SIMILAR_ISSUES" | jq '. | length')" -gt 0 ]; then
echo "has_similar=true" >> $GITHUB_OUTPUT
else
echo "has_similar=false" >> $GITHUB_OUTPUT
fi
- name: Check if issue should be a discussion
id: discussion_check
if: github.event_name == 'issues'
env:
CHROMA_API_KEY: ${{ secrets.CHROMA_CLOUD_API_KEY }}
CHROMA_TENANT: ${{ secrets.CHROMA_TENANT }}
CHROMA_DATABASE: ${{ secrets.CHROMA_DATABASE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd deja-view
# Create a Python script to analyze the issue
cat << 'PYTHON_SCRIPT' > check_discussion.py
import os
import json
import re
from github_similarity_service import SimilarityService
# Get issue details from environment
issue_title = os.environ.get('ISSUE_TITLE', '')
issue_body = os.environ.get('ISSUE_BODY', '')
issue_labels = json.loads(os.environ.get('ISSUE_LABELS', '[]'))
# Mock Issue object for analysis
class MockIssue:
def __init__(self):
self.title = issue_title
self.body = issue_body
self.labels = issue_labels
self.state = 'open'
self.number = int(os.environ.get('ISSUE_NUMBER', 0))
self.created_at = ''
self.updated_at = ''
self.url = ''
service = SimilarityService()
issue = MockIssue()
score, reasons = service._calculate_discussion_score(issue)
result = {
'score': score,
'reasons': reasons,
'should_be_discussion': score >= 0.5,
'confidence': 'high' if score >= 0.7 else 'medium' if score >= 0.5 else 'low'
}
print(json.dumps(result))
PYTHON_SCRIPT
# Run the analysis
DISCUSSION_ANALYSIS=$(ISSUE_TITLE="${{ github.event.issue.title }}" \
ISSUE_BODY='${{ github.event.issue.body }}' \
ISSUE_LABELS='${{ toJson(github.event.issue.labels.*.name) }}' \
ISSUE_NUMBER="${{ github.event.issue.number }}" \
python check_discussion.py)
echo "analysis<<EOF" >> $GITHUB_OUTPUT
echo "$DISCUSSION_ANALYSIS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Extract whether it should be a discussion
SHOULD_BE_DISCUSSION=$(echo "$DISCUSSION_ANALYSIS" | jq -r '.should_be_discussion')
echo "should_be_discussion=$SHOULD_BE_DISCUSSION" >> $GITHUB_OUTPUT
# Extract confidence level
CONFIDENCE=$(echo "$DISCUSSION_ANALYSIS" | jq -r '.confidence')
echo "confidence=$CONFIDENCE" >> $GITHUB_OUTPUT
- name: Comment with analysis
uses: actions/github-script@v8
with:
script: |
let comment = '';
const hasSimilar = '${{ steps.search.outputs.has_similar }}' === 'true';
const isPR = '${{ github.event_name }}' === 'pull_request';
const shouldBeDiscussion = !isPR && '${{ steps.discussion_check.outputs.should_be_discussion }}' === 'true';
// Add similar issues section if found
if (hasSimilar) {
const similarIssues = JSON.parse(`${{ steps.search.outputs.similar_issues }}`);
if (isPR) {
// Filter only open issues for PRs
const openIssues = similarIssues.filter(issue => issue.state === 'open');
if (openIssues.length > 0) {
// Simple table format for PRs
comment += '## 📋 Related Open Issues\n\n';
comment += 'These open issues appear to be related to this PR (≥85% similarity):\n\n';
comment += '| # | Title | Similarity |\n';
comment += '|---|-------|------------|\n';
openIssues.forEach(issue => {
const similarity = (issue.similarity * 100).toFixed(0);
const title = issue.title.length > 50 ? issue.title.substring(0, 47) + '...' : issue.title;
comment += `| [#${issue.number}](${issue.url}) | ${title} | ${similarity}% |\n`;
});
comment += '\n';
comment += '_Consider closing related issues if this PR addresses them._\n';
} else {
// Don't add any comment if no open issues found
return;
}
} else {
// Original format for issues
comment += '## 🔍 Similar Issues Found\n\n';
comment += 'I found some existing issues that might be related:\n\n';
similarIssues.forEach((issue, index) => {
const similarity = (issue.similarity * 100).toFixed(1);
const state = issue.state === 'open' ? '🟢' : '🔴';
comment += `${index + 1}. ${state} [#${issue.number}: ${issue.title}](${issue.url}) (${similarity}% similar)\n`;
if (issue.summary) {
comment += ` > ${issue.summary.substring(0, 150)}${issue.summary.length > 150 ? '...' : ''}\n`;
}
comment += '\n';
});
comment += '\n';
}
}
// Add discussion suggestion if applicable
if (shouldBeDiscussion) {
const analysis = JSON.parse(`${{ steps.discussion_check.outputs.analysis }}`);
const confidence = '${{ steps.discussion_check.outputs.confidence }}';
if (hasSimilar) {
comment += '---\n\n';
}
comment += '## 💬 Discussion Suggestion\n\n';
const confidenceEmoji = {
'high': '🟢',
'medium': '🟡',
'low': '🔴'
};
comment += `This issue might be better suited as a **GitHub Discussion** ${confidenceEmoji[confidence] || ''}\n\n`;
comment += `**Confidence**: ${confidence.charAt(0).toUpperCase() + confidence.slice(1)} (${(analysis.score * 100).toFixed(0)}%)\n\n`;
if (analysis.reasons && analysis.reasons.length > 0) {
comment += '**Reasons**:\n';
analysis.reasons.forEach(reason => {
comment += `- ${reason}\n`;
});
comment += '\n';
}
comment += 'GitHub Discussions are great for:\n';
comment += '- Questions and help requests\n';
comment += '- Feature requests and ideas\n';
comment += '- General feedback and brainstorming\n';
comment += '- Community conversations\n\n';
comment += '_Consider converting this to a discussion if it\'s not a bug report or actionable task._\n';
}
// Only comment if we have something to say
if (comment) {
comment += '\n---\n';
comment += '_This analysis was automatically generated by [deja-view](https://github.com/bdougie/deja-view)._';
if ('${{ github.event_name }}' === 'pull_request') {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: comment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}
}
- name: Add labels
if: github.event_name == 'issues'
uses: actions/github-script@v8
with:
script: |
const labels = [];
// Check for duplicate
if ('${{ steps.search.outputs.has_similar }}' === 'true') {
const similarIssues = JSON.parse(`${{ steps.search.outputs.similar_issues }}`);
const hasDuplicate = similarIssues.some(issue => issue.similarity > 0.9);
if (hasDuplicate) {
labels.push('potential-duplicate');
}
}
// Check for discussion suggestion
if ('${{ steps.discussion_check.outputs.should_be_discussion }}' === 'true') {
const confidence = '${{ steps.discussion_check.outputs.confidence }}';
if (confidence === 'high') {
labels.push('should-be-discussion');
} else if (confidence === 'medium') {
labels.push('discussion');
}
}
// Add labels if any
if (labels.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: labels
});
}
snyk-agent .github/workflows/snyk-agent.yaml
View raw YAML
name: Daily Snyk Agent
on:
schedule:
# Runs at 9:00 AM UTC every day
- cron: "0 9 * * *"
workflow_dispatch: # Allows manual triggering
jobs:
run-cn-task:
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
- name: Install Continue CLI globally
run: npm install -g @continuedev/cli@latest
- name: Run Snyk Agent
run: cd extensions/cli && cn -p --agent continuedev/snyk-code-scan-agent "The current directory"
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
CONTINUE_API_KEY: ${{ secrets.CONTINUE_API_KEY }}
stable-release perms .github/workflows/stable-release.yml
View raw YAML
name: Stable Release
on:
workflow_dispatch:
inputs:
stable_version:
description: "Version for stable release (e.g., 1.2.3)"
required: true
type: string
permissions:
contents: write
issues: write
pull-requests: write
id-token: write # Required for OIDC
jobs:
stable-release:
name: Stable Release
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Setup packages
uses: ./.github/actions/setup-packages
- name: Setup core component
uses: ./.github/actions/setup-component
with:
component: core
include-root: true
- name: Build core
run: |
cd core
npm run build
- name: Install CLI dependencies
working-directory: extensions/cli
run: npm ci
- name: Update version
working-directory: extensions/cli
run: npm version ${{ inputs.stable_version }} --no-git-tag-version
- name: Build
working-directory: extensions/cli
run: npm run build
- name: Run tests
working-directory: extensions/cli
run: npm test
- name: Setup Node.js for OIDC publish
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- name: Publish to npm
working-directory: extensions/cli
run: |
unset NODE_AUTH_TOKEN
npm publish --tag latest --provenance
echo "Published version: ${{ inputs.stable_version }}"
- name: Create release on GitHub
env:
GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git tag "v${{ inputs.stable_version }}"
git push origin "v${{ inputs.stable_version }}"
gh release create "v${{ inputs.stable_version }}" \
--title "CLI Release v${{ inputs.stable_version }}" \
--notes "Release v${{ inputs.stable_version }} built and published from the main branch." \
--latest
- name: Publish Blueprints to Runloop
env:
RUNLOOP_API_KEY: ${{ secrets.RUNLOOP_API_KEY }}
run: |
publish_blueprint() {
local name=$1
local template=$2
echo "Publishing blueprint '$name' to Runloop API for version ${{ inputs.stable_version }}"
# Use blueprint configuration from template file
cp ".github/workflows/$template" blueprint.json
# Publish to Runloop API
response=$(curl -X POST "https://api.runloop.ai/v1/blueprints" \
-H "Authorization: Bearer $RUNLOOP_API_KEY" \
-H "Content-Type: application/json" \
-d @blueprint.json \
-w "%{http_code}" \
-s)
http_code=$(echo "$response" | tail -c 4)
response_body=$(echo "$response" | head -c -4)
if [[ "$http_code" == "200" ]] || [[ "$http_code" == "201" ]]; then
echo "✅ Successfully published blueprint '$name' to Runloop API"
echo "Response: $response_body"
blueprint_id=$(echo "$response_body" | jq -r '.id // empty')
if [[ -n "$blueprint_id" ]]; then
echo "Blueprint ID: $blueprint_id"
fi
else
echo "❌ Failed to publish blueprint '$name' to Runloop API"
echo "HTTP Code: $http_code"
echo "Response: $response_body"
exit 1
fi
}
# Publish both cn and cn-staging blueprints
publish_blueprint "cn" "runloop-blueprint-template.json"
publish_blueprint "cn-staging" "runloop-blueprint-staging-template.json"
stale-issue-helper .github/workflows/stale-issue-helper.yaml
View raw YAML
name: "Label / close stale issues"
on:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
close-issue-message: "This issue was closed because it wasn't updated for 10 days after being marked stale. If it's still important, please reopen + comment and we'll gladly take another look!"
stale-issue-message: "This issue hasn't been updated in 90 days and will be closed after an additional 10 days without activity. If it's still important, please leave a comment and share any new information that would help us address the issue."
days-before-stale: 90
days-before-close: 10
days-before-pr-stale: -1
days-before-pr-close: -1
operations-per-run: 1000
stale-issue-label: "stale"
stale-pr-label: "stale"
exempt-issue-labels: "needs-triage,no-stale,high,highest"
exempt-pr-labels: "no-stale"
submit-github-dependency-graph perms .github/workflows/submit-github-dependency-graph.yml
View raw YAML
name: Submit Gradle Dependency Graph For Dependabot
on:
push:
branches: ["main"]
permissions:
contents: write
jobs:
dependency-submission:
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: "temurin"
java-version: 17
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v6
with:
# The gradle project is not in the root of the repository.
build-root-directory: extensions/intellij
tidy-up-codebase .github/workflows/tidy-up-codebase.yml
View raw YAML
name: Weekly CN Task
on:
schedule:
# Runs at 8/9:30 AM PST (16:30 UTC) every Monday so PR shows up at beginning of week
- cron: "30 16 * * 1"
workflow_dispatch: # Allows manual triggering
jobs:
run-cn-task:
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
uses: ./.github/workflows/run-continue-agent.yml
with:
agent: continuedev/tidy-up-markdown-agent
branch_name: main
secrets:
CONTINUE_API_KEY: ${{ secrets.CONTINUE_API_KEY }}
upload-runloop-blueprint matrix perms .github/workflows/upload-runloop-blueprint.yml
View raw YAML
name: Upload Runloop Blueprint
on:
workflow_dispatch:
push:
branches:
- main
paths:
- '.github/workflows/runloop-blueprint-template.json'
- '.github/workflows/runloop-blueprint-staging-template.json'
permissions:
contents: read
jobs:
upload-blueprints:
name: Upload Blueprints to Runloop
runs-on: ubuntu-latest
# Only run this workflow on the main repository (continuedev/continue)
if: github.repository == 'continuedev/continue'
strategy:
matrix:
include:
- template: runloop-blueprint-template.json
name: cn
- template: runloop-blueprint-staging-template.json
name: cn-staging
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Publish ${{ matrix.name }} Blueprint to Runloop
env:
RUNLOOP_API_KEY: ${{ secrets.RUNLOOP_API_KEY }}
run: |
echo "Publishing blueprint '${{ matrix.name }}' to Runloop API"
# Use blueprint configuration from template file
cp .github/workflows/${{ matrix.template }} blueprint.json
# Publish to Runloop API
response=$(curl -X POST "https://api.runloop.ai/v1/blueprints" \
-H "Authorization: Bearer $RUNLOOP_API_KEY" \
-H "Content-Type: application/json" \
-d @blueprint.json \
-w "%{http_code}" \
-s)
http_code=$(echo "$response" | tail -c 4)
response_body=$(echo "$response" | head -c -4)
if [[ "$http_code" == "200" ]] || [[ "$http_code" == "201" ]]; then
echo "✅ Successfully published blueprint '${{ matrix.name }}' to Runloop API"
echo "Response: $response_body"
# Extract blueprint ID if available
blueprint_id=$(echo "$response_body" | jq -r '.id // empty')
if [[ -n "$blueprint_id" ]]; then
echo "Blueprint ID: $blueprint_id"
echo "blueprint_id=$blueprint_id" >> $GITHUB_OUTPUT
fi
else
echo "❌ Failed to publish blueprint '${{ matrix.name }}' to Runloop API"
echo "HTTP Code: $http_code"
echo "Response: $response_body"
exit 1
fi
vscode-prerelease perms .github/workflows/vscode-prerelease.yml
View raw YAML
name: VSCode Pre-release
on:
workflow_dispatch:
inputs:
main_commit_sha:
description: "Main branch commit SHA to create pre-release from - leave empty to use HEAD of main"
required: false
type: string
prerelease_version:
description: "New pre-release version (e.g., 1.3.15) - leave empty to auto-increment"
required: false
type: string
permissions:
contents: write
pull-requests: write
jobs:
create-prerelease:
name: Create VSCode Pre-release
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ inputs.main_commit_sha || 'main' }}
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Determine version numbers
id: version
working-directory: extensions/vscode
run: |
# Get current version from package.json
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo "Current version in package.json: $CURRENT_VERSION"
# Determine new pre-release version
if [[ -n "${{ inputs.prerelease_version }}" ]]; then
NEW_VERSION="${{ inputs.prerelease_version }}"
echo "Using manually specified new version: $NEW_VERSION"
else
# Auto-increment patch version
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
NEW_PATCH=$((patch + 1))
NEW_VERSION="${major}.${minor}.${NEW_PATCH}"
echo "Auto-incremented version: $NEW_VERSION"
fi
TAG_NAME="v${NEW_VERSION}-vscode"
echo "previous_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
echo "Summary:"
echo " Previous version: $CURRENT_VERSION"
echo " New version: $NEW_VERSION"
echo " Tag name: $TAG_NAME"
- name: Create pre-release branch
id: branch
run: |
BRANCH_NAME="prerelease/vscode-${{ steps.version.outputs.new_version }}"
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git checkout -b "$BRANCH_NAME"
echo "Created branch: $BRANCH_NAME"
- name: Update package.json version
working-directory: extensions/vscode
run: |
# Update version in package.json
npm version ${{ steps.version.outputs.new_version }} --no-git-tag-version
echo "Updated package.json to version ${{ steps.version.outputs.new_version }}"
- name: Commit version bump
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add extensions/vscode/package.json
git commit -m "chore: bump VSCode extension version to ${{ steps.version.outputs.new_version }}"
echo "Committed version bump"
- name: Push branch and create PR
id: pr
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git push origin "${{ steps.branch.outputs.branch_name }}"
echo "Pushed branch: ${{ steps.branch.outputs.branch_name }}"
# Create pull request
PR_URL=$(gh pr create \
--base main \
--head "${{ steps.branch.outputs.branch_name }}" \
--title "chore: VSCode pre-release ${{ steps.version.outputs.new_version }}" \
--body "$(cat <<'EOF'
## VSCode Pre-release ${{ steps.version.outputs.new_version }}
This PR bumps the VSCode extension version for pre-release.
### Changes
- Version bumped from ${{ steps.version.outputs.previous_version }} to ${{ steps.version.outputs.new_version }}
- Based on commit: ${{ inputs.main_commit_sha }}
### Release Process
After merging this PR:
1. The tag \`${{ steps.version.outputs.tag_name }}\` will be created automatically
2. A GitHub pre-release will be created with auto-generated release notes
🤖 This PR was created automatically by the VSCode Pre-release workflow.
EOF
)")
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
echo "Created PR: $PR_URL"
- name: Auto-merge PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get PR number from URL
PR_NUMBER=$(echo "${{ steps.pr.outputs.pr_url }}" | grep -oE '[0-9]+$')
# Merge the PR
gh pr merge "$PR_NUMBER" --squash --auto
echo "PR #$PR_NUMBER set to auto-merge"
# Wait for merge to complete (with timeout)
echo "Waiting for PR to be merged..."
TIMEOUT=300 # 5 minutes
ELAPSED=0
INTERVAL=10
while [ $ELAPSED -lt $TIMEOUT ]; do
PR_STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state')
if [ "$PR_STATE" = "MERGED" ]; then
echo "PR successfully merged!"
break
fi
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
echo "Still waiting... ($ELAPSED seconds elapsed)"
done
if [ $ELAPSED -ge $TIMEOUT ]; then
echo "Warning: Timed out waiting for PR merge. Please check manually." && exit 1
fi
- name: Checkout main branch
run: |
git fetch origin main
git checkout main
git pull origin main
- name: Create and push tag
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git tag "${{ steps.version.outputs.tag_name }}"
git push origin "${{ steps.version.outputs.tag_name }}"
echo "Created and pushed tag: ${{ steps.version.outputs.tag_name }}"
- name: Get previous tag for release notes
id: prev_tag
run: |
# Find the previous vscode pre-release tag
PREV_TAG=$(git tag -l "v*-vscode" --sort=-version:refname | head -n 2 | tail -n 1)
if [ -z "$PREV_TAG" ]; then
echo "No previous tag found, using first commit"
PREV_TAG=$(git rev-list --max-parents=0 HEAD)
fi
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
echo "Previous tag for release notes: $PREV_TAG"
- name: Create GitHub pre-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Generate release notes between previous tag and current tag
RELEASE_NOTES=$(gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/releases/generate-notes \
-f tag_name="${{ steps.version.outputs.tag_name }}" \
-f target_commitish="main" \
-f previous_tag_name="${{ steps.prev_tag.outputs.prev_tag }}" \
--jq '.body')
# Create the pre-release
gh release create "${{ steps.version.outputs.tag_name }}" \
--title "VSCode Pre-release ${{ steps.version.outputs.new_version }}" \
--notes "$RELEASE_NOTES" \
--prerelease \
--target main
echo "Created pre-release: ${{ steps.version.outputs.tag_name }}"
- name: Summary
run: |
echo "## VSCode Pre-release Created Successfully! 🚀" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Version Information" >> $GITHUB_STEP_SUMMARY
echo "- **Previous Version:** ${{ steps.version.outputs.previous_version }}" >> $GITHUB_STEP_SUMMARY
echo "- **New Version:** ${{ steps.version.outputs.new_version }}" >> $GITHUB_STEP_SUMMARY
echo "- **Tag:** \`${{ steps.version.outputs.tag_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Links" >> $GITHUB_STEP_SUMMARY
echo "- **PR:** ${{ steps.pr.outputs.pr_url }}" >> $GITHUB_STEP_SUMMARY
echo "- **Release:** https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Commit" >> $GITHUB_STEP_SUMMARY
echo "- **Base Commit:** \`${{ inputs.main_commit_sha }}\`" >> $GITHUB_STEP_SUMMARY
vscode-version-bump .github/workflows/vscode-version-bump.yml
View raw YAML
name: Create VS Code main release draft
on:
# Not using this now because making drafts was just noisy. Will be useful when we are ready for automated releases.
# schedule:
# # Runs at 7 AM PST (15:00 UTC) every Friday
# - cron: "0 15 * * 5"
workflow_dispatch:
# Allows manual triggering
jobs:
version-bump:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history and tags
- name: Setup GitHub CLI
run: |
gh auth login --with-token <<< "${{ github.token }}"
- name: Use Node.js from .nvmrc
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Find and process version tags
run: |
echo "Starting version bump process..."
# Find last v1.1.x-vscode tag that's at least 6 days old
CURRENT_TIMESTAMP=$(date +%s)
SIX_DAYS_AGO=$((CURRENT_TIMESTAMP - 6*24*60*60))
echo "Current timestamp: $(date -d @${CURRENT_TIMESTAMP})"
echo "Six days ago: $(date -d @${SIX_DAYS_AGO})"
echo "Looking for v1.1.x-vscode tags..."
git for-each-ref --sort=-creatordate --format '%(refname:short) %(creatordate:iso)' refs/tags | grep 'v1\.1\.[0-9]\+-vscode' || echo "No matching tags found"
LAST_1_1_TAG=$(git for-each-ref --sort=-creatordate --format '%(refname:short) %(creatordate:unix)' refs/tags \
| grep 'v1\.1\.[0-9]\+-vscode' \
| while read tag timestamp; do
if [ $timestamp -le $SIX_DAYS_AGO ]; then
echo ${tag% *}
break
fi
done)
echo "Selected v1.1.x tag: $LAST_1_1_TAG"
if [ -z "$LAST_1_1_TAG" ]; then
echo "::error::No suitable v1.1.x-vscode tag found"
exit 1
fi
# Find last v1.0.y-vscode tag
echo "Looking for v1.0.y-vscode tags..."
git tag --sort=-v:refname | grep '^v1\.0\.[0-9]\+-vscode' || echo "No matching tags found"
LAST_1_0_TAG=$(git tag --sort=-v:refname | grep '^v1\.0\.[0-9]\+-vscode' | head -n1)
echo "Selected v1.0.y tag: $LAST_1_0_TAG"
if [ -z "$LAST_1_0_TAG" ]; then
echo "::error::No v1.0.y-vscode tag found"
exit 1
fi
# Extract the y number and increment it
Y_NUMBER=$(echo $LAST_1_0_TAG | sed 's/v1\.0\.\([0-9]\+\)-vscode/\1/')
NEXT_Y=$((Y_NUMBER + 1))
NEW_BRANCH="v1.0.${NEXT_Y}-vscode"
NEW_VERSION="1.0.${NEXT_Y}"
echo "Current Y number: $Y_NUMBER"
echo "Next Y number: $NEXT_Y"
echo "New branch name: $NEW_BRANCH"
echo "New version: $NEW_VERSION"
# Create new branch from the v1.1.x tag
echo "Creating new branch from $LAST_1_1_TAG..."
git checkout $LAST_1_1_TAG
git checkout -b $NEW_BRANCH
# Update the version in package.json
echo "Current package.json version:"
cat extensions/vscode/package.json | grep version
echo "Updating version in package.json..."
jq ".version = \"$NEW_VERSION\"" extensions/vscode/package.json > temp.json && mv temp.json extensions/vscode/package.json
echo "New package.json version:"
cat extensions/vscode/package.json | grep version
# Configure git
echo "Configuring git..."
git config user.name "GitHub Actions Bot"
git config user.email "actions@github.com"
# Commit and push changes
echo "Committing changes..."
git add extensions/vscode/package.json
git commit -m "Bump VS Code extension to ${NEW_VERSION}"
echo "Pushing branch to origin..."
git push origin $NEW_BRANCH
# Add release creation
echo "Creating draft release..."
gh release create "${NEW_BRANCH}" \
--title "${NEW_BRANCH}" \
--generate-notes \
--draft \
--latest \
--notes-start-tag "${LAST_1_0_TAG}"
echo "Version bump process completed successfully!"
- name: Check for errors
if: failure()
run: |
echo "::error::Failed to process version tags and create new branch"
echo "Last few lines of git log:"
git log -n 5 --oneline
echo "Current git status:"
git status
echo "Current branches:"
git branch -a