Release Backfill #1
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 Backfill | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: Existing semver tag to publish, for example v0.1.0 | |
| required: true | |
| type: string | |
| jobs: | |
| checks: | |
| name: ${{ matrix.target }} | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| RELEASE_TAG: ${{ inputs.release_tag }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| asset_name: mcp-repl-x86_64-unknown-linux-gnu.tar.gz | |
| artifact_name: release-x86_64-unknown-linux-gnu | |
| - os: macos-15 | |
| target: aarch64-apple-darwin | |
| asset_name: mcp-repl-aarch64-apple-darwin.tar.gz | |
| artifact_name: release-aarch64-apple-darwin | |
| - os: windows-2022 | |
| target: x86_64-pc-windows-msvc | |
| asset_name: mcp-repl-x86_64-pc-windows-msvc.zip | |
| artifact_name: release-x86_64-pc-windows-msvc | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.RELEASE_TAG }} | |
| fetch-depth: 0 | |
| - name: Validate release tag | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| [[ "${RELEASE_TAG}" =~ ^v[0-9]+(\.[0-9]+){2}(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]] | |
| git rev-parse "refs/tags/${RELEASE_TAG}" >/dev/null | |
| - name: Set up Rust (stable) | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| components: clippy, rustfmt | |
| rustflags: "" | |
| - name: Install nightly rustfmt | |
| run: rustup toolchain install nightly --profile minimal --component rustfmt | |
| - name: Set up R | |
| uses: r-lib/actions/setup-r@v2 | |
| - name: cargo check | |
| run: cargo check | |
| - name: cargo build | |
| run: cargo build | |
| - name: cargo clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| - name: cargo test (skip client integrations) | |
| if: matrix.os != 'windows-2022' | |
| run: cargo test -- --skip codex_tui_initial_sandbox_state --skip codex_tui_initial_sandbox_state_windows_stub | |
| - name: cargo test (windows serial, skip client integrations) | |
| if: matrix.os == 'windows-2022' | |
| run: cargo test -j 1 -- --test-threads=1 --skip codex_tui_initial_sandbox_state --skip codex_tui_initial_sandbox_state_windows_stub | |
| - name: cargo +nightly fmt | |
| run: cargo +nightly fmt --all -- --check | |
| - name: cargo build --release | |
| run: cargo build --release --locked | |
| - name: Smoke test release binary | |
| if: matrix.os != 'windows-2022' | |
| run: ./target/release/mcp-repl --help | |
| - name: Smoke test release binary (windows) | |
| if: matrix.os == 'windows-2022' | |
| shell: pwsh | |
| run: | | |
| .\target\release\mcp-repl.exe --help | |
| - name: Package release archive | |
| if: matrix.os != 'windows-2022' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| package_dir="dist/mcp-repl-${{ matrix.target }}" | |
| mkdir -p "$package_dir" | |
| cp target/release/mcp-repl "$package_dir/mcp-repl" | |
| cp README.md LICENSE "$package_dir/" | |
| tar -C dist -czf "dist/${{ matrix.asset_name }}" "mcp-repl-${{ matrix.target }}" | |
| - name: Package release archive (windows) | |
| if: matrix.os == 'windows-2022' | |
| shell: pwsh | |
| run: | | |
| $packageDir = "dist/mcp-repl-${{ matrix.target }}" | |
| New-Item -ItemType Directory -Force -Path $packageDir | Out-Null | |
| Copy-Item "target/release/mcp-repl.exe" "$packageDir/mcp-repl.exe" | |
| Copy-Item "README.md" "$packageDir/README.md" | |
| Copy-Item "LICENSE" "$packageDir/LICENSE" | |
| Push-Location "dist" | |
| Compress-Archive -Path "mcp-repl-${{ matrix.target }}" -DestinationPath "${{ matrix.asset_name }}" -Force | |
| Pop-Location | |
| - name: Upload packaged artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact_name }} | |
| path: dist/${{ matrix.asset_name }} | |
| if-no-files-found: error | |
| publish-release: | |
| name: publish-release | |
| needs: checks | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: write | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_TAG: ${{ inputs.release_tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.RELEASE_TAG }} | |
| fetch-depth: 0 | |
| - name: Validate release tag | |
| id: release_tag | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ "${RELEASE_TAG}" =~ ^v[0-9]+(\.[0-9]+){2}$ ]]; then | |
| echo "prerelease=false" >> "$GITHUB_OUTPUT" | |
| elif [[ "${RELEASE_TAG}" =~ ^v[0-9]+(\.[0-9]+){2}(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)$ ]]; then | |
| echo "prerelease=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "release tag must be final semver like v0.1.0 or prerelease semver like v0.1.0-rc1" >&2 | |
| exit 1 | |
| fi | |
| git rev-parse "refs/tags/${RELEASE_TAG}" >/dev/null | |
| - name: Download packaged artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: release-* | |
| merge-multiple: true | |
| path: dist | |
| - name: Verify packaged asset set | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| expected_assets=( | |
| mcp-repl-x86_64-unknown-linux-gnu.tar.gz | |
| mcp-repl-aarch64-apple-darwin.tar.gz | |
| mcp-repl-x86_64-pc-windows-msvc.zip | |
| ) | |
| for asset in "${expected_assets[@]}"; do | |
| test -f "dist/$asset" | |
| done | |
| actual_count="$(find dist -maxdepth 1 -type f | wc -l | tr -d ' ')" | |
| test "$actual_count" = "3" | |
| - name: Write SHA256SUMS.txt | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ( | |
| cd dist | |
| sha256sum \ | |
| mcp-repl-x86_64-unknown-linux-gnu.tar.gz \ | |
| mcp-repl-aarch64-apple-darwin.tar.gz \ | |
| mcp-repl-x86_64-pc-windows-msvc.zip \ | |
| > SHA256SUMS.txt | |
| ) | |
| - name: Decide whether this tag should be latest | |
| id: latest_guard | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ steps.release_tag.outputs.prerelease }}" = "true" ]; then | |
| echo "is_latest=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| newest_final_tag="$(git tag --list 'v*.*.*' | grep -E '^v[0-9]+(\.[0-9]+){2}$' | sort -V | tail -n 1)" | |
| if [ "$newest_final_tag" = "${RELEASE_TAG}" ]; then | |
| echo "is_latest=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "is_latest=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Create or update tag release | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| prerelease_flag="${{ steps.release_tag.outputs.prerelease }}" | |
| if gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then | |
| release_id="$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}" --jq .id)" | |
| latest_flag=false | |
| if [ "${{ steps.latest_guard.outputs.is_latest }}" = "true" ]; then | |
| latest_flag=true | |
| fi | |
| gh api \ | |
| --method PATCH \ | |
| -H "Accept: application/vnd.github+json" \ | |
| "repos/${GITHUB_REPOSITORY}/releases/${release_id}" \ | |
| -F tag_name="${RELEASE_TAG}" \ | |
| -F name="${RELEASE_TAG}" \ | |
| -F draft=false \ | |
| -F prerelease="${prerelease_flag}" \ | |
| -f make_latest="${latest_flag}" \ | |
| >/dev/null | |
| gh release upload "${RELEASE_TAG}" dist/* --clobber | |
| else | |
| latest_args=("--latest=false") | |
| prerelease_args=() | |
| if [ "${{ steps.latest_guard.outputs.is_latest }}" = "true" ]; then | |
| latest_args=("--latest") | |
| fi | |
| if [ "${prerelease_flag}" = "true" ]; then | |
| prerelease_args=("--prerelease") | |
| fi | |
| gh release create "${RELEASE_TAG}" dist/* --title "${RELEASE_TAG}" --generate-notes "${prerelease_args[@]}" "${latest_args[@]}" | |
| fi |