Skip to content

feat(cli): add predownload command to pre-pull container images#1245

Merged
Mossaka merged 4 commits intomainfrom
feat/103-predownload-images
Mar 12, 2026
Merged

feat(cli): add predownload command to pre-pull container images#1245
Mossaka merged 4 commits intomainfrom
feat/103-predownload-images

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Mar 11, 2026

Summary

  • Adds awf predownload subcommand that pre-pulls Docker container images ahead of time
  • Supports --image-registry, --image-tag, --agent-image, and --enable-api-proxy flags
  • After predownloading, users can use --skip-pull to avoid pulling images at runtime
  • 5 unit tests for image resolution logic

Fixes #193

Test plan

  • Verify awf predownload pulls squid and agent images
  • Verify awf predownload --agent-image act pulls agent-act image
  • Verify awf predownload --enable-api-proxy also pulls api-proxy
  • Verify awf predownload --image-tag v1.0.0 uses correct tag
  • Verify awf predownload followed by awf --skip-pull ... works

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings March 11, 2026 18:51
@github-actions
Copy link
Contributor

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 82.50% 82.13% 📉 -0.37%
Statements 82.50% 82.13% 📉 -0.37%
Functions 82.69% 81.60% 📉 -1.09%
Branches 74.78% 74.78% ➡️ +0.00%
📁 Per-file Coverage Changes (2 files)
File Lines (Before → After) Statements (Before → After)
src/cli.ts 47.0% → 46.9% (-0.11%) 47.5% → 47.4% (-0.11%)
src/docker-manager.ts 84.0% → 84.5% (+0.54%) 83.3% → 83.8% (+0.52%)
✨ New Files (1 files)
  • src/commands/predownload.ts: 50.0% lines

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new awf predownload CLI subcommand to pre-pull the Docker images used by AWF ahead of time, enabling faster startup and supporting offline/air-gapped workflows when combined with --skip-pull.

Changes:

  • Introduces src/commands/predownload.ts with image-resolution logic and a pull loop invoking docker pull.
  • Adds unit tests for image resolution in src/commands/predownload.test.ts.
  • Wires the new predownload subcommand into src/cli.ts with flags for registry/tag/agent image selection and api-proxy inclusion.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/commands/predownload.ts Implements image list resolution + executes docker pull for each resolved image.
src/commands/predownload.test.ts Tests resolveImages behavior for presets, custom images, and api-proxy inclusion.
src/cli.ts Adds the predownload subcommand and exposes relevant flags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +26
const isPreset = agentImage === 'default' || agentImage === 'act';
if (isPreset) {
const imageName = agentImage === 'act' ? 'agent-act' : 'agent';
images.push(`${imageRegistry}/${imageName}:${imageTag}`);
} else {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

resolveImages re-implements the same preset-to-image mapping logic that already exists in generateDockerCompose (e.g., default→agent, act→agent-act). This duplication is likely to drift as image naming/registry/tag logic evolves (including api-proxy behavior). Consider extracting a shared image-resolution helper used by both generateDockerCompose and this command so the pulled images always match what runtime would use.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +29
} else {
// Custom image - pull as-is
images.push(agentImage);
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Custom agentImage values are passed directly as the docker pull image reference. If the value contains whitespace or starts with -, Docker will treat it as invalid or as a flag (e.g. --help) rather than an image, leading to confusing behavior. Add lightweight validation (e.g., reject leading - / any whitespace, or validate against a Docker image reference regex) before adding it to the pull list.

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +61
logger.error(`${failed} of ${images.length} image(s) failed to pull`);
process.exit(1);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The failure path exits the process, but predownloadCommand itself isn’t covered by tests (only resolveImages is). Adding unit tests that mock execa and process.exit would catch regressions in pull invocation, failure counting, and exit-code behavior.

Suggested change
logger.error(`${failed} of ${images.length} image(s) failed to pull`);
process.exit(1);
const message = `${failed} of ${images.length} image(s) failed to pull`;
logger.error(message);
const error: Error & { exitCode?: number } = new Error(message);
error.exitCode = 1;
throw error;

Copilot uses AI. Check for mistakes.
src/cli.ts Outdated
Comment on lines +1294 to +1301
.option('--image-tag <tag>', 'Container image tag', 'latest')
.option(
'--agent-image <value>',
'Agent image preset (default, act) or custom image',
'default'
)
.option('--enable-api-proxy', 'Also download the API proxy image', false)
.action(async (options) => {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

--image-tag here affects squid/agent and (when --enable-api-proxy is set) also the api-proxy image. Consider updating the option help text to make that explicit, to match actual behavior and reduce confusion for users.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Contributor

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 82.50% 82.82% 📈 +0.32%
Statements 82.50% 82.80% 📈 +0.30%
Functions 82.69% 82.07% 📉 -0.62%
Branches 74.78% 75.12% 📈 +0.34%
📁 Per-file Coverage Changes (2 files)
File Lines (Before → After) Statements (Before → After)
src/cli.ts 47.0% → 46.9% (-0.11%) 47.5% → 47.4% (-0.11%)
src/docker-manager.ts 84.0% → 84.5% (+0.54%) 83.3% → 83.8% (+0.52%)
✨ New Files (1 files)
  • src/commands/predownload.ts: 100.0% lines

Coverage comparison generated by scripts/ci/compare-coverage.ts

@github-actions
Copy link
Contributor

github-actions bot commented Mar 11, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 83.62% 83.98% 📈 +0.36%
Statements 83.62% 83.97% 📈 +0.35%
Functions 84.01% 84.37% 📈 +0.36%
Branches 76.35% 76.61% 📈 +0.26%
📁 Per-file Coverage Changes (2 files)
File Lines (Before → After) Statements (Before → After)
src/cli.ts 55.5% → 55.7% (+0.23%) 56.0% → 56.2% (+0.22%)
src/docker-manager.ts 85.4% → 86.0% (+0.52%) 84.8% → 85.3% (+0.50%)
✨ New Files (1 files)
  • src/commands/predownload.ts: 100.0% lines

Coverage comparison generated by scripts/ci/compare-coverage.ts

@github-actions
Copy link
Contributor

test: expand credential hiding tests to all 14 protected paths
test(docker): verify capsh execution chain after PR #715
GitHub MCP review: ✅
safeinputs-gh pr list: ✅
playwright title check: ✅
tavily search: ❌ (tool unavailable)
file write+cat: ✅
discussion query+comment: ✅
build (npm ci && npm run build): ✅
Overall: FAIL

🔮 The oracle has spoken through Smoke Codex for issue #1245

@github-actions
Copy link
Contributor

🤖 Smoke test results for run 22969455364@Mossaka

Test Status
GitHub MCP (last 2 merged PRs) #1240 "test(docker): verify capsh execution chain after PR #715", #1232 "fix(cli): clear LD_PRELOAD after one-shot-token library loads"
Playwright (github.com title contains "GitHub")
File write /tmp/gh-aw/agent/smoke-test-copilot-22969455364.txt
Bash (cat file verify)

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results — PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1245

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.12 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1245

@github-actions github-actions bot mentioned this pull request Mar 11, 2026
@Mossaka Mossaka force-pushed the feat/103-predownload-images branch from abffc75 to 5a962a4 Compare March 12, 2026 18:57
@github-actions
Copy link
Contributor

🤖 Smoke test results for #1245@Mossaka

Test Result
GitHub MCP (last 2 merged PRs) #1261 "ci: skip CI when only release.yml changes", #1260 "fix: make release workflow compatible with branch protection"
Playwright (github.com title)
File write
Bash verify

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1245

@github-actions
Copy link
Contributor

GitHub MCP (last 2 merged PRs): ✅
chore(deps): aggregated dependency updates | docs: document flag validation constraints
Safeinputs GH CLI: ✅
Playwright title check: ✅
Tavily web search: ❌
File writing: ✅
Bash cat verification: ✅
Discussion interaction: ✅
Build (npm ci && npm run build): ✅
Overall status: FAIL

🔮 The oracle has spoken through Smoke Codex for issue #1245

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.12 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results

  • ✅ GitHub MCP: #1218 chore(deps): aggregated dependency updates, #1230 docs: document flag validation constraints
  • ✅ Playwright: GitHub page title verified
  • ✅ File write: /tmp/gh-aw/agent/smoke-test-claude-23018810714.txt created
  • ✅ Bash: File contents verified

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1245

@Mossaka Mossaka force-pushed the feat/103-predownload-images branch from 5a962a4 to d2c3f2a Compare March 12, 2026 20:22
@github-actions
Copy link
Contributor

Smoke Test Results

Test Status
GitHub MCP (last 2 merged PRs: #1265, #1262)
Playwright (github.com title contains "GitHub")
File write (smoke-test-claude-23022151420.txt)
Bash verify (file read back)

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results — PASS

Test Result
GitHub MCP (last 2 merged PRs) #1265 "fix: add missing formatItem and program imports in cli.test.ts", #1262 "test: add logger/aggregator tests for blocked domain detection"
Playwright (github.com title check) ✅ "GitHub · Change is constant. GitHub keeps you ahead. · GitHub"
File write + read /tmp/gh-aw/agent/smoke-test-copilot-23022151504.txt created
Bash tool ✅ File verified via cat

Author: @Mossaka | Assignees: none

📰 BREAKING: Report filed by Smoke Copilot for issue #1245

@github-actions
Copy link
Contributor

Smoke test results:
PR titles: fix: add missing formatItem and program imports in cli.test.ts | test: add logger/aggregator tests for blocked domain detection
GitHub MCP merged PRs ✅
safeinputs-gh pr list ✅
Playwright title contains GitHub ✅
Tavily search ❌
File write + cat ✅
Build (npm ci && npm run build) ✅
Overall: FAIL

🔮 The oracle has spoken through Smoke Codex for issue #1245

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.12 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results

Test Result
GitHub MCP: #1265 fix: add missing formatItem and program imports in cli.test.ts
GitHub MCP: #1262 test: add logger/aggregator tests for blocked domain detection
Playwright: github.com title contains "GitHub"
File write: smoke-test-claude-23022670598.txt
Bash verify: file content confirmed

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1245

@github-actions
Copy link
Contributor

Merged PRs: fix: add missing formatItem and program imports in cli.test.ts | test: add logger/aggregator tests for blocked domain detection
Recent PRs: fix: add missing formatItem and program imports in cli.test.ts | feat(proxy): add GitHub Enterprise Cloud/Server support with automatic endpoint detection
Tests: MCP ✅, safeinputs-gh ✅, Playwright ✅, Tavily ❌, file ✅, bash ✅, discussion ✅, build ✅
Overall: FAIL

🔮 The oracle has spoken through Smoke Codex for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results — Run 23022670640

GitHub MCP: Last 2 merged PRs — #1265 by @Copilot, #1262 by @Mossaka
Playwright: github.com title contains "GitHub"
File Write: /tmp/gh-aw/agent/smoke-test-copilot-23022670640.txt created
Bash Verify: File read back successfully

Overall: PASS | PR author: @Mossaka | No assignees

📰 BREAKING: Report filed by Smoke Copilot for issue #1245

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.12 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: FAILED — Python and Node.js versions differ between host and chroot environment.

Tested by Smoke Chroot for issue #1245

Adds `awf predownload` subcommand that pulls Docker images ahead of time
for offline use or faster startup. Supports --image-registry, --image-tag,
--agent-image, and --enable-api-proxy flags. After predownloading, users
can use --skip-pull to avoid pulling at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mossaka and others added 3 commits March 12, 2026 21:03
Add 5 tests covering the predownloadCommand async function: successful
pull of all images, api-proxy inclusion, process.exit on failure,
continued pulling after partial failure, and non-Error rejection handling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract predownload action handler to named exported function and add
unit test to maintain function coverage levels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Validate custom agentImage to reject leading dashes and whitespace
- Replace process.exit(1) with thrown error with exitCode for testability
- Update --image-tag help text to clarify it applies to all images
- Add tests for image reference validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka Mossaka force-pushed the feat/103-predownload-images branch from c17c9ff to b634c44 Compare March 12, 2026 21:04
@github-actions
Copy link
Contributor

Smoke Test Results — PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1245

@github-actions
Copy link
Contributor

Smoke Test Results — Run 23023824896

GitHub MCP — Last 2 merged PRs: #1265 "fix: add missing formatItem and program imports in cli.test.ts", #1262 "test: add logger/aggregator tests for blocked domain detection"
Playwright — github.com title contains "GitHub"
File Write/tmp/gh-aw/agent/smoke-test-copilot-23023824896.txt created and verified
Bash — File read back successfully

Overall: PASS

PR author: @Mossaka | Assignees: none

📰 BREAKING: Report filed by Smoke Copilot for issue #1245

@github-actions
Copy link
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.12 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1245

@github-actions
Copy link
Contributor

PR titles:
feat(cli): add --agent-timeout flag for execution time limit
fix: add missing formatItem and program imports in cli.test.ts
GitHub MCP review ✅
safeinputs-gh PR list ✅
Playwright title ✅
Tavily search ❌ (missing tool)
File write ✅ | Bash cat ✅
Discussion comment ✅
Build ✅ | Overall FAIL

🔮 The oracle has spoken through Smoke Codex for issue #1245

@github-actions
Copy link
Contributor

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color 1/1 passed ✅ PASS
Go env 1/1 passed ✅ PASS
Go uuid 1/1 passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx all passed ✅ PASS
Node.js execa all passed ✅ PASS
Node.js p-limit all passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #1245 ·

@Mossaka Mossaka merged commit fb7bc5b into main Mar 12, 2026
62 of 63 checks passed
@Mossaka Mossaka deleted the feat/103-predownload-images branch March 12, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Predownload images

2 participants