Homebrew formula #117
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: Homebrew Formula Test | |
| on: | |
| push: | |
| branches: | |
| - master | |
| - homebrew-formula | |
| paths: | |
| - 'packaging/homebrew/**' | |
| - '.github/workflows/homebrew.yml' | |
| pull_request: | |
| branches: | |
| - master | |
| paths: | |
| - 'packaging/homebrew/**' | |
| - '.github/workflows/homebrew.yml' | |
| workflow_dispatch: | |
| jobs: | |
| # Fast smoke tests that run before expensive operations | |
| smoke-test: | |
| name: Quick Formula Validation | |
| runs-on: ubuntu-latest # Use Linux for speed (Homebrew works on Linux too) | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Homebrew | |
| uses: Homebrew/actions/setup-homebrew@master | |
| - name: Validate formula syntax with brew style | |
| run: | | |
| echo "Checking formula syntax..." | |
| brew style packaging/homebrew/mfc.rb | |
| - name: Run brew audit (without installation) | |
| run: | | |
| echo "Configuring git for brew tap-new..." | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| echo "Creating temporary local tap..." | |
| brew tap-new mflowcode/test | |
| cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb | |
| echo "Running brew audit (online checks)..." | |
| brew audit --online --skip-style mflowcode/test/mfc || true | |
| echo "Cleaning up tap..." | |
| brew untap mflowcode/test | |
| - name: Validate Ruby syntax | |
| run: | | |
| echo "Checking Ruby syntax..." | |
| ruby -c packaging/homebrew/mfc.rb | |
| - name: Check for common formula issues | |
| run: | | |
| echo "Checking for common issues..." | |
| # Check that required fields are present | |
| grep -q 'desc "' packaging/homebrew/mfc.rb || (echo "❌ Missing desc"; exit 1) | |
| grep -q 'homepage "' packaging/homebrew/mfc.rb || (echo "❌ Missing homepage"; exit 1) | |
| grep -q 'url "' packaging/homebrew/mfc.rb || (echo "❌ Missing url"; exit 1) | |
| grep -q 'sha256 "' packaging/homebrew/mfc.rb || (echo "❌ Missing sha256"; exit 1) | |
| grep -q 'license "' packaging/homebrew/mfc.rb || (echo "❌ Missing license"; exit 1) | |
| # Check that install method exists | |
| grep -q 'def install' packaging/homebrew/mfc.rb || (echo "❌ Missing install method"; exit 1) | |
| # Check that test block exists | |
| grep -q 'test do' packaging/homebrew/mfc.rb || (echo "❌ Missing test block"; exit 1) | |
| echo "✅ All required formula components present" | |
| - name: Verify URL is reachable | |
| run: | | |
| echo "Checking that source URL is reachable..." | |
| URL=$(grep -E 'url "https://[^"]+' packaging/homebrew/mfc.rb | head -1 | sed 's/.*url "\([^"]*\)".*/\1/') | |
| if [ -z "$URL" ]; then | |
| echo "❌ Could not extract URL from formula" | |
| exit 1 | |
| fi | |
| echo "URL: $URL" | |
| HTTP_CODE=$(curl -sI -w "%{http_code}" -o /dev/null "$URL") | |
| if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then | |
| echo "✅ URL is reachable (HTTP $HTTP_CODE)" | |
| else | |
| echo "⚠️ URL returned HTTP $HTTP_CODE (may indicate an issue)" | |
| # Don't fail here - could be a temporary issue | |
| fi | |
| - name: Verify SHA256 checksum | |
| run: | | |
| echo "Verifying SHA256 checksum matches URL..." | |
| URL=$(grep -E 'url "https://[^"]+' packaging/homebrew/mfc.rb | head -1 | sed 's/.*url "\([^"]*\)".*/\1/') | |
| EXPECTED_SHA=$(grep 'sha256 "' packaging/homebrew/mfc.rb | head -1 | sed 's/.*sha256 "\([^"]*\)".*/\1/') | |
| if [ -z "$URL" ] || [ -z "$EXPECTED_SHA" ]; then | |
| echo "❌ Could not extract URL or SHA256 from formula" | |
| exit 1 | |
| fi | |
| echo "Downloading tarball to compute checksum..." | |
| ACTUAL_SHA=$(curl -sL "$URL" | shasum -a 256 | awk '{print $1}') | |
| echo "Expected SHA256: $EXPECTED_SHA" | |
| echo "Actual SHA256: $ACTUAL_SHA" | |
| if [ "$EXPECTED_SHA" = "$ACTUAL_SHA" ]; then | |
| echo "✅ SHA256 checksum matches!" | |
| else | |
| echo "❌ SHA256 mismatch!" | |
| exit 1 | |
| fi | |
| # Full installation test (only runs if smoke tests pass) | |
| test-formula: | |
| name: Full Installation Test | |
| needs: smoke-test # Only run after smoke tests pass | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Homebrew | |
| run: | | |
| echo "Homebrew version:" | |
| brew --version | |
| echo "Updating Homebrew..." | |
| brew update | |
| - name: Install formula dependencies | |
| run: | | |
| echo "Installing MFC dependencies..." | |
| brew install cmake gcc [email protected] boost fftw hdf5 open-mpi openblas | |
| - name: Install MFC from formula | |
| run: | | |
| echo "Creating temporary local tap..." | |
| brew tap-new mflowcode/test | |
| echo "Copying formula to tap..." | |
| cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb | |
| echo "Installing MFC from local tap..." | |
| # Note: brew may exit with code 1 due to dylib fixup warnings on some Python packages (non-fatal) | |
| # We verify installation using brew commands rather than parsing log output | |
| set +e # Don't fail immediately on error | |
| brew install --build-from-source --verbose mflowcode/test/mfc 2>&1 | tee /tmp/brew-install.log | |
| brew_exit_code=$? | |
| set -e | |
| # Verify installation using brew list (more robust than log parsing) | |
| if brew list mflowcode/test/mfc &>/dev/null; then | |
| echo "✅ MFC installed successfully (ignoring dylib relocation warnings)" | |
| # Optionally verify with brew info | |
| brew info mflowcode/test/mfc | |
| exit 0 | |
| else | |
| echo "❌ MFC installation failed" | |
| exit $brew_exit_code | |
| fi | |
| - name: Display error logs on failure | |
| if: failure() | |
| run: | | |
| echo "=== Displaying last 200 lines of brew install log ===" | |
| if [ -f /tmp/brew-install.log ]; then | |
| tail -200 /tmp/brew-install.log | |
| fi | |
| echo -e "\n=== Displaying Homebrew log files ===" | |
| if [ -d ~/Library/Logs/Homebrew/mfc/ ]; then | |
| for logfile in ~/Library/Logs/Homebrew/mfc/*; do | |
| if [ -f "$logfile" ]; then | |
| echo -e "\n\n====== $logfile ======" | |
| cat "$logfile" | |
| fi | |
| done | |
| fi | |
| echo -e "\n=== Searching for Cantera config.log ===" | |
| cantera_config_log=$(find /private/tmp -name "config.log" -path "*/mfc--cantera*" 2>/dev/null | head -1) | |
| if [ -n "$cantera_config_log" ] && [ -f "$cantera_config_log" ]; then | |
| echo -e "\n\n====== Cantera config.log ======" | |
| echo "Found at: $cantera_config_log" | |
| cat "$cantera_config_log" | |
| # Copy to a known location for artifact upload | |
| mkdir -p /tmp/cantera-logs | |
| cp "$cantera_config_log" /tmp/cantera-logs/config.log | |
| else | |
| echo "Cantera config.log not found" | |
| echo "Searching in all /private/tmp directories:" | |
| find /private/tmp -name "config.log" 2>/dev/null || echo "No config.log files found" | |
| fi | |
| - name: Upload Homebrew logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: homebrew-logs | |
| path: | | |
| /tmp/brew-install.log | |
| /tmp/cantera-logs/ | |
| ~/Library/Logs/Homebrew/mfc/ | |
| if-no-files-found: ignore | |
| - name: Test MFC installation | |
| run: | | |
| echo "=== Testing MFC Installation ===" | |
| echo "1. Checking binaries exist and are executable..." | |
| test -f $(brew --prefix)/bin/mfc && test -x $(brew --prefix)/bin/mfc | |
| test -f $(brew --prefix)/bin/pre_process && test -x $(brew --prefix)/bin/pre_process | |
| test -f $(brew --prefix)/bin/simulation && test -x $(brew --prefix)/bin/simulation | |
| test -f $(brew --prefix)/bin/post_process && test -x $(brew --prefix)/bin/post_process | |
| echo " ✓ All binaries exist and are executable" | |
| echo "2. Verifying installation structure..." | |
| test -f $(brew --prefix mfc)/libexec/mfc.sh | |
| test -d $(brew --prefix mfc)/toolchain | |
| echo " ✓ Installation structure verified" | |
| echo "3. Checking Python venv..." | |
| test -d $(brew --prefix mfc)/libexec/venv | |
| test -f $(brew --prefix mfc)/libexec/venv/bin/python | |
| test -f $(brew --prefix mfc)/libexec/venv/bin/pip | |
| echo " ✓ Python venv exists" | |
| echo "4. Checking examples..." | |
| test -d $(brew --prefix mfc)/examples | |
| test -f $(brew --prefix mfc)/examples/1D_sodshocktube/case.py | |
| echo " ✓ Examples installed" | |
| echo "5. Testing mfc wrapper..." | |
| mfc --help | |
| echo " ✓ mfc --help succeeded" | |
| echo "=== All tests passed! ===" | |
| - name: Run MFC test case | |
| run: | | |
| echo "Running a simple test case (1D Sod shock tube)..." | |
| TESTDIR=$(mktemp -d) | |
| cp $(brew --prefix mfc)/examples/1D_sodshocktube/case.py "$TESTDIR/" | |
| echo "Running with $(sysctl -n hw.ncpu) processors..." | |
| # Use absolute path since mfc wrapper creates its own tmpdir | |
| mfc run "$TESTDIR/case.py" -j $(sysctl -n hw.ncpu) | |
| echo "Test case completed successfully!" | |
| - name: Uninstall and cleanup | |
| if: always() | |
| run: | | |
| echo "Cleaning up..." | |
| brew uninstall mfc || true | |
| brew cleanup |