From 206d99a672c8068a9d532fb439d321d14feea6f8 Mon Sep 17 00:00:00 2001 From: Fedor Korotkov Date: Wed, 3 Jun 2026 06:37:04 -0700 Subject: [PATCH] Migrate CI to GitHub Actions (#351) --- .ci/cirrus.base.yml | 28 ----- .ci/cirrus.release.yml | 23 ---- .ci/cirrus.runner.yml | 46 -------- .ci/cirrus.vanilla.yml | 27 ----- .ci/cirrus.xcode.yml | 49 -------- .cirrus.star | 52 --------- .cirrus.yml | 18 --- .github/workflows/monthly.yml | 203 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 166 +++++++++++++++++++++++++++ .github/workflows/vanilla.yml | 127 +++++++++++++++++++++ README.md | 6 +- 11 files changed, 499 insertions(+), 246 deletions(-) delete mode 100644 .ci/cirrus.base.yml delete mode 100644 .ci/cirrus.release.yml delete mode 100644 .ci/cirrus.runner.yml delete mode 100644 .ci/cirrus.vanilla.yml delete mode 100644 .ci/cirrus.xcode.yml delete mode 100644 .cirrus.star delete mode 100644 .cirrus.yml create mode 100644 .github/workflows/monthly.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/vanilla.yml diff --git a/.ci/cirrus.base.yml b/.ci/cirrus.base.yml deleted file mode 100644 index 889530e..0000000 --- a/.ci/cirrus.base.yml +++ /dev/null @@ -1,28 +0,0 @@ -task: - name: "Update Base Images ($MACOS_VERSION)" - alias: update-base - matrix: - - env: - MACOS_VERSION: sonoma - DISABLE_SIP_TEMPLATE: disable-sip.pkr.hcl - - env: - MACOS_VERSION: sequoia - DISABLE_SIP_TEMPLATE: disable-sip-with-username.pkr.hcl - - env: - MACOS_VERSION: tahoe - DISABLE_SIP_TEMPLATE: disable-sip-with-username.pkr.hcl - <<: *defaults - pull_vanilla_script: - - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest - - tart clone ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest "$MACOS_VERSION-base" - disable_sip_script: - - packer init "templates/${DISABLE_SIP_TEMPLATE}" - - packer build -var vm_name="$MACOS_VERSION-base" "templates/${DISABLE_SIP_TEMPLATE}" - build_base_script: - - packer init templates/base.pkr.hcl - - packer build -var vm_name="$MACOS_VERSION-base" templates/base.pkr.hcl - push_base_script: - - tart push $MACOS_VERSION-base ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - always: - cleanup_script: - - tart delete $MACOS_VERSION-base diff --git a/.ci/cirrus.release.yml b/.ci/cirrus.release.yml deleted file mode 100644 index a54eb05..0000000 --- a/.ci/cirrus.release.yml +++ /dev/null @@ -1,23 +0,0 @@ -task: - name: "Release Xcode $CIRRUS_TAG ($MACOS_VERSION)" - env: - XCODE_COMPONENTS: "\"MetalToolchain\"" - matrix: - - MACOS_VERSION: tahoe - - MACOS_VERSION: sequoia - <<: *defaults - pull_base_script: - - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - build_script: - - packer init templates/xcode.pkr.hcl - - packer build -var macos_version="$MACOS_VERSION" -var xcode_version="[\"$CIRRUS_TAG\"]" -var xcode_components="[$XCODE_COMPONENTS]" templates/xcode.pkr.hcl - push_script: | - if [[ $CIRRUS_TAG == *"beta"* ]] - then - tart push $MACOS_VERSION-xcode:$CIRRUS_TAG ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$CIRRUS_TAG - else - tart push $MACOS_VERSION-xcode:$CIRRUS_TAG ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$CIRRUS_TAG ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:latest - fi - always: - cleanup_script: - - tart delete $MACOS_VERSION-xcode:$CIRRUS_TAG || true diff --git a/.ci/cirrus.runner.yml b/.ci/cirrus.runner.yml deleted file mode 100644 index 545a71b..0000000 --- a/.ci/cirrus.runner.yml +++ /dev/null @@ -1,46 +0,0 @@ -task: - name: "Update Runner Image ($MACOS_VERSION)" - env: - matrix: - - 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 - - MACOS_VERSION: tahoe - XCODE_VERSIONS: "\"26.5\",\"26.4.1\",\"26.3\",\"26.2\",\"26.1.1\",\"26.0.1\"" - XCODE_COMPONENTS: "\"MetalToolchain\"" - ADDITIONAL_IOS_BUILDS: "18.6" - DISK_SIZE: 330 - <<: *defaults - pull_base_script: - - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - init_xcode_script: packer init templates/xcode.pkr.hcl - build_xcode_script: | - 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 - finalize_script: | - 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 - push_script: | - if [[ -z "$CIRRUS_PR" ]]; then - tart push "$MACOS_VERSION-xcode:runner" ghcr.io/cirruslabs/macos-runner:$MACOS_VERSION - else - echo "Skipping pushing for PR..." - fi - always: - cleanup_script: - - tart delete "$MACOS_VERSION-xcode:runner" diff --git a/.ci/cirrus.vanilla.yml b/.ci/cirrus.vanilla.yml deleted file mode 100644 index 3de8d41..0000000 --- a/.ci/cirrus.vanilla.yml +++ /dev/null @@ -1,27 +0,0 @@ -env: - RESOLVE_VM_NAME: "resolve-macos-number-task-id-${CIRRUS_TASK_ID}" - RESOLVE_FILE: "${RESOLVE_VM_NAME}.txt" - -task: - name: "Update Vanilla Image ($MACOS_VERSION)" - env: - matrix: - - MACOS_VERSION: tahoe - - MACOS_VERSION: sequoia - - MACOS_VERSION: sonoma - - MACOS_VERSION: monterey - only_if: $CIRRUS_BRANCH == $CIRRUS_DEFAULT_BRANCH && changesInclude("templates/vanilla-$MACOS_VERSION.pkr.hcl") - <<: *defaults - build_script: - - packer init templates/vanilla-$MACOS_VERSION.pkr.hcl - - packer build templates/vanilla-$MACOS_VERSION.pkr.hcl - resolve_macos_number_script: - - packer build -var vm_base_name=$MACOS_VERSION-vanilla -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: - - tart push $MACOS_VERSION-vanilla ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:$MACOS_NUMBER - always: - cleanup_script: - - tart delete $MACOS_VERSION-vanilla diff --git a/.ci/cirrus.xcode.yml b/.ci/cirrus.xcode.yml deleted file mode 100644 index 4a0ce03..0000000 --- a/.ci/cirrus.xcode.yml +++ /dev/null @@ -1,49 +0,0 @@ -task: - name: "Update Xcode Images ($MACOS_VERSION $XCODE_VERSION)" - depends_on: update-base - env: - matrix: - - MACOS_VERSION: tahoe - XCODE_VERSION: "26.2" - XCODE_COMPONENTS: "\"MetalToolchain\"" - LATEST: true - - MACOS_VERSION: tahoe - XCODE_VERSION: "26.1.1" - XCODE_COMPONENTS: "\"MetalToolchain\"" - - MACOS_VERSION: tahoe - XCODE_VERSION: "26.0.1" - XCODE_COMPONENTS: "\"MetalToolchain\"" - - MACOS_VERSION: sequoia - XCODE_VERSION: 16.4 - LATEST: true - - MACOS_VERSION: sequoia - XCODE_VERSION: 16.3 - - MACOS_VERSION: sequoia - XCODE_VERSION: 16.2 - - MACOS_VERSION: sequoia - XCODE_VERSION: 16.1 - - MACOS_VERSION: sequoia - XCODE_VERSION: 16 - - MACOS_VERSION: sonoma - XCODE_VERSION: 16.1 - LATEST: true - - MACOS_VERSION: sonoma - XCODE_VERSION: 16 - - MACOS_VERSION: sonoma - XCODE_VERSION: 15.4 - <<: *defaults - pull_base_script: - - tart pull ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest - build_xcode_script: - - packer init templates/xcode.pkr.hcl - - packer build -var macos_version="$MACOS_VERSION" -var xcode_version="[\"$XCODE_VERSION\"]" -var xcode_components="[$XCODE_COMPONENTS]" templates/xcode.pkr.hcl - push_script: | - if [[ -z "$LATEST" ]] - then - tart push "$MACOS_VERSION-xcode:$XCODE_VERSION" ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_VERSION - else - tart push "$MACOS_VERSION-xcode:$XCODE_VERSION" ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_VERSION ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:latest - fi - always: - cleanup_script: - - tart delete "$MACOS_VERSION-xcode:$XCODE_VERSION" diff --git a/.cirrus.star b/.cirrus.star deleted file mode 100644 index eec6aa2..0000000 --- a/.cirrus.star +++ /dev/null @@ -1,52 +0,0 @@ -load("cirrus", "env", "http", "fs", "changes_include") -load("github.com/cirrus-modules/graphql", "rerun_task_if_issue_in_logs") - - -def on_task_failed(ctx): - if ctx.payload.data.task.automaticReRun: - print("Task is already an automatic re-run! Won't even try to re-run it...") - return - rerun_task_if_issue_in_logs(ctx.payload.data.task.id, "The network connection was lost") - - -def on_build_failed(ctx): - # Only send Slack notifications for failed cron builds[1] - # - # [1]: https://cirrus-ci.org/guide/writing-tasks/#cron-builds - if "Cron" not in ctx.payload.data.build.changeMessageTitle: - return - - resp = http.post(env.get("SLACK_WEBHOOK_URL"), headers={ - "Content-Type": "application/json", - }, json_body={ - "text": "Build {build_id} (\"{change_message_title}\") failed on branch \"{branch_name}\" in repository \"{repository_name}\".".format( - build_id=ctx.payload.data.build.id, - change_message_title=ctx.payload.data.build.changeMessageTitle, - 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: - fail("failed to post message to Slack: got unexpected HTTP {}".format(resp.status_code)) - - resp_json = resp.json() - - if resp_json["ok"] != True: - fail("got error when posting message to Slack: {}".format(resp_json["error"])) - - -def main(ctx): - result = fs.read(".ci/cirrus.vanilla.yml") - if env.get("CIRRUS_TAG") != None: - result += fs.read(".ci/cirrus.release.yml") - if env.get("CIRRUS_CRON") == "monthly": - result += fs.read(".ci/cirrus.base.yml") - result += fs.read(".ci/cirrus.xcode.yml") - prForRunners = env.get("CIRRUS_PR") and changes_include(".ci/cirrus.runner.yml") - if prForRunners or env.get("CIRRUS_TAG") != None: - result += fs.read(".ci/cirrus.runner.yml") - return result diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index b76bee1..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,18 +0,0 @@ -persistent_worker: - labels: - name: dev-mini - resources: - tart-vms: 1 - -env: - TART_REGISTRY_HOSTNAME: ghcr.io - TART_REGISTRY_USERNAME: fkorotkov # GitHub supports only PATs - TART_REGISTRY_PASSWORD: ENCRYPTED[!82ed873afdf627284305afef4958c85a8f73127b09978a9786ac521559630ea6c9a5ab6e7f8315abf9ead09b6eff6eae!] - AWS_ACCESS_KEY_ID: ENCRYPTED[c187b670a17eead88c1698849376273991d09678efe37ae2f0c9738c27a2422741a71c501ef4b6a4df7bff3eca5213a9] - AWS_SECRET_ACCESS_KEY: ENCRYPTED[e456254a53b82e3167f2da23e24c389620cb3f7d47e4e5e7d993813bf9bb18c784d5cb8d88d19632073acc9e1f6096c9] - -defaults: &defaults - timeout_in: 3h - info_script: - - tart --version - - packer --version diff --git a/.github/workflows/monthly.yml b/.github/workflows/monthly.yml new file mode 100644 index 0000000..1b8ae1c --- /dev/null +++ b/.github/workflows/monthly.yml @@ -0,0 +1,203 @@ +name: Monthly Images + +on: + schedule: + - cron: "0 8 * * 6" + workflow_dispatch: + +permissions: + contents: read + packages: write + +concurrency: + group: tart-image-builds + cancel-in-progress: false + +env: + TART_REGISTRY_HOSTNAME: ghcr.io + TART_REGISTRY_USERNAME: ${{ github.actor }} + TART_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + +jobs: + should-run: + name: Check Monthly Cadence + runs-on: [self-hosted, macOS, ARM64] + outputs: + build: ${{ steps.cadence.outputs.build }} + steps: + - name: Check first Saturday + id: cadence + env: + EVENT_NAME: ${{ github.event_name }} + run: | + set -euo pipefail + + build=false + if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then + build=true + else + day="$(date -u +%d)" + if (( 10#$day <= 7 )); then + build=true + fi + fi + + echo "build=$build" >> "$GITHUB_OUTPUT" + if [[ "$build" != "true" ]]; then + echo "Not the first Saturday of the month; skipping image rebuilds." + fi + + update-base: + name: Update Base Images (${{ matrix.macos_version }}) + needs: should-run + if: needs.should-run.outputs.build == 'true' + 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: + MACOS_VERSION: ${{ matrix.macos_version }} + DISABLE_SIP_TEMPLATE: ${{ matrix.disable_sip_template }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Tool versions + run: | + tart --version + packer --version + + - name: Pull vanilla image + 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 + run: | + packer init "templates/$DISABLE_SIP_TEMPLATE" + packer build -var "vm_name=$MACOS_VERSION-base" "templates/$DISABLE_SIP_TEMPLATE" + + - name: Build base image + run: | + packer init templates/base.pkr.hcl + packer build -var "vm_name=$MACOS_VERSION-base" templates/base.pkr.hcl + + - name: Push base image + run: | + tart push "$MACOS_VERSION-base" "ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest" + + - name: Cleanup + if: always() + run: | + tart delete "$MACOS_VERSION-base" || true + + update-xcode: + name: Update Xcode Images (${{ matrix.macos_version }} ${{ matrix.xcode_version }}) + needs: + - should-run + - update-base + if: needs.should-run.outputs.build == 'true' + runs-on: [self-hosted, macOS, ARM64] + timeout-minutes: 180 + strategy: + fail-fast: false + max-parallel: 1 + matrix: + include: + - macos_version: tahoe + xcode_version: "26.2" + xcode_components: '"MetalToolchain"' + latest: true + - macos_version: tahoe + xcode_version: "26.1.1" + xcode_components: '"MetalToolchain"' + latest: false + - macos_version: tahoe + xcode_version: "26.0.1" + xcode_components: '"MetalToolchain"' + latest: false + - macos_version: sequoia + xcode_version: "16.4" + xcode_components: "" + latest: true + - macos_version: sequoia + xcode_version: "16.3" + xcode_components: "" + latest: false + - macos_version: sequoia + xcode_version: "16.2" + xcode_components: "" + latest: false + - macos_version: sequoia + xcode_version: "16.1" + xcode_components: "" + latest: false + - macos_version: sequoia + xcode_version: "16" + xcode_components: "" + latest: false + - macos_version: sonoma + xcode_version: "16.1" + xcode_components: "" + latest: true + - macos_version: sonoma + xcode_version: "16" + xcode_components: "" + latest: false + - macos_version: sonoma + xcode_version: "15.4" + xcode_components: "" + latest: false + env: + MACOS_VERSION: ${{ matrix.macos_version }} + XCODE_COMPONENTS: ${{ matrix.xcode_components }} + XCODE_VERSION: ${{ matrix.xcode_version }} + LATEST: ${{ matrix.latest }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Tool versions + run: | + tart --version + packer --version + + - name: Pull base image + run: | + tart pull "ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest" + + - name: Build Xcode image + run: | + packer init templates/xcode.pkr.hcl + packer build \ + -var "macos_version=$MACOS_VERSION" \ + -var "xcode_version=[\"$XCODE_VERSION\"]" \ + -var "xcode_components=[$XCODE_COMPONENTS]" \ + templates/xcode.pkr.hcl + + - name: Push Xcode image + run: | + if [[ "$LATEST" == "true" ]]; then + tart push "$MACOS_VERSION-xcode:$XCODE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:latest" + else + tart push "$MACOS_VERSION-xcode:$XCODE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_VERSION" + fi + + - name: Cleanup + if: always() + run: | + tart delete "$MACOS_VERSION-xcode:$XCODE_VERSION" || true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..fb10152 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,166 @@ +name: Release Images + +on: + release: + types: + - published + workflow_dispatch: + inputs: + xcode_version: + description: "Xcode version/tag to release" + required: true + type: string + +permissions: + contents: read + packages: write + +concurrency: + group: tart-image-builds + cancel-in-progress: false + +env: + TART_REGISTRY_HOSTNAME: ghcr.io + TART_REGISTRY_USERNAME: ${{ github.actor }} + TART_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + XCODE_RELEASE_VERSION: ${{ github.event.release.tag_name || inputs.xcode_version }} + +jobs: + release-xcode: + name: Release Xcode ${{ github.event.release.tag_name || inputs.xcode_version }} (${{ matrix.macos_version }}) + runs-on: [self-hosted, macOS, ARM64] + timeout-minutes: 180 + strategy: + fail-fast: false + max-parallel: 1 + matrix: + macos_version: + - tahoe + - sequoia + env: + MACOS_VERSION: ${{ matrix.macos_version }} + XCODE_COMPONENTS: '"MetalToolchain"' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Validate release version + run: | + set -euo pipefail + if [[ -z "$XCODE_RELEASE_VERSION" ]]; then + echo "XCODE_RELEASE_VERSION is required." + exit 1 + fi + + - name: Tool versions + run: | + tart --version + packer --version + + - name: Pull base image + run: | + tart pull "ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest" + + - name: Build release image + run: | + packer init templates/xcode.pkr.hcl + packer build \ + -var "macos_version=$MACOS_VERSION" \ + -var "xcode_version=[\"$XCODE_RELEASE_VERSION\"]" \ + -var "xcode_components=[$XCODE_COMPONENTS]" \ + templates/xcode.pkr.hcl + + - name: Push release image + run: | + if [[ "$XCODE_RELEASE_VERSION" == *beta* ]]; then + tart push "$MACOS_VERSION-xcode:$XCODE_RELEASE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_RELEASE_VERSION" + else + tart push "$MACOS_VERSION-xcode:$XCODE_RELEASE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:$XCODE_RELEASE_VERSION" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-xcode:latest" + fi + + - name: Cleanup + if: always() + run: | + tart delete "$MACOS_VERSION-xcode:$XCODE_RELEASE_VERSION" || true + + release-runner: + name: Update Runner Image (${{ matrix.macos_version }}) + needs: release-xcode + runs-on: [self-hosted, macOS, ARM64] + timeout-minutes: 180 + strategy: + fail-fast: false + max-parallel: 1 + matrix: + include: + - 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 + - macos_version: tahoe + xcode_versions: '"26.5","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 + 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 + + - name: Tool versions + run: | + tart --version + packer --version + + - name: Pull base image + run: | + tart pull "ghcr.io/cirruslabs/macos-$MACOS_VERSION-base:latest" + + - name: Build runner image + 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 + 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: Push runner image + run: | + tart push "$MACOS_VERSION-xcode:runner" "ghcr.io/cirruslabs/macos-runner:$MACOS_VERSION" + + - name: Cleanup + if: always() + run: | + tart delete "$MACOS_VERSION-xcode:runner" || true diff --git a/.github/workflows/vanilla.yml b/.github/workflows/vanilla.yml new file mode 100644 index 0000000..e450ea5 --- /dev/null +++ b/.github/workflows/vanilla.yml @@ -0,0 +1,127 @@ +name: Vanilla Images + +on: + push: + paths: + - "templates/vanilla-*.pkr.hcl" + workflow_dispatch: + inputs: + macos_version: + description: "macOS vanilla image to build" + required: true + default: all + type: choice + options: + - all + - tahoe + - sequoia + - sonoma + - monterey + +permissions: + contents: read + packages: write + +concurrency: + group: tart-image-builds + cancel-in-progress: false + +env: + TART_REGISTRY_HOSTNAME: ghcr.io + TART_REGISTRY_USERNAME: ${{ github.actor }} + TART_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + +jobs: + update-vanilla: + name: Update Vanilla Image (${{ matrix.macos_version }}) + if: >- + ${{ + github.event_name == 'workflow_dispatch' || + github.ref == format('refs/heads/{0}', github.event.repository.default_branch) + }} + runs-on: [self-hosted, macOS, ARM64] + timeout-minutes: 180 + strategy: + fail-fast: false + max-parallel: 1 + matrix: + macos_version: + - tahoe + - sequoia + - sonoma + - monterey + env: + MACOS_VERSION: ${{ matrix.macos_version }} + RESOLVE_VM_NAME: resolve-macos-number-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.macos_version }} + RESOLVE_FILE: resolve-macos-number-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.macos_version }}.txt + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Select image + id: select + env: + BEFORE_SHA: ${{ github.event.before }} + EVENT_NAME: ${{ github.event_name }} + INPUT_MACOS_VERSION: ${{ inputs.macos_version || 'all' }} + run: | + set -euo pipefail + + build=false + if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then + if [[ "$INPUT_MACOS_VERSION" == "all" || "$INPUT_MACOS_VERSION" == "$MACOS_VERSION" ]]; then + build=true + fi + else + if [[ "$BEFORE_SHA" =~ ^0+$ ]]; then + git diff-tree --no-commit-id --name-only -r "$GITHUB_SHA" > changed-files.txt + else + git diff --name-only "$BEFORE_SHA" "$GITHUB_SHA" > changed-files.txt + fi + + if grep -Fxq "templates/vanilla-$MACOS_VERSION.pkr.hcl" changed-files.txt; then + build=true + fi + 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: Resolve macOS version + id: resolve + if: steps.select.outputs.build == 'true' + run: | + packer build \ + -var "vm_base_name=$MACOS_VERSION-vanilla" \ + -var "vm_name=$RESOLVE_VM_NAME" \ + -var "resolve_file=$RESOLVE_FILE" \ + templates/resolve-macos-number.pkr.hcl + echo "macos_number=$(cat "$RESOLVE_FILE")" >> "$GITHUB_OUTPUT" + rm -f "$RESOLVE_FILE" + + - name: Push vanilla image + if: steps.select.outputs.build == 'true' + run: | + tart push "$MACOS_VERSION-vanilla" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:latest" \ + "ghcr.io/cirruslabs/macos-$MACOS_VERSION-vanilla:${{ steps.resolve.outputs.macos_number }}" + + - name: Cleanup + if: always() && steps.select.outputs.build == 'true' + run: | + tart delete "$MACOS_VERSION-vanilla" || true + tart delete "$RESOLVE_VM_NAME" || true diff --git a/README.md b/README.md index 3474be7..9bc78e4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## macOS Packer Templates for Tart -Repository with Packer templates to build macOS [Tart](https://tart.run/) virtual machines to use with [Cirrus Runners](https://cirrus-runners.app/), -[Cirrus CI](https://cirrus-ci.org/guide/macOS/) or [any other automation](https://tart.run/integrations/cirrus-cli/). +Repository with Packer templates to build macOS [Tart](https://tart.run/) virtual machines to use with self-hosted +GitHub Actions runners, [Cirrus Runners](https://cirrus-runners.app/) or [any other automation](https://tart.run/integrations/cirrus-cli/). The following image variants are currently available: @@ -22,4 +22,4 @@ Please watch this repository releases to get notified about new images. Some of the images are regularly getting rebuild in order to update the pre-installed packages. -[This configuration file](.ci/cirrus.release.yml) defines images that are getting rebuilt monthly on the first Saturday of the month. +[This workflow](.github/workflows/monthly.yml) defines images that are getting rebuilt monthly on the first Saturday of the month.