Merge pull request #36 from sqlrsync/v0.0.10 #113
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: Multi-Platform Build | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - beta | |
| pull_request: | |
| branches: | |
| - main | |
| - beta | |
| - "v*" | |
| release: | |
| types: [published] | |
| jobs: | |
| securityIntention: | |
| name: Security Intention | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Security Intention | |
| run: | | |
| echo "This workflow is intended to build the project in a secure manner:" | |
| echo " - Only installs absolutely essential and trusted dependencies. (steps \"Install *\")" | |
| echo " - Uses HTTPS for direct package downloads" | |
| echo " - Only uses official Github Actions \"actions/*\"" | |
| build: | |
| name: Build for ${{ matrix.os }}-${{matrix.arch}} | |
| runs-on: ${{ matrix.runs-on }} | |
| strategy: | |
| matrix: | |
| include: | |
| - os: darwin | |
| runs-on: macos-latest | |
| arch: arm64 | |
| - os: darwin | |
| runs-on: macos-latest | |
| arch: x86_64 | |
| - os: linux | |
| runs-on: ubuntu-latest | |
| arch: x86_64 | |
| - os: linux-musl | |
| runs-on: ubuntu-latest | |
| arch: x86_64 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: "1.21" | |
| cache: false | |
| - name: Install dependencies (Ubuntu) | |
| if: matrix.os == 'linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y sqlite3 libsqlite3-dev build-essential | |
| - name: Install dependencies (Alpine/musl) | |
| if: matrix.os == 'linux-musl' | |
| run: | | |
| # Use Alpine container for musl builds | |
| docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace alpine:latest sh -c " | |
| apk add --no-cache build-base sqlite-dev go curl git && | |
| echo 'Alpine dependencies installed' | |
| " | |
| - name: Install dependencies (macOS) | |
| if: matrix.os == 'darwin' | |
| run: | | |
| brew install sqlite3 | |
| - name: Install dependencies (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| choco install sqlite | |
| - name: Build SQLite (Unix) | |
| if: matrix.os != 'windows' && matrix.os != 'linux-musl' | |
| run: | | |
| cd sqlite | |
| if [ ! -d "sqlite-latest" ]; then | |
| # Download and extract SQLite source if not present | |
| curl -O https://www.sqlite.org/2024/sqlite-autoconf-3450100.tar.gz | |
| tar xzf sqlite-autoconf-3450100.tar.gz | |
| mv sqlite-autoconf-3450100 sqlite-latest | |
| fi | |
| cd sqlite-latest | |
| ./configure --prefix=$(pwd)/../install --enable-static --disable-shared "CFLAGS=-DSQLITE_ENABLE_DBPAGE_VTAB=1 -O2" | |
| make | |
| make install | |
| - name: Build SQLite (Alpine/musl) | |
| if: matrix.os == 'linux-musl' | |
| run: | | |
| # Build SQLite in Alpine container for musl compatibility | |
| docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace alpine:latest sh -c " | |
| apk add --no-cache build-base curl && | |
| cd sqlite && | |
| if [ ! -d 'sqlite-latest' ]; then | |
| curl -O https://www.sqlite.org/2024/sqlite-autoconf-3450100.tar.gz | |
| tar xzf sqlite-autoconf-3450100.tar.gz | |
| mv sqlite-autoconf-3450100 sqlite-latest | |
| fi && | |
| cd sqlite-latest && | |
| ./configure --prefix=\$(pwd)/../install --enable-static --disable-shared 'CFLAGS=-DSQLITE_ENABLE_DBPAGE_VTAB=1 -O2' && | |
| make && | |
| make install | |
| " | |
| - name: Build SQLite (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| cd sqlite | |
| if (!(Test-Path "sqlite-latest")) { | |
| Invoke-WebRequest -Uri "https://www.sqlite.org/2024/sqlite-autoconf-3450100.tar.gz" -OutFile "sqlite-autoconf-3450100.tar.gz" | |
| tar -xzf sqlite-autoconf-3450100.tar.gz | |
| Rename-Item sqlite-autoconf-3450100 sqlite-latest | |
| } | |
| cd sqlite-latest | |
| # Use MSYS2/MinGW for Windows build | |
| bash -c "./configure --prefix=$(pwd)/../install --enable-static --disable-shared 'CFLAGS=-DSQLITE_ENABLE_DBPAGE_VTAB=1 -O2'" | |
| bash -c "make" | |
| bash -c "make install" | |
| - name: Build Bridge | |
| if: matrix.os != 'linux-musl' | |
| run: | | |
| cd bridge | |
| make | |
| - name: Build Bridge (Alpine/musl) | |
| if: matrix.os == 'linux-musl' | |
| run: | | |
| # Build bridge in Alpine container | |
| docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace alpine:latest sh -c " | |
| apk add --no-cache build-base go && | |
| cd bridge && | |
| make | |
| " | |
| - name: Set build environment (Darwin ARM64) | |
| if: matrix.os == 'darwin' && matrix.arch == 'arm64' | |
| run: | | |
| echo "GOOS=darwin" >> $GITHUB_ENV | |
| echo "GOARCH=arm64" >> $GITHUB_ENV | |
| echo "CGO_ENABLED=1" >> $GITHUB_ENV | |
| - name: Set build environment (Darwin AMD64) | |
| if: matrix.os == 'darwin' && matrix.arch == 'amd64' | |
| run: | | |
| echo "GOOS=darwin" >> $GITHUB_ENV | |
| echo "GOARCH=amd64" >> $GITHUB_ENV | |
| echo "CGO_ENABLED=1" >> $GITHUB_ENV | |
| - name: Set build environment (Linux x86_64) | |
| if: matrix.os == 'linux' && matrix.arch == 'x86_64' | |
| run: | | |
| echo "GOOS=linux" >> $GITHUB_ENV | |
| echo "GOARCH=amd64" >> $GITHUB_ENV | |
| echo "CGO_ENABLED=1" >> $GITHUB_ENV | |
| - name: Set build environment (Linux musl x86_64) | |
| if: matrix.os == 'linux-musl' && matrix.arch == 'x86_64' | |
| run: | | |
| echo "GOOS=linux" >> $GITHUB_ENV | |
| echo "GOARCH=amd64" >> $GITHUB_ENV | |
| echo "CGO_ENABLED=1" >> $GITHUB_ENV | |
| - name: Set build environment (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| echo "GOOS=windows" >> $env:GITHUB_ENV | |
| echo "GOARCH=amd64" >> $env:GITHUB_ENV | |
| echo "CGO_ENABLED=1" >> $env:GITHUB_ENV | |
| - name: Build Client (Unix) | |
| if: matrix.os != 'windows' && matrix.os != 'linux-musl' | |
| run: | | |
| cd client | |
| make build | |
| - name: Build Client (Alpine/musl) | |
| if: matrix.os == 'linux-musl' | |
| run: | | |
| # Build client in Alpine container | |
| docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace alpine:latest sh -c " | |
| apk add --no-cache zlib-dev build-base go git && | |
| git config --global --add safe.directory /workspace && | |
| cd client && | |
| make build | |
| " | |
| # Verify binary was created | |
| if [ ! -f ./client/bin/sqlrsync ]; then | |
| echo "ERROR: Binary not found at ./client/bin/sqlrsync" | |
| exit 1 | |
| fi | |
| echo "✓ Binary built successfully at ./client/bin/sqlrsync" | |
| file ./client/bin/sqlrsync | |
| - name: Docker based test (Alpine/musl) | |
| if: matrix.os == 'linux-musl' | |
| run: | | |
| docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace alpine:latest sh -c " | |
| ldd ./client/bin/sqlrsync && | |
| ./client/bin/sqlrsync --version && | |
| ./client/bin/sqlrsync usgs.gov/earthquakes.db | |
| " | |
| - name: Build Client (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| cd client | |
| # Use make with MSYS2/MinGW | |
| bash -c "make build" | |
| - name: Test sqlrsync --version | |
| if: matrix.os != 'linux-musl' | |
| run: | | |
| echo "Testing sqlrsync --version..." | |
| ./client/bin/sqlrsync --version | |
| - name: Test sqlrsync help | |
| if: matrix.os != 'linux-musl' | |
| run: | | |
| echo "Testing sqlrsync help..." | |
| ./client/bin/sqlrsync || true | |
| - name: Test sqlrsync with usgs.gov/earthquakes.db | |
| if: matrix.os != 'linux-musl' | |
| run: | | |
| echo "Testing sqlrsync usgs.gov/earthquakes.db..." | |
| ./client/bin/sqlrsync usgs.gov/earthquakes.db | |
| - name: Test sqlrsync with subscribe for 10 seconds (Linux) | |
| if: matrix.os == 'linux' | |
| run: | | |
| echo "Testing sqlrsync usgs.gov/earthquakes.db --subscribe for 10 seconds..." | |
| timeout 10s ./client/bin/sqlrsync usgs.gov/earthquakes.db --subscribe > subscribe_output.log 2>&1 || true | |
| - name: Test sqlrsync with subscribe for 10 seconds (macOS) | |
| if: matrix.os == 'darwin' | |
| run: | | |
| echo "Testing sqlrsync usgs.gov/earthquakes.db --subscribe for 10 seconds..." | |
| # macOS doesn't have timeout, use gtimeout or alternative | |
| if command -v gtimeout &> /dev/null; then | |
| gtimeout 10s ./client/bin/sqlrsync usgs.gov/earthquakes.db --subscribe > subscribe_output.log 2>&1 || true | |
| else | |
| # Fallback: run in background and kill after 10 seconds | |
| ./client/bin/sqlrsync usgs.gov/earthquakes.db --subscribe > subscribe_output.log 2>&1 & | |
| PID=$! | |
| sleep 10 | |
| kill $PID 2>/dev/null || true | |
| wait $PID 2>/dev/null || true | |
| fi | |
| - name: Test sqlrsync with subscribe for 10 seconds (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| echo "Testing sqlrsync usgs.gov/earthquakes.db --subscribe for 10 seconds..." | |
| # Windows doesn't have timeout, use PowerShell equivalent | |
| $job = Start-Job { ./client/bin/sqlrsync.exe usgs.gov/earthquakes.db --subscribe } | |
| Wait-Job $job -Timeout 10 | |
| Stop-Job $job | |
| Receive-Job $job > subscribe_output.log 2>&1 || $true | |
| - name: Verify subscribe output (Unix) | |
| if: matrix.os != 'windows' && matrix.os != 'linux-musl' | |
| run: | | |
| echo "Checking for 'Sync complete' in output..." | |
| cat subscribe_output.log | |
| if grep -q "Sync complete" subscribe_output.log; then | |
| echo "✅ SUCCESS: Found 'Sync complete' in output" | |
| else | |
| echo "❌ FAILURE: 'Sync complete' not found in output" | |
| echo "Full output:" | |
| cat subscribe_output.log | |
| exit 1 | |
| fi | |
| - name: Create release directory | |
| run: | | |
| mkdir -p release | |
| - name: Package binary (Unix) | |
| if: matrix.os != 'windows' | |
| run: | | |
| if [ "${{ matrix.os }}" = "darwin" ] && [ "${{ matrix.arch }}" = "arm64" ]; then | |
| BINARY_NAME="sqlrsync-${{ matrix.os }}-${{ matrix.arch }}" | |
| else | |
| BINARY_NAME="sqlrsync-${{ matrix.os }}-${{ matrix.arch }}" | |
| fi | |
| cp client/bin/sqlrsync release/${BINARY_NAME} | |
| - name: Package binary (Windows) | |
| if: matrix.os == 'windows' | |
| run: | | |
| $BINARY_NAME = "sqlrsync-${{ matrix.os }}-${{ matrix.arch }}.exe" | |
| Copy-Item "client/bin/sqlrsync.exe" "release/$BINARY_NAME" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sqlrsync-${{ matrix.os }}-${{ matrix.arch }} | |
| path: release/* | |
| release: | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| needs: build | |
| permissions: | |
| contents: write | |
| packages: write | |
| issues: write | |
| pull-requests: write | |
| actions: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Extract version from main.go | |
| id: extract-version | |
| run: | | |
| VERSION=$(grep 'var VERSION = ' client/main.go | sed 's/var VERSION = "\(.*\)"/\1/') | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Extracted version: $VERSION" | |
| - name: Check if tag exists | |
| id: tag-check | |
| run: | | |
| VERSION=${{ steps.extract-version.outputs.version }} | |
| if git rev-parse "v$VERSION" >/dev/null 2>&1; then | |
| echo "Tag v$VERSION already exists" | |
| echo "tag-created=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "Tag v$VERSION does not exist, will create" | |
| echo "tag-created=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Download all release artifacts | |
| if: steps.tag-check.outputs.tag-created == 'true' | |
| uses: actions/download-artifact@v5 | |
| - name: Create tag and GitHub Release, attach artifact | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| TAG=v${{ steps.extract-version.outputs.version }} | |
| git config user.name "${{ github.actor }}" | |
| git config user.email "${{ github.actor }}@users.noreply.github.com" | |
| git tag -a $TAG -m "Release $TAG" | |
| git push origin $TAG | |
| # create the release and attach the artifact (gh CLI) | |
| gh release create $TAG --generate-notes sqlrsync-*/sqlrsync-* |