Что такое артефакты?

Артефакт — это специальный образ, используемый в других артефактах или отдельных образах, описанных в конфигурации. Артефакт предназначен преимущественно для отделения ресурсов инструментов сборки от процесса сборки образа приложения. Примерами таких ресурсов могут быть — программное обеспечение или данные, которые необходимы для сборки, но не нужны для запуска приложения, и т.п.

Образ артефакта нельзя протегировать как обычный образ, и использовать как отдельное приложение.

Используя артефакты, вы можете собирать неограниченное количество компонентов, что позволяет решать, например, следующие задачи:

  • Если приложение состоит из набора компонент, каждый со своими зависимостями, то обычно вам приходится пересобирать все компоненты каждый раз. Вам бы хотелось пересобирать только те компоненты, которым это действительно нужно.
  • Компоненты должны быть собраны в разных окружениях.

Импортирование ресурсов из артефактов указывается с помощью директивы import в конфигурации в секции образа или секции артефакта).

Конфигурация

Конфигурация артефакта похожа на конфигурацию обычного образа. Каждый артефакт должен быть описан в своей секции конфигурации.

Инструкции, связанные со стадией from (инструкции указания базового образа и монтирования), а также инструкции импорта точно такие же как и при описании образа.

Стадия добавления инструкций Docker (docker_instructions) и соответствующие директивы не доступны при описании артефактов. Артефакт — это инструмент сборки, и все что от него требуется, это — только данные.

Остальные стадии и инструкции описания артефактов рассматриваются далее подробно.

Именование

artifact: <artifact name>

Образ артефакта объявляется с помощью директивы artifact. Синтаксис: artifact: <artifact name>. Так как артефакты используются только самим werf, отсутствуют какие-либо ограничения на именование артефактов, в отличие от ограничений на именование обычных образов.

Пример:

artifact: "application assets"

Добавление исходного кода из git-репозиториев

В отличие от обычных образов, у конвейера стадий артефактов нет стадий gitCache и gitLatestPatch.

В werf для артефактов реализована необязательная зависимость от изменений в git-репозиториях. Таким образом, по умолчанию werf игнорирует какие-либо изменения в git-репозитории, кэшируя образ после первой сборки. Но вы можете определить зависимости от файлов и папок, при изменении в которых образ артефакта будет пересобираться

Читайте подробнее про работу с git-репозиториями в соответствующей статье.

Запуск инструкций сборки

У артефактов точно такое же как и у обычных образов использование директив и пользовательских стадий — beforeInstall, install, beforeSetup и setup.

Если в директиве stageDependencies в блоке git для пользовательской стадии не указана зависимость от каких-либо файлов, то образ кэшируется после первой сборки, и не будет повторно собираться пока соответствующая стадия находится в stages storage.

Если необходимо повторно собирать артефакт при любых изменениях в git, нужно указать stageDependency **/* для соответствующей пользовательской стадии. Пример для стадии install:

git:
- to: /
  stageDependencies:
    install: "**/*"

Читайте подробнее про работу с инструкциями сборки в соответствующей статье.

Все директивы

artifact: <artifact_name>
from: <image>
fromLatest: <bool>
herebyIAdmitThatFromLatestMightBreakReproducibility: <bool>
fromCacheVersion: <version>
fromImage: <image_name>
fromImageArtifact: <artifact_name>
git:
# local git
- add: <absolute path in git repository>
  to: <absolute path inside image>
  owner: <owner>
  group: <group>
  includePaths:
  - <path or glob relative to path in add>
  excludePaths:
  - <path or glob relative to path in add>
  stageDependencies:
    install:
    - <path or glob relative to path in add>
    beforeSetup:
    - <path or glob relative to path in add>
    setup:
    - <path or glob relative to path in add>
# remote git
- url: <git repo url>
  branch: <branch name>
  herebyIAdmitThatBranchMightBreakReproducibility: <bool>
  commit: <commit>
  tag: <tag>
  add: <absolute path in git repository>
  to: <absolute path inside image>
  owner: <owner>
  group: <group>
  includePaths:
  - <path or glob relative to path in add>
  excludePaths:
  - <path or glob relative to path in add>
  stageDependencies:
    install:
    - <path or glob relative to path in add>
    beforeSetup:
    - <path or glob relative to path in add>
    setup:
    - <path or glob relative to path in add>
shell:
  beforeInstall:
  - <cmd>
  install:
  - <cmd>
  beforeSetup:
  - <cmd>
  setup:
  - <cmd>
  cacheVersion: <version>
  beforeInstallCacheVersion: <version>
  installCacheVersion: <version>
  beforeSetupCacheVersion: <version>
  setupCacheVersion: <version>
ansible:
  beforeInstall:
  - <task>
  install:
  - <task>
  beforeSetup:
  - <task>
  setup:
  - <task>
  cacheVersion: <version>
  beforeInstallCacheVersion: <version>
  installCacheVersion: <version>
  beforeSetupCacheVersion: <version>
  setupCacheVersion: <version>
mount:
- from: build_dir
  to: <absolute_path>
- from: tmp_dir
  to: <absolute_path>
- fromPath: <absolute_or_relative_path>
  to: <absolute_path>
import:
- artifact: <artifact name>
  image: <image name>
  stage: <stage name>
  before: <install || setup>
  after: <install || setup>
  add: <absolute path>
  to: <absolute path>
  owner: <owner>
  group: <group>
  includePaths:
  - <relative path or glob>
  excludePaths:
  - <relative path or glob>
asLayers: <bool>

Использование артефактов

В отличие от обычного образа, у образа артефакта нет стадии git latest patch. Это сделано намеренно, т.к. стадия git latest patch выполняется обычно при каждом коммите, применяя появившиеся изменения к файлам. Однако артефакт рекомендуется использовать как образ с высокой вероятностью кэширования, который обновляется редко или нечасто (например, при изменении специальных файлов).

Пример: нужно импортировать в артефакт данные из git, и пересобирать ассеты только тогда, когда влияющие на сборку ассетов файлы изменяются. Т.е. в случае, изменения каких-либо других файлов в git, ассеты пересобираться не должны.

Конечно, существуют случаи когда необходимо включать изменения любых файлов git-репозитория в образ артефакта (например, если в артефакте происходит сборка приложения на Go). В этом случае необходимо указать зависимость относительно стадии (сборку которой необходимо выполнять при изменениях в git) с помощью git.stageDependencies и * в качестве шаблона. Пример:

git:
- add: /
  to: /app
  stageDependencies:
    setup:
    - "*"

В этом случае любые изменения файлов в git-репозитории будут приводить к пересборке образа артефакта, и всех образов, в которых определен импорт этого артефакта.

Замечание: Если вы используете какие-либо файлы и при сборке артефакта и при сборке обычного образа, правильный путь — использовать директиву git.add при описании каждого образа, где это необходимо, т.е. несколько раз. Не рекомендуемый вариант — добавить файлы при сборке артефакта, а потом импортировать их используя директиву import в другой образ.