1- name : Homebrew Formula Test
1+ name : Homebrew
22
33on :
44 push :
55 branches :
66 - master
7- - homebrew-formula
8- paths :
9- - ' packaging/homebrew/**'
10- - ' .github/workflows/homebrew.yml'
117 pull_request :
128 branches :
139 - master
14- paths :
15- - ' packaging/homebrew/**'
16- - ' .github/workflows/homebrew.yml'
1710 workflow_dispatch :
1811
1912jobs :
20- # Fast smoke tests that run before expensive operations
21- smoke-test :
22- name : Quick Formula Validation
23- runs-on : ubuntu-latest # Use Linux for speed (Homebrew works on Linux too)
24-
13+ homebrew-mfc :
14+ name : Test Homebrew package (macOS)
15+ runs-on : macos-latest
16+
2517 steps :
26- - name : Checkout repository
18+ - name : Checkout repo
2719 uses : actions/checkout@v4
28-
20+
2921 - name : Set up Homebrew
3022 uses : Homebrew/actions/setup-homebrew@master
31-
32- - name : Validate formula syntax with brew style
33- run : |
34- echo "Checking formula syntax..."
35- brew style packaging/homebrew/mfc.rb
36-
37- - name : Run brew audit (without installation)
38- run : |
39- echo "Configuring git for brew tap-new..."
40- git config --global user.email "github-actions[bot]@users.noreply.github.com"
41- git config --global user.name "github-actions[bot]"
42-
43- echo "Creating temporary local tap..."
44- brew tap-new mflowcode/test
45- cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb
46-
47- echo "Running brew audit (online checks)..."
48- brew audit --online --skip-style mflowcode/test/mfc || true
49-
50- echo "Cleaning up tap..."
51- brew untap mflowcode/test
52-
53- - name : Validate Ruby syntax
54- run : |
55- echo "Checking Ruby syntax..."
56- ruby -c packaging/homebrew/mfc.rb
57-
58- - name : Check for common formula issues
59- run : |
60- echo "Checking for common issues..."
61-
62- # Check that required fields are present
63- grep -q 'desc "' packaging/homebrew/mfc.rb || (echo "❌ Missing desc"; exit 1)
64- grep -q 'homepage "' packaging/homebrew/mfc.rb || (echo "❌ Missing homepage"; exit 1)
65- grep -q 'url "' packaging/homebrew/mfc.rb || (echo "❌ Missing url"; exit 1)
66- grep -q 'sha256 "' packaging/homebrew/mfc.rb || (echo "❌ Missing sha256"; exit 1)
67- grep -q 'license "' packaging/homebrew/mfc.rb || (echo "❌ Missing license"; exit 1)
68-
69- # Check that install method exists
70- grep -q 'def install' packaging/homebrew/mfc.rb || (echo "❌ Missing install method"; exit 1)
71-
72- # Check that test block exists
73- grep -q 'test do' packaging/homebrew/mfc.rb || (echo "❌ Missing test block"; exit 1)
74-
75- echo "✅ All required formula components present"
76-
77- - name : Verify URL is reachable
78- run : |
79- echo "Checking that source URL is reachable..."
80- URL=$(grep -E 'url "https://[^"]+' packaging/homebrew/mfc.rb | head -1 | sed 's/.*url "\([^"]*\)".*/\1/')
81-
82- if [ -z "$URL" ]; then
83- echo "❌ Could not extract URL from formula"
84- exit 1
85- fi
86-
87- echo "URL: $URL"
88- HTTP_CODE=$(curl -sI -w "%{http_code}" -o /dev/null "$URL")
89-
90- if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
91- echo "✅ URL is reachable (HTTP $HTTP_CODE)"
92- else
93- echo "⚠️ URL returned HTTP $HTTP_CODE (may indicate an issue)"
94- # Don't fail here - could be a temporary issue
95- fi
96-
97- - name : Verify SHA256 checksum
98- run : |
99- echo "Verifying SHA256 checksum matches URL..."
100- URL=$(grep -E 'url "https://[^"]+' packaging/homebrew/mfc.rb | head -1 | sed 's/.*url "\([^"]*\)".*/\1/')
101- EXPECTED_SHA=$(grep 'sha256 "' packaging/homebrew/mfc.rb | head -1 | sed 's/.*sha256 "\([^"]*\)".*/\1/')
102-
103- if [ -z "$URL" ] || [ -z "$EXPECTED_SHA" ]; then
104- echo "❌ Could not extract URL or SHA256 from formula"
105- exit 1
106- fi
107-
108- echo "Downloading tarball to compute checksum..."
109- ACTUAL_SHA=$(curl -sL "$URL" | shasum -a 256 | awk '{print $1}')
110-
111- echo "Expected SHA256: $EXPECTED_SHA"
112- echo "Actual SHA256: $ACTUAL_SHA"
113-
114- if [ "$EXPECTED_SHA" = "$ACTUAL_SHA" ]; then
115- echo "✅ SHA256 checksum matches!"
116- else
117- echo "❌ SHA256 mismatch!"
118- exit 1
119- fi
12023
121- # Full installation test (only runs if smoke tests pass)
122- test-formula :
123- name : Full Installation Test
124- needs : smoke-test # Only run after smoke tests pass
125- runs-on : macos-latest
126-
127- steps :
128- - name : Checkout repository
129- uses : actions/checkout@v4
130-
131- - name : Set up Homebrew
132- run : |
133- echo "Homebrew version:"
134- brew --version
135- echo "Updating Homebrew..."
136- brew update
137-
138- - name : Install formula dependencies
139- run : |
140- echo "Installing MFC dependencies..."
141- brew install cmake gcc [email protected] boost fftw hdf5 open-mpi openblas 142-
143- - name : Install MFC from formula
144- run : |
145- echo "Creating temporary local tap..."
146- brew tap-new mflowcode/test
147-
148- echo "Copying formula to tap..."
149- cp packaging/homebrew/mfc.rb $(brew --repository)/Library/Taps/mflowcode/homebrew-test/Formula/mfc.rb
150-
151- echo "Installing MFC from local tap..."
152- # Note: brew may exit with code 1 due to dylib fixup warnings on some Python packages (non-fatal)
153- # We verify installation using brew commands rather than parsing log output
154- set +e # Don't fail immediately on error
155- brew install --build-from-source --verbose mflowcode/test/mfc 2>&1 | tee /tmp/brew-install.log
156- brew_exit_code=$?
157- set -e
158-
159- # Verify installation using brew list (more robust than log parsing)
160- if brew list mflowcode/test/mfc &>/dev/null; then
161- echo "✅ MFC installed successfully (ignoring dylib relocation warnings)"
162- # Optionally verify with brew info
163- brew info mflowcode/test/mfc
164- exit 0
165- else
166- echo "❌ MFC installation failed"
167- exit $brew_exit_code
168- fi
169-
170- - name : Display error logs on failure
171- if : failure()
24+ - name : Install MFC via Homebrew
17225 run : |
173- echo "=== Displaying last 200 lines of brew install log ==="
174- if [ -f /tmp/brew-install.log ]; then
175- tail -200 /tmp/brew-install.log
176- fi
177-
178- echo -e "\n=== Displaying Homebrew log files ==="
179- if [ -d ~/Library/Logs/Homebrew/mfc/ ]; then
180- for logfile in ~/Library/Logs/Homebrew/mfc/*; do
181- if [ -f "$logfile" ]; then
182- echo -e "\n\n====== $logfile ======"
183- cat "$logfile"
184- fi
185- done
186- fi
187-
188- echo -e "\n=== Searching for Cantera config.log ==="
189- cantera_config_log=$(find /private/tmp -name "config.log" -path "*/mfc--cantera*" 2>/dev/null | head -1)
190- if [ -n "$cantera_config_log" ] && [ -f "$cantera_config_log" ]; then
191- echo -e "\n\n====== Cantera config.log ======"
192- echo "Found at: $cantera_config_log"
193- cat "$cantera_config_log"
194- # Copy to a known location for artifact upload
195- mkdir -p /tmp/cantera-logs
196- cp "$cantera_config_log" /tmp/cantera-logs/config.log
197- else
198- echo "Cantera config.log not found"
199- echo "Searching in all /private/tmp directories:"
200- find /private/tmp -name "config.log" 2>/dev/null || echo "No config.log files found"
201- fi
202-
203- - name : Upload Homebrew logs on failure
204- if : failure()
205- uses : actions/upload-artifact@v4
206- with :
207- name : homebrew-logs
208- path : |
209- /tmp/brew-install.log
210- /tmp/cantera-logs/
211- ~/Library/Logs/Homebrew/mfc/
212- if-no-files-found : ignore
213-
214- - name : Test MFC installation
215- run : |
216- echo "=== Testing MFC Installation ==="
217-
218- echo "1. Checking binaries exist and are executable..."
219- test -f $(brew --prefix)/bin/mfc && test -x $(brew --prefix)/bin/mfc
220- test -f $(brew --prefix)/bin/pre_process && test -x $(brew --prefix)/bin/pre_process
221- test -f $(brew --prefix)/bin/simulation && test -x $(brew --prefix)/bin/simulation
222- test -f $(brew --prefix)/bin/post_process && test -x $(brew --prefix)/bin/post_process
223- echo " ✓ All binaries exist and are executable"
224-
225- echo "2. Verifying installation structure..."
226- test -f $(brew --prefix mfc)/libexec/mfc.sh
227- test -d $(brew --prefix mfc)/toolchain
228- echo " ✓ Installation structure verified"
229-
230- echo "3. Checking Python venv..."
231- test -d $(brew --prefix mfc)/libexec/venv
232- test -f $(brew --prefix mfc)/libexec/venv/bin/python
233- test -f $(brew --prefix mfc)/libexec/venv/bin/pip
234- echo " ✓ Python venv exists"
235-
236- echo "4. Checking examples..."
237- test -d $(brew --prefix mfc)/examples
238- test -f $(brew --prefix mfc)/examples/1D_sodshocktube/case.py
239- echo " ✓ Examples installed"
240-
241- echo "5. Testing mfc wrapper..."
242- mfc --help
243- echo " ✓ mfc --help succeeded"
244-
245- echo "=== All tests passed! ==="
246-
26+ set -euo pipefail
27+ # Prefer bottle; fall back to source build if needed
28+ brew install mflowcode/mfc/mfc || brew install --build-from-source mflowcode/mfc/mfc
29+
24730 - name : Run MFC test case
24831 run : |
32+ set -euo pipefail
24933 echo "Running a simple test case (1D Sod shock tube)..."
25034 TESTDIR=$(mktemp -d)
251- cp $(brew --prefix mfc)/examples/1D_sodshocktube/case.py "$TESTDIR/"
252-
35+ cp " $(brew --prefix mfc)/examples/1D_sodshocktube/case.py" "$TESTDIR/"
36+
25337 echo "Running with $(sysctl -n hw.ncpu) processors..."
254- # Use absolute path and shorthand syntax (mfc auto-detects and prepends 'run')
255- mfc "$TESTDIR/case.py" -j $(sysctl -n hw.ncpu)
256-
257- echo "Test case completed successfully!"
258-
259- - name : Uninstall and cleanup
260- if : always()
38+ mfc "$TESTDIR/case.py" -j "$(sysctl -n hw.ncpu)"
39+
40+ test -d "$TESTDIR/silo_hdf5"
41+ echo "✅ Test case completed successfully and produced output"
42+
43+ - name : Basic installation verification
26144 run : |
262- echo "Cleaning up..."
263- brew uninstall mfc || true
264- brew cleanup
45+ set -euo pipefail
46+ echo "1. Checking binaries..."
47+ test -x "$(brew --prefix mfc)/bin/pre_process"
48+ test -x "$(brew --prefix mfc)/bin/simulation"
49+ test -x "$(brew --prefix mfc)/bin/post_process"
50+ test -x "$(brew --prefix mfc)/bin/mfc"
51+
52+ echo "2. Checking toolchain..."
53+ test -d "$(brew --prefix mfc)/toolchain"
54+
55+ echo "3. Checking Python venv..."
56+ test -d "$(brew --prefix mfc)/libexec/venv"
57+ test -x "$(brew --prefix mfc)/libexec/venv/bin/python"
58+
59+ echo "4. Checking examples..."
60+ test -d "$(brew --prefix mfc)/examples"
61+
62+ echo "5. Testing mfc command..."
63+ mfc --help
64+
65+ echo "✅ All verification checks passed"
0 commit comments