Skip to content

feat: add artifact actions#2159

Merged
yohamta0 merged 2 commits into
mainfrom
feature/artifact-actions
May 16, 2026
Merged

feat: add artifact actions#2159
yohamta0 merged 2 commits into
mainfrom
feature/artifact-actions

Conversation

@yohamta0

@yohamta0 yohamta0 commented May 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add DAG-run artifact actions so workflows can write, read, and list run artifacts without shelling out to DAG_RUN_ARTIFACTS_DIR.

Changes

  • Add artifact.write, artifact.read, and artifact.list action normalization and executor registration.
  • Add a built-in artifact executor with relative path enforcement, symlink escape checks, optional JSON read output, glob filtering, and overwrite controls.
  • Auto-enable DAG artifacts when artifact actions are used.
  • Wire artifact action config into DAG JSON schema validation.
  • Update agent authoring guidance to prefer explicit artifact actions for run outputs.

Validation

  • go test ./internal/agent ./internal/cmn/schema ./internal/core/spec ./internal/runtime/builtin ./internal/runtime/builtin/artifact

Checklist

  • Artifact write/read/list behavior is covered by tests.
  • DAG JSON schema accepts artifact actions and config.
  • Local focused validation completed.

Summary by CodeRabbit

  • New Features

    • Added built-in artifact actions: artifact.write, artifact.read, and artifact.list for DAG-run artifact management (write/read/list, patterns, recursion, max_bytes, atomic writes).
  • Behavior

    • DAGs using artifact actions will enable artifact storage automatically; explicit configuration is validated to prevent contradictory settings.
  • Documentation

    • Updated guidance to prefer native artifact actions over shell commands for DAG-run artifacts.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b590d6b-c40b-490e-8dc1-790e5b89a25b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds built-in DAG actions artifact.write, artifact.read, artifact.list; updates prompts and tests to prefer them; extends DAG schema and spec normalization; implements a secure artifact executor (write/read/list) with config validation and tests; and wires the executor into the runtime.

Changes

Artifact Action Feature

Layer / File(s) Summary
Artifact action documentation and schema
internal/agent/system_prompt.go, internal/agent/system_prompt.txt, internal/agent/system_prompt_test.go, internal/cmn/schema/dag.schema.json, internal/cmn/schema/dag_schema_test.go
System prompts now recommend artifact.write/artifact.read/artifact.list over shell commands for DAG-run artifacts; JSON schema adds artifactActionConfig and includes artifact action names; schema tests validate artifact steps.
Artifact action normalization and step spec wiring
internal/core/spec/step_types.go, internal/core/spec/step_v2.go, internal/core/spec/step_v2_test.go, internal/core/spec/step_test.go, internal/core/spec/dag.go, internal/core/spec/dag_test.go
Registers artifact executor type and artifact.* action normalizers; TestMain adds artifact capability; adds reflective DAG scanning to auto-enable artifacts when artifact actions appear and validates artifacts.enabled when actions are used.
Artifact executor core operations
internal/runtime/builtin/artifact/artifact.go
Implements artifact executor with write/read/list operations confined to the artifacts directory, strict path sanitization, symlink-aware containment checks, optional atomic writes, pattern filtering, deterministic listing, and JSON outputs.
Artifact executor configuration
internal/runtime/builtin/artifact/config.go
Parses and validates config for artifact operations (required fields per op, format constraints, glob pattern validation, mode parsing), defines default behavior (atomic=true), and registers a config JSON schema.
Artifact executor testing
internal/runtime/builtin/artifact/artifact_test.go
Tests success paths (write/read/list), escape prevention (traversal, absolute, Windows paths, symlinks), non-atomic overwrite rejection, missing artifact-dir constructor failure, and includes test helpers.
Runtime executor registration
internal/runtime/builtin/builtin.go
Blank import ensures the artifact builtin package is initialized and the executor is registered at runtime.

Sequence Diagram

sequenceDiagram
  participant StepConfig as Step Config
  participant Executor as Artifact Executor
  participant RunWrite as runWrite
  participant RunRead as runRead
  participant RunList as runList
  participant FS as Filesystem
  StepConfig->>Executor: Run(ctx) with command "write|read|list" + config
  Executor->>Executor: parse operation from first command
  alt operation == write
    Executor->>RunWrite: runWrite(config)
    RunWrite->>FS: sanitize path, prepare root, create parents, write (atomic if enabled)
    RunWrite->>Executor: JSON result (operation,path,bytes,created)
  else operation == read
    Executor->>RunRead: runRead(config)
    RunRead->>FS: resolve path, read bytes (respect max_bytes)
    RunRead->>Executor: raw bytes or JSON (content+metadata)
  else operation == list
    Executor->>RunList: runList(config)
    RunList->>FS: walk/list entries (recursive?, pattern), collect metadata
    RunList->>Executor: JSON listing (entries,count)
  end
  Executor->>StepConfig: set exit code and output
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • dagucloud/dagu#2122: Establishes the v2 action/with step schema framework that this PR extends by registering the new artifact.* actions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add artifact actions' clearly and concisely summarizes the main change—addition of new artifact-related actions—matching the substantial changes across the codebase.
Description check ✅ Passed The description provides a clear summary, detailed list of changes, validation steps, and completed checklist items, largely aligning with the template structure despite minor formatting variations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/artifact-actions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/core/spec/dag.go (1)

890-907: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast when artifact.* is combined with artifacts.enabled: false.

This now auto-detects artifact actions, but an explicit artifacts.enabled: false still wins and the DAG builds successfully. That pushes a contradictory config into runtime, where the executor fails because DAG_RUN_ARTIFACTS_DIR is never populated. Please reject that combination during spec build instead of deferring it to execution.

Suggested guard
 func buildArtifacts(_ BuildContext, d *dag) (*core.ArtifactsConfig, error) {
 	autoEnable := dagReferencesRunArtifactsDir(d) || dagUsesBuiltinArtifactAction(d)
+
+	if autoEnable && d.Artifacts != nil && d.Artifacts.Enabled != nil && !*d.Artifacts.Enabled {
+		return nil, core.NewValidationError(
+			"artifacts.enabled",
+			*d.Artifacts.Enabled,
+			fmt.Errorf("artifact actions require artifacts.enabled to be true"),
+		)
+	}
 
 	if d.Artifacts == nil {
 		if autoEnable {
 			return &core.ArtifactsConfig{Enabled: true}, nil
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/core/spec/dag.go` around lines 890 - 907, The buildArtifacts
function currently auto-enables artifacts when dagReferencesRunArtifactsDir(d)
or dagUsesBuiltinArtifactAction(d) is true but silently accepts an explicit
artifacts.enabled: false; update buildArtifacts to detect the conflict and
return an error when autoEnable is true AND d.Artifacts != nil AND
d.Artifacts.Enabled != nil AND *d.Artifacts.Enabled == false, referencing
buildArtifacts, dagReferencesRunArtifactsDir, dagUsesBuiltinArtifactAction and
d.Artifacts.Enabled; the error should reject the spec build rather than
producing a runtime-misconfigured core.ArtifactsConfig.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/runtime/builtin/artifact/artifact.go`:
- Around line 218-250: The code currently uses os.WriteFile(target.abs, ...)
when e.cfg.Overwrite && !e.cfg.Atomic, which can follow a swapped-in symlink
after the earlier checks; change the write path so overwrite operations never
use os.WriteFile directly: when e.cfg.Overwrite is true, always write via the
atomic path (fileutil.WriteFileAtomic(target.abs, data, mode)) or alternatively
return an error rejecting the unsupported config combination (e.g. check
e.cfg.Overwrite && !e.cfg.Atomic and either call fileutil.WriteFileAtomic or
return fmt.Errorf(...)). Update the logic around ensureWritableTargetInsideRoot,
the overwrite branch, and the final write handling to route overwrite writes
through fileutil.WriteFileAtomic (or fail) instead of using os.WriteFile with
target.abs.

---

Outside diff comments:
In `@internal/core/spec/dag.go`:
- Around line 890-907: The buildArtifacts function currently auto-enables
artifacts when dagReferencesRunArtifactsDir(d) or
dagUsesBuiltinArtifactAction(d) is true but silently accepts an explicit
artifacts.enabled: false; update buildArtifacts to detect the conflict and
return an error when autoEnable is true AND d.Artifacts != nil AND
d.Artifacts.Enabled != nil AND *d.Artifacts.Enabled == false, referencing
buildArtifacts, dagReferencesRunArtifactsDir, dagUsesBuiltinArtifactAction and
d.Artifacts.Enabled; the error should reject the spec build rather than
producing a runtime-misconfigured core.ArtifactsConfig.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 190e3ba9-ab1c-4ed8-88c6-1d34ad24882e

📥 Commits

Reviewing files that changed from the base of the PR and between 7821c7d and f5565e8.

📒 Files selected for processing (15)
  • internal/agent/system_prompt.go
  • internal/agent/system_prompt.txt
  • internal/agent/system_prompt_test.go
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/core/spec/dag.go
  • internal/core/spec/dag_test.go
  • internal/core/spec/step_test.go
  • internal/core/spec/step_types.go
  • internal/core/spec/step_v2.go
  • internal/core/spec/step_v2_test.go
  • internal/runtime/builtin/artifact/artifact.go
  • internal/runtime/builtin/artifact/artifact_test.go
  • internal/runtime/builtin/artifact/config.go
  • internal/runtime/builtin/builtin.go

Comment thread internal/runtime/builtin/artifact/artifact.go
@yohamta0 yohamta0 force-pushed the feature/artifact-actions branch from f5565e8 to d960e37 Compare May 16, 2026 10:57
@yohamta0

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yohamta0 yohamta0 force-pushed the feature/artifact-actions branch 2 times, most recently from a8f0c17 to a8944d1 Compare May 16, 2026 11:35
@yohamta0 yohamta0 force-pushed the feature/artifact-actions branch from a355f8c to 54c6308 Compare May 16, 2026 12:40
@yohamta0 yohamta0 merged commit b5fdc1b into main May 16, 2026
10 checks passed
@yohamta0 yohamta0 deleted the feature/artifact-actions branch May 16, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant