Update GitHub Actions workflow for bottle management #94
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: Bottle | |
| on: | |
| push: | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| test-and-bottle: | |
| name: Test and build bottles per macOS | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [macos-14, macos-15, macos-26] # Sonoma, Sequoia, Tahoe (public preview) | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout tap | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Homebrew | |
| uses: Homebrew/actions/setup-homebrew@master | |
| - name: Ensure no conflicting taps provide mfc | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew untap mflowcode/mfc >/dev/null 2>&1 || true | |
| brew untap mflowcode/local >/dev/null 2>&1 || true | |
| - name: Test tarball download | |
| run: | | |
| curl -I "https://github.com/MFlowCode/MFC/archive/refs/tags/v5.1.5.tar.gz" | |
| curl -L "https://github.com/MFlowCode/MFC/archive/refs/tags/v5.1.5.tar.gz" | shasum -a 256 | |
| - name: Determine version and root URL (from checked-out formula) | |
| id: meta | |
| run: | | |
| set -euo pipefail | |
| FORMULA="Formula/mfc.rb" | |
| URL="$( | |
| grep -Eo 'https://github.com/[^"]+/archive/refs/tags/v[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz' "${FORMULA}" \ | |
| | tail -n 1 | |
| )" | |
| if [[ -z "${URL}" ]]; then | |
| echo "Could not extract release tarball URL from ${FORMULA}" >&2 | |
| exit 1 | |
| fi | |
| VERSION="$(echo "${URL}" | sed -E 's/.*v([0-9]+\.[0-9]+\.[0-9]+)\.tar\.gz/\1/')" | |
| if [[ -z "${VERSION}" ]]; then | |
| echo "Could not parse version from URL: ${URL}" >&2 | |
| exit 1 | |
| fi | |
| TAG="mfc-${VERSION}" | |
| ROOT_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "root_url=${ROOT_URL}" >> "$GITHUB_OUTPUT" | |
| echo "Formula URL: ${URL}" | |
| echo "Formula version: ${VERSION}" | |
| echo "Release tag: ${TAG}" | |
| echo "Bottle root_url: ${ROOT_URL}" | |
| - name: Create temp tap with checked-out formula | |
| run: | | |
| set -euo pipefail | |
| # brew tap-new needs git identity sometimes | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| # Create a local tap and copy the formula into Homebrew's tap location | |
| brew tap-new mflowcode/local | |
| TAP_DIR="$(brew --repository)/Library/Taps/mflowcode/homebrew-local" | |
| mkdir -p "${TAP_DIR}/Formula" | |
| cp Formula/mfc.rb "${TAP_DIR}/Formula/mfc.rb" | |
| echo "Temp tap formula:" | |
| ls -la "${TAP_DIR}/Formula/mfc.rb" | |
| - name: Install formula with --build-bottle (temp tap) | |
| run: | | |
| set -euo pipefail | |
| echo "Installing mfc with --build-bottle (allowing non-fatal dylib fixup failures)..." | |
| # Homebrew may exit non-zero due to dylib ID fixup issues in Python wheels, | |
| # even though the formula actually installed correctly. Treat that as | |
| # non-fatal as long as the formula is present. | |
| set +e | |
| brew install --build-bottle mflowcode/local/mfc 2>&1 | tee /tmp/brew-install.log | |
| brew_exit_code=$? | |
| set -e | |
| if brew list mflowcode/local/mfc &>/dev/null; then | |
| echo "✅ mfc installed successfully (ignoring dylib fixup warnings)" | |
| else | |
| echo "❌ mfc installation failed; propagating brew exit code" | |
| exit $brew_exit_code | |
| fi | |
| - name: Run Sod shock tube test case | |
| run: | | |
| set -euo pipefail | |
| echo "Running a simple test case (1D Sod shock tube) on ${{ matrix.os }}..." | |
| TESTDIR=$(mktemp -d) | |
| cp "$(brew --prefix mflowcode/local/mfc)/examples/1D_sodshocktube/case.py" "$TESTDIR/" | |
| cd "$TESTDIR" | |
| mfc case.py -j 1 | |
| test -d "$TESTDIR/silo_hdf5" | |
| echo "✅ Test case ran successfully and produced output" | |
| - name: Basic installation verification | |
| run: | | |
| set -euo pipefail | |
| PREFIX="$(brew --prefix mflowcode/local/mfc)" | |
| echo "1. Checking binaries..." | |
| test -x "${PREFIX}/bin/pre_process" | |
| test -x "${PREFIX}/bin/simulation" | |
| test -x "${PREFIX}/bin/post_process" | |
| test -x "${PREFIX}/bin/mfc" | |
| echo "2. Checking toolchain..." | |
| test -d "${PREFIX}/toolchain" | |
| echo "3. Checking Python venv..." | |
| test -d "${PREFIX}/libexec/venv" | |
| test -x "${PREFIX}/libexec/venv/bin/python" | |
| echo "4. Checking examples..." | |
| test -d "${PREFIX}/examples" | |
| echo "5. Testing mfc command..." | |
| mfc --help | |
| echo "✅ All verification checks passed on ${{ matrix.os }}" | |
| - name: Build bottle (temp tap formula) | |
| run: | | |
| set -euo pipefail | |
| brew bottle --root-url="${{ steps.meta.outputs.root_url }}" --json mflowcode/local/mfc | |
| ls -1 *.bottle.* | |
| - name: Upload bottle artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bottles-${{ matrix.os }} | |
| path: | | |
| *.bottle.* | |
| merge-bottles: | |
| name: Merge bottles and update formula | |
| needs: test-and-bottle | |
| runs-on: macos-14 | |
| steps: | |
| - name: Checkout tap | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Homebrew | |
| uses: Homebrew/actions/setup-homebrew@master | |
| - name: Determine version and root URL (from checked-out formula) | |
| id: meta | |
| run: | | |
| set -euo pipefail | |
| FORMULA="Formula/mfc.rb" | |
| URL="$( | |
| grep -Eo 'https://github.com/[^"]+/archive/refs/tags/v[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz' "${FORMULA}" \ | |
| | tail -n 1 | |
| )" | |
| if [[ -z "${URL}" ]]; then | |
| echo "Could not extract release tarball URL from ${FORMULA}" >&2 | |
| exit 1 | |
| fi | |
| VERSION="$(echo "${URL}" | sed -E 's/.*v([0-9]+\.[0-9]+\.[0-9]+)\.tar\.gz/\1/')" | |
| if [[ -z "${VERSION}" ]]; then | |
| echo "Could not parse version from URL: ${URL}" >&2 | |
| exit 1 | |
| fi | |
| TAG="mfc-${VERSION}" | |
| ROOT_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "root_url=${ROOT_URL}" >> "$GITHUB_OUTPUT" | |
| - name: Configure git for bottle merge | |
| run: | | |
| set -euo pipefail | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| - name: Download all bottle artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: bottles | |
| - name: Flatten bottle directory | |
| run: | | |
| set -euo pipefail | |
| echo "Before flattening:" | |
| find bottles -name '*.bottle.*' -type f | |
| find bottles -mindepth 2 -name '*.bottle.*' -type f -exec mv {} bottles/ \; | |
| echo "" | |
| echo "After flattening:" | |
| ls -1 bottles/*.bottle.* | |
| - name: Rename bottles for GitHub release | |
| run: | | |
| set -euo pipefail | |
| echo "Renaming bottles (mfc-- → mfc-)..." | |
| for file in bottles/mfc--*.bottle.*; do | |
| if [[ -f "$file" ]]; then | |
| newname=$(echo "$file" | sed 's/mfc--/mfc-/') | |
| mv "$file" "$newname" | |
| echo " $file → $newname" | |
| fi | |
| done | |
| echo "" | |
| echo "Bottles ready for upload:" | |
| ls -1 bottles/*.bottle.* | |
| - name: Ensure no conflicting taps provide mfc (merge job) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew untap mflowcode/mfc >/dev/null 2>&1 || true | |
| brew untap mflowcode/local >/dev/null 2>&1 || true | |
| - name: Create temp tap for merge and copy formula into it | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| brew tap-new mflowcode/local | |
| TAP_DIR="$(brew --repository)/Library/Taps/mflowcode/homebrew-local" | |
| mkdir -p "${TAP_DIR}/Formula" | |
| cp Formula/mfc.rb "${TAP_DIR}/Formula/mfc.rb" | |
| brew info mflowcode/local/mfc | |
| - name: Merge bottle metadata into formula | |
| id: merge | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| JSON_BOTTLES=(bottles/*.bottle*.json) | |
| if [[ ! -e "${JSON_BOTTLES[0]}" ]]; then | |
| echo "No bottle metadata (*.bottle*.json) found in bottles/" | |
| ls -la bottles/ | |
| exit 1 | |
| fi | |
| TAP_DIR="$(brew --repository)/Library/Taps/mflowcode/homebrew-local" | |
| echo "Merging bottle metadata from:" | |
| printf '%s\n' "${JSON_BOTTLES[@]}" | |
| brew bottle --merge --write --root-url="${{ steps.meta.outputs.root_url }}" "${JSON_BOTTLES[@]}" | |
| # Copy the updated formula back into this checkout so git add works here | |
| cp "${TAP_DIR}/Formula/mfc.rb" Formula/mfc.rb | |
| if git diff --quiet -- Formula/mfc.rb; then | |
| echo "bottle_updated=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "bottle_updated=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Commit formula update if changed | |
| if: steps.merge.outputs.bottle_updated == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| git add Formula/mfc.rb | |
| if git diff --cached --quiet; then | |
| echo "No changes staged; skipping commit." | |
| exit 0 | |
| fi | |
| git commit -m "mfc: bottles for v${{ steps.meta.outputs.version }}" | |
| - name: Push bottle updates if changed | |
| if: steps.merge.outputs.bottle_updated == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| git remote set-url origin "https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git" | |
| git push origin HEAD:main | |
| - name: Create/update release and upload bottles | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ steps.meta.outputs.tag }} | |
| name: MFC bottles ${{ steps.meta.outputs.version }} | |
| files: bottles/*.bottle.* | |
| fail_on_unmatched_files: true | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} |