Skip to content

fix: validate sftp executor schema#2022

Merged
yottahmd merged 21 commits intomainfrom
fix/sftp-executor-schema
Apr 22, 2026
Merged

fix: validate sftp executor schema#2022
yottahmd merged 21 commits intomainfrom
fix/sftp-executor-schema

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented Apr 21, 2026

Summary

  • add SFTP executor config schema coverage to the shared DAG schema
  • wire type: sftp to SFTP-specific with and legacy config validation
  • add regression coverage for schema validation and spec builder acceptance of type: sftp

Closes #1976

Testing

  • go test ./internal/cmn/schema ./internal/core/spec
  • make test TEST_TARGET='./internal/cmn/schema ./internal/core/spec'

Summary by CodeRabbit

  • New Features

    • SFTP executor for file transfers (upload/download, default upload) with auth, host‑key checking, timeout and optional bastion; new public SFTP config; legacy alias accepted but deprecated.
  • Changes

    • Queue API now reports certain lease‑owned NotStarted/Queued runs as Running.
    • SSH/SFTP port fields accept numeric or string values.
    • More robust temp/proc file creation and explicit attempt‑close handling.
  • Bug Fixes

    • Surface attempt close failures and ensure status is closed before publishing to queue.
  • Tests

    • Expanded unit, integration, and e2e tests covering SFTP validation, enqueue behavior, queue counts, release‑gating, and file‑signal coordination.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

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: c3cf3ad9-0499-4cf1-8b87-d9eceb17682b

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

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds SFTP executor JSON Schema and tests; accepts numeric SSH/SFTP ports; makes enqueueDAGRun explicitly close attempt handles and join close/enqueue errors; replaces timing-based test waits with filesystem signaling; and includes related unit/integration/e2e test updates and helpers.

Changes

Cohort / File(s) Summary
SFTP Schema
internal/cmn/schema/dag.schema.json
Add #/definitions/sftpExecutorConfig; conditional validation requiring step.with (and deprecated step.config) when type: "sftp", and requiring executorObject.config when executorObject.type: "sftp".
Schema tests
internal/cmn/schema/dag_schema_test.go
Add tests for sftpExecutorConfig (table-driven: legacy config alias, numeric/string port, direction values, invalid/empty/unknown fields) and helpers to resolve schema definitions & extract first-step effective config.
Executor mapping test
internal/core/spec/step_test.go
Add SFTPTypeAndWith case asserting buildStepExecutor maps type: "sftp" and copies with into executor config.
Enqueue flow & tests
internal/cmd/enqueue.go, internal/cmd/enqueue_internal_test.go
Stop deferring att.Close; explicitly close after writing status, best-effort close on write failure, join close+enqueue errors when both occur; add tests/mocks ensuring Close happens before enqueue and enqueue proceeds when Close errors.
Queue reporting & tests
internal/service/frontend/api/v1/queues.go, internal/service/frontend/api/v1/queues_internal_test.go
Map persisted NotStarted/Queued to Running for fresh leases in runningSummaryFromLease; add test asserting claimed attempts reported as running and refactor helper to parametrize persisted status.
E2E gating & fixture
ui/e2e/distributed-stack.spec.ts, ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
Introduce host-side release gate (release file + FIFO); DAG step blocks on FIFO; reorder test assertions to occur after release; add release helper and conditional cleanup on failure.
Integration test helpers & tests
internal/intg/handler_test.go, internal/intg/platform_helpers_test.go
Add writeFileCommand and waitForTestFile helpers; tests now write/read filesystem markers and use bounded waits instead of polling DAG status.
SSH runtime schema & tests
internal/runtime/builtin/ssh/config.go, internal/runtime/builtin/ssh/ssh_test.go
Introduce portValueSchema to accept numeric or string ports for port and bastion.port; add test for numeric bastion port handling.
Agent tests (wait helpers)
internal/runtime/agent/agent_test.go
Add waitForTestFile and waitForCancel helpers; use filesystem markers and bounded waits in agent tests; standardize cancellation handling.
Fileproc temp creation
internal/persis/fileproc/handle.go, internal/persis/fileproc/handle_test.go
Add createProcTempFile with a retry to handle races creating temp files/parent dir; add test ensuring parent dir is created.
Distributed heartbeat test tweak
internal/intg/distr/zombie_recovery_test.go
Heartbeat refresh loop now re-checks run status and lease freshness together and updates outer variables only when checks pass.
Sock server response handling
internal/cmn/sock/server.go
httpResponseWriter.Write now sets ContentLength, propagates response.Write errors, and returns bytes written on success.
Various tests adjusted for file signaling
multiple internal/* test files
Replace some DAG-status polling and sleeps with filesystem marker writes/reads and bounded waits; add helper functions used across tests.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Caller
    participant Enqueue as enqueueDAGRun
    participant Attempt as AttemptHandle
    participant Queue as QueueStore

    Caller->>Enqueue: enqueueDAGRun(ctx, run)
    Enqueue->>Attempt: Write(status=Queued)
    Attempt-->>Enqueue: write OK / writeErr
    Enqueue->>Attempt: Close()
    Attempt-->>Enqueue: closeErr (ok | error)
    Enqueue->>Queue: Enqueue(dag-run)
    alt Enqueue fails
        Queue-->>Enqueue: enqueueErr
        Enqueue-->>Caller: return errors.Join(closeErr?, enqueueErr)
    else Enqueue succeeds
        Queue-->>Enqueue: ok
        Enqueue-->>Caller: return nil (log closeErr if present)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes multiple out-of-scope changes unrelated to SFTP executor schema validation, including handler/agent test refactoring, queue status handling, distributed worker synchronization, and proc file race condition fixes. Separate out-of-scope changes (test refactoring, queue status handling, proc file handling, worker synchronization) into distinct PRs focused on their specific concerns.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: validate sftp executor schema' clearly and concisely describes the main change—adding SFTP executor schema validation.
Linked Issues check ✅ Passed The PR fully addresses issue #1976 by adding SFTP executor schema validation to the DAG schema, wiring type:sftp to proper validation rules, and adding comprehensive regression tests.

✏️ 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 fix/sftp-executor-schema

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmn/schema/dag_schema_test.go`:
- Around line 672-695: The two negative tests "RejectInvalidDirection" and
"RejectUnknownConfigField" are missing the otherwise-valid SFTP connection
fields so failures might be due to missing required fields instead of the
intended rule; update the YAML specs used by those cases to include the same
valid SFTP baseline fields used in the passing SFTP test (e.g.,
host/port/auth/any required keys) and then only change the specific value under
test (set direction: sync for RejectInvalidDirection and add unknown_field for
RejectUnknownConfigField) so validation fails solely on the enum/unknown-field
rule.

In `@internal/cmn/schema/dag.schema.json`:
- Around line 2551-2554: Schema allows port as integer and permits empty
source/destination, but runtime SFTP config (NewSFTPExecutor and the SFTP config
struct fields) expects port as string and non-empty source/destination; to fix,
make schema constraints match runtime: change port and bastion.port to only
accept strings (or update NewSFTPExecutor/config types to accept integers if you
prefer), and add "minLength":1 (or equivalent non-empty string constraint) for
SFTP "source" and "destination" to disallow empty paths; update all occurrences
noted (port blocks and the SFTP source/destination blocks around the referenced
schema locations) so schema and runtime validation are consistent.
🪄 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: bfcbb0e2-ef1a-4c09-9cdd-31013419b876

📥 Commits

Reviewing files that changed from the base of the PR and between f2cc809 and 4fbae91.

📒 Files selected for processing (3)
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/core/spec/step_test.go

Comment thread internal/cmn/schema/dag_schema_test.go
Comment thread internal/cmn/schema/dag.schema.json
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmn/schema/dag.schema.json`:
- Around line 2492-2495: The schema for sshExecutorConfig.port currently
restricts the port to a string, causing a mismatch with the runtime PortValue
parser in port.go (which accepts integers and whole-number floats) and the tests
in port_test.go; update the "port" schema definition in dag.schema.json to
accept both string and numeric values (e.g., change "type": "string" to allow
"number" as well) and keep the default/description consistent so values like 22
(unquoted) validate against the JSON schema while still matching PortValue
parsing at runtime.
🪄 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: 5da63c5d-902a-45c5-992e-de89fb00f838

📥 Commits

Reviewing files that changed from the base of the PR and between 4fbae91 and 8e60685.

📒 Files selected for processing (2)
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/cmn/schema/dag_schema_test.go

Comment thread internal/cmn/schema/dag.schema.json
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
internal/service/frontend/api/v1/queues_internal_test.go (1)

242-290: Optional: also cover core.NotStarted in the new helper's test matrix.

runningSummaryFromLease now branches on both core.NotStarted and core.Queued, but only the core.Queued path is exercised. Consider a sibling test (or table-driven variant) asserting the same StatusRunning outcome when the persisted status is core.NotStarted, since that’s an equally realistic race window between lease claim and first status write.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/service/frontend/api/v1/queues_internal_test.go` around lines 242 -
290, Add a test case that exercises the core.NotStarted branch of
runningSummaryFromLease: reuse the helper createDistributedQueueRunWithStatus to
create a lease whose persisted run status is core.NotStarted (instead of
core.Queued) and assert the resulting running summary yields StatusRunning (same
expectation as the core.Queued case). Locate the existing test(s) that call
createDistributedQueueRunWithStatus and either add a sibling test or expand the
table-driven matrix to include an entry with status core.NotStarted and verify
the same StatusRunning outcome; ensure you reference runningSummaryFromLease,
createDistributedQueueRunWithStatus, core.NotStarted, and StatusRunning in the
new assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmd/enqueue.go`:
- Around line 139-150: The code can leave a persisted queued attempt on disk if
att.Close(ctx.Context) fails before ctx.QueueStore.Enqueue runs; to fix, change
the Close error handling in the block around
att.Write/att.Close/ctx.QueueStore.Enqueue so that a Close error does not abort
enqueue: if att.Close returns an error, log or record the Close error (e.g. with
process logger or ctx.Logger) but continue to call
ctx.QueueStore.Enqueue(ctx.Context, dag.ProcGroup(), exec.QueuePriorityLow,
dagRun); because Attempt.Close is idempotent (see Attempt.Close implementation),
this avoids orphaned on-disk attempts; alternatively, if you prefer explicit
cleanup, call att.Close/att.Cleanup (or the appropriate cleanup/remove helper)
on failure before returning — update the error handling around att.Close and the
subsequent ctx.QueueStore.Enqueue to implement one of these strategies and
surface both errors appropriately (e.g., enqueue error should still be returned,
but Close errors should not prevent enqueue).

In `@internal/cmn/schema/dag.schema.json`:
- Around line 2594-2620: The JSON schema for sftpExecutorConfig is inconsistent:
update the "bastion.port" property to accept both string and integer (use oneOf:
[ { "type": "string" }, { "type": "integer" } ]) to match the top-level "port"
and sshExecutorConfig.port; also reconcile the runtime sftpConfigSchema in
internal/runtime/builtin/ssh/config.go (currently treats bastion.port as string)
by relaxing its type to accept numeric ports or convert the top-level port to
string-only—ensure both the JSON schema property "bastion.port" and the runtime
sftpConfigSchema agree on the same type handling.

In `@ui/e2e/distributed-stack.spec.ts`:
- Around line 46-55: The async helper releaseRuns is missing an explicit return
type; change its declaration to include Promise<void> (e.g., const releaseRuns =
async (): Promise<void> => { ... }) so it matches the file's TypeScript style
and other helpers like waitForWorkerState, and ensure the function body still
returns no value (only performs side effects on releaseFile/releaseGate).

In `@ui/e2e/fixtures/dags/e2e-distributed-queue.yaml`:
- Around line 8-13: The script can continue if reading the release FIFO fails;
update the snippet around release_file and release_gate to fail fast by enabling
shell errexit (add set -e at the top of the script) and explicitly validate the
FIFO before reading it (check that release_gate is a named pipe using [ -p
"$release_gate" ] and exit with an error if not present), then perform the
blocking read (cat "$release_gate") so the step cannot silently succeed when the
FIFO is missing or unreadable.

---

Nitpick comments:
In `@internal/service/frontend/api/v1/queues_internal_test.go`:
- Around line 242-290: Add a test case that exercises the core.NotStarted branch
of runningSummaryFromLease: reuse the helper createDistributedQueueRunWithStatus
to create a lease whose persisted run status is core.NotStarted (instead of
core.Queued) and assert the resulting running summary yields StatusRunning (same
expectation as the core.Queued case). Locate the existing test(s) that call
createDistributedQueueRunWithStatus and either add a sibling test or expand the
table-driven matrix to include an entry with status core.NotStarted and verify
the same StatusRunning outcome; ensure you reference runningSummaryFromLease,
createDistributedQueueRunWithStatus, core.NotStarted, and StatusRunning in the
new assertion.
🪄 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: 76865353-f792-4503-84fd-105ecaf10b35

📥 Commits

Reviewing files that changed from the base of the PR and between 8e60685 and 2467854.

📒 Files selected for processing (8)
  • internal/cmd/enqueue.go
  • internal/cmd/enqueue_internal_test.go
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/service/frontend/api/v1/queues.go
  • internal/service/frontend/api/v1/queues_internal_test.go
  • ui/e2e/distributed-stack.spec.ts
  • ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/cmn/schema/dag_schema_test.go

Comment thread internal/cmd/enqueue.go
Comment thread internal/cmn/schema/dag.schema.json
Comment thread ui/e2e/distributed-stack.spec.ts Outdated
Comment thread ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/cmd/enqueue_internal_test.go (1)

210-215: Consider asserting the queued status exists before publish.

The fake currently checks only that Close happened before Enqueue. Adding a status check here would also guard against a future reorder that publishes before the queued status is written.

Proposed stricter queue observer
 func (s *enqueueObservingQueueStore) Enqueue(context.Context, string, exec.QueuePriority, exec.DAGRunRef) error {
 	if !s.attempt.closed {
 		return errors.New("status attempt was not closed before queue enqueue")
 	}
+	if s.attempt.status == nil || s.attempt.status.Status != core.Queued {
+		return errors.New("queued status was not written before queue enqueue")
+	}
 	s.enqueued = true
 	return nil
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/enqueue_internal_test.go` around lines 210 - 215, The Enqueue
implementation in enqueueObservingQueueStore only verifies attempt.closed;
update it to also assert the attempt has its "queued" status set before
publishing: in Enqueue (enqueueObservingQueueStore.Enqueue) check the attempt's
status field (e.g., s.attempt.status == exec.RunStatusQueued or a boolean like
s.attempt.queued) and return an error if the queued status is missing, then set
s.enqueued = true and return nil; this ensures the queued status exists prior to
marking enqueued.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/cmd/enqueue_internal_test.go`:
- Around line 210-215: The Enqueue implementation in enqueueObservingQueueStore
only verifies attempt.closed; update it to also assert the attempt has its
"queued" status set before publishing: in Enqueue
(enqueueObservingQueueStore.Enqueue) check the attempt's status field (e.g.,
s.attempt.status == exec.RunStatusQueued or a boolean like s.attempt.queued) and
return an error if the queued status is missing, then set s.enqueued = true and
return nil; this ensures the queued status exists prior to marking enqueued.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 32b92003-7f7c-4b4d-81b3-9da8f0e80d52

📥 Commits

Reviewing files that changed from the base of the PR and between 23fe5ef and ce5bc7f.

📒 Files selected for processing (9)
  • internal/cmd/enqueue.go
  • internal/cmd/enqueue_internal_test.go
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/runtime/builtin/ssh/config.go
  • internal/runtime/builtin/ssh/ssh_test.go
  • internal/service/frontend/api/v1/queues_internal_test.go
  • ui/e2e/distributed-stack.spec.ts
  • ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
🚧 Files skipped from review as they are similar to previous changes (5)
  • ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
  • internal/cmd/enqueue.go
  • internal/cmn/schema/dag_schema_test.go
  • ui/e2e/distributed-stack.spec.ts
  • internal/cmn/schema/dag.schema.json

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
internal/cmn/schema/dag_schema_test.go (1)

636-769: LGTM!

Good coverage for the SFTP executor schema: canonical with, legacy config alias, numeric/string port, optional bastion, and the negative cases (invalid direction, empty source, unknown field) now retain a valid SFTP baseline so failures are attributable to the rule under test (addressing prior feedback).

One optional nit: the wantErr: "steps" substring is quite permissive — any validation failure rooted at steps passes the assertion. If you want tighter guarantees, consider asserting on a more specific substring (e.g., "direction", "source", or "unknown_field") for each negative case. Not blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmn/schema/dag_schema_test.go` around lines 636 - 769, The tests in
TestDAGSchemaSFTPExecutor use a permissive error assertion (tt.wantErr =
"steps") which can hide whether the validation failed for the intended field;
update the negative-case test table entries (e.g., "RejectInvalidDirection",
"RejectEmptySource", "RejectUnknownConfigField") to set wantErr to a more
specific substring matching the expected validation message (for example
"direction", "source", "unknown_field") and ensure the test loop still asserts
require.Contains(err.Error(), tt.wantErr) so failures verify the precise
validation error in TestDAGSchemaSFTPExecutor.
internal/runtime/agent/agent_test.go (1)

630-657: Optional: extract the duplicated cancellation-wait block.

The done := make(chan struct{}) + goroutine + select { case <-done: case <-time.After(30*time.Second): t.Fatal(...) } pattern is now repeated verbatim across HTTPValid, HTTPInvalidRequest, and HTTPHandleCancel (Lines 630-634/653-657, 677-681/696-700, 720-724/738-742). Consider a small helper, e.g. waitForCancel(t, done, 30*time.Second), to reduce noise. Not blocking.

♻️ Sketch
func waitForCancel(t *testing.T, done <-chan struct{}, timeout time.Duration) {
	t.Helper()
	select {
	case <-done:
	case <-time.After(timeout):
		t.Fatal("timed out waiting for DAG cancellation")
	}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/agent/agent_test.go` around lines 630 - 657, Extract the
repeated cancellation-wait pattern into a helper (e.g., waitForCancel) and
replace the duplicated blocks in HTTPValid, HTTPInvalidRequest, and
HTTPHandleCancel: locate the done := make(chan struct{}) + goroutine that calls
dagAgent.RunCancel(t) and the select that waits for done or times out after 30s,
then implement waitForCancel(t, done, 30*time.Second) (make it t.Helper()) and
call it after dagAgent.Abort() in each test to remove the duplicated code and
keep behavior identical.
internal/cmd/enqueue_internal_test.go (2)

44-70: Consider asserting attempt.closed to strengthen the close-failure test.

TestEnqueueDAGRunPublishesQueueWhenCloseFails relies on enqueueObservingQueueStore.Enqueue to indirectly verify closure ordering, but doesn't explicitly assert that Close was invoked and its error was tolerated. Adding assert.True(t, attempt.closed) would make the intent explicit and guard against a future regression where Close is skipped entirely (in which case closed stays false but Enqueue would also fail — still caught, but the failure mode would be less clear).

♻️ Suggested addition
 	require.NoError(t, enqueueDAGRun(ctx, dag, "run-1", core.TriggerTypeManual, ""))
 	assert.True(t, queueStore.enqueued)
+	assert.True(t, attempt.closed, "attempt should be closed even when Close returns an error")
 	require.NotNil(t, attempt.status)
 	assert.Equal(t, core.Queued, attempt.status.Status)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/enqueue_internal_test.go` around lines 44 - 70, Add an explicit
assertion that the tracking attempt's Close was called by checking
attempt.closed in TestEnqueueDAGRunPublishesQueueWhenCloseFails: after invoking
enqueueDAGRun (and before/or alongside the existing asserts that check
queueStore.enqueued and attempt.status), add assert.True(t, attempt.closed) to
ensure enqueueTrackingAttempt.Close on the enqueueTrackingAttempt struct was
invoked and its error was tolerated; this makes the test's intent explicit and
ties to enqueueObservingQueueStore.Enqueue and enqueueDAGRun behavior.

19-70: Duplicated test setup — extract a small helper.

The two tests are nearly identical except for closeErr and one extra assertion. A small table-driven form or a helper that builds (attempt, runStore, queueStore, ctx, dag) would reduce duplication and make future additions (e.g., Enqueue-failure cases) cheaper.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/enqueue_internal_test.go` around lines 19 - 70, Both tests
TestEnqueueDAGRunClosesStatusBeforeQueuePublish and
TestEnqueueDAGRunPublishesQueueWhenCloseFails share nearly identical setup;
extract a small helper (or table-driven setup) that builds and returns the
common fixtures — an *enqueueTrackingAttempt*, *enqueueTrackingDAGRunStore*,
*enqueueObservingQueueStore*, the *Context* (with DAGRunStore/QueueStore) and
the *dag* from th.DAG — and then call that helper from each test passing the
differing parameter (closeErr or expected assertions). Update tests to call the
helper (or iterate table cases) and keep only the unique assertions (e.g.,
closeErr presence and queue-enqueued checks) while reusing the helper-created
attempt, runStore, queueStore, ctx, and dag before invoking enqueueDAGRun.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/e2e/distributed-stack.spec.ts`:
- Around line 188-196: The finally block can overwrite the original test error
if releaseRuns() throws, so wrap the fallback call to releaseRuns() in a
try/catch (when !released && releaseGateReady) to absorb any errors from the
fallback release and optionally log them, ensuring the original exception
remains thrown and that the subsequent cleanup calls (fs.rm for releaseFile and
releaseGate) still execute; update the finally to call releaseRuns() inside try
{ await releaseRuns() } catch (err) { /* log or ignore */ } while leaving the
rest of the finally (the checks on completed and the fs.rm calls) unchanged.

---

Nitpick comments:
In `@internal/cmd/enqueue_internal_test.go`:
- Around line 44-70: Add an explicit assertion that the tracking attempt's Close
was called by checking attempt.closed in
TestEnqueueDAGRunPublishesQueueWhenCloseFails: after invoking enqueueDAGRun (and
before/or alongside the existing asserts that check queueStore.enqueued and
attempt.status), add assert.True(t, attempt.closed) to ensure
enqueueTrackingAttempt.Close on the enqueueTrackingAttempt struct was invoked
and its error was tolerated; this makes the test's intent explicit and ties to
enqueueObservingQueueStore.Enqueue and enqueueDAGRun behavior.
- Around line 19-70: Both tests TestEnqueueDAGRunClosesStatusBeforeQueuePublish
and TestEnqueueDAGRunPublishesQueueWhenCloseFails share nearly identical setup;
extract a small helper (or table-driven setup) that builds and returns the
common fixtures — an *enqueueTrackingAttempt*, *enqueueTrackingDAGRunStore*,
*enqueueObservingQueueStore*, the *Context* (with DAGRunStore/QueueStore) and
the *dag* from th.DAG — and then call that helper from each test passing the
differing parameter (closeErr or expected assertions). Update tests to call the
helper (or iterate table cases) and keep only the unique assertions (e.g.,
closeErr presence and queue-enqueued checks) while reusing the helper-created
attempt, runStore, queueStore, ctx, and dag before invoking enqueueDAGRun.

In `@internal/cmn/schema/dag_schema_test.go`:
- Around line 636-769: The tests in TestDAGSchemaSFTPExecutor use a permissive
error assertion (tt.wantErr = "steps") which can hide whether the validation
failed for the intended field; update the negative-case test table entries
(e.g., "RejectInvalidDirection", "RejectEmptySource",
"RejectUnknownConfigField") to set wantErr to a more specific substring matching
the expected validation message (for example "direction", "source",
"unknown_field") and ensure the test loop still asserts
require.Contains(err.Error(), tt.wantErr) so failures verify the precise
validation error in TestDAGSchemaSFTPExecutor.

In `@internal/runtime/agent/agent_test.go`:
- Around line 630-657: Extract the repeated cancellation-wait pattern into a
helper (e.g., waitForCancel) and replace the duplicated blocks in HTTPValid,
HTTPInvalidRequest, and HTTPHandleCancel: locate the done := make(chan struct{})
+ goroutine that calls dagAgent.RunCancel(t) and the select that waits for done
or times out after 30s, then implement waitForCancel(t, done, 30*time.Second)
(make it t.Helper()) and call it after dagAgent.Abort() in each test to remove
the duplicated code and keep behavior identical.
🪄 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: d310e64f-c784-436f-919d-5e238c17dc73

📥 Commits

Reviewing files that changed from the base of the PR and between 23fe5ef and fc740ea.

📒 Files selected for processing (10)
  • internal/cmd/enqueue.go
  • internal/cmd/enqueue_internal_test.go
  • internal/cmn/schema/dag.schema.json
  • internal/cmn/schema/dag_schema_test.go
  • internal/runtime/agent/agent_test.go
  • internal/runtime/builtin/ssh/config.go
  • internal/runtime/builtin/ssh/ssh_test.go
  • internal/service/frontend/api/v1/queues_internal_test.go
  • ui/e2e/distributed-stack.spec.ts
  • ui/e2e/fixtures/dags/e2e-distributed-queue.yaml
✅ Files skipped from review due to trivial changes (3)
  • internal/runtime/builtin/ssh/ssh_test.go
  • internal/runtime/builtin/ssh/config.go
  • internal/cmn/schema/dag.schema.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/cmd/enqueue.go
  • ui/e2e/fixtures/dags/e2e-distributed-queue.yaml

Comment thread ui/e2e/distributed-stack.spec.ts
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
internal/runtime/agent/agent_test.go (2)

71-86: LGTM — filesystem signaling helpers are solid.

waitForTestFile and waitForCancel are small, correct, and t.Helper() is used appropriately so failures point to call sites. The 50ms poll interval and explicit 30s cancel timeout are sensible for CI.

One optional nit: the failure message in waitForCancel ("timed out waiting for DAG cancellation") is identical to the inline block in TestAgent_Run/ReceiveSignal (Line 321). If you want, you could swap that inline select over to waitForCancel too for consistency — not required.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/agent/agent_test.go` around lines 71 - 86, The inline select
in the TestAgent_Run/ReceiveSignal subtest duplicates the timeout logic in
waitForCancel; replace that inline select with a call to waitForCancel(t, done,
30*time.Second) so the test reuses the helper. Locate the subtest
(TestAgent_Run/ReceiveSignal) where it currently does select { case <-done: case
<-time.After(...): t.Fatal(...) } and remove that block, calling
waitForCancel(t, done, 30*time.Second) instead to keep behavior consistent and
centralized in the waitForCancel helper.

622-741: HTTP subtests: filesystem-signaling migration looks correct.

All three subtests (HTTPValid, HTTPInvalidRequest, HTTPHandleCancel) now:

  • Use distinct per-subtest startedFile/releaseFile under a shared t.TempDir() (good — prevents cross-subtest collisions when running in parallel).
  • Wait for the on-disk startedFile marker before interacting with the agent, which is a stronger signal than status polling since the step body itself writes the marker.
  • Bound the post-abort wait with waitForCancel(..., 30*time.Second) instead of an implicit/unbounded wait.

A couple of small observations, none blocking:

  1. In HTTPValid (Lines 647–657), after waitForTestFile returns you immediately query /status and assert core.Running. There is a tiny window between the step writing the marker and the agent's status transitioning to Running as observed by HandleHTTP. In practice the step is still blocked in waitForFileScript when the status is read, so Running is essentially guaranteed — but if this ever flakes on slow CI, consider wrapping the status check in require.Eventually the way TestAgent_Run/ReceiveSignal does.

  2. waitForTestFile here is a near-duplicate of the one in internal/intg/platform_helpers_test.go (per the provided context snippet). Since these live in different test packages, sharing would require promoting it to a non-_test helper package (e.g., internal/test). Fine to leave as-is for this PR given the scope is SFTP schema validation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/agent/agent_test.go` around lines 622 - 741, HTTPValid's
immediate status check can race; wrap the status assertion in a retry (use
require.Eventually) after waitForTestFile to ensure HandleHTTP returns
core.Running reliably: in the HTTPValid subtest, replace the direct call/require
sequence that invokes dagAgent.HandleHTTP(th.Context)/exec.StatusFromJSON and
require.Equal(core.Running) with a short retry loop using require.Eventually
that re-calls dagAgent.HandleHTTP(...)/exec.StatusFromJSON until
Status==core.Running or timeout; optionally consider promoting waitForTestFile
to a shared test helper if you want to deduplicate across packages (but the
immediate fix is to make the status assertion in HTTPValid resilient as
described).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/runtime/agent/agent_test.go`:
- Around line 71-86: The inline select in the TestAgent_Run/ReceiveSignal
subtest duplicates the timeout logic in waitForCancel; replace that inline
select with a call to waitForCancel(t, done, 30*time.Second) so the test reuses
the helper. Locate the subtest (TestAgent_Run/ReceiveSignal) where it currently
does select { case <-done: case <-time.After(...): t.Fatal(...) } and remove
that block, calling waitForCancel(t, done, 30*time.Second) instead to keep
behavior consistent and centralized in the waitForCancel helper.
- Around line 622-741: HTTPValid's immediate status check can race; wrap the
status assertion in a retry (use require.Eventually) after waitForTestFile to
ensure HandleHTTP returns core.Running reliably: in the HTTPValid subtest,
replace the direct call/require sequence that invokes
dagAgent.HandleHTTP(th.Context)/exec.StatusFromJSON and
require.Equal(core.Running) with a short retry loop using require.Eventually
that re-calls dagAgent.HandleHTTP(...)/exec.StatusFromJSON until
Status==core.Running or timeout; optionally consider promoting waitForTestFile
to a shared test helper if you want to deduplicate across packages (but the
immediate fix is to make the status assertion in HTTPValid resilient as
described).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90093ce8-af6f-4db6-af09-c596a69f5dc3

📥 Commits

Reviewing files that changed from the base of the PR and between fc740ea and 91d5995.

📒 Files selected for processing (4)
  • internal/cmd/enqueue_internal_test.go
  • internal/cmn/schema/dag_schema_test.go
  • internal/runtime/agent/agent_test.go
  • ui/e2e/distributed-stack.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • internal/cmd/enqueue_internal_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/e2e/distributed-stack.spec.ts
  • internal/cmn/schema/dag_schema_test.go

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

@yottahmd yottahmd force-pushed the main branch 2 times, most recently from a9de1f4 to bb5e75d Compare April 21, 2026 10:27
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
internal/runtime/agent/agent_test.go (2)

635-639: Nit: inconsistent close(done) placement across subtests.

HTTPValid uses defer close(done) while HTTPInvalidRequest and HTTPHandleCancel call close(done) after RunCancel returns. Both are correct, but aligning on one style (ideally defer, which also closes if RunCancel panics via t.Fatal in another goroutine) would make the three subtests easier to scan.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/agent/agent_test.go` around lines 635 - 639, The three
subtests (HTTPValid, HTTPInvalidRequest, HTTPHandleCancel) create a done channel
and start goroutines calling dagAgent.RunCancel(t); standardize them to use
defer close(done) inside the goroutine so the channel is closed even if
RunCancel panics or calls t.Fatal—replace any post-call close(done) with defer
close(done) in the goroutine that invokes RunCancel to make behavior consistent
and safer.

630-655: Filesystem-signaling refactor looks correct.

Concatenating writeFileCommand(...) + "\n" + waitForFileScript(...) works on both POSIX (two shell statements) and PowerShell (newline-separated statements), and %q preserves the newline when embedded into the YAML double-quoted command: value. The retry on HandleHTTP is a sound replacement for AssertLatestStatus(Running) since HandleHTTP always stamps Status = core.Running on GET /status success (see internal/runtime/agent/agent.go lines 1322-1331), so the loop effectively gates on StatusOK.

One minor nit: a fresh mockResponseWriter{} is allocated every iteration (good, avoids stale state), but shadowing via var mockResponseWriter = mockResponseWriter{} reuses the type name as the variable name. Harmless here since the type isn't referenced again in the closure, but renaming to e.g. rw := mockResponseWriter{} would be clearer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runtime/agent/agent_test.go` around lines 630 - 655, The test
currently declares a variable using the same identifier as its type ("var
mockResponseWriter = mockResponseWriter{}"), which shadows the type name and is
confusing; change the loop local to a clearly named variable like "rw :=
mockResponseWriter{}" and then use "rw" in the subsequent calls (rw.status,
rw.body) when invoking dagAgent.HandleHTTP and parsing the response to avoid
type/variable shadowing while preserving the existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/runtime/agent/agent_test.go`:
- Around line 635-639: The three subtests (HTTPValid, HTTPInvalidRequest,
HTTPHandleCancel) create a done channel and start goroutines calling
dagAgent.RunCancel(t); standardize them to use defer close(done) inside the
goroutine so the channel is closed even if RunCancel panics or calls
t.Fatal—replace any post-call close(done) with defer close(done) in the
goroutine that invokes RunCancel to make behavior consistent and safer.
- Around line 630-655: The test currently declares a variable using the same
identifier as its type ("var mockResponseWriter = mockResponseWriter{}"), which
shadows the type name and is confusing; change the loop local to a clearly named
variable like "rw := mockResponseWriter{}" and then use "rw" in the subsequent
calls (rw.status, rw.body) when invoking dagAgent.HandleHTTP and parsing the
response to avoid type/variable shadowing while preserving the existing
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: afabc9f5-4cca-4e5e-a35d-e75097d8966c

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee0df1 and 3f901e9.

📒 Files selected for processing (1)
  • internal/runtime/agent/agent_test.go

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

@yottahmd yottahmd force-pushed the fix/sftp-executor-schema branch from a1e99a4 to ed2c3f2 Compare April 21, 2026 13:39
@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/runtime/agent/agent_test.go`:
- Around line 79-86: In waitForCancel replace the direct t.Fatal call with the
testify require equivalent: import "github.com/stretchr/testify/require" and
call require.FailNow(t, "timed out waiting for DAG cancellation") (or
require.FailNow(t, "timed out waiting for DAG cancellation", nil) as needed), so
the helper uses stretchr/testify assertions instead of t.Fatal; update imports
accordingly.
🪄 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: 6edafbe4-5e86-437c-9987-9daf3bf7859f

📥 Commits

Reviewing files that changed from the base of the PR and between 3f901e9 and ed2c3f2.

📒 Files selected for processing (3)
  • internal/persis/fileproc/handle.go
  • internal/persis/fileproc/handle_test.go
  • internal/runtime/agent/agent_test.go

Comment thread internal/runtime/agent/agent_test.go
@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/intg/distr/zombie_recovery_test.go (1)

187-191: Minor: post-loop Greater check is now redundant.

Line 191's assert.Greater(lease.LastHeartbeatAt, initialLease) is already guaranteed by the Eventually exit condition at line 167 and re-verified implicitly by waitForLease at line 190 (which may, however, return a newer lease — so this assertion still holds). Not worth changing, but you could drop it to reduce noise, or keep it as a belt-and-suspenders guard against regressions in waitForLease.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/intg/distr/zombie_recovery_test.go` around lines 187 - 191, The
final assert.Greater(lease.LastHeartbeatAt, initialLease) is redundant because
the Eventually loop and waitForLease(...) already guarantee the lease advanced;
remove the assertion line to reduce test noise (i.e., delete the assert.Greater
call that references lease.LastHeartbeatAt and initialLease after waitForLease),
leaving the latestStatus() check and the lease = waitForLease(...) call intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/intg/distr/zombie_recovery_test.go`:
- Around line 187-191: The final assert.Greater(lease.LastHeartbeatAt,
initialLease) is redundant because the Eventually loop and waitForLease(...)
already guarantee the lease advanced; remove the assertion line to reduce test
noise (i.e., delete the assert.Greater call that references
lease.LastHeartbeatAt and initialLease after waitForLease), leaving the
latestStatus() check and the lease = waitForLease(...) call intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f496bb2-3c24-4a0e-8319-302179f6b3ec

📥 Commits

Reviewing files that changed from the base of the PR and between ed2c3f2 and 8e17fc8.

📒 Files selected for processing (1)
  • internal/intg/distr/zombie_recovery_test.go

@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

@yottahmd
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

✅ 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.

@yottahmd yottahmd merged commit b9cd41d into main Apr 22, 2026
11 checks passed
@yottahmd yottahmd deleted the fix/sftp-executor-schema branch April 22, 2026 09:31
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.

[BUG] - DAG Definitions - type sftp unrecognized

1 participant