Skip to content

feat(workflows): add native archive step type for zip/tar packaging - #2730

Merged
Andriy Knysh (aknysh) merged 14 commits into
mainfrom
osterman/custom-step-type-prd
Jul 14, 2026
Merged

Andriy Knysh (aknysh) merged 14 commits into
mainfrom
osterman/custom-step-type-prd

Conversation

@osterman

@osterman Erik Osterman (Cloud Posse) (osterman) commented Jul 11, 2026 •

Copy link
Copy Markdown
Member

what

  • Add a native type: archive step for workflows and custom commands that packs a directory or file into a zip, tar, or tgz archive using the Go standard library only (archive/zip, archive/tar, compress/gzip) — no external zip/tar binary required.
  • Support action: replace (always rebuild fresh) on every format, and action: update (incremental add/refresh) for zip and uncompressed tar; action: create/action: extract and tar.bz2/tar.xz writers are reserved in the schema for a later phase and return a typed "not yet implemented" error.
  • Support subpath nesting, include/exclude glob filtering (reusing the existing pkg/utils.PathMatch matcher), and format inference from the destination/source extension.
  • Reuse the existing kind: step hook bridge instead of adding a dedicated hook kind, so kind: step + type: archive works as a component lifecycle hook with zero hook-side code.
  • Add the docs/prd/archive-step.md PRD, step-type reference docs, a changelog blog post, and a roadmap milestone.

why

  • Packaging build artifacts (most commonly a Lambda function's handler.zip before terraform plan/apply) had no native Atmos primitive — the only option was shelling out to zip/tar via a kind: command hook or type: shell step, which breaks on Windows CI and gives no typed validation.
  • This surfaced while migrating a Terragrunt example that used a before_hook wrapping the zip binary; a data "archive_file" Terraform data source was tried first but doesn't reliably run before packaging is needed.
  • The step ships as a step type only (not a new hook kind) to follow the precedent set by emulator/http/container, which reach hooks purely through the kind: step bridge — this avoids duplicating schema and hook-engine code for a capability the step registry already provides.

references

  • PRD: docs/prd/archive-step.md

Packaging build artifacts (e.g. a Lambda handler.zip) had no native Atmos
primitive; the only option was shelling out to zip/tar, which breaks on
Windows and gives no typed validation. The new `type: archive` step packs
a directory/file into a zip/tar/tgz archive using the Go standard library
only. It reuses the existing `kind: step` hook bridge instead of adding a
dedicated hook kind, so it's usable as a lifecycle hook for free.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@atmos-pro

atmos-pro Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@osterman Erik Osterman (Cloud Posse) (osterman) added the minor New features that do not break anything label Jul 11, 2026
@github-actions github-actions Bot added the size/l Large size PR label Jul 11, 2026
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

lychee's exclude list only whitelists /cli/ and /functions/ root-relative
website paths (the only forms it can't resolve locally); /stacks/generate
isn't covered, so the link checker treated it as a literal repo-relative
file path and failed. Match the convention every other PRD doc uses for
paths outside those two prefixes: a full https://atmos.tools/... URL.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Resource Changes Found for bucket in test

Atmos CI

create

Plan: 4 to add, 0 to change, 0 to destroy.
To reproduce this locally, run:

atmos terraform plan bucket -s test

Create

+ aws_s3_bucket.checkov_target
+ aws_s3_bucket.this
+ aws_s3_bucket.trivy_target
+ aws_s3_bucket_public_access_block.trivy_target
Terraform Plan Summary
  # aws_s3_bucket.checkov_target will be created
  + resource "aws_s3_bucket" "checkov_target" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "atmos-native-ci-e2e-checkov-test"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # aws_s3_bucket.this will be created
  + resource "aws_s3_bucket" "this" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "atmos-native-ci-e2e-test"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags                        = {
          + "AtmosFixture" = "native-ci-e2e"
          + "Stage"        = "test"
        }
      + tags_all                    = {
          + "AtmosFixture" = "native-ci-e2e"
          + "Stage"        = "test"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # aws_s3_bucket.trivy_target will be created
  + resource "aws_s3_bucket" "trivy_target" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "atmos-native-ci-e2e-trivy-test"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # aws_s3_bucket_public_access_block.trivy_target will be created
  + resource "aws_s3_bucket_public_access_block" "trivy_target" {
      + block_public_acls       = true
      + block_public_policy     = true
      + bucket                  = (known after apply)
      + id                      = (known after apply)
      + ignore_public_acls      = true
      + restrict_public_buckets = true
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + bucket_name = "atmos-native-ci-e2e-test"

@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1205334b-81a7-47f8-acac-bf6c45b1fed8

📥 Commits

Reviewing files that changed from the base of the PR and between d50f2e3 and 7d90cb3.

📒 Files selected for processing (2)
  • errors/errors.go
  • website/src/data/roadmap.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/src/data/roadmap.js
  • errors/errors.go

📝 Walkthrough

Walkthrough

Adds a native archive workflow step supporting ZIP, TAR, and TGZ replacement or incremental updates, deterministic mtime modes, workflow and hook integration, typed validation, tests, and documentation.

Changes

Archive step contract and integration

Layer / File(s) Summary
Archive step PRD and contract
docs/prd/archive-step.md, docs/prd/custom-hooks.md
Defines archive actions, formats, schema, mtime behavior, hook bridging, implementation boundaries, tests, and rollout.
Workflow schema and handler
pkg/schema/..., errors/errors.go, pkg/runner/step/archive.go
Adds archive fields and typed errors, registers the handler, resolves templates, validates inputs, and returns execution metadata.

Archive implementation

Layer / File(s) Summary
Archive engine and formats
pkg/archive/*.go
Implements format detection, filtered traversal, replacement and incremental updates, atomic writes, and ZIP/TAR handling.
Reproducible archive metadata
pkg/archive/mtime.go
Adds filesystem, epoch, and Git-derived mtime modes with permission normalization and fallbacks.
Archive and handler validation
pkg/archive/*_test.go, pkg/runner/step/archive_test.go, pkg/hooks/step_engine_test.go
Tests actions, formats, filtering, atomicity, deterministic output, handler behavior, template resolution, and step-engine integration.

Documentation and repository support

Layer / File(s) Summary
Archive documentation and release support
website/..., docs/..., .github/workflows/test.yml, pkg/cache/filelock_unix.go
Documents archive configuration, hooks, update restrictions, reproducible output, schema metadata, and roadmap status; also updates test timing comments and Unix lock retries.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ArchiveHandler
  participant VariableResolver
  participant ArchiveRun
  participant DetectFormat
  participant CollectEntries
  participant AtomicWriter
  ArchiveHandler->>VariableResolver: Resolve archive fields
  ArchiveHandler->>ArchiveRun: Pass action and PackOptions
  ArchiveRun->>DetectFormat: Detect format
  ArchiveRun->>CollectEntries: Collect filtered entries
  CollectEntries-->>ArchiveRun: Return pack entries
  ArchiveRun->>AtomicWriter: Write or update archive
  AtomicWriter-->>ArchiveHandler: Return success or typed error
Loading

Possibly related PRs

  • cloudposse/atmos#2710: Updates the published workflow-step schema surface also extended by the archive fields.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: a native workflow archive step for zip/tar packaging.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch osterman/custom-step-type-prd

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/prd/archive-step.md`:
- Line 267: Update the “Generate Terraform Files” link in the archive-step
documentation to reference an existing documentation path or valid website route
instead of /stacks/generate, ensuring link checking resolves the target
successfully.

In `@pkg/archive/archive.go`:
- Around line 140-146: Update validatePackOptions to check for a nil opts before
accessing Source or Destination, and return the established typed validation
error for invalid pack options. Preserve the existing source and destination
validation for non-nil PackOptions.
- Around line 78-80: Update the format detection call in the archive flow around
DetectFormat to infer from opts.Destination first and fall back to the source
archive path when Format is omitted, preserving explicit format handling. Add a
regression test covering a file source such as bundle.tar with a destination
such as out.bin and asserting tar inference.

In `@pkg/archive/tar.go`:
- Around line 17-49: Update writeTar to create and write the archive through a
temporary file in the destination directory, preserving the existing tar/gzip
construction and error handling. Close and remove the temporary file on every
failure, including addTarEntry, tar.Close, and gzip.Close; rename the completed
temporary file to destination only after all writes succeed, matching the atomic
replacement pattern used by updateTar.
- Around line 65-85: Update the archive update flow around the temporary file
creation and os.Rename to preserve the existing destination file mode when
replacing an existing archive. Capture the destination’s permissions before
creating the temp file, apply that mode to the temp file before renaming, and
retain the current behavior for destinations that do not already exist.

In `@pkg/archive/walk.go`:
- Around line 76-80: Update the walkErr handling in the archive walking flow to
classify only genuine missing-source failures as ErrArchiveSourceNotFound.
Preserve already-classified filter errors and return other filesystem or
callback failures distinctly, while retaining the existing source context where
appropriate.
- Around line 36-38: Update the single-file branch in the archive-walking
function around the !info.IsDir() check to evaluate the source basename against
the configured Include and Exclude filters before returning a packEntry. Reuse
the existing filter-matching logic used for directory entries, returning no
entries when the file is excluded or not included; otherwise preserve the
current archivePath construction and return behavior.
- Around line 37-38: Validate the subpath before the archive-entry returns and
joins in the walk logic around archivePath, including the paths used at the
referenced entry ranges. Reject absolute paths and any "." or ".." components
when split on both forward and backslashes, then only call archiveJoin for valid
relative subpaths.

In `@pkg/archive/zip.go`:
- Around line 13-33: Update writeZip to create a temporary file in the
destination directory instead of calling os.Create on destination, write and
finalize the ZIP there, and propagate errors from both file and ZIP close
operations. Rename the completed temporary file to destination only after all
writes and closes succeed, and remove the temporary file on any failure so the
existing archive remains intact.

In `@website/blog/2026-07-11-archive-step-type.mdx`:
- Around line 76-78: Update the format option documentation near the format
description to state that the archive format is inferred from the destination
extension, falling back to the source extension when the destination has no
extension. Preserve the existing list of supported formats and the note about
unsupported tar.bz2/tar.xz writing.

In `@website/docs/workflows/workflows/workflow/steps/type.mdx`:
- Line 30: Update the archive step entry in the workflow steps table so its
purpose text mentions all supported formats, including tgz, using “zip/tar/tgz”
or a link to the complete format list. Leave the existing configuration keys
unchanged.

In `@website/docs/workflows/workflows/workflow/steps/type/archive.mdx`:
- Around line 49-50: Update the format field description near the archive step
documentation to state that format inference falls back to the source extension
when it cannot be inferred from destination. Preserve the existing supported
formats, destination-extension mappings, and unsupported tar.bz2/tar.xz
limitation.
- Line 10: Update the opening description of the archive step type to mention
tgz alongside zip and tar as a supported archive format, keeping the existing
implementation and platform details unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bba68c8b-9612-4d46-a05a-560e29ce1b5e

📥 Commits

Reviewing files that changed from the base of the PR and between 28c1489 and f34f951.

📒 Files selected for processing (20)
  • docs/prd/archive-step.md
  • docs/prd/custom-hooks.md
  • errors/errors.go
  • pkg/archive/archive.go
  • pkg/archive/archive_test.go
  • pkg/archive/format.go
  • pkg/archive/tar.go
  • pkg/archive/walk.go
  • pkg/archive/zip.go
  • pkg/hooks/step_engine_test.go
  • pkg/runner/step/archive.go
  • pkg/runner/step/archive_test.go
  • pkg/schema/task.go
  • pkg/schema/workflow.go
  • website/blog/2026-07-11-archive-step-type.mdx
  • website/docs/stacks/hooks.mdx
  • website/docs/workflows/_partials/_step-types.mdx
  • website/docs/workflows/workflows/workflow/steps/type.mdx
  • website/docs/workflows/workflows/workflow/steps/type/archive.mdx
  • website/src/data/roadmap.js

Comment thread docs/prd/archive-step.md Outdated
Comment thread pkg/archive/archive.go
Comment thread pkg/archive/archive.go
Comment thread pkg/archive/tar.go Outdated
Comment thread pkg/archive/tar.go Outdated
Comment thread pkg/archive/zip.go Outdated
Comment thread website/blog/2026-07-11-archive-step-type.mdx
Comment thread website/docs/workflows/workflows/workflow/steps/type.mdx Outdated
Comment thread website/docs/workflows/workflows/workflow/steps/type/archive.mdx Outdated
Comment thread website/docs/workflows/workflows/workflow/steps/type/archive.mdx
Fixes several correctness/security issues from PR review: writeZip/writeTar
now write through a temp file and rename atomically, so a failure partway
through (e.g. a source file vanishing mid-run) never truncates or corrupts
the previous archive; action: update no longer downgrades an existing
archive's file permissions to the temp file's default mode; a single-file
source now respects include/exclude filters instead of always being
archived; Run(action, nil) returns a typed validation error instead of
panicking; invalid glob-pattern errors from directory walking are no longer
misclassified as a missing source; and subpath is validated to reject
absolute paths and "."/".." segments, closing a path-traversal vector where
an extracted archive could write outside its target directory.

Also fixes two doc gaps: the step-types summary table and the archive step's
intro paragraph both undersold supported formats as "zip/tar" when tgz is
also supported.

Three review comments proposing a destination-then-source format-inference
fallback were not applied — the documented contract in
docs/prd/archive-step.md is destination-only for pack actions and
source-only for extract, not a fallback chain, so the "bug" was based on a
misreading of ambiguous PR description wording, not an actual gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TestSchemaCoversWorkflowStepFields was failing in CI: the archive step's
format/destination/subpath/include/exclude fields were missing from the
published workflow_step schema, which would reject valid workflow files
annotated with the $schema. action/source were already covered since the
archive step reuses those existing fields.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json (1)

2403-2406: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

action field description doesn't mention archive verbs.

The action field is reused by the archive step type for create, extract, update, and replace (per pkg/runner/step/archive.go:39-48), but the description only covers container verbs (build, push, run, inspect). This could confuse users authoring type: archive steps.

📝 Updated description
         "action": {
           "type": "string",
-          "description": "Container verb for the container step type: build, push, run, or inspect."
+          "description": "Container verb for the container step type (build, push, run, inspect), or archive verb for the archive step type (create, extract, update, replace)."
         },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json` around
lines 2403 - 2406, Update the action field description in the atmos manifest
schema to document archive verbs create, extract, update, and replace in
addition to the existing container verbs build, push, run, and inspect.
🧹 Nitpick comments (1)
website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json (1)

2436-2461: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Schema fields match the Go contract — consider constraining format with an enum.

The five new properties (format, destination, subpath, include, exclude) correctly mirror pkg/schema/workflow.go:375-382 and map to archive.PackOptions fields consumed in pkg/archive/archive.go:25-99. Types and descriptions are accurate.

The format field is a free-form string whose description lists valid values (zip, tar, tgz, tar.bz2, tar.xz). Adding an enum would let schema validators catch typos before runtime, matching the pattern already used for kubernetes_provider (line 506) and backend_type (line 1281).

♻️ Suggested enum for `format`
         "format": {
           "type": "string",
+          "enum": ["zip", "tar", "tgz", "tar.bz2", "tar.xz"],
           "description": "Archive format for the archive step type: zip, tar, tgz, tar.bz2, or tar.xz. Inferred from destination's extension when omitted."
         },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json` around
lines 2436 - 2461, Constrain the archive step’s format property to the
documented values by adding an enum containing zip, tar, tgz, tar.bz2, and
tar.xz, while preserving its existing string type and description.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`:
- Around line 2403-2406: Update the action field description in the atmos
manifest schema to document archive verbs create, extract, update, and replace
in addition to the existing container verbs build, push, run, and inspect.

---

Nitpick comments:
In `@website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`:
- Around line 2436-2461: Constrain the archive step’s format property to the
documented values by adding an enum containing zip, tar, tgz, tar.bz2, and
tar.xz, while preserving its existing string type and description.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 290604ef-2a89-4058-a074-0170a4d3703e

📥 Commits

Reviewing files that changed from the base of the PR and between 05d86d2 and a14653e.

📒 Files selected for processing (10)
  • errors/errors.go
  • pkg/archive/archive.go
  • pkg/archive/archive_test.go
  • pkg/archive/tar.go
  • pkg/archive/walk.go
  • pkg/archive/zip.go
  • website/docs/workflows/_partials/_step-types.mdx
  • website/docs/workflows/workflows/workflow/steps/type.mdx
  • website/docs/workflows/workflows/workflow/steps/type/archive.mdx
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
✅ Files skipped from review due to trivial changes (3)
  • website/docs/workflows/_partials/_step-types.mdx
  • website/docs/workflows/workflows/workflow/steps/type.mdx
  • website/docs/workflows/workflows/workflow/steps/type/archive.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • pkg/archive/tar.go
  • errors/errors.go
  • pkg/archive/zip.go
  • pkg/archive/archive.go

@codecov

codecov Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.80892% with 64 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.65%. Comparing base (f7da938) to head (7d90cb3).

Files with missing lines Patch % Lines
pkg/archive/mtime.go 78.49% 10 Missing and 10 partials ⚠️
pkg/archive/tar.go 79.54% 9 Missing and 9 partials ⚠️
pkg/archive/zip.go 82.05% 7 Missing and 7 partials ⚠️
pkg/archive/archive.go 93.10% 6 Missing and 2 partials ⚠️
pkg/archive/format.go 95.45% 2 Missing ⚠️
pkg/archive/walk.go 97.87% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2730      +/-   ##
==========================================
+ Coverage   81.60%   81.65%   +0.05%     
==========================================
  Files        1641     1648       +7     
  Lines      154902   155530     +628     
==========================================
+ Hits       126408   127000     +592     
- Misses      21564    21571       +7     
- Partials     6930     6959      +29     
Flag Coverage Δ
unittests 81.65% <89.80%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
errors/errors.go 100.00% <ø> (ø)
pkg/cache/filelock_unix.go 82.60% <ø> (ø)
pkg/runner/step/archive.go 100.00% <100.00%> (ø)
pkg/schema/task.go 97.35% <100.00%> (+0.06%) ⬆️
pkg/schema/workflow.go 100.00% <ø> (ø)
pkg/archive/format.go 95.45% <95.45%> (ø)
pkg/archive/walk.go 97.87% <97.87%> (ø)
pkg/archive/archive.go 93.10% <93.10%> (ø)
pkg/archive/zip.go 82.05% <82.05%> (ø)
pkg/archive/tar.go 79.54% <79.54%> (ø)
... and 1 more

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Codecov flagged the archive-step PR's patch coverage at 74.4% (target 85%).
Adds targeted tests for previously-uncovered branches: format inference
across all tar.bz2/tar.xz/tar extension aliases, Run() with an unknown
action, update()'s own validation/MkdirAll error paths, destinationMode and
atomicRewrite's direct error paths (stat failures, CreateTemp failure, a
failing write callback, a rename-over-non-empty-directory failure), missing
source entries fed straight into updateZip/updateTar, corrupt existing
archives on update, single-file sources with an invalid glob pattern, a
generic (non-glob) directory-walk failure, and every template-resolution
error path in the archive step handler (source/destination/format/subpath/
include/exclude) plus a combined include+exclude success case. Raises
pkg/archive from 83.7% to 93.0% and pkg/runner/step/archive.go to 100%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/archive/archive_test.go (1)

568-593: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider asserting the specific error type for MkdirAll failures.

TestRun_Replace_MkdirAllFailure and TestRun_Update_MkdirAllFailure only assert require.Error(t, err), whereas the sibling TestAtomicRewrite_DestinationModeError (line 623) exercises the same "destination nested under a regular file" scenario and asserts errors.Is(err, errUtils.ErrArchiveWriteFailed). Tightening these two tests to check the same sentinel would catch regressions where the error type changes silently.

♻️ Proposed tightening
 func TestRun_Replace_MkdirAllFailure(t *testing.T) {
 	dir := t.TempDir()
 	src := filepath.Join(dir, "src")
 	writeFixture(t, src)

 	err := Run(ActionReplace, &PackOptions{Source: src, Destination: notADirDestination(t, dir)})
 	require.Error(t, err)
+	assert.True(t, errors.Is(err, errUtils.ErrArchiveWriteFailed))
 }

 func TestRun_Update_MkdirAllFailure(t *testing.T) {
 	dir := t.TempDir()
 	src := filepath.Join(dir, "src")
 	writeFixture(t, src)

 	err := Run(ActionUpdate, &PackOptions{Source: src, Destination: notADirDestination(t, dir)})
 	require.Error(t, err)
+	assert.True(t, errors.Is(err, errUtils.ErrArchiveWriteFailed))
 }

Please confirm replace()/update() actually surface ErrArchiveWriteFailed for this failure path before applying (not fully visible in the provided context).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/archive/archive_test.go` around lines 568 - 593, Update
TestRun_Replace_MkdirAllFailure and TestRun_Update_MkdirAllFailure to assert
that the returned error matches errUtils.ErrArchiveWriteFailed using errors.Is,
while retaining the existing error assertion if appropriate. First verify that
replace() and update() propagate this sentinel for the notADirDestination
MkdirAll failure path, and adjust only the error propagation if necessary to
preserve that contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/archive/archive_test.go`:
- Around line 568-593: Update TestRun_Replace_MkdirAllFailure and
TestRun_Update_MkdirAllFailure to assert that the returned error matches
errUtils.ErrArchiveWriteFailed using errors.Is, while retaining the existing
error assertion if appropriate. First verify that replace() and update()
propagate this sentinel for the notADirDestination MkdirAll failure path, and
adjust only the error propagation if necessary to preserve that contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 85393001-f737-4c6d-b048-2a2b9e44d49b

📥 Commits

Reviewing files that changed from the base of the PR and between a14653e and 73e358c.

📒 Files selected for processing (4)
  • errors/errors.go
  • pkg/archive/archive_test.go
  • pkg/runner/step/archive_test.go
  • website/src/data/roadmap.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/src/data/roadmap.js
  • errors/errors.go

Shell/stdlib zip and tar both bake in real file mtime and permission
bits, so identical source content produces different archive bytes on
every rebuild — the same non-determinism long reported against
Terraform's archive_file provider. Add reproducible: epoch|git,
backed by go-git commit history (no shelling out to git log), plus
permission-bit normalization. Opt-in and off by default so existing
workflows are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
pkg/archive/tar.go (1)

14-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add tgz to the reproducibility byte-identical test.

The comment claims tgz output needs no extra reproducibility handling, but TestRun_Replace_Reproducible_ByteIdenticalRegardlessOfSourceMetadata only tests zip and tar. Adding {"tgz", ".tgz"} would verify the gzip header (timestamp, OS field) doesn't break determinism. As per coding guidelines, every new feature must include comprehensive unit tests targeting >80% code coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/archive/tar.go` around lines 14 - 20, Extend
TestRun_Replace_Reproducible_ByteIdenticalRegardlessOfSourceMetadata to include
the tgz format with its .tgz extension alongside zip and tar. Ensure the test
compares tgz outputs byte-for-byte across differing source metadata, covering
gzip-header determinism and the reproducibility behavior described by the
writeTar documentation.

Source: Coding guidelines

pkg/archive/reproducible_test.go (1)

61-73: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test for source = repo root.

No test covers newReproducibleTimestamps with source set to the repository root. This is the edge case where filepath.Rel returns ".", which currently causes lastCommitForPrefix to fail silently and fall back to 1980-01-01. As per coding guidelines, every new feature must include comprehensive unit tests targeting >80% code coverage.

🧪 Proposed test
func TestNewReproducibleTimestamps_EpochMode_SourceIsRepoRoot(t *testing.T) {
	root, _, _, t3 := gitFixture(t)

	rt := newReproducibleTimestamps(ReproducibleEpoch, root)

	// When source is the repo root, the epoch should be the latest commit
	// in the repo (t3, "add readme"), not the fallback 1980-01-01.
	assert.Equal(t, t3, rt.epoch)
	assert.Equal(t, t3, rt.modTimeFor(filepath.Join(root, "src", "a.txt")))
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/archive/reproducible_test.go` around lines 61 - 73, Add a unit test
covering newReproducibleTimestamps with source set to the repository root,
verifying the epoch and a file timestamp use the repository’s latest commit
rather than the fallback timestamp. Create the test alongside
TestNewReproducibleTimestamps_EpochMode_UsesLastCommitTouchingSubtree and reuse
gitFixture and the existing timestamp assertions.

Source: Coding guidelines

pkg/runner/step/archive.go (1)

90-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the repeated resolve-and-wrap pattern.

source, destination, format, subpath, include, exclude, and now reproducible each repeat the same vars.Resolve(...) + if err != nil { return ..., fmt.Errorf("step '%s': failed to resolve %s: %w", ...) } shape. With reproducible as the sixth near-identical block, a small helper would cut the boilerplate without changing behavior.

♻️ Sketch of a helper to reduce duplication
func resolveStepField(stepName, fieldName, value string, vars *Variables) (string, error) {
	resolved, err := vars.Resolve(value)
	if err != nil {
		return "", fmt.Errorf("step '%s': failed to resolve %s: %w", stepName, fieldName, err)
	}
	return resolved, nil
}

Each call site collapses to source, err := resolveStepField(step.Name, "source", source, vars), etc.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/runner/step/archive.go` around lines 90 - 139, Extract the repeated
variable-resolution and error-wrapping logic from resolveArchiveOptions into a
helper such as resolveStepField, accepting the step name, field name, value, and
Variables. Use it for source, destination, format, subpath, and reproducible,
while preserving the existing resolveArchiveGlobs handling for include and
exclude and all current error messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/archive/reproducible.go`:
- Around line 206-225: Update lastCommitForPrefix to treat relPrefix "." as the
repository-root prefix: make its PathFilter match every Git path while
preserving the existing exact and nested-prefix matching for non-root prefixes.
Ensure root-source calls return the latest commit instead of io.EOF and
triggering reproducibleFallbackEpoch.

In `@pkg/runner/step/archive.go`:
- Around line 57-63: The reproducible-mode check in Validate currently validates
the raw templated value instead of the resolved option. Move this validation to
the resolved archive options used by resolveArchiveOptions and archive.Run, or
explicitly enforce literal-only values consistently; preserve acceptance of
templates resolving to epoch or git.

In `@website/blog/2026-07-11-archive-step-type.mdx`:
- Around line 114-143: Add a caveat to the “Reproducible Output” section
clarifying that reproducible timestamp and permission normalization applies only
to the archive’s replace path. State that update-mode copied-forward entries
retain the mtime and mode from their prior write, so update archives are not
fully normalized.

---

Nitpick comments:
In `@pkg/archive/reproducible_test.go`:
- Around line 61-73: Add a unit test covering newReproducibleTimestamps with
source set to the repository root, verifying the epoch and a file timestamp use
the repository’s latest commit rather than the fallback timestamp. Create the
test alongside
TestNewReproducibleTimestamps_EpochMode_UsesLastCommitTouchingSubtree and reuse
gitFixture and the existing timestamp assertions.

In `@pkg/archive/tar.go`:
- Around line 14-20: Extend
TestRun_Replace_Reproducible_ByteIdenticalRegardlessOfSourceMetadata to include
the tgz format with its .tgz extension alongside zip and tar. Ensure the test
compares tgz outputs byte-for-byte across differing source metadata, covering
gzip-header determinism and the reproducibility behavior described by the
writeTar documentation.

In `@pkg/runner/step/archive.go`:
- Around line 90-139: Extract the repeated variable-resolution and
error-wrapping logic from resolveArchiveOptions into a helper such as
resolveStepField, accepting the step name, field name, value, and Variables. Use
it for source, destination, format, subpath, and reproducible, while preserving
the existing resolveArchiveGlobs handling for include and exclude and all
current error messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bd88d7a7-0b56-4ad9-928e-3a024afbb868

📥 Commits

Reviewing files that changed from the base of the PR and between 73e358c and b9541d4.

📒 Files selected for processing (15)
  • docs/prd/archive-step.md
  • errors/errors.go
  • pkg/archive/archive.go
  • pkg/archive/archive_test.go
  • pkg/archive/reproducible.go
  • pkg/archive/reproducible_test.go
  • pkg/archive/tar.go
  • pkg/archive/zip.go
  • pkg/runner/step/archive.go
  • pkg/runner/step/archive_test.go
  • pkg/schema/task.go
  • pkg/schema/workflow.go
  • website/blog/2026-07-11-archive-step-type.mdx
  • website/docs/workflows/workflows/workflow/steps/type/archive.mdx
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • errors/errors.go
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • pkg/schema/task.go
  • pkg/schema/workflow.go
  • pkg/archive/zip.go

Comment thread pkg/archive/mtime.go
Comment thread pkg/runner/step/archive.go Outdated
Comment thread website/blog/2026-07-11-archive-step-type.mdx
- lastCommitForPrefix silently fell back to the fixed epoch when source
  was the repository root (filepath.Rel returns "." there, which never
  matches a real git path); match every path in that case.
- Validate rejected a templated reproducible field before resolution,
  so a template resolving to a valid mode still failed early. Move the
  check to after vars.Resolve, in resolveArchiveOptions.
- Note in the blog post that reproducible only normalizes the replace
  path, matching the caveat already in the step reference doc.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TestDestinationMode's "stat error other than not-exist" case and
TestCopyUnchangedTarEntries_OpenFailure both fail on Windows: they use
a file-as-directory-component trick to force a stat/open error, but
Windows reports that as ERROR_PATH_NOT_FOUND (which os.IsNotExist
treats as true), not POSIX's distinct ENOTDIR — so the code under
test correctly treats it as "doesn't exist" and returns no error.
Skip on Windows, matching the existing TestAtomicRewrite_RenameFailure
precedent for the same class of platform difference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/runner/step/archive.go (1)

57-60: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comment references non-existent function name validateResolvedReproducible.

The comment says "See validateResolvedReproducible" but the actual function is resolveArchiveReproducible (line 141). Update the reference to match.

📝 Proposed fix for comment reference
 	// reproducible is not validated here: it supports Go templates and
 	// resolveArchiveOptions resolves it before archive.Run sees it, so
 	// checking the raw (possibly templated) value here would reject a
-	// template that resolves to a valid mode. See validateResolvedReproducible.
+	// template that resolves to a valid mode. See resolveArchiveReproducible.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/runner/step/archive.go` around lines 57 - 60, Update the comment near the
reproducible validation note to reference the existing
resolveArchiveReproducible function instead of the non-existent
validateResolvedReproducible name; leave the surrounding explanation unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/runner/step/archive_test.go`:
- Around line 280-302: Update TestArchiveHandler_Execute_Reproducible to
explicitly call os.Chmod on handler.js after os.WriteFile, setting its
permissions to 0o664 and checking the error. Keep the existing archive assertion
unchanged so it verifies normalization from 0o664 to 0o644.

---

Nitpick comments:
In `@pkg/runner/step/archive.go`:
- Around line 57-60: Update the comment near the reproducible validation note to
reference the existing resolveArchiveReproducible function instead of the
non-existent validateResolvedReproducible name; leave the surrounding
explanation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6ac7a388-00e0-45de-bb12-abeab9fb3159

📥 Commits

Reviewing files that changed from the base of the PR and between 73e358c and 4c14ac5.

📒 Files selected for processing (15)
  • docs/prd/archive-step.md
  • errors/errors.go
  • pkg/archive/archive.go
  • pkg/archive/archive_test.go
  • pkg/archive/reproducible.go
  • pkg/archive/reproducible_test.go
  • pkg/archive/tar.go
  • pkg/archive/zip.go
  • pkg/runner/step/archive.go
  • pkg/runner/step/archive_test.go
  • pkg/schema/task.go
  • pkg/schema/workflow.go
  • website/blog/2026-07-11-archive-step-type.mdx
  • website/docs/workflows/workflows/workflow/steps/type/archive.mdx
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
🚧 Files skipped from review as they are similar to previous changes (9)
  • pkg/archive/tar.go
  • pkg/archive/archive.go
  • pkg/schema/workflow.go
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • pkg/schema/task.go
  • errors/errors.go
  • pkg/archive/reproducible.go
  • pkg/archive/zip.go
  • pkg/archive/archive_test.go

Comment thread pkg/runner/step/archive_test.go Outdated
Renames the archive step's opt-in reproducible: epoch|git field to
mtime: filesystem|epoch|git, naming it after the mechanism it controls
(the per-entry timestamp stamped into the archive) rather than an
opinionated outcome word, and making the default an explicit value
instead of an implicit empty string.

Also tightens the PRD and blog post: the archive_file dependency-ordering
claim now cites the actual upstream Terraform issues and explains the
missing-reference root cause instead of reading as an unqualified
strawman, and both docs now state explicitly that action: replace is
idempotent while action: update is not, rather than implying it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- pkg/cache: bump the exclusive-lock retry budget from 500ms to 2s
  (filelock_unix.go). TestFileCache_ConcurrentAccess was intermittently
  failing on Linux CI with "cache file is locked by another process" -
  10 goroutines contending for the cache directory's single lock file
  could exceed the old 50-retry/10ms budget under normal CI load. Ran
  the test 50x locally with -race after the fix with no failures.
- CI workflow: bump the Windows/macOS "Acceptance tests" step timeout
  from 45m to 60m. Compared successful vs. failed run timings for this
  step: 37m43s vs. 45m06s (timed out) - only ~7 minutes of headroom on
  a step with that much run-to-run variance. 60m matches the Linux
  coverage step's existing budget.
- docs/prd/archive-step.md, website/blog: drop the "still-open" framing
  on the cited archive_file GitHub issues - verified via `gh issue view`
  that all three (hashicorp/terraform#30042, terraform-provider-archive
  #218 and #34) are actually closed. Reworded to cite them as documented
  evidence of the failure mode without asserting current issue-tracker
  status.
- website/docs archive.mdx: scope the byte-identical-output claim to
  mtime: epoch/git only - mtime: filesystem preserves real source mtime
  and permission bits and is not deterministic.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@mergify

mergify Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

@mergify mergify Bot added the needs-cloudposse Needs Cloud Posse assistance label Jul 13, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 13, 2026
… meaningful

os.WriteFile's requested mode is subject to the process umask, so under the
common 0o022 umask the source file already landed at 0o644 on disk - the
same value the test asserts on the archived entry. That made the assertion
pass trivially without proving normalization actually ran. os.Chmod bypasses
umask, guaranteeing the source is genuinely 0o664 before archiving.

Addresses a CodeRabbit finding on PR #2730; verified against current code
that the other four open findings on that review pass no longer apply (format
inference from source is by design reserved for the not-yet-implemented
extract action per the PRD, and the tar.go permission-stripping concern is
already handled by atomicRewrite's destinationMode() chmod).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 13, 2026
@mergify

mergify Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Erik Osterman (Cloud Posse) (@osterman)? 🙏

@mergify mergify Bot added the conflict This PR has conflicts label Jul 13, 2026
…type-prd

# Conflicts:
#	.github/workflows/test.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@errors/errors.go`:
- Line 845: In the error sentinel declarations near ErrLayerExtraction, restore
the deprecated ErrTarballExtraction alias by assigning it to ErrLayerExtraction.
Add a deprecation comment documenting that callers should use
ErrLayerExtraction, preserving the existing sentinel identity for external
users.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc9e34ca-6ac9-4aa9-b61f-3a45bc3a1656

📥 Commits

Reviewing files that changed from the base of the PR and between d50f2e3 and 7d90cb3.

📒 Files selected for processing (2)
  • errors/errors.go
  • website/src/data/roadmap.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/src/data/roadmap.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@errors/errors.go`:
- Line 845: In the error sentinel declarations near ErrLayerExtraction, restore
the deprecated ErrTarballExtraction alias by assigning it to ErrLayerExtraction.
Add a deprecation comment documenting that callers should use
ErrLayerExtraction, preserving the existing sentinel identity for external
users.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc9e34ca-6ac9-4aa9-b61f-3a45bc3a1656

📥 Commits

Reviewing files that changed from the base of the PR and between d50f2e3 and 7d90cb3.

📒 Files selected for processing (2)
  • errors/errors.go
  • website/src/data/roadmap.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/src/data/roadmap.js
🛑 Comments failed to post (1)
errors/errors.go (1)

845-845: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n '\bErrTarballExtraction\b|\bErrLayerExtraction\b' --glob '*.go'

Repository: cloudposse/atmos

Length of output: 154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant section of errors/errors.go.
file="errors/errors.go"
wc -l "$file"
sed -n '830,860p' "$file"

# Search for the old and new sentinel names across Go files.
rg -n '\bErrTarballExtraction\b|\bErrLayerExtraction\b' . --glob '*.go' || true

Repository: cloudposse/atmos

Length of output: 2068


Preserve the deprecated alias for the old sentinel. Keep ErrTarballExtraction = ErrLayerExtraction with a deprecation comment so external callers don’t break.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@errors/errors.go` at line 845, In the error sentinel declarations near
ErrLayerExtraction, restore the deprecated ErrTarballExtraction alias by
assigning it to ErrLayerExtraction. Add a deprecation comment documenting that
callers should use ErrLayerExtraction, preserving the existing sentinel identity
for external users.

@aknysh
Andriy Knysh (aknysh) merged commit 0de155e into main Jul 14, 2026
83 checks passed
@aknysh
Andriy Knysh (aknysh) deleted the osterman/custom-step-type-prd branch July 14, 2026 01:46
@atmos-pro

atmos-pro Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@mergify mergify Bot removed the needs-cloudposse Needs Cloud Posse assistance label Jul 14, 2026
@github-actions

Copy link
Copy Markdown

Warning

Release Documentation Required

This PR is labeled minor or major and requires documentation updates:

  • Changelog entry - Add a blog post in website/blog/YYYY-MM-DD-feature-name.mdx
  • Roadmap update - Update website/src/data/roadmap.js with the new milestone

Alternatively: If this change doesn't require release documentation, remove the minor or major label.

@github-actions

Copy link
Copy Markdown

These changes were released in v1.223.0-rc.11.

This branch was successfully deployed

1 active deployment
preview — 7d90cb34 Deployed Jul 14, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/l Large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants