name: release-please
on:
push:
branches:
- main
workflow_dispatch:
permissions:
actions: write
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- id: release
uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
command: manifest
config-file: .release-please-config.json
- uses: actions/checkout@v4
if: ${{ steps.release.outputs.release_created == 'true' }}
with:
ref: ${{ steps.release.outputs.tag_name }}
- name: Install Rust
if: ${{ steps.release.outputs.release_created == 'true' }}
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo registry
if: ${{ steps.release.outputs.release_created == 'true' }}
uses: swatinem/rust-cache@v2
- name: Publish crate
if: ${{ steps.release.outputs.release_created == 'true' }}
run: cargo publish --locked --token "$CARGO_REGISTRY_TOKEN"
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Dispatch Arch package workflow
if: ${{ steps.release.outputs.release_created == 'true' }}
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.release.outputs.tag_name }}
run: gh workflow run publish-arch-package.yml --ref "$TAG"
release-binaries:
needs: release
if: ${{ needs.release.outputs.release_created == 'true' }}
name: release binary ${{ matrix.target }}
permissions:
contents: write
pull-requests: write
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
cache-targets: false
- os: macos-13
target: x86_64-apple-darwin
cache-targets: true
- os: macos-14
target: aarch64-apple-darwin
cache-targets: true
- os: windows-latest
target: x86_64-pc-windows-msvc
cache-targets: true
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.tag_name }}
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo registry
uses: swatinem/rust-cache@v2
with:
cache-targets: ${{ matrix.cache-targets }}
shared-key: release-binaries-${{ matrix.target }}
- name: Build binary
run: cargo build --release --locked --bin rho --target ${{ matrix.target }}
- name: Sign Windows binary
if: runner.os == 'Windows'
shell: pwsh
env:
WINDOWS_SIGNING_CERT_BASE64: ${{ secrets.WINDOWS_SIGNING_CERT_BASE64 }}
WINDOWS_SIGNING_CERT_PASSWORD: ${{ secrets.WINDOWS_SIGNING_CERT_PASSWORD }}
run: |
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_SIGNING_CERT_BASE64)) {
Write-Host "WINDOWS_SIGNING_CERT_BASE64 is not set; skipping Authenticode signing."
exit 0
}
$CertPath = Join-Path $env:RUNNER_TEMP "rho-signing-cert.pfx"
[IO.File]::WriteAllBytes($CertPath, [Convert]::FromBase64String($env:WINDOWS_SIGNING_CERT_BASE64))
$Signtool = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\bin" -Recurse -Filter signtool.exe |
Where-Object { $_.FullName -match "x64" } |
Select-Object -First 1 -ExpandProperty FullName
if (-not $Signtool) {
throw "signtool.exe was not found"
}
& $Signtool sign /f $CertPath /p $env:WINDOWS_SIGNING_CERT_PASSWORD /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 target/${{ matrix.target }}/release/rho.exe
& $Signtool verify /pa target/${{ matrix.target }}/release/rho.exe
- name: Package Unix binary
if: runner.os != 'Windows'
run: |
mkdir -p dist
cp target/${{ matrix.target }}/release/rho dist/rho
tar -C dist -czf rho-${{ matrix.target }}.tar.gz rho
shasum -a 256 rho-${{ matrix.target }}.tar.gz > rho-${{ matrix.target }}.tar.gz.sha256
- name: Package Windows binary
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null
Copy-Item target/${{ matrix.target }}/release/rho.exe dist/rho.exe
Compress-Archive -Path dist/rho.exe -DestinationPath rho-${{ matrix.target }}.zip -Force
$Hash = (Get-FileHash -Algorithm SHA256 rho-${{ matrix.target }}.zip).Hash.ToLowerInvariant()
"$Hash rho-${{ matrix.target }}.zip" | Out-File -Encoding ascii rho-${{ matrix.target }}.zip.sha256
- name: Upload Unix release assets
if: runner.os != 'Windows'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release.outputs.tag_name }}
run: gh release upload "$TAG" rho-${{ matrix.target }}.tar.gz rho-${{ matrix.target }}.tar.gz.sha256 --clobber
- name: Upload Windows release assets
if: runner.os == 'Windows'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release.outputs.tag_name }}
shell: pwsh
run: gh release upload "$env:TAG" rho-${{ matrix.target }}.zip rho-${{ matrix.target }}.zip.sha256 --clobber
- name: Checkout main for Scoop manifest update
if: runner.os == 'Windows'
uses: actions/checkout@v4
with:
ref: main
- name: Download Windows checksum
if: runner.os == 'Windows'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release.outputs.tag_name }}
shell: pwsh
run: gh release download "$env:TAG" --pattern "rho-${{ matrix.target }}.zip.sha256"
- name: Update Scoop manifest
if: runner.os == 'Windows'
env:
GH_TOKEN: ${{ github.token }}
shell: pwsh
run: |
$Tag = "${{ needs.release.outputs.tag_name }}"
$Version = $Tag -replace '^rho-coding-agent-v', ''
$Asset = "rho-${{ matrix.target }}.zip"
$Hash = ((Get-Content "$Asset.sha256" -Raw) -split '\s+')[0]
$Url = "https://github.com/${{ github.repository }}/releases/download/$Tag/$Asset"
$ManifestPath = "bucket/rho.json"
$Manifest = Get-Content $ManifestPath -Raw | ConvertFrom-Json
$Manifest.version = $Version
$Manifest.architecture.'64bit'.url = $Url
$Manifest.architecture.'64bit'.hash = $Hash
$Manifest | ConvertTo-Json -Depth 10 | Set-Content -Path $ManifestPath -Encoding UTF8
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add $ManifestPath
if (git diff --cached --quiet) {
Write-Host "Scoop manifest is already up to date."
exit 0
}
$Branch = "build/update-scoop-manifest-$Tag"
if (git ls-remote --heads origin $Branch) {
git fetch origin "${Branch}:refs/remotes/origin/${Branch}"
}
git checkout -B $Branch
git commit -m "build(windows): update scoop manifest for $Tag"
git push --force-with-lease origin "HEAD:$Branch"
$Title = "build(windows): update scoop manifest for $Tag"
$BodyFile = New-TemporaryFile
Set-Content -Path $BodyFile -Value "Updates the Scoop manifest for $Tag."
$ExistingPr = gh pr list --head $Branch --base main --json number --jq '.[0].number'
if ($ExistingPr) {
gh pr edit $ExistingPr --title $Title --body-file $BodyFile
} else {
gh pr create --base main --head $Branch --title $Title --body-file $BodyFile
}