Skip to content

Releases: redwoodjs/local-ci

dtu-github-actions@0.17.1

Choose a tag to compare

@github-actions github-actions released this 14 Jul 07:03
aa1802a

Patch Changes

  • 9ec9d45: Refs #378. Give every job private writable node_modules, keep npm installs private while sharing npm's download cache, and atomically publish completed pnpm, Yarn, and Bun dependency trees as lockfile-keyed snapshots that are copied into each job with copy-on-write when available.

@redwoodjs/agent-ci@0.17.1

Choose a tag to compare

@github-actions github-actions released this 14 Jul 07:03
aa1802a

Patch Changes

  • 9ec9d45: Refs #378. Give every job private writable node_modules, keep npm installs private while sharing npm's download cache, and atomically publish completed pnpm, Yarn, and Bun dependency trees as lockfile-keyed snapshots that are copied into each job with copy-on-write when available.
  • Updated dependencies [9ec9d45]
    • dtu-github-actions@0.17.1

dtu-github-actions@0.17.0

Choose a tag to compare

@github-actions github-actions released this 13 Jul 10:20
b1848e0

Patch Changes

  • 37a094e: Harden ephemeral DTU startup and cleanup for nested local runs, including safer host/network resolution and test coverage for loopback routing through the local runner.
  • 06fa6e6: Harden the ephemeral DTU control plane: require a cryptographically secure, in-process control token for seed/start-runner/dump endpoints (including trailing-slash routes), fail closed when secure randomness is unavailable, and reject runner log paths that escape the run log root through symlinks. Also remove shell execution from compare handling and update vulnerable dependencies, including the unpatched decompress transitive dependency.

@redwoodjs/agent-ci@0.17.0

Choose a tag to compare

@github-actions github-actions released this 13 Jul 10:20
b1848e0

Minor Changes

  • 7a349fd: Add the Rust Agent CI runner implementation for source-checkout parity testing while keeping the published npm package on the TypeScript runner path. From a repository checkout, AGENT_CI_FORCE_RUST=1 pnpm agent-ci-dev ... builds and runs the Rust binary; published npm installs do not include a native runner yet. The Rust runner now honors --jobs for concurrent dependency-wave execution, macOS VM execution honors AGENT_CI_MACOS_VM_CONCURRENCY, nested local runs avoid container-name collisions, smoke benchmarks compare TypeScript and Rust orchestration overhead, shared TypeScript/Rust fixture contracts cover scheduler, event, run-result, Docker socket, and default job-limit parity, pure workflow planning plus reusable workflow expansion and event/result contracts now live in agent-ci-core, the generic job-wave pool and execution-plan adapters live in agent-ci-runtime, --all has Rust smoke coverage and workflow fan-out, and the Rust implementation is split into core and runtime crates with focused run, DTU, expression, Docker, runner, and macOS VM modules.

    Native npm platform-package publishing and npm-launcher native opt-in are intentionally deferred until the release workflow builds, stages, and verifies real target binaries in the same artifact-staging style used by redwoodjs/machinen.

Patch Changes

  • 928fb44: Refs #370. Add agent-ci run --prewarm-through <workflow:job:step-id> and AGENT_CI_PREWARM_THROUGH so a disposable job can warm shared node_modules through an explicit workflow step before parallel jobs begin. Agent CI now warns with an actionable prewarm command when cold parallel install jobs look likely, including a structured diagnostic event in --json mode.

  • 06fa6e6: Harden the ephemeral DTU control plane: require a cryptographically secure, in-process control token for seed/start-runner/dump endpoints (including trailing-slash routes), fail closed when secure randomness is unavailable, and reject runner log paths that escape the run log root through symlinks. Also remove shell execution from compare handling and update vulnerable dependencies, including the unpatched decompress transitive dependency.

  • c331673: Harden the opt-in Rust runner orchestration for matrix needs, reusable workflow expansion and outputs, partial wave failures, cyclic dependency planning errors, pull request branch filters, detached pause handling, nested ephemeral DTU host/network resolution, cleanup of nested containers attached to Rust job networks, and the expanded Rust smoke parity gate with per-workflow diagnostics, heartbeats, status ledgers, and timeout cleanup.

    Refs #367.

  • Updated dependencies [37a094e]

  • Updated dependencies [06fa6e6]

    • dtu-github-actions@0.17.0

dtu-github-actions@0.16.2

Choose a tag to compare

@github-actions github-actions released this 22 May 16:47
456f869

Patch Changes

  • b619fc7: Avoid reusing runner numbers while stable log directories still exist, and clear stale per-run timeline/log artifacts when a runner name is reused, so old timeline.json records cannot be merged into a fresh run and reported as a false failure.

    Refs #341.

@redwoodjs/agent-ci@0.16.2

Choose a tag to compare

@github-actions github-actions released this 22 May 16:48
456f869

Patch Changes

  • b619fc7: Avoid reusing runner numbers while stable log directories still exist, and clear stale per-run timeline/log artifacts when a runner name is reused, so old timeline.json records cannot be merged into a fresh run and reported as a false failure.

    Refs #341.

  • Updated dependencies [b619fc7]

    • dtu-github-actions@0.16.2

dtu-github-actions@0.16.1

Choose a tag to compare

@github-actions github-actions released this 21 May 09:08
adf908c

Patch Changes

  • 412d672: Fix remote actions referenced through deep sub-paths (for example owner/repo/.github/actions/name@ref) by passing the parent repository and action path separately to the runner.

    Refs #362.

dtu-github-actions@0.16.0

Choose a tag to compare

@github-actions github-actions released this 21 May 07:42
f8b99e4

Minor Changes

  • c8da13a: Add agent-ci run --var-file <path|-> for loading workflow variables from JSON files or GitHub CLI gh variable list --json name,value output piped on stdin. Explicit --var KEY=VALUE flags override file-provided values.

    Refs #358.

  • ab075d9: chore: require Node 24 and drop tsx

    Node 24 ships native TypeScript stripping as a stable feature, so we no
    longer need the tsx runtime to execute .ts files. Every tsx foo.ts
    invocation in package scripts becomes node foo.ts. tsx is removed
    from devDependencies in every workspace.

    To make this work with the codebase's existing import convention,
    TypeScript is configured to emit .js paths in built output while
    allowing source files to use real .ts extensions:

    • allowImportingTsExtensions: true
    • rewriteRelativeImportExtensions: true

    All 72 source files have been mechanically updated: every relative
    import that previously said from "./foo.js" now says
    from "./foo.ts". The compiled dist/ output still emits the .js
    extension, so consumers see no change.

    Breaking change: the published packages now declare
    engines.node: ">=24". Node 22 is no longer supported.

    CI: the tests.yml workflow bumps from Node 22 to Node 24. Smoke
    workflows that set node-version: 22 are left alone — they are
    fixtures exercising specific Node versions via actions/setup-node,
    not our project's runtime.

Patch Changes

  • c20a05b: perf(cli): parallelize the startup git calls

    The first thing agent-ci run does is ask git for several pieces of
    information: the current branch, the head commit SHA, the changed
    files, the remote slug, and (when the tree is dirty) an ephemeral
    commit that captures the working-tree state. Each call shelled out to
    execSync, blocking the event loop for ~50–200 ms.

    This change converts each of those helpers to use execFile via
    promisify, so they return promises. handleWorkflow then runs them
    concurrently with Promise.all instead of one at a time.

    Functions converted:

    • getFirstRemoteUrl and resolveRepoSlug in config.ts
    • computeDirtySha in runner/dirty-sha.ts
    • getChangedFiles in workflow/workflow-parser.ts
    • resolveHeadSha, resolveBaseSha, and persistRunResult in
      commands/run.ts

    Switching from execSync(command-string) to execFile("git", [args])
    also removes a shell escaping step on every call — args are passed as
    an array, not a single string.

    Refs #334.

  • 50933a6: chore: remove unused runtime dependencies

    Three runtime dependencies were declared in package.json files but
    never imported by any source file in the package:

    • log-update from @redwoodjs/agent-ci (the diff-renderer module
      replaced it long ago; only stale code comments remain).
    • jsonc-parser from dtu-github-actions.
    • yaml from @redwoodjs/ts-runner (the cli package still depends
      on yaml; this only drops the unused declaration in ts-runner).

    Smaller node_modules, smaller published packages, and one fewer
    thing to keep up to date when the upstream releases a new version.
    No runtime behaviour change.

  • 4b07e75: refactor(workflow-parser): split the GitHub Actions expression evaluator

    Collapses the eight-parameter context that resolveExprAtom /
    evaluateExprValue were threading through every recursive call into a single
    ExprContext object, extracts each built-in function (hashFiles, fromJSON,
    toJSON, format, contains, startsWith, endsWith, join) into its own
    handler, and moves context-variable lookups (runner.*, github.*, matrix.*,
    secrets.*, vars.*, inputs.*, steps.*, needs.*, env.*) into
    resolveContextRef. expandExpressions's public positional signature is
    unchanged.

    No behavioral changes.

  • 24387c7: perf(cli): lazy-load command modules so light commands skip the heavy dependency graph

    Extracts the run, retry/abort, and clean commands into separate modules
    loaded via dynamic import() from cli.ts. The dispatcher now only loads what
    the invoked command actually needs.

    Measured impact on agent-ci --help:

    • Cold start: 240 ms → 20 ms
    • Peak RSS: 88 MB → 42 MB

    --help and unknown commands no longer load dockerode, @grpc/grpc-js,
    protobufjs, ssh2, the runner graph, or the workflow parser. Behavior of every
    command is unchanged; --help/-h now exits 0 (previously 1, which was a
    quirk of falling through the dispatch chain).

    Refs #334.

  • d0a8495: refactor(local-job): extract three helpers out of executeLocalJob

    executeLocalJob had grown to ~860 lines and scored 73 on the
    cognitive-complexity metric — the highest in the cli package after
    the previous round of refactors. Three self-contained blocks of code
    inside it have been moved into module-scope helpers:

    • pullContainerImageWithProgress(docker, image, store, containerName)
      — the ~100-line Docker pull with per-layer download / extract
      progress reporting (direct-container mode).
    • seedRunnerBinaryToHost(docker, hostRunnerSeedDir) — the one-time
      extraction of the actions-runner binary from the seed image
      (direct-container mode).
    • waitForContainerExit(container, waitPromise, timeoutMs) — the
      promise-race that force-stops the container if the runner does not
      exit within the timeout.

    executeLocalJob is now ~715 lines, cognitive 56. No behaviour
    change; the full local smoke suite passes.

  • 2f2af0d: refactor(local-job): lift the timeline-sync closure to module scope

    executeLocalJob had a ~190-line updateStoreFromTimeline closure
    that read timeline.json plus the paused-signal file every 100ms and
    updated the RunStateStore. The closure captured six mutable let
    variables defined just above it; fallow's previous report flagged it
    as the biggest remaining complexity hotspot (cognitive 70).

    This change pulls the closure to module scope as two helpers:

    • syncTimelineToStore(state, ctx) — drives one poll tick. Cognitive
      score 22.
    • buildStepsFromTimeline(steps, state) — folds the raw timeline
      records into the StepState[] shape the renderer expects. Cognitive
      score 45.

    Both take an explicit TimelineSyncState object that the polling loop
    mutates between ticks, plus a read-only TimelineSyncContext with the
    paths, store reference, and onNewPause callback.

    Also drops padW / totalSteps from the old closure — they were
    computed but never used (legacy padding logic).

    No behaviour change; the full local smoke suite passes 45/45.

  • 6b7802b: chore: relax published engines.node back to >=22

    #351 bumped the published packages' engines.node to >=24 along
    with the development-side switch to Node's native TypeScript support.
    End users never run our source files, only the compiled
    dist/cli.js. That compiled output targets ES2020 and only uses APIs
    available on Node 22 (the long-term support release), so the
    published requirement was stricter than it needed to be.

    This change:

    • Sets engines.node to >=22 in @redwoodjs/agent-ci and
      dtu-github-actions. End users on Node 22 stop seeing the
      "unsupported engine" warning.
    • Adds engines.node: ">=24" to the repo-root package.json so
      contributors keep getting an explicit signal that the development
      scripts (which run .ts files directly through Node's native
      type-stripping) need Node 24.

    No code change.

  • 8d92c73: refactor(cli/run): split runCmd and handleWorkflow into focused helpers

    packages/cli/src/commands/run.ts housed two very long orchestrator
    functions. Static analysis (fallow health) scored them as the two
    highest-complexity functions in the cli package:

    • runCmd — cognitive 91, ~228 lines
    • handleWorkflow — cognitive 136, ~717 lines

    They mixed argument parsing, workflow discovery, matrix expansion,
    resource classification, scheduling, wave execution, and final reporting
    in a single body, which made each one hard to follow and hard to change.

    This change pulls clearly bounded steps out into top-level helpers
    without changing any observable behaviour:

    • parseRunArgs, parseJobsFlag, parseVarFlag, resolveGithubTokenFlag,
      discoverRelevantWorkflows, resolveWorkflowArgPath, finalizeRun
      carved out of runCmd.
    • expandJobs, classifyJobsResources, runWaveJobs — carved out of
      handleWorkflow. The ExpandedJob type is lifted to module scope so
      the new helpers can take it.

    New scores (fallow health):

    • runCmd: cognitive 9 (was 91)
    • handleWorkflow: cognitive 61 (was 136)
    • parseRunArgs: cognitive 26 (new, replaces the inline arg loop)

    No runtime behaviour change; full smoke suite passes.

  • a0d3bb0: chore: unexport helpers that were never imported externally

    log-prune.ts and generators.ts had six identifiers marked export
    that no other file actually imported:

    • DEFAULT_RETAIN_DAYS, DEFAULT_RETAIN_RUNS, DEFAULT_THROTTLE_MS
      (used only inside log-prune.ts)
    • toContextData, toTemplateTokenMapping
      (used only inside generators.ts)
    • toContainerTemplateToken
      (not used anywhere — wholly dead, removed)

    Tightens the public surface so callers can't accidentally rely on
    internal helpers, and gets a step closer to a clean dead-code report.
    No runtime behaviour change.

@redwoodjs/agent-ci@0.16.1

Choose a tag to compare

@github-actions github-actions released this 21 May 09:08
adf908c

Patch Changes

  • 412d672: Fix remote actions referenced through deep sub-paths (for example owner/repo/.github/actions/name@ref) by passing the parent repository and action path separately to the runner.

    Refs #362.

  • Updated dependencies [412d672]

    • dtu-github-actions@0.16.1

@redwoodjs/agent-ci@0.16.0

Choose a tag to compare

@github-actions github-actions released this 21 May 07:42
f8b99e4

Minor Changes

  • c8da13a: Add agent-ci run --var-file <path|-> for loading workflow variables from JSON files or GitHub CLI gh variable list --json name,value output piped on stdin. Explicit --var KEY=VALUE flags override file-provided values.

    Refs #358.

  • ab075d9: chore: require Node 24 and drop tsx

    Node 24 ships native TypeScript stripping as a stable feature, so we no
    longer need the tsx runtime to execute .ts files. Every tsx foo.ts
    invocation in package scripts becomes node foo.ts. tsx is removed
    from devDependencies in every workspace.

    To make this work with the codebase's existing import convention,
    TypeScript is configured to emit .js paths in built output while
    allowing source files to use real .ts extensions:

    • allowImportingTsExtensions: true
    • rewriteRelativeImportExtensions: true

    All 72 source files have been mechanically updated: every relative
    import that previously said from "./foo.js" now says
    from "./foo.ts". The compiled dist/ output still emits the .js
    extension, so consumers see no change.

    Breaking change: the published packages now declare
    engines.node: ">=24". Node 22 is no longer supported.

    CI: the tests.yml workflow bumps from Node 22 to Node 24. Smoke
    workflows that set node-version: 22 are left alone — they are
    fixtures exercising specific Node versions via actions/setup-node,
    not our project's runtime.

Patch Changes

  • c20a05b: perf(cli): parallelize the startup git calls

    The first thing agent-ci run does is ask git for several pieces of
    information: the current branch, the head commit SHA, the changed
    files, the remote slug, and (when the tree is dirty) an ephemeral
    commit that captures the working-tree state. Each call shelled out to
    execSync, blocking the event loop for ~50–200 ms.

    This change converts each of those helpers to use execFile via
    promisify, so they return promises. handleWorkflow then runs them
    concurrently with Promise.all instead of one at a time.

    Functions converted:

    • getFirstRemoteUrl and resolveRepoSlug in config.ts
    • computeDirtySha in runner/dirty-sha.ts
    • getChangedFiles in workflow/workflow-parser.ts
    • resolveHeadSha, resolveBaseSha, and persistRunResult in
      commands/run.ts

    Switching from execSync(command-string) to execFile("git", [args])
    also removes a shell escaping step on every call — args are passed as
    an array, not a single string.

    Refs #334.

  • 50933a6: chore: remove unused runtime dependencies

    Three runtime dependencies were declared in package.json files but
    never imported by any source file in the package:

    • log-update from @redwoodjs/agent-ci (the diff-renderer module
      replaced it long ago; only stale code comments remain).
    • jsonc-parser from dtu-github-actions.
    • yaml from @redwoodjs/ts-runner (the cli package still depends
      on yaml; this only drops the unused declaration in ts-runner).

    Smaller node_modules, smaller published packages, and one fewer
    thing to keep up to date when the upstream releases a new version.
    No runtime behaviour change.

  • 4b07e75: refactor(workflow-parser): split the GitHub Actions expression evaluator

    Collapses the eight-parameter context that resolveExprAtom /
    evaluateExprValue were threading through every recursive call into a single
    ExprContext object, extracts each built-in function (hashFiles, fromJSON,
    toJSON, format, contains, startsWith, endsWith, join) into its own
    handler, and moves context-variable lookups (runner.*, github.*, matrix.*,
    secrets.*, vars.*, inputs.*, steps.*, needs.*, env.*) into
    resolveContextRef. expandExpressions's public positional signature is
    unchanged.

    No behavioral changes.

  • 24387c7: perf(cli): lazy-load command modules so light commands skip the heavy dependency graph

    Extracts the run, retry/abort, and clean commands into separate modules
    loaded via dynamic import() from cli.ts. The dispatcher now only loads what
    the invoked command actually needs.

    Measured impact on agent-ci --help:

    • Cold start: 240 ms → 20 ms
    • Peak RSS: 88 MB → 42 MB

    --help and unknown commands no longer load dockerode, @grpc/grpc-js,
    protobufjs, ssh2, the runner graph, or the workflow parser. Behavior of every
    command is unchanged; --help/-h now exits 0 (previously 1, which was a
    quirk of falling through the dispatch chain).

    Refs #334.

  • d0a8495: refactor(local-job): extract three helpers out of executeLocalJob

    executeLocalJob had grown to ~860 lines and scored 73 on the
    cognitive-complexity metric — the highest in the cli package after
    the previous round of refactors. Three self-contained blocks of code
    inside it have been moved into module-scope helpers:

    • pullContainerImageWithProgress(docker, image, store, containerName)
      — the ~100-line Docker pull with per-layer download / extract
      progress reporting (direct-container mode).
    • seedRunnerBinaryToHost(docker, hostRunnerSeedDir) — the one-time
      extraction of the actions-runner binary from the seed image
      (direct-container mode).
    • waitForContainerExit(container, waitPromise, timeoutMs) — the
      promise-race that force-stops the container if the runner does not
      exit within the timeout.

    executeLocalJob is now ~715 lines, cognitive 56. No behaviour
    change; the full local smoke suite passes.

  • 2f2af0d: refactor(local-job): lift the timeline-sync closure to module scope

    executeLocalJob had a ~190-line updateStoreFromTimeline closure
    that read timeline.json plus the paused-signal file every 100ms and
    updated the RunStateStore. The closure captured six mutable let
    variables defined just above it; fallow's previous report flagged it
    as the biggest remaining complexity hotspot (cognitive 70).

    This change pulls the closure to module scope as two helpers:

    • syncTimelineToStore(state, ctx) — drives one poll tick. Cognitive
      score 22.
    • buildStepsFromTimeline(steps, state) — folds the raw timeline
      records into the StepState[] shape the renderer expects. Cognitive
      score 45.

    Both take an explicit TimelineSyncState object that the polling loop
    mutates between ticks, plus a read-only TimelineSyncContext with the
    paths, store reference, and onNewPause callback.

    Also drops padW / totalSteps from the old closure — they were
    computed but never used (legacy padding logic).

    No behaviour change; the full local smoke suite passes 45/45.

  • 6b7802b: chore: relax published engines.node back to >=22

    #351 bumped the published packages' engines.node to >=24 along
    with the development-side switch to Node's native TypeScript support.
    End users never run our source files, only the compiled
    dist/cli.js. That compiled output targets ES2020 and only uses APIs
    available on Node 22 (the long-term support release), so the
    published requirement was stricter than it needed to be.

    This change:

    • Sets engines.node to >=22 in @redwoodjs/agent-ci and
      dtu-github-actions. End users on Node 22 stop seeing the
      "unsupported engine" warning.
    • Adds engines.node: ">=24" to the repo-root package.json so
      contributors keep getting an explicit signal that the development
      scripts (which run .ts files directly through Node's native
      type-stripping) need Node 24.

    No code change.

  • 8d92c73: refactor(cli/run): split runCmd and handleWorkflow into focused helpers

    packages/cli/src/commands/run.ts housed two very long orchestrator
    functions. Static analysis (fallow health) scored them as the two
    highest-complexity functions in the cli package:

    • runCmd — cognitive 91, ~228 lines
    • handleWorkflow — cognitive 136, ~717 lines

    They mixed argument parsing, workflow discovery, matrix expansion,
    resource classification, scheduling, wave execution, and final reporting
    in a single body, which made each one hard to follow and hard to change.

    This change pulls clearly bounded steps out into top-level helpers
    without changing any observable behaviour:

    • parseRunArgs, parseJobsFlag, parseVarFlag, resolveGithubTokenFlag,
      discoverRelevantWorkflows, resolveWorkflowArgPath, finalizeRun
      carved out of runCmd.
    • expandJobs, classifyJobsResources, runWaveJobs — carved out of
      handleWorkflow. The ExpandedJob type is lifted to module scope so
      the new helpers can take it.

    New scores (fallow health):

    • runCmd: cognitive 9 (was 91)
    • handleWorkflow: cognitive 61 (was 136)
    • parseRunArgs: cognitive 26 (new, replaces the inline arg loop)

    No runtime behaviour change; full smoke suite passes.

  • a0d3bb0: chore: unexport helpers that were never imported externally

    log-prune.ts and generators.ts had six identifiers marked export
    that no other file actually imported:

    • DEFAULT_RETAIN_DAYS, DEFAULT_RETAIN_RUNS, DEFAULT_THROTTLE_MS
      (used only inside log-prune.ts)
    • toContextData, toTemplateTokenMapping
      (used only inside generators.ts)
    • toContainerTemplateToken
      (not used anywhere — wholly dead, removed)

    Tightens the public surface so callers can't accidentally rely on
    internal helpers, and gets a step closer to a clean dead-code report.
    No runtime behaviour change.

  • Updated dependencies [c20a05b]

  • Updated dependencies [50933a6]

  • Updated dependencies [4b...

Read more