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

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

Что такое workflow artifacts, как upload/download actions используются для сборок, coverage, test reports, логов и handoff между jobs; retention и удаление артефактов.

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

Artifacts и reports

Что такое workflow artifacts, как upload/download actions используются для сборок, coverage, test reports, логов и handoff между jobs; retention и удаление артефактов.

Artifacts и reports

Workflow artifact — это файл или набор файлов, прикреплённый к конкретному workflow run. Его используют, когда результат job должен пережить завершение runner: build bundle, coverage report, JUnit XML, screenshots, SBOM, архив логов, скомпилированный бинарник или handoff-файл для следующего job. В отличие от Step outputs и job outputs, artifact не предназначен для маленьких строковых значений в expressions. В отличие от Dependency cache, artifact не ускоряет будущие runs, а сохраняет результат именно этого run.

Типовая ментальная модель простая: job создаёт файлы в workspace, actions/upload-artifact загружает их в хранилище GitHub Actions, другой job или человек скачивает их через actions/download-artifact, UI, GitHub CLI или REST API.

flowchart TD A[Job: build/test] --> B[Файлы в workspace<br/>dist, coverage, junit, traces] B --> C[actions/upload-artifact] C --> D[(Artifact storage<br/>привязан к workflow run)] D --> E[GitHub UI / CLI / REST API] D --> F[actions/download-artifact] F --> G[Job: deploy / aggregate / debug] H[GITHUB_STEP_SUMMARY] --> I[Короткий Markdown-итог в run summary] C -. artifact-id / artifact-url .-> J[Step output для ссылок и API]
flowchart TD
  A[Job: build/test] --> B[Файлы в workspace<br/>dist, coverage, junit, traces]
  B --> C[actions/upload-artifact]
  C --> D[(Artifact storage<br/>привязан к workflow run)]
  D --> E[GitHub UI / CLI / REST API]
  D --> F[actions/download-artifact]
  F --> G[Job: deploy / aggregate / debug]
  H[GITHUB_STEP_SUMMARY] --> I[Короткий Markdown-итог в run summary]
  C -. artifact-id / artifact-url .-> J[Step output для ссылок и API]
Жизненный цикл artifact: файл создаётся в job, загружается в workflow run, затем скачивается человеком, API или downstream job.

Что обычно складывают в artifacts

Artifacts хороши для результатов, которые полезно открыть после CI. Например, frontend job может загрузить dist/, backend job — coverage HTML и JUnit XML, E2E job — screenshots и trace-файлы, security job — SARIF/SBOM, release job — .zip, .tar.gz, .dmg или .apk перед публикацией.

name: Node CI

on:
  pull_request:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci
      - run: npm test -- --coverage
      - run: npm run build

      - name: Upload coverage report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: coverage-html
          path: coverage/
          retention-days: 7
          if-no-files-found: error

      - name: Upload build bundle
        uses: actions/upload-artifact@v4
        with:
          name: web-dist-${{ github.sha }}
          path: |
            dist/
            !dist/**/*.map
          retention-days: 14

Здесь if: always() у coverage важен: если тесты упали, отчёт всё равно может помочь при разборе. if-no-files-found: error делает отсутствие отчёта явной проблемой, а не тихим warning. Исключение !dist/**/*.map показывает, что path может быть многострочным набором include/exclude patterns.

Handoff между jobs

Artifacts часто связывают jobs, которые нельзя или не хочется объединять. Например, build собирает статический bundle, а deploy скачивает ровно тот bundle, который прошёл CI. Это лучше, чем пересобирать проект во втором job и надеяться, что окружение, lockfile и registry отдали тот же результат.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: web-dist
          path: dist/
          retention-days: 3

  deploy-preview:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: read
      deployments: write
    steps:
      - uses: actions/download-artifact@v5
        with:
          name: web-dist
          path: ./dist
      - run: ls -la ./dist
      - run: ./scripts/deploy-preview.sh ./dist

needs: build здесь не просто «красивый граф». Он гарантирует, что deploy-preview стартует после загрузки artifact. При скачивании одного artifact файлы кладутся в указанную директорию. Если скачать все artifacts без name, обычно получится отдельная папка на каждый artifact — это удобно для агрегатора отчётов, но неудобно для deploy-скрипта, ожидающего один конкретный путь.

Reports: artifact, summary или PR annotation?

Слово «report» в GitHub Actions не означает один специальный механизм. Есть несколько вариантов, и они решают разные задачи.

Coverage HTML, Playwright traces, screenshots, JUnit XML и длинные логи обычно идут в artifacts: их можно скачать, открыть локально или передать другому job. Короткий Markdown-итог лучше писать в GITHUB_STEP_SUMMARY, о чём отдельно говорит Workflow commands и summaries. Ошибки линтера или security findings иногда лучше публиковать как annotations, SARIF/code scanning alert или комментарий в PR, чтобы разработчик увидел проблему без скачивания архива.

Практичный паттерн для CI: artifact хранит полный отчёт, summary даёт ссылку и краткую выжимку.

- name: Write job summary
  if: always()
  run: |
    echo "### Test reports" >> "$GITHUB_STEP_SUMMARY"
    echo "- Coverage HTML: artifact \`coverage-html\`" >> "$GITHUB_STEP_SUMMARY"
    echo "- JUnit XML: artifact \`junit-report\`" >> "$GITHUB_STEP_SUMMARY"

Такой подход хорошо сочетается с CI pipeline и Monitoring и troubleshooting: быстрый диагноз виден прямо в run summary, а детали остаются в скачиваемом архиве.

Retention, удаление и стоимость

Artifacts не вечные. По умолчанию GitHub хранит build logs и artifacts ограниченное время; для artifacts можно задать retention-days на уровне upload step, но значение не может превышать лимит, настроенный на уровне repository, organization или enterprise. Для временных preview-сборок обычно достаточно 1–7 дней. Для release-candidate архивов — дольше, но лучше осознанно, а не «пусть лежит 90 дней».

- uses: actions/upload-artifact@v4
  with:
    name: playwright-traces
    path: test-results/
    retention-days: 5

Удалять artifacts можно из UI workflow run, через REST API, GitHub CLI или удалением самого workflow run. После удаления artifact не восстанавливается. В больших repos это становится частью эксплуатации: E2E traces и debug bundles быстро занимают место, особенно при Matrix strategy, где каждый вариант OS/runtime может грузить отдельный набор файлов.

Имена, matrix и immutability

Называйте artifacts так, чтобы их можно было отличить без открытия архива: coverage-node-22, playwright-chromium, web-dist-${{ github.sha }}, binary-${{ matrix.os }}-${{ matrix.version }}. В matrix jobs это не косметика, а защита от конфликтов. Начиная с современной линейки upload-artifact, artifact считается immutable: несколько jobs не должны дозаписывать один и тот же artifact с одним именем. Если нужно собрать результаты matrix, каждый вариант загружает свой artifact, а отдельный aggregator job скачивает их все и строит общий report.

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest]
    node: [20, 22]

steps:
  - run: npm test -- --reporter=junit
  - uses: actions/upload-artifact@v4
    if: always()
    with:
      name: junit-${{ matrix.os }}-node-${{ matrix.node }}
      path: reports/junit.xml

Если вам надо «обновить» artifact, лучше создать новый с новым именем или использовать явный overwrite, понимая, что старый artifact фактически заменяется и получает новый identity. Для аудита релизов это обычно плохая идея; для промежуточного preview — иногда нормально.

Безопасность artifacts

Artifact не должен быть корзиной для всего workspace. Не загружайте .env, private keys, npm tokens, cloud credentials, cookies браузерных тестов и production config. Hidden files в новых версиях upload action требуют отдельного внимания: если включаете их загрузку, явно исключайте чувствительные файлы. Secrets могут быть замаскированы в логах, но artifact — это файл, который вы сами сохранили; GitHub не превращает его автоматически в безопасное хранилище.

Для untrusted PR особенно важна связка с Secure use и threat model и pull_request_target и untrusted PR. Не берите artifact из недоверенного workflow и не деплойте его в production без проверки. Для цепочки «CI собрал → CD опубликовал» используйте явные permissions из Permissions и GITHUB_TOKEN, protected environments и, для supply-chain сценариев, artifact attestations или подпись релизных файлов.

Artifact, release asset или package?

Artifact живёт внутри GitHub Actions run. Release asset живёт у GitHub Release и подходит для публичной или полупубличной доставки версии: архивы, changelog, binaries. Package или container image живёт в registry, например GitHub Packages или GHCR, и имеет собственные tags, permissions и lifecycle. Поэтому dist/ между jobs — artifact; .tar.gz у GitHub Release — release asset; Docker image ghcr.io/acme/api:1.4.2 — тема Packages и container images.

Хороший workflow не смешивает эти роли. Artifact помогает довести проверенный файл до deploy/release job. А уже deploy/release job решает, станет ли этот файл production-deploy, release asset или package.

See also

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

Почему artifact в GitHub Actions подходит для dist/, coverage HTML или JUnit XML, но не для маленьких строковых значений в expressions?

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

Artifact хранит файлы конкретного workflow run после завершения runner. Для маленьких строковых значений между steps/jobs нужны step outputs или job outputs.

Источники

  1. Store and share data with workflow artifacts - GitHub Docs
  2. actions/upload-artifact README
  3. actions/download-artifact README
  4. Removing workflow artifacts - GitHub Docs
  5. REST API endpoints for GitHub Actions artifacts - GitHub Docs