You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+20-4Lines changed: 20 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,25 +7,41 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
7
7
```bash
8
8
bun install # install dependencies
9
9
bun run typecheck # tsc --noEmit (type check only, no emit)
10
+
bun test# run unit tests (bun:test) for input validation
10
11
bun run build # bundle src/index.ts → dist/index.js
11
12
```
12
13
13
-
Run both before committing any source change — the runner executes `dist/index.js` directly, so it must always be up to date.
14
+
Run typecheck, tests, and build before committing any source change — the runner executes `dist/index.js` directly, so it must always be up to date.
14
15
15
-
There are no unit tests. The CI workflow (`tester.yml`) validates against a live AWS environment via OIDC.
16
+
Unit tests live in `src/inputs.test.ts` and exercise `sanitizeInputs()` by setting `INPUT_*` env vars (the same mechanism `@actions/core` uses at runtime). Test files are excluded from `tsconfig.json` so bun test handles their typing directly. The CI workflow (`tester.yml`) additionally validates against a live AWS environment via OIDC.
16
17
17
18
## Architecture
18
19
19
20
Single-file GitHub Action (`src/index.ts`) that wraps the AWS SSM `SendCommand` API to run bash commands on EC2 instances without SSH.
20
21
21
22
**Entry points:**
22
23
-`action.yml` — input/output schema and runtime declaration (`node24`)
-`src/inputs.ts` — `sanitizeInputs()` reads inputs via `@actions/core`, validates them, and returns a typed `SanitizedInputs` (or `null` on failure). Pure enough to unit-test by setting `INPUT_*` env vars.
26
+
-`src/inputs.test.ts` — bun:test unit tests for `sanitizeInputs()`
24
27
-`dist/index.js` — Bun-bundled self-contained output; **must be committed** (runners have no build step)
25
28
26
29
**Input validation in `sanitizeInputs()`** (returns `null` and calls `core.setFailed` on any error):
27
-
-`aws-region` — validated against `/^[a-z]{2}-[a-z]+-\d+$/`
30
+
-`aws-region` — validated against `/^[a-z]{2}-[a-z]+(-[a-z]+)?-\d+$/` (supports commercial, GovCloud, and ISO regions)
28
31
-`instance-ids` — each line validated against `/^i-[0-9a-f]{8}([0-9a-f]{9})?$/`; max 50
32
+
-`targets` — each line parsed as `Key=<k>,Values=<v1>[,<v2>...]`; key matched against `/^(InstanceIds|tag:[\w.\-:/+=@ ]{1,128}|resource-groups:(Name|ResourceTypeFilters))$/`; max 5 targets, 50 values per target, 256 chars per value (AWS SSM limits)
33
+
-`document-name` — optional, defaults to `AWS-RunShellScript`. Validated as either a simple SSM document name (`[A-Za-z0-9._-]{3,128}`) or a full document ARN (commercial / cn / us-gov / iso / iso-b partitions)
34
+
-`wait-for-output` — parsed via `core.getBooleanInput`; must be `"true"` or `"false"` (case-insensitive), defaults to `false`
35
+
-`wait-timeout` — parsed as integer, must be 1–3600 inclusive; rejects floats and non-numeric strings; defaults to `60`
36
+
37
+
**Output polling (when `waitForOutput` is true) in `src/index.ts`:**
38
+
- For `instance-ids` mode: polls `GetCommandInvocationCommand` directly for each known ID
39
+
- For `targets` mode: calls `ListCommandInvocationsCommand` first to discover instance IDs (requires `ssm:ListCommandInvocations`), then polls each
40
+
- Exponential backoff: starts at 3 s, caps at 15 s
- Logs per-instance stdout/stderr in collapsible groups; sets `output` action output; fails action on non-success or timeout
43
+
- AWS truncates `StandardOutputContent` at 24 000 bytes per invocation
44
+
- Exactly one of `instance-ids` / `targets` must be set — both or neither is rejected. In `SendCommand`, the action sends `InstanceIds`*or*`Targets`, never both
29
45
-`working-directory` — validated against `/^\/[a-zA-Z0-9._\-/]*$/`; no `..`
30
46
-`command` — split on newlines; empty result is rejected
31
47
-`comment` — newlines stripped, truncated to 100 chars (AWS API limit)
0 commit comments