# Release version 0.14.5 #123
Workflow file for this run
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: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*.*.*" | |
| env: | |
| RUST_BACKTRACE: short | |
| HUSKY: 0 | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| create-draft-release: | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: write | |
| outputs: | |
| release_id: ${{ steps.release.outputs.release_id }} | |
| release_url: ${{ steps.release.outputs.release_url }} | |
| prerelease: ${{ steps.meta.outputs.prerelease }} | |
| release_body: ${{ steps.release.outputs.release_body }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - id: meta | |
| name: Resolve release channel | |
| shell: bash | |
| run: | | |
| if [[ "${GITHUB_REF_NAME}" == *"-rc"* ]]; then | |
| echo "prerelease=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "prerelease=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check tag commit belongs to default branch | |
| shell: bash | |
| run: | | |
| DEFAULT_BRANCH="${{ github.event.repository.default_branch }}" | |
| git fetch origin "${DEFAULT_BRANCH}" | |
| TAG_COMMIT=$(git rev-list -n 1 "${GITHUB_REF_NAME}") | |
| if git merge-base --is-ancestor "${TAG_COMMIT}" "origin/${DEFAULT_BRANCH}"; then | |
| echo "Tag ${GITHUB_REF_NAME} is based on ${DEFAULT_BRANCH}" | |
| else | |
| echo "Tag ${GITHUB_REF_NAME} is not based on ${DEFAULT_BRANCH}" | |
| exit 1 | |
| fi | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Verify tag matches app version | |
| shell: bash | |
| run: | | |
| APP_VERSION=$(node -p "require('./src-tauri/tauri.conf.json').version") | |
| if [[ "v$APP_VERSION" != "${GITHUB_REF_NAME}" ]]; then | |
| echo "Tag ${GITHUB_REF_NAME} does not match app version v$APP_VERSION" | |
| exit 1 | |
| fi | |
| - id: release | |
| name: Create or reuse draft release | |
| uses: actions/github-script@v7 | |
| env: | |
| PRERELEASE: ${{ steps.meta.outputs.prerelease }} | |
| with: | |
| script: | | |
| const tag = context.ref.replace("refs/tags/", ""); | |
| const { owner, repo } = context.repo; | |
| const prerelease = process.env.PRERELEASE === "true"; | |
| const releaseName = `codeg ${tag}`; | |
| const { data: tagRef } = await github.rest.git.getRef({ | |
| owner, | |
| repo, | |
| ref: `tags/${tag}`, | |
| }); | |
| let commitSha = tagRef.object.sha; | |
| if (tagRef.object.type === "tag") { | |
| const { data: annotatedTag } = await github.rest.git.getTag({ | |
| owner, | |
| repo, | |
| tag_sha: commitSha, | |
| }); | |
| if (annotatedTag.object.type !== "commit") { | |
| core.setFailed( | |
| `Tag ${tag} points to ${annotatedTag.object.type}, not a commit.`, | |
| ); | |
| return; | |
| } | |
| commitSha = annotatedTag.object.sha; | |
| } | |
| const { data: commit } = await github.rest.repos.getCommit({ | |
| owner, | |
| repo, | |
| ref: commitSha, | |
| }); | |
| const releaseBody = | |
| commit.commit.message?.trim() || "_No commit message._"; | |
| let release; | |
| try { | |
| const existing = await github.rest.repos.getReleaseByTag({ | |
| owner, | |
| repo, | |
| tag, | |
| }); | |
| if (!existing.data.draft) { | |
| core.setFailed( | |
| `Release for tag ${tag} already exists and is not a draft.`, | |
| ); | |
| return; | |
| } | |
| release = existing.data; | |
| if ( | |
| release.prerelease !== prerelease || | |
| release.name !== releaseName || | |
| (release.body ?? "").trim() !== releaseBody | |
| ) { | |
| const updated = await github.rest.repos.updateRelease({ | |
| owner, | |
| repo, | |
| release_id: release.id, | |
| name: releaseName, | |
| prerelease, | |
| body: releaseBody, | |
| }); | |
| release = updated.data; | |
| } | |
| core.info(`Reusing existing draft release #${release.id}`); | |
| } catch (error) { | |
| if (error.status !== 404) { | |
| throw error; | |
| } | |
| const created = await github.rest.repos.createRelease({ | |
| owner, | |
| repo, | |
| tag_name: tag, | |
| name: releaseName, | |
| body: releaseBody, | |
| draft: true, | |
| prerelease, | |
| }); | |
| release = created.data; | |
| core.info(`Created draft release #${release.id}`); | |
| } | |
| core.setOutput("release_id", String(release.id)); | |
| core.setOutput("release_url", release.html_url); | |
| core.setOutput("release_body", releaseBody); | |
| build-tauri: | |
| needs: create-draft-release | |
| name: Build ${{ matrix.name }} | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: "macOS x64" | |
| runner: "macos-latest" | |
| target: "x86_64-apple-darwin" | |
| - name: "macOS arm64" | |
| runner: "macos-latest" | |
| target: "aarch64-apple-darwin" | |
| - name: "Linux x64" | |
| runner: "ubuntu-22.04" | |
| target: "x86_64-unknown-linux-gnu" | |
| - name: "Linux arm64" | |
| runner: "ubuntu-22.04" | |
| target: "aarch64-unknown-linux-gnu" | |
| - name: "Windows x64" | |
| runner: "windows-2022" | |
| target: "x86_64-pc-windows-msvc" | |
| - name: "Windows arm64" | |
| runner: "windows-latest" | |
| target: "aarch64-pc-windows-msvc" | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: "pnpm" | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Rust cache | |
| uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: "./src-tauri -> target" | |
| shared-key: ${{ matrix.target }} | |
| - name: Install Linux x64 dependencies | |
| if: matrix.target == 'x86_64-unknown-linux-gnu' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf | |
| - name: Install Linux arm64 cross dependencies | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| cat > /tmp/sources.list << 'EOF' | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse | |
| deb [arch=amd64] http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse | |
| EOF | |
| sudo mv /etc/apt/sources.list /etc/apt/sources.list.default | |
| sudo mv /tmp/sources.list /etc/apt/sources.list | |
| sudo dpkg --add-architecture arm64 | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| gcc-aarch64-linux-gnu \ | |
| g++-aarch64-linux-gnu \ | |
| libwebkit2gtk-4.1-dev:arm64 \ | |
| libayatana-appindicator3-dev:arm64 \ | |
| librsvg2-dev:arm64 \ | |
| libssl-dev:arm64 \ | |
| patchelf | |
| - name: Configure Linux arm64 cross env | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| shell: bash | |
| run: | | |
| echo "PKG_CONFIG_ALLOW_CROSS=1" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR=aarch64-linux-gnu-gcc-ar" >> "$GITHUB_ENV" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=-Clinker=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" | |
| echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" | |
| echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> "$GITHUB_ENV" | |
| echo "AR_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc-ar" >> "$GITHUB_ENV" | |
| - name: Verify Linux arm64 cross toolchain | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| shell: bash | |
| run: | | |
| which aarch64-linux-gnu-gcc | |
| aarch64-linux-gnu-gcc -v | |
| rustup target list --installed | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER}" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR}" | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS}" | |
| - name: Install frontend dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Build the `codeg-mcp` companion binary for the matrix target and | |
| # stage it as a Tauri sidecar at | |
| # `src-tauri/binaries/codeg-mcp-<triple>{.exe}`. `tauri-action` (below) | |
| # then bundles it via the `bundle.externalBin` entry in | |
| # `tauri.conf.json` — Tauri installs it next to the main executable | |
| # (Contents/MacOS on macOS, install root on Linux/Windows) where the | |
| # runtime `locate_codeg_mcp_binary()` finds it via `current_exe` | |
| # sibling lookup. The Linux arm64 cross env vars set above also | |
| # apply to this cargo invocation. | |
| - name: Stage codeg-mcp sidecar for Tauri bundle | |
| shell: bash | |
| run: pnpm tauri:prepare-sidecars --target ${{ matrix.target }} | |
| - name: Verify codeg-mcp sidecar landed | |
| shell: bash | |
| run: | | |
| ext="" | |
| case "${{ matrix.target }}" in | |
| *windows*) ext=".exe" ;; | |
| esac | |
| file="src-tauri/binaries/codeg-mcp-${{ matrix.target }}${ext}" | |
| if [ ! -f "$file" ]; then | |
| echo "FATAL: sidecar $file missing after prepare-sidecars" | |
| exit 1 | |
| fi | |
| ls -la "$file" | |
| - name: Build and upload to draft release (Linux arm64) | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| uses: tauri-apps/tauri-action@v0.6.1 | |
| env: | |
| # The matrix-target sidecar is already staged and verified above. | |
| # Skip the duplicate beforeBuildCommand sidecar pass so cross builds | |
| # do not fall back to the runner host triple. | |
| CODEG_SKIP_SIDECAR: "1" | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| PKG_CONFIG_ALLOW_CROSS: 1 | |
| PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig | |
| PKG_CONFIG_LIBDIR: /usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig | |
| PKG_CONFIG_SYSROOT_DIR: /usr/aarch64-linux-gnu | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR: aarch64-linux-gnu-gcc-ar | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS: -Clinker=aarch64-linux-gnu-gcc | |
| CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc | |
| CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++ | |
| AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc-ar | |
| with: | |
| releaseId: ${{ needs.create-draft-release.outputs.release_id }} | |
| tagName: ${{ github.ref_name }} | |
| releaseBody: ${{ needs.create-draft-release.outputs.release_body }} | |
| releaseDraft: true | |
| prerelease: ${{ needs.create-draft-release.outputs.prerelease }} | |
| tauriScript: pnpm tauri | |
| args: --target ${{ matrix.target }} --bundles deb,rpm | |
| includeUpdaterJson: false | |
| retryAttempts: 2 | |
| - name: Build and upload to draft release (Windows) | |
| if: contains(matrix.target, 'windows') | |
| uses: tauri-apps/tauri-action@v0.6.1 | |
| env: | |
| # The matrix-target sidecar is already staged and verified above. | |
| # Skip the duplicate beforeBuildCommand sidecar pass so cross builds | |
| # do not fall back to the runner host triple. | |
| CODEG_SKIP_SIDECAR: "1" | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| with: | |
| releaseId: ${{ needs.create-draft-release.outputs.release_id }} | |
| tagName: ${{ github.ref_name }} | |
| releaseBody: ${{ needs.create-draft-release.outputs.release_body }} | |
| releaseDraft: true | |
| prerelease: ${{ needs.create-draft-release.outputs.prerelease }} | |
| tauriScript: pnpm tauri | |
| # Skip MSI bundling on Windows: tauri-apps/tauri#14681 — light.exe | |
| # fails when externalBin is configured. NSIS installer + updater | |
| # artifacts cover the same distribution channel. | |
| args: --target ${{ matrix.target }} --bundles nsis,updater | |
| includeUpdaterJson: true | |
| retryAttempts: 2 | |
| - name: Build and upload to draft release (Non-Linux arm64) | |
| if: matrix.target != 'aarch64-unknown-linux-gnu' && !contains(matrix.target, 'windows') | |
| uses: tauri-apps/tauri-action@v0.6.1 | |
| env: | |
| # The matrix-target sidecar is already staged and verified above. | |
| # Skip the duplicate beforeBuildCommand sidecar pass so cross builds | |
| # do not fall back to the runner host triple. | |
| CODEG_SKIP_SIDECAR: "1" | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| with: | |
| releaseId: ${{ needs.create-draft-release.outputs.release_id }} | |
| tagName: ${{ github.ref_name }} | |
| releaseBody: ${{ needs.create-draft-release.outputs.release_body }} | |
| releaseDraft: true | |
| prerelease: ${{ needs.create-draft-release.outputs.prerelease }} | |
| tauriScript: pnpm tauri | |
| args: --target ${{ matrix.target }} | |
| includeUpdaterJson: true | |
| retryAttempts: 2 | |
| build-server: | |
| needs: create-draft-release | |
| name: Server ${{ matrix.name }} | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: "Linux x64" | |
| runner: "ubuntu-22.04" | |
| target: "x86_64-unknown-linux-gnu" | |
| artifact: "codeg-server-linux-x64" | |
| - name: "Linux arm64" | |
| runner: "ubuntu-22.04" | |
| target: "aarch64-unknown-linux-gnu" | |
| artifact: "codeg-server-linux-arm64" | |
| - name: "macOS x64" | |
| runner: "macos-latest" | |
| target: "x86_64-apple-darwin" | |
| artifact: "codeg-server-darwin-x64" | |
| - name: "macOS arm64" | |
| runner: "macos-latest" | |
| target: "aarch64-apple-darwin" | |
| artifact: "codeg-server-darwin-arm64" | |
| - name: "Windows x64" | |
| runner: "windows-2022" | |
| target: "x86_64-pc-windows-msvc" | |
| artifact: "codeg-server-windows-x64" | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Rust cache | |
| uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: "./src-tauri -> target" | |
| shared-key: server-${{ matrix.target }} | |
| - name: Install Linux arm64 cross compiler | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| cat > /tmp/sources.list << 'EOF' | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse | |
| deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse | |
| deb [arch=amd64] http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse | |
| deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse | |
| EOF | |
| sudo mv /etc/apt/sources.list /etc/apt/sources.list.default | |
| sudo mv /tmp/sources.list /etc/apt/sources.list | |
| sudo dpkg --add-architecture arm64 | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| gcc-aarch64-linux-gnu \ | |
| g++-aarch64-linux-gnu \ | |
| libssl-dev:arm64 | |
| echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_ALLOW_CROSS=1" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> "$GITHUB_ENV" | |
| echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" | |
| echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> "$GITHUB_ENV" | |
| echo "AR_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc-ar" >> "$GITHUB_ENV" | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: "pnpm" | |
| - name: Build frontend | |
| run: | | |
| pnpm install --frozen-lockfile | |
| pnpm build | |
| - name: Build server + codeg-mcp companion | |
| working-directory: src-tauri | |
| # `codeg-mcp` is the stdio MCP companion the runtime injects per | |
| # session (see acp/delegation/companion.rs). Built with the same | |
| # `--no-default-features --target` flags as the server so it shares | |
| # the cross-compile env (Linux arm64) without dragging in tauri | |
| # runtime deps. | |
| run: | | |
| cargo build --release --bin codeg-server --no-default-features --target ${{ matrix.target }} | |
| cargo build --release --bin codeg-mcp --no-default-features --target ${{ matrix.target }} | |
| - name: Package (Unix) | |
| if: runner.os != 'Windows' | |
| run: | | |
| mkdir -p dist/${{ matrix.artifact }} | |
| cp src-tauri/target/${{ matrix.target }}/release/codeg-server dist/${{ matrix.artifact }}/ | |
| cp src-tauri/target/${{ matrix.target }}/release/codeg-mcp dist/${{ matrix.artifact }}/ | |
| chmod +x dist/${{ matrix.artifact }}/codeg-server dist/${{ matrix.artifact }}/codeg-mcp | |
| cp -r out dist/${{ matrix.artifact }}/web | |
| cd dist && tar czf ${{ matrix.artifact }}.tar.gz ${{ matrix.artifact }} | |
| - name: Package (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path dist/${{ matrix.artifact }} | |
| Copy-Item src-tauri/target/${{ matrix.target }}/release/codeg-server.exe dist/${{ matrix.artifact }}/ | |
| Copy-Item src-tauri/target/${{ matrix.target }}/release/codeg-mcp.exe dist/${{ matrix.artifact }}/ | |
| Copy-Item -Recurse out dist/${{ matrix.artifact }}/web | |
| Compress-Archive -Path dist/${{ matrix.artifact }} -DestinationPath dist/${{ matrix.artifact }}.zip | |
| - name: Smoke test packaged artifact (Unix) | |
| if: runner.os != 'Windows' | |
| run: | | |
| set -euo pipefail | |
| test -x "dist/${{ matrix.artifact }}/codeg-server" | |
| test -x "dist/${{ matrix.artifact }}/codeg-mcp" | |
| # `codeg-mcp --help` exits 0 without flags and prints the usage | |
| # line. Only run it for native targets; cross-compiled arm64 | |
| # binaries on x64 runners can't execute. | |
| if [ "${{ matrix.target }}" = "x86_64-unknown-linux-gnu" ] || \ | |
| [ "${{ matrix.target }}" = "x86_64-apple-darwin" ] || \ | |
| [ "${{ matrix.target }}" = "aarch64-apple-darwin" ]; then | |
| "dist/${{ matrix.artifact }}/codeg-mcp" --help | grep -F 'codeg-mcp --parent-connection-id' | |
| else | |
| echo "skipping codeg-mcp --help on cross-target ${{ matrix.target }}" | |
| fi | |
| - name: Smoke test packaged artifact (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| if (-not (Test-Path "dist/${{ matrix.artifact }}/codeg-server.exe")) { | |
| throw "codeg-server.exe missing from packaged artifact" | |
| } | |
| if (-not (Test-Path "dist/${{ matrix.artifact }}/codeg-mcp.exe")) { | |
| throw "codeg-mcp.exe missing from packaged artifact" | |
| } | |
| $help = & "dist/${{ matrix.artifact }}/codeg-mcp.exe" --help | |
| if ($help -notlike "*codeg-mcp --parent-connection-id*") { | |
| throw "codeg-mcp --help output unexpected: $help" | |
| } | |
| - name: Upload artifact for Docker build (Linux only) | |
| if: startsWith(matrix.target, 'x86_64-unknown-linux') || startsWith(matrix.target, 'aarch64-unknown-linux') | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| path: dist/${{ matrix.artifact }} | |
| retention-days: 1 | |
| - name: Upload to release (Unix) | |
| if: runner.os != 'Windows' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: gh release upload "${{ github.ref_name }}" dist/${{ matrix.artifact }}.tar.gz --clobber | |
| - name: Upload to release (Windows) | |
| if: runner.os == 'Windows' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: gh release upload "${{ github.ref_name }}" dist/${{ matrix.artifact }}.zip --clobber | |
| build-docker: | |
| needs: | |
| - create-draft-release | |
| - build-server | |
| name: Build Docker image | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download Linux x64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codeg-server-linux-x64 | |
| path: artifacts/linux-x64 | |
| - name: Download Linux arm64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codeg-server-linux-arm64 | |
| path: artifacts/linux-arm64 | |
| - name: Prepare Docker build context | |
| run: | | |
| set -euo pipefail | |
| mkdir -p dist/amd64 dist/arm64 | |
| cp artifacts/linux-x64/codeg-server dist/amd64/codeg-server | |
| cp artifacts/linux-x64/codeg-mcp dist/amd64/codeg-mcp | |
| cp artifacts/linux-arm64/codeg-server dist/arm64/codeg-server | |
| cp artifacts/linux-arm64/codeg-mcp dist/arm64/codeg-mcp | |
| cp -r artifacts/linux-x64/web dist/web | |
| chmod +x dist/amd64/codeg-server dist/amd64/codeg-mcp \ | |
| dist/arm64/codeg-server dist/arm64/codeg-mcp | |
| # Fail fast if any companion went missing — Docker would otherwise | |
| # produce an image where delegation silently degrades. | |
| for f in dist/amd64/codeg-mcp dist/arm64/codeg-mcp; do | |
| test -x "$f" || { echo "FATAL: $f missing or non-exec"; exit 1; } | |
| done | |
| - name: Set up QEMU (for multi-arch manifest) | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Extract version from tag | |
| id: version | |
| run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: Dockerfile.ci | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: | | |
| ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }} | |
| ghcr.io/${{ github.repository }}:latest | |
| ${{ secrets.DOCKERHUB_USERNAME }}/codeg:${{ steps.version.outputs.version }} | |
| ${{ secrets.DOCKERHUB_USERNAME }}/codeg:latest | |
| publish-release: | |
| needs: | |
| - create-draft-release | |
| - build-tauri | |
| - build-server | |
| - build-docker | |
| if: ${{ needs.build-tauri.result == 'success' && needs.build-server.result == 'success' && needs.build-docker.result == 'success' }} | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Publish draft release | |
| uses: actions/github-script@v7 | |
| env: | |
| RELEASE_ID: ${{ needs.create-draft-release.outputs.release_id }} | |
| with: | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const releaseId = Number(process.env.RELEASE_ID); | |
| const prerelease = | |
| "${{ needs.create-draft-release.outputs.prerelease }}" === "true"; | |
| await github.rest.repos.updateRelease({ | |
| owner, | |
| repo, | |
| release_id: releaseId, | |
| draft: false, | |
| prerelease, | |
| }); | |
| core.info(`Published release #${releaseId}`); |