Build and Release PlayBuffer #162
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: Build and Release PlayBuffer | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| schedule: | |
| - cron: '0 0 * * *' # Run daily at midnight UTC to check for new PortAudio commits | |
| workflow_dispatch: # Allow manual trigger | |
| permissions: | |
| contents: write # allow creating releases and updating last_built.txt | |
| jobs: | |
| check-portaudio: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should-build: ${{ steps.check.outputs.should_build }} | |
| portaudio-commit: ${{ steps.check.outputs.portaudio_commit }} | |
| version: ${{ steps.check.outputs.version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Check for new PortAudio commit | |
| id: check | |
| run: | | |
| # Get latest PortAudio commit | |
| LATEST_COMMIT=$(git ls-remote https://github.com/PortAudio/portaudio.git HEAD | awk '{print $1}') | |
| SHORT_COMMIT=${LATEST_COMMIT:0:7} | |
| # Generate version tag with increment to avoid duplicates | |
| DATE_TAG=$(date +"%Y.%m.%d") | |
| BUILD_NUM=1 | |
| # Find the next available increment for today | |
| while true; do | |
| VERSION="v${DATE_TAG}-${SHORT_COMMIT}.${BUILD_NUM}" | |
| # Check if this tag already exists | |
| TAG_EXISTS=$(curl -s https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/$VERSION -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" | jq -r .tag_name) | |
| if [ "$TAG_EXISTS" = "$VERSION" ]; then | |
| BUILD_NUM=$((BUILD_NUM + 1)) | |
| else | |
| break | |
| fi | |
| done | |
| echo "portaudio_commit=$LATEST_COMMIT" >> $GITHUB_OUTPUT | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| # Check if we've already built this PortAudio commit | |
| if [ -f last_built.txt ]; then | |
| LAST_BUILT=$(cat last_built.txt | sed 's/PortAudio commit: //') | |
| if [ "$LATEST_COMMIT" = "$LAST_BUILT" ] && [ "${{ github.event_name }}" = "schedule" ]; then | |
| echo "should_build=false" >> $GITHUB_OUTPUT | |
| echo "No new PortAudio commits since last build ($SHORT_COMMIT)" | |
| else | |
| echo "should_build=true" >> $GITHUB_OUTPUT | |
| echo "Building PortAudio commit: $SHORT_COMMIT (version: $VERSION)" | |
| fi | |
| else | |
| echo "should_build=true" >> $GITHUB_OUTPUT | |
| echo "No previous build found, building PortAudio commit: $SHORT_COMMIT (version: $VERSION)" | |
| fi | |
| build: | |
| needs: check-portaudio | |
| if: needs.check-portaudio.outputs.should-build == 'true' || github.event_name != 'schedule' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cmake build-essential pkg-config libasound2-dev | |
| - name: Install dependencies (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| # Nothing to install - pkgconf and cmake are pre-installed on macOS runners | |
| - name: Install dependencies (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| # CMake is pre-installed on Windows runners | |
| shell: pwsh | |
| - name: Build PortAudio from latest source | |
| run: | | |
| # Clone latest PortAudio from master branch | |
| git clone --depth 1 --branch master https://github.com/PortAudio/portaudio.git | |
| cd portaudio | |
| mkdir build | |
| cd build | |
| if [ "${{ runner.os }}" = "Windows" ]; then | |
| cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install | |
| cmake --build . --config Release | |
| cmake --install . --config Release | |
| else | |
| cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install | |
| make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) | |
| make install | |
| fi | |
| shell: bash | |
| - name: Build PlayBuffer (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| echo "Building PlayBuffer on Ubuntu" | |
| export PKG_CONFIG_PATH="$PWD/portaudio/install/lib/pkgconfig:$PKG_CONFIG_PATH" | |
| export LD_LIBRARY_PATH="$PWD/portaudio/install/lib:$LD_LIBRARY_PATH" | |
| export PLAYBUFFER_VERSION="${{ needs.check-portaudio.outputs.version }}" | |
| export PORTAUDIO_COMMIT="${{ needs.check-portaudio.outputs.portaudio-commit }}" | |
| chmod +x scripts/build-ubuntu.sh | |
| ./scripts/build-ubuntu.sh | |
| - name: Build PlayBuffer (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| echo "Building PlayBuffer on macOS" | |
| export PKG_CONFIG_PATH="$PWD/portaudio/install/lib/pkgconfig:$PKG_CONFIG_PATH" | |
| export DYLD_LIBRARY_PATH="$PWD/portaudio/install/lib:$DYLD_LIBRARY_PATH" | |
| export PLAYBUFFER_VERSION="${{ needs.check-portaudio.outputs.version }}" | |
| export PORTAUDIO_COMMIT="${{ needs.check-portaudio.outputs.portaudio-commit }}" | |
| chmod +x scripts/build-macos.sh | |
| ./scripts/build-macos.sh | |
| - name: Build PlayBuffer (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| Write-Host "Building PlayBuffer on Windows" | |
| $env:CMAKE_PREFIX_PATH = "$PWD\portaudio\install" | |
| $env:PLAYBUFFER_VERSION = "${{ needs.check-portaudio.outputs.version }}" | |
| $env:PORTAUDIO_COMMIT = "${{ needs.check-portaudio.outputs.portaudio-commit }}" | |
| .\scripts\build-windows.ps1 | |
| shell: pwsh | |
| - name: Package artifacts (Ubuntu/macOS) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| mkdir -p artifacts | |
| if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then OS_NAME=linux; else OS_NAME=macos; fi | |
| # Copy the built executable | |
| if [ -f play_buffer ]; then | |
| cp play_buffer "artifacts/play_buffer_${OS_NAME}" | |
| echo "Packaged play_buffer_${OS_NAME}" | |
| elif [ -f build/play_buffer ]; then | |
| cp build/play_buffer "artifacts/play_buffer_${OS_NAME}" | |
| echo "Packaged play_buffer_${OS_NAME}" | |
| else | |
| echo "Warning: play_buffer executable not found" | |
| find . -name "play_buffer" -type f || echo "No play_buffer found" | |
| fi | |
| echo "Packaged files:" | |
| ls -la artifacts/ | |
| - name: Package artifacts (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| New-Item -ItemType Directory -Force -Path artifacts | Out-Null | |
| # Copy the built executable | |
| if (Test-Path "play_buffer.exe") { | |
| Copy-Item "play_buffer.exe" "artifacts\play_buffer_windows.exe" | |
| Write-Host "Packaged play_buffer_windows.exe" | |
| } elseif (Test-Path "build\play_buffer.exe") { | |
| Copy-Item "build\play_buffer.exe" "artifacts\play_buffer_windows.exe" | |
| Write-Host "Packaged play_buffer_windows.exe" | |
| } else { | |
| Write-Host "Warning: play_buffer.exe executable not found" | |
| Get-ChildItem -Recurse -Filter "play_buffer.exe" | Write-Host | |
| } | |
| Write-Host "Packaged files:" | |
| Get-ChildItem artifacts/ | |
| shell: pwsh | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playbuffer-${{ matrix.os }} | |
| path: artifacts/ | |
| release: | |
| needs: [check-portaudio, build] | |
| if: (needs.check-portaudio.outputs.should-build == 'true' || github.event_name != 'schedule') && github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts/ | |
| - name: List packaged artifacts | |
| run: | | |
| echo "Artifacts directory contents before release:" | |
| if [ -d artifacts/ ]; then | |
| ls -la artifacts/ | |
| find artifacts/ -type f | |
| else | |
| echo "No artifacts directory found." | |
| fi | |
| - name: Add build metadata | |
| run: | | |
| mkdir -p artifacts | |
| echo "PlayBuffer build version: ${{ needs.check-portaudio.outputs.version }}" > artifacts/build-info.txt | |
| echo "GitHub run number: ${{ github.run_number }}" >> artifacts/build-info.txt | |
| echo "Repository: ${GITHUB_REPOSITORY}" >> artifacts/build-info.txt | |
| echo "Commit: $(git rev-parse HEAD)" >> artifacts/build-info.txt | |
| echo "PortAudio commit: ${{ needs.check-portaudio.outputs.portaudio-commit }}" >> artifacts/build-info.txt | |
| - name: Create release | |
| run: | | |
| if ls artifacts/*/* 1> /dev/null 2>&1; then | |
| COMMIT_SHA=$(git rev-parse HEAD) | |
| COMMIT_URL="https://github.com/${GITHUB_REPOSITORY}/commit/$COMMIT_SHA" | |
| PORTAUDIO_COMMIT="${{ needs.check-portaudio.outputs.portaudio-commit }}" | |
| PORTAUDIO_SHORT="${PORTAUDIO_COMMIT:0:7}" | |
| # Link to the specific Actions run for traceability | |
| RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }}" | |
| # Build markdown notes where the run number text is a clickable link | |
| NOTES=$'Automated build of PlayBuffer with latest PortAudio\n\n' | |
| NOTES+=$'PortAudio commit: https://github.com/PortAudio/portaudio/commit/'$PORTAUDIO_COMMIT$'\n' | |
| NOTES+=$'PlayBuffer commit: '$COMMIT_URL$'\n' | |
| NOTES+=$'GitHub Actions run: ['"#${{ github.run_number }}"']('$RUN_URL$')\n' | |
| gh release create ${{ needs.check-portaudio.outputs.version }} \ | |
| --title "PlayBuffer ${{ needs.check-portaudio.outputs.version }}" \ | |
| --notes "$NOTES" | |
| else | |
| echo "No artifacts found to upload. Skipping release." | |
| exit 0 | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload release assets | |
| run: | | |
| # Upload any artifact files and the build-info file | |
| for file in artifacts/*/* artifacts/*; do | |
| if [ -f "$file" ]; then | |
| gh release upload ${{ needs.check-portaudio.outputs.version }} "$file" || echo "Failed to upload $file" | |
| fi | |
| done | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Update last built commit | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| PORTAUDIO_COMMIT="${{ needs.check-portaudio.outputs.portaudio-commit }}" | |
| echo "PortAudio commit: $PORTAUDIO_COMMIT" > last_built.txt | |
| # Only commit if there are changes | |
| if git diff --quiet last_built.txt; then | |
| echo "No changes to last_built.txt - already up to date" | |
| else | |
| git add last_built.txt | |
| git commit -m "Update last built PortAudio commit to $PORTAUDIO_COMMIT" | |
| git push | |
| echo "Updated last_built.txt with commit: $PORTAUDIO_COMMIT" | |
| fi |