Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
theoriginalgri committed Oct 3, 2022
0 parents commit e5da9b5
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 0 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Run GitLab Runner jobs with macOS virtualization

## What is this?
A set of configuration files which allows gitlab-runner to make use of the macOS virtualization framework.
Under the hood, these scripts use the [tart](https://github.com/cirruslabs/tart) commandline tool to provision VMs for jobs.
The macOS virtualization framework allows running two macOS virtual machines in parallel.

## Installation
Clone this repository onto your build machine and register a `custom` gitlab-runner to your instance.
You need to adjust the paths in `prepare_exec`, `run_exec` and `cleanup_exec` which can also be found in `gitlab-runner-example-config.toml`.

Install dependencies: `brew install gitlab-runner daemonize tart`.

## Configurations
- `TART_IMAGE`: Choose a different tart image, e.g. from https://github.com/orgs/cirruslabs/packages?tab=packages&q=macos. The current default is `ghcr.io/cirruslabs/macos-monterey-xcode:14`.
18 changes: 18 additions & 0 deletions base.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

VM_ID="runner-$CUSTOM_ENV_CI_RUNNER_ID-project-$CUSTOM_ENV_CI_PROJECT_ID-concurrent-$CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID-job-$CUSTOM_ENV_CI_JOB_ID"
VM_IMAGE="${CUSTOM_ENV_TART_IMAGE:-ghcr.io/cirruslabs/macos-monterey-xcode:14}"
VM_USER="admin"
VM_PASSWORD="admin"

_get_vm_ip() {
tart ip "$VM_ID" --wait 30 || true
}

_get_vm_pid() {
ps -A | grep -m1 "tart run $VM_ID" | awk '{print $1}'
}

_ssh() {
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$VM_USER"@"$VM_IP" "/bin/zsh --login -c '$@'" >/dev/null
}
13 changes: 13 additions & 0 deletions cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # Get variables from base script.

set -o pipefail

# Destroy VM.
VM_PID=$(_get_vm_pid)
kill $VM_PID || true

# Delete VM disk.
tart delete "$VM_ID"
24 changes: 24 additions & 0 deletions gitlab-runner-example-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
concurrent = 2
check_interval = 0

[session_server]
session_timeout = 1800

[[runners]]
name = "tart-driver"
url = "https://gitlab.com/"
id = 123
token = "asdf"
token_obtained_at = 2022-10-03T10:27:18Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "custom"
builds_dir = "/Users/admin/builds"
cache_dir = "/Users/admin/cache"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.custom]
prepare_exec = "/Users/ci/gitlab-runner-tart/prepare.sh"
run_exec = "/Users/ci/gitlab-runner-tart/run.sh"
cleanup_exec = "/Users/ci/gitlab-runner-tart/cleanup.sh"
19 changes: 19 additions & 0 deletions install-ssh-key.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/expect -f
lassign $argv IPSrv Login Passwd

set timeout 10

spawn ssh-copy-id -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=1s $Login@$IPSrv

expect {
-re ".*assword:.*" {
send "$Passwd\r"
exp_continue
}

-re ".*ERROR:.*" {
exit 4
}

eof {}
}
54 changes: 54 additions & 0 deletions prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env bash

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # Get variables from base script.

set -eo pipefail

# trap any error, and mark it as a system failure.
trap "exit $SYSTEM_FAILURE_EXIT_CODE" ERR

# Install the VM
tart clone "$VM_IMAGE" "$VM_ID"

# Update VM configuration
tart set "$VM_ID" --cpu 4 --memory 8192

# Run the VM in background
daemonize $(brew --prefix)/bin/tart run "$VM_ID" --no-graphics

# Wait for VM to get IP
echo 'Waiting for VM to get IP'
VM_IP=$(_get_vm_ip)

if [ -n "$VM_IP" ]; then
echo "VM got IP: $VM_IP"
else
echo 'Waited 30 seconds for VM to start, exiting...'
# Inform GitLab Runner that this is a system failure, so it
# should be retried.
exit "$SYSTEM_FAILURE_EXIT_CODE"
fi

# Wait for ssh to become available
echo "Waiting for sshd to be available"
for i in $(seq 1 30); do
if ${currentDir}/install-ssh-key.sh "$VM_IP" "$VM_USER" "$VM_PASSWORD" >/dev/null 2>/dev/null; then
break
fi

if [ "$i" == "30" ]; then
echo 'Waited 30 seconds for sshd to start, exiting...'
# Inform GitLab Runner that this is a system failure, so it
# should be retried.
exit "$SYSTEM_FAILURE_EXIT_CODE"
fi

sleep 1
done

echo "Updating hostname"
_ssh "sudo scutil --set HostName $VM_ID && sudo scutil --set ComputerName $VM_ID"

echo "Installing gitlab-runner for artifact uploads"
_ssh "brew install gitlab-runner"
13 changes: 13 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # Get variables from base script.

VM_IP=$(_get_vm_ip)

ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$VM_USER"@"$VM_IP" /bin/zsh --login < "${1}"
if [ $? -ne 0 ]; then
# Exit using the variable, to make the build as failure in GitLab
# CI.
exit "$BUILD_FAILURE_EXIT_CODE"
fi

0 comments on commit e5da9b5

Please sign in to comment.