feat(cli): add predownload command to pre-pull container images#1245
feat(cli): add predownload command to pre-pull container images#1245
Conversation
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>
|
| 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
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>
There was a problem hiding this comment.
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.tswith image-resolution logic and a pull loop invokingdocker pull. - Adds unit tests for image resolution in
src/commands/predownload.test.ts. - Wires the new
predownloadsubcommand intosrc/cli.tswith 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.
| const isPreset = agentImage === 'default' || agentImage === 'act'; | ||
| if (isPreset) { | ||
| const imageName = agentImage === 'act' ? 'agent-act' : 'agent'; | ||
| images.push(`${imageRegistry}/${imageName}:${imageTag}`); | ||
| } else { |
There was a problem hiding this comment.
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.
| } else { | ||
| // Custom image - pull as-is | ||
| images.push(agentImage); | ||
| } |
There was a problem hiding this comment.
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.
| logger.error(`${failed} of ${images.length} image(s) failed to pull`); | ||
| process.exit(1); |
There was a problem hiding this comment.
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.
| 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; |
src/cli.ts
Outdated
| .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) => { |
There was a problem hiding this comment.
--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.
|
| 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
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>
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (2 files)
✨ New Files (1 files)
Coverage comparison generated by |
|
test: expand credential hiding tests to all 14 protected paths
|
|
🤖 Smoke test results for run
Overall: PASS
|
|
Smoke Test Results — PASS
|
Chroot Version Comparison Results
Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.
|
Summary
awf predownloadsubcommand that pre-pulls Docker container images ahead of time--image-registry,--image-tag,--agent-image, and--enable-api-proxyflags--skip-pullto avoid pulling images at runtimeFixes #193
Test plan
awf predownloadpulls squid and agent imagesawf predownload --agent-image actpulls agent-act imageawf predownload --enable-api-proxyalso pulls api-proxyawf predownload --image-tag v1.0.0uses correct tagawf predownloadfollowed byawf --skip-pull ...works🤖 Generated with Claude Code