Learn (Almost) Anything
КаталогСкачать курс

Автоматизация в GitHub

Как выпускать и поддерживать actions: semantic tags, immutable releases, changelog, Marketplace metadata, deprecation policy и backward compatibility.

ruЭнциклопедия33 урока6 модулей9
GitHub actionsАвтоматизация в GitHubМодель workflowсостояние и артефактыматрицы и runtimeрелизы и environmentsПереиспользование и собственные actionsgovernance и эксплуатацияgithubactions

Versioning и maintenance actions

Как выпускать и поддерживать actions: semantic tags, immutable releases, changelog, Marketplace metadata, deprecation policy и backward compatibility.

Versioning и maintenance actions

Версионирование action — это публичный контракт между автором и workflow, которые эту action вызывают. В обычной библиотеке breaking change ломает сборку после обновления dependency. В GitHub Actions хуже: чужой uses: owner/action@v1 может стоять в CI, release pipeline или production deploy. Поэтому maintenance action — это не только «поставить tag», а дисциплина: какие версии считаются совместимыми, какие tags можно двигать, где нужен immutable release, что написано в changelog и как заранее предупредить пользователей о deprecation.

Action может быть Composite actions, JavaScript actions или Docker container actions, но release-логика для всех похожа: metadata в action.yml, тесты до публикации, release notes, понятные tags и политика совместимости.

flowchart TD A[PR в action repo] --> B[CI: tests, lint, smoke workflow] B --> C{Breaking change?} C -- нет --> D[Patch/minor release: v1.4.2] C -- да --> E[Major release: v2.0.0] D --> F[Draft GitHub Release] E --> F F --> G[Release notes + assets] G --> H[Publish immutable release для точного tag] H --> I[Обновить floating tags v1 / v1.4, если они не release-bound] I --> J[README, changelog, Marketplace metadata, deprecation notes]
flowchart TD
  A[PR в action repo] --> B[CI: tests, lint, smoke workflow]
  B --> C{Breaking change?}
  C -- нет --> D[Patch/minor release: v1.4.2]
  C -- да --> E[Major release: v2.0.0]
  D --> F[Draft GitHub Release]
  E --> F
  F --> G[Release notes + assets]
  G --> H[Publish immutable release для точного tag]
  H --> I[Обновить floating tags v1 / v1.4, если они не release-bound]
  I --> J[README, changelog, Marketplace metadata, deprecation notes]
Типичный цикл выпуска action: от PR до release notes и обновления tags.

Что именно версионируется

Публичный API action — это не только код. Для пользователя API состоит из:

- uses: acme/release-notes@v1
  with:
    changelog-path: CHANGELOG.md
    fail-on-missing: "true"

Здесь контрактом являются имя action, inputs, outputs, side effects, требуемые permissions, поддерживаемые runners, формат файлов, exit codes и даже ожидаемые annotations в логах. Если вы переименовали input, изменили default, перестали поддерживать Windows runner или начали требовать contents: write, это может быть breaking change.

Для Reusable workflows контракт ещё шире: workflow_call inputs, secrets, outputs, jobs, environments и permissions. Но принцип тот же: всё, что caller должен знать заранее, относится к совместимости.

SemVer: v1.4.2, v1.4, v1

На практике для actions обычно используют Semantic Versioning: MAJOR.MINOR.PATCH. Patch — совместимый bugfix, minor — новая совместимая функциональность, major — несовместимое изменение. У GitHub Actions есть своя привычка поверх SemVer: публиковать точный tag v1.4.2 и дополнительно поддерживать moving tags v1.4 и v1.

Пример ожиданий:

v1.4.2  -> конкретный immutable-ish release, удобно для воспроизводимости
v1.4    -> последняя patch-версия в ветке 1.4.x
v1      -> последняя совместимая версия major-линейки 1.x
main    -> development branch; не рекомендуется для пользователей
SHA     -> максимальная фиксация, но без автоматических bugfix-обновлений

GitHub Docs рекомендует не заставлять пользователей ссылаться на default branch: main может содержать ещё нестабильный код. Хороший README показывает спокойный default:

- uses: acme/release-notes@v1

А рядом объясняет более строгие варианты:

# Фиксация на конкретный patch release
- uses: acme/release-notes@v1.4.2

# Максимальная фиксация supply chain, но обновления только вручную
- uses: acme/release-notes@8f3c2a4b9d2e1f0a6c7d8e9f0011223344556677

Это напрямую связано с Marketplace actions и pinning: автору удобно давать moving major tag, а потребитель в строгой среде может pin по full SHA.

Moving tags и immutable releases

Исторический паттерн для actions такой: при релизе v1.4.2 автор передвигает v1.4 и v1 на новый commit. Это даёт пользователям @v1 security fixes без правки всех workflow.

git tag v1.4.2

git tag -f v1.4 v1.4.2
git tag -f v1 v1.4.2

git push origin v1.4.2
git push -f origin v1.4 v1

Но immutable releases меняют правила. Если release опубликован как immutable, связанные assets и Git tag защищены от изменения после публикации. Это хорошо для supply chain: уже опубликованный v1.4.2 не должен внезапно стать другим кодом. Цена — нельзя использовать release-bound tag как moving pointer. Поэтому разумная схема такая: точные release tags (v1.4.2) публикуются как immutable releases, а floating tags (v1, v1.4) остаются обычными Git tags, не привязанными к GitHub Release, если вы хотите их двигать.

Для immutable release GitHub рекомендует сначала создать draft release, прикрепить все assets, проверить notes, а потом publish. После публикации исправлять «забыл файл» уже нельзя без нового release.

Release workflow для автора action

Минимально зрелый процесс выглядит так:

ИнтерактивЦикл релиза action#int-1
Шаг 1 из 61. Зафиксировать контракт
Проверьте `action.yml`: inputs, outputs, `runs`, supported runners, required permissions и примеры в README. Всё это часть публичного API action.
Короткий reference-процесс для выпуска новой версии action без сюрпризов для пользователей.

Для JavaScript action добавляется важная деталь: если action исполняется из bundled dist/, release должен гарантировать, что dist/ соответствует исходникам. Иначе пользователь получает tag, где TypeScript поменяли, а compiled bundle забыли обновить. Это нормальная причина иметь отдельный release workflow.

name: release

on:
  release:
    types: [published]

permissions:
  contents: write

jobs:
  verify-release:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.release.tag_name }}
      - uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm test
      - run: npm run build
      - run: git diff --exit-code dist/ action.yml

В реальном проекте можно добавлять smoke-test workflow, который вызывает action как внешний пользователь. Это ловит ошибки уровня uses, with, outputs и path handling, которые unit-тесты не видят. Если action публикует отчёты, проверьте Artifacts и reports; если пишет summary, проверьте Workflow commands и summaries.

Marketplace metadata

GitHub Marketplace берёт карточку action из repository release и metadata-файла. Для публикации action repository должен быть public, в корне должен быть один основной action.yml или action.yaml, а name должен быть уникальным. В action.yml важны не только runs, inputs и outputs, но и описание, author и branding.

name: "Release Notes Guard"
description: "Validate changelog entries before publishing a release"
author: "Acme CI"

inputs:
  changelog-path:
    description: "Path to CHANGELOG.md"
    required: false
    default: "CHANGELOG.md"

outputs:
  changed:
    description: "true when the release section exists"

branding:
  icon: "check-circle"
  color: "green"

runs:
  using: "node24"
  main: "dist/index.js"

Marketplace — не аудит безопасности. Публикация делает action discoverable, но не превращает её в trusted dependency. Поэтому README должен явно показывать required Permissions и GITHUB_TOKEN, supported runners, examples, upgrade notes и security contact.

Backward compatibility и deprecation

Самый частый maintenance-провал — «мы просто улучшили input». Например, было:

with:
  token: ${{ secrets.GITHUB_TOKEN }}

Потом автор решил переименовать input в github-token. Для новых пользователей красивее, но старые workflow падают. Совместимый вариант — поддерживать оба input в рамках v1, пометить старый как deprecated в README и warning annotation, а удалить только в v2.

v1.5.0: добавлен input github-token, token deprecated
v1.x: token продолжает работать
v2.0.0: token удалён, github-token обязателен

Deprecation policy должна быть скучной и явной: что deprecated, с какой версии, чем заменить, когда будет удалено, есть ли codemod или пример миграции. Для security-sensitive изменений иногда нужен быстрый major, но всё равно лучше дать понятный migration guide.

Changelog, support window и security

Changelog для action должен быть написан с позиции пользователя workflow: «какие inputs изменились», «какие permissions теперь нужны», «какие runners больше не поддерживаются», «какой output добавлен». Внутреннее «refactor parser» полезно только если влияет на поведение.

Хорошая release note для action выглядит так:


Быстрое повторение #rc-1

Почему для GitHub Action breaking change опаснее, чем для обычной библиотеки?

Показать ответ

Action может вызываться из чужих CI, release pipeline или production deploy через uses: owner/action@v1. Если контракт ломается, падают workflow пользователей, которые могли вообще не менять свой код.

v1.6.0

Added

  • Added format: json|markdown input. Default remains markdown.

Fixed

  • Fixed Windows path handling for changelog files in nested folders.

Security

  • Reduced default token usage; contents: read is enough unless create-release: true.

Deprecated

  • token input is deprecated. Use github-token; removal planned for v2.

Maintenance также включает Dependabot для dependencies, vulnerability reporting через `SECURITY.md`, CI на pull requests и осторожность с untrusted PR. Если release workflow имеет `contents: write`, не запускайте его на коде из непроверенного fork. Это уже область [Secure use и threat model](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/28) и [pull_request_target и untrusted PR](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/29).

### See also

- [Marketplace actions и pinning](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/22) — как потребители выбирают tag, SHA и trust model.
- [JavaScript actions](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/25) — packaging, `dist/`, runtime compatibility и release artifacts.
- [Docker container actions](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/26) — versioning container images и digest-подход.
- [Composite actions](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/24) — совместимость shell steps, inputs и outputs.
- [Reusable workflows](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/23) — versioning целых pipelines через `workflow_call`.
- [Permissions и GITHUB_TOKEN](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/5) — как документировать минимальные права action.
- [Secure use и threat model](/course/ec671477-2168-479f-9d68-bc3280c672bd/lessons/28) — supply chain, pinning и release trust.

Внешние справки: GitHub Docs по release and maintain actions, managing custom actions, immutable releases, Marketplace publishing и metadata syntax; спецификация Semantic Versioning 2.0.0.

Источники

  1. GitHub Docs: Releasing and maintaining actions
  2. GitHub Docs: Managing custom actions
  3. GitHub Docs: Using immutable releases and tags to manage your action's releases
  4. GitHub Docs: Immutable releases
  5. GitHub Docs: Preventing changes to your releases
  6. GitHub Docs: Verifying the integrity of a release
  7. GitHub Docs: Publishing actions in GitHub Marketplace
  8. GitHub Docs: Metadata syntax reference
  9. GitHub Docs: Managing releases in a repository
  10. Semantic Versioning 2.0.0