release patch #35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: publish | |
| run-name: "${{ format('release {0}', inputs.bump) }}" | |
| on: | |
| push: | |
| branches: | |
| - ci | |
| - dev | |
| - beta | |
| - 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 | |
| version_suffix: | |
| description: "Append suffix to version." | |
| required: false | |
| type: string | |
| concurrency: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version || inputs.version_suffix || inputs.bump }} | |
| permissions: | |
| id-token: write | |
| contents: write | |
| packages: write | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| OPENCODE_NPM_PACKAGE_PREFIX: "@naster17/opencode-pro" | |
| jobs: | |
| version: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: ./.github/actions/setup-bun | |
| - name: Configure OpenCode for Gemini | |
| uses: ./.github/actions/setup-opencode-gemini | |
| with: | |
| model: ${{ vars.OPENCODE_CHANGELOG_MODEL || vars.OPENCODE_MODEL || 'google/gemini-2.5-pro' }} | |
| small-model: ${{ vars.OPENCODE_SMALL_MODEL || 'google/gemini-2.5-flash' }} | |
| - 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_VERSION_SUFFIX: ${{ inputs.version_suffix || vars.OPENCODE_VERSION_SUFFIX }} | |
| OPENCODE_MODEL: ${{ vars.OPENCODE_CHANGELOG_MODEL || vars.OPENCODE_MODEL || 'google/gemini-2.5-pro' }} | |
| GOOGLE_GENERATIVE_AI_API_KEY: ${{ secrets.GOOGLE_GENERATIVE_AI_API_KEY }} | |
| GH_REPO: ${{ (github.ref_name == 'beta' && vars.OPENCODE_BETA_REPO) || 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: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| 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') || '' }} | |
| 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@v6 | |
| with: | |
| name: opencode-cli | |
| path: | | |
| packages/opencode/dist/opencode-darwin* | |
| packages/opencode/dist/opencode-linux* | |
| packages/opencode/dist/opencode-pro-darwin* | |
| packages/opencode/dist/opencode-pro-linux* | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: opencode-cli-windows | |
| path: | | |
| packages/opencode/dist/opencode-windows* | |
| packages/opencode/dist/opencode-pro-windows* | |
| outputs: | |
| version: ${{ needs.version.outputs.version }} | |
| sign-cli-windows: | |
| needs: | |
| - build-cli | |
| - version | |
| if: github.repository == 'anomalyco/opencode' | |
| runs-on: windows-latest | |
| steps: | |
| - run: echo "Skipping Windows CLI signing in this fork" | |
| build-electron: | |
| needs: | |
| - build-cli | |
| - version | |
| continue-on-error: false | |
| env: | |
| HAS_APPLE_CERT: ${{ secrets.APPLE_CERTIFICATE != '' }} | |
| 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-latest" | |
| target: aarch64-pc-windows-msvc | |
| platform_flag: --win --arm64 | |
| - host: "windows-latest" | |
| target: x86_64-pc-windows-msvc | |
| platform_flag: --win | |
| - host: "ubuntu-latest" | |
| target: x86_64-unknown-linux-gnu | |
| platform_flag: --linux | |
| - host: "ubuntu-latest" | |
| target: aarch64-unknown-linux-gnu | |
| platform_flag: --linux | |
| runs-on: ${{ matrix.settings.host }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Skip unsigned macOS build on forks | |
| if: runner.os == 'macOS' && env.HAS_APPLE_CERT != 'true' | |
| run: echo "Skipping macOS build because APPLE_CERTIFICATE is not configured" | |
| - uses: apple-actions/import-codesign-certs@v5 | |
| if: runner.os == 'macOS' && env.HAS_APPLE_CERT == 'true' | |
| with: | |
| keychain: build | |
| p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }} | |
| p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| - name: Setup Apple API Key | |
| if: runner.os == 'macOS' && env.HAS_APPLE_CERT == 'true' | |
| run: echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8 | |
| - uses: ./.github/actions/setup-bun | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| with: | |
| install-flags: ${{ matrix.settings.bun_install_flags }} | |
| - uses: actions/setup-node@v6 | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| with: | |
| node-version: "24" | |
| - name: Cache apt packages | |
| if: contains(matrix.settings.host, 'ubuntu') && (runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true') | |
| uses: actions/cache@v5 | |
| 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') && (runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true') | |
| 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 | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| 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 | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| 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 | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| run: bun run build | |
| working-directory: packages/desktop | |
| env: | |
| 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 and publish | |
| if: needs.version.outputs.release && (runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true') | |
| run: npx electron-builder ${{ matrix.settings.platform_flag }} --publish always --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 && (runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true') }} | |
| 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 and upload macOS .app.tar.gz | |
| if: runner.os == 'macOS' && env.HAS_APPLE_CERT == 'true' && needs.version.outputs.release | |
| working-directory: packages/desktop/dist | |
| env: | |
| GH_TOKEN: ${{ steps.committer.outputs.token }} | |
| run: | | |
| if [[ "${{ matrix.settings.target }}" == "x86_64-apple-darwin" ]]; then | |
| APP_DIR="mac" | |
| OUT_NAME="opencode-pro-desktop-mac-x64.app.tar.gz" | |
| elif [[ "${{ matrix.settings.target }}" == "aarch64-apple-darwin" ]]; then | |
| APP_DIR="mac-arm64" | |
| OUT_NAME="opencode-pro-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")" | |
| gh release upload "v${{ needs.version.outputs.version }}" "$OUT_NAME" --clobber --repo "${{ needs.version.outputs.repo }}" | |
| - uses: actions/upload-artifact@v6 | |
| if: runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true' | |
| with: | |
| name: opencode-desktop-${{ matrix.settings.target }} | |
| path: packages/desktop/dist/* | |
| - uses: actions/upload-artifact@v6 | |
| if: needs.version.outputs.release && (runner.os != 'macOS' || env.HAS_APPLE_CERT == 'true') | |
| 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() && !cancelled() | |
| runs-on: ubuntu-latest | |
| env: | |
| HAS_AUR_KEY: ${{ secrets.AUR_KEY != '' }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/setup-bun | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| registry-url: "https://registry.npmjs.org" | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: opencode-cli | |
| path: packages/opencode/dist | |
| - uses: actions/download-artifact@v6 | |
| continue-on-error: true | |
| with: | |
| name: opencode-cli-windows | |
| path: packages/opencode/dist | |
| - uses: actions/download-artifact@v6 | |
| if: needs.sign-cli-windows.result == 'success' | |
| continue-on-error: true | |
| with: | |
| name: opencode-cli-signed-windows | |
| path: packages/opencode/dist | |
| - uses: actions/download-artifact@v6 | |
| if: needs.version.outputs.release | |
| continue-on-error: true | |
| with: | |
| pattern: latest-yml-* | |
| path: /tmp/latest-yml | |
| - name: Setup git committer | |
| id: committer | |
| uses: ./.github/actions/setup-git-committer | |
| - name: Cache apt packages (AUR) | |
| if: env.HAS_AUR_KEY == 'true' | |
| uses: actions/cache@v5 | |
| 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 | |
| if: env.HAS_AUR_KEY == 'true' | |
| 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 | |
| - run: ./script/publish.ts | |
| env: | |
| OPENCODE_VERSION: ${{ needs.version.outputs.version }} | |
| OPENCODE_RELEASE: ${{ needs.version.outputs.release }} | |
| OPENCODE_PUBLISH_NPM: ${{ github.event_name == 'workflow_dispatch' && needs.version.outputs.release && 'true' || 'false' }} | |
| AUR_KEY: ${{ secrets.AUR_KEY }} | |
| GITHUB_TOKEN: ${{ steps.committer.outputs.token }} | |
| GH_REPO: ${{ needs.version.outputs.repo }} | |
| NPM_CONFIG_PROVENANCE: false | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| 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 }} |