Skip to content

Conversation

@sbryngelson
Copy link
Member

@sbryngelson sbryngelson commented Nov 4, 2025

User description

Homebrew formula


PR Type

Enhancement, Documentation


Description

  • Add Homebrew formula for macOS installation of MFC

  • Create comprehensive Homebrew documentation covering installation and usage

  • Organize packaging files into dedicated packaging/homebrew/ directory

  • Remove issue templates and consolidate to Homebrew-specific content


Diagram Walkthrough

flowchart LR
  A["Homebrew Formula<br/>mfc.rb"] -- "defines" --> B["Installation<br/>Process"]
  B -- "installs" --> C["Binaries<br/>pre_process, simulation,<br/>post_process"]
  B -- "installs" --> D["Wrapper Script<br/>mfc"]
  B -- "installs" --> E["Python Toolchain<br/>& Examples"]
  F["HOMEBREW.md<br/>Documentation"] -- "explains" --> B
  F -- "guides" --> G["Users"]
Loading

File Walkthrough

Relevant files
Enhancement
mfc.rb
Homebrew formula for MFC installation                                       

packaging/homebrew/mfc.rb

  • Defines Homebrew formula class for MFC with version 5.1.0
  • Specifies build dependencies (cmake, gcc, python@3.12) and runtime
    dependencies (boost, fftw, hdf5, open-mpi, openblas)
  • Implements install method that builds three binaries and creates
    wrapper script
  • Includes test suite verifying binary existence and wrapper
    functionality
  • Provides post-installation caveats with usage examples and
    documentation links
+82/-0   
Documentation
HOMEBREW.md
Complete Homebrew installation and usage guide                     

packaging/homebrew/HOMEBREW.md

  • Comprehensive documentation covering Homebrew formula structure and
    dependencies
  • Details build process, environment configuration, and wrapper script
    functionality
  • Explains installation methods (standard and development HEAD
    installations)
  • Documents testing procedures, post-installation setup, and usage
    examples
  • Covers distribution methods, platform support, versioning, and
    technical details
  • Highlights advantages over manual installation and maintenance
    requirements
+211/-0 
Miscellaneous
bug_report.md
Remove bug report issue template                                                 

.github/ISSUE_TEMPLATE/bug_report.md

  • Removed bug report issue template from repository
  • Consolidation of branch to focus solely on Homebrew packaging
+0/-30   

Note

Adds a Homebrew formula for MFC with a runtime wrapper, CI workflows to test and deploy/sync the tap, and comprehensive setup/deployment docs with minor config updates.

  • Homebrew/Packaging:
    • Add packaging/homebrew/mfc.rb formula (v5.1.0) with build deps, venv setup (Cantera 3.1.0), installs binaries, examples, toolchain, and an mfc wrapper script.
    • Include tests and caveats in formula.
  • CI/CD:
    • Add .github/workflows/deploy-tap.yml to audit/style, auto-bump URL/SHA on tags, and sync mfc.rb to MFlowCode/homebrew-mfc (with bootstrap logic).
    • Add .github/workflows/homebrew.yml to install deps, style-check, build from a local tap, validate install, run example case, and upload logs on failure.
  • Docs:
    • Add packaging/homebrew/HOMEBREW.md, SETUP_INSTRUCTIONS.md, TAP_REPO_SETUP.md, and DEPLOYMENT_CHECKLIST.md detailing install, usage, tap setup, and deployment flow.
  • Config:
    • Update .gitignore to ignore packaging/spack/spack-test and .spack.
    • Update .typos.toml dictionary (add Sur).

Written by Cursor Bugbot for commit ceee0ac. Configure here.

sbryngelson and others added 8 commits November 4, 2025 11:56
This commit adds package management infrastructure:

- Homebrew formula (mfc.rb) for macOS installation
- Spack package (package.py) for HPC environments
- Comprehensive documentation for package usage
- GitHub issue templates for better user support
- Star growth tracking and analytics

This enables easier installation and broader adoption of MFC.

Co-authored-by: AI Assistant <assistant@anthropic.com>
Replaced 5 separate documentation files with one comprehensive HOMEBREW.md that covers:
- Formula structure and dependencies
- Build process and installation
- Testing and validation
- Usage examples and post-installation
- Distribution methods
- Technical details and platform support
These files are general project status/summary documents, not specific
to the Homebrew formula. The homebrew-formula branch should only contain:
- mfc.rb (the formula)
- HOMEBREW.md (Homebrew-specific documentation)
Moved documentation updates to dedicated documentation-updates branch.
This branch now focuses solely on Homebrew packaging.
Organized Homebrew formula files into dedicated directory structure:
- mfc.rb -> packaging/homebrew/mfc.rb
- HOMEBREW.md -> packaging/homebrew/HOMEBREW.md

This matches the Spack organization and provides a unified packaging/
directory for all package management systems.
Synced README with documentation-updates branch which contains
the most current version from upstream/master.
Copilot AI review requested due to automatic review settings November 4, 2025 17:56
@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Nov 4, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Duplicate Code

The wrapper script is created twice in the install method. First, mfc.sh is installed as mfc at line 37, then immediately overwritten with a new bash script at lines 46-51. The first installation is redundant and should be removed.

# Install the mfc.sh wrapper
bin.install "mfc.sh" => "mfc"

# Install Python toolchain
prefix.install "toolchain"

# Install examples
pkgshare.install "examples"

# Create a simple wrapper that sets up the environment
(bin/"mfc").write <<~EOS
  #!/bin/bash
  export BOOST_INCLUDE="#{Formula["boost"].opt_include}"
  exec "#{prefix}/mfc.sh" "$@"
EOS
chmod 0755, bin/"mfc"
Possible Issue

The mfc wrapper script references #{prefix}/mfc.sh but mfc.sh is never installed to the prefix directory. Line 37 installs it to bin/mfc which gets overwritten. The script should either install mfc.sh to prefix or reference it from the source directory.

(bin/"mfc").write <<~EOS
  #!/bin/bash
  export BOOST_INCLUDE="#{Formula["boost"].opt_include}"
  exec "#{prefix}/mfc.sh" "$@"
Missing Tests

The test suite only verifies that binaries exist and that the wrapper accepts --help. It doesn't test actual functionality like running a simple example case or verifying that the installed binaries can execute successfully. Consider adding a basic functional test.

test do
  # Test that the binaries exist and run
  assert_predicate bin/"pre_process", :exist?
  assert_predicate bin/"simulation", :exist?
  assert_predicate bin/"post_process", :exist?

  # Test mfc wrapper
  system bin/"mfc", "--help"
end

Fixed three issues identified by AI PR reviewer:

1. **Duplicate Code**: Removed redundant mfc.sh installation that was
   immediately overwritten. Now mfc.sh is installed once to prefix.

2. **Path Reference**: Fixed wrapper script to correctly reference
   mfc.sh from prefix directory where it's actually installed.

3. **Enhanced Tests**: Added functional tests that verify:
   - Binaries can execute (test -h flag)
   - mfc.sh and toolchain are properly installed
   - All components are accessible

Changes ensure the formula works correctly and tests verify actual
functionality beyond just file existence.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Homebrew packaging support for MFC on macOS, enabling users to install MFC via brew install mfc. The changes include a Ruby formula file for Homebrew and comprehensive documentation.

  • Adds Homebrew formula (mfc.rb) defining dependencies, build process, and installation logic
  • Provides detailed documentation (HOMEBREW.md) explaining the formula structure and usage
  • Removes the old bug report issue template

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
packaging/homebrew/mfc.rb Homebrew formula that builds and installs MFC with all dependencies
packaging/homebrew/HOMEBREW.md Complete documentation for the Homebrew packaging system
.github/ISSUE_TEMPLATE/bug_report.md Removes outdated bug report template

Addressed three additional suggestions from AI PR reviewer:

1. **Use libexec for mfc.sh** (Importance: 9)
   - Changed from prefix.install to libexec.install for mfc.sh
   - Updated wrapper to reference #{libexec}/mfc.sh
   - Follows Homebrew best practices for executable scripts

2. **Remove hardcoded compiler variables** (Importance: 7)
   - Removed ENV["FC"], ENV["CC"], ENV["CXX"] settings
   - Removed ENV["BOOST_INCLUDE"] from build step
   - Let Homebrew's superenv handle compiler setup via gcc dependency
   - Kept BOOST_INCLUDE only in wrapper script where needed at runtime

3. **Enhanced functional testing** (Importance: 6)
   - Added full toolchain test: runs actual example case
   - Tests 'mfc run' with 1D_sodshocktube example
   - Verifies entire workflow works end-to-end
   - Updated assertions to check libexec/mfc.sh location

These changes make the formula more idiomatic and robust.
Fixed remaining issues identified by Copilot:

1. **Directory check issue** (Critical)
   - mfc.sh expects to be run from MFC's root (checks toolchain/util.sh)
   - Updated wrapper to 'cd' to installation prefix before exec
   - Added comment explaining why directory change is needed
   - This ensures mfc.sh finds toolchain/util.sh at runtime

2. **Hardcoded version in documentation** (Documentation)
   - Removed hardcoded '5.1.0' references from HOMEBREW.md
   - Changed to generic language: 'When a new MFC version is released'
   - Updated technical details to show example pattern: vVERSION
   - Prevents documentation from becoming outdated with each release

Issues 1 & 2 (duplicate code and path reference) were already fixed
in previous commits (now using libexec.install without duplication).

The wrapper now works correctly:
  cd #{prefix} && exec #{libexec}/mfc.sh

This allows mfc.sh to find its expected directory structure.
@sbryngelson
Copy link
Member Author

/improve

@sbryngelson sbryngelson requested a review from Copilot November 4, 2025 18:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Fixed two remaining issues from Copilot review:

1. **Document toolchain installation rationale**
   - Added detailed comment explaining why full toolchain is needed
   - Documents dependencies: util.sh, main.py, bootstrap/, templates/
   - Clarifies this is not unnecessary bloat but required functionality

2. **Add syntax highlighting to code blocks**
   - Added 'bash' language identifier to all shell command blocks
   - Improves documentation readability
   - Fixed blocks at lines 62, 74, 83, 137

3. **Update environment documentation**
   - Removed outdated references to hardcoded compiler variables
   - Updated to reflect reliance on Homebrew's superenv
   - Clarified BOOST_INCLUDE is set in wrapper, not during build

All documentation now accurately reflects the current implementation
and provides proper syntax highlighting for better user experience.
Addressed two suggestions from qodo-merge-pro review:

1. **Add explicit error handling to wrapper** (Importance: 2)
   - Changed: cd "#{prefix}" && exec
   - To: cd "#{prefix}" || exit 1; exec
   - Ensures script fails fast if directory change fails
   - Prevents execution in wrong directory if prefix is missing

2. **Use lighter test command** (Importance: 7)
   - Changed: mfc run (full simulation)
   - To: mfc count (case file parsing only)
   - Much faster test execution
   - More reliable (doesn't depend on simulation completing)
   - Still validates: wrapper, toolchain, case parsing, Python env
   - Reduces test time from minutes to seconds

Both changes improve robustness and testing efficiency.
Added GitHub Actions workflow to test Homebrew formula on macOS:

**Triggers:**
- Push to master or homebrew-formula branches
- PRs to master
- Changes to packaging/homebrew/ or workflow file
- Manual workflow dispatch

**Test Steps:**
1. Set up Homebrew and update
2. Install all MFC dependencies
3. Validate formula syntax (audit + style check)
4. Install MFC from local formula (build from source)
5. Run Homebrew's built-in formula tests
6. Test MFC commands:
   - mfc wrapper (--help)
   - All three binaries (-h flags)
   - Case file parsing (mfc count)
7. Verify installation structure
8. Clean up

**Benefits:**
- Ensures formula works on macOS
- Catches syntax errors early
- Validates installation structure
- Tests actual functionality
- Runs on every formula change

**Runner:** macos-latest (GitHub-hosted)
Fixed all 16 style violations detected by brew style:

**Required Headers:**
- Added: # typed: true (Sorbet type checking)
- Added: # frozen_string_literal: true (Ruby optimization)
- Added: Top-level documentation comment for Mfc class

**Whitespace Issues:**
- Removed all trailing whitespace (7 locations)
- Removed trailing blank lines at end of file

**Assertion Updates:**
- Changed: assert_predicate -> assert_path_exists (5 locations)
- More idiomatic for Homebrew formulas

**CI Workflow:**
- Removed brew audit with path (now disabled in Homebrew)
- Keep brew style check which catches all these issues

All offenses are now resolved. The formula passes brew style checks.
- Create temporary local tap (mflowcode/test) to satisfy Homebrew's tap requirement
- Copy formula to tap before installation
- This works around Homebrew rejecting direct file path installations
- Add git config before brew tap-new to avoid 'empty ident name' error
- Required for GitHub Actions runners without git identity
- Remove leading spaces from Python code in heredoc
- Python patch is appended at module level, requires zero indentation
- Fixes IndentationError in brew test that was breaking bottle workflow
@MFlowCode MFlowCode deleted a comment from Copilot AI Nov 7, 2025
@MFlowCode MFlowCode deleted a comment from Copilot AI Nov 7, 2025
The mfc wrapper was trying to write lock.yaml to the read-only Cellar
location. This patch overrides mfc.common paths to use the temporary
working directory for writable files (build/, lock.yaml) while keeping
toolchain and examples pointing to the Homebrew installation.
sitecustomize.py is loaded automatically at Python startup, ensuring
our path overrides (MFC_ROOT_DIR, MFC_BUILD_DIR, MFC_LOCK_FILEPATH)
are applied before any mfc.common imports happen. This fixes the
lock.yaml write error that occurred when the patch loaded too late.
The homebrew-mfc tap CI was failing with 'Failed changing dylib ID' errors
when trying to relocate compiled Python C extensions (orjson.so) in the venv.

Added pour_bottle? method returning false to disable bottles entirely,
forcing source builds. This is the correct approach for formulas with
Python venvs containing compiled extensions that cannot be relocated.

The previous skip_relocation! directive was incorrect as it's only valid
inside a bottle block, not at the class level.
This commit properly fixes bottle relocation issues by addressing the root cause:

1. Removed pour_bottle? hack that disabled bottles entirely

2. Added LDFLAGS with -headerpad_max_install_names when compiling Python
   packages to ensure C extensions (like orjson) have sufficient Mach-O
   header padding for Homebrew's bottle relocation process

3. Force pip to compile from source (--no-binary :all:) instead of using
   pre-built wheels, ensuring our LDFLAGS are applied during compilation

4. Changed shebang from #!/bin/bash to #!/usr/bin/env bash for better
   portability and to satisfy brew audit checks

This allows the formula to create proper bottles in the homebrew-mfc tap
while maintaining fast installation times for users.

Fixes: 'Failed changing dylib ID' errors during bottling
Fixes: 'Non-executables were installed' audit warnings
… deps from source

Cantera 3.1.0 has CMake compatibility issues when building from source with
CMake 4.x (tries to build old yaml-cpp that requires CMake < 3.5).

Solution: Use hybrid approach:
- Install Cantera from pre-built wheel (doesn't need custom LDFLAGS)
- Set LDFLAGS and compile MFC toolchain dependencies from source with
  --no-binary :all: to ensure orjson and other C extensions have proper
  header padding for bottle relocation

This allows bottles to be created while avoiding the Cantera build failure.
Removed --no-binary :all: flag that was forcing ALL packages to compile
from source, which caused failures for Rust-based packages like 'typos'
that require Rust compiler.

New approach:
- Set LDFLAGS with -headerpad_max_install_names in environment
- Let pip decide whether to use wheels or compile from source
- Pip will use LDFLAGS when compiling C extensions (like orjson)
- Most packages will use pre-built wheels (faster, no extra deps needed)
- Only packages that need compilation will be built from source

This is simpler, faster, and avoids requiring Rust/other compilers
while still fixing the bottle relocation issues for packages with
C extensions that need custom header padding.
The issue was that orjson (a transitive dependency) was being installed
as a pre-built wheel from PyPI, which doesn't have sufficient header
padding for Homebrew's bottle relocation process.

Solution:
1. Install all dependencies normally (including wheels)
2. Force-reinstall orjson from source with LDFLAGS set
3. Use --no-deps to avoid reinstalling dependencies

This ensures orjson is compiled with -Wl,-headerpad_max_install_names
which provides the necessary header space for brew test-bot to successfully
relocate the dylib during bottling.
The formula contains a Python virtual environment with pre-built C extensions
(orjson, etc.) that cannot be reliably relocated by Homebrew's bottling process.

Attempts to force-compile these packages from source fail because:
- orjson requires Rust (maturin build tool)
- typos requires Rust
- Setting LDFLAGS only helps packages built from source, not wheels

Solution: Use 'bottle :unneeded' to tell Homebrew not to create bottles.
Users will install from source, which is appropriate for scientific computing
software like MFC. The installation process remains the same and works correctly.
…w install

Homebrew no longer supports 'bottle :unneeded'. Its presence triggered
'mfc: wrong number of arguments (given 1, expected 0)' when installing
from a temporary local tap. Removing it restores installability.

Note: Tap CI may still fail on bottle relocation for orjson unless we
add a Rust build dependency and force-build orjson from source.
@MFlowCode MFlowCode deleted a comment from qodo-merge-pro bot Nov 8, 2025
@MFlowCode MFlowCode deleted a comment from qodo-merge-pro bot Nov 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant