Notcurses-Native.git | .github/workflows/ | _verify-macos-x86_64.yml edit


# Reusable workflow: verify the macos-x86_64 prebuilt installs +
# loads on a Rosetta'd x86_64 Rakudo. The macos-14 runner is arm64;
# we install Rosetta + source-build x86_64 Rakudo under it (no
# Raku/setup-raku@v1 prebuilt for x86_64 macOS).
#
# Wrapping every Raku/zef invocation in `arch -x86_64` guarantees
# we're testing the x86_64 prebuilt as a real Intel-Mac user would —
# the Rakudo process is x86_64, NativeCall loads x86_64 dylibs, etc.

name: _verify-macos-x86_64

on:
  workflow_call:

env:
  TERM: xterm
  COLORTERM: truecolor
  LANG: en_US.UTF-8
  LC_ALL: en_US.UTF-8
  NOTCURSES_NATIVE_REQUIRE_SHIM: '1'
  RAKUDO_VERSION: '2026.03'

jobs:
  verify:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v6
        with: { submodules: recursive }

      - name: Install Rosetta
        run: softwareupdate --install-rosetta --agree-to-license || true

      - name: Install x86_64 Homebrew + Rakudo build deps
        run: |
          set -euxo pipefail
          if [[ ! -x /usr/local/bin/brew ]]; then
            arch -x86_64 /bin/bash -c \
              "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \
              < /dev/null
          fi
          # Rakudo's Configure.pl + the build itself need perl, git,
          # make. macOS already has perl/git via Xcode CLT but those
          # are arm64-native; arch -x86_64 on a fat (universal)
          # binary uses the x86_64 slice automatically. For safety
          # install x86_64 brew versions too.
          arch -x86_64 /usr/local/bin/brew install --overwrite python@3.14
          arch -x86_64 /usr/local/bin/brew install perl git
          echo "/usr/local/bin" >> "$GITHUB_PATH"

      - name: Restore source-built Rakudo
        # restore + save split (not actions/cache@v4) so a downstream
        # test failure doesn't invalidate the ~10-20 min Rakudo build.
        # Key has `-rakudo-only-v2` suffix to invalidate caches that
        # carried stale zef state in site/ — see the linux-aarch64
        # lane for the full root-cause writeup.
        id: rakudo-cache
        uses: actions/cache/restore@v4
        with:
          path: ~/.rakubrew
          key: rakudo-macos-x86_64-${{ env.RAKUDO_VERSION }}-rakudo-only-v2

      - name: Build x86_64 Rakudo under Rosetta (rakubrew)
        run: |
          # arch -x86_64 wraps the whole rakubrew/Configure.pl/make
          # process so NQP+MoarVM+Rakudo all build as x86_64. Even
          # if cache restored, the script's idempotent short-circuit
          # checks (already-built) skip the expensive part.
          arch -x86_64 bash scripts/ci/build-rakudo.sh

      - name: Strip zef module state — we cache Rakudo only, not installs
        run: rm -rf ~/.rakubrew/versions/moar-*/install/share/perl6/site || true

      - name: Save Rakudo cache (build succeeded — independent of tests)
        if: steps.rakudo-cache.outputs.cache-hit != 'true'
        uses: actions/cache/save@v4
        with:
          path: ~/.rakubrew
          key: rakudo-macos-x86_64-${{ env.RAKUDO_VERSION }}-rakudo-only-v2

      - name: Install zef under Rosetta (~30s; not cached — see script header)
        run: arch -x86_64 bash scripts/ci/install-zef.sh

      - name: Add Rakudo shims + site-bin to PATH
        # shims/ for raku/zef (rakubrew-managed). site-bin for
        # zef-installed module bins like prove6 (rakubrew doesn't
        # auto-rehash after `zef install` so those aren't shimmed).
        run: |
          echo "$HOME/.rakubrew/shims" >> "$GITHUB_PATH"
          echo "$HOME/.rakubrew/versions/moar-${{ env.RAKUDO_VERSION }}/install/share/perl6/site/bin" >> "$GITHUB_PATH"

      - name: Verify Rakudo runs as x86_64 under Rosetta
        # `which raku` resolves to rakubrew's shim — a Perl-script
        # dispatch wrapper, not the binary. `file` on the shim
        # reports "Perl script text", which never contains "x86_64".
        # Ask raku itself instead: `$*KERNEL.hardware` is sourced
        # from uname(2), and Rosetta lies to the x86_64 process to
        # report "x86_64" (whereas an arm64 raku here would report
        # "arm64"). The `arch -x86_64` wrap is paranoid but matches
        # how every subsequent step runs raku/zef/prove6.
        run: |
          set -e
          detected=$(arch -x86_64 raku -e 'print $*KERNEL.hardware')
          echo "Rakudo reports hardware: $detected"
          [ "$detected" = "x86_64" ] || {
            echo "❌ Expected x86_64 (Rosetta), got '$detected' — Rakudo build wasn't wrapped in arch -x86_64?"
            exit 1
          }

      - name: zef install (prebuilt path)
        run: arch -x86_64 zef install --/test .

      - name: zef install App::Prove6
        run: arch -x86_64 zef install --/test App::Prove6

      - name: prove6 (prebuilt path)
        run: arch -x86_64 prove6 --verbose -I lib -I t/lib t

      - name: prove (xt — terminal-dependent, prebuilt path)
        # Perl's `prove` (the orchestrator) doesn't need to be
        # x86_64 — it just forks the -e command per test file. The
        # `raku` invocation IS x86_64 via `arch -x86_64`, which is
        # what loads the bundled prebuilt under test.
        run: prove -e 'arch -x86_64 raku -I lib -I t/lib' --verbose xt/*.rakutest

      - name: Install x86_64 brew deps for source-build pass
        run: |
          arch -x86_64 /usr/local/bin/brew install \
            cmake pkg-config ffmpeg ncurses libunistring libdeflate

      - name: zef install (source-build path)
        env: { NOTCURSES_NATIVE_BUILD_FROM_SOURCE: '1' }
        run: arch -x86_64 zef install --/test --force-install .

      - name: prove6 (source-build path)
        run: arch -x86_64 prove6 --verbose -I lib -I t/lib t