Skip to content

Commit 5ae7e8d

Browse files
avrabeclaude
andauthored
fix(ci): mythos-auto plumbing — slug ordering, unzip install (#164)
PR #163 was the first end-to-end test of mythos-auto.yml (added in #162). It surfaced three plumbing issues: 1. The action's `oven-sh/setup-bun` step requires `unzip`, which is not installed by default on the rust-cpu runners. Without it the action's bun-based post-step entrypoints exit 127, and the whole scan-step exits failure before emitting structured output. 2. The `Slugify file path for artifact name` step sat AFTER the discover step with no `if: always()`. When discover failed, the slug step was skipped, leaving `steps.slug.outputs.slug` empty. Downstream `if: always()` steps then wrote `mythos-out/.json` (no slug) and `upload-artifact` complained "No files were found with the provided path: mythos-out/.json". 3. The `Save structured output as artifact` step embedded `${{ steps.slug.outputs.slug }}` in the run-block via direct interpolation. Silently substituting an empty slug into a file path is a footgun even if the slug step had run — better to read slug from an env var and fail loudly on empty. Fixes: - Slugify step moves BEFORE the discover step, so it always runs (no `if: always()` needed because both detect+slug are the precondition for everything below). - New `Install unzip (required by setup-bun)` step, best-effort apt install mirroring the action's own subprocess-isolation install pattern. `continue-on-error: true` so non-Debian runners don't break the workflow. - `Save structured output as artifact` reads slug from env (`SLUG`) rather than `${{ }}` interpolation; explicitly errors out if SLUG is empty rather than silently writing to a malformed path. - `upload-artifact` step gains an extra `steps.slug.outputs.slug != ''` guard so it never tries to upload with an empty name. The placeholder-FINDING fallback (the part that surfaced these issues by writing "discover step failed before emitting structured output" into the aggregate comment) is intentional and stays — it guarantees the gate blocks on workflow failure rather than silently passing. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 84a1ed9 commit 5ae7e8d

1 file changed

Lines changed: 43 additions & 11 deletions

File tree

.github/workflows/mythos-auto.yml

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,42 @@ jobs:
145145
steps:
146146
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
147147

148+
# Slugify before discover so the placeholder-write step below
149+
# always has a non-empty `steps.slug.outputs.slug` to reference
150+
# — even when the discover step fails and skips. (PR #163's
151+
# first run skipped this step because it sat AFTER discover
152+
# with no `if: always()`, leaving artifact paths as
153+
# `mythos-out/.json`.)
154+
- name: Slugify file path for artifact name
155+
id: slug
156+
env:
157+
F: ${{ matrix.file }}
158+
run: |
159+
# actions/upload-artifact rejects '/' in names.
160+
slug=${F//\//__}
161+
echo "slug=${slug}" >> "$GITHUB_OUTPUT"
162+
163+
# The action's `oven-sh/setup-bun` step requires `unzip`, which
164+
# is not installed by default on rust-cpu runners. Best-effort
165+
# apt install; mirrors the action's own subprocess-isolation
166+
# install pattern. Continues on failure so non-Debian runners
167+
# don't break the workflow — if unzip is genuinely unavailable
168+
# the next setup-bun step fails and the placeholder fallback
169+
# fires correctly.
170+
- name: Install unzip (required by setup-bun)
171+
continue-on-error: true
172+
run: |
173+
if command -v unzip >/dev/null 2>&1; then
174+
echo "unzip already present"
175+
exit 0
176+
fi
177+
if command -v apt-get >/dev/null && command -v sudo >/dev/null; then
178+
sudo apt-get update -qq
179+
sudo apt-get install -y --no-install-recommends unzip
180+
else
181+
echo "::warning::no apt-get/sudo; setup-bun will likely fail"
182+
fi
183+
148184
- name: Run Mythos discover.md on ${{ matrix.file }}
149185
id: discover
150186
# claude-code-action v1 pinned by commit SHA (not the `v1`
@@ -175,32 +211,28 @@ jobs:
175211
--max-turns 30
176212
--json-schema '{"type":"object","required":["verdict"],"properties":{"verdict":{"type":"string","enum":["NO_FINDINGS","FINDING"]},"file":{"type":"string"},"function":{"type":"string"},"hypothesis":{"type":"string"},"impact":{"type":"string"},"candidate_uca":{"type":"string"},"kani_harness":{"type":"string"},"poc_test":{"type":"string"}}}'
177213
178-
- name: Slugify file path for artifact name
179-
id: slug
180-
env:
181-
F: ${{ matrix.file }}
182-
run: |
183-
# actions/upload-artifact rejects '/' in names.
184-
slug=${F//\//__}
185-
echo "slug=${slug}" >> "$GITHUB_OUTPUT"
186-
187214
- name: Save structured output as artifact
188215
if: always()
189216
env:
190217
RESULT_JSON: ${{ steps.discover.outputs.structured_output }}
218+
SLUG: ${{ steps.slug.outputs.slug }}
191219
F: ${{ matrix.file }}
192220
run: |
193221
mkdir -p mythos-out
222+
if [ -z "${SLUG:-}" ]; then
223+
echo "::error::slug step output is empty — refusing to write to mythos-out/.json"
224+
exit 1
225+
fi
194226
# If the action failed before emitting structured output,
195227
# synthesize a FINDING-shaped placeholder so the aggregator
196228
# treats this file as blocking rather than silently passing.
197229
if [ -z "${RESULT_JSON:-}" ]; then
198230
RESULT_JSON='{"verdict":"FINDING","file":"'"$F"'","hypothesis":"discover step failed before emitting structured output — see workflow logs"}'
199231
fi
200-
printf '%s' "$RESULT_JSON" > "mythos-out/${{ steps.slug.outputs.slug }}.json"
232+
printf '%s' "$RESULT_JSON" > "mythos-out/${SLUG}.json"
201233
202234
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
203-
if: always()
235+
if: always() && steps.slug.outputs.slug != ''
204236
with:
205237
name: mythos-result-${{ steps.slug.outputs.slug }}
206238
path: mythos-out/${{ steps.slug.outputs.slug }}.json

0 commit comments

Comments
 (0)