СодержаниеGitHub Actions на macOS может быть дорогимСоветы по экономии денегПо возможности используйте runner на базе LinuxЗапуск задания одновременноИзбегайте выполнения рабочего процесса с помощью фильтровВнимание: обязательные проверки статуса и пропуск рабочих процессовВ этом сообщении блога я делюсь советами о том, как наиболее эффективно использовать GitHub Actions и избежать лишнего времени выполнения и денежных затрат.Я предполагаю, что вы знакомы с GitHub Actions и уже использовали их, но вот краткий обзор:GitHub Actions — это встроенный инструментарий CI/CD, который позволяет определять рабочие процессы и задания, запускаемые при определенных событиях GitHub (например, push или pull_request) на вашем репозитории.Вам необходимо определить тип машины, на которой выполняется задание. Это может быть: самостоятельный runner (раннер, например, локальный Mac Mini у вас дома) или раннер, размещенный на GitHub.Существует несколько типов раннеров, размещенных на GitHub, но часто вам понадобится образ раннера на основе macOS.Так в чём проблема?Раннер – программное обеспечение, предназначенное для автоматизации выполнения заданий. GitHub Actions на macOS может быть дорогимХорошей новостью является то, что использование GitHub Actions не связано с публичными репозиториями.Но будьте осторожны, если вы используете приватный репозиторий!Для приватных репозиториев каждая учётная запись GitHub получает определенное количество бесплатных минут и хранилища для использования с раннерами, размещёнными на GitHub, в зависимости от продукта, используемого с учетной записью. Любое использование сверх включенных величин контролируется лимитами расходов.Образы раннера на базе MacOS затратны для GitHub, поэтому GitHub применяет минутный множитель.Использование 1000 минут macOS потребует 10 000 минут, включенных в вашу учётную запись. После того, как вы израсходуете весь свой бюджет, оплата раннеров для macOS становится дорогой из-за этого множителя.Использование образа раннера на базе macOS обходится в десять раз дороже, чем на базе Linux.Источник: About billing for GitHub ActionsСоветы по экономии денегПо возможности используйте раннер на базе Linux.Это несложно, но всё же стоит упомянуть.Если вы хотите проверить pull request, вы можете использовать для этой работы раннер на базе Linux. В ubuntu-latest установлен Swift.jobs: SwiftLint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: GitHub Action for SwiftLint uses: norio-nomura/action-swiftlint@3.2.1Такие инструменты, как SwiftLint или SwiftFormat, работают в Linux, поскольку они не зависят от специфичных для Apple фреймворков.К вашему сведению: в январе 2023 года ubuntu-latest ссылается на образ раннера ubuntu-22.04, который поставляется с предустановленной версией Swift 5.7.3.Запуск задания одновременноЯ не хочу избегать параллельных заданий, потому что здорово, что вы можете определить матричную стратегию для автоматического создания нескольких запусков заданий, основанных на комбинациях переменных.Вот пример сборки пакета Swift на iOS для разных версий Swift:Swift 5.7.1, который поставляется с Xcode 14.1;Swift 5.5, который поставляется с Xcode 13.jobs: build-macOS: name: Xcode ${{ matrix.xcode }} runs-on: ${{ matrix.runner-image }} env: DEVELOPER_DIR: "/Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer" strategy: fail-fast: false matrix: # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md#xcode # https://github.com/actions/runner-images/blob/main/images/macos/macos-11-Readme.md#xcode include: - xcode: "14.1" runner-image: macOS-12 name: "macOS 12, Xcode 14.1, Swift 5.7.1" - xcode: "13.0" runner-image: macOS-11 name: "macOS 11, Xcode 13.0, Swift 5.5.0" steps: - uses: actions/checkout@v3 - name: Build (${{ matrix.name }}) run: set -o pipefail && xcodebuild -project -scheme YourPackageName-Package -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11' clean test | xcprettyВернёмся к теме. Я имею в виду, что вы должны избегать одновременного выполнения одной и той же работы, логически принадлежащей одной и той же группе. Поясню на примере:Я создаю pull request, и запускается рабочий процесс.Вы заметили, что забыли добавить файл, поэтому выполняете push и добавляете в свой pull request.Предыдущий рабочий процесс всё ещё выполняется, и запускается новый рабочий процесс – это пример избыточного параллельного рабочего процесса/задания.Для данного примера было бы лучше, если бы GitHub немедленно отменил выполнение предыдущего рабочего процесса.Это возможно с помощью jobs.<job_id>.concurrency, чтобы гарантировать, что только одно задание или рабочий процесс, использующий одну и ту же группу параллелизма, будет выполняться одновременно. Группа параллелизма может быть любой строкой или выражением. Пример использования параллелизма для отмены любого незавершённого задания или выполнения:concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: trueНапример, популярный XcodeProj от Tuist использует эту функцию.# https://github.com/tuist/XcodeProj/blob/8.8.0/.github/workflows/xcodeproj.yml concurrency: group: xcodeproj-${{ github.head_ref }} cancel-in-progress: trueДополнительную информацию можно найти в документации GitHub Using Concurrency.Избегайте выполнения рабочего процесса с помощью фильтровНужно ли вам создавать исходный код Swift, если вы обновили только файл README?Нет! Используйте фильтр путей, если вы хотите рассмотреть шаблоны путей к файлам.Мне нравится определять следующий рабочий процесс в .github/workflows/ci-build.yml:name: ci on: push: paths: - ".github/workflows/**" - "**/*.swift" pull_request: paths: - ".github/workflows/**" - "**/*.swift"Изменения, связанные с исходным кодом (а также изменения, связанные с рабочим процессом), запускают рабочий процесс, но такие файлы, как README, не запускают рабочий процесс.Внимание: обязательные проверки статуса и пропуск рабочих процессовВозможно, вы настроили проверку состояния, чтобы рабочий процесс был успешным, прежде чем запрос на вытягивание будет объединён.Но если рабочий процесс пропускается из-за фильтрации путей (или фильтрации ветвей, или сообщения фиксации), то проверки, связанные с этим рабочим процессом, останутся “Pending” (ожидающими), а pull request будет заблокирован от слияния (merging).Одним из решений может быть Using conditions to control job execution (использование условий для управления выполнением задания), но я считаю, что у GitHub есть лучшее решение.Давайте создадим дополнительный рабочий процесс, определенный в .github/workflows/ci-build-skiped.yml:name: ci on: push: paths-ignore: - ".github/workflows/**" - "**/*.swift" pull_request: paths-ignore: - ".github/workflows/**" - "**/*.swift" jobs: build: runs-on: ubuntu-latest steps: - run: 'echo "No build required"'Определив дополнительный рабочий процесс с помощью инструментов:идентичный рабочий процесс и имя задания;использование paths-ignore (путей игнорирования) в качестве аналогаМы можем гарантировать выполнение минимального рабочего процесса/задания и, следовательно, проверку статуса.Убедитесь, что ключ имени и требуемое имя задания в обоих файлах рабочего процесса совпадают.Дополнительные сведения см. в документации GitHub Handling skipped but required checks.Оригинал статьиПодписывайся на наши соцсети: Telegram / VKontakteВступай в открытый чат для iOS-разработчиков: t.me/swiftbook_chat