Skip to content

Commit d261c78

Browse files
committed
Merge remote-tracking branch 'origin/main' into osterman/scanner-ci-annotations-results
2 parents 4c8f5a4 + 2c6912a commit d261c78

216 files changed

Lines changed: 17494 additions & 3160 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/docs/SKILL.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ Every new or changed `atmos.yaml` section needs configuration docs.
3737
- Use `<dl>`, `<dt>`, and `<dd>` for configuration keys and option definitions.
3838
- Include defaults, supported values, and environment variables when they are part of the public interface.
3939

40+
## Sidebar Hierarchy
41+
42+
For configuration docs, make the sidebar resemble the YAML hierarchy.
43+
44+
- Parent categories may link to the page for the object they represent.
45+
- Prefer visible labels that are config keys or object names, such as `workflows`, `workflow`, `steps`, and `env`.
46+
- Avoid editorial labels like "Overview", "Execution", or "Runtime Context" when the page represents a configuration object.
47+
- Do not promote enum values or type-specific parameters to sidebar peers unless they are independent configuration objects.
48+
- When possible, use folder structure plus `_category_.json` so autogenerated sidebar entries inherit the YAML-shaped hierarchy from the docs tree.
49+
- If site-level sidebar sorting prevents YAML-order rendering, use explicit sidebar entries for that section rather than changing global sidebar behavior.
50+
4051
## Command Docs
4152

4253
When command behavior is configured by `atmos.yaml`, link command docs back to configuration docs.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# End-to-end test for the `github/artifacts` planfile store via the EXPLICIT CLI
2+
# (manual) path, across two separate jobs:
3+
#
4+
# plan job -> `atmos terraform plan --ci` uploads the planfile to GitHub
5+
# Actions Artifacts.
6+
# apply job -> explicitly `atmos terraform planfile download` the artifact
7+
# (cross-job, same run) and `atmos terraform apply --planfile=...`.
8+
#
9+
# The AUTOMATIC hook-driven flow (plan --ci upload -> deploy --ci auto download +
10+
# verify + apply) is tested separately in planfile-verify-e2e.yml.
11+
#
12+
# This is the one path no Go unit test can cover: the backend talks to the
13+
# GitHub Actions Artifacts API directly using the runner-only
14+
# ACTIONS_RUNTIME_TOKEN / ACTIONS_RESULTS_URL, which GitHub withholds from
15+
# `run:` steps. We dogfood the in-repo `actions/github-runtime` action
16+
# (mode: env) to surface them — exactly the wiring documented at
17+
# /ci/planfile-storage.
18+
#
19+
# The IaC binary is also dogfooded through the Atmos toolchain: the fixture
20+
# declares `dependencies.tools.opentofu` (+ `command: tofu`), so
21+
# `atmos terraform plan/apply` auto-installs OpenTofu and resolves it from the
22+
# toolchain PATH — no hashicorp/setup-terraform action required.
23+
name: Planfile Artifacts E2E
24+
25+
on:
26+
workflow_dispatch:
27+
pull_request:
28+
types: [opened, synchronize, reopened]
29+
paths:
30+
- 'pkg/ci/artifact/**'
31+
- 'cmd/terraform/planfile/**'
32+
- 'pkg/ci/plugins/terraform/**'
33+
- 'actions/github-runtime/**'
34+
- 'tests/fixtures/scenarios/planfile-artifacts-e2e/**'
35+
- '.github/workflows/planfile-artifacts-e2e.yml'
36+
37+
permissions:
38+
contents: read
39+
actions: read # Required for the GITHUB_TOKEN to list/download artifacts via the REST API.
40+
41+
concurrency:
42+
group: ${{ github.workflow }}-${{ github.ref }}
43+
cancel-in-progress: true
44+
45+
env:
46+
# Pin the SHA so the plan upload and the apply download derive the identical
47+
# planfile key across both jobs.
48+
ATMOS_CI_SHA: ${{ github.sha }}
49+
GITHUB_TOKEN: ${{ github.token }}
50+
FIXTURE_DIR: tests/fixtures/scenarios/planfile-artifacts-e2e
51+
52+
jobs:
53+
plan:
54+
name: plan (upload planfile)
55+
runs-on: ubuntu-latest
56+
steps:
57+
- name: Checkout
58+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
59+
with:
60+
persist-credentials: false
61+
62+
- name: Set up Go
63+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
64+
with:
65+
go-version-file: "go.mod"
66+
67+
- name: Build atmos
68+
run: |
69+
make build
70+
echo "$PWD/build" >> "$GITHUB_PATH"
71+
72+
# Surface the runner's ACTIONS_* credentials to every later run step.
73+
# This is the entire reason github/artifacts works from a `run:` step.
74+
- name: Expose GitHub Actions runtime credentials
75+
uses: ./actions/github-runtime
76+
with:
77+
mode: env
78+
79+
- name: Plan and upload the planfile
80+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
81+
run: atmos terraform plan mycomponent -s prod --ci
82+
83+
apply:
84+
name: apply (consume planfile)
85+
needs: plan
86+
runs-on: ubuntu-latest
87+
steps:
88+
- name: Checkout
89+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
90+
with:
91+
persist-credentials: false
92+
93+
- name: Set up Go
94+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
95+
with:
96+
go-version-file: "go.mod"
97+
98+
- name: Build atmos
99+
run: |
100+
make build
101+
echo "$PWD/build" >> "$GITHUB_PATH"
102+
103+
- name: Expose GitHub Actions runtime credentials
104+
uses: ./actions/github-runtime
105+
with:
106+
mode: env
107+
108+
- name: Download the planfile uploaded by the plan job
109+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
110+
run: |
111+
set -euo pipefail
112+
# The named "github" store carries prefix=planfile and resolves owner/repo
113+
# from GITHUB_REPOSITORY — matching exactly what the plan job's --ci upload
114+
# hook wrote (planfile-<stack>--<component>--<sha>.tfplan.tar in this run).
115+
# Artifacts are run-scoped, so the plan job's upload is visible here.
116+
atmos terraform planfile download mycomponent -s prod \
117+
--store=github -o "$RUNNER_TEMP/downloaded.planfile"
118+
test -s "$RUNNER_TEMP/downloaded.planfile"
119+
120+
- name: Apply the downloaded planfile
121+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
122+
run: |
123+
set -euo pipefail
124+
# Apply exactly the plan that was reviewed in the plan job — no re-plan.
125+
atmos terraform apply mycomponent -s prod --planfile="$RUNNER_TEMP/downloaded.planfile"
126+
echo "Round-trip OK: planfile uploaded by the plan job was applied by the apply job."
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# End-to-end test for the AUTOMATIC native-CI planfile flow on `deploy`.
2+
#
3+
# Distinct from planfile-artifacts-e2e.yml (which exercises the *manual* CLI:
4+
# `planfile download` + `apply --planfile`). This workflow exercises the
5+
# hook-driven automatic path:
6+
#
7+
# plan job -> `atmos terraform plan` auto-uploads the planfile, then
8+
# `atmos terraform planfile list` asserts it landed.
9+
# deploy-verify job -> `atmos terraform deploy` auto-downloads the stored plan,
10+
# runs the plan-diff, and applies the verified plan
11+
# (verification is on by default under CI).
12+
# deploy-drift job -> mutates the component so the fresh plan differs, then
13+
# asserts `deploy` FAILS on drift (verify mode fail).
14+
#
15+
# CI is auto-detected (CI/GITHUB_ACTIONS) and the fixture sets `ci.enabled: true`,
16+
# so the `--ci` flag is unnecessary — the commands behave natively and assert via
17+
# their own exit codes and structured output rather than grepping logs.
18+
#
19+
# The warn/off mode decisions are covered by unit tests (finalizeVerification,
20+
# ResolveVerifyMode); this workflow covers the real runner integration.
21+
#
22+
# Like the upload, the automatic download talks to the GitHub Artifacts runtime
23+
# API, so every job surfaces ACTIONS_RUNTIME_TOKEN/RESULTS_URL via the in-repo
24+
# github-runtime action. OpenTofu is dogfooded through the Atmos toolchain (the
25+
# fixture declares dependencies.tools.opentofu), so there is no setup-terraform.
26+
name: Planfile Verify E2E
27+
28+
on:
29+
workflow_dispatch:
30+
pull_request:
31+
types: [opened, synchronize, reopened]
32+
paths:
33+
- 'pkg/ci/artifact/**'
34+
- 'cmd/terraform/**'
35+
- 'internal/exec/terraform_verify_plan.go'
36+
- 'internal/exec/terraform_plan_diff*.go'
37+
- 'pkg/ci/plugins/terraform/**'
38+
- 'actions/github-runtime/**'
39+
- 'tests/fixtures/scenarios/planfile-artifacts-e2e/**'
40+
- '.github/workflows/planfile-verify-e2e.yml'
41+
42+
permissions:
43+
contents: read
44+
actions: read # GITHUB_TOKEN reads artifacts via the REST API (fallback path).
45+
46+
concurrency:
47+
group: ${{ github.workflow }}-${{ github.ref }}
48+
cancel-in-progress: true
49+
50+
env:
51+
# Pin the SHA so the plan upload and the deploy download derive the identical
52+
# planfile key across jobs.
53+
ATMOS_CI_SHA: ${{ github.sha }}
54+
GITHUB_TOKEN: ${{ github.token }}
55+
FIXTURE_DIR: tests/fixtures/scenarios/planfile-artifacts-e2e
56+
57+
jobs:
58+
plan:
59+
name: plan (upload planfile)
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: Checkout
63+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
64+
with:
65+
persist-credentials: false
66+
- name: Set up Go
67+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
68+
with:
69+
go-version-file: "go.mod"
70+
- name: Build atmos
71+
run: |
72+
make build
73+
echo "$PWD/build" >> "$GITHUB_PATH"
74+
- name: Expose GitHub Actions runtime credentials
75+
uses: ./actions/github-runtime
76+
with:
77+
mode: env
78+
- name: Plan and upload the planfile
79+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
80+
# No --ci: GitHub Actions is auto-detected (CI/GITHUB_ACTIONS) and the
81+
# fixture sets ci.enabled, so the upload hook runs natively.
82+
run: atmos terraform plan mycomponent -s prod
83+
- name: List the uploaded planfile
84+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
85+
# Exercises the github/artifacts List() against the real runner API and
86+
# proves the upload landed, asserting the command's structured JSON output
87+
# (not grepping log prose). The command already filters by component+stack
88+
# +SHA, so a non-empty array means the planfile is there; an absent one
89+
# renders `null`, which `length > 0` fails on.
90+
run: |
91+
set -euo pipefail
92+
atmos terraform planfile list mycomponent -s prod --format=json \
93+
| jq -e 'length > 0' > /dev/null
94+
95+
deploy-verify:
96+
name: deploy (auto verify + apply)
97+
needs: plan
98+
runs-on: ubuntu-latest
99+
steps:
100+
- name: Checkout
101+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
102+
with:
103+
persist-credentials: false
104+
- name: Set up Go
105+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
106+
with:
107+
go-version-file: "go.mod"
108+
- name: Build atmos
109+
run: |
110+
make build
111+
echo "$PWD/build" >> "$GITHUB_PATH"
112+
- name: Expose GitHub Actions runtime credentials
113+
uses: ./actions/github-runtime
114+
with:
115+
mode: env
116+
- name: Deploy with automatic verification
117+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
118+
# No drift: the deploy re-plans the unchanged component, the plan-diff matches
119+
# the stored plan, and the verified plan is applied. No --ci, no log grep: a
120+
# green deploy *proves* verification ran, because a missing stored plan now
121+
# fails loudly (planfiles.required defaults to tracking the verify mode,
122+
# which is fail under CI).
123+
run: atmos terraform deploy mycomponent -s prod
124+
125+
deploy-drift:
126+
name: deploy (drift fails)
127+
needs: plan
128+
runs-on: ubuntu-latest
129+
steps:
130+
- name: Checkout
131+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
132+
with:
133+
persist-credentials: false
134+
- name: Set up Go
135+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
136+
with:
137+
go-version-file: "go.mod"
138+
- name: Build atmos
139+
run: |
140+
make build
141+
echo "$PWD/build" >> "$GITHUB_PATH"
142+
- name: Expose GitHub Actions runtime credentials
143+
uses: ./actions/github-runtime
144+
with:
145+
mode: env
146+
- name: Induce drift and expect deploy to fail
147+
working-directory: tests/fixtures/scenarios/planfile-artifacts-e2e
148+
# Native exit code is the contract: deploy exits non-zero on drift
149+
# (ErrPlanVerificationFailed), so an inverted check needs no --ci, no
150+
# captured `$?`, and no log grep.
151+
run: |
152+
set -euo pipefail
153+
# Mutate the component so the fresh plan differs from the stored plan.
154+
sed -i 's/test = "test"/test = "drifted"/' components/terraform/mock/main.tf
155+
156+
if atmos terraform deploy mycomponent -s prod; then
157+
echo "ERROR: expected drift to block the deploy, but it succeeded."
158+
exit 1
159+
fi
160+
echo "Drift correctly blocked the deploy."

.github/workflows/pre-commit.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ jobs:
4040

4141
- name: Install Go tools
4242
run: |
43-
# Install gofumpt for pre-commit
44-
go install mvdan.cc/gofumpt@latest
43+
# Install gofumpt for pre-commit.
44+
# Pin to the gofumpt bundled by golangci-lint v2.5.0 (the gofumpt formatter in
45+
# .golangci.yml) so the standalone hook and the linter stay in lockstep. Floating
46+
# @latest drifted to v0.10.0, which reformats v0.9.x-clean code and broke unrelated
47+
# files that fell into the PR diff range.
48+
go install mvdan.cc/gofumpt@v0.9.1
4549
4650
# Install golangci-lint v2
4751
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.5.0

.github/workflows/test.yml

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,8 +745,60 @@ jobs:
745745
]
746746
}
747747
748+
# run container step tests against a local registry (build -> push -> run)
749+
# Docker is available directly on the runner (see the k3s job), and a
750+
# registry:2 service container provides a hermetic push/pull target on
751+
# localhost:5000 so the full build -> push -> run cycle is exercised without
752+
# GitHub Container Registry, leftover packages, or fork-PR token limits.
753+
container-step:
754+
name: "[container-step] example"
755+
needs: build
756+
runs-on: ubuntu-latest
757+
758+
services:
759+
registry:
760+
image: registry:2
761+
ports:
762+
- 5000:5000
763+
764+
timeout-minutes: 15
765+
steps:
766+
- name: Download build artifacts
767+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
768+
with:
769+
name: build-artifacts-linux
770+
path: /usr/local/bin
771+
772+
- name: Set execute permissions on atmos
773+
run: chmod +x /usr/local/bin/atmos
774+
775+
- name: Check out code into the Go module directory
776+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
777+
with:
778+
persist-credentials: false
779+
780+
- name: Run container steps (run, build, bake, push, workspace, env)
781+
working-directory: examples/container-step
782+
run: |
783+
set -euo pipefail
784+
atmos workflow hello -f container-step
785+
atmos workflow build-run -f container-step
786+
atmos workflow bake-build-run -f container-step
787+
atmos workflow push-local-registry -f container-step
788+
atmos workflow workspace -f container-step
789+
atmos workflow env -f container-step
790+
791+
- name: Verify a failing container step propagates a non-zero exit code
792+
working-directory: examples/container-step
793+
run: |
794+
if atmos workflow failing-check -f container-step; then
795+
echo "expected the 'failing-check' workflow to fail, but it succeeded"
796+
exit 1
797+
fi
798+
echo "failing-check correctly returned a non-zero exit code"
799+
748800
release:
749-
needs: [test, lint, mock, k3s, floci, floci-go, docker, validate]
801+
needs: [test, lint, mock, k3s, floci, floci-go, docker, validate, container-step]
750802
if: github.event_name == 'push'
751803
uses: cloudposse/.github/.github/workflows/shared-go-auto-release.yml@8244c7c9142e92281e7841f655fa48e9ceb9b454 # main
752804
with:

0 commit comments

Comments
 (0)