feat: add support for configuring branch name prefix #117
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: PR Build | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened] | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.VERSION }} | |
| pr_number: ${{ steps.version.outputs.PR_NUMBER }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| targets: x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu | |
| - name: Install cross-compilation tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-aarch64-linux-gnu | |
| - name: Set PR version | |
| id: version | |
| run: | | |
| PR_NUMBER=${{ github.event.pull_request.number }} | |
| COMMIT_SHA=${{ github.event.pull_request.head.sha }} | |
| COMMIT_SHA=${COMMIT_SHA::7} | |
| CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') | |
| PR_VERSION="${CARGO_VERSION}-pr.${PR_NUMBER}.${COMMIT_SHA}" | |
| echo "VERSION=$PR_VERSION" >> $GITHUB_OUTPUT | |
| echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT | |
| echo "Generated PR version: ${PR_VERSION}" | |
| sed -i "s/^version = \".*\"/version = \"${PR_VERSION}\"/" Cargo.toml | |
| - name: Format check | |
| run: cargo fmt --all -- --check | |
| - name: Build for Linux x64 | |
| run: cargo build --release --target x86_64-unknown-linux-gnu | |
| - name: Build for Linux ARM64 | |
| env: | |
| CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc | |
| run: cargo build --release --target aarch64-unknown-linux-gnu | |
| - name: Prepare artifacts | |
| run: | | |
| cp target/x86_64-unknown-linux-gnu/release/grove grove-linux-x64 | |
| cp target/aarch64-unknown-linux-gnu/release/grove grove-linux-arm64 | |
| - name: Upload Linux executables | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: grove-linux-executables | |
| path: | | |
| grove-linux-x64 | |
| grove-linux-arm64 | |
| retention-days: 1 | |
| build-macos: | |
| runs-on: macos-latest | |
| needs: build-linux | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: x86_64-apple-darwin,aarch64-apple-darwin | |
| - name: Set version | |
| run: sed -i '' "s/^version = \".*\"/version = \"${{ needs.build-linux.outputs.version }}\"/" Cargo.toml | |
| - name: Build for macOS x64 | |
| run: cargo build --release --target x86_64-apple-darwin | |
| - name: Build for macOS ARM64 | |
| run: cargo build --release --target aarch64-apple-darwin | |
| - name: Prepare artifacts | |
| run: | | |
| cp target/x86_64-apple-darwin/release/grove grove-darwin-x64 | |
| cp target/aarch64-apple-darwin/release/grove grove-darwin-arm64 | |
| - name: Import Code Signing Certificate | |
| env: | |
| MACOS_CERT_P12_BASE64: ${{ secrets.MACOS_CERT_P12_BASE64 }} | |
| MACOS_CERT_P12_PASSWORD: ${{ secrets.MACOS_CERT_P12_PASSWORD }} | |
| run: | | |
| # Create a temporary keychain | |
| KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db | |
| KEYCHAIN_PASSWORD=$(openssl rand -base64 32) | |
| # Decode the certificate | |
| echo "$MACOS_CERT_P12_BASE64" | base64 --decode > $RUNNER_TEMP/certificate.p12 | |
| # Create and configure keychain | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| security set-keychain-settings -lut 21600 $KEYCHAIN_PATH | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| # Import certificate | |
| security import $RUNNER_TEMP/certificate.p12 -P "$MACOS_CERT_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
| security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
| security list-keychain -d user -s $KEYCHAIN_PATH | |
| # Clean up certificate file | |
| rm $RUNNER_TEMP/certificate.p12 | |
| - name: Sign macOS Binaries | |
| run: | | |
| # Find the signing identity | |
| IDENTITY=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}') | |
| echo "Signing with identity: $IDENTITY" | |
| # Sign both binaries with JIT entitlements | |
| codesign --force --options runtime --timestamp --entitlements .github/workflows/assets/entitlements.plist --sign "$IDENTITY" grove-darwin-x64 | |
| codesign --force --options runtime --timestamp --entitlements .github/workflows/assets/entitlements.plist --sign "$IDENTITY" grove-darwin-arm64 | |
| # Verify signatures | |
| codesign --verify --verbose grove-darwin-x64 | |
| codesign --verify --verbose grove-darwin-arm64 | |
| - name: Notarize macOS Binaries | |
| env: | |
| APPLE_ID_EMAIL: ${{ secrets.APPLE_ID_EMAIL }} | |
| APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
| run: | | |
| # Create zip files for notarization | |
| zip grove-darwin-x64.zip grove-darwin-x64 | |
| zip grove-darwin-arm64.zip grove-darwin-arm64 | |
| # Get team ID from signing identity | |
| TEAM_ID=$(security find-identity -v -p codesigning | grep "Developer ID Application" | head -1 | sed -n 's/.*(\([A-Z0-9]*\)).*/\1/p') | |
| # Notarize x64 binary | |
| xcrun notarytool submit grove-darwin-x64.zip \ | |
| --apple-id "$APPLE_ID_EMAIL" \ | |
| --password "$APPLE_APP_SPECIFIC_PASSWORD" \ | |
| --team-id "$TEAM_ID" \ | |
| --wait | |
| # Notarize ARM64 binary | |
| xcrun notarytool submit grove-darwin-arm64.zip \ | |
| --apple-id "$APPLE_ID_EMAIL" \ | |
| --password "$APPLE_APP_SPECIFIC_PASSWORD" \ | |
| --team-id "$TEAM_ID" \ | |
| --wait | |
| # Clean up zip files | |
| rm grove-darwin-x64.zip grove-darwin-arm64.zip | |
| - name: Upload macOS executables | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: grove-macos-executables | |
| path: | | |
| grove-darwin-x64 | |
| grove-darwin-arm64 | |
| retention-days: 1 | |
| build-windows: | |
| runs-on: windows-latest | |
| needs: build-linux | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set version | |
| shell: pwsh | |
| run: | | |
| $version = '${{ needs.build-linux.outputs.version }}' | |
| (Get-Content Cargo.toml -Raw) ` | |
| -replace '^(version = ").*(")$', "`$1$version`$2" | | |
| Set-Content Cargo.toml | |
| - name: Build for Windows x64 | |
| run: cargo build --release --target x86_64-pc-windows-msvc | |
| - name: Prepare artifacts | |
| run: | | |
| copy target\x86_64-pc-windows-msvc\release\grove.exe grove-windows-x64.exe | |
| - name: Upload Windows executable | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: grove-windows-executable | |
| path: | | |
| grove-windows-x64.exe | |
| retention-days: 1 | |
| publish-pr: | |
| runs-on: ubuntu-latest | |
| needs: [build-linux, build-macos, build-windows] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| actions: write | |
| steps: | |
| - name: Download Linux executables | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: grove-linux-executables | |
| path: ./executables | |
| - name: Download macOS executables | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: grove-macos-executables | |
| path: ./executables | |
| - name: Download Windows executables | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: grove-windows-executable | |
| path: ./executables | |
| - name: Upload combined PR executables | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: grove-pr-${{ needs.build-linux.outputs.pr_number }}-${{ needs.build-linux.outputs.version }} | |
| path: ./executables | |
| retention-days: 30 | |
| - name: Delete intermediate artifacts | |
| uses: geekyeggo/delete-artifact@v5 | |
| with: | |
| name: | | |
| grove-linux-executables | |
| grove-macos-executables | |
| grove-windows-executable | |
| - name: Comment on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prNumber = ${{ needs.build-linux.outputs.pr_number }}; | |
| const version = '${{ needs.build-linux.outputs.version }}'; | |
| const runId = context.runId; | |
| const body = `🌳 **Grove PR Build Ready!** | |
| **Version:** \`${version}\` | |
| **Install with:** | |
| \`\`\`bash | |
| curl https://i.safia.sh/captainsafia/grove/pr/${prNumber} | sh | |
| \`\`\` | |
| **Or if you already have grove installed:** | |
| \`\`\`bash | |
| grove self-update --pr ${prNumber} | |
| \`\`\` | |
| **Or download directly from [Actions Artifacts](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId})** | |
| Available binaries: | |
| - \`grove-linux-x64\` | |
| - \`grove-linux-arm64\` | |
| - \`grove-darwin-x64\` | |
| - \`grove-darwin-arm64\` | |
| - \`grove-windows-x64.exe\``; | |
| // Check if a comment already exists | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const botComment = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('Grove PR Build Ready') | |
| ); | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: body, | |
| }); | |
| } |