Ephemeral CI for iOS with GitHub Actions and Orka Just Got Better

After showing around a first iteration of Orka-Actions-Connect, we embraced the community’s feedback and made it simpler to deploy and effortless to maintain.

Orka + GitHub Actions

This past August, we published a blog post that detailed an early-stage success in getting GitHub Actions workflows to run on single-use macOS VMs in Orka. And as you might expect, we were eager to show it around and thrilled to get feedback from the community. And while the general consensus was that it was cool, it was also too complex to facilitate the “set it and forget it” approach that so many teams look for in CI tooling.

So, we took that input and we reduced the complexity for end users significantly. For starters, in the original iteration, there was a self-hosted master runner that lived in the Orka environment. We’ve done away with that, and now the work that it was responsible for – namely spinning up and tearing down the self-hosted runner for a given workflow – is handled by Ubuntu VMs provided by GitHub.

Unfortunately, the added complexity of making a secure connection to the Orka environment from the Ubuntu VM meant added time per workflow. But we managed to find some other optimizations to make up lost time.

But enough of the nitty-gritty, let’s get to how simple it is to set up now!

Setting Up Orka-Actions-Connect

There are two steps to getting this up and running. First, you’ll need to define an image in Orka that will be used as a template to spin up your self-hosted runner.

To do so, you can follow the simple steps outlined in the Configure your macOS Agent Image section of Orka-Actions-Connect’s documentation. This process includes spinning up and VM in Orka, running an installation script on that VM, adding any additional dependencies required by your workflow, and finally saving the VM’s state as an image, which will serve as a template for your ephemeral self-hosted runners.

Next, you’ll need to augment your current GitHub Actions workflow YAML with some boilerplate code. This boilerplate facilitates the inclusion of two additional Jobs that effectively “sandwich” your existing workflow, such that the workflow will still run as it currently does, but on Orka, rather than on GitHub supplied macOS instances.

These additional Jobs use two GitHub Actions that are available in the GitHub Actions Marketplace -- orka-actions-up, and orka-actions-down, which are responsible for spinning up a self-hosted runner, associating it with your repository in GitHub, passing your workflow to this new runner in Orka, and ultimately tearing everything down as the final step of your CI process.

Orka-Actions-Connect Workflow Example

Orka-Actions-Connect is designed to easily accommodate existing workflow definitions. For illustration’s sake, let’s say your existing workflow looks like this:

1   on:
2 push:
3 branches:
4 - main
5 jobs:
6 build:
7 runs-on: macOS
8 steps:
9 id: build
10 run: |
11 ./build.sh

Essentially, this workflow says that any time someone pushes to the main branch of the repository, the ./build.sh script is executed on a GitHub-provided macOS VM.

In order to execute this same workflow in Orka, you would need to create the required secrets set on the repo in GitHub, and update the workflow as follows:

1   on:
2 push:
3 branches:
4 - main
6 jobs:
7 up:
8 runs-on: ubuntu-latest # NOTE: both orka-actions-up and orka-actions-down run on `ubuntu-latest`
9 steps:
10 - name: up
11 id: up
12 uses: jeff-vincent/orka-actions-up@v1.1.1
13 with:
14 orkaUser: ${{ secrets.ORKA_USER }}
15 orkaPass: ${{ secrets.ORKA_PASS }}
16 orkaBaseImage: gha-agent.img
17 githubPat: ${{ secrets.GH_PAT }}
18 vpnUser: ${{ secrets.VPN_USER }}
19 vpnPassword: ${{ secrets.VPN_PASSWORD }}
20 vpnAddress: ${{ secrets.VPN_ADDRESS }}
21 vpnServerCert: ${{ secrets.VPN_SERVER_CERT }}
22 vcpuCount: 6
23 coreCount: 6
24 outputs:
25 vm-name: ${{ steps.up.outputs.vm-name }}
27 build: # NOTE: this is where your macOS-based, GitHub Actions workflow will be executed.
28 needs: up
29 runs-on: [self-hosted, "${{ needs.up.outputs.vm-name }}"] # NOTE: this section of the workflow can contain any number of seperate jobs,
30 steps: # but each must have this `runs-on` value.
31 - name: build
32 id: build
33 run: |
34 ./build.sh
35 down:
36 if: always()
37 needs: [up, build] # NOTE: all jobs you wish to run on the macOS instance,
38 runs-on: ubuntu-latest # along with the `orka-actions-up` job, must be listed here.
39 steps:
40 - name: down
41 id: down
42 uses: jeff-vincent/orka-actions-down@v1.1.0
43 with:
44 orkaUser: ${{ secrets.ORKA_USER }}
45 orkaPass: ${{ secrets.ORKA_PASS }}
46 githubPat: ${{ secrets.GH_PAT }}
47 vpnUser: ${{ secrets.VPN_USER }}
48 vpnPassword: ${{ secrets.VPN_PASSWORD }}
49 vpnAddress: ${{ secrets.VPN_ADDRESS }}
50 vpnServerCert: ${{ secrets.VPN_SERVER_CERT }}
51 vmName: ${{ needs.job1.outputs.vm-name }}

Although our file grew a bit, the additional code is largely just some boilerplate we added. Specifically, we have “sandwiched” our existing build job with an up job and a down job, which spin up and tear down the GitHub Actions self-hosted runner in Orka.

Finally, we have also made two small changes to our original build job, which you can see on lines 28-29 above. Line 28 tells GitHub Actions that build cannot begin until up has been completed in order to keep the flow of jobs synchronous, and thus ensure that an appropriately labeled runner will be available when the macOS job is executed. Line 29 is passing the runner label that was assigned in the up job as a runs-on argument, so as to correctly direct the job to this newly spun-up runner.

Join the conversation!

Tools like these become better and better with feedback from the Orka and Mac development community. If you haven’t already, come over to our Community Slack channel – we’d love to hear your ideas, questions, and suggestions.