Compare commits
16 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
d6ee41d6d5 | |
|
|
741758b9ba | |
|
|
f03344599b | |
|
|
16e9ad7d00 | |
|
|
85b77e41bc | |
|
|
9be4b9dc86 | |
|
|
46050816d8 | |
|
|
d358da6f50 | |
|
|
b4926493fb | |
|
|
c166ec1698 | |
|
|
3d6445b446 | |
|
|
f5a7e1e631 | |
|
|
0a9ad1a419 | |
|
|
cd2d1c6698 | |
|
|
65519d3874 | |
|
|
71b405bd0c |
|
|
@ -89,7 +89,8 @@ jobs:
|
|||
|
||||
release-runner:
|
||||
name: Update Runner Image (${{ matrix.macos_version }})
|
||||
needs: release-xcode
|
||||
# Keep runner refreshes independent from the release-xcode matrix so one
|
||||
# Xcode image failure does not skip the runner matrix.
|
||||
runs-on: [self-hosted, macOS, ARM64]
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
|
|
@ -104,11 +105,11 @@ jobs:
|
|||
xcode_components: '"MetalToolchain"'
|
||||
disk_size: 380
|
||||
- macos_version: tahoe
|
||||
xcode_versions: '"26.5","27-beta","26.4.1","26.3","26.2","26.1.1","26.0.1"'
|
||||
xcode_versions: '"26.6","27-beta-4","26.5","27-beta","26.4.1","26.3","26.2","26.1.1","26.0.1"'
|
||||
additional_ios_builds: "18.6"
|
||||
additional_tvos_builds: ""
|
||||
xcode_components: '"MetalToolchain"'
|
||||
disk_size: 330
|
||||
disk_size: 520
|
||||
env:
|
||||
ADDITIONAL_IOS_BUILDS: ${{ matrix.additional_ios_builds }}
|
||||
ADDITIONAL_TVOS_BUILDS: ${{ matrix.additional_tvos_builds }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,381 @@
|
|||
name: Template Builds
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/monthly.yml"
|
||||
- ".github/workflows/release.yml"
|
||||
- ".github/workflows/template-validation.yml"
|
||||
- "data/**"
|
||||
- "scripts/**"
|
||||
- "templates/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
concurrency:
|
||||
group: template-builds-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }}
|
||||
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TART_REGISTRY_HOSTNAME: ghcr.io
|
||||
TART_REGISTRY_USERNAME: ${{ github.actor }}
|
||||
TART_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
packer-validate:
|
||||
name: Packer Validate
|
||||
runs-on: macos-15
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Packer
|
||||
uses: hashicorp/setup-packer@v3
|
||||
|
||||
- name: Install validation dependencies
|
||||
run: |
|
||||
brew install ansible
|
||||
|
||||
- name: Prepare validation inputs
|
||||
run: |
|
||||
mkdir -p "$HOME/XcodesCache"
|
||||
touch "$HOME/XcodesCache/Xcode_26.6.xip"
|
||||
|
||||
- name: Validate templates
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
validate() {
|
||||
local template="$1"
|
||||
shift
|
||||
|
||||
packer init "$template"
|
||||
packer validate "$@" "$template"
|
||||
}
|
||||
|
||||
for template in templates/vanilla-*.pkr.hcl; do
|
||||
validate "$template"
|
||||
done
|
||||
|
||||
validate templates/base.pkr.hcl \
|
||||
-var vm_name=template-validation-base
|
||||
|
||||
validate templates/disable-sip.pkr.hcl \
|
||||
-var vm_name=template-validation-disable-sip
|
||||
|
||||
validate templates/disable-sip-with-username.pkr.hcl \
|
||||
-var vm_name=template-validation-disable-sip-user
|
||||
|
||||
validate templates/exex-script.pkr.hcl \
|
||||
-var vm_name=template-validation-exec \
|
||||
-var script_path=scripts/finalize-tahoe.sh
|
||||
|
||||
validate templates/resolve-macos-number.pkr.hcl \
|
||||
-var vm_base_name=template-validation-base \
|
||||
-var vm_name=template-validation-resolve \
|
||||
-var resolve_file=macos-version.txt
|
||||
|
||||
validate templates/xcode.pkr.hcl \
|
||||
-var macos_version=tahoe \
|
||||
-var 'xcode_version=["26.6"]' \
|
||||
-var expected_runtimes_file=data/expected.tahoe.runtimes.txt
|
||||
|
||||
build-vanilla:
|
||||
name: Build Vanilla Image (${{ matrix.macos_version }})
|
||||
needs: packer-validate
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: [self-hosted, macOS, ARM64]
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
macos_version:
|
||||
- golden-gate
|
||||
- tahoe
|
||||
- sequoia
|
||||
- sonoma
|
||||
- monterey
|
||||
env:
|
||||
MACOS_VERSION: ${{ matrix.macos_version }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Select image
|
||||
id: select
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
git diff --name-only "$BASE_SHA" "$HEAD_SHA" > changed-files.txt
|
||||
|
||||
build=false
|
||||
if grep -Fxq "templates/vanilla-$MACOS_VERSION.pkr.hcl" changed-files.txt; then
|
||||
build=true
|
||||
fi
|
||||
|
||||
echo "build=$build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Tool versions
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart --version
|
||||
packer --version
|
||||
|
||||
- name: Build vanilla image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
packer init "templates/vanilla-$MACOS_VERSION.pkr.hcl"
|
||||
packer build "templates/vanilla-$MACOS_VERSION.pkr.hcl"
|
||||
|
||||
- name: Cleanup
|
||||
if: always() && steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart delete "$MACOS_VERSION-vanilla" || true
|
||||
|
||||
build-base:
|
||||
name: Build Base Image (${{ matrix.macos_version }})
|
||||
needs: packer-validate
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: [self-hosted, macOS, ARM64]
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
include:
|
||||
- macos_version: sonoma
|
||||
disable_sip_template: disable-sip.pkr.hcl
|
||||
- macos_version: sequoia
|
||||
disable_sip_template: disable-sip-with-username.pkr.hcl
|
||||
- macos_version: tahoe
|
||||
disable_sip_template: disable-sip-with-username.pkr.hcl
|
||||
env:
|
||||
DISABLE_SIP_TEMPLATE: ${{ matrix.disable_sip_template }}
|
||||
MACOS_VERSION: ${{ matrix.macos_version }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Select image
|
||||
id: select
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
git diff --name-only "$BASE_SHA" "$HEAD_SHA" > changed-files.txt
|
||||
|
||||
build=false
|
||||
if grep -Eq '^(templates/base\.pkr\.hcl|templates/disable-sip.*\.pkr\.hcl|data/(github_known_hosts|limit\.maxfiles\.plist|setup-info-template\.json|tart-guest-.*\.plist)|scripts/(install-actions-runner|update-tcc-database)\.sh|ansible/)' changed-files.txt; then
|
||||
build=true
|
||||
fi
|
||||
|
||||
echo "build=$build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Tool versions
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart --version
|
||||
packer --version
|
||||
|
||||
- name: Pull vanilla image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart pull "ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest"
|
||||
tart clone "ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest" "$MACOS_VERSION-base"
|
||||
|
||||
- name: Disable SIP
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
packer init "templates/$DISABLE_SIP_TEMPLATE"
|
||||
packer build -var "vm_name=$MACOS_VERSION-base" "templates/$DISABLE_SIP_TEMPLATE"
|
||||
|
||||
- name: Build base image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
packer init templates/base.pkr.hcl
|
||||
packer build -var "vm_name=$MACOS_VERSION-base" templates/base.pkr.hcl
|
||||
|
||||
- name: Cleanup
|
||||
if: always() && steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart delete "$MACOS_VERSION-base" || true
|
||||
|
||||
build-runner:
|
||||
name: Build Runner Image (${{ matrix.macos_version }})
|
||||
needs: packer-validate
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: [self-hosted, macOS, ARM64]
|
||||
timeout-minutes: 180
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
include:
|
||||
- macos_version: tahoe
|
||||
xcode_versions: '"26.6","27-beta-2","26.5","27-beta","26.4.1","26.3","26.2","26.1.1","26.0.1"'
|
||||
additional_ios_builds: "18.6"
|
||||
additional_tvos_builds: ""
|
||||
xcode_components: '"MetalToolchain"'
|
||||
disk_size: 520
|
||||
- macos_version: sequoia
|
||||
xcode_versions: '"26.0.1",16.4,16.3,16.2,16.1,16'
|
||||
additional_ios_builds: "18.5,18.4,18.2,17.5"
|
||||
additional_tvos_builds: "17.5"
|
||||
xcode_components: '"MetalToolchain"'
|
||||
disk_size: 380
|
||||
env:
|
||||
ADDITIONAL_IOS_BUILDS: ${{ matrix.additional_ios_builds }}
|
||||
ADDITIONAL_TVOS_BUILDS: ${{ matrix.additional_tvos_builds }}
|
||||
DISK_SIZE: ${{ matrix.disk_size }}
|
||||
MACOS_VERSION: ${{ matrix.macos_version }}
|
||||
XCODE_COMPONENTS: ${{ matrix.xcode_components }}
|
||||
XCODE_VERSIONS: ${{ matrix.xcode_versions }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Select image
|
||||
id: select
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
git diff --name-only "$BASE_SHA" "$HEAD_SHA" > changed-files.txt
|
||||
|
||||
build=false
|
||||
if grep -Fxq ".github/workflows/release.yml" changed-files.txt; then
|
||||
build=true
|
||||
elif grep -Fxq "data/expected.$MACOS_VERSION.runtimes.txt" changed-files.txt; then
|
||||
build=true
|
||||
elif grep -Fxq "scripts/finalize-$MACOS_VERSION.sh" changed-files.txt; then
|
||||
build=true
|
||||
elif grep -Eq '^(templates/xcode\.pkr\.hcl|data/setup-info-template\.json|scripts/install-actions-runner\.sh)$' changed-files.txt; then
|
||||
build=true
|
||||
fi
|
||||
|
||||
echo "build=$build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Tool versions
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart --version
|
||||
packer --version
|
||||
|
||||
- name: Pull base image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart pull "ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest"
|
||||
|
||||
- name: Prepare Xcode archives
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
source ~/.zprofile || true
|
||||
|
||||
if ! command -v xcodes >/dev/null; then
|
||||
brew install xcodes
|
||||
fi
|
||||
|
||||
mkdir -p "$HOME/XcodesCache"
|
||||
IFS=',' read -ra versions <<< "$XCODE_VERSIONS"
|
||||
|
||||
for raw_version in "${versions[@]}"; do
|
||||
version="${raw_version//\"/}"
|
||||
target="$HOME/XcodesCache/Xcode_${version}.xip"
|
||||
|
||||
if [[ -f "$target" ]]; then
|
||||
echo "Using cached Xcode $version at $target"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Downloading Xcode $version"
|
||||
if [[ -z "${FASTLANE_SESSION:-}" ]]; then
|
||||
echo "::error::Missing $target and FASTLANE_SESSION is not configured. Pre-cache the Xcode archive on the runner or add Apple Developer auth secrets."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_args=(download "$version" --directory "$HOME/XcodesCache" --use-fastlane-auth)
|
||||
if [[ -n "${FASTLANE_USER:-}" ]]; then
|
||||
download_args+=(--fastlane-user "$FASTLANE_USER")
|
||||
fi
|
||||
xcodes "${download_args[@]}"
|
||||
|
||||
candidate=""
|
||||
case "$version" in
|
||||
27-beta-2)
|
||||
candidate="$HOME/XcodesCache/Xcode_27_beta_2.xip"
|
||||
;;
|
||||
27-beta)
|
||||
candidate="$HOME/XcodesCache/Xcode_27_beta.xip"
|
||||
;;
|
||||
*)
|
||||
candidate="$(find "$HOME/XcodesCache" -maxdepth 1 -type f -name "Xcode_${version}*.xip" -print -quit)"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -n "$candidate" && -f "$candidate" && "$candidate" != "$target" ]]; then
|
||||
mv "$candidate" "$target"
|
||||
fi
|
||||
|
||||
test -f "$target"
|
||||
done
|
||||
|
||||
- name: Build runner image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
packer init templates/xcode.pkr.hcl
|
||||
packer build \
|
||||
-var tag=runner \
|
||||
-var "disk_size=$DISK_SIZE" \
|
||||
-var disk_free_mb=100000 \
|
||||
-var "macos_version=$MACOS_VERSION" \
|
||||
-var "xcode_version=[$XCODE_VERSIONS]" \
|
||||
-var "additional_ios_builds=[$ADDITIONAL_IOS_BUILDS]" \
|
||||
-var "additional_tvos_builds=[$ADDITIONAL_TVOS_BUILDS]" \
|
||||
-var "xcode_components=[$XCODE_COMPONENTS]" \
|
||||
-var "expected_runtimes_file=data/expected.$MACOS_VERSION.runtimes.txt" \
|
||||
templates/xcode.pkr.hcl
|
||||
|
||||
- name: Finalize runner image
|
||||
if: steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
if [[ -f "scripts/finalize-$MACOS_VERSION.sh" ]]; then
|
||||
packer build \
|
||||
-var "vm_name=$MACOS_VERSION-xcode:runner" \
|
||||
-var "script_path=scripts/finalize-$MACOS_VERSION.sh" \
|
||||
templates/exex-script.pkr.hcl
|
||||
else
|
||||
echo "Skipping prepare script for $MACOS_VERSION"
|
||||
fi
|
||||
|
||||
- name: Cleanup
|
||||
if: always() && steps.select.outputs.build == 'true'
|
||||
run: |
|
||||
tart delete "$MACOS_VERSION-xcode:runner" || true
|
||||
|
|
@ -13,6 +13,7 @@ on:
|
|||
type: choice
|
||||
options:
|
||||
- all
|
||||
- golden-gate
|
||||
- tahoe
|
||||
- sequoia
|
||||
- sonoma
|
||||
|
|
@ -46,6 +47,7 @@ jobs:
|
|||
max-parallel: 1
|
||||
matrix:
|
||||
macos_version:
|
||||
- golden-gate
|
||||
- tahoe
|
||||
- sequoia
|
||||
- sonoma
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ GitHub Actions runners, [Cirrus Runners](https://cirrus-runners.app/) or [any ot
|
|||
|
||||
The following image variants are currently available:
|
||||
|
||||
* `macos-{tahoe,sequoia,sonoma}-vanilla` — a vanilla macOS installation with helpful tweaks such as auto-login, but no additional software preinstalled
|
||||
* `macos-{golden-gate,tahoe,sequoia,sonoma}-vanilla` — a vanilla macOS installation with helpful tweaks such as auto-login, but no additional software preinstalled
|
||||
* `macos-{tahoe,sequoia,sonoma}-base` — based on `macos-{tahoe,sequoia,sonoma}-vanilla` image, it comes with `brew` and [other useful software](https://github.com/cirruslabs/macos-image-templates/blob/main/templates/base.pkr.hcl) pre-installed, but without Xcode
|
||||
* `macos-{tahoe,sequoia,sonoma}-xcode:N` — based on `macos-{tahoe,sequoia,sonoma}-base` image and has `Xcode N` with [`Flutter`](https://flutter.dev/) pre-installed
|
||||
* `macos-runner:{tahoe,sequoia,sonoma}` — a variant of `xcode:N` with several versions of `Xcode` pre-installed and [`xcodes` tool](https://github.com/XcodesOrg/xcodes) to switch between them.
|
||||
|
|
|
|||
|
|
@ -5,12 +5,11 @@ iOS 26.1 (26.1 - 23B86) - com.apple.CoreSimulator.SimRuntime.iOS-26-1
|
|||
iOS 26.3 (26.3.1 - 23D8133) - com.apple.CoreSimulator.SimRuntime.iOS-26-3
|
||||
iOS 26.4 (26.4.1 - 23E254a) - com.apple.CoreSimulator.SimRuntime.iOS-26-4
|
||||
iOS 26.5 (26.5 - 23F77) - com.apple.CoreSimulator.SimRuntime.iOS-26-5
|
||||
tvOS 26.2 (26.2 - 23K51) - com.apple.CoreSimulator.SimRuntime.tvOS-26-2
|
||||
tvOS 26.4 (26.4 - 23L243a) - com.apple.CoreSimulator.SimRuntime.tvOS-26-4
|
||||
iOS 27.0 (27.0 - 24A5355p) - com.apple.CoreSimulator.SimRuntime.iOS-27-0
|
||||
iOS 27.0 (27.0 - 24A5370g) - com.apple.CoreSimulator.SimRuntime.iOS-27-0
|
||||
tvOS 26.5 (26.5 - 23L470) - com.apple.CoreSimulator.SimRuntime.tvOS-26-5
|
||||
watchOS 26.2 (26.2 - 23S303) - com.apple.CoreSimulator.SimRuntime.watchOS-26-2
|
||||
watchOS 26.4 (26.4 - 23T240b) - com.apple.CoreSimulator.SimRuntime.watchOS-26-4
|
||||
tvOS 27.0 (27.0 - 24J5305f) - com.apple.CoreSimulator.SimRuntime.tvOS-27-0
|
||||
watchOS 26.5 (26.5 - 23T570) - com.apple.CoreSimulator.SimRuntime.watchOS-26-5
|
||||
visionOS 26.2 (26.2 - 23N301) - com.apple.CoreSimulator.SimRuntime.xrOS-26-2
|
||||
visionOS 26.4 (26.4.1 - 23O249a) - com.apple.CoreSimulator.SimRuntime.xrOS-26-4
|
||||
watchOS 27.0 (27.0 - 24R5305f) - com.apple.CoreSimulator.SimRuntime.watchOS-27-0
|
||||
visionOS 26.5 (26.5 - 23O470) - com.apple.CoreSimulator.SimRuntime.xrOS-26-5
|
||||
visionOS 27.0 (27.0 - 24M5306g) - com.apple.CoreSimulator.SimRuntime.xrOS-27-0
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ source ~/.zprofile
|
|||
set -euo pipefail
|
||||
|
||||
update_tcc_database() {
|
||||
sudo sqlite3 "$1" <<-'EOF'
|
||||
local tart_guest_agent_path
|
||||
tart_guest_agent_path="$(realpath /opt/homebrew/bin/tart-guest-agent)"
|
||||
|
||||
sudo sqlite3 "$1" <<-EOF
|
||||
INSERT OR REPLACE
|
||||
INTO access (
|
||||
service,
|
||||
|
|
@ -36,7 +39,17 @@ update_tcc_database() {
|
|||
('kTCCServiceScreenCapture', 1, '/usr/bin/osascript', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServicePostEvent', 1, '/usr/bin/osascript', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServiceAppleEvents', 1, '/usr/bin/osascript', 2, 0, 1, 0, 'com.apple.systemevents'),
|
||||
('kTCCServiceAppleEvents', 1, '/usr/bin/osascript', 2, 0, 1, 0, 'com.apple.Safari');
|
||||
('kTCCServiceAppleEvents', 1, '/usr/bin/osascript', 2, 0, 1, 0, 'com.apple.Safari'),
|
||||
-- Direct Python invocation
|
||||
('kTCCServiceAccessibility', 0, 'org.python.python', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServiceScreenCapture', 0, 'org.python.python', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServiceMicrophone', 0, 'org.python.python', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServicePostEvent', 0, 'org.python.python', 2, 0, 1, NULL, 'UNUSED'),
|
||||
-- Commands invoked through the Tart Guest Agent
|
||||
('kTCCServiceAccessibility', 1, '${tart_guest_agent_path}', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServiceScreenCapture', 1, '${tart_guest_agent_path}', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServiceMicrophone', 1, '${tart_guest_agent_path}', 2, 0, 1, NULL, 'UNUSED'),
|
||||
('kTCCServicePostEvent', 1, '${tart_guest_agent_path}', 2, 0, 1, NULL, 'UNUSED');
|
||||
EOF
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ build {
|
|||
"brew --version",
|
||||
"brew update",
|
||||
"brew install wget unzip zip ca-certificates cmake gcc git-lfs jq yq gh gitlab-runner",
|
||||
"brew install buildkite/buildkite/buildkite-agent",
|
||||
"brew install buildkite/buildkite/buildkite-agent@3",
|
||||
"brew install equinix-labs/otel-cli/otel-cli",
|
||||
"brew install curl || true", // doesn't work on Monterey
|
||||
"brew install --cask git-credential-manager",
|
||||
|
|
@ -121,8 +121,12 @@ build {
|
|||
"echo 'export PATH=\"/opt/homebrew/opt/node@24/bin:$PATH\"' >> ~/.zprofile",
|
||||
"source ~/.zprofile",
|
||||
"node --version",
|
||||
"npm install --global yarn",
|
||||
"npm install --global yarn pnpm",
|
||||
"echo 'export PNPM_HOME=\"$HOME/Library/pnpm\"' >> ~/.zprofile",
|
||||
"echo 'export PATH=\"$PNPM_HOME:$PATH\"' >> ~/.zprofile",
|
||||
"source ~/.zprofile",
|
||||
"yarn --version",
|
||||
"pnpm --version",
|
||||
]
|
||||
}
|
||||
provisioner "shell" {
|
||||
|
|
@ -164,7 +168,7 @@ build {
|
|||
inline = [
|
||||
# Install Tart Guest Agent
|
||||
"source ~/.zprofile",
|
||||
"brew install cirruslabs/cli/tart-guest-agent",
|
||||
"brew install openai/tools/tart-guest-agent",
|
||||
|
||||
# Install daemon variant of the Tart Guest Agent
|
||||
"sudo mv ~/tart-guest-daemon.plist /Library/LaunchDaemons/org.cirruslabs.tart-guest-daemon.plist",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
packer {
|
||||
required_plugins {
|
||||
tart = {
|
||||
version = ">= 1.16.0"
|
||||
source = "github.com/cirruslabs/tart"
|
||||
}
|
||||
ansible = {
|
||||
version = "~> 1"
|
||||
source = "github.com/hashicorp/ansible"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source "tart-cli" "tart" {
|
||||
from_ipsw = "https://updates.cdn-apple.com/2026SummerSeed/fullrestores/140-55718/5809AFC6-1923-4590-AAFC-904A0283E659/UniversalMac_27.0_26A5388g_Restore.ipsw"
|
||||
vm_name = "golden-gate-vanilla"
|
||||
cpu_count = 4
|
||||
memory_gb = 8
|
||||
disk_size_gb = 50
|
||||
disk_format = "asif"
|
||||
ssh_password = "admin"
|
||||
ssh_username = "admin"
|
||||
ssh_timeout = "180s"
|
||||
// Requires Tart 2.33.0+ and macOS 27+ on both the host and guest VM
|
||||
run_extra_args = [
|
||||
"--provisioning-opts=${join(",", [
|
||||
"fullName=Managed via Tart",
|
||||
"username=admin",
|
||||
"password=admin",
|
||||
"logsInAutomatically=true",
|
||||
"enablesRemoteLogin=true",
|
||||
])}",
|
||||
]
|
||||
boot_command = [
|
||||
# Wait for first-boot provisioning to finish automatic login
|
||||
"<wait120s>",
|
||||
# Enable Keyboard navigation
|
||||
# This is so that we can navigate the System Settings app using the keyboard
|
||||
"<wait10s><leftAltOn><spacebar><leftAltOff>Terminal<wait10s><enter>",
|
||||
"<wait10s><wait10s>defaults write NSGlobalDomain AppleKeyboardUIMode -int 3<enter>",
|
||||
# Disable Gatekeeper (1/2)
|
||||
"<wait10s>sudo spctl --global-disable<enter>",
|
||||
"<wait10s>admin<enter>",
|
||||
# Disable Gatekeeper (2/2)
|
||||
# On Tahoe opening System Settings through Spotlight is not very reliable, sometimes opens System information
|
||||
"<wait10s>open '/System/Applications/System Settings.app'<enter>",
|
||||
# Wait for System Settings to fully open before navigating with the keyboard
|
||||
"<wait120s>",
|
||||
"<wait10s><leftCtrlOn><f2><leftCtrlOff><right><right><right><down>Privacy & Security<enter>",
|
||||
"<wait10s><leftShiftOn><tab><tab><tab><tab><tab><tab><leftShiftOff>",
|
||||
"<wait10s><down><wait1s><down><wait1s><enter>",
|
||||
"<wait10s>admin<enter>",
|
||||
"<wait10s><leftShiftOn><tab><leftShiftOff><wait1s><spacebar>",
|
||||
# Quit System Settings
|
||||
"<wait10s><leftAltOn>q<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 \"mkdir -p /etc/sudoers.d/; echo 'admin ALL=(ALL) NOPASSWD: ALL' | EDITOR=tee visudo /etc/sudoers.d/admin-nopasswd\"",
|
||||
// Enable Screen Sharing for "tart run --vnc"
|
||||
"sudo launchctl enable system/com.apple.screensharing",
|
||||
// Use the same timezone as the previous Setup Assistant flow
|
||||
"sudo systemsetup -settimezone GMT 2>/dev/null",
|
||||
// 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 -setsleep 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 = [
|
||||
# Ensure that Gatekeeper is disabled
|
||||
"spctl --status | grep -q 'assessments disabled'",
|
||||
# Ensure that FileVault remains disabled by default
|
||||
"sudo fdesetup status | grep -q 'FileVault is Off'",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -6,13 +6,13 @@ packer {
|
|||
}
|
||||
ansible = {
|
||||
version = "~> 1"
|
||||
source = "github.com/hashicorp/ansible"
|
||||
source = "github.com/hashicorp/ansible"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source "tart-cli" "tart" {
|
||||
from_ipsw = "https://updates.cdn-apple.com/2026SpringFCS/fullrestores/122-58869/DFB1CEEF-5619-4591-9924-E20DB2C8FED0/UniversalMac_26.5_25F71_Restore.ipsw"
|
||||
from_ipsw = "https://updates.cdn-apple.com/2026SummerFCS/fullrestores/140-83079/25315EF6-AEAB-4588-9774-A3723774C47F/UniversalMac_26.6.1_25G76_Restore.ipsw"
|
||||
vm_name = "tahoe-vanilla"
|
||||
cpu_count = 4
|
||||
memory_gb = 8
|
||||
|
|
|
|||
|
|
@ -16,39 +16,39 @@ variable "xcode_version" {
|
|||
}
|
||||
|
||||
variable "additional_ios_builds" {
|
||||
type = list(string)
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "additional_tvos_builds" {
|
||||
type = list(string)
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "xcode_components" {
|
||||
type = list(string)
|
||||
default = []
|
||||
type = list(string)
|
||||
default = []
|
||||
description = "Additional Xcode components to download."
|
||||
}
|
||||
|
||||
variable "expected_runtimes_file" {
|
||||
type = string
|
||||
default = ""
|
||||
type = string
|
||||
default = ""
|
||||
description = "Path to file containing expected simulator runtimes. If empty, runtime verification is skipped."
|
||||
}
|
||||
|
||||
variable "tag" {
|
||||
type = string
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "disk_size" {
|
||||
type = number
|
||||
type = number
|
||||
default = 140
|
||||
}
|
||||
|
||||
variable "disk_free_mb" {
|
||||
type = number
|
||||
type = number
|
||||
default = 15000
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ build {
|
|||
}
|
||||
|
||||
provisioner "file" {
|
||||
sources = [ for version in var.xcode_version : pathexpand("~/XcodesCache/Xcode_${version}.xip")]
|
||||
sources = [for version in var.xcode_version : pathexpand("~/XcodesCache/Xcode_${version}.xip")]
|
||||
destination = "/Users/admin/Downloads/"
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ build {
|
|||
// select the latest one as the default
|
||||
dynamic "provisioner" {
|
||||
for_each = local.xcode_install_provisioners
|
||||
labels = ["shell"]
|
||||
labels = ["shell"]
|
||||
content {
|
||||
inline = provisioner.value.inline
|
||||
}
|
||||
|
|
@ -169,11 +169,11 @@ build {
|
|||
|
||||
dynamic "provisioner" {
|
||||
for_each = length(var.xcode_version) > 2 ? [2] : []
|
||||
labels = ["shell"]
|
||||
labels = ["shell"]
|
||||
content {
|
||||
inline = [
|
||||
"source ~/.zprofile",
|
||||
"sudo xcodes select '${var.xcode_version[2]}'",
|
||||
"sudo xcode-select -s /Applications/Xcode_${var.xcode_version[2]}.app/Contents/Developer",
|
||||
"xcodebuild -downloadAllPlatforms",
|
||||
]
|
||||
}
|
||||
|
|
@ -181,11 +181,11 @@ build {
|
|||
|
||||
dynamic "provisioner" {
|
||||
for_each = length(var.xcode_version) > 1 ? [1] : []
|
||||
labels = ["shell"]
|
||||
labels = ["shell"]
|
||||
content {
|
||||
inline = [
|
||||
"source ~/.zprofile",
|
||||
"sudo xcodes select '${var.xcode_version[1]}'",
|
||||
"sudo xcode-select -s /Applications/Xcode_${var.xcode_version[1]}.app/Contents/Developer",
|
||||
"xcodebuild -downloadAllPlatforms",
|
||||
]
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ build {
|
|||
provisioner "shell" {
|
||||
inline = [
|
||||
"source ~/.zprofile",
|
||||
"sudo xcodes select '${var.xcode_version[0]}'",
|
||||
"sudo xcode-select -s /Applications/Xcode_${var.xcode_version[0]}.app/Contents/Developer",
|
||||
"xcodebuild -downloadAllPlatforms",
|
||||
]
|
||||
}
|
||||
|
|
@ -232,10 +232,9 @@ build {
|
|||
"brew install libimobiledevice ideviceinstaller ios-deploy carthage",
|
||||
"brew install xcbeautify swiftformat swiftlint swiftgen licenseplist",
|
||||
"brew install mint",
|
||||
"brew tap tuist/tuist",
|
||||
"brew install --formula tuist",
|
||||
"rbenv install 3.3.10",
|
||||
"rbenv global 3.3.10", # fastlane conflicts with 3.4.0+ https://github.com/fastlane/fastlane/issues/29527
|
||||
"git clone --depth 1 https://github.com/tuist/homebrew-tuist.git \"$(brew --repository)/Library/Taps/tuist/homebrew-tuist\"",
|
||||
"rm -rf \"$(brew --repository)/Library/Taps/tuist/homebrew-tuist/Casks\"",
|
||||
"tuist_version=$(ruby -ne 'if $_ =~ %r{/download/([^/]+)/}; puts $1; exit; end' \"$(brew --repository)/Library/Taps/tuist/homebrew-tuist/Aliases/tuist\") && brew trust --formula \"tuist/tuist/tuist@$tuist_version\" && brew install --formula \"tuist/tuist/tuist@$tuist_version\"",
|
||||
"gem update",
|
||||
"gem install fastlane",
|
||||
"gem install cocoapods",
|
||||
|
|
@ -247,7 +246,7 @@ build {
|
|||
// Copy expected runtimes file if provided
|
||||
dynamic "provisioner" {
|
||||
for_each = var.expected_runtimes_file != "" ? [1] : []
|
||||
labels = ["file"]
|
||||
labels = ["file"]
|
||||
content {
|
||||
source = var.expected_runtimes_file
|
||||
destination = "/Users/admin/runtimes.expected.txt"
|
||||
|
|
@ -257,7 +256,7 @@ build {
|
|||
// Verify simulator runtimes match expected list if file was provided
|
||||
dynamic "provisioner" {
|
||||
for_each = var.expected_runtimes_file != "" ? [1] : []
|
||||
labels = ["shell"]
|
||||
labels = ["shell"]
|
||||
content {
|
||||
inline = [
|
||||
"source ~/.zprofile",
|
||||
|
|
|
|||
Loading…
Reference in New Issue