INTEGRITY Документация

Сборка и развёртывание репозиториев Artifacts

События Artifacts могут собирать и развёртывать проекты, хранящиеся в репозиториях Artifacts. Когда пользователь или агент отправляет коммит, это событие запускает Экземпляр Workflow.

В рамках Workflow вы определяете конвейер непрерывной интеграции (CI) с помощью @cloudflare/ci SDK для кэширования зависимостей, запуска проверок и сборки проекта. Последний шаг вашего конвейера CI может развернуть результат в Worker или Workers for Platforms User Worker.

Это полезно, когда нужно:

Как это работает

Изменения репозиториев Artifacts
Изменения репозитория
CI Workflow
1Установка и кеширование зависимостей
2Выполняйте этапы CI
Build
Линтинг
Проверка типов
Формат
Разверните Worker
  1. Отправляйте изменения репозитория : git push в репозиторий Artifacts генерирует artifacts.repo.pushed событие, которое указывает репозиторий, ветку и commit, куда был выполнен push.
  2. Запустите рабочий процесс CI : событие запускает Workflow, который выполняет checkout коммита, устанавливает и кеширует зависимости, а затем параллельно выполняет этапы CI: сборку, lint, проверку типов и форматирование. Если какой-либо этап завершается с ошибкой, Workflow останавливается до развёртывания.
  3. Разверните Worker : Workflow разворачивает собранный Worker либо напрямую в вашем аккаунте, либо как User Worker, если используется Workers for Platforms

Запустите рабочий процесс CI

Используйте @cloudflare/ci SDK для описания этапов CI. SDK предоставляет два инструмента для создания конвейера:

Диаграмма с тремя последовательными коммитами: у коммита 1 происходит промах кэша, поэтому выполняется шаг установки и его снимок песочницы кэшируется; у коммита 2 файл pnpm-lock.yaml не изменился, поэтому ключ кэша совпадает и используется кэшированный снимок, а установка пропускается; у коммита 3 файл pnpm-lock.yaml изменился, поэтому ключ кэша не совпадает и установка выполняется заново.

Кэшированный раннер запускается за снимок своего sandbox, который затем повторно используют другие раннеры. Несколько раннеров могут ответвляться от одного и того же закэшированного результата: например, раннеры для lint, type-check и test могут использовать одну и ту же закэшированную установку.

Раннер, завершившийся ошибкой, повторяет попытку согласно своей конфигурация шага, где можно задать количество попыток повтора, график задержек и тайм-ауты. Раннеры, зависящие от предыдущего шага, не запускаются, пока его повтор не завершится успешно. Если достигнут заданный лимит попыток, Workflow завершается с Errored состояние.

Ниже приведён пример того, как настроить ваш Workflow для использования раннеров и кеша, чтобы устанавливать зависимости, запускать проверки, собирать проект и разворачивать Worker:

src/index.js
import { CIWorkflow } from "./src/pipeline";

export class CI extends CIWorkflow {
	async pipeline(_event, _step, ci) {
		// Install once, then run independent checks from the shared snapshot.
		const deps = await ci.runner({
			name: "install",
			command: "bun install --frozen-lockfile",
			cache: { inputs: ["package.json", "bun.lock"] },
		});

		await Promise.all([
			deps.runner({ name: "lint", command: "bun run lint" }),
			deps.runner({ name: "test", command: "bun run test" }),
			deps.runner({ name: "typecheck", command: "bun run typecheck" }),
			deps.runner({ name: "build", command: "bun run build" }),
		]);

		await deps.runner({
			name: "deploy",
			command: "bun wrangler deploy",
			cloudflareCredentials: {
				accountId: this.env.CLOUDFLARE_DEPLOY_ACCOUNT_ID,
			},
		});
	}
}
src/index.ts
import { CIWorkflow } from "./src/pipeline";
import type {
	CiContext,
	CiParams,
	CiRunnerResult,
	CloudflareArtifacts,
} from "./src/pipeline";
import type { WorkflowEvent, WorkflowStep } from "cloudflare:workers";

export class CI extends CIWorkflow {
	protected async pipeline(
		_event: WorkflowEvent<CiParams<CloudflareArtifacts>>,
		_step: WorkflowStep,
		ci: CiContext,
	): Promise<void> {
		// Install once, then run independent checks from the shared snapshot.
		const deps: CiRunnerResult = await ci.runner({
			name: "install",
			command: "bun install --frozen-lockfile",
			cache: { inputs: ["package.json", "bun.lock"] },
		});

		await Promise.all([
			deps.runner({ name: "lint", command: "bun run lint" }),
			deps.runner({ name: "test", command: "bun run test" }),
			deps.runner({ name: "typecheck", command: "bun run typecheck" }),
			deps.runner({ name: "build", command: "bun run build" }),
		]);

		await deps.runner({
			name: "deploy",
			command: "bun wrangler deploy",
			cloudflareCredentials: {
				accountId: this.env.CLOUDFLARE_DEPLOY_ACCOUNT_ID,
			},
		});
	}
}

Запускайте сборку при изменении кода

Когда пользователь или агент отправляет коммит в репозиторий Artifacts, Artifacts создаёт событие, которое указывает изменённые репозиторий, ветку и коммит. Это событие можно использовать для запуска экземпляра Workflow, который выполняет CI-конвейер: он автоматически получает нужный коммит и клонирует репозиторий, а затем устанавливает зависимости, запускает проверки, собирает проект и (или) развёртывает Worker в соответствии с вашим кодом.

В этом руководстве эти шаги CI определены в классе Workflow с именем CIWorkflow. Чтобы запускать этот Workflow автоматически после каждого push, добавьте cf.artifacts.repo.pushed триггер в конфигурацию Wrangler. Также добавьте:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "<worker-name>",
  "main": "src/index.ts",
  "compatibility_date": "2026-06-16",
  "compatibility_flags": ["nodejs_compat"],
  "artifacts": [
    {
      "binding": "ARTIFACTS",
      "namespace": "<artifacts-namespace>"
    }
  ],
  "containers": [
    {
      "class_name": "CiSandbox",
      "image": "./Dockerfile",
      "max_instances": 10,
      "instance_type": "standard-4"
    }
  ],
  "durable_objects": {
    "bindings": [
      {
        "name": "SANDBOX",
        "class_name": "CiSandbox"
      }
    ]
  },
  "workflows": [
    {
      "name": "<workflow-name>",
      "binding": "CI_WORKFLOW",
      "class_name": "CI"
    }
  ],
  "exports": {
    "CiSandbox": {
      "type": "durable-object",
      "storage": "sqlite"
    }
  },
  "r2_buckets": [
    {
      "binding": "BACKUP_BUCKET",
      "bucket_name": "<backup-bucket-name>"
    }
  ],
  "triggers": {
    "events": [
      {
        "type": "cf.artifacts.repo.pushed",
        // filter is optional. If you don't set repoName we will run the same workflow for every push on any repo in your Artifacts namespace
        "filter": {
          "namespace": "CI",
          "repoName": "my-repo"
        },
        "target": {
          "scriptName": "<worker-name>",
          "workflowName": "<workflow-name>"
        }
      }
    ]
  },
  "observability": {
    "enabled": true,
    "logs": {
      "enabled": true
    }
  }
}
"$schema" = "node_modules/wrangler/config-schema.json"
name = "<worker-name>"
main = "src/index.ts"
compatibility_date = "2026-06-16"
compatibility_flags = [ "nodejs_compat" ]

[[artifacts]]
binding = "ARTIFACTS"
namespace = "<artifacts-namespace>"

[[containers]]
class_name = "CiSandbox"
image = "./Dockerfile"
max_instances = 10
instance_type = "standard-4"

[[durable_objects.bindings]]
name = "SANDBOX"
class_name = "CiSandbox"

[[workflows]]
name = "<workflow-name>"
binding = "CI_WORKFLOW"
class_name = "CI"

[exports.CiSandbox]
type = "durable-object"
storage = "sqlite"

[[r2_buckets]]
binding = "BACKUP_BUCKET"
bucket_name = "<backup-bucket-name>"

[[triggers.events]]
type = "cf.artifacts.repo.pushed"

  [triggers.events.filter]
  namespace = "CI"
  repoName = "my-repo"

  [triggers.events.target]
  scriptName = "<worker-name>"
  workflowName = "<workflow-name>"

[observability]
enabled = true

  [observability.logs]
  enabled = true

Просмотр статуса сборки

[observability] параметр в конфигурации Wrangler фиксирует статус и логи каждого запуска конвейера. Чтобы определить, на каком этапе произошёл сбой, проверьте экземпляр на панели управления Workflows:

Перейдите в Workflows ↗

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

Разверните приложение

Чтобы задеплоить Worker, передайте wrangler deploy в итоговый runner() шаг, то есть workspace.runner({ name: "deploy", command: "wrangler deploy" }).

Чтобы задеплоить User Worker, передайте wrangler deploy --dispatch_namespace <DISPATCH_NAMESPACE> в итоговый runner() шаг.

Запускайте один рабочий процесс для каждого репозитория в пространстве имён

filter в вашем триггере необязателен. Когда вы задаёте repoName, Workflow запускается только при push в этот конкретный репозиторий. Если не указать repoName, Cloudflare запускает один и тот же Workflow при каждом push в любой репозиторий вашего пространства имён Artifacts.

Это полезно для платформ, которые создают и поддерживают единый CI Workflow и хотят применять его одинаково ко всем репозиториям клиентов в пространстве имен. Вместо отдельного триггера для каждого репозитория один общий Workflow собирает, проверяет и деплоит каждый репозиторий при push.

Платформенное пространство имён
Репозиторий артефактов A
Репозиторий артефактов B
Репозиторий артефактов C
Репозиторий артефактов D
Репозиторий артефактов E
Общий рабочий процесс CIсоздано и принадлежит платформе
сборкаlintтестtypecheck
развёртывание A
развёртывание B
развёртывание C
развёртывание D
развёртывание E
развёртывание на каждый репозиторий

Чтобы запускать один и тот же Workflow для каждого репозитория в пространстве имен, поместите repoName из триггера filter и оставьте только namespace:

{
	"triggers": {
		"events": [
			{
				"type": "cf.artifacts.repo.pushed",
				"filter": {
					"namespace": "CI"
				},
				"target": {
					"scriptName": "my-ci-worker",
					"workflowName": "ci-workflow"
				}
			}
		]
	}
}
[[triggers.events]]
type = "cf.artifacts.repo.pushed"

  [triggers.events.filter]
  namespace = "CI"

  [triggers.events.target]
  scriptName = "my-ci-worker"
  workflowName = "ci-workflow"

Каждый push по-прежнему запускает отдельный экземпляр Workflow для репозитория, ветки и коммита, которые изменились, поэтому вы можете разворачивать отдельный Worker для каждого репозитория на основе одного общего определения Workflow.