GitHub Actions: найкращі практики


Цей робочий документ містить набір найкращих практик роботи з GitHub Actions. Якщо є якісь пропозиції чи доповнення, відкрийте pull request на GitHub!

Набір найкращих практик

Установімо тайм-аути для робочих процесів

Типово GitHub Actions зупиняє робочі процеси через 6 годин, якщо ті не встигли завершитися до того часу. Багатьом робочим процесам потрібно значно менше часу на завершення, але іноді трапляються несподівані помилки або завдання зависає, доки запуск робочого процесу не зупинять через 6 годин після його початку. Тому радимо вказати коротший тайм-аут.

Ідеальний тайм-аут залежить від конкретного робочого процесу, але 30 хвилин зазвичай більш ніж достатньо для робочих процесів у репозиторіях Exercism.

Це дає такі переваги:

  • PR не витрачатимуть пів дня на очікування CI, проблеми вдасться помітити раніше, а запуски робочих процесів можна перезапустити.
  • Кількість загалом паралельних збірок обмежена, тож завислі завдання не завдаватимуть клопоту іншим PR, якщо їх скасувати рано.

Приклад

jobs:
  configlet:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - [...]

Подумаймо, чи справді потрібні (сторонні) дії

До дій варто ставитися як до залежностей в улюбленій мові програмування1: це код, написаний сторонніми авторами поза контролем Exercism. Навіть якщо ми довіряємо авторам дії, репозиторій можуть вороже захопити, і це опосередковано дасть цим людям доступ до репозиторіїв Exercism, зокрема й на запис.

Тому варто уважно зважити, чи справді варто додавати нову дію, чи краще перенести код у (нову) дію під контролем Exercism.

Також подумаймо, чи дію активно підтримують: наприклад, перевірмо недавню активність репозиторію або переконаймося, що дія належить організації, а не окремому акаунту.

Дії, опубліковані GitHub або організацією Exercism, загалом можна вважати (більш-менш) безпечними, щоб додавати їх без особливих роздумів.

Обмежмо область дії токена робочого процесу

Типово токен доступу, наданий робочому процесу, має широкі права як на читання, так і на запис.

Принцип найменших привілеїв варто застосовувати і до робочих процесів.

Можна вказати, які дозволи потрібні робочому процесу, окремо для кожного робочого процесу.

Приклад

Якщо робочому процесу потрібно лише читати вміст репозиторію, а не записувати до нього, наприклад, бо це звичайна перевірка CI, можна обмежити токен так:

permissions:
  contents: read

Повний список дозволів дивіться в документації GitHub.

Привʼяжімо дії до SHA

Використовуючи інші дії, привʼязуймо їх до коміту (за його SHA), а не до гілки чи тегу. Це гарантує, що щоразу виконуватиметься той самий код, чого не можна гарантувати, якщо привʼязувати до гілки чи тегу.

Це дає дві переваги:

  1. Це робить збірку стабільною
  2. Це заважає зловмиснику змінити гілку чи тег так, щоб вони вказували на шкідливий код

Єдиний виняток із цього правила, можливо, це дії, які ми (Exercism) створили самі.

Як знайти SHA коміту

Зазвичай ми хочемо привʼязатися до SHA коміту конкретного релізу. Щоб знайти SHA коміту релізу, перейдіть на сторінку релізів репозиторію дії (наприклад, https://github.com/actions/checkout/releases). Знайдіть потрібний реліз і натисніть на скорочений SHA (наприклад, a12a394), наведений у розділі зведення ліворуч від релізу. Після цього відкриється сторінка з подробицями релізу, де буде вказано повний SHA коміту, який можна використати.

Приклад

- name: Checkout code
  uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846

Привʼяжімо тестові раннери до версії

Більшість робочих процесів виконуються на підтримуваних раннерах GitHub. Використовуючи один із цих раннерів, вказуйте конкретну версію замість останньої.

Це гарантує, що робочий процес завжди виконуватиметься на тому самому раннері, що робить збірку стабільною.

Приклад

Використовуйте:

runs-on: ubuntu-22.04

замість:

runs-on: ubuntu-latest

Подумаймо, чи варто налаштувати стратегію конкурентності

Часто немає ні потреби, ні сенсу запускати CI на проміжних комітах, якщо тим часом уже надіслано новіший коміт.

Можна налаштувати стратегію конкурентності, щоб автоматично скасовувати запущені робочі процеси в тому самому контексті.

Приклад

Щоб скасовувати проміжні збірки в PR, можна використати такі налаштування конкурентності:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
Повідомлення про сторонні матеріали

Наведений вище приклад ґрунтується на CI-робочому процесі PkgTemplates.jl, опублікованому за ліцензією MIT:

MIT License

Copyright (c) 2017-2020 Chris de Graaf, Invenia Technical Computing Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Подумаймо, які тригери справді потрібні

Прочитаймо посібник «Security hardening for GitHub Actions»

Перелічені вище практики аж ніяк не вичерпні. Щоб отримати вичерпний посібник із добрих практик безпечного використання GitHub Actions, зазирніть до посібника GitHub з безпеки.

Контрольний список робочого процесу

Скористаймося наведеним нижче контрольним списком, щоб перевірити, чи дотримується робочий процес найкращих практик. Контрольний список не претендує на повноту, він зосереджується на найважливіших пунктах.

Версія для копіювання, наприклад, для PR

  1. якщо тільки мова не використовує екосистему npm. ↩