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]
Что обычно складывают в 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 ./distneeds: 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
- Step outputs и job outputs — короткие строковые значения между steps и jobs.
- Dependency cache — cache keys, restore keys и ускорение повторных runs.
- Workflow commands и summaries — Markdown summaries, warnings, errors и environment files.
- CI pipeline — где artifacts появляются в обычной build/test цепочке.
- Matrix strategy — именование artifacts в matrix jobs и aggregation pattern.
- Deployment workflows — как использовать проверенный build artifact в deploy job.
- Release automation — когда artifact превращается в release asset.
- Secure use и threat model — почему artifacts тоже входят в supply-chain threat model.
