Skip to content

Build and Release PlayBuffer #141

Build and Release PlayBuffer

Build and Release PlayBuffer #141

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