feat(artifact): add direct log artifact upload to action runtime#396
Merged
marcusrbrown merged 1 commit intomainfrom Mar 28, 2026
Merged
feat(artifact): add direct log artifact upload to action runtime#396marcusrbrown merged 1 commit intomainfrom
marcusrbrown merged 1 commit intomainfrom
Conversation
Move OpenCode log artifact upload from workflow YAML steps into the action's TypeScript runtime. When OPENCODE_PROMPT_ARTIFACT is enabled, the action now uploads ~/.local/share/opencode/log as a GitHub artifact automatically — no separate upload-artifact step needed. - Add @actions/artifact service with DefaultArtifactClient wrapper - Upload in cleanup phase (primary) and post hook (fallback) - Track upload state via ARTIFACT_UPLOADED to prevent duplicates - Add getGitHubRunAttempt() with NaN/negative guard - Remove upload-artifact steps from fro-bot.yaml and ci.yaml - Add unit tests for upload service, env accessor, and post branching
e396018 to
1b6c248
Compare
fro-bot
approved these changes
Mar 28, 2026
Owner
fro-bot
left a comment
There was a problem hiding this comment.
Review Summary
This PR demonstrates excellent adherence to established codebase patterns. The implementation is well-structured with comprehensive test coverage.
Architecture & Design ✓
- Layer placement: New
services/artifact/module correctly positioned as Layer 1 (services layer) - Double-write pattern: Post-action fallback mirrors the existing cache save pattern (
STATE_KEYS.CACHE_SAVED→STATE_KEYS.ARTIFACT_UPLOADED) - Non-fatal error handling: Both upload paths gracefully degrade with warnings, never crashing the action
Code Quality ✓
- Logger injection: All functions properly inject logger
- Functional style: No classes, only pure functions
- ESM imports:
.jsextensions correctly used - Strict booleans: Explicit comparisons (
=== 'true',!== 'true') not implicit falsy - Guard conditions:
getGitHubRunAttempt()usesNumber.isFinite()and guards against zero/negative values
Test Coverage ✓
6 new tests in upload.test.ts + 4 new tests in post.test.ts + 6 new tests in env.test.ts:
- Missing directory handling
- Empty directory handling
- Upload success/failure paths
- Custom options passthrough
- Directory entry filtering (files vs directories)
- State key verification
Implementation Details ✓
upload.ts: Clean implementation with graceful handling of missing/empty directoriescleanup.ts: Correctly uploads after cache save whenOPENCODE_PROMPT_ARTIFACTis enabledpost.ts: Fallback upload via state check mirrors cache save patterngetGitHubRunAttempt(): Returns1for invalid/missing/zero/negative values (correct default)
Bundling ✓
@actions/artifact@6.2.1 correctly bundled via existing noExternal rule for @actions/* packages (line 172 in tsdown.config.ts).
Verification ✓
- 1085 tests pass
- Type check clean
- Lint clean (34 warnings are pre-existing, none in new code)
- Dist in sync
No blocking issues found. The implementation is production-ready.
Run Summary
| Field | Value |
|---|---|
| Event | pull_request |
| Repository | fro-bot/agent |
| Run ID | 23692874135 |
| Cache | hit |
| Session | ses_2ca067d11ffe5emqJuH27wRBgb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
actions/upload-artifact) into the action's TypeScript runtimeOPENCODE_PROMPT_ARTIFACTis enabled, the action automatically uploads~/.local/share/opencode/logas a GitHub artifact — consumers no longer need a separateupload-artifactworkflow stepopencode-logs-{runId}-{runAttempt}Changes
New:
src/services/artifact/(Layer 1)upload.ts—uploadLogArtifact()wrapping@actions/artifactDefaultArtifactClient. Collects files viafs.readdir({recursive: true}), uploads with 7-day retention and max compression. Non-fatal on failure.index.ts— Re-exportsModified: Harness (Layer 3)
cleanup.ts— Uploads artifacts after cache save whenOPENCODE_PROMPT_ARTIFACTis set; writesARTIFACT_UPLOADEDstate on successpost.ts— Fallback artifact upload in post-action hook if cleanup didn't complete it (mirrors the cache save double-write pattern)state-keys.ts— AddedARTIFACT_UPLOADEDstate key for main↔post handoffModified: Shared (Layer 0)
env.ts— AddedgetGitHubRunAttempt()withNumber.isFinite()guard against NaN/negative valuesModified: Workflows
fro-bot.yaml/ci.yaml— Removedactions/upload-artifactsteps (replaced by in-action upload)New dependency
@actions/artifact@6.2.1— bundled by tsdown via existing@actions/*ruleHow it works
execution.tswrites prompt artifact to log dir whenOPENCODE_PROMPT_ARTIFACT=true(existing, unchanged)finallyblock) uploads the log directory as a GitHub artifactARTIFACT_UPLOADEDstate — uploads only if cleanup didn't complete itTest coverage
upload.test.ts(6 tests) — dir missing, empty dir, upload success/failure, custom options, directory entry filteringenv.test.ts(6 new) —getGitHubRunAttemptwith valid, missing, empty, non-numeric, zero, negative valuespost.test.ts(4 new) — artifact upload enabled+not-yet-uploaded, already-uploaded skip, disabled skip, non-fatal failurestate-keys.test.ts(2 updated) — new key + count1085 tests pass, 0 lint errors, type-check clean, dist in sync.