Skip to main content

publish

Publish local files to an Amazon S3 or Git target. Unchanged files are skipped, and destination-only files are retained.

The publish step is independent of component type. Use it in a workflow, custom command, or any component hook that needs to publish files. The target determines where those files go.

Usage​

steps:
- name: publish-assets
type: publish
source: dist/
target:
kind: aws/s3
bucket: acme-artifacts
prefix: releases/v1/
region: us-east-1

The bucket must already exist. Directory contents retain their relative paths; empty directories do not create objects. A single file uses its basename unless destination supplies another name.

Examples​

Package and Publish an Archive​

steps:
- name: package
type: archive
source: src/
destination: handler.zip
mtime: epoch
- name: publish
type: publish
source: '{{ .steps.package.value }}'
target:
kind: aws/s3
bucket: acme-artifacts
prefix: lambda/v1/
region: us-east-1
- type: log
content: 'Artifact: {{ .steps.publish.value }}'

The archive step's timestamp settings produce reproducible archives, allowing unchanged builds to skip the upload.

The advanced CloudFormation example runs the complete pipeline locally with Floci: build and test a Lambda application, archive and publish it, deploy it, and validate its HTTP response with an after.apply hook. It also checks unchanged uploads and a second release.

Publish to Git​

Configure a managed Git repository, then select it in the target:

steps:
- name: publish-config
type: publish
source: dist/
target:
kind: git
repository: deployment-repo
path: generated/service
commit:
message: Publish service configuration

Git clones or updates the configured repository, writes files below path, then commits and pushes changes scoped to that path. An unchanged run creates no new commit and performs no push unless it retries an unpushed commit from a prior run. Files remain byte-for-byte intact, including archives and YAML files. Publishing does not combine YAML documents.

Use a Component's Named Target​

Within a component hook, target: artifacts selects the component's merged provision.targets.artifacts definition:

provision:
targets:
artifacts:
kind: aws/s3
bucket: acme-artifacts
prefix: releases/v1/
region: us-east-1
hooks:
publish-assets:
events: [before.aws/cloudformation.apply]
kind: steps
with:
- type: publish
source: dist/
target: artifacts

An explicit target is required. The step does not use provision.default. Workflows and custom commands without component scope must provide an inline target. Selecting a deployment-only target fails without deploying resources.

Settings​

source
Required local file or directory. Relative paths use the step's working directory. Symlinks and special files are rejected.
target
Required inline target mapping, or the name of a component's provision target when running in a hook. Supported kinds are aws/s3 and git.
destination
Optional path relative to the target root. For a file, replaces its basename; a trailing slash appends the basename. For a directory, adds a prefix to each relative path. Absolute paths, parent traversal, backslashes, and Git metadata paths are rejected. Write spaces and # literally; returned S3 URIs are escaped automatically.

String settings support Go templates, including strings within the target map. Common fields such as working_directory, retry, and when also apply. The step has no action field.

S3 Target​

kind
aws/s3.
bucket
Required existing S3 bucket.
region
Required bucket region.
prefix
Optional relative key prefix. Files are published below this prefix.
content_type
Optional Content-Type header applied verbatim to every file, including any explicit charset. By default, the MIME type uses the filename extension with content detection as a fallback. Text charsets come from content detection, not extension defaults; an undetected charset is omitted. Detection samples the file and does not transcode its bytes.
cache_control
Optional Cache-Control header. Omitting it clears a previously configured value on the next upload.
auth
Optional target authentication, such as auth: {identity: artifacts-writer}.

Git Target​

kind
git.
repository
Required name from git.repositories.
path
Required directory root within the repository. The repository root itself is not allowed. Filename extensions do not change directory semantics.
commit
Optional message and signing settings, using the existing Git target conventions.
auth
Optional target identity override. Otherwise the repository's configured identity applies.

The manifest-specific split setting and pull-request creation are unsupported. File/directory collisions and symlink destinations fail without replacing the conflicting entry. Existing component delivery to Git still reconciles its managed path; the publish step retains destination-only files.

Authentication​

Publishing uses the existing identity selection rules: an explicit step or runner identity takes precedence over target authentication. Hooks inherit the component's auth scope; the target can select its own identity when no explicit caller override applies. Automatically selected component identities do not become explicit overrides. Each target resolves credentials independently.

Without an Atmos identity, S3 uses the runner's AWS environment and standard SDK credential chain. The SDK receives environment values without changing the process environment. Use AWS_ENDPOINT_URL_S3 for an S3-compatible test endpoint. Git uses its repository identity when no target or caller identity overrides it.

S3 callers need permission to inspect and upload objects. Grant s3:GetObject and s3:PutObject, plus s3:ListBucket to distinguish missing objects from access-denied responses. Access errors fail without attempting an upload. Bucket encryption policies may require KMS permissions.

Incremental Publishing​

S3 compares the atmos-sha256 metadata digest, size, content type, and cache control. Objects without Atmos metadata are uploaded once. Comparison does not download remote content or use a shared deployment manifest. Replaced objects do not preserve unrelated metadata; bucket versioning and encryption defaults apply.

Git compares file content and commits only changes. Repository signing and push-retry configuration apply. Dirty unrelated work in the managed checkout can prevent reconciliation or a scoped commit.

Results​

The step prints an informational summary on stderr with the number of files uploaded or written, the unchanged count, and every destination. S3 destinations include the full bucket and object key. Git output includes the repository, resolved branch, and repository-relative file paths. Listed destinations include unchanged files. Set output: none to hide these messages.

ValueMeaning
.steps.publish.valueLocation for one file; target name or inline for zero or multiple files.
.steps.publish.valuesAll locations, including unchanged files: S3 URIs or Git repository-relative paths.
.steps.publish.metadata.kindTarget kind.
.steps.publish.metadata.targetTarget name or inline.
.steps.publish.metadata.changedFiles written.
.steps.publish.metadata.unchangedFiles already matching.
.steps.publish.metadata.bucket / .keyS3 bucket and object key, or prefix for multiple files.
.steps.publish.metadata.uploadedS3 objects uploaded.
.steps.publish.metadata.repository / .branchGit repository name and configured branch.
.steps.publish.metadata.commitCreated Git commit SHA; empty when no commit was created.

Limitations​

S3 files must be no larger than 5 GiB; multipart uploads and bucket creation are unsupported. Publishing is not atomic across files. Earlier writes may remain after a failure; S3 retries skip completed matching objects.

Publishing does not delete remote files, download files, or rewrite template references. CloudFormation template packaging retains its separate content-addressed keys and metadata format. For Lambda assets, use a new object key per release and pass it as a template parameter so CloudFormation can detect the change. See the asset packaging hook example.

The publishing handler's dry-run validates local paths and target configuration without authenticating, calling AWS, or cloning, committing, or pushing Git repositories.