" /> " />

Projects πŸ”Έ Articles πŸ”Έ Categories πŸ”Έ

Deploying an ephemeral macOS environment through Github Actions

Oh no! Someone's giving me macOS stuff to test and I don't have access to any Mac whatsoever this weekend!
What in the doushio can I do?

Most solutions for getting a virtualized Mac running involve downloading the 7GB-something setup from Apple, installing it in some form of virtualization software, setting up a bunch of bullshit magical variables to masquerade your VM as an iMac and then waiting through the entire installation process.

Past that, you'll also need to add an Apple Account, download Xcode and its glorious 6 GBs of awful IDE design, etc etc jesus this is going to eat my entire weekend
you can technically only download the xcode command line tools and they're like 200MBs but I'm trying to overdramatize a bit here

The other solution is of course to rent a Mac VPS, but as this is a super niche market, prices are atrociously expensive for what amounts to me running homebrew for about 30 minutes.

Jumping into Actions

Since GitHub Actions introduced matrix builds recently, there very conveniently are macOS runners for me to run code on. And they come with a lot of devtools preinstalled, making for a rather comfy experience.

At this point I could just write an Actions script running my homebrew code and be done with it, but I thought I could have something a bit more flexible.
Hot off the trail of my last Actions venture, I thought about using the tmate action to spawn a SSH session on the Mac runner for me. It'd basically give me an on-demand, pre-provisioned macOS command line whenever I'd want!

For up to 6 hours of execution time but honestly that's already way too much

Writing the Action

Using the tmate action as-is would basically make this setup dead simple, but it doesn't work on Mac runners as-is. Darn.

Luckily the entire action is really easy to replicate in bash, so I just wrote my own:

name: Summon Steve Jobs

on: [push]


    runs-on: macOS-10.14

    - uses: actions/checkout@v1
    - name: Install tmate
      run: |
        brew install tmate openssh screenfetch
        echo -e 'y\n'|ssh-keygen -q -t rsa -N "" -f ~/.ssh/id_rsa
        tmate -S /tmp/tmate.sock new-session -d
        tmate -S /tmp/tmate.sock wait tmate-ready
    - name: It just works
      run: |
        SSH="$(tmate -S /tmp/tmate.sock display -p '#{tmate_ssh}')"
        WEB="$(tmate -S /tmp/tmate.sock display -p '#{tmate_web}')"
        echo "SSH: ${SSH}"
        echo "Web: ${WEB}"
        echo "You can now connect to the tmate session."
        while true; do 
          # loop infinitely
          sleep 10

The only issue here is that quitting the session doesn't automatically end the run like the original action does, but it's good enough.β„’

rebel rebel how could they know

Spare Thoughts

I was curious about whether you could get VNC output on this, but while the command to enable VNC works, the runners don't expose anything for you to connect to.

Since I wanked this to debug the upcoming Homebrew support for LRR, it's totally legal and not breaking the Actions TOS in any way. πŸ˜‡