From 3968515612a1fb66d65da4ec3d450f98807d377d Mon Sep 17 00:00:00 2001 From: Fernando Belotto Date: Thu, 8 Oct 2026 00:16:58 -0300 Subject: [PATCH 1/2] ci: route trusted macOS builds to the M1 Max runner --- .github/actionlint.yaml | 4 +++ .github/workflows/ci.yml | 72 +++++++++++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 0000000..bf3df49 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,4 @@ +self-hosted-runner: + labels: + - ci-build + - windowcleaner-build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 285bdb0..44a353f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,33 +10,49 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read +# This public repository uses a personal, persistent runner. Only the owner can +# trigger these jobs, and PRs must originate from this same repository. Fork and +# external-contributor PRs cannot use this runner; review/import trusted changes +# into an owner-authored repository branch before requesting required CI. jobs: build-and-test: + if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: Build & Test - runs-on: macos-15 + runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] timeout-minutes: 30 + defaults: + run: + shell: /opt/homebrew/bin/python3 /Users/fernando/ci-tools/serial-shell.py {0} + env: + DEVELOPER_DIR: /Users/fernando/ci-tools/Xcode.app/Contents/Developer steps: + - name: Use provisioned build tools + run: | + echo /opt/homebrew/bin >> "$GITHUB_PATH" + test -x "$DEVELOPER_DIR/usr/bin/xcodebuild" - name: Checkout uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Select Xcode + - name: Verify provisioned Xcode run: | - # Use the latest stable Xcode available on the runner - sudo xcode-select -s /Applications/Xcode.app/Contents/Developer xcodebuild -version swift --version - name: Cache DerivedData uses: actions/cache@v4 with: - path: ~/Library/Developer/Xcode/DerivedData - key: ${{ runner.os }}-deriveddata-${{ hashFiles('**/*.swift', '**/project.pbxproj') }} + path: ${{ runner.temp }}/WindowCleaner-DerivedData + key: ${{ runner.os }}-windowcleaner-deriveddata-${{ hashFiles('**/*.swift', '**/project.pbxproj') }} restore-keys: | - ${{ runner.os }}-deriveddata- + ${{ runner.os }}-windowcleaner-deriveddata- - - name: Install xcpretty - run: gem install xcpretty + - name: Verify provisioned xcpretty + run: command -v xcpretty - name: Build run: | @@ -46,6 +62,7 @@ jobs: -scheme WindowCleaner \ -destination "platform=macOS" \ -configuration Debug \ + -derivedDataPath "$RUNNER_TEMP/WindowCleaner-DerivedData" \ -skipPackagePluginValidation \ -skipMacroValidation \ CODE_SIGNING_ALLOWED=NO \ @@ -59,6 +76,7 @@ jobs: -scheme WindowCleaner \ -destination "platform=macOS" \ -configuration Debug \ + -derivedDataPath "$RUNNER_TEMP/WindowCleaner-DerivedData" \ -skipPackagePluginValidation \ -skipMacroValidation \ CODE_SIGNING_ALLOWED=NO \ @@ -76,31 +94,55 @@ jobs: retention-days: 7 lint: + if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: SwiftLint - runs-on: macos-15 + runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] timeout-minutes: 10 + defaults: + run: + shell: /opt/homebrew/bin/python3 /Users/fernando/ci-tools/serial-shell.py {0} + env: + DEVELOPER_DIR: /Users/fernando/ci-tools/Xcode.app/Contents/Developer steps: + - name: Use provisioned build tools + run: | + echo /opt/homebrew/bin >> "$GITHUB_PATH" + test -x "$DEVELOPER_DIR/usr/bin/xcodebuild" - name: Checkout uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Install SwiftLint - run: brew install swiftlint + - name: Verify provisioned SwiftLint + run: swiftlint version - name: Run SwiftLint run: swiftlint --strict --reporter github-actions-logging format-check: + if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: Format Check - runs-on: macos-15 + runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] timeout-minutes: 10 + defaults: + run: + shell: /opt/homebrew/bin/python3 /Users/fernando/ci-tools/serial-shell.py {0} + env: + DEVELOPER_DIR: /Users/fernando/ci-tools/Xcode.app/Contents/Developer steps: + - name: Use provisioned build tools + run: | + echo /opt/homebrew/bin >> "$GITHUB_PATH" + test -x "$DEVELOPER_DIR/usr/bin/xcodebuild" - name: Checkout uses: actions/checkout@v4 + with: + persist-credentials: false - - name: Install SwiftFormat - run: brew install swiftformat + - name: Verify provisioned SwiftFormat + run: swiftformat --version - name: Check Formatting run: | From 2f26fbd6c02ce345e13a36a9e7ecac4f9154dbe8 Mon Sep 17 00:00:00 2001 From: Fernando Belotto Date: Thu, 8 Oct 2026 00:19:43 -0300 Subject: [PATCH 2/2] ci: bound shared-runner queues and shorten development retention --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44a353f..bca77a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: Build & Test runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] - timeout-minutes: 30 + timeout-minutes: 90 defaults: run: @@ -91,13 +91,13 @@ jobs: path: | TestResults.xcresult test-results.xml - retention-days: 7 + retention-days: 1 lint: if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: SwiftLint runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] - timeout-minutes: 10 + timeout-minutes: 90 defaults: run: @@ -124,7 +124,7 @@ jobs: if: github.repository == 'fernandobelotto/WindowCleaner' && github.repository_owner == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor == 'fernandobelotto' && (github.event_name != 'pull_request' || github.event.pull_request.user.login == 'fernandobelotto') name: Format Check runs-on: [self-hosted, macOS, ARM64, ci-build, windowcleaner-build] - timeout-minutes: 10 + timeout-minutes: 90 defaults: run: