feat: group built-in tool capabilities #73
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: | |
| workflow_dispatch: | |
| push: | |
| tags: | |
| - "v*" | |
| permissions: | |
| contents: write | |
| id-token: write | |
| jobs: | |
| build-binary: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| target: linux-x86_64 | |
| rust_target: x86_64-unknown-linux-musl | |
| goos: linux | |
| goarch: amd64 | |
| exe_ext: "" | |
| cross: false | |
| build_dir: target | |
| - os: ubuntu-latest | |
| target: linux-arm64 | |
| rust_target: aarch64-unknown-linux-musl | |
| goos: linux | |
| goarch: arm64 | |
| exe_ext: "" | |
| cross: true | |
| build_dir: target-cross | |
| - os: windows-latest | |
| target: windows-x86_64 | |
| rust_target: x86_64-pc-windows-msvc | |
| goos: windows | |
| goarch: amd64 | |
| exe_ext: ".exe" | |
| cross: false | |
| build_dir: target | |
| - os: macos-15-intel | |
| target: macos-x86_64 | |
| rust_target: x86_64-apple-darwin | |
| goos: darwin | |
| goarch: amd64 | |
| exe_ext: "" | |
| cross: false | |
| build_dir: target | |
| - os: macos-latest | |
| target: macos-arm64 | |
| rust_target: aarch64-apple-darwin | |
| goos: darwin | |
| goarch: arm64 | |
| exe_ext: "" | |
| cross: false | |
| build_dir: target | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Protoc | |
| uses: arduino/setup-protoc@v3 | |
| with: | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Linux build dependencies | |
| if: ${{ runner.os == 'Linux' && !contains(matrix.rust_target, 'linux-musl') }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 libasound2-dev | |
| - name: Install musl tools (Linux) | |
| if: ${{ contains(matrix.rust_target, 'linux-musl') && !matrix.cross }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 musl-tools libasound2-dev linux-libc-dev | |
| - name: Install cross (ARM Linux) | |
| if: ${{ matrix.cross }} | |
| run: cargo install cross --git https://github.com/cross-rs/cross | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.rust_target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| if: ${{ !matrix.cross }} | |
| - name: Build Rust binary (native) | |
| if: ${{ !matrix.cross }} | |
| shell: bash | |
| run: | | |
| cargo build --release --locked --target ${{ matrix.rust_target }} --bin anda | |
| if [[ "${{ matrix.target }}" == windows-* || "${{ matrix.target }}" == macos-* ]]; then | |
| cargo build --release --locked --target ${{ matrix.rust_target }} --bin anda_launcher | |
| fi | |
| - name: Build Rust binary (cross) | |
| if: ${{ matrix.cross }} | |
| shell: bash | |
| env: | |
| XDG_CACHE_HOME: /tmp/anda-xdg-cache | |
| run: | | |
| cross build --release --locked --target-dir ${{ matrix.build_dir }} --target ${{ matrix.rust_target }} --bin anda | |
| - name: Collect artifacts | |
| shell: bash | |
| run: | | |
| mkdir -p release | |
| cp "${{ matrix.build_dir }}/${{ matrix.rust_target }}/release/anda${{ matrix.exe_ext }}" "release/anda-${{ matrix.target }}${{ matrix.exe_ext }}" | |
| if [[ "${{ matrix.target }}" == windows-* || "${{ matrix.target }}" == macos-* ]]; then | |
| cp "${{ matrix.build_dir }}/${{ matrix.rust_target }}/release/anda_launcher${{ matrix.exe_ext }}" "release/anda_launcher-${{ matrix.target }}${{ matrix.exe_ext }}" | |
| fi | |
| ls -lah release | |
| - name: Check Artifact Signing configuration | |
| if: ${{ runner.os == 'Windows' }} | |
| id: artifact-signing-config | |
| shell: pwsh | |
| env: | |
| AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} | |
| AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} | |
| AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| AZURE_ARTIFACT_SIGNING_ENDPOINT: ${{ vars.AZURE_ARTIFACT_SIGNING_ENDPOINT }} | |
| AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME: ${{ vars.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} | |
| AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME: ${{ vars.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} | |
| run: | | |
| $missing = @( | |
| "AZURE_CLIENT_ID", | |
| "AZURE_TENANT_ID", | |
| "AZURE_SUBSCRIPTION_ID", | |
| "AZURE_ARTIFACT_SIGNING_ENDPOINT", | |
| "AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME", | |
| "AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME" | |
| ) | Where-Object { [string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($_)) } | |
| if ($missing.Count -gt 0) { | |
| Write-Host "Azure Artifact Signing is not fully configured; skipping Windows Authenticode signing. Missing: $($missing -join ', ')" | |
| "configured=false" >> $env:GITHUB_OUTPUT | |
| exit 0 | |
| } | |
| "configured=true" >> $env:GITHUB_OUTPUT | |
| - name: Azure login for Artifact Signing | |
| if: ${{ runner.os == 'Windows' && steps.artifact-signing-config.outputs.configured == 'true' }} | |
| uses: azure/login@v3 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Sign Windows binaries | |
| if: ${{ runner.os == 'Windows' && steps.artifact-signing-config.outputs.configured == 'true' }} | |
| uses: azure/artifact-signing-action@v2 | |
| with: | |
| endpoint: ${{ vars.AZURE_ARTIFACT_SIGNING_ENDPOINT }} | |
| signing-account-name: ${{ vars.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} | |
| certificate-profile-name: ${{ vars.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} | |
| files-folder: ${{ github.workspace }}\release | |
| files-folder-filter: exe,dll,msi,msix,msixbundle,appx,appxbundle,cab | |
| file-digest: SHA256 | |
| timestamp-rfc3161: http://timestamp.acs.microsoft.com | |
| timestamp-digest: SHA256 | |
| description: Anda Bot | |
| description-url: https://github.com/ldclabs/anda-bot | |
| - name: Verify Windows binary signatures | |
| if: ${{ runner.os == 'Windows' && steps.artifact-signing-config.outputs.configured == 'true' }} | |
| shell: pwsh | |
| run: | | |
| $extensions = @(".exe", ".dll", ".msi", ".msix", ".msixbundle", ".appx", ".appxbundle", ".cab") | |
| foreach ($file in Get-ChildItem -LiteralPath release -File | Where-Object { $extensions -contains $_.Extension.ToLowerInvariant() }) { | |
| $signature = Get-AuthenticodeSignature -LiteralPath $file.FullName | |
| if ($signature.Status -ne "Valid") { | |
| throw "Invalid Authenticode signature for $($file.FullName): $($signature.Status) $($signature.StatusMessage)" | |
| } | |
| Write-Host "Verified Authenticode signature for $($file.Name)" | |
| } | |
| - name: Generate checksums | |
| shell: bash | |
| run: | | |
| for file in release/*; do | |
| if command -v sha256sum >/dev/null 2>&1; then | |
| hash="$(sha256sum "$file" | awk '{print $1}')" | |
| elif command -v shasum >/dev/null 2>&1; then | |
| hash="$(shasum -a 256 "$file" | awk '{print $1}')" | |
| else | |
| hash="$(openssl dgst -sha256 "$file" | awk '{print $NF}')" | |
| fi | |
| echo "$hash $(basename "$file")" > "${file}.sha256" | |
| done | |
| ls -lah release | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-${{ matrix.target }} | |
| path: release/* | |
| if-no-files-found: error | |
| package-skills: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Package skills | |
| shell: bash | |
| run: | | |
| mkdir -p release | |
| skills_archive="anda-skills.zip" | |
| (cd skills && zip -qr "../release/${skills_archive}" . -x '__pycache__/*' '*/__pycache__/*' '*.pyc' '.DS_Store' '*/.DS_Store') | |
| hash="$(sha256sum "release/${skills_archive}" | awk '{print $1}')" | |
| echo "$hash ${skills_archive}" > "release/${skills_archive}.sha256" | |
| ls -lah release | |
| - name: Upload skills artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-skills | |
| path: release/* | |
| if-no-files-found: error | |
| package-windows-installer: | |
| needs: | |
| - build-binary | |
| - package-skills | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Download Windows binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-windows-x86_64 | |
| path: release | |
| - name: Download skills | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-skills | |
| path: release | |
| - name: Check Artifact Signing configuration | |
| id: artifact-signing-config | |
| shell: pwsh | |
| env: | |
| AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} | |
| AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} | |
| AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| AZURE_ARTIFACT_SIGNING_ENDPOINT: ${{ vars.AZURE_ARTIFACT_SIGNING_ENDPOINT }} | |
| AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME: ${{ vars.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} | |
| AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME: ${{ vars.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} | |
| run: | | |
| $missing = @( | |
| "AZURE_CLIENT_ID", | |
| "AZURE_TENANT_ID", | |
| "AZURE_SUBSCRIPTION_ID", | |
| "AZURE_ARTIFACT_SIGNING_ENDPOINT", | |
| "AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME", | |
| "AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME" | |
| ) | Where-Object { [string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($_)) } | |
| if ($missing.Count -gt 0) { | |
| Write-Host "Azure Artifact Signing is not fully configured; building an unsigned Windows installer. Missing: $($missing -join ', ')" | |
| "configured=false" >> $env:GITHUB_OUTPUT | |
| exit 0 | |
| } | |
| "configured=true" >> $env:GITHUB_OUTPUT | |
| - name: Build Windows installer | |
| shell: pwsh | |
| run: | | |
| ./scripts/build-windows-installer.ps1 -ReleaseDir release | |
| - name: Azure login for Artifact Signing | |
| if: ${{ steps.artifact-signing-config.outputs.configured == 'true' }} | |
| uses: azure/login@v3 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Sign Windows installer | |
| if: ${{ steps.artifact-signing-config.outputs.configured == 'true' }} | |
| uses: azure/artifact-signing-action@v2 | |
| with: | |
| endpoint: ${{ vars.AZURE_ARTIFACT_SIGNING_ENDPOINT }} | |
| signing-account-name: ${{ vars.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} | |
| certificate-profile-name: ${{ vars.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} | |
| files: ${{ github.workspace }}\release\AndaBotSetup-windows-x86_64.exe | |
| file-digest: SHA256 | |
| timestamp-rfc3161: http://timestamp.acs.microsoft.com | |
| timestamp-digest: SHA256 | |
| description: Anda Bot Setup | |
| description-url: https://github.com/ldclabs/anda-bot | |
| - name: Verify Windows installer signature | |
| if: ${{ steps.artifact-signing-config.outputs.configured == 'true' }} | |
| shell: pwsh | |
| run: | | |
| $path = Join-Path $PWD "release\AndaBotSetup-windows-x86_64.exe" | |
| $signature = Get-AuthenticodeSignature -LiteralPath $path | |
| if ($signature.Status -ne "Valid") { | |
| throw "Invalid Authenticode signature for ${path}: $($signature.Status) $($signature.StatusMessage)" | |
| } | |
| Write-Host "Verified Authenticode signature for AndaBotSetup-windows-x86_64.exe" | |
| - name: Generate Windows installer checksum | |
| shell: pwsh | |
| run: | | |
| $path = Join-Path $PWD "release\AndaBotSetup-windows-x86_64.exe" | |
| $hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $path).Hash.ToLowerInvariant() | |
| Set-Content -Path "$path.sha256" -Value "$hash AndaBotSetup-windows-x86_64.exe" -Encoding ASCII | |
| - name: Upload Windows installer | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-windows-installer | |
| path: | | |
| release/AndaBotSetup-windows-x86_64.exe | |
| release/AndaBotSetup-windows-x86_64.exe.sha256 | |
| if-no-files-found: error | |
| release: | |
| needs: | |
| - build-binary | |
| - package-skills | |
| - package-windows-installer | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: release-* | |
| merge-multiple: true | |
| path: release | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: release/* | |
| - name: Publish Homebrew formula | |
| env: | |
| CHECKSUM_DIR: release | |
| HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| run: scripts/publish-homebrew.sh "${{ github.ref_name }}" |