Compare commits

...
33 Commits
Author SHA1 Message Date
Nikolay Edigaryev a9f16e07e6 Provide a default when stdinpass variable is not set 2025-02-11 23:03:01 +01:00
Nikolay Edigaryev 998bbf8ca8 Parse available updates to avoid upgrading to the next macOS version (#208)
* Parse available updates to avoid upgrading to the next macOS version

* Do not override ANSIBLE_CONFIG with our ansible.cfg

Otherwise Packer + Ansible integration goes haywire.

Instead, only modify the required variables through ansible_env_vars.

* Support Monterey
2025-02-12 01:45:40 +04:00
Nikolay Edigaryev 5a55351c81 Use xargs fix for all vanilla images, not just Sequoia (#207) 2025-02-06 18:55:36 +04:00
Nikolay Edigaryev 64b1190f65 Only pass a single item to "softwareupdate --install" each time (#206) 2025-02-06 17:39:40 +04:00
Nikolay Edigaryev 4df29efc66 Run "softwareupdate" on vanilla images (#204)
* Run "softwareupdate" on vanilla images

* Install Command Line Tools for Xcode

* Run Ansible after password-less sudo is configured

* Don't use SFTP

* Fix Ansible playbook path

* No updates are available → No new software available

* stderr_lines → stderr

* Dynamically resolve MACOS_NUMBER
2025-02-01 01:23:11 +04:00
Fedor Korotkov b205e70322 macOS Sequoia 15.3 (#205) 2025-01-27 14:38:08 -05:00
Nikolay Edigaryev c18ef9c553 Use Slack workflows (#201)
* Use Slack workflows

* Use SLACK_WEBHOOK_URL
2025-01-14 23:47:30 +04:00
fedor cec270adb3 No software updates 2025-01-06 17:54:53 -05:00
fedor 6d14eaee8c Install recommended updates 2025-01-06 17:36:50 -05:00
Fedor Korotkov f1a9e22ed2 Fixed known host creation (#202)
`~/.ssh` should exist for `file` provisioner.
2025-01-06 14:35:10 -05:00
Fedor Korotkov 2545826772 Add github.com keys to ~/.ssh/known_hosts (#200)
* Add github.com keys to `~/.ssh/known_hosts`

* Static known hosts

* Fixed path
2025-01-06 09:54:14 -05:00
fedor 0b49ba6651 Xcode 16.2 2024-12-30 09:29:55 -05:00
jxlwqq e5474440fc Sequoia 15.2 (#199) 2024-12-28 05:31:37 -05:00
Nikolay Edigaryev 0c165a93d2 Compatibility with GitHub Actions Runner Images for /usr/local/bin (#198) 2024-12-11 19:56:48 +04:00
fedor d3ad77c873 Xcode 16.2 RC 2024-12-05 16:06:21 -05:00
Kevin M. Cox 40128d40e2 Update vanilla-sequoia.pkr.hcl (#196)
It looks like the tab sequence for the Time Zone screen changed in one of the releases after 15.0.

I've testing this key sequence manually and via a packer build and it works with macOS 15.1.1.
2024-12-05 01:27:54 +04:00
Fedor Korotkov 7920f0cda2 Include Xcode 15.1 in Somoma runner (#197)
We unintentionally pushed Xcode 16.1 variant for `sonoma-xcode` image. We plan to only include new versions of Xcode with Sequoia images.

Instead for removing the 16.1 artifact. Let's include it in the runner image for consistency.
2024-12-04 16:08:58 -05:00
Fedor Korotkov b3b4dafc83 Update cirrus.release.yml 2024-12-04 11:36:28 -05:00
fedor ae70c6052d Ignore curl failure 2024-11-26 10:18:40 -05:00
fedor 1ea5f77e35 Build Monterey 2024-11-26 09:02:31 -05:00
fedor 8392fd1b30 Xcode 16.2 Beta 3 2024-11-20 16:04:50 -05:00
Fedor Korotkov fdff7d8daf Sequoia 15.1.1 2024-11-19 22:15:26 -05:00
Michal Moczulski 6a01707630 Update Android dependencies (#195)
* Use latest stable versions of Android dependencies

* Fix link to Android command line tools
2024-11-13 09:05:09 -05:00
fedor 49718082b2 Updated disk sizes 2024-11-13 07:09:41 -05:00
Nikolay Edigaryev 5b17f4e264 Wait 30 minutes instead of 15 (#194)
Just to be sure.
2024-11-12 21:29:32 +04:00
Nikolay Edigaryev 14fb85f5b3 Disable apsd daemon and wait before shutting down (#193) 2024-11-12 21:26:35 +04:00
fedor c8a1e808b6 Xcode 16.2 Beta 2 2024-11-06 10:50:07 -05:00
Fedor Korotkov 8c1f0c213f Release Sequoia IPSW
Fixes #192
2024-11-04 13:43:48 -05:00
Fedor Korotkov 9875d24c4b Added 15.1 and 15.0.1 2024-11-03 22:37:22 -05:00
fedor 8425f62a71 Update one runner image at a time
So while the second one is building runners can download the first one.
2024-11-02 09:49:05 -04:00
fedor 7ebaf88c48 Include {15.1,15.0.1} into runner 2024-11-01 11:51:50 -04:00
fedor 639b46cb2f Update sonoma-xcode:{15.1,15.0.1} 2024-11-01 11:26:11 -04:00
fedor 77cc104d6d Updated release cadence to highlight supported Xcode version. 2024-10-31 15:55:48 -04:00
17 changed files with 472 additions and 46 deletions
-2
View File
@@ -1,8 +1,6 @@
task: task:
name: "Release Xcode $CIRRUS_TAG ($MACOS_VERSION)" name: "Release Xcode $CIRRUS_TAG ($MACOS_VERSION)"
matrix: matrix:
- env:
MACOS_VERSION: sonoma
- env: - env:
MACOS_VERSION: sequoia MACOS_VERSION: sequoia
<<: *defaults <<: *defaults
+6 -3
View File
@@ -1,17 +1,20 @@
task: task:
name: "Update Runner Image ($MACOS_VERSION)" name: "Update Runner Image ($MACOS_VERSION)"
execution_lock: runner-image-update
env: env:
matrix: matrix:
- MACOS_VERSION: sonoma - MACOS_VERSION: sonoma
XCODE_VERSIONS: 16,15.4,15.3,15.2 XCODE_VERSIONS: "16.1,16,15.4,15.3,15.2,15.1,\"15.0.1\""
DISK_SIZE: 375
- MACOS_VERSION: sequoia - MACOS_VERSION: sequoia
XCODE_VERSIONS: "16.1,\"16.2-beta-1\",16,15.4" XCODE_VERSIONS: "16.2,16.1,16,15.4"
DISK_SIZE: 320
<<: *defaults <<: *defaults
pull_base_script: pull_base_script:
- tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest
init_xcode_script: packer init templates/xcode.pkr.hcl init_xcode_script: packer init templates/xcode.pkr.hcl
build_xcode_script: | build_xcode_script: |
packer build -var tag=runner -var disk_size=300 \ packer build -var tag=runner -var disk_size=$DISK_SIZE \
-var disk_free_mb=100000 \ -var disk_free_mb=100000 \
-var macos_version="$MACOS_VERSION" \ -var macos_version="$MACOS_VERSION" \
-var xcode_version="[$XCODE_VERSIONS]" \ -var xcode_version="[$XCODE_VERSIONS]" \
+22 -21
View File
@@ -1,29 +1,30 @@
task: env:
name: "Update Vanilla Sonoma Image" RESOLVE_VM_BASE_NAME: "ghcr.io/cirruslabs/macos-${MACOS_VERSION}-vanilla:latest"
only_if: $CIRRUS_BRANCH == $CIRRUS_DEFAULT_BRANCH && changesInclude("templates/vanilla-sonoma.pkr.hcl") RESOLVE_VM_NAME: "resolve-macos-number-task-id-${CIRRUS_TASK_ID}"
<<: *defaults RESOLVE_FILE: "${RESOLVE_VM_NAME}.txt"
build_script:
- packer init templates/vanilla-sonoma.pkr.hcl
- packer build templates/vanilla-sonoma.pkr.hcl
disable_sip_script:
- packer build -var vm_name=sonoma-vanilla templates/disable-sip.pkr.hcl
push_script:
- tart push sonoma-vanilla ghcr.io/cirruslabs/macos-sonoma-vanilla:latest ghcr.io/cirruslabs/macos-sonoma-vanilla:14.6
always:
cleanup_script:
- tart delete sonoma-vanilla
task: task:
name: "Update Vanilla Sequoia Image" name: "Update Vanilla Image ($MACOS_VERSION)"
only_if: $CIRRUS_BRANCH == $CIRRUS_DEFAULT_BRANCH && changesInclude("templates/vanilla-sequoia.pkr.hcl") env:
matrix:
- MACOS_VERSION: sequoia
- MACOS_VERSION: sonoma
- MACOS_VERSION: ventura
- MACOS_VERSION: monterey
only_if: $CIRRUS_BRANCH == $CIRRUS_DEFAULT_BRANCH && changesInclude("templates/vanilla-$MACOS_VERSION.pkr.hcl")
<<: *defaults <<: *defaults
build_script: build_script:
- packer init templates/vanilla-sequoia.pkr.hcl - packer init templates/vanilla-$MACOS_VERSION.pkr.hcl
- packer build templates/vanilla-sequoia.pkr.hcl - packer build templates/vanilla-$MACOS_VERSION.pkr.hcl
disable_sip_script: disable_sip_script:
- packer build -var vm_name=sequoia-vanilla templates/disable-sip.pkr.hcl - packer build -var vm_name=$MACOS_VERSION-vanilla templates/disable-sip.pkr.hcl
resolve_macos_number_script:
- packer build -var vm_base_name=$RESOLVE_VM_BASE_NAME -var vm_name=$RESOLVE_VM_NAME -var resolve_file=$RESOLVE_FILE templates/resolve-macos-number.pkr.hcl
- echo "MACOS_NUMBER=$(cat $RESOLVE_FILE)" >> $CIRRUS_ENV
- rm $RESOLVE_FILE
- tart delete $RESOLVE_VM_NAME
push_script: push_script:
- tart push sequoia-vanilla ghcr.io/cirruslabs/macos-sequoia-vanilla:latest ghcr.io/cirruslabs/macos-sequoia-vanilla:15.1 - tart push $MACOS_VERSION-vanilla ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:$MACOS_NUMBER
always: always:
cleanup_script: cleanup_script:
- tart delete sequoia-vanilla - tart delete $MACOS_VERSION-vanilla
+12 -2
View File
@@ -4,19 +4,29 @@ task:
env: env:
matrix: matrix:
- MACOS_VERSION: sequoia - MACOS_VERSION: sequoia
XCODE_VERSION: 16.1 XCODE_VERSION: 16.2
LATEST: true LATEST: true
- MACOS_VERSION: sequoia
XCODE_VERSION: 16.1
- MACOS_VERSION: sequoia - MACOS_VERSION: sequoia
XCODE_VERSION: 16 XCODE_VERSION: 16
- MACOS_VERSION: sequoia
XCODE_VERSION: 15.4
- MACOS_VERSION: sonoma
XCODE_VERSION: 16.1
LATEST: true
- MACOS_VERSION: sonoma - MACOS_VERSION: sonoma
XCODE_VERSION: 16 XCODE_VERSION: 16
LATEST: true
- MACOS_VERSION: sonoma - MACOS_VERSION: sonoma
XCODE_VERSION: 15.4 XCODE_VERSION: 15.4
- MACOS_VERSION: sonoma - MACOS_VERSION: sonoma
XCODE_VERSION: 15.3 XCODE_VERSION: 15.3
- MACOS_VERSION: sonoma - MACOS_VERSION: sonoma
XCODE_VERSION: 15.2 XCODE_VERSION: 15.2
- MACOS_VERSION: sonoma
XCODE_VERSION: 15.1
- MACOS_VERSION: sonoma
XCODE_VERSION: 15.0.1
<<: *defaults <<: *defaults
pull_base_script: pull_base_script:
- tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest
+10 -6
View File
@@ -16,14 +16,18 @@ def on_build_failed(ctx):
if "Cron" not in ctx.payload.data.build.changeMessageTitle: if "Cron" not in ctx.payload.data.build.changeMessageTitle:
return return
resp = http.post("https://slack.com/api/chat.postMessage", headers={ resp = http.post(env.get("SLACK_WEBHOOK_URL"), headers={
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": "Bearer " + env.get("SLACK_TOKEN"),
}, json_body={ }, json_body={
"channel": "#image-updates", "text": "Build {build_id} (\"{change_message_title}\") failed on branch \"{branch_name}\" in repository \"{repository_name}\".".format(
"text": "Build <https://cirrus-ci.com/build/{build_id}|{build_id} (\"{change_message_title}\")> failed on branch \"{branch_name}\" in repository \"{repository_name}\".".format( build_id=ctx.payload.data.build.id,
build_id=ctx.payload.data.build.id, change_message_title=ctx.payload.data.build.changeMessageTitle, change_message_title=ctx.payload.data.build.changeMessageTitle,
branch_name=ctx.payload.data.build.branch, repository_name=ctx.payload.data.repository.name), branch_name=ctx.payload.data.build.branch,
repository_name=ctx.payload.data.repository.name,
),
"url": "https://cirrus-ci.com/build/{build_id}".format(
build_id=ctx.payload.data.build.id,
),
}) })
if resp.status_code != 200: if resp.status_code != 200:
+8 -6
View File
@@ -7,15 +7,17 @@ The following image variants are currently available:
* `macos-{sequoia,sonoma}-base` image has only `brew` pre-installed and the latest version of `macOS` available * `macos-{sequoia,sonoma}-base` image has only `brew` pre-installed and the latest version of `macOS` available
* `macos-{sequoia,sonoma}-xcode:N` image is based on `macos-{sequoia,sonoma}-base` image and has `Xcode N` with [`Flutter`](https://flutter.dev/) pre-installed * `macos-{sequoia,sonoma}-xcode:N` image is based on `macos-{sequoia,sonoma}-base` image and has `Xcode N` with [`Flutter`](https://flutter.dev/) pre-installed
* `macos-runner:sonoma` image is a variant of `xcode:N` with 3 latest versions of `Xcode` pre-installed and [`xcodes` tool](https://github.com/XcodesOrg/xcodes) to switch between them. * `macos-runner:{sequoia,sonoma}` image is a variant of `xcode:N` with several versions of `Xcode` pre-installed and [`xcodes` tool](https://github.com/XcodesOrg/xcodes) to switch between them.
See a full list of VMs available [here](https://github.com/orgs/cirruslabs/packages?tab=packages&q=macos-). See a full list of VMs available [here](https://github.com/orgs/cirruslabs/packages?tab=packages&q=macos-).
## Release Cadence ## Release Cadence
Once a new version of Xcode is released, we will initiate a GitHub release which will automatically build and push Once a new version of Xcode is released, we will initiate a GitHub release which will automatically build and push
a new version of the `macos-{sequoia,sonoma}-xcode:N` image as well as `macos-runner:sonoma`. This generally happens within 24 hours a new version of the `macos-sequoia-xcode:N`. This generally happens within 24 hours of a release.
of a release. Please watch this repository releases to get notified about new images. Please watch this repository releases to get notified about new images.
For an Xcode release which is non beta and not an RC `ghcr.io/cirruslabs/macos-runner:sequoia` image will also be updated.
## Update Cadence ## Update Cadence
@@ -23,8 +25,8 @@ Some of the images are regularly getting rebuild in order to update the pre-inst
monthly on the first Saturday of the month: monthly on the first Saturday of the month:
* `ghcr.io/cirruslabs/macos-{sequoia,sonoma}-base` * `ghcr.io/cirruslabs/macos-{sequoia,sonoma}-base`
* `ghcr.io/cirruslabs/macos-sonoma-xcode:{16-beta,latest,15.4,15.3,15.2}` * `ghcr.io/cirruslabs/macos-runner:sonoma` which is a superset of `ghcr.io/cirruslabs/macos-sonoma-xcode:{latest,16.1,16,15.4,15.3,15.2,15.1,15.0.1}`
* `ghcr.io/cirruslabs/macos-sequoia-xcode:{16-beta}` * `ghcr.io/cirruslabs/macos-runner:sequoia` which is a superset of `ghcr.io/cirruslabs/macos-sequoia-xcode:{latest,16.2,16.1,16,15.4}`
Note that `ghcr.io/cirruslabs/macos-runner:sonoma` is updated every Sunday and this image is [optimised for startup](https://cirrus-runners.app/blog/2024/04/11/optimizing-startup-time-of-cirrus-runners/) Note that `ghcr.io/cirruslabs/macos-runner:{sequoia,sonoma}` are updated every Sunday and these images are [optimised for startup](https://cirrus-runners.app/blog/2024/04/11/optimizing-startup-time-of-cirrus-runners/)
on Cirrus Runners and Cirrus CI services. on Cirrus Runners and Cirrus CI services.
+5
View File
@@ -0,0 +1,5 @@
- hosts: default
roles:
- system-updater
vars:
ansible_password: admin
@@ -0,0 +1,37 @@
- name: Perform first "softwareupdate" invocation
include_tasks: softwareupdate.yml
# Needed after a major macOS update, otherwise things like
# Command Line Tools won't be updated
- name: Perform second "softwareupdate" invocation
include_tasks: softwareupdate.yml
# This one looks weird, but unfortunately there's no other way around, because Homebrew
# is not designed to run as root (see https://gist.github.com/irazasyed/7732946
# for more details).
- name: fix up /usr/local permissions for Homebrew
file:
path: /usr/local/share/man
state: directory
owner: "{{ ansible_user_id }}"
recurse: yes
become: yes
- name: "ensure that there are no more software updates available: check for available updates"
command:
cmd: "softwareupdate --all --list"
register: software_updates_result
- name: "ensure that there are no more software updates available: parse available updates"
set_fact:
software_updates: "{{ software_updates_result.stdout | regex_findall('\\* Label: (.*)\\n\\tTitle: (.*), Version: (.*), Size: (.*), Recommended: (.*), Action: (.*), .*') | map('zip', ['label', 'title', 'version', 'size', 'recommended', 'action']) | map('map', 'reverse') | map('community.general.dict') }}"
- name: "ensure that there are no more software updates available: print available updates"
debug:
var: software_updates
- name: "ensure that there are no more software updates available: fail if some updates were not installed"
fail:
msg: "Found unapplied update: {{ item.label }}"
loop: "{{ software_updates }}"
when: "not item.label.startswith('macOS') or item.version.split('.')[0] == ansible_facts['distribution_version'].split('.')[0]"
@@ -0,0 +1,43 @@
- name: check for available updates
command:
cmd: "softwareupdate --all --list"
register: software_updates_result
- name: parse available updates
set_fact:
software_updates: "{{ software_updates_result.stdout | regex_findall('\\* Label: (.*)\\n\\tTitle: (.*), Version: (.*), Size: (.*), Recommended: (.*), Action: (.*), .*') | map('zip', ['label', 'title', 'version', 'size', 'recommended', 'action']) | map('map', 'reverse') | map('community.general.dict') }}"
- name: print available updates
debug:
var: software_updates
# It seems that we must always pass "--restart" command-line argument to "softwareupdate",
# otherwise on the OS update the "softwareupdate" will be stuck at "Downloaded: macOS [...]"
- name: install available update
command:
cmd: "softwareupdate --install --agree-to-license --force --restart --user admin --stdinpass {{ stdinpass | default("") }} '{{ item.label }}'"
stdin: "{{ ansible_password }}"
register: update_result
# Work around the following:
# > Data could not be sent to remote host [...].
# > Make sure this host can be reached over ssh:
# > ssh: connect to host [...] port 22: Connection refused.
ignore_unreachable: yes
# Ignore SIGTERM/SIGKILL sent "softwareupdate" process
# when the system reboots due to --restart
failed_when: update_result.rc not in [0, 9, -9, 15, -15]
become: yes
loop: "{{ software_updates }}"
when: "not item.label.startswith('macOS') or item.version.split('.')[0] == ansible_facts['distribution_version'].split('.')[0]"
# Wait for the connection since the previous command could restart the host
- name: wait for connection
wait_for_connection:
# We need to wait long enough for the "softwareupdate" to initiate the reboot,
# otherwise it's possible that we'll interrupt the process by running
# the commands below on a non-restarted system.
delay: 60
timeout: 1800
when:
- update_result is defined
- not update_result.skipped
+3
View File
@@ -0,0 +1,3 @@
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
+22 -2
View File
@@ -56,16 +56,34 @@ build {
"echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> ~/.zprofile", "echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> ~/.zprofile",
"echo \"export HOMEBREW_NO_AUTO_UPDATE=1\" >> ~/.zprofile", "echo \"export HOMEBREW_NO_AUTO_UPDATE=1\" >> ~/.zprofile",
"echo \"export HOMEBREW_NO_INSTALL_CLEANUP=1\" >> ~/.zprofile", "echo \"export HOMEBREW_NO_INSTALL_CLEANUP=1\" >> ~/.zprofile",
]
}
provisioner "shell" {
inline = [
"source ~/.zprofile", "source ~/.zprofile",
"brew --version", "brew --version",
"brew update", "brew update",
"brew install curl wget unzip zip ca-certificates cmake gcc git-lfs jq yq gh gitlab-runner", "brew install wget unzip zip ca-certificates cmake gcc git-lfs jq yq gh gitlab-runner",
"brew install curl || true", // doesn't work on Monterey
"brew install --cask git-credential-manager", "brew install --cask git-credential-manager",
"git lfs install", "git lfs install",
"sudo softwareupdate --install-rosetta --agree-to-license" "sudo softwareupdate --install-rosetta --agree-to-license"
] ]
} }
// Add GitHub to known hosts
// Similar to https://github.com/actions/runner-images/blob/main/images/macos/scripts/build/configure-ssh.sh
provisioner "shell" {
inline = [
"mkdir -p ~/.ssh"
]
}
provisioner "file" {
source = "data/github_known_hosts"
destination = "~/.ssh/known_hosts"
}
// Install the GitHub Actions runner // Install the GitHub Actions runner
provisioner "shell" { provisioner "shell" {
script = "scripts/install-actions-runner.sh" script = "scripts/install-actions-runner.sh"
@@ -126,7 +144,9 @@ build {
provisioner "shell" { provisioner "shell" {
inline = [ inline = [
"source ~/.zprofile", "source ~/.zprofile",
"test -d /Users/runner" "test -d /Users/runner",
"test -f ~/.ssh/known_hosts",
"brew doctor"
] ]
} }
} }
+46
View File
@@ -0,0 +1,46 @@
packer {
required_plugins {
tart = {
version = ">= 1.12.0"
source = "github.com/cirruslabs/tart"
}
}
}
variable "vm_base_name" {
type = string
}
variable "vm_name" {
type = string
}
variable "resolve_file" {
type = string
}
source "tart-cli" "tart" {
vm_base_name = "${var.vm_base_name}"
vm_name = "${var.vm_name}"
cpu_count = 4
memory_gb = 8
ssh_password = "admin"
ssh_username = "admin"
ssh_timeout = "120s"
}
build {
sources = ["source.tart-cli.tart"]
provisioner "shell" {
inline = [
"sw_vers --productVersion > /tmp/sw-vers-product-version.txt",
]
}
provisioner "file" {
source = "/tmp/sw-vers-product-version.txt"
destination = "${var.resolve_file}"
direction = "download"
}
}
+147
View File
@@ -0,0 +1,147 @@
packer {
required_plugins {
tart = {
version = ">= 1.2.0"
source = "github.com/cirruslabs/tart"
}
ansible = {
version = "~> 1"
source = "github.com/hashicorp/ansible"
}
}
}
source "tart-cli" "tart" {
# You can find macOS IPSW URLs on various websites like https://ipsw.me/
from_ipsw = "https://updates.cdn-apple.com/2022FallFCS/fullrestores/012-66032/8D8D90C6-A876-4FFF-BBF4-D158939B3841/UniversalMac_12.6.1_21G217_Restore.ipsw"
vm_name = "monterey-vanilla"
cpu_count = 4
memory_gb = 8
disk_size_gb = 40
ssh_password = "admin"
ssh_username = "admin"
ssh_timeout = "120s"
boot_command = [
# hello, hola, bonjour, etc.
"<wait60s><spacebar>",
# Language: most of the times we have a list of "English"[1], "English (UK)", etc. with
# "English" language already selected. If we type "english", it'll cause us to switch
# to the "English (UK)", which is not what we want. To solve this, we switch to some other
# language first, e.g. "Italiano" and then switch back to "English". We'll then jump to the
# first entry in a list of "english"-prefixed items, which will be "English".
#
# [1]: should be named "English (US)", but oh well 🤷
"<wait30s>italiano<esc>english<enter>",
# Select Your Country and Region
"<wait30s>united states<leftShiftOn><tab><leftShiftOff><spacebar>",
# Written and Spoken Languages
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Accessibility
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Data & Privacy
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Migration Assistant
"<wait10s><tab><tab><tab><spacebar>",
# Sign In with Your Apple ID
"<wait10s><leftShiftOn><tab><leftShiftOff><leftShiftOn><tab><leftShiftOff><spacebar>",
# Are you sure you want to skip signing in with an Apple ID?
"<wait10s><tab><spacebar>",
# Terms and Conditions
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# I have read and agree to the macOS Software License Agreement
"<wait10s><tab><spacebar>",
# Create a Computer Account
"<wait10s>admin<tab><tab>admin<tab>admin<tab><tab><tab><spacebar>",
# Enable Location Services
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Are you sure you don't want to use Location Services?
"<wait10s><tab><spacebar>",
# Select Your Time Zone
"<wait10s><tab>UTC<enter><leftShiftOn><tab><leftShiftOff><spacebar>",
# Analytics
"<wait10s><tab><spacebar><leftShiftOn><tab><leftShiftOff><spacebar>",
# Screen Time
"<wait10s><tab><spacebar>",
# Siri
"<wait10s><tab><spacebar><leftShiftOn><tab><leftShiftOff><spacebar>",
# Choose Your Look
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Enable Voice Over
"<wait10s><leftAltOn><f5><leftAltOff><wait5s>v",
# Now that the installation is done, open "System Preferences"
"<wait10s><leftAltOn><spacebar><leftAltOff>System Preferences<enter>",
# Navigate to "Sharing"
"<wait10s>sharing<enter>",
# Enable Screen Sharing
"<wait10s><tab><tab><tab><tab><spacebar>",
# Enable Remote Login
"<wait10s><down><down><down><down><spacebar><tab><tab><spacebar>",
# Disable Voice Over
"<leftAltOn><f5><leftAltOff>",
]
// A (hopefully) temporary workaround for Virtualization.Framework's
// installation process not fully finishing in a timely manner
create_grace_time = "30s"
// Keep the recovery partition, otherwise it's not possible to "softwareupdate"
recovery_partition = "keep"
}
build {
sources = ["source.tart-cli.tart"]
provisioner "shell" {
inline = [
// Enable passwordless sudo
"echo admin | sudo -S sh -c \"echo 'admin ALL=(ALL) NOPASSWD: ALL' | EDITOR=tee visudo /etc/sudoers.d/admin-nopasswd\"",
// Enable auto-login
//
// See https://github.com/xfreebird/kcpassword for details.
"echo '00000000: 1ced 3f4a bcbc ba2c caca 4e82' | sudo xxd -r - /etc/kcpassword",
"sudo defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser admin",
// Disable screensaver at login screen
"sudo defaults write /Library/Preferences/com.apple.screensaver loginWindowIdleTime 0",
// Disable screensaver for admin user
"defaults -currentHost write com.apple.screensaver idleTime 0",
// Prevent the VM from sleeping
"sudo systemsetup -setdisplaysleep Off 2>/dev/null",
"sudo systemsetup -setsleep Off 2>/dev/null",
"sudo systemsetup -setcomputersleep Off 2>/dev/null",
// Launch Safari to populate the defaults
"/Applications/Safari.app/Contents/MacOS/Safari &",
"SAFARI_PID=$!",
"disown",
"sleep 30",
"kill -9 $SAFARI_PID",
// Enable Safari's remote automation
"sudo safaridriver --enable",
// Disable screen lock
//
// Note that this only works if the user is logged-in,
// i.e. not on login screen.
"sysadminctl -screenLock off -password admin",
]
}
provisioner "shell" {
inline = [
# Install command-line tools
"touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
"softwareupdate --list | sed -n 's/.*Label: \\(Command Line Tools for Xcode-.*\\)/\\1/p' | xargs -I {} softwareupdate --install '{}'",
"rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
]
}
provisioner "ansible" {
playbook_file = "ansible/playbook-system-updater.yml"
extra_arguments = [
"--extra-vars", "stdinpass=admin",
]
ansible_env_vars = [
"ANSIBLE_TRANSPORT=paramiko",
"ANSIBLE_HOST_KEY_CHECKING=False",
]
use_proxy = false
}
}
+27 -2
View File
@@ -4,11 +4,15 @@ packer {
version = ">= 1.12.0" version = ">= 1.12.0"
source = "github.com/cirruslabs/tart" source = "github.com/cirruslabs/tart"
} }
ansible = {
version = "~> 1"
source = "github.com/hashicorp/ansible"
}
} }
} }
source "tart-cli" "tart" { source "tart-cli" "tart" {
from_ipsw = "https://updates.cdn-apple.com/2024FallFCS/fullrestores/072-12340/78D28AC4-CCFC-45D2-BD27-1E5D915E43F9/UniversalMac_15.1_24B83_Restore.ipsw" from_ipsw = "https://updates.cdn-apple.com/2025WinterFCS/fullrestores/072-08269/7CAAB9F7-E970-428D-8764-4CD7BCD105CD/UniversalMac_15.3_24D60_Restore.ipsw"
vm_name = "sequoia-vanilla" vm_name = "sequoia-vanilla"
cpu_count = 4 cpu_count = 4
memory_gb = 8 memory_gb = 8
@@ -52,7 +56,7 @@ source "tart-cli" "tart" {
# Are you sure you don't want to use Location Services? # Are you sure you don't want to use Location Services?
"<wait10s><tab><spacebar>", "<wait10s><tab><spacebar>",
# Select Your Time Zone # Select Your Time Zone
"<wait10s><tab>UTC<enter><leftShiftOn><tab><leftShiftOff><spacebar>", "<wait10s><tab><tab>UTC<enter><leftShiftOn><tab><tab><leftShiftOff><spacebar>",
# Analytics # Analytics
"<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>", "<wait10s><leftShiftOn><tab><leftShiftOff><spacebar>",
# Screen Time # Screen Time
@@ -83,6 +87,9 @@ source "tart-cli" "tart" {
// A (hopefully) temporary workaround for Virtualization.Framework's // A (hopefully) temporary workaround for Virtualization.Framework's
// installation process not fully finishing in a timely manner // installation process not fully finishing in a timely manner
create_grace_time = "30s" create_grace_time = "30s"
// Keep the recovery partition, otherwise it's not possible to "softwareupdate"
recovery_partition = "keep"
} }
build { build {
@@ -118,4 +125,22 @@ build {
"sysadminctl -screenLock off -password admin", "sysadminctl -screenLock off -password admin",
] ]
} }
provisioner "shell" {
inline = [
# Install command-line tools
"touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
"softwareupdate --list | sed -n 's/.*Label: \\(Command Line Tools for Xcode-.*\\)/\\1/p' | xargs -I {} softwareupdate --install '{}'",
"rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
]
}
provisioner "ansible" {
playbook_file = "ansible/playbook-system-updater.yml"
ansible_env_vars = [
"ANSIBLE_TRANSPORT=paramiko",
"ANSIBLE_HOST_KEY_CHECKING=False",
]
use_proxy = false
}
} }
+25
View File
@@ -4,6 +4,10 @@ packer {
version = ">= 1.12.0" version = ">= 1.12.0"
source = "github.com/cirruslabs/tart" source = "github.com/cirruslabs/tart"
} }
ansible = {
version = "~> 1"
source = "github.com/hashicorp/ansible"
}
} }
} }
@@ -78,6 +82,9 @@ source "tart-cli" "tart" {
// A (hopefully) temporary workaround for Virtualization.Framework's // A (hopefully) temporary workaround for Virtualization.Framework's
// installation process not fully finishing in a timely manner // installation process not fully finishing in a timely manner
create_grace_time = "30s" create_grace_time = "30s"
// Keep the recovery partition, otherwise it's not possible to "softwareupdate"
recovery_partition = "keep"
} }
build { build {
@@ -115,4 +122,22 @@ build {
"sysadminctl -screenLock off -password admin", "sysadminctl -screenLock off -password admin",
] ]
} }
provisioner "shell" {
inline = [
# Install command-line tools
"touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
"softwareupdate --list | sed -n 's/.*Label: \\(Command Line Tools for Xcode-.*\\)/\\1/p' | xargs -I {} softwareupdate --install '{}'",
"rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
]
}
provisioner "ansible" {
playbook_file = "ansible/playbook-system-updater.yml"
ansible_env_vars = [
"ANSIBLE_TRANSPORT=paramiko",
"ANSIBLE_HOST_KEY_CHECKING=False",
]
use_proxy = false
}
} }
+25
View File
@@ -4,6 +4,10 @@ packer {
version = ">= 1.12.0" version = ">= 1.12.0"
source = "github.com/cirruslabs/tart" source = "github.com/cirruslabs/tart"
} }
ansible = {
version = "~> 1"
source = "github.com/hashicorp/ansible"
}
} }
} }
@@ -86,6 +90,9 @@ source "tart-cli" "tart" {
// A (hopefully) temporary workaround for Virtualization.Framework's // A (hopefully) temporary workaround for Virtualization.Framework's
// installation process not fully finishing in a timely manner // installation process not fully finishing in a timely manner
create_grace_time = "30s" create_grace_time = "30s"
// Keep the recovery partition, otherwise it's not possible to "softwareupdate"
recovery_partition = "keep"
} }
build { build {
@@ -124,4 +131,22 @@ build {
"defaults -currentHost write com.apple.screensaver idleTime 0" "defaults -currentHost write com.apple.screensaver idleTime 0"
] ]
} }
provisioner "shell" {
inline = [
# Install command-line tools
"touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
"softwareupdate --list | sed -n 's/.*Label: \\(Command Line Tools for Xcode-.*\\)/\\1/p' | xargs -I {} softwareupdate --install '{}'",
"rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress",
]
}
provisioner "ansible" {
playbook_file = "ansible/playbook-system-updater.yml"
ansible_env_vars = [
"ANSIBLE_TRANSPORT=paramiko",
"ANSIBLE_HOST_KEY_CHECKING=False",
]
use_proxy = false
}
} }
+34 -2
View File
@@ -37,7 +37,7 @@ variable "disk_free_mb" {
variable "android_sdk_tools_version" { variable "android_sdk_tools_version" {
type = string type = string
default = "11076708" # https://developer.android.com/studio/#command-tools default = "11076708" # https://developer.android.com/studio#command-line-tools-only
} }
source "tart-cli" "tart" { source "tart-cli" "tart" {
@@ -112,7 +112,7 @@ build {
"rm android-sdk-tools.zip", "rm android-sdk-tools.zip",
"mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest", "mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest",
"yes | sdkmanager --licenses", "yes | sdkmanager --licenses",
"yes | sdkmanager 'platform-tools' 'platforms;android-33' 'build-tools;34.0.0' 'ndk;25.2.9519653'" "yes | sdkmanager 'platform-tools' 'platforms;android-35' 'build-tools;35.0.0' 'ndk;27.2.12479018'"
] ]
} }
@@ -229,4 +229,36 @@ build {
"test -d /Users/runner" "test -d /Users/runner"
] ]
} }
# Disable apsd[1][2] daemon as it causes high CPU usage after boot
#
# [1]: https://iboysoft.com/wiki/apsd-mac.html
# [2]: https://discussions.apple.com/thread/4459153
provisioner "shell" {
inline = [
"sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist"
]
}
# Compatibility with GitHub Actions Runner Images, where
# /usr/local/bin belongs to the default user. Also see [2].
#
# [1]: https://github.com/actions/runner-images/blob/6bbddd20d76d61606bea5a0133c950cc44c370d3/images/macos/scripts/build/configure-machine.sh#L96
# [2]: https://github.com/actions/runner-images/discussions/7607
provisioner "shell" {
inline = [
"sudo chown admin /usr/local/bin"
]
}
# Wait for the "update_dyld_sim_shared_cache" process[1][2] to finish
# to avoid wasting CPU cycles after boot
#
# [1]: https://apple.stackexchange.com/questions/412101/update-dyld-sim-shared-cache-is-taking-up-a-lot-of-memory
# [2]: https://stackoverflow.com/a/68394101/9316533
provisioner "shell" {
inline = [
"sleep 1800"
]
}
} }