@@ -290,27 +290,48 @@ jobs:
290290 fi
291291 echo "Scan completed with exit code $EXIT_CODE"
292292
293+ - name : Resolve latest run directory
294+ id : run-dir
295+ run : |
296+ # Timestamped run directories — resolve the 'latest' symlink
297+ RUN_DIR="cli-test-results/latest"
298+ if [ -L "$RUN_DIR" ]; then
299+ RESOLVED="cli-test-results/$(readlink "$RUN_DIR")"
300+ echo "Run directory: $RESOLVED"
301+ echo "dir=$RESOLVED" >> "$GITHUB_OUTPUT"
302+ else
303+ echo "::error::No 'latest' symlink in cli-test-results/"
304+ ls -la cli-test-results/ || true
305+ exit 1
306+ fi
307+
293308 - name : Verify outputs
309+ env :
310+ RUN_DIR : ${{ steps.run-dir.outputs.dir }}
294311 run : |
295- for f in cli-test-results /argus-results.json cli-test-results /argus-results.sarif; do
312+ for f in "$RUN_DIR /argus-results.json" "$RUN_DIR /argus-results.sarif" ; do
296313 test -f "$f" || { echo "FAIL: $f not produced"; exit 1; }
297314 done
298315
299316 - name : Validate SARIF
317+ env :
318+ RUN_DIR : ${{ steps.run-dir.outputs.dir }}
300319 run : |
301320 python3 -c "
302- import json
303- data = json.load(open('cli-test-results/ argus-results.sarif'))
321+ import json, os
322+ data = json.load(open(os.path.join(os.environ['RUN_DIR'], ' argus-results.sarif') ))
304323 assert data.get('version') == '2.1.0', f'Bad SARIF version: {data.get(\"version\")}'
305324 assert 'runs' in data, 'Missing runs'
306325 print(f'SARIF valid: {len(data[\"runs\"])} run(s)')
307326 "
308327
309328 - name : Validate JSON results
329+ env :
330+ RUN_DIR : ${{ steps.run-dir.outputs.dir }}
310331 run : |
311332 python3 -c "
312- import json
313- data = json.load(open('cli-test-results/ argus-results.json'))
333+ import json, os
334+ data = json.load(open(os.path.join(os.environ['RUN_DIR'], ' argus-results.json') ))
314335 results = data.get('results', [])
315336 assert len(results) > 0, 'No scanner results'
316337 scanners = [r['scanner'] for r in results]
@@ -320,17 +341,20 @@ jobs:
320341 "
321342
322343 - name : Validate audit trail
344+ env :
345+ RUN_DIR : ${{ steps.run-dir.outputs.dir }}
323346 run : |
324347 echo "Checking audit artifacts..."
325- for f in cli-test-results /argus.log cli-test-results /argus-audit.json cli-test-results /argus-summary.md; do
348+ for f in "$RUN_DIR /argus.log" "$RUN_DIR /argus-audit.json" "$RUN_DIR /argus-summary.md" ; do
326349 test -f "$f" || { echo "FAIL: $f not produced"; exit 1; }
327350 echo " OK: $f ($(wc -c < "$f") bytes)"
328351 done
329352
330353 # Validate audit manifest structure
331354 python3 -c "
332- import json
333- m = json.load(open('cli-test-results/argus-audit.json'))
355+ import json, os, hashlib
356+ run_dir = os.environ['RUN_DIR']
357+ m = json.load(open(os.path.join(run_dir, 'argus-audit.json')))
334358 assert m.get('scan_id'), 'Missing scan_id'
335359 assert m.get('started_at'), 'Missing started_at'
336360 assert m.get('completed_at'), 'Missing completed_at'
@@ -345,20 +369,17 @@ jobs:
345369 print(f' Artifacts: {len(m[\"artifacts\"])} files')
346370
347371 # Verify SHA-256 hashes for static artifacts
348- # (argus.log and argus-audit.json are excluded — log is still
349- # active when manifest is written, manifest can't hash itself)
350- import hashlib
351372 for a in m['artifacts']:
352- full = f'cli-test-results/{a[\" path\"]}'
373+ full = os.path.join(run_dir, a[' path'])
353374 actual = hashlib.sha256(open(full, 'rb').read()).hexdigest()
354375 assert actual == a['sha256'], f'Hash mismatch for {a[\"path\"]}: expected {a[\"sha256\"][:16]}... got {actual[:16]}...'
355376 print(f' Artifact hashes: {len(m[\"artifacts\"])} verified')
356377 "
357378
358379 # Validate structured log is JSONL
359380 python3 -c "
360- import json
361- with open('cli-test-results/ argus.log') as f:
381+ import json, os
382+ with open(os.path.join(os.environ['RUN_DIR'], ' argus.log') ) as f:
362383 lines = [line for line in f if line.strip()]
363384 for i, line in enumerate(lines):
364385 entry = json.loads(line)
0 commit comments