├── lib └── shared ├── .cirrus.yml ├── plugin.yml ├── hooks ├── pre-exit ├── command └── pre-command └── README.md /lib/shared: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VM_NAME="buildkite-${BUILDKITE_STEP_ID}" 4 | -------------------------------------------------------------------------------- /.cirrus.yml: -------------------------------------------------------------------------------- 1 | task: 2 | name: Lint 3 | container: 4 | image: buildkite/plugin-linter:latest 5 | script: 6 | - lint --id cirruslabs/tart --path . 7 | -------------------------------------------------------------------------------- /plugin.yml: -------------------------------------------------------------------------------- 1 | name: Tart 2 | description: Runs your build steps in Tart Virtual Machines 3 | author: https://github.com/cirruslabs 4 | requirements: 5 | - tart 6 | - sshpass 7 | configuration: 8 | properties: 9 | image: 10 | type: string 11 | ssh_username: 12 | type: string 13 | ssh_password: 14 | type: string 15 | headless: 16 | type: boolean 17 | always_pull: 18 | type: boolean 19 | softnet: 20 | type: boolean 21 | required: 22 | - image 23 | additionalProperties: false 24 | -------------------------------------------------------------------------------- /hooks/pre-exit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set shell options to enable fail-fast behavior 4 | # 5 | # * -e: fail the script when an error occurs or command fails 6 | # * -u: fail the script when attempting to reference unset parameters 7 | # * -o pipefail: by default an exit status of a pipeline is that of its 8 | # last command, this fails the pipe early if an error in 9 | # any of its commands occurs 10 | # 11 | set -euo pipefail 12 | 13 | # Include shared variables and functions 14 | HOOKS_DIR=$(dirname -- "${BASH_SOURCE[0]}") 15 | HOOKS_DIR_ABSOLUTE=$(cd -- "${HOOKS_DIR}" && pwd) 16 | . "${HOOKS_DIR_ABSOLUTE}/../lib/shared" 17 | 18 | # Stop the VM 19 | tart stop "${VM_NAME}" 20 | 21 | # Delete the VM 22 | tart delete "${VM_NAME}" 23 | -------------------------------------------------------------------------------- /hooks/command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set shell options to enable fail-fast behavior 4 | # 5 | # * -e: fail the script when an error occurs or command fails 6 | # * -u: fail the script when attempting to reference unset parameters 7 | # * -o pipefail: by default an exit status of a pipeline is that of its 8 | # last command, this fails the pipe early if an error in 9 | # any of its commands occurs 10 | # 11 | set -euo pipefail 12 | 13 | # Include shared variables and functions 14 | HOOKS_DIR=$(dirname -- "${BASH_SOURCE[0]}") 15 | HOOKS_DIR_ABSOLUTE=$(cd -- "${HOOKS_DIR}" && pwd) 16 | . "${HOOKS_DIR_ABSOLUTE}/../lib/shared" 17 | 18 | # Wait for the VM to boot and retrieve its IP 19 | VM_IP=$(tart ip --wait 60 "${VM_NAME}") 20 | 21 | # Execute the command on the VM 22 | SSH_USERNAME="${BUILDKITE_PLUGIN_TART_SSH_USERNAME:-admin}" 23 | SSH_PASSWORD="${BUILDKITE_PLUGIN_TART_SSH_PASSWORD:-admin}" 24 | 25 | sshpass -p "${SSH_PASSWORD}" ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" \ 26 | -o LogLevel=ERROR \ 27 | "${SSH_USERNAME}@${VM_IP}" \ 28 | "cd /Volumes/My\ Shared\ Files/ && zsh -l -c \"${BUILDKITE_COMMAND}\"" 29 | -------------------------------------------------------------------------------- /hooks/pre-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set shell options to enable fail-fast behavior 4 | # 5 | # * -e: fail the script when an error occurs or command fails 6 | # * -u: fail the script when attempting to reference unset parameters 7 | # * -o pipefail: by default an exit status of a pipeline is that of its 8 | # last command, this fails the pipe early if an error in 9 | # any of its commands occurs 10 | # 11 | set -euo pipefail 12 | 13 | # Include shared variables and functions 14 | HOOKS_DIR=$(dirname -- "${BASH_SOURCE[0]}") 15 | HOOKS_DIR_ABSOLUTE=$(cd -- "${HOOKS_DIR}" && pwd) 16 | . "${HOOKS_DIR_ABSOLUTE}/../lib/shared" 17 | 18 | # Make sure that the VM image is set 19 | if [ -z "${BUILDKITE_PLUGIN_TART_IMAGE}" ] 20 | then 21 | print "Please specify a VM image to use (e.g. ghcr.io/cirruslabs/macos-sonoma-base:latest)" 22 | 23 | exit 1 24 | fi 25 | 26 | # "always_pull" support 27 | if [ "${BUILDKITE_PLUGIN_TART_ALWAYS_PULL:-true}" = "true" ] 28 | then 29 | tart pull "${BUILDKITE_PLUGIN_TART_IMAGE}" 30 | fi 31 | 32 | # Clone the VM image 33 | tart clone "${BUILDKITE_PLUGIN_TART_IMAGE}" "${VM_NAME}" 34 | 35 | # Configure "tart run" invocation 36 | RUN_ARGS=() 37 | 38 | # Mount the project's directory 39 | RUN_ARGS+=("--dir ${BUILDKITE_BUILD_CHECKOUT_PATH}") 40 | 41 | # "headless" support 42 | if [ "${BUILDKITE_PLUGIN_TART_HEADLESS:-true}" = "true" ] 43 | then 44 | RUN_ARGS+=("--no-graphics") 45 | fi 46 | 47 | # "softnet" support 48 | if [ "${BUILDKITE_PLUGIN_TART_SOFTNET:-false}" = "true" ] 49 | then 50 | RUN_ARGS+=("--net-softnet") 51 | fi 52 | 53 | # Run the VM in background 54 | nohup tart run ${RUN_ARGS[*]} "${VM_NAME}" >/dev/null 2>&1 & 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tart Buildkite Plugin 2 | 3 | A [Buildkite plugin](https://buildkite.com/docs/plugins) for running pipeline steps in [Tart](https://github.com/cirruslabs/tart) Virtual Machines. 4 | 5 | ## Prequisites 6 | 7 | This plugin assumes that your pipeline is running on an Apple Silicon host with [Tart](https://tart.run/) installed: 8 | 9 | ``` 10 | brew install cirruslabs/cli/tart 11 | ``` 12 | 13 | You'll also need to install the `sshpass` utility program, so that the plugin will be able to connect to the Tart VMs using password-based authentication: 14 | 15 | ``` 16 | brew install cirruslabs/cli/sshpass 17 | ``` 18 | 19 | ## Example 20 | 21 | Add the following to your `pipeline.yml`: 22 | 23 | ```yml 24 | steps: 25 | - command: uname -a 26 | plugins: 27 | - cirruslabs/tart#v0.2.0: 28 | image: ghcr.io/cirruslabs/macos-sonoma-base:latest 29 | ``` 30 | 31 | ## Configuration 32 | 33 | ### `image` (`string`, required) 34 | 35 | Tart VM image to use. 36 | 37 | ### `ssh_username` (`string`, optional) 38 | 39 | Username to use when connecting to the VM via SSH. 40 | 41 | Defaults to `admin`. 42 | 43 | ### `ssh_password` (`string`, optional) 44 | 45 | Password to use when connecting to the VM via SSH. 46 | 47 | Defaults to `admin`. 48 | 49 | ### `headless` (`boolean`, optional) 50 | 51 | Whether to run the VM in headless mode (`true`) or with GUI (`false`). 52 | 53 | Defaults to `true`. 54 | 55 | ### `always_pull` (`boolean`, optional) 56 | 57 | Whether to always pull the VM using `tart pull` before `tart clone` (`true`) or not (`false`). 58 | 59 | Defaults to `true`. 60 | 61 | ### `softnet` (`boolean`, optional) 62 | 63 | Whether to enable [software networking isolation for Tart](https://github.com/cirruslabs/softnet) (`true`) or not (`false`). 64 | 65 | Defaults to `false`. 66 | --------------------------------------------------------------------------------