From 31e325c7e66688479e0ffdbeb1cae93986c4aabc Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 14:35:31 +0700 Subject: [PATCH 1/6] chore: prune inert upstream workflows, fix the generic CI ones 22 workflows deleted: all repo-gated to anomalyco/opencode, dependent on upstream secrets/infra, dev-branch-only, or reading the removed TEAM_MEMBERS. The 4 generic CI workflows (typecheck, test, nix-eval, storybook) are retargeted dev->main and moved off Blacksmith runners (not installed here; jobs queued forever) to GitHub-hosted ones. Co-Authored-By: Claude Fable 5 --- .github/workflows/beta.yml | 37 -- .github/workflows/close-issues.yml | 24 - .github/workflows/close-prs.yml | 50 -- .github/workflows/compliance-close.yml | 133 ----- .github/workflows/containers.yml | 45 -- .github/workflows/deploy.yml | 48 -- .github/workflows/docs-locale-sync.yml | 100 ---- .github/workflows/docs-update.yml | 72 --- .github/workflows/duplicate-issues.yml | 221 --------- .github/workflows/generate.yml | 51 -- .github/workflows/nix-eval.yml | 6 +- .github/workflows/nix-hashes.yml | 162 ------ .github/workflows/notify-discord.yml | 14 - .github/workflows/opencode.yml | 34 -- .github/workflows/pr-management.yml | 95 ---- .github/workflows/pr-standards.yml | 351 ------------- .github/workflows/publish-github-action.yml | 30 -- .github/workflows/publish-vscode.yml | 37 -- .github/workflows/publish.yml | 521 -------------------- .github/workflows/release-github-action.yml | 29 -- .github/workflows/review.yml | 83 ---- .github/workflows/stats.yml | 35 -- .github/workflows/storybook.yml | 6 +- .github/workflows/test.yml | 14 +- .github/workflows/triage.yml | 56 --- .github/workflows/typecheck.yml | 6 +- 26 files changed, 16 insertions(+), 2244 deletions(-) delete mode 100644 .github/workflows/beta.yml delete mode 100644 .github/workflows/close-issues.yml delete mode 100644 .github/workflows/close-prs.yml delete mode 100644 .github/workflows/compliance-close.yml delete mode 100644 .github/workflows/containers.yml delete mode 100644 .github/workflows/deploy.yml delete mode 100644 .github/workflows/docs-locale-sync.yml delete mode 100644 .github/workflows/docs-update.yml delete mode 100644 .github/workflows/duplicate-issues.yml delete mode 100644 .github/workflows/generate.yml delete mode 100644 .github/workflows/nix-hashes.yml delete mode 100644 .github/workflows/notify-discord.yml delete mode 100644 .github/workflows/opencode.yml delete mode 100644 .github/workflows/pr-management.yml delete mode 100644 .github/workflows/pr-standards.yml delete mode 100644 .github/workflows/publish-github-action.yml delete mode 100644 .github/workflows/publish-vscode.yml delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/release-github-action.yml delete mode 100644 .github/workflows/review.yml delete mode 100644 .github/workflows/stats.yml delete mode 100644 .github/workflows/triage.yml diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml deleted file mode 100644 index e93d5fbdb2..0000000000 --- a/.github/workflows/beta.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: beta - -on: - workflow_dispatch: - schedule: - - cron: "0 * * * *" - -jobs: - sync: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Setup Git Committer - id: setup-git-committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Install OpenCode - run: bun i -g opencode-ai - - - name: Sync beta branch - env: - GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - run: bun script/beta.ts diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml deleted file mode 100644 index b8a2e3f575..0000000000 --- a/.github/workflows/close-issues.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: close-issues - -on: - schedule: - - cron: "0 2 * * *" # Daily at 2:00 AM - workflow_dispatch: - -jobs: - close: - runs-on: ubuntu-latest - permissions: - contents: read - issues: write - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 - with: - bun-version: latest - - - name: Close stale issues - env: - GITHUB_TOKEN: ${{ github.token }} - run: bun script/github/close-issues.ts diff --git a/.github/workflows/close-prs.yml b/.github/workflows/close-prs.yml deleted file mode 100644 index a1e603a881..0000000000 --- a/.github/workflows/close-prs.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: close-prs - -on: - schedule: - - cron: "0 22 * * *" # Daily at 10:00 PM UTC - workflow_dispatch: - inputs: - dry-run: - description: "Log matching PRs without closing them" - type: boolean - default: true - max-close: - description: "Maximum matching PRs to close" - type: string - required: false - default: "50" - -jobs: - close: - runs-on: ubuntu-latest - timeout-minutes: 240 - permissions: - contents: read - issues: write - pull-requests: write - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 - with: - bun-version: latest - - - name: Close old PRs without enough positive reactions - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - max_close="${{ inputs['max-close'] }}" - if [ -z "$max_close" ]; then - max_close="50" - fi - - args=("--threshold" "2" "--age-months" "1" "--sleep-ms" "20000" "--max-close" "$max_close") - - if [ "${{ github.event_name }}" = "schedule" ]; then - args+=("--execute") - elif [ "${{ inputs['dry-run'] }}" = "false" ]; then - args+=("--execute") - fi - - bun script/github/close-prs.ts "${args[@]}" diff --git a/.github/workflows/compliance-close.yml b/.github/workflows/compliance-close.yml deleted file mode 100644 index a83824e5cf..0000000000 --- a/.github/workflows/compliance-close.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: compliance-close - -on: - schedule: - # Run every 30 minutes to check for expired compliance windows - - cron: "*/30 * * * *" - workflow_dispatch: - -permissions: - contents: read - issues: write - pull-requests: write - -jobs: - close-non-compliant: - runs-on: ubuntu-latest - steps: - - name: Close non-compliant issues and PRs after 2 hours - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 - with: - script: | - const { data: items } = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - labels: 'needs:compliance', - state: 'open', - per_page: 100, - }); - - if (items.length === 0) { - core.info('No open issues/PRs with needs:compliance label'); - return; - } - - const now = Date.now(); - const twoHours = 2 * 60 * 60 * 1000; - const orgMemberAssociations = new Set(['OWNER', 'MEMBER']); - const agentLogin = 'opencode-agent[bot]'; - const { data: file } = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: '.github/TEAM_MEMBERS', - ref: 'dev', - }); - const teamMembers = new Set( - Buffer.from(file.content, 'base64') - .toString() - .split('\n') - .map((line) => line.trim().toLowerCase()) - .filter(Boolean) - ); - - function isExempt(item) { - const login = item.user?.login?.toLowerCase(); - return ( - login === agentLogin || - orgMemberAssociations.has(item.author_association) || - (login && teamMembers.has(login)) - ); - } - - for (const item of items) { - const isPR = !!item.pull_request; - const kind = isPR ? 'PR' : 'issue'; - const login = item.user?.login; - - if (isExempt(item)) { - core.info(`Skipping ${kind} #${item.number}; author ${login || 'unknown'} is exempt`); - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: item.number, - name: 'needs:compliance', - }); - } catch (e) {} - continue; - } - - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: item.number, - }); - - const complianceComment = comments.find(c => c.body.includes('')); - if (!complianceComment) continue; - - const commentAge = now - new Date(complianceComment.created_at).getTime(); - if (commentAge < twoHours) { - core.info(`${kind} #${item.number} still within 2-hour window (${Math.round(commentAge / 60000)}m elapsed)`); - continue; - } - - const closeMessage = isPR - ? 'This pull request has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new pull request that follows our guidelines.' - : 'This issue has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new issue that follows our issue templates.'; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: item.number, - body: closeMessage, - }); - - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: item.number, - name: 'needs:compliance', - }); - } catch (e) {} - - if (isPR) { - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: item.number, - state: 'closed', - }); - } else { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: item.number, - state: 'closed', - state_reason: 'not_planned', - }); - } - - core.info(`Closed non-compliant ${kind} #${item.number} after 2-hour window`); - } diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml deleted file mode 100644 index 15bf078316..0000000000 --- a/.github/workflows/containers.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: containers - -on: - push: - branches: - - dev - paths: - - packages/containers/** - - .github/workflows/containers.yml - - package.json - workflow_dispatch: - -permissions: - contents: read - packages: write - -jobs: - build: - runs-on: blacksmith-4vcpu-ubuntu-2404 - env: - REGISTRY: ghcr.io/${{ github.repository_owner }} - TAG: "24.04" - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - uses: ./.github/actions/setup-bun - - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - - name: Login to GHCR - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push containers - run: bun ./packages/containers/script/build.ts --push - env: - REGISTRY: ${{ env.REGISTRY }} - TAG: ${{ env.TAG }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 18e6cf7acb..0000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: deploy - -on: - push: - branches: - - dev - - production - workflow_dispatch: - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: read - id-token: write - -jobs: - deploy: - if: github.repository == 'anomalyco/opencode' && (github.ref_name == 'dev' || github.ref_name == 'production') - runs-on: ubuntu-latest - environment: ${{ github.ref_name }} - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - - uses: ./.github/actions/setup-bun - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: "24" - - - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 - with: - role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }} - role-session-name: opencode-${{ github.run_id }} - aws-region: us-east-1 - - - run: bun sst deploy --stage=${{ github.ref_name }} - env: - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - PLANETSCALE_SERVICE_TOKEN_NAME: ${{ secrets.PLANETSCALE_SERVICE_TOKEN_NAME }} - PLANETSCALE_SERVICE_TOKEN: ${{ secrets.PLANETSCALE_SERVICE_TOKEN }} - STRIPE_SECRET_KEY: ${{ github.ref_name == 'production' && secrets.STRIPE_SECRET_KEY_PROD || secrets.STRIPE_SECRET_KEY_DEV }} - HONEYCOMB_API_KEY: ${{ secrets.HONEYCOMB_API_KEY }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - SENTRY_PROJECT: ${{ vars.WEB_SENTRY_PROJECT }} - SENTRY_RELEASE: web@${{ github.sha }} - VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} - VITE_SENTRY_RELEASE: web@${{ github.sha }} diff --git a/.github/workflows/docs-locale-sync.yml b/.github/workflows/docs-locale-sync.yml deleted file mode 100644 index 5f921e8bb7..0000000000 --- a/.github/workflows/docs-locale-sync.yml +++ /dev/null @@ -1,100 +0,0 @@ -name: docs-locale-sync - -on: - push: - branches: - - dev - paths: - - packages/web/src/content/docs/*.mdx - -jobs: - sync-locales: - if: false - #if: github.actor != 'opencode-agent[bot]' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - persist-credentials: false - fetch-depth: 0 - ref: ${{ github.ref_name }} - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Compute changed English docs - id: changes - run: | - FILES=$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" -- ':(glob)packages/web/src/content/docs/*.mdx' || true) - if [ -z "$FILES" ]; then - echo "has_changes=false" >> "$GITHUB_OUTPUT" - echo "No English docs changed in push range" - exit 0 - fi - echo "has_changes=true" >> "$GITHUB_OUTPUT" - { - echo "files<> "$GITHUB_OUTPUT" - - - name: Install OpenCode - if: steps.changes.outputs.has_changes == 'true' - run: curl -fsSL https://opencode.ai/install | bash - - - name: Sync locale docs with OpenCode - if: steps.changes.outputs.has_changes == 'true' - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENCODE_CONFIG_CONTENT: | - { - "permission": { - "*": "deny", - "read": "allow", - "edit": "allow", - "glob": "allow", - "task": "allow" - } - } - run: | - opencode run --agent docs --model opencode/gpt-5.3-codex <<'EOF' - Update localized docs to match the latest English docs changes. - - Changed English doc files: - - ${{ steps.changes.outputs.files }} - - - Requirements: - 1. Update all relevant locale docs under packages/web/src/content/docs// so they reflect these English page changes. - 2. You MUST use the Task tool for translation work and launch subagents with subagent_type `translator` (defined in .opencode/agent/translator.md). - 3. Do not translate directly in the primary agent. Use translator subagent output as the source for locale text updates. - 4. Run translator subagent Task calls in parallel whenever file/locale translation work is independent. - 5. Use only the minimum tools needed for this task (read/glob, file edits, and translator Task). Do not use shell, web, search, or GitHub tools for translation work. - 6. Preserve frontmatter keys, internal links, code blocks, and existing locale-specific metadata unless the English change requires an update. - 7. Keep locale docs structure aligned with their corresponding English pages. - 8. Do not modify English source docs in packages/web/src/content/docs/*.mdx. - 9. If no locale updates are needed, make no changes. - EOF - - - name: Commit and push locale docs updates - if: steps.changes.outputs.has_changes == 'true' - run: | - if [ -z "$(git status --porcelain)" ]; then - echo "No locale docs changes to commit" - exit 0 - fi - git add -A - git commit -m "docs(i18n): sync locale docs from english changes" - git pull --rebase --autostash origin "$GITHUB_REF_NAME" - git push origin HEAD:"$GITHUB_REF_NAME" diff --git a/.github/workflows/docs-update.yml b/.github/workflows/docs-update.yml deleted file mode 100644 index 4767dec539..0000000000 --- a/.github/workflows/docs-update.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: docs-update - -on: - schedule: - - cron: "0 */12 * * *" - workflow_dispatch: - -env: - LOOKBACK_HOURS: 4 - -jobs: - update-docs: - if: github.repository == 'sst/opencode' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - id-token: write - contents: write - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 # Fetch full history to access commits - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Get recent commits - id: commits - run: | - COMMITS=$(git log --since="${{ env.LOOKBACK_HOURS }} hours ago" --pretty=format:"- %h %s" 2>/dev/null || echo "") - if [ -z "$COMMITS" ]; then - echo "No commits in the last ${{ env.LOOKBACK_HOURS }} hours" - echo "has_commits=false" >> $GITHUB_OUTPUT - else - echo "has_commits=true" >> $GITHUB_OUTPUT - { - echo "list<> $GITHUB_OUTPUT - fi - - - name: Run opencode - if: steps.commits.outputs.has_commits == 'true' - uses: sst/opencode/github@2c14fc5586fe0b88e5c04732d2e846769cc35671 # latest - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - with: - model: opencode/gpt-5.2 - agent: docs - prompt: | - Review the following commits from the last ${{ env.LOOKBACK_HOURS }} hours and identify any new features that may need documentation. - - - ${{ steps.commits.outputs.list }} - - - Steps: - 1. For each commit that looks like a new feature or significant change: - - Read the changed files to understand what was added - - Check if the feature is already documented in packages/web/src/content/docs/* - 2. If you find undocumented features: - - Update the relevant documentation files in packages/web/src/content/docs/* - - Follow the existing documentation style and structure - - Make sure to document the feature clearly with examples where appropriate - 3. If all new features are already documented, report that no updates are needed - 4. If you are creating a new documentation file be sure to update packages/web/astro.config.mjs too. - - Focus on user-facing features and API changes. Skip internal refactors, bug fixes, and test updates unless they affect user-facing behavior. - Don't feel the need to document every little thing. It is perfectly okay to make 0 changes at all. - Try to keep documentation only for large features or changes that already have a good spot to be documented. diff --git a/.github/workflows/duplicate-issues.yml b/.github/workflows/duplicate-issues.yml deleted file mode 100644 index 3972247daf..0000000000 --- a/.github/workflows/duplicate-issues.yml +++ /dev/null @@ -1,221 +0,0 @@ -name: duplicate-issues - -on: - issues: - types: [opened, edited] - -jobs: - check-duplicates: - if: github.event.action == 'opened' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 1 - - - name: Check exempt issue author - id: author - run: | - LOGIN="${{ github.event.issue.user.login }}" - ASSOCIATION="${{ github.event.issue.author_association }}" - - if [ "$LOGIN" = "opencode-agent[bot]" ] || - [ "$ASSOCIATION" = "OWNER" ] || - [ "$ASSOCIATION" = "MEMBER" ] || - grep -qxiF "$LOGIN" .github/TEAM_MEMBERS; then - echo "skip=true" >> "$GITHUB_OUTPUT" - echo "Skipping issue automation for exempt author: $LOGIN ($ASSOCIATION)" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - uses: ./.github/actions/setup-bun - if: steps.author.outputs.skip != 'true' - - - name: Install opencode - if: steps.author.outputs.skip != 'true' - run: curl -fsSL https://opencode.ai/install | bash - - - name: Check duplicates and compliance - if: steps.author.outputs.skip != 'true' - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENCODE_PERMISSION: | - { - "bash": { - "*": "deny", - "gh issue*": "allow" - }, - "webfetch": "deny" - } - run: | - opencode run -m opencode/claude-sonnet-4-6 "A new issue has been created: - - Issue number: ${{ github.event.issue.number }} - Issue author association: ${{ github.event.issue.author_association }} - - Lookup this issue with gh issue view ${{ github.event.issue.number }}. - - You have TWO tasks. Perform both, then post a SINGLE comment (if needed). - - --- - - TASK 1: CONTRIBUTING GUIDELINES COMPLIANCE CHECK - - Check whether the issue follows our contributing guidelines and issue templates. - - If the issue author association is OWNER or MEMBER, skip this compliance check. Do not add the needs:compliance label for organization-owned issues. - - This project has three issue templates that every issue MUST use one of: - - 1. Bug Report - requires a Description field with real content - 2. Feature Request - requires a verification checkbox and description, title should start with [FEATURE]: - 3. Question - requires the Question field with real content - - Additionally check: - - No AI-generated walls of text (long, AI-generated descriptions are not acceptable) - - The issue has real content, not just template placeholder text left unchanged - - Bug reports should include some context about how to reproduce - - Feature requests should explain the problem or need - - We want to push for having the user provide system description & information - - Do NOT be nitpicky about optional fields. Only flag real problems like: no template used, required fields empty or placeholder text only, obviously AI-generated walls of text, or completely empty/nonsensical content. - - --- - - TASK 2: DUPLICATE CHECK - - Search through existing issues (excluding #${{ github.event.issue.number }}) to find potential duplicates. - Consider: - 1. Similar titles or descriptions - 2. Same error messages or symptoms - 3. Related functionality or components - 4. Similar feature requests - - Additionally, if the issue mentions keybinds, keyboard shortcuts, or key bindings, note the pinned keybinds issue #4997. - - --- - - POSTING YOUR COMMENT: - - Based on your findings, post a SINGLE comment on issue #${{ github.event.issue.number }}. Build the comment as follows: - - If the issue is NOT compliant and the author association is not OWNER or MEMBER, start the comment with: - - Then explain what needs to be fixed and that they have 2 hours to edit the issue before it is automatically closed. Also add the label needs:compliance to the issue using: gh issue edit ${{ github.event.issue.number }} --add-label needs:compliance - - If duplicates were found, include a section about potential duplicates with links. - - If the issue mentions keybinds/keyboard shortcuts, include a note about #4997. - - If the issue IS compliant AND no duplicates were found AND no keybind reference, do NOT comment at all. - - Use this format for the comment: - - [If not compliant:] - - This issue doesn't fully meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md). - - **What needs to be fixed:** - - [specific reasons] - - Please edit this issue to address the above within **2 hours**, or it will be automatically closed. - - [If duplicates found, add:] - --- - This issue might be a duplicate of existing issues. Please check: - - #[issue_number]: [brief description of similarity] - - [If keybind-related, add:] - For keybind-related issues, please also check our pinned keybinds documentation: #4997 - - [End with if not compliant:] - If you believe this was flagged incorrectly, please let a maintainer know. - - Remember: post at most ONE comment combining all findings. If everything is fine, post nothing." - - recheck-compliance: - if: github.event.action == 'edited' && contains(github.event.issue.labels.*.name, 'needs:compliance') - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 1 - - - name: Check exempt issue author - id: author - run: | - LOGIN="${{ github.event.issue.user.login }}" - ASSOCIATION="${{ github.event.issue.author_association }}" - - if [ "$LOGIN" = "opencode-agent[bot]" ] || - [ "$ASSOCIATION" = "OWNER" ] || - [ "$ASSOCIATION" = "MEMBER" ] || - grep -qxiF "$LOGIN" .github/TEAM_MEMBERS; then - echo "skip=true" >> "$GITHUB_OUTPUT" - echo "Skipping issue automation for exempt author: $LOGIN ($ASSOCIATION)" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - uses: ./.github/actions/setup-bun - if: steps.author.outputs.skip != 'true' - - - name: Install opencode - if: steps.author.outputs.skip != 'true' - run: curl -fsSL https://opencode.ai/install | bash - - - name: Recheck compliance - if: steps.author.outputs.skip != 'true' - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENCODE_PERMISSION: | - { - "bash": { - "*": "deny", - "gh issue*": "allow" - }, - "webfetch": "deny" - } - run: | - opencode run -m opencode/claude-sonnet-4-6 "Issue #${{ github.event.issue.number }} was previously flagged as non-compliant and has been edited. - Issue author association: ${{ github.event.issue.author_association }} - - Lookup this issue with gh issue view ${{ github.event.issue.number }}. - - If the issue author association is OWNER or MEMBER, remove the needs:compliance label if present, delete the previous compliance comment if present, and do not post a new comment. - - Re-check whether the issue now follows our contributing guidelines and issue templates. - - This project has three issue templates that every issue MUST use one of: - - 1. Bug Report - requires a Description field with real content - 2. Feature Request - requires a verification checkbox and description, title should start with [FEATURE]: - 3. Question - requires the Question field with real content - - Additionally check: - - No AI-generated walls of text (long, AI-generated descriptions are not acceptable) - - The issue has real content, not just template placeholder text left unchanged - - Bug reports should include some context about how to reproduce - - Feature requests should explain the problem or need - - We want to push for having the user provide system description & information - - Do NOT be nitpicky about optional fields. Only flag real problems like: no template used, required fields empty or placeholder text only, obviously AI-generated walls of text, or completely empty/nonsensical content. - - If the issue is NOW compliant: - 1. Remove the needs:compliance label: gh issue edit ${{ github.event.issue.number }} --remove-label needs:compliance - 2. Find and delete the previous compliance comment (the one containing ) using: gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments --jq '.[] | select(.body | contains(\"\")) | .id' then delete it with: gh api -X DELETE repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments/{id} - 3. Post a short comment thanking them for updating the issue. - - If the issue is STILL not compliant: - Post a comment explaining what still needs to be fixed. Keep the needs:compliance label." diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml deleted file mode 100644 index 324cfec020..0000000000 --- a/.github/workflows/generate.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: generate - -on: - push: - branches: - - dev - -jobs: - generate: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Generate - run: ./script/generate.ts - - - name: Commit and push - run: | - if [ -z "$(git status --porcelain)" ]; then - echo "No changes to commit" - exit 0 - fi - git add -A - git commit -m "chore: generate" --allow-empty - git push origin HEAD:${{ github.ref_name }} --no-verify - # if ! git push origin HEAD:${{ github.event.pull_request.head.ref || github.ref_name }} --no-verify; then - # echo "" - # echo "============================================" - # echo "Failed to push generated code." - # echo "Please run locally and push:" - # echo "" - # echo " ./script/generate.ts" - # echo " git add -A && git commit -m \"chore: generate\" && git push" - # echo "" - # echo "============================================" - # exit 1 - # fi diff --git a/.github/workflows/nix-eval.yml b/.github/workflows/nix-eval.yml index 75332695a1..0419db0254 100644 --- a/.github/workflows/nix-eval.yml +++ b/.github/workflows/nix-eval.yml @@ -2,9 +2,9 @@ name: nix-eval on: push: - branches: [dev] + branches: [main] pull_request: - branches: [dev] + branches: [main] workflow_dispatch: concurrency: @@ -16,7 +16,7 @@ permissions: jobs: nix-eval: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Checkout repository diff --git a/.github/workflows/nix-hashes.yml b/.github/workflows/nix-hashes.yml deleted file mode 100644 index ce1d9237fd..0000000000 --- a/.github/workflows/nix-hashes.yml +++ /dev/null @@ -1,162 +0,0 @@ -name: nix-hashes - -permissions: - contents: write - -on: - workflow_dispatch: - push: - branches: [dev, beta] - paths: - - "bun.lock" - - "package.json" - - "packages/*/package.json" - - "flake.lock" - - "nix/node_modules.nix" - - "nix/scripts/**" - - "patches/**" - - ".github/workflows/nix-hashes.yml" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - # Native runners required: bun install cross-compilation flags (--os/--cpu) - # do not produce byte-identical node_modules as native installs. - compute-hash: - strategy: - fail-fast: false - matrix: - include: - - system: x86_64-linux - runner: blacksmith-4vcpu-ubuntu-2404 - - system: aarch64-linux - runner: blacksmith-4vcpu-ubuntu-2404-arm - - system: x86_64-darwin - runner: macos-15-intel - - system: aarch64-darwin - runner: macos-latest - runs-on: ${{ matrix.runner }} - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Setup Nix - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 # v34 - - - name: Compute node_modules hash - id: hash - env: - SYSTEM: ${{ matrix.system }} - run: | - set -euo pipefail - - BUILD_LOG=$(mktemp) - trap 'rm -f "$BUILD_LOG"' EXIT - - HASH="" - MAX_ATTEMPTS=3 - for ((ATTEMPT = 1; ATTEMPT <= MAX_ATTEMPTS; ATTEMPT++)); do - # Build with fakeHash to trigger hash mismatch and reveal correct hash - nix build ".#packages.${SYSTEM}.node_modules_updater" --no-link 2>&1 | tee "$BUILD_LOG" || true - - HASH="$(nix run --inputs-from . nixpkgs#gnugrep -- -oP 'got:\s*\Ksha256-[A-Za-z0-9+/=]+' "$BUILD_LOG" | tail -n1 || true)" - - [ -n "$HASH" ] && break - - if [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; then - echo "::warning::Attempt ${ATTEMPT}/${MAX_ATTEMPTS} produced no hash for ${SYSTEM}; retrying in $((ATTEMPT * 10))s" - sleep $((ATTEMPT * 10)) - fi - done - - if [ -z "$HASH" ]; then - echo "::error::Failed to compute hash for ${SYSTEM} after ${MAX_ATTEMPTS} attempts" - cat "$BUILD_LOG" - exit 1 - fi - - echo "$HASH" > hash.txt - echo "Computed hash for ${SYSTEM}: $HASH" - - - name: Upload hash - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: hash-${{ matrix.system }} - path: hash.txt - retention-days: 1 - - update-hashes: - needs: compute-hash - if: github.event_name != 'pull_request' - runs-on: blacksmith-4vcpu-ubuntu-2404 - - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - persist-credentials: false - fetch-depth: 0 - ref: ${{ github.ref_name }} - - - name: Setup git committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Pull latest changes - run: | - git pull --rebase --autostash origin "$GITHUB_REF_NAME" - - - name: Download hash artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - path: hashes - pattern: hash-* - - - name: Update hashes.json - run: | - set -euo pipefail - - HASH_FILE="nix/hashes.json" - - [ -f "$HASH_FILE" ] || echo '{"nodeModules":{}}' > "$HASH_FILE" - - for SYSTEM in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do - FILE="hashes/hash-${SYSTEM}/hash.txt" - if [ -f "$FILE" ]; then - HASH="$(tr -d '[:space:]' < "$FILE")" - echo "${SYSTEM}: ${HASH}" - jq --arg sys "$SYSTEM" --arg h "$HASH" '.nodeModules[$sys] = $h' "$HASH_FILE" > tmp.json - mv tmp.json "$HASH_FILE" - else - echo "::warning::Missing hash for ${SYSTEM}" - fi - done - - cat "$HASH_FILE" - - - name: Commit changes - run: | - set -euo pipefail - - HASH_FILE="nix/hashes.json" - - if [ -z "$(git status --short -- "$HASH_FILE")" ]; then - echo "No changes to commit" - echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" - echo "Status: no changes" >> "$GITHUB_STEP_SUMMARY" - exit 0 - fi - - git add "$HASH_FILE" - git commit -m "chore: update nix node_modules hashes" - - git pull --rebase --autostash origin "$GITHUB_REF_NAME" - git push origin HEAD:"$GITHUB_REF_NAME" - - echo "### Nix hashes" >> "$GITHUB_STEP_SUMMARY" - echo "Status: committed $(git rev-parse --short HEAD)" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/notify-discord.yml b/.github/workflows/notify-discord.yml deleted file mode 100644 index 0b2b1cde05..0000000000 --- a/.github/workflows/notify-discord.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: notify-discord - -on: - release: - types: [released] # fires when a draft release is published - -jobs: - notify: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - name: Send nicely-formatted embed to Discord - uses: SethCohen/github-releases-to-discord@24d166886aee4646d448c8a389ff9e1ebcab3682 # v1.20.0 - with: - webhook_url: ${{ secrets.DISCORD_WEBHOOK }} diff --git a/.github/workflows/opencode.yml b/.github/workflows/opencode.yml deleted file mode 100644 index 3469c21917..0000000000 --- a/.github/workflows/opencode.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: opencode - -on: - issue_comment: - types: [created] - pull_request_review_comment: - types: [created] - -jobs: - opencode: - if: | - contains(github.event.comment.body, ' /oc') || - startsWith(github.event.comment.body, '/oc') || - contains(github.event.comment.body, ' /opencode') || - startsWith(github.event.comment.body, '/opencode') - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - id-token: write - contents: read - pull-requests: read - issues: read - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - uses: ./.github/actions/setup-bun - - - name: Run opencode - uses: anomalyco/opencode/github@2c14fc5586fe0b88e5c04732d2e846769cc35671 # latest - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENCODE_PERMISSION: '{"bash": "deny"}' - with: - model: opencode/claude-opus-4-5 diff --git a/.github/workflows/pr-management.yml b/.github/workflows/pr-management.yml deleted file mode 100644 index b6aa4e589d..0000000000 --- a/.github/workflows/pr-management.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: pr-management - -on: - pull_request_target: - types: [opened] - -jobs: - check-duplicates: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 1 - - - name: Check team membership - id: team-check - run: | - LOGIN="${{ github.event.pull_request.user.login }}" - if [ "$LOGIN" = "opencode-agent[bot]" ] || grep -qxF "$LOGIN" .github/TEAM_MEMBERS; then - echo "is_team=true" >> "$GITHUB_OUTPUT" - echo "Skipping: $LOGIN is a team member or bot" - else - echo "is_team=false" >> "$GITHUB_OUTPUT" - fi - - - name: Setup Bun - if: steps.team-check.outputs.is_team != 'true' - uses: ./.github/actions/setup-bun - - - name: Install dependencies - if: steps.team-check.outputs.is_team != 'true' - run: bun install - - - name: Install opencode - if: steps.team-check.outputs.is_team != 'true' - run: curl -fsSL https://opencode.ai/install | bash - - - name: Build prompt - if: steps.team-check.outputs.is_team != 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: | - { - echo "Check for duplicate PRs related to this new PR:" - echo "" - echo "CURRENT_PR_NUMBER: $PR_NUMBER" - echo "" - echo "Title: $(gh pr view "$PR_NUMBER" --json title --jq .title)" - echo "" - echo "Description:" - gh pr view "$PR_NUMBER" --json body --jq .body - } > pr_info.txt - - - name: Check for duplicate PRs - if: steps.team-check.outputs.is_team != 'true' - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: | - COMMENT=$(bun script/duplicate-pr.ts -f pr_info.txt "Check the attached file for PR details and search for duplicates") - - if [ "$COMMENT" != "No duplicate PRs found" ]; then - gh pr comment "$PR_NUMBER" --body "_The following comment was made by an LLM, it may be inaccurate:_ - - $COMMENT" - fi - - add-contributor-label: - runs-on: ubuntu-latest - permissions: - pull-requests: write - issues: write - steps: - - name: Add Contributor Label - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const isPR = !!context.payload.pull_request; - const issueNumber = isPR ? context.payload.pull_request.number : context.payload.issue.number; - const authorAssociation = isPR ? context.payload.pull_request.author_association : context.payload.issue.author_association; - - if (authorAssociation === 'CONTRIBUTOR') { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - labels: ['contributor'] - }); - } diff --git a/.github/workflows/pr-standards.yml b/.github/workflows/pr-standards.yml deleted file mode 100644 index 06838089d3..0000000000 --- a/.github/workflows/pr-standards.yml +++ /dev/null @@ -1,351 +0,0 @@ -name: pr-standards - -on: - pull_request_target: - types: [opened, edited, synchronize] - -jobs: - check-standards: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - name: Check PR standards - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 - with: - script: | - const pr = context.payload.pull_request; - const login = pr.user.login; - - // Skip PRs older than Feb 18, 2026 at 6PM EST (Feb 19, 2026 00:00 UTC) - const cutoff = new Date('2026-02-19T00:00:00Z'); - const prCreated = new Date(pr.created_at); - if (prCreated < cutoff) { - console.log(`Skipping: PR #${pr.number} was created before cutoff (${prCreated.toISOString()})`); - return; - } - - // Check if author is a team member or bot - if (login === 'opencode-agent[bot]') return; - const { data: file } = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: '.github/TEAM_MEMBERS', - ref: 'dev' - }); - const members = Buffer.from(file.content, 'base64').toString().split('\n').map(l => l.trim()).filter(Boolean); - if (members.includes(login)) { - console.log(`Skipping: ${login} is a team member`); - return; - } - - const title = pr.title; - - async function addLabel(label) { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - labels: [label] - }); - } - - async function removeLabel(label) { - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - name: label - }); - } catch (e) { - // Label wasn't present, ignore - } - } - - async function comment(marker, body) { - const markerText = ``; - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number - }); - - const existing = comments.find(c => c.body.includes(markerText)); - if (existing) return; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - body: markerText + '\n' + body - }); - } - - // Step 1: Check title format - // Matches: feat:, feat(scope):, feat (scope):, etc. - const titlePattern = /^(feat|fix|docs|chore|refactor|test)\s*(\([a-zA-Z0-9-]+\))?\s*:/; - const hasValidTitle = titlePattern.test(title); - - if (!hasValidTitle) { - await addLabel('needs:title'); - await comment('title', `Hey! Your PR title \`${title}\` doesn't follow conventional commit format. - - Please update it to start with one of: - - \`feat:\` or \`feat(scope):\` new feature - - \`fix:\` or \`fix(scope):\` bug fix - - \`docs:\` or \`docs(scope):\` documentation changes - - \`chore:\` or \`chore(scope):\` maintenance tasks - - \`refactor:\` or \`refactor(scope):\` code refactoring - - \`test:\` or \`test(scope):\` adding or updating tests - - Where \`scope\` is the package name (e.g., \`app\`, \`desktop\`, \`opencode\`). - - See [CONTRIBUTING.md](../blob/dev/CONTRIBUTING.md#pr-titles) for details.`); - return; - } - - await removeLabel('needs:title'); - - // Step 2: Check for linked issue (skip for docs/refactor/feat PRs) - const skipIssueCheck = /^(docs|refactor|feat)\s*(\([a-zA-Z0-9-]+\))?\s*:/.test(title); - if (skipIssueCheck) { - await removeLabel('needs:issue'); - console.log('Skipping issue check for docs/refactor/feat PR'); - return; - } - const query = ` - query($owner: String!, $repo: String!, $number: Int!) { - repository(owner: $owner, name: $repo) { - pullRequest(number: $number) { - closingIssuesReferences(first: 1) { - totalCount - } - } - } - } - `; - - const result = await github.graphql(query, { - owner: context.repo.owner, - repo: context.repo.repo, - number: pr.number - }); - - const linkedIssues = result.repository.pullRequest.closingIssuesReferences.totalCount; - - if (linkedIssues === 0) { - await addLabel('needs:issue'); - await comment('issue', `Thanks for your contribution! - - This PR doesn't have a linked issue. All PRs must reference an existing issue. - - Please: - 1. Open an issue describing the bug/feature (if one doesn't exist) - 2. Add \`Fixes #\` or \`Closes #\` to this PR description - - See [CONTRIBUTING.md](../blob/dev/CONTRIBUTING.md#issue-first-policy) for details.`); - return; - } - - await removeLabel('needs:issue'); - console.log('PR meets all standards'); - - check-compliance: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - name: Check PR template compliance - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 - with: - script: | - const pr = context.payload.pull_request; - const login = pr.user.login; - - // Skip PRs older than Feb 18, 2026 at 6PM EST (Feb 19, 2026 00:00 UTC) - const cutoff = new Date('2026-02-19T00:00:00Z'); - const prCreated = new Date(pr.created_at); - if (prCreated < cutoff) { - console.log(`Skipping: PR #${pr.number} was created before cutoff (${prCreated.toISOString()})`); - return; - } - - // Check if author is a team member or bot - if (login === 'opencode-agent[bot]') return; - const { data: file } = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: '.github/TEAM_MEMBERS', - ref: 'dev' - }); - const members = Buffer.from(file.content, 'base64').toString().split('\n').map(l => l.trim()).filter(Boolean); - if (members.includes(login)) { - console.log(`Skipping: ${login} is a team member`); - return; - } - - const body = pr.body || ''; - const title = pr.title; - const isDocsRefactorOrFeat = /^(docs|refactor|feat)\s*(\([a-zA-Z0-9-]+\))?\s*:/.test(title); - - const issues = []; - - // Check: template sections exist - const hasWhatSection = /### What does this PR do\?/.test(body); - const hasTypeSection = /### Type of change/.test(body); - const hasVerifySection = /### How did you verify your code works\?/.test(body); - const hasChecklistSection = /### Checklist/.test(body); - const hasIssueSection = /### Issue for this PR/.test(body); - - if (!hasWhatSection || !hasTypeSection || !hasVerifySection || !hasChecklistSection || !hasIssueSection) { - issues.push('PR description is missing required template sections. Please use the [PR template](../blob/dev/.github/pull_request_template.md).'); - } - - // Check: "What does this PR do?" has real content (not just placeholder text) - if (hasWhatSection) { - const whatMatch = body.match(/### What does this PR do\?\s*\n([\s\S]*?)(?=###|$)/); - const whatContent = whatMatch ? whatMatch[1].trim() : ''; - const placeholder = 'Please provide a description of the issue'; - const onlyPlaceholder = whatContent.includes(placeholder) && whatContent.replace(placeholder, '').replace(/[*\s]/g, '').length < 20; - if (!whatContent || onlyPlaceholder) { - issues.push('"What does this PR do?" section is empty or only contains placeholder text. Please describe your changes.'); - } - } - - // Check: at least one "Type of change" checkbox is checked - if (hasTypeSection) { - const typeMatch = body.match(/### Type of change\s*\n([\s\S]*?)(?=###|$)/); - const typeContent = typeMatch ? typeMatch[1] : ''; - const hasCheckedBox = /- \[x\]/i.test(typeContent); - if (!hasCheckedBox) { - issues.push('No "Type of change" checkbox is checked. Please select at least one.'); - } - } - - // Check: issue reference (skip for docs/refactor/feat) - if (!isDocsRefactorOrFeat && hasIssueSection) { - const issueMatch = body.match(/### Issue for this PR\s*\n([\s\S]*?)(?=###|$)/); - const issueContent = issueMatch ? issueMatch[1].trim() : ''; - const hasIssueRef = /(closes|fixes|resolves)\s+#\d+/i.test(issueContent) || /#\d+/.test(issueContent); - if (!hasIssueRef) { - issues.push('No issue referenced. Please add `Closes #` linking to the relevant issue.'); - } - } - - // Check: "How did you verify" has content - if (hasVerifySection) { - const verifyMatch = body.match(/### How did you verify your code works\?\s*\n([\s\S]*?)(?=###|$)/); - const verifyContent = verifyMatch ? verifyMatch[1].trim() : ''; - if (!verifyContent) { - issues.push('"How did you verify your code works?" section is empty. Please explain how you tested.'); - } - } - - // Check: checklist boxes are checked - if (hasChecklistSection) { - const checklistMatch = body.match(/### Checklist\s*\n([\s\S]*?)(?=###|$)/); - const checklistContent = checklistMatch ? checklistMatch[1] : ''; - const unchecked = (checklistContent.match(/- \[ \]/g) || []).length; - const checked = (checklistContent.match(/- \[x\]/gi) || []).length; - if (checked < 2) { - issues.push('Not all checklist items are checked. Please confirm you have tested locally and have not included unrelated changes.'); - } - } - - // Helper functions - async function addLabel(label) { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - labels: [label] - }); - } - - async function removeLabel(label) { - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - name: label - }); - } catch (e) {} - } - - const hasComplianceLabel = pr.labels.some(l => l.name === 'needs:compliance'); - - if (issues.length > 0) { - // Non-compliant - if (!hasComplianceLabel) { - await addLabel('needs:compliance'); - } - - const marker = ''; - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number - }); - const existing = comments.find(c => c.body.includes(marker)); - - const body_text = `${marker} - This PR doesn't fully meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) and [PR template](../blob/dev/.github/pull_request_template.md). - - **What needs to be fixed:** - ${issues.map(i => `- ${i}`).join('\n')} - - Please edit this PR description to address the above within **2 hours**, or it will be automatically closed. - - If you believe this was flagged incorrectly, please let a maintainer know.`; - - if (existing) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id, - body: body_text - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - body: body_text - }); - } - - console.log(`PR #${pr.number} is non-compliant: ${issues.join(', ')}`); - } else if (hasComplianceLabel) { - // Was non-compliant, now fixed - await removeLabel('needs:compliance'); - - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number - }); - const marker = ''; - const existing = comments.find(c => c.body.includes(marker)); - if (existing) { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id - }); - } - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - body: 'Thanks for updating your PR! It now meets our contributing guidelines. :+1:' - }); - - console.log(`PR #${pr.number} is now compliant, label removed`); - } else { - console.log(`PR #${pr.number} is compliant`); - } diff --git a/.github/workflows/publish-github-action.yml b/.github/workflows/publish-github-action.yml deleted file mode 100644 index e5ca91b561..0000000000 --- a/.github/workflows/publish-github-action.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: publish-github-action - -on: - workflow_dispatch: - push: - tags: - - "github-v*.*.*" - - "!github-v1" - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: write - -jobs: - publish: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - fetch-depth: 0 - - - run: git fetch --force --tags - - - name: Publish - run: | - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - ./script/publish - working-directory: ./github diff --git a/.github/workflows/publish-vscode.yml b/.github/workflows/publish-vscode.yml deleted file mode 100644 index 00c7e26048..0000000000 --- a/.github/workflows/publish-vscode.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: publish-vscode - -on: - workflow_dispatch: - push: - tags: - - "vscode-v*.*.*" - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: write - -jobs: - publish: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - fetch-depth: 0 - - - uses: ./.github/actions/setup-bun - - - run: git fetch --force --tags - - run: bun install -g @vscode/vsce - - - name: Install extension dependencies - run: bun install - working-directory: ./sdks/vscode - - - name: Publish - run: | - ./script/publish - working-directory: ./sdks/vscode - env: - VSCE_PAT: ${{ secrets.VSCE_PAT }} - OPENVSX_TOKEN: ${{ secrets.OPENVSX_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 037020c03a..0000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,521 +0,0 @@ -name: publish -run-name: "${{ format('release {0}', inputs.bump) }}" - -on: - push: - branches: - - ci - - dev - - beta - - fix/npm-native-binary-install - - snapshot-* - workflow_dispatch: - inputs: - bump: - description: "Bump major, minor, or patch" - required: false - type: choice - options: - - major - - minor - - patch - version: - description: "Override version (optional)" - required: false - type: string - -concurrency: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version || inputs.bump }} - -permissions: - id-token: write - contents: write - packages: write - -jobs: - version: - runs-on: blacksmith-4vcpu-ubuntu-2404 - if: github.repository == 'anomalyco/opencode' - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - fetch-depth: 0 - - - uses: ./.github/actions/setup-bun - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Install OpenCode - if: inputs.bump || inputs.version - run: bun i -g opencode-ai - - - id: version - run: | - ./script/version.ts - env: - GH_TOKEN: ${{ steps.committer.outputs.token }} - OPENCODE_BUMP: ${{ inputs.bump }} - OPENCODE_VERSION: ${{ inputs.version }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GH_REPO: ${{ (github.ref_name == 'beta' && 'anomalyco/opencode-beta') || github.repository }} - outputs: - version: ${{ steps.version.outputs.version }} - release: ${{ steps.version.outputs.release }} - tag: ${{ steps.version.outputs.tag }} - repo: ${{ steps.version.outputs.repo }} - - build-cli: - needs: version - runs-on: blacksmith-4vcpu-ubuntu-2404 - if: github.repository == 'anomalyco/opencode' - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - fetch-tags: true - - - uses: ./.github/actions/setup-bun - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Build - id: build - run: | - ./packages/opencode/script/build.ts ${{ (github.ref_name == 'beta' && '--sourcemaps') || '' }} - ./packages/cli/script/build.ts ${{ (github.ref_name == 'beta' && '--sourcemaps') || '' }} - env: - OPENCODE_VERSION: ${{ needs.version.outputs.version }} - OPENCODE_RELEASE: ${{ needs.version.outputs.release }} - GH_REPO: ${{ needs.version.outputs.repo }} - GH_TOKEN: ${{ steps.committer.outputs.token }} - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: opencode-cli - path: | - packages/opencode/dist/opencode-darwin* - packages/opencode/dist/opencode-linux* - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: opencode-cli-windows - path: packages/opencode/dist/opencode-windows* - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: opencode-preview-cli - path: packages/cli/dist/cli-* - - outputs: - version: ${{ needs.version.outputs.version }} - - sign-cli-windows: - needs: - - build-cli - - version - runs-on: blacksmith-4vcpu-windows-2025 - if: github.repository == 'anomalyco/opencode' - env: - AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} - AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} - AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - AZURE_TRUSTED_SIGNING_ACCOUNT_NAME: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }} - AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }} - AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }} - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: opencode-cli-windows - path: packages/opencode/dist - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Azure login - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 - with: - client-id: ${{ env.AZURE_CLIENT_ID }} - tenant-id: ${{ env.AZURE_TENANT_ID }} - subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }} - - - uses: azure/artifact-signing-action@b443cf8ea4124818d2ea9f043cba29fc3ec47b16 # v1.2.0 - with: - endpoint: ${{ env.AZURE_TRUSTED_SIGNING_ENDPOINT }} - signing-account-name: ${{ env.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }} - certificate-profile-name: ${{ env.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }} - files: | - ${{ github.workspace }}\packages\opencode\dist\opencode-windows-arm64\bin\opencode.exe - ${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64\bin\opencode.exe - ${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline\bin\opencode.exe - exclude-environment-credential: true - exclude-workload-identity-credential: true - exclude-managed-identity-credential: true - exclude-shared-token-cache-credential: true - exclude-visual-studio-credential: true - exclude-visual-studio-code-credential: true - exclude-azure-cli-credential: false - exclude-azure-powershell-credential: true - exclude-azure-developer-cli-credential: true - exclude-interactive-browser-credential: true - - - name: Verify Windows CLI signatures - shell: pwsh - run: | - $files = @( - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-arm64\bin\opencode.exe", - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64\bin\opencode.exe", - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline\bin\opencode.exe" - ) - - foreach ($file in $files) { - $sig = Get-AuthenticodeSignature $file - if ($sig.Status -ne "Valid") { - throw "Invalid signature for ${file}: $($sig.Status)" - } - } - - - name: Repack Windows CLI archives - working-directory: packages/opencode/dist - shell: pwsh - run: | - Compress-Archive -Path "opencode-windows-arm64\bin\*" -DestinationPath "opencode-windows-arm64.zip" -Force - Compress-Archive -Path "opencode-windows-x64\bin\*" -DestinationPath "opencode-windows-x64.zip" -Force - Compress-Archive -Path "opencode-windows-x64-baseline\bin\*" -DestinationPath "opencode-windows-x64-baseline.zip" -Force - - - name: Upload signed Windows CLI release assets - if: needs.version.outputs.release != '' - shell: pwsh - env: - GH_TOKEN: ${{ steps.committer.outputs.token }} - run: | - gh release upload "v${{ needs.version.outputs.version }}" ` - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-arm64.zip" ` - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64.zip" ` - "${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline.zip" ` - --clobber ` - --repo "${{ needs.version.outputs.repo }}" - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: opencode-cli-signed-windows - path: | - packages/opencode/dist/opencode-windows-arm64 - packages/opencode/dist/opencode-windows-x64 - packages/opencode/dist/opencode-windows-x64-baseline - - build-electron: - needs: - - build-cli - - version - if: github.repository == 'anomalyco/opencode' - continue-on-error: false - env: - AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} - AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} - AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - AZURE_TRUSTED_SIGNING_ACCOUNT_NAME: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }} - AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }} - AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }} - strategy: - fail-fast: false - matrix: - settings: - - host: macos-26-intel - target: x86_64-apple-darwin - platform_flag: --mac --x64 - bun_install_flags: --os=darwin --cpu=x64 - - host: macos-26 - target: aarch64-apple-darwin - platform_flag: --mac --arm64 - bun_install_flags: --os=darwin --cpu=arm64 - # github-hosted: blacksmith lacks ARM64 MSVC cross-compilation toolchain - - host: "windows-2025" - target: aarch64-pc-windows-msvc - platform_flag: --win --arm64 - - host: "blacksmith-4vcpu-windows-2025" - target: x86_64-pc-windows-msvc - platform_flag: --win - - host: "blacksmith-4vcpu-ubuntu-2404" - target: x86_64-unknown-linux-gnu - platform_flag: --linux - - host: "blacksmith-4vcpu-ubuntu-2404-arm" - target: aarch64-unknown-linux-gnu - platform_flag: --linux --arm64 - runs-on: ${{ matrix.settings.host }} - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 - if: runner.os == 'macOS' - with: - keychain: build - p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }} - p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - - - name: Setup Apple API Key - if: runner.os == 'macOS' - run: echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8 - - - uses: ./.github/actions/setup-bun - with: - install-flags: ${{ matrix.settings.bun_install_flags }} - - - name: Azure login - if: runner.os == 'Windows' - uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 - with: - client-id: ${{ env.AZURE_CLIENT_ID }} - tenant-id: ${{ env.AZURE_TENANT_ID }} - subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }} - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: "24" - - - name: Cache apt packages - if: contains(matrix.settings.host, 'ubuntu') - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - with: - path: ~/apt-cache - key: ${{ runner.os }}-${{ matrix.settings.target }}-apt-electron-${{ hashFiles('.github/workflows/publish.yml') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.settings.target }}-apt-electron- - - - name: Install dependencies (ubuntu only) - if: contains(matrix.settings.host, 'ubuntu') - run: | - mkdir -p ~/apt-cache && chmod -R a+rw ~/apt-cache - sudo apt-get update - sudo apt-get install -y --no-install-recommends -o dir::cache::archives="$HOME/apt-cache" rpm - sudo chmod -R a+rw ~/apt-cache - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Prepare - run: bun ./scripts/prepare.ts - working-directory: packages/desktop - env: - OPENCODE_VERSION: ${{ needs.version.outputs.version }} - OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} - OPENCODE_CLI_ARTIFACT: ${{ (runner.os == 'Windows' && 'opencode-cli-windows') || 'opencode-cli' }} - RUST_TARGET: ${{ matrix.settings.target }} - GH_TOKEN: ${{ github.token }} - GITHUB_RUN_ID: ${{ github.run_id }} - - - name: Build - run: bun run build - working-directory: packages/desktop - env: - NODE_OPTIONS: --max-old-space-size=4096 - OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - SENTRY_PROJECT: ${{ vars.WEB_SENTRY_PROJECT }} - SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} - VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} - VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }} - VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} - - - name: Package - if: needs.version.outputs.release - run: npx electron-builder ${{ matrix.settings.platform_flag }} --publish never --config electron-builder.config.ts - working-directory: packages/desktop - timeout-minutes: 60 - env: - OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} - GH_TOKEN: ${{ steps.committer.outputs.token }} - CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }} - CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_API_KEY: ${{ runner.temp }}/apple-api-key.p8 - APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY }} - APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} - - - name: Package (no publish) - if: ${{ !needs.version.outputs.release }} - run: npx electron-builder ${{ matrix.settings.platform_flag }} --publish never --config electron-builder.config.ts - working-directory: packages/desktop - timeout-minutes: 60 - env: - OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} - - - name: Create macOS .app.tar.gz - if: runner.os == 'macOS' && needs.version.outputs.release - working-directory: packages/desktop/dist - run: | - if [[ "${{ matrix.settings.target }}" == "x86_64-apple-darwin" ]]; then - APP_DIR="mac" - OUT_NAME="opencode-desktop-mac-x64.app.tar.gz" - elif [[ "${{ matrix.settings.target }}" == "aarch64-apple-darwin" ]]; then - APP_DIR="mac-arm64" - OUT_NAME="opencode-desktop-mac-arm64.app.tar.gz" - else - echo "Unknown macOS target: ${{ matrix.settings.target }}" - exit 1 - fi - APP_PATH=$(find "$APP_DIR" -maxdepth 1 -name "*.app" -type d | head -1) - if [ -z "$APP_PATH" ]; then - echo "No .app bundle found in $APP_DIR" - exit 1 - fi - tar -czf "$OUT_NAME" -C "$(dirname "$APP_PATH")" "$(basename "$APP_PATH")" - - - name: Verify signed Windows Electron artifacts - if: runner.os == 'Windows' - shell: pwsh - run: | - $files = @() - $files += Get-ChildItem "${{ github.workspace }}\packages\desktop\dist\*.exe" | Select-Object -ExpandProperty FullName - $files += Get-ChildItem "${{ github.workspace }}\packages\desktop\dist\*unpacked\*.exe" | Select-Object -ExpandProperty FullName - $files += Get-ChildItem "${{ github.workspace }}\packages\desktop\dist\*unpacked\resources\opencode-cli.exe" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName - - foreach ($file in $files | Select-Object -Unique) { - $sig = Get-AuthenticodeSignature $file - if ($sig.Status -ne "Valid") { - throw "Invalid signature for ${file}: $($sig.Status)" - } - } - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: opencode-desktop-${{ matrix.settings.target }} - path: packages/desktop/dist/* - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: needs.version.outputs.release - with: - name: latest-yml-${{ matrix.settings.target }} - path: packages/desktop/dist/latest*.yml - - publish: - needs: - - version - - build-cli - - sign-cli-windows - - build-electron - if: always() && !failure() && !cancelled() - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - - - uses: ./.github/actions/setup-bun - - - name: Login to GitHub Container Registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: "24" - registry-url: "https://registry.npmjs.org" - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: opencode-cli - path: packages/opencode/dist - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: opencode-cli-windows - path: packages/opencode/dist - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: opencode-cli-signed-windows - path: packages/opencode/dist - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - name: opencode-preview-cli - path: packages/cli/dist - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: needs.version.outputs.release - with: - pattern: latest-yml-* - path: /tmp/latest-yml - - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: needs.version.outputs.release - with: - pattern: opencode-desktop-* - path: /tmp/desktop - merge-multiple: true - - - name: Setup git committer - id: committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Cache apt packages (AUR) - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - with: - path: /var/cache/apt/archives - key: ${{ runner.os }}-apt-aur-${{ hashFiles('.github/workflows/publish.yml') }} - restore-keys: | - ${{ runner.os }}-apt-aur- - - - name: Setup SSH for AUR - run: | - sudo apt-get update - sudo apt-get install -y pacman-package-manager - mkdir -p ~/.ssh - echo "${{ secrets.AUR_KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts || true - - - name: Upload desktop release assets - if: needs.version.outputs.release - env: - GH_TOKEN: ${{ steps.committer.outputs.token }} - run: | - shopt -s nullglob - files=(/tmp/desktop/*.{exe,blockmap,dmg,zip,AppImage,deb,rpm} /tmp/desktop/*.app.tar.gz) - if (( ${#files[@]} == 0 )); then - echo "No desktop release assets found" - exit 1 - fi - gh release upload "v${{ needs.version.outputs.version }}" "${files[@]}" --clobber --repo "${{ needs.version.outputs.repo }}" - - - run: ./script/publish.ts - env: - OPENCODE_VERSION: ${{ needs.version.outputs.version }} - OPENCODE_RELEASE: ${{ needs.version.outputs.release }} - AUR_KEY: ${{ secrets.AUR_KEY }} - GITHUB_TOKEN: ${{ steps.committer.outputs.token }} - GH_REPO: ${{ needs.version.outputs.repo }} - NPM_CONFIG_PROVENANCE: false - LATEST_YML_DIR: /tmp/latest-yml - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} diff --git a/.github/workflows/release-github-action.yml b/.github/workflows/release-github-action.yml deleted file mode 100644 index 4a1d7218bb..0000000000 --- a/.github/workflows/release-github-action.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: release-github-action - -on: - push: - branches: - - dev - paths: - - "github/**" - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: write - -jobs: - release: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - - - run: git fetch --force --tags - - - name: Release - run: | - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - ./github/script/release diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml deleted file mode 100644 index 00a4fba8ca..0000000000 --- a/.github/workflows/review.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: review - -on: - issue_comment: - types: [created] - -jobs: - check-guidelines: - if: | - github.event.issue.pull_request && - startsWith(github.event.comment.body, '/review') && - contains(fromJson('["OWNER","MEMBER"]'), github.event.comment.author_association) - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - pull-requests: write - steps: - - name: Get PR number - id: pr-number - run: | - if [ "${{ github.event_name }}" = "pull_request_target" ]; then - echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT - else - echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT - fi - - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 1 - - - uses: ./.github/actions/setup-bun - - - name: Install opencode - run: curl -fsSL https://opencode.ai/install | bash - - - name: Get PR details - id: pr-details - run: | - gh api /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }} > pr_data.json - echo "title=$(jq -r .title pr_data.json)" >> $GITHUB_OUTPUT - echo "sha=$(jq -r .head.sha pr_data.json)" >> $GITHUB_OUTPUT - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check PR guidelines compliance - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENCODE_PERMISSION: '{ "bash": { "*": "deny", "gh*": "allow", "gh pr review*": "deny" } }' - PR_TITLE: ${{ steps.pr-details.outputs.title }} - run: | - PR_BODY=$(jq -r .body pr_data.json) - opencode run -m opencode/gpt-5.5 --variant medium "A new pull request has been created: '${PR_TITLE}' - - - ${{ steps.pr-number.outputs.number }} - - - - $PR_BODY - - - Please check all the code changes in this pull request against the style guide, also look for any bugs if they exist. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do - - When critiquing code against the style guide, be sure that the code is ACTUALLY in violation, don't complain about else statements if they already use early returns there. You may complain about excessive nesting though, regardless of else statement usage. - When critiquing code style don't be a zealot, we don't like "let" statements but sometimes they are the simplest option, if someone does a bunch of nesting with let, they should consider using iife (see packages/opencode/src/util.iife.ts) - - Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block. - If you are writing suggested fixes, BE SURE THAT the change you are recommending is actually valid typescript, often I have seen missing closing "}" or other syntax errors. - Generally, write a comment instead of writing suggested change if you can help it. - - Command MUST be like this. - \`\`\` - gh api \ - --method POST \ - -H \"Accept: application/vnd.github+json\" \ - -H \"X-GitHub-Api-Version: 2022-11-28\" \ - /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }}/comments \ - -f 'body=[summary of issue]' -f 'commit_id=${{ steps.pr-details.outputs.sha }}' -f 'path=[path-to-file]' -F \"line=[line]\" -f 'side=RIGHT' - \`\`\` - - Only create comments for actual violations. If the code follows all guidelines, comment on the issue using gh cli: 'lgtm' AND NOTHING ELSE!!!!." diff --git a/.github/workflows/stats.yml b/.github/workflows/stats.yml deleted file mode 100644 index bc97cfcd71..0000000000 --- a/.github/workflows/stats.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: stats - -on: - schedule: - - cron: "0 12 * * *" # Run daily at 12:00 UTC - workflow_dispatch: # Allow manual trigger - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -jobs: - stats: - if: github.repository == 'anomalyco/opencode' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - - steps: - - name: Checkout - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Run stats script - run: bun script/stats.ts - - - name: Commit stats - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add STATS.md - git diff --staged --quiet || git commit -m "ignore: update download stats $(date -I)" - git push - env: - POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index be2e099d0e..6beb97b831 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -2,7 +2,7 @@ name: storybook on: push: - branches: [dev] + branches: [main] paths: - ".github/workflows/storybook.yml" - "package.json" @@ -11,7 +11,7 @@ on: - "packages/ui/**" - "packages/session-ui/**" pull_request: - branches: [dev] + branches: [main] paths: - ".github/workflows/storybook.yml" - "package.json" @@ -28,7 +28,7 @@ concurrency: jobs: build: name: storybook build - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c69de1d93b..7560fcbb0a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,14 +3,14 @@ name: test on: push: branches: - - dev + - main pull_request: workflow_dispatch: concurrency: - # Keep every run on dev so cancelled checks do not pollute the default branch + # Keep every run on main so cancelled checks do not pollute the default branch # commit history. PRs and other branches still share a group and cancel stale runs. - group: ${{ case(github.ref == 'refs/heads/dev', format('{0}-{1}', github.workflow, github.run_id), format('{0}-{1}', github.workflow, github.event.pull_request.number || github.ref)) }} + group: ${{ case(github.ref == 'refs/heads/main', format('{0}-{1}', github.workflow, github.run_id), format('{0}-{1}', github.workflow, github.event.pull_request.number || github.ref)) }} cancel-in-progress: true permissions: @@ -28,9 +28,9 @@ jobs: matrix: settings: - name: linux - host: blacksmith-4vcpu-ubuntu-2404 + host: ubuntu-latest - name: windows - host: blacksmith-4vcpu-windows-2025 + host: windows-latest runs-on: ${{ matrix.settings.host }} defaults: run: @@ -86,9 +86,9 @@ jobs: matrix: settings: - name: linux - host: blacksmith-4vcpu-ubuntu-2404 + host: ubuntu-latest - name: windows - host: blacksmith-4vcpu-windows-2025 + host: windows-latest runs-on: ${{ matrix.settings.host }} env: PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.playwright-browsers diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml deleted file mode 100644 index 0350e43877..0000000000 --- a/.github/workflows/triage.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: triage - -on: - issues: - types: [opened] - -jobs: - triage: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 1 - - - name: Check exempt issue author - id: author - run: | - LOGIN="${{ github.event.issue.user.login }}" - ASSOCIATION="${{ github.event.issue.author_association }}" - - if [ "$LOGIN" = "opencode-agent[bot]" ] || - [ "$ASSOCIATION" = "OWNER" ] || - [ "$ASSOCIATION" = "MEMBER" ] || - grep -qxiF "$LOGIN" .github/TEAM_MEMBERS; then - echo "skip=true" >> "$GITHUB_OUTPUT" - echo "Skipping issue automation for exempt author: $LOGIN ($ASSOCIATION)" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - name: Setup Bun - if: steps.author.outputs.skip != 'true' - uses: ./.github/actions/setup-bun - - - name: Install opencode - if: steps.author.outputs.skip != 'true' - run: curl -fsSL https://opencode.ai/install | bash - - - name: Triage issue - if: steps.author.outputs.skip != 'true' - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - ISSUE_TITLE: ${{ github.event.issue.title }} - ISSUE_BODY: ${{ github.event.issue.body }} - run: | - opencode run --agent triage "The following issue was just opened, triage it: - - Title: $ISSUE_TITLE - - $ISSUE_BODY" diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index fc9a52797c..1679ca6b19 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -2,14 +2,14 @@ name: typecheck on: push: - branches: [dev] + branches: [main] pull_request: - branches: [dev] + branches: [main] workflow_dispatch: jobs: typecheck: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 From 8ce2d8ffeedadb2973eef7acde63f4c9679ae223 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 14:36:17 +0700 Subject: [PATCH 2/6] docs: record workflow pruning in DIVERGENCES.md Co-Authored-By: Claude Fable 5 --- DIVERGENCES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIVERGENCES.md b/DIVERGENCES.md index 1378f5ab4b..49c97e6ab4 100644 --- a/DIVERGENCES.md +++ b/DIVERGENCES.md @@ -41,6 +41,8 @@ never conflict and are not tracked here. | `README.*.md` (21 translations) | Deleted | Upstream marketing translations, irrelevant to the fork. | Keep deleted (`git rm` the upstream side of modify/delete conflicts). | | `screenshot-uk.png` | Deleted | Orphaned README-translation asset; referenced by nothing. | Keep deleted. | | `.github/TEAM_MEMBERS` | Deleted | Upstream's team roster. The five workflows that read it (pr-standards, pr-management, triage, duplicate-issues, compliance-close) fetch it from a `dev` branch this fork doesn't have, so they are already inert here. | Keep deleted. | +| `.github/workflows/` — 22 upstream workflows deleted (beta, close-issues, close-prs, compliance-close, containers, deploy, docs-locale-sync, docs-update, duplicate-issues, generate, nix-hashes, notify-discord, opencode, pr-management, pr-standards, publish, publish-github-action, publish-vscode, release-github-action, review, stats, triage) | Deleted | All inert or upstream-only here: gated on `anomalyco/opencode`, publish/deploy to upstream infra, need upstream secrets (`OPENCODE_APP_SECRET`, `OPENCODE_API_KEY`, marketplace/Discord/PostHog tokens), trigger only on a `dev` branch the fork lacks, or read the deleted `TEAM_MEMBERS`. | Keep deleted; delete new upstream workflows too unless they're generic self-contained CI. | +| `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest` | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. | Keep our branches + runners; take upstream's other changes. | | `sdks/vscode/package.json` | `description` "opencode for VS Code" → "CoDev Code for VS Code" | Manifest branding. `name`, `displayName`, command IDs/titles stay upstream — the fork doesn't publish this extension; revisit before shipping it. | Keep our description; take upstream's other fields. | | Locale dicts in `packages/{ui,app}/src/i18n/`, `packages/desktop/src/renderer/i18n/`, `packages/console/app/src/i18n/`, `packages/stats/app/src/i18n/`, `packages/web/src/content/i18n/`; translated docs dirs in `packages/web/src/content/docs/` | Deleted every locale except `en`/`es` (incl. `packages/app/src/i18n/parity.test.ts`) | Fork ships English + Spanish only. | Keep deleted (`git rm` the upstream side of modify/delete conflicts); also delete any locale files upstream adds. | | `packages/app/src/context/language.tsx`, `packages/app/src/entry.tsx`, `packages/desktop/src/renderer/i18n/index.ts`, `packages/console/app/src/i18n/index.ts`, `packages/console/app/src/lib/language.ts`, `packages/console/app/src/component/footer.tsx`, `packages/stats/app/src/i18n.ts`, `packages/web/src/i18n/locales.ts`, `packages/web/astro.config.mjs`, `packages/enterprise/src/app.tsx` | Locale registries trimmed to `en` + `es`: `Locale` types, LOCALES/LABEL/TAG/DOCS maps, dict loaders, accept-language matchers, starlight `locales` config; enterprise/entry `zh` special cases now use `es`; console footer always links Discord (Feishu was zh-only) | Fork ships English + Spanish only. | Keep our trimmed lists; take upstream's structural changes and re-trim any new locale entries. | From 82a9831834526c2a19b484f3fe091e58c2a51733 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 14:46:04 +0700 Subject: [PATCH 3/6] fix: align global tmp-path test with codev-code data dir Upstream's test asserts tmpdir()/opencode; the fork's global.ts app constant makes it tmpdir()/codev-code. First CI run ever on this fork caught it. Co-Authored-By: Claude Fable 5 --- DIVERGENCES.md | 2 +- packages/core/test/global.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DIVERGENCES.md b/DIVERGENCES.md index 49c97e6ab4..0c28b5385c 100644 --- a/DIVERGENCES.md +++ b/DIVERGENCES.md @@ -12,7 +12,7 @@ never conflict and are not tracked here. | File | Change | Why | On conflict | | --- | --- | --- | --- | -| `packages/core/src/global.ts` | `const app = "opencode"` → `"codev-code"` | Config/data/cache/state dirs under `~/.config/codev-code` etc. | Keep ours (the one constant); take upstream's surrounding changes. | +| `packages/core/src/global.ts`, `packages/core/test/global.test.ts` | `const app = "opencode"` → `"codev-code"`; test expectation `tmpdir()/opencode` → `tmpdir()/codev-code` | Config/data/cache/state dirs under `~/.config/codev-code` etc.; upstream's path test asserts the literal dir name. | Keep ours (the one constant + expectation); take upstream's surrounding changes. | | `packages/opencode/src/index.ts` | `scriptName("opencode")` → `"codev"`; `show()` prefix check `"opencode "` → `"codev "` | Help/usage text shows the real user-facing command (the `codev` hub forwards unknown commands to this binary). The `show()` check must always match the scriptName. | Keep our two strings; take upstream's surrounding changes. | | `package.json` (root) | Added `release` script delegating to packages/opencode | `bun run release` works from the repo root. | Keep our release line; take upstream's other fields. | | `packages/opencode/package.json` | bin key `opencode` → `codev-code` (shim path `./bin/opencode` unchanged); added `release` script | Installed binary is named `codev-code`; `bun run release` publishes the version in this file (upstream-synced; script/release.ts is fork-only). | Keep our bin key and release line; take upstream's other fields including `version`. | diff --git a/packages/core/test/global.test.ts b/packages/core/test/global.test.ts index 4e13e88424..ef7c6826cd 100644 --- a/packages/core/test/global.test.ts +++ b/packages/core/test/global.test.ts @@ -6,7 +6,7 @@ import { Global } from "@opencode-ai/core/global" describe("global paths", () => { test("tmp path is under the system temp directory", () => { - expect(Global.Path.tmp).toBe(path.join(os.tmpdir(), "opencode")) + expect(Global.Path.tmp).toBe(path.join(os.tmpdir(), "codev-code")) expect(Global.make().tmp).toBe(Global.Path.tmp) }) From d446c12152b38792e818780c586c067060ed62d6 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 14:54:26 +0700 Subject: [PATCH 4/6] fix: locale-projection e2e spec tests es instead of removed de/ar Verified locally with Playwright (1 passed). Co-Authored-By: Claude Fable 5 --- DIVERGENCES.md | 2 +- .../regression/session-timeline-locale-projection.spec.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/DIVERGENCES.md b/DIVERGENCES.md index 0c28b5385c..819369da68 100644 --- a/DIVERGENCES.md +++ b/DIVERGENCES.md @@ -45,7 +45,7 @@ never conflict and are not tracked here. | `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest` | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. | Keep our branches + runners; take upstream's other changes. | | `sdks/vscode/package.json` | `description` "opencode for VS Code" → "CoDev Code for VS Code" | Manifest branding. `name`, `displayName`, command IDs/titles stay upstream — the fork doesn't publish this extension; revisit before shipping it. | Keep our description; take upstream's other fields. | | Locale dicts in `packages/{ui,app}/src/i18n/`, `packages/desktop/src/renderer/i18n/`, `packages/console/app/src/i18n/`, `packages/stats/app/src/i18n/`, `packages/web/src/content/i18n/`; translated docs dirs in `packages/web/src/content/docs/` | Deleted every locale except `en`/`es` (incl. `packages/app/src/i18n/parity.test.ts`) | Fork ships English + Spanish only. | Keep deleted (`git rm` the upstream side of modify/delete conflicts); also delete any locale files upstream adds. | -| `packages/app/src/context/language.tsx`, `packages/app/src/entry.tsx`, `packages/desktop/src/renderer/i18n/index.ts`, `packages/console/app/src/i18n/index.ts`, `packages/console/app/src/lib/language.ts`, `packages/console/app/src/component/footer.tsx`, `packages/stats/app/src/i18n.ts`, `packages/web/src/i18n/locales.ts`, `packages/web/astro.config.mjs`, `packages/enterprise/src/app.tsx` | Locale registries trimmed to `en` + `es`: `Locale` types, LOCALES/LABEL/TAG/DOCS maps, dict loaders, accept-language matchers, starlight `locales` config; enterprise/entry `zh` special cases now use `es`; console footer always links Discord (Feishu was zh-only) | Fork ships English + Spanish only. | Keep our trimmed lists; take upstream's structural changes and re-trim any new locale entries. | +| `packages/app/src/context/language.tsx`, `packages/app/src/entry.tsx`, `packages/desktop/src/renderer/i18n/index.ts`, `packages/console/app/src/i18n/index.ts`, `packages/console/app/src/lib/language.ts`, `packages/console/app/src/component/footer.tsx`, `packages/stats/app/src/i18n.ts`, `packages/web/src/i18n/locales.ts`, `packages/web/astro.config.mjs`, `packages/enterprise/src/app.tsx`, `packages/app/e2e/regression/session-timeline-locale-projection.spec.ts` | Locale registries trimmed to `en` + `es`: `Locale` types, LOCALES/LABEL/TAG/DOCS maps, dict loaders, accept-language matchers, starlight `locales` config; enterprise/entry `zh` special cases now use `es`; console footer always links Discord (Feishu was zh-only); e2e locale-projection spec tests `es` ("Explorado") instead of de/ar | Fork ships English + Spanish only. | Keep our trimmed lists; take upstream's structural changes and re-trim any new locale entries. | ## Known rebrand gaps (deliberate, revisit before external distribution) diff --git a/packages/app/e2e/regression/session-timeline-locale-projection.spec.ts b/packages/app/e2e/regression/session-timeline-locale-projection.spec.ts index 3901f8865e..1bc0f18280 100644 --- a/packages/app/e2e/regression/session-timeline-locale-projection.spec.ts +++ b/packages/app/e2e/regression/session-timeline-locale-projection.spec.ts @@ -1,10 +1,7 @@ import { expect, test } from "@playwright/test" import { assistantMessage, setupTimeline, toolPart, userMessage } from "../performance/timeline-stability/fixture" -for (const profile of [ - { locale: "de", label: "Erkundet" }, - { locale: "ar", label: "تم الاستكشاف" }, -] as const) { +for (const profile of [{ locale: "es", label: "Explorado" }] as const) { test(`projects translated context status in ${profile.locale}`, async ({ page }) => { const ids = [`prt_locale_${profile.locale}_01_read`, `prt_locale_${profile.locale}_02_glob`] await setupTimeline(page, { From 05206f1b3d766f7d1e51badbbe538771b1548b71 Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 15:08:44 +0700 Subject: [PATCH 5/6] fix: align remaining tests with fork divergences; windows ripgrep timeout - cli error format asserts 'codev models' (scriptName rename) - mcp add subprocess test reads .config/codev-code (data-dir rename) - ripgrep it.live tests get 120s timeouts: first use downloads the binary, which blows bun's 5s default on GitHub-hosted Windows Co-Authored-By: Claude Fable 5 --- DIVERGENCES.md | 5 +++-- packages/core/test/ripgrep.test.ts | 4 ++++ packages/opencode/test/cli/error.test.ts | 2 +- packages/opencode/test/cli/mcp-add.test.ts | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/DIVERGENCES.md b/DIVERGENCES.md index 819369da68..2227220b51 100644 --- a/DIVERGENCES.md +++ b/DIVERGENCES.md @@ -12,8 +12,8 @@ never conflict and are not tracked here. | File | Change | Why | On conflict | | --- | --- | --- | --- | -| `packages/core/src/global.ts`, `packages/core/test/global.test.ts` | `const app = "opencode"` → `"codev-code"`; test expectation `tmpdir()/opencode` → `tmpdir()/codev-code` | Config/data/cache/state dirs under `~/.config/codev-code` etc.; upstream's path test asserts the literal dir name. | Keep ours (the one constant + expectation); take upstream's surrounding changes. | -| `packages/opencode/src/index.ts` | `scriptName("opencode")` → `"codev"`; `show()` prefix check `"opencode "` → `"codev "` | Help/usage text shows the real user-facing command (the `codev` hub forwards unknown commands to this binary). The `show()` check must always match the scriptName. | Keep our two strings; take upstream's surrounding changes. | +| `packages/core/src/global.ts`, `packages/core/test/global.test.ts`, `packages/opencode/test/cli/mcp-add.test.ts` | `const app = "opencode"` → `"codev-code"`; test expectations `tmpdir()/opencode` → `tmpdir()/codev-code` and `.config/opencode/` → `.config/codev-code/` | Config/data/cache/state dirs under `~/.config/codev-code` etc.; upstream tests assert the literal dir name. | Keep ours (the one constant + expectations); take upstream's surrounding changes. | +| `packages/opencode/src/index.ts`, `packages/opencode/test/cli/error.test.ts` | `scriptName("opencode")` → `"codev"`; `show()` prefix check `"opencode "` → `"codev "`; test expectation `` `opencode models` `` → `` `codev models` `` | Help/usage text shows the real user-facing command (the `codev` hub forwards unknown commands to this binary). The `show()` check must always match the scriptName; upstream's error-format test asserts the literal command. | Keep our strings + expectation; take upstream's surrounding changes. | | `package.json` (root) | Added `release` script delegating to packages/opencode | `bun run release` works from the repo root. | Keep our release line; take upstream's other fields. | | `packages/opencode/package.json` | bin key `opencode` → `codev-code` (shim path `./bin/opencode` unchanged); added `release` script | Installed binary is named `codev-code`; `bun run release` publishes the version in this file (upstream-synced; script/release.ts is fork-only). | Keep our bin key and release line; take upstream's other fields including `version`. | | `bun.lock` | Mirrors the bin key rename above | Lockfile records workspace bin mappings. | Regenerate with `bun install`; never hand-merge. | @@ -43,6 +43,7 @@ never conflict and are not tracked here. | `.github/TEAM_MEMBERS` | Deleted | Upstream's team roster. The five workflows that read it (pr-standards, pr-management, triage, duplicate-issues, compliance-close) fetch it from a `dev` branch this fork doesn't have, so they are already inert here. | Keep deleted. | | `.github/workflows/` — 22 upstream workflows deleted (beta, close-issues, close-prs, compliance-close, containers, deploy, docs-locale-sync, docs-update, duplicate-issues, generate, nix-hashes, notify-discord, opencode, pr-management, pr-standards, publish, publish-github-action, publish-vscode, release-github-action, review, stats, triage) | Deleted | All inert or upstream-only here: gated on `anomalyco/opencode`, publish/deploy to upstream infra, need upstream secrets (`OPENCODE_APP_SECRET`, `OPENCODE_API_KEY`, marketplace/Discord/PostHog tokens), trigger only on a `dev` branch the fork lacks, or read the deleted `TEAM_MEMBERS`. | Keep deleted; delete new upstream workflows too unless they're generic self-contained CI. | | `.github/workflows/{typecheck,test,nix-eval,storybook}.yml` | Triggers `dev` → `main` (incl. test.yml's concurrency-group ref check); runners `blacksmith-*` → `ubuntu-latest`/`windows-latest` | Fork's default branch is `main`; Blacksmith runners aren't installed here, so jobs queued forever. | Keep our branches + runners; take upstream's other changes. | +| `packages/core/test/ripgrep.test.ts` | `120_000` timeout on both `it.live` tests | First use downloads + extracts the ripgrep binary; GitHub-hosted Windows runners blow bun's 5s default. | Keep our timeouts; take upstream's test changes. | | `sdks/vscode/package.json` | `description` "opencode for VS Code" → "CoDev Code for VS Code" | Manifest branding. `name`, `displayName`, command IDs/titles stay upstream — the fork doesn't publish this extension; revisit before shipping it. | Keep our description; take upstream's other fields. | | Locale dicts in `packages/{ui,app}/src/i18n/`, `packages/desktop/src/renderer/i18n/`, `packages/console/app/src/i18n/`, `packages/stats/app/src/i18n/`, `packages/web/src/content/i18n/`; translated docs dirs in `packages/web/src/content/docs/` | Deleted every locale except `en`/`es` (incl. `packages/app/src/i18n/parity.test.ts`) | Fork ships English + Spanish only. | Keep deleted (`git rm` the upstream side of modify/delete conflicts); also delete any locale files upstream adds. | | `packages/app/src/context/language.tsx`, `packages/app/src/entry.tsx`, `packages/desktop/src/renderer/i18n/index.ts`, `packages/console/app/src/i18n/index.ts`, `packages/console/app/src/lib/language.ts`, `packages/console/app/src/component/footer.tsx`, `packages/stats/app/src/i18n.ts`, `packages/web/src/i18n/locales.ts`, `packages/web/astro.config.mjs`, `packages/enterprise/src/app.tsx`, `packages/app/e2e/regression/session-timeline-locale-projection.spec.ts` | Locale registries trimmed to `en` + `es`: `Locale` types, LOCALES/LABEL/TAG/DOCS maps, dict loaders, accept-language matchers, starlight `locales` config; enterprise/entry `zh` special cases now use `es`; console footer always links Discord (Feishu was zh-only); e2e locale-projection spec tests `es` ("Explorado") instead of de/ar | Fork ships English + Spanish only. | Keep our trimmed lists; take upstream's structural changes and re-trim any new locale entries. | diff --git a/packages/core/test/ripgrep.test.ts b/packages/core/test/ripgrep.test.ts index 3abce1c02d..88b1822f91 100644 --- a/packages/core/test/ripgrep.test.ts +++ b/packages/core/test/ripgrep.test.ts @@ -29,6 +29,9 @@ describe("Ripgrep", () => { }), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), ), + // First use downloads + extracts the ripgrep binary; GitHub-hosted + // Windows runners need well over bun's 5s default for that. + 120_000, ) it.live("never includes git metadata", () => @@ -61,5 +64,6 @@ describe("Ripgrep", () => { }), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), ), + 120_000, ) }) diff --git a/packages/opencode/test/cli/error.test.ts b/packages/opencode/test/cli/error.test.ts index b29ca2b3ba..e88c21f4c0 100644 --- a/packages/opencode/test/cli/error.test.ts +++ b/packages/opencode/test/cli/error.test.ts @@ -73,7 +73,7 @@ describe("cli.error", () => { const expected = [ "Model not found: anthropic/claude-sonet-4", "Did you mean: claude-sonnet-4", - "Try: `opencode models` to list available models", + "Try: `codev models` to list available models", "Or check your config (opencode.json) provider/model names", ].join("\n") diff --git a/packages/opencode/test/cli/mcp-add.test.ts b/packages/opencode/test/cli/mcp-add.test.ts index 9a49384855..973130808a 100644 --- a/packages/opencode/test/cli/mcp-add.test.ts +++ b/packages/opencode/test/cli/mcp-add.test.ts @@ -22,7 +22,7 @@ describe("opencode mcp add (non-interactive subprocess)", () => { opencode.expectExit(result, 0) const config = yield* Effect.promise(() => - Bun.file(path.join(home, ".config", "opencode", "opencode.json")).json(), + Bun.file(path.join(home, ".config", "codev-code", "opencode.json")).json(), ) expect(config.mcp.github).toEqual({ type: "remote", @@ -58,7 +58,7 @@ describe("opencode mcp add (non-interactive subprocess)", () => { opencode.expectExit(result, 0) const config = yield* Effect.promise(() => - Bun.file(path.join(home, ".config", "opencode", "opencode.json")).json(), + Bun.file(path.join(home, ".config", "codev-code", "opencode.json")).json(), ) expect(config.mcp.local).toEqual({ type: "local", From 023de6b911de4e5da6a009bfc2f3c7a74cea611f Mon Sep 17 00:00:00 2001 From: minhn4 Date: Thu, 9 Jul 2026 15:10:09 +0700 Subject: [PATCH 6/6] minor changes --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 426531b318..ec1c6d647c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # CoDev Code -The AI coding agent of the CoDev ecosystem. The [codev](https://github.com/quickbeard/codev) hub CLI dispatches to it directly: bare `codev` opens the agent, and any command the hub doesn't claim (`codev run "..."`, `codev serve`, `codev models`, …) is passed through. The installed binary itself is named `codev-code`. - CoDev Code is a fork of [opencode](https://github.com/anomalyco/opencode) that tracks upstream while carrying a small set of organization-specific changes. Read [DIVERGENCES.md](DIVERGENCES.md) before editing any upstream file — it defines where changes are allowed to live. ## Development