shapehq / tartelet

βš™οΈπŸ’» A macOS app that makes it a breeze to manage multiple GitHub Actions runners in ephemeral virtual machines on a single host machine. The benefits are that runners can run in parallel, and each job runs in an isolated environment.
MIT License
520 stars 19 forks source link
github-actions macos runner self-hosted-runner swift

Hero artwork

πŸ‘‹ Welcome to Tartelet - a macOS app that launches self-hosted GitHub Actions runners in virtual machines using Tart.

Tartelet makes it a breeze to manage up to two GitHub Actions runners in ephemeral virtual machines on a single host machine. The benefits are that runners can run in parallel and each job runs in an isolated environment that is recreated after each GitHub Actions job has finished.

πŸš€ Getting Started

Please refer to the following articles in the wiki to get started with Tartelet.

πŸ‘¨β€πŸ”§ How does it work?

Screenshot of Tartelet running two virtual machines

Tartelet uses Tart for managing the virtual machines and Tart which in turn uses Apple's Apple's Virtualization framework. The lifecycle of a GitHub Actions runner managed by Tartelet is as follows:

  1. Tartelet uses Tart to clone a virtual machine.
  2. The virtual machine is booted.
  3. After the machine is booted, a setup script is being run. The script downloads the newest version of GitHub's runner application and registers the runner on the GitHub organization.
  4. The runner listens for a job and executes it.
  5. After executing the job, the runner automatically removes itself from the GitHub organization.
  6. The virtual machine is shutdown.
  7. Tartelet uses Tart to delete the virtual machine.

After the last step the process starts over.

🏎 How is the performance?

The performance depends on the hardware that the app is running on. When testing on a Mac mini M1 from 2020 with 16 GB memory, we found that our jobs run 3 - 4 times faster than on GitHub's runners.

We found that our jobs run about 12% slower when running two virtual machines in parallel compared to running a single virtual machine. We find this performance cost negligible as running two virtual machines significantly increases our throughput at a low monetary cost.

This means that Tartelet can run two virtual machines at once. This the maximum number of virtual machines that Apple’s Virtualization framework allows us to run at once.

After a job has finished, the virtual machine that ran the job is shut down and destroyed, and a new virtual machine is created and booted. This process takes about 25 - 30 seconds. However, that overhead is insignificant in most cases as Tartelet creates a new virtual machine after each job has finished. This means that a new virtual machine and its GitHub Actions runner are ready to process the next job. Unless there are more jobs queued on GitHub than the number of available virtual machines, the overhead of creating and booting a virtual machine becomes negligible.

These numbers were last updated in January/February 2023.

πŸ‘©β€πŸ’» How can I contribute?

Pull requests with bugfixes and new features are much appreciated. We are happy to review PRs and merge them once they are ready, as long as they contain changes that fit within the vision of Tartelet.

Clone the repository to get started working on the project.

git clone git@github.com:shapehq/tartelet.git

Generating a Project File with XcodeGen

After cloning the repository you will notice that the project does not contain a .xcodeproj file. This should be generated using XcodeGen. Install XcodeGen using Homebrew by running the following command in your terminal.

brew install xcodegen

After installing XcodeGen the project file can be generated by running the following command.

xcodegen generate

Generating Resource Constants with SwiftGen

We use SwiftGen to generate constants for images, colors, and localizations. Install SwiftGen using Homebrew by running the following command in your terminal.

brew install swiftgen

Constants for images, colors, and localizations are then generated by running the following command in your terminal.

swiftgen

The swiftgen.yml file at the root of the repository describes how constants are generated.

Configuring the project to run on your machine

To run the project locally, it is necessary to edit the Tartelet.entitlements file to specify a keychain access group that you control. Then you will need to edit the Composers.swift file to ensure the keychain is initialized with the keychain access group specified in the entitlements file. If you do not do this, the app will not be able to persist settings to the keychain.

In other words, you will need to search for $(AppIdentifierPrefix)dk.shape.Tartelet and 566MC7D8D4.dk.shape.Tartelet in the project and replace the occurrences with references to your keychain access group.

Linting the Codebase with SwiftLint

We use SwiftLint to ensure uniformity in the code. Install SwiftLint using Homebrew by running the following command in your terminal.

brew install swiftlint

🀨 Why is it named Tartelet?

The app is named Tartelet because it builds upon Tart, a source-available CLI for managing macOS virtual machines. Tartelet makes it easy to run multiple virtual machines using Tart. The Danish word for "easy" is "let". "Tart" + "e" + "let" = "Tartelet" and a "tartelet" is a traditional Danish food.

πŸ™ Acknowledgements


Tartelet is built with ❀️ by Shape in Denmark. Oh, and we are hiring πŸ€—