GitHub Actions

GitHub Actions intro

GitHub Actions – це платформа CI/CD (Continuous Integration/Continuous Deployment), яка дозволяє автоматизувати ваші тестувальні та розгортальні процеси прямо у вашому репозиторії GitHub. Cypress, Playwirght (та і будь-який інший фреймворк для тестування фронтенду) – це інструмент для автоматизації тестування веб-додатків, що працює безпосередньо в браузері. Щоб використовувати ці фреймворки з GitHub Actions, вам потрібно створити файл workflow у вашому репозиторії GitHub.

GitHub надає віртуальні машини Linux, Windows і macOS для запуску ваших робочих процесів, або ви можете розмістити власні програми запуску у власному центрі обробки даних або хмарній інфраструктурі.

Ми можемо налаштувати воркфлов GitHub Actions на запуск, коли у вашому сховищі відбувається подія, наприклад відкриття PR або створення issue. Ваш робочий цикл містить одне або кілька завдань, які можуть виконуватися послідовно або паралельно. Кожeн step виконуватиметься у власному ранері віртуальної машини або всередині контейнера та має один або кілька кроків, які або запускають сценарій, який ви визначаєте, або дію, яка є розширенням для багаторазового використання, яке може спростити ваш робочий процес.

Використання GitHub Actions безкоштовне для стандартних раннерів, розміщених на GitHub у публічних репо, і для приватного використання раннерів. Для приватних репозиторіїв кожен обліковий запис GitHub отримує певну кількість безкоштовних хвилин і пам’яті для використання з раннерами, розміщеними на GitHub, залежно від плану облікового запису. Будь-яке використання понад включені суми контролюється лімітами витрат.

Більше детальна інфо по типах клаудів і цінах на офіційній документації: https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions

Основні поняття GitHub Actions

workflows

Робочий процес (workflows) — це настроюваний автоматизований процес, який виконуватиме одне або кілька завдань. Робочі процеси описані в файлі YAML, який ви створюєте у вашому репозиторії, і запускатимуться, коли їх ініціює подія у вашому репозиторії, або їх можна запустити вручну чи за визначеним розкладом (cron).

Робочі процеси визначаються в каталозі .github/workflows у репозиторії, і репозиторій може мати кілька робочих процесів, кожен із яких може виконувати інший набір завдань. Наприклад, ви можете мати один робочий процес для створення та тестування PR, інший робочий процес для деплою вашої програми кожного разу, коли створюється реліз, і ще один робочий процес, який додає тег щоразу, коли хтось відкриває issue.

events

Подія — це певна подія в репозиторії, яка запускає робочого процесу(workflows). Наприклад, подія може виникати з GitHub, коли хтось створює PR, відкриває проблему(issue) або надсилає комміт до сховища. Ви також можете запустити робочий процес за розкладом, опублікувавши в REST API або вручну.

jobs

Джоба — це набір кроків у воркфлові, який виконується на одному ранері. Кожен крок є або шелл скриптом, який буде виконано, або дією, яка буде запущена. Кроки виконуються по порядку і залежать один від одного. Оскільки кожен крок виконується на одному ранері, ви можете обмінюватися даними від одного кроку до іншого. Наприклад, у вас може бути крок, який запускає тести, а потім етап, який перевіряє створення рапорті і завантажує репорт.

Можна налаштувати залежність завдання від інших завдань; за замовчуванням завдання не мають залежностей і виконуються паралельно одне одному. Коли завдання стає залежним від іншого завдання, воно чекатиме, поки залежне завдання завершиться, перш ніж його можна буде запустити. Наприклад, у вас може бути кілька завдань збирання для різних архітектур, які не мають жодних залежностей, і завдання пакування, яке залежить від цих завдань. Завдання збирання виконуватимуться паралельно, а коли всі вони будуть успішно завершені, запуститься завдання пакування.

actions

Дія — це спеціальний скрипт для платформи GitHub Actions, яка виконує складне, але часто повторюване завдання. Використовуйте actions, щоб зменшити кількість повторюваного коду, який ви пишете у файлах робочого процесу. actions може отримати до репозиторію з GitHub, налаштувати правильний інструментарій для вашого середовища збірки або налаштувати автентифікацію для вашого клауда.

Є можливість написати власні дії або знайти дії для використання у своїх вокрфловах з GitHub Marketplace.

runners

Ранер — це сервер, який запускає ваші форкфлови, коли вони запускаються. Кожен ранер може виконувати одну роботу за раз. GitHub надає доступ до платформ Ubuntu Linux, Microsoft Windows і macOS для запуску форкфловів; кожен запуск форкфлову виконується на новій, щойно створеній віртуальній машині. GitHub також пропонує більші ранери, які доступні у більших конфігураціях (з збільшеним характеристиками ЦП, ОЗУ, памʼяті). Але ці банери зі збільшеними ресурсами доступні лише за кошти.

YAML

Файли YML (або YAML, що розшифровується як “YAML Ain’t Markup Language”) є вельми популярним вибором для конфігураційних файлів, особливо у сфері розробки програмного забезпечення та DevOps. Ось декілька причин, чому файли YML вважаються корисними:

Легкість читання

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

Структуровані дані

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

Мінімалізм

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

Мовно-незалежний

YAML не залежить від певної мови програмування, що робить його універсальним рішенням для конфігурації у різноманітних середовищах та проектах.

Підтримка складних типів даних

YAML підтримує різноманітні типи даних, включаючи рядки, числа, дати, масиви та вкладені об’єкти, дозволяючи детально конфігурувати велику кількість аспектів програми або процесу.

Широка підтримка

Багато інструментів DevOps, таких як Docker, Kubernetes, Ansible, і звичайно, GitHub Actions, підтримують YAML як основний формат для своїх конфігураційних файлів, забезпечуючи широку сумісність.

Вбудовані коментарі

YAML дозволяє додавати коментарі безпосередньо в конфігураційні файли, роблячи процес документації логіки та прийнятих рішень більш інтуїтивним. Якщо порівнювати з json форматом для зберігання конфігів – то YAML з вбудованою підтримкою коментів виграє і значно спрощує використання.

Ці характеристики роблять YAML дуже привабливим для використання в різноманітних задачах, особливо там, де потрібен чистий, лаконічний та гнучкий формат для визначення даних або конфігурації

name: <name of your workflow>

on: <event or list of events>

jobs:
  job_1:
    name: <name of the first job>
    runs-on: <type of machine to run the job on>
    steps:
      - name: <step 1>
        run: |
          <commands>
      - name: <step 2>
        run: |
          <commands>
  job_2:
    name: <name of the second job>
    runs-on: <type of machine to run the job on>
    steps:
      - name: <step 1>
        run: |
          <commands>
      - name: <step 2>
        run: |

Події для запуску

Конфігурація для запуску по розкладу

on:
  schedule:
    # * is a special character in YAML so you have to quote this string
    - cron:  '30 5,17 * * *'

Можна налаштувати виконання воокрфлову в певний час UTC за допомогою синтаксису POSIX cron. Воркфлови будуть виконуватися на останньому коміті в гілці за замовчуванням або в основній гілці. Найкоротший інтервал, з яким можна запускати форкфлови, – кожні 5 хвилин.

Запуск на одній події

on: push

Запуск на кількох подіях – наприклад на пуші або коли хтось робить форт репозиторію.

on: [push, fork]

Запуск тестів при подіях які відбуваються для певних гілок в репозиторії.

on:
  push:
    branches:
      - main

Запуск тестів на PR

on:
  pull_request:

Для додаткового контролю і пропуску тригеру воркфлову для гілок які підпають під паттерн який можна зазначити в кроці branches-ignore

branches-ignore:    
      - 'mona/octocat'
      - 'releases/**-alpha'

Конфігурація для одночасного трігеру воркфлову і також для ігнорування специфічних гілок можна додати таким чином – ! знак в конфігуруції буде означати ігнорування бранчі для запуску воркфлову.

on:
  pull_request:
    branches:    
      - 'releases/**'
      - '!releases/**-alpha'

Якщо шлях до файлу збігаютється з шаблонами в paths-ignore, воркфлов не запускатиметься. Якщо шляхи не відповідають шаблонам у paths-ignore, навіть якщо деякі назви шляхів відповідають шаблонам, воркфлов буде запущено.

Воркфлов з фільтром шляху запускатиметься лише для подій push, які включають принаймні один файл поза каталогом документів у корені сховища.

on:
  push:
    paths-ignore:
      - 'docs/**'

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

on:
  issues:
    types:
      - closed
  pull_request:
    types:
      - closed
			- opened
	    - labeled
			- created
			- edited

yaml for cypress (ч.1)

Приклад простого воркфлову для запуску усіх тестів які є в репозиторії

Цей воркфлов можна налаштувати першим і запусти для перевірки налаштувань

name: End-to-end tests
on: push
jobs:
  cypress-run:
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      # Install npm dependencies, cache them correctly
      # and run all Cypress tests
      - name: Cypress run
        uses: cypress-io/github-action@v6

Запуск тестів на різних браузерах

Chrome

name: Chrome
on: push
jobs:
  chrome:
    runs-on: ubuntu-22.04
    name: E2E on Chrome
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          browser: chrome

Firefox

name: Firefox
on: push
jobs:
  firefox:
    runs-on: ubuntu-22.04
    name: E2E on Firefox
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          browser: firefox

Edge

name: Edge
on: push
jobs:
  edge:
    runs-on: ubuntu-22.04
    name: E2E on Edge
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          browser: edge

❗якщо не передавати параметр по запуску браузера – то усі тести будуть проганятися в electron.

Запуск з параметром headed

name: Chrome headed
on: push
jobs:
  cypress-run:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          browser: chrome
          headed: true

❗по дефолту усі тести будуть запускатися з параметром headless

Запуск тестів в docker контейнері:

name: Test in Docker
on: push
jobs:
  cypress-run:
    runs-on: ubuntu-22.04
    # Cypress Docker image from https://hub.docker.com/r/cypress
    # with browsers pre-installed
    container:
      image: cypress/browsers:latest
      options: --user 1001
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          browser: chrome

Передача параметрів запуску з env. variables з env параметром

name: Cypress tests
on: push
jobs:
  cypress-run:
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Cypress run with env
        uses: cypress-io/github-action@v6
        with:
          env: host=api.dev.local,port=4222

якщо потрібно передавати список параметрів – то це потрібно робити в одну стрічку, і через кому.

Можна створити env.variables всередині воркфлову. Не варто додавати будь-які критичні (паролі, ключі доступу) у відкриті репозиторії.

env:
  DAY_OF_WEEK: Monday
	ENV_VAR: url
	ENV_VAR_2: 3000

Запуск специфічних файлів з тестами з параметром spec

name: Cypress tests
on: push
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          spec: cypress/e2e/spec1.cy.js

Для запуску кількох файлів – можна передавати шлях до кількох файлів. Або використати glob паттерн.

spec: |
  cypress/e2e/spec-a.cy.js
  cypress/**/*-b.cy.js

yaml for cypress (ч.2)

Для запуску команди з файлу package.json використати command

steps:
  - name: Checkout 🛎
    uses: actions/checkout@v4

  - name: Custom tests 🧪
    uses: cypress-io/github-action@v6
    with:
      command: npm run e2e:ci

❗при використанні command інші параметри будуть ігноруватися: auto-cancel-after-failuresbrowserci-build-idcommand-prefixcomponentconfigconfig-fileenvgroupheadedparallelprojectpublish-summaryquietrecordspec ,tag

Завантаження результатів тестів на cypress cloud

name: Cypress tests
on: push
jobs:
  cypress-run:
    name: Cypress run
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          record: true
        env:
          # pass the Cypress Cloud record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
          # pass GitHub token to allow accurately detecting a build vs a re-run build
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Для успішного виконнаня коду потрібно передати через env. variables Cypress key & GitHub token.

Генерація ключів

для генерації CYPRESS_RECORD_KEY потрібно зареєструватися на Cypress Cloud і після генерації токена помістити в сікрети.

для генерації GITHUB_TOKEN потрібно пройти кроки https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens

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

Створення секретів

потім потрібно додати токен в сікрети для репозиторію

  1. клікнути на лінку settings

2.у вкладці “Security” знайти, і вибрати  Secrets and variables, потім Actions.

3.потім знайти лінк Secrets

4.клікнути на кнопку New repository secret

5.в поле Name додати назву сікрета – назва має збігатися з тією яка буде використана в воркфлові.

6.в поле Secret додати значення яке згенерували раніше

7.і клікнути зберегти

8.таку ж процедура пройти для ключа для Cypress Cloud

❗тепер сікрети будуть доступні для використання у воркфловах.

Завантаження результатів/артефактів на GitHub

name: Artifacts
on: push
jobs:
  cypress-run:
    runs-on: ubuntu-22.04
    name: Artifacts
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
      # after the test run completes store videos and any screenshots
      - uses: actions/upload-artifact@v3
        # add the line below to store screenshots only on failures
        # if: failure()
        with:
          name: cypress-screenshots
          path: cypress/screenshots
          if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to `warn`
      - uses: actions/upload-artifact@v3
        with:
          name: cypress-videos
          path: cypress/videos
          if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to `warn`

Паралельний запуск тестів.

! Для розпаралелювання Cypress потрібен обліковий запис Cypress Cloud і використання ключа доступу.

Ви можете обертати декілька контейнерів, що працюють паралельно, використовуючи аргумент стратегія: матриця. Для зміни паралельних потоків змінюйте кількість у масиві контейнерів: [1, 2, …], щоб отримати більше безкоштовних або платних контейнерів. Потім використовуйте параметри запису та паралелі для перевірки балансу навантаження.

name: Parallel Cypress Tests
on: push
jobs:
  test:
    name: Cypress run
    runs-on: ubuntu-22.04
    strategy:
      # when one test fails, DO NOT cancel the other
      # containers, because this will kill Cypress processes
      # leaving Cypress Cloud hanging ...
      # https://github.com/cypress-io/github-action/issues/48
      fail-fast: false
      matrix:
        # run 3 copies of the current job in parallel
        containers: [1, 2, 3]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # because of "record" and "parallel" parameters
      # these containers will load balance all found tests among themselves
      - name: Cypress run
        uses: cypress-io/github-action@v6
        with:
          record: true
          parallel: true
          group: 'Actions example'
        env:
          # pass the Cypress Cloud record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
          # Recommended: pass the GitHub token lets this action correctly
          # determine the unique run id necessary to re-run the checks
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Генерація кастомного ідентифікатора для Cypress Cloud

Якщо ви повторно запустите воркфлов, і використовуєте той самий ідентифікатор для іншого воркфлову, Cypress Cloud скасує запуск із повідомленням про помилку «Збірка вже завершена». Щоб уникнути цього, вам потрібно створити новий ідентифікатор спеціальної збірки під час кожного повторного запуску робочого процесу. Хорошим рішенням, показаним у прикладі, є запуск такси під назвою prepare, яка просто генерує новий випадковий ідентифікатор. Цей ідентифікатор може використовуватися завданнями тестування, щоб зв’язати збірку разом. Якщо користувач повторно запускає воркфлов, генерується новий унікальний ідентифікатор збірки, що дозволяє записати новий запуск Cypress Cloud.

jobs:
  # single job that generates and outputs a common id
  prepare:
    outputs:
      uuid: ${{ steps.uuid.outputs.value }}
    steps:
      - name: Generate unique ID 💎
        id: uuid
        # take the current commit + timestamp together
        # the typical value would be something like
        # "sha-5d3fe...35d3-time-1620841214"
        run: echo "value=sha-$GITHUB_SHA-time-$(date +"%s")" >> $GITHUB_OUTPUT
  smoke-tests:
    needs: ['prepare']
    steps:
      - uses: actions/checkout@v4
      - uses: cypress-io/github-action@v6
        with:
          record: true
          parallel: true
          ci-build-id: ${{ needs.prepare.outputs.uuid }}
        env:
          # pass the Cypress Cloud record key as an environment variable
          CYPRESS_RECORD_KEY: ${{ secrets.EXAMPLE_RECORDING_KEY }}

yaml for playwright

Воркфлов для встановлення усіх залежностей проекту, для запуску усіх тестів, генерацію рапортів, завантаження на GitHub

name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 18
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npx playwright test
    - uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

Запуск тестів в docker контейнері

name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  playwright:
    name: 'Playwright Tests'
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/playwright:v1.39.0-jammy
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - name: Install dependencies
        run: npm ci
      - name: Run your tests
        run: npx playwright test

По дефолту html репорт недоступний для перегляду на GitHub тому потрібно налаштувати стороннє сховище і сторінку де можна переглянути репорт.

Або додати завантаження артефактів на GitHub за допомогою кроку

- name: Save report
  uses: actions/upload-artifact@v3
	with: 
		path: html/report
		name: Main report
	if: failure() || success()
- name: Get report
	uses:  actions/download-artifact@v3
	with:
		name: Main report
	if: failure() || success()

Підсумок

На цій лекції розібралися з осноарими пунктами налаштування запуску автоматизованих тестів на сторонніх середовищах – сьогодні на Github Actions. Цей CI/CD інструмент дозволяє безкоштовно налаштувати процес запуску Е2Е тестів для фреймворків які ми розглядали раніше – Cypress & Playwright.

Розглянули основні налаштування:

  • створення workflows з нуля
  • огляд основних кроків всередині воркфлову
  • імплементація кастомних команд з файлу packge.json
  • інтеграція з сторонами тулами для запуску тестів – Cypress Cloud.
  • налаштування кроку по збереження репортів на гітхабі

Розглянули плюси використання YAML файлів для збереження конфігів проекту.