Spec-Zone.ru › Crystal

GitHub Actions

Сборка и запуск тестов

Чтобы постоянно тестировать наше примерное приложение — как при отправке коммита, так и когда кто-нибудь открывает pull request, добавьте этот минимальный файл рабочего процесса:

.github/workflows/ci.yml
on:
  push:
  pull_request:
    branches: [master]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Download source
        uses: actions/checkout@v2
      - name: Install Crystal
        uses: crystal-lang/install-crystal@v1
      - name: Run tests
        run: crystal spec

Чтобы начать работу с GitHub Actions, добавьте этот YAML-файл в свой Git-репозиторий в каталог .github/workflows/, отправьте его на GitHub и откройте вкладку Actions.

Быстрый старт

Воспользуйтесь конфигуратором для действия install-crystal, чтобы быстро получить конфигурацию с необходимыми функциями CI. Или продолжайте читать, чтобы узнать больше.

Рабочий процесс запускается в контейнере «последняя версия Ubuntu» по умолчанию, предоставляемом GitHub: ссылка. Он загружает исходный код из самого репозитория (непосредственно в текущий каталог), устанавливает Crystal с помощью официального GitHub Action для Crystal, а затем запускает тесты, предполагая, что они находятся в каталоге spec/.

Если какой-либо шаг завершится с ошибкой, сборка будет помечена как неудачная, автор получит уведомление, а в случае отправки коммита общий статус сборки проекта станет неудачным.

Совет

Чтобы повысить качество кодовой базы, рассмотрите возможность использования следующих флагов для crystal spec:
--order=random --error-on-warnings

Нет тестов?

Если покрытие тестами невысокое, рассмотрите возможность добавить хотя бы пример программы и собирать его в рамках CI:

Для библиотеки:

          - name: Build example
            run: crystal build examples/hello.cr

Для приложения (это очень полезно, даже если у вас есть тесты):

          - name: Build
            run: crystal build src/game_of_life.cr

Тестирование с разными версиями Crystal

По умолчанию устанавливается последняя выпущенная версия Crystal. Но вы также можете тестировать ночную сборку Crystal и, возможно, некоторые более старые версии, поддержку которых ваш проект всё ещё обеспечивает. Измените начало файла рабочего процесса следующим образом:

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        crystal: [0.35.1, latest, nightly]
    runs-on: ubuntu-latest
    steps:
      - name: Download source
        uses: actions/checkout@v2
      - name: Install Crystal
        uses: crystal-lang/install-crystal@v1
        with:
          crystal: ${{ matrix.crystal }}
      - ...

Все эти версии будут тестироваться параллельно.

Указав версию Crystal, вы можете даже отказаться от поддержки последней версии (которая постоянно меняется) и поддерживать только определённые версии.

Тестирование в нескольких операционных системах

Обычно разработчики запускают тесты только в Ubuntu, и этого достаточно, если в коде нет платформозависимых частей. Но добавить ещё одну систему в матрицу тестирования несложно: просто добавьте следующее в начало определения задания:

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - ...

Установка пакетов Shards

В большинстве проектов есть внешние зависимости — «shards». Объявив их в shard.yml, просто добавьте шаг установки в рабочий процесс (после install-crystal и перед любым тестированием):

      - name: Install shards
        run: shards install

Последние версии зависимостей или зафиксированные версии?

Если в репозитории хранится файл shard.lock (обычно это полезно для приложений), учитывайте его влияние на CI: shards install всегда устанавливает точные версии, указанные в этом файле. Но если вы разрабатываете библиотеку, вероятно, вам стоит первым узнать, если новая версия зависимости нарушит её установку: иначе об этом узнают пользователи, поскольку файл блокировки не применяется транзитивно. Поэтому настоятельно рекомендуем запускать shards update вместо shards install либо не хранить в репозитории shard.lock. В таком случае имеет смысл добавить в репозиторий запуски по расписанию.

Установка бинарных зависимостей

Нашему приложению или некоторым shards могут потребоваться внешние библиотеки. Способы их установки могут сильно различаться. Обычно пакеты в Ubuntu устанавливают с помощью команды apt.

Добавьте шаг установки ближе к началу рабочего процесса. Например, для libsqlite3:

      - name: Install packages
        run: sudo apt-get -qy install libsqlite3-dev

Проверка форматирования кода

Если вы хотите убедиться, что весь ваш код отформатирован с помощью crystal tool format, добавьте соответствующую проверку в качестве шага ближе к концу рабочего процесса. Если кто-то отправит неправильно отформатированный код, сборка завершится с ошибкой, как и при неудачном прохождении тестов.

      - name: Check formatting
        run: crystal tool format --check

Также рассмотрите возможность добавить эту проверку для себя в качестве хука Git pre-commit.

Использование официального образа Docker

Мы использовали «действие» для установки Crystal в образ ОС по умолчанию, предоставляемый GitHub. У этого подхода есть несколько преимуществ. Но вместо этого вы можете использовать официальные образы Docker для Crystal, хотя такой вариант подходит только для Linux.

В этом случае базовая конфигурация будет выглядеть так:

.github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: crystallang/crystal:latest
    steps:
      - name: Download source
        uses: actions/checkout@v2

      - name: Run tests
        run: crystal spec

Среди других вариантов контейнеров есть crystallang/crystal:nightly, crystallang/crystal:0.36.1, crystallang/crystal:latest-alpine.

Кэширование

Загрузка и установка зависимостей (в частности, shards) при каждом запуске выполняются с нуля. Кэширование в GitHub Actions позволяет избежать части этой повторной работы.

Надёжный способ — добавить шаг actions/cache (перед шагом, в котором используется shards) со следующим определением:

      - name: Cache shards
        uses: actions/cache@v2
        with:
          path: ~/.cache/shards
          key: ${{ runner.os }}-shards-${{ hashFiles('shard.yml') }}
          restore-keys: ${{ runner.os }}-shards-
      - name: Install shards
        run: shards update

Важно

Необходимо использовать отдельные key и restore-keys. Если использовать только статический ключ, в кэше сохранится состояние после самого первого запуска, и оно будет повторно использоваться бесконечно, независимо от любых изменений.

Однако это позволяет сэкономить только время, затрачиваемое на первоначальную загрузку репозиториев.

Более «смелый» подход — кэшировать сам каталог lib, но он работает только в том случае, если вы полностью полагаетесь на shard.lock (см. Последние версии зависимостей или зафиксированные версии?):

      - name: Cache shards
        uses: actions/cache@v2
        with:
          path: lib
          key: ${{ runner.os }}-shards-${{ hashFiles('**/shard.lock') }}
      - name: Install shards
        run: shards check || shards install

Обратите внимание, что мы также сделали установку условной — она выполняется, только если есть shards check. Это позволяет сэкономить ещё немного времени.

Публикация исполняемых файлов

Если ваш проект — приложение, вероятно, вы захотите распространять его в виде исполняемого («бинарного») файла. Для Linux x86_64 наиболее популярный вариант — собрать файл и выполнить статическую компоновку в Alpine Linux. Это означает, что использовать контейнер Ubuntu по умолчанию и действие установки от GitHub нельзя. Вместо этого используйте официальный контейнер:

.github/workflows/release.yml
jobs:
  release_linux:
    runs-on: ubuntu-latest
    container:
      image: crystallang/crystal:latest-alpine
    steps:
      - uses: actions/checkout@v2
      - run: shards build --production --release --static --no-debug

После этих шагов следует добавить действие для публикации полученного исполняемого файла (bin/*) одним из двух способов (или обоими):

  • В составе релиза: см. полный пример.
    Затем в README можно добавить ссылку на последний релиз, используя URL, например https://github.com/:username/:reponame/releases/latest

  • В составе CI, выполняемого при каждом коммите, с помощью actions/upload-artifact.
    В этом случае можно добавить ссылку на последнюю ночную сборку через внешний сервис https://nightly.link/

Также можно распространять исполняемые файлы для macOS (поиск примеров) и Windows (поиск примеров).

To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/1.2/guides/ci/gh-actions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API