Skip to content

Commit 605dba2

Browse files
committed
Merge remote-tracking branch 'origin/main' into osterman/terramate-migration-skill
# Conflicts: # agent-skills/skills/atmos-migration/SKILL.md
2 parents 9a2067e + 13bce50 commit 605dba2

3,379 files changed

Lines changed: 280118 additions & 161286 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.

.atmos.d/build.yaml

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ commands:
22
- name: build
33
description: Build and documentation commands for Atmos development
44
default: binary
5-
# No working_directory here (unlike other custom commands): this command
6-
# bootstraps the very first build using a pinned, possibly-older atmos
7-
# release (see .github/workflows/version-tracker.yaml's
8-
# ATMOS_BOOTSTRAP_VERSION), so it must not depend on YAML tags newer than
9-
# that pin (e.g. !repo-root). Each step below resolves the repo root
10-
# itself via `git rev-parse --show-toplevel` instead.
5+
working_directory: !repo-root .
116
env: &build_env
127
- key: GOTOOLCHAIN
138
value: auto
@@ -26,7 +21,9 @@ commands:
2621
- type: toast
2722
level: info
2823
content: Building Atmos...
29-
- &build_binary_step |
24+
- &build_binary_step
25+
type: shell
26+
command: |
3027
set -eu
3128
sh scripts/build-atmos.sh "${ATMOS_BUILD_TARGET:-default}" "${ATMOS_BUILD_VERSION:-test}"
3229
- &build_success_step
@@ -39,15 +36,23 @@ commands:
3936
content: 'Run `atmos dev shell` so `atmos` resolves to `./build/atmos`.'
4037
commands:
4138
- name: deps
42-
description: Download Go module dependencies
39+
description: Download Go module dependencies, retrying on transient network failures
40+
working_directory: !repo-root .
4341
env:
4442
- key: GOTOOLCHAIN
4543
value: auto
4644
steps:
47-
- cd "$(git rev-parse --show-toplevel)" && go mod download
45+
- command: go mod download
46+
type: shell
47+
retry:
48+
max_attempts: 5
49+
initial_delay: 5s
50+
max_delay: 60s
51+
backoff_strategy: exponential
4852

4953
- name: binary
5054
description: Build the Atmos binary
55+
working_directory: !repo-root .
5156
env: *build_env
5257
flags:
5358
- name: target
@@ -66,6 +71,7 @@ commands:
6671

6772
- name: version
6873
description: Print the version from an already-built Atmos binary
74+
working_directory: !repo-root .
6975
env:
7076
- key: ATMOS_BUILD_TARGET
7177
value: "{{ .Flags.target }}"
@@ -76,7 +82,6 @@ commands:
7682
steps:
7783
- |
7884
set -eu
79-
cd "$(git rev-parse --show-toplevel)"
8085
8186
target="${ATMOS_BUILD_TARGET:-default}"
8287
@@ -97,12 +102,12 @@ commands:
97102
98103
- name: readme
99104
description: Regenerate README.md from README.yaml
105+
working_directory: !repo-root .
100106
env:
101107
- key: GOTOOLCHAIN
102108
value: auto
103109
steps:
104110
- |
105111
set -eu
106-
cd "$(git rev-parse --show-toplevel)"
107112
atmos build
108113
./build/atmos docs generate readme

.atmos.d/dev.yaml

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,23 @@ commands:
5959

6060
- name: shell
6161
description: Start a development shell with build/ first on PATH
62+
# Custom commands install only explicitly declared dependencies. Keep
63+
# this in sync with the development tool pins in .tool-versions so a
64+
# fresh `atmos dev shell` is immediately usable after cache cleanup.
65+
dependencies:
66+
tools:
67+
hashicorp/terraform: 1.15.6
68+
opentofu/opentofu: 1.12.2
69+
peteretelej/tree: v1.3.0
70+
sharkdp/bat: v0.26.1
71+
tofu: v1.11.6
72+
working_directory: !repo-root .
6273
steps:
6374
- type: exec
6475
command: |
6576
set -eu
66-
root="$(git rev-parse --show-toplevel)"
67-
cd "$root"
6877
export ATMOS_DEV_SHELL=1
69-
export PATH="$root/build:$PATH"
78+
export PATH="$PWD/build:$PATH"
7079
exec "${SHELL:-/bin/sh}"
7180
7281
- name: validate
@@ -123,11 +132,7 @@ commands:
123132
commands:
124133
- name: notices
125134
description: Regenerate NOTICE from Go dependency licenses
126-
# No working_directory here: scripts/generate-notice.sh already
127-
# resolves the repo root itself via its own script path. Avoiding
128-
# the !repo-root tag also keeps this file parseable by the older
129-
# bootstrap atmos binary used to self-host CI's first build (see
130-
# .atmos.d/build.yaml for the same constraint).
135+
working_directory: !repo-root .
131136
env: *go_auto_env
132137
steps:
133138
- type: spin
@@ -139,16 +144,15 @@ commands:
139144
content: NOTICE regenerated.
140145

141146
- name: mocks
142-
description: Regenerate auth/http mocks using go:generate directives
147+
description: Regenerate auth/http/store mocks using go:generate directives
143148
env: *go_auto_env
144149
steps:
145150
- type: atmos
146-
command: test generate-auth-http-mocks
151+
command: test generate-auth-http-store-mocks
147152

148153
- name: snapshots
149154
description: Regenerate CLI golden snapshots
150-
# No working_directory here (see the "notices" command above for
151-
# why): cd's to the repo root inline in the step below instead.
155+
working_directory: !repo-root .
152156
env:
153157
- key: GOTOOLCHAIN
154158
value: auto
@@ -167,7 +171,6 @@ commands:
167171
- type: shell
168172
command: |
169173
set -eu
170-
cd "$(git rev-parse --show-toplevel)"
171174
filter="${ATMOS_SNAPSHOT_FILTER:-}"
172175
173176
selected=0
@@ -186,3 +189,24 @@ commands:
186189
else
187190
go test ./tests -v -count=1 -timeout 40m -run "$filter" -regenerate-snapshots
188191
fi
192+
193+
- name: schema
194+
description: Regenerate the atmos-manifest JSON Schema website copy from the embedded schema
195+
working_directory: !repo-root .
196+
env:
197+
<<: *go_auto_env
198+
# go run . builds the whole atmos binary graph, which pulls in cgo-linked
199+
# hardware-security-key deps (e.g. github.com/bearsh/hid) that need system
200+
# libudev headers most CI runners don't have. atmos itself always builds
201+
# with CGO disabled (see .goreleaser.yml, scripts/build-atmos.sh), so match
202+
# that here too.
203+
CGO_ENABLED: "0"
204+
SCHEMA_OUTPUT: website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
205+
steps:
206+
- type: spin
207+
title: Generating atmos-manifest schema
208+
command: go run . stack schema {{ .env.SCHEMA_OUTPUT }}
209+
timeout: 2m
210+
- type: toast
211+
level: success
212+
content: atmos-manifest schema regenerated at {{ .env.SCHEMA_OUTPUT }}.

.atmos.d/fix.yaml

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
commands:
2+
- name: fix
3+
description: |
4+
Autonomous patch-quality checks for pr-maintenance-loop, scoped to the current branch's
5+
diff vs a base ref (default origin/main): lint, failing tests, coverage gaps, and replying
6+
to/resolving GitHub PR review threads.
7+
8+
These commands gather data and apply purely mechanical steps (e.g. running the existing
9+
lint gate). The actual "fix this failing test" / "fix this coverage gap" / "fix this lint
10+
finding" reasoning is done by Claude Code agents that consume this output — see
11+
.claude/skills/lint/SKILL.md and .claude/skills/test-coverage/SKILL.md.
12+
flags:
13+
- name: all
14+
type: bool
15+
default: false
16+
description: Run sync, ci, threads, lint, then coverage in sequence (omits `comments`, which needs per-thread parameters) — the full pr-maintenance-loop cycle, runnable standalone outside the hourly loop
17+
steps:
18+
# `when:` conditions only see env/stack/step/status/ci (pkg/runner/runner.go
19+
# taskConditionContext) — flag values aren't available there, confirmed by
20+
# testing, so this guard has to stay a shell conditional rather than a
21+
# native `exit` step gated by `when`.
22+
- type: shell
23+
command: |
24+
set -eu
25+
if [ "{{ .Flags.all }}" != "true" ]; then
26+
echo "Select a fix mode, for example: atmos fix --all, or atmos fix lint / tests / coverage / comments" >&2
27+
exit 1
28+
fi
29+
- type: atmos
30+
command: fix sync
31+
- type: atmos
32+
command: fix ci
33+
- type: atmos
34+
command: fix threads
35+
- type: toast
36+
level: info
37+
content: "Running patch-scoped lint, then tests and coverage..."
38+
- type: atmos
39+
command: fix lint
40+
- type: atmos
41+
command: fix coverage
42+
- type: toast
43+
level: success
44+
content: "atmos fix --all complete."
45+
46+
commands:
47+
- name: symlinks
48+
description: Verify that every Git-tracked symbolic link resolves
49+
working_directory: !repo-root .
50+
steps:
51+
- type: shell
52+
command: scripts/check-symlinks.sh
53+
54+
- name: sync
55+
description: |
56+
Update the PR against origin/main if behind (GitHub-side, via `gh pr update-branch`),
57+
then sync this local checkout with the remote PR branch — `gh pr update-branch` only
58+
updates the remote side via GitHub's API, never the local checkout, so this second half
59+
is required every time to avoid stale local git state (false lint/coverage findings,
60+
rejected pushes). On a real conflict (gh pr update-branch fails), falls back to a local
61+
merge attempt and reports `STATUS: MERGE_CONFLICT` with the conflicted files' content
62+
for the `merge-conflict-resolve` agent (via the `fix-all` skill) to resolve when
63+
confident, or abort and report otherwise — this command itself never decides how to
64+
resolve content conflicts, only surfaces them. The final local-checkout sync is fail
65+
closed: if it isn't a clean fast-forward, this reports an error rather than forcing a
66+
merge or rewrite.
67+
steps:
68+
- type: toast
69+
level: info
70+
content: "Syncing with origin/main and the remote PR branch..."
71+
- type: shell
72+
command: .claude/skills/pr-maintenance-loop/scripts/sync-branch.sh
73+
- type: toast
74+
level: success
75+
content: "Sync complete."
76+
77+
- name: lint
78+
description: |
79+
Patch-aware lint check. Delegates to the existing `atmos lint --changed`, which builds
80+
the custom golangci-lint binary (staleness-guarded — only rebuilds when missing or
81+
stale) and runs it scoped to lines changed vs origin/main.
82+
steps:
83+
# Without this, `--new-from-rev=origin/main` diffs against whatever the local
84+
# origin/main ref last pointed to — which can be stale in a long-running loop against
85+
# an actively-developed repo, wrongly flagging already-merged upstream commits as "new"
86+
# findings on this patch. Confirmed for real: a rebase a few cycles back left the local
87+
# ref behind, and 3 findings from an already-merged, unrelated PR (#2674) got reported
88+
# as if they belonged to this patch.
89+
- type: shell
90+
command: git fetch origin main --quiet
91+
- type: toast
92+
level: info
93+
content: "Running patch-scoped lint (atmos lint --changed)..."
94+
- type: atmos
95+
command: lint --changed
96+
- type: toast
97+
level: success
98+
content: "Patch-scoped lint complete."
99+
100+
- name: coverage
101+
description: |
102+
Run tests scoped to the packages touched by the diff vs a base ref, and report raw
103+
pass/fail status, test output, coverage profile, and the diff itself — no line-level
104+
analysis is done here, that's left to the consuming agent.
105+
arguments:
106+
- name: base-ref
107+
description: Base ref to diff against
108+
default: origin/main
109+
# base-ref is passed via command-level env (not interpolated into a step's command
110+
# string) so shell metacharacters in the value can't be parsed by `sh -c` as command
111+
# syntax. Must be command-level, list-of-key/value form — step-level `env:` (either map
112+
# or list form) silently does not reach the shell subprocess on this atmos version,
113+
# confirmed by testing; command-level list form (matching .atmos.d/build.yaml's existing
114+
# convention) is the one that actually works.
115+
env:
116+
- key: ATMOS_BASE_REF
117+
value: '{{ index .Arguments "base-ref" }}'
118+
steps:
119+
# Same staleness fix as `atmos fix lint` — keep the local remote-tracking ref for the
120+
# base-ref current before diffing against it.
121+
- type: shell
122+
command: git fetch origin --quiet
123+
- type: toast
124+
level: info
125+
content: 'Running scoped tests + coverage vs {{ index .Arguments "base-ref" }}...'
126+
- type: shell
127+
command: .claude/skills/test-coverage/scripts/patch-test-coverage.sh "$ATMOS_BASE_REF"
128+
129+
- name: tests
130+
description: |
131+
Alias for `atmos fix coverage` — the same scoped test run reports pass/fail status too,
132+
this is just the entry point to reach for when the question is "are my tests passing"
133+
rather than "is my patch covered."
134+
arguments:
135+
- name: base-ref
136+
description: Base ref to diff against
137+
default: origin/main
138+
steps:
139+
- type: atmos
140+
command: fix coverage {{ index .Arguments "base-ref" }}
141+
142+
- name: comments
143+
description: |
144+
Reply to (and optionally resolve) a GitHub PR review thread. Hardcodes exactly two
145+
GraphQL mutations (addPullRequestReviewThreadReply, then resolveReviewThread only with
146+
--resolve) — never accepts arbitrary query text, so --body can't be repurposed into a
147+
different mutation even if fully attacker-controlled.
148+
149+
Run `atmos fix threads` first to find a thread's ID.
150+
flags:
151+
- name: thread-id
152+
required: true
153+
description: GraphQL node ID of the review thread (see `atmos fix threads`)
154+
- name: body
155+
required: true
156+
description: 'Reply text, e.g. `Fixed in COMMIT_SHA: one-line summary`'
157+
- name: resolve
158+
type: bool
159+
default: false
160+
description: Also mark the thread resolved — only pass this when a concrete fixing commit exists
161+
# thread-id and body are passed via command-level env (not interpolated into a step's
162+
# command string) so shell metacharacters in --body (quotes, backticks, $()) can't be
163+
# parsed by `sh -c` as command syntax. Must be command-level, list-of-key/value form —
164+
# see the identical note on `fix coverage` above for why.
165+
env:
166+
- key: ATMOS_THREAD_ID
167+
value: '{{ index .Flags "thread-id" }}'
168+
- key: ATMOS_BODY
169+
value: '{{ index .Flags "body" }}'
170+
steps:
171+
- type: shell
172+
command: |
173+
set -eu
174+
args=(--thread-id "$ATMOS_THREAD_ID" --body "$ATMOS_BODY")
175+
if [ "{{ .Flags.resolve }}" = "true" ]; then
176+
args+=(--resolve)
177+
fi
178+
.claude/skills/pr-maintenance-loop/scripts/gh-resolve-review-thread.sh "${args[@]}"
179+
- type: toast
180+
level: success
181+
content: 'Replied to review thread {{ index .Flags "thread-id" }}{{ if .Flags.resolve }} and marked it resolved{{ end }}.'
182+
183+
# Named `threads`, deliberately NOT sharing the `comments` prefix: a multi-word name like
184+
# `comments list` still resolves through the same "comments" command node (same as a true
185+
# nested `commands:` under it) and inherits its required --thread-id/--body flags before
186+
# Cobra even dispatches — confirmed by testing, both ways failed identically on missing
187+
# required flags that belong to the unrelated parent.
188+
- name: threads
189+
description: |
190+
List unresolved, non-outdated CodeRabbit review threads on the current branch's PR —
191+
read-only, no mutation. Prints each thread's node ID (what `atmos fix comments
192+
--thread-id` needs), file path, comment URL, and a one-line preview.
193+
steps:
194+
- type: shell
195+
command: .claude/skills/pr-maintenance-loop/scripts/list-review-threads.sh
196+
197+
- name: ci
198+
description: |
199+
List currently failing CI checks on the current branch's PR, with a failure-log excerpt
200+
where fetchable, plus the diff vs a base ref — read-only, no mutation. Does not judge
201+
whether a failure is caused by this patch or pre-existing; that's left to the consuming
202+
agent, same as `atmos fix coverage`.
203+
steps:
204+
# Same staleness fix as `atmos fix lint` — this script's diff-vs-origin/main section at
205+
# the end needs a current local ref.
206+
- type: shell
207+
command: git fetch origin main --quiet
208+
- type: toast
209+
level: info
210+
content: "Checking CI status..."
211+
- type: shell
212+
command: .claude/skills/pr-maintenance-loop/scripts/list-failing-checks.sh

0 commit comments

Comments
 (0)