Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .github/workflows/individual-tool-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -615,9 +615,9 @@ jobs:
path: verify-deploy-test-results.json
retention-days: 7

# Test build-image with multi-language scenarios
test-build-image:
name: build-image Multi-Language Tests (${{ matrix.os }})
# Test build-image-context with multi-language scenarios
test-build-image-context:
name: build-image-context Multi-Language Tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
Expand Down Expand Up @@ -670,7 +670,7 @@ jobs:
ls -la test/fixtures/build-scenarios/dotnet/
echo "✅ All test fixtures found"

- name: Run build-image integration test (Linux only)
- name: Run build-image-context integration test (Linux only)
if: runner.os == 'Linux'
id: build-tests
run: |
Expand All @@ -692,7 +692,7 @@ jobs:
echo "# 🔨 Multi-Language Build Integration Tests" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Tool Tested" >> $GITHUB_STEP_SUMMARY
echo "- \`build-image\` - Builds Docker images from Dockerfiles" >> $GITHUB_STEP_SUMMARY
echo "- \`build-image-context\` - Returns Docker build commands for agents to execute" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Platform:** ${{ matrix.os }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
Expand All @@ -704,10 +704,10 @@ jobs:
echo "**Expected:** \`//./pipe/docker_engine\` (Windows named pipe)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Note:** Windows runners only validate socket path. Full build tests run on Linux." >> $GITHUB_STEP_SUMMARY
elif [ -f "build-image-test-results.json" ]; then
TOTAL=$(jq -r '.total' build-image-test-results.json)
PASSED=$(jq -r '.passed' build-image-test-results.json)
FAILED=$(jq -r '.failed' build-image-test-results.json)
elif [ -f "build-image-context-test-results.json" ]; then
TOTAL=$(jq -r '.total' build-image-context-test-results.json)
PASSED=$(jq -r '.passed' build-image-context-test-results.json)
FAILED=$(jq -r '.failed' build-image-context-test-results.json)

echo "## Results" >> $GITHUB_STEP_SUMMARY
echo "- **Total Tests**: $TOTAL" >> $GITHUB_STEP_SUMMARY
Expand All @@ -716,7 +716,7 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY

echo "## Test Cases" >> $GITHUB_STEP_SUMMARY
jq -r '.results[] | "- " + (if .passed then "✅" else "❌" end) + " **" + .name + "**" + (if .imageSize then " (" + ((.imageSize / 1000000) | floor | tostring) + "MB)" else "" end)' build-image-test-results.json >> $GITHUB_STEP_SUMMARY
jq -r '.results[] | "- " + (if .passed then "✅" else "❌" end) + " **" + .name + "**" + (if .imageSize then " (" + ((.imageSize / 1000000) | floor | tostring) + "MB)" else "" end)' build-image-context-test-results.json >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

if [ "${{ steps.build-tests.outcome }}" = "success" ]; then
Expand All @@ -725,7 +725,7 @@ jobs:
echo "### ❌ Some Tests Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Failed test details:**" >> $GITHUB_STEP_SUMMARY
jq -r '.results[] | select(.passed == false) | "- **" + .name + "**: " + .message' build-image-test-results.json >> $GITHUB_STEP_SUMMARY
jq -r '.results[] | select(.passed == false) | "- **" + .name + "**: " + .message' build-image-context-test-results.json >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
Expand All @@ -746,8 +746,8 @@ jobs:
if: always() && runner.os == 'Linux'
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v4
with:
name: build-image-test-results-${{ matrix.os }}
path: build-image-test-results.json
name: build-image-context-test-results-${{ matrix.os }}
path: build-image-context-test-results.json
retention-days: 7

# Complete E2E Workflow Test - Tests entire containerization pipeline
Expand Down Expand Up @@ -831,7 +831,7 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Workflow Pipeline Tested" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "analyze-repo → generate-dockerfile → build-image → scan-image" >> $GITHUB_STEP_SUMMARY
echo "analyze-repo → generate-dockerfile → build-image-context → scan-image" >> $GITHUB_STEP_SUMMARY
echo " → tag-image → prepare-cluster → push-image → deploy → verify-deploy" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
Expand Down Expand Up @@ -873,7 +873,7 @@ jobs:
echo "## Tools Tested" >> $GITHUB_STEP_SUMMARY
echo "1. **analyze-repo** - Repository analysis" >> $GITHUB_STEP_SUMMARY
echo "2. **generate-dockerfile** - Dockerfile generation" >> $GITHUB_STEP_SUMMARY
echo "3. **build-image** - Docker image building" >> $GITHUB_STEP_SUMMARY
echo "3. **build-image-context** - Docker build command generation" >> $GITHUB_STEP_SUMMARY
echo "4. **scan-image** - Security vulnerability scanning" >> $GITHUB_STEP_SUMMARY
echo "5. **prepare-cluster** - Kubernetes cluster setup" >> $GITHUB_STEP_SUMMARY
echo "6. **tag-image** - Image tagging" >> $GITHUB_STEP_SUMMARY
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,16 @@ Restart VS Code to enable the MCP server in GitHub Copilot.
For direct tool usage without MCP protocol (e.g., VS Code extensions, programmatic access):

```typescript
import { analyzeRepo, buildImage, scanImage } from 'containerization-assist-mcp/sdk';
import { analyzeRepo, buildImageContext, scanImage } from 'containerization-assist-mcp/sdk';

// Simple function calls - no MCP server needed
const analysis = await analyzeRepo({ repositoryPath: './myapp' });
if (analysis.ok) {
console.log('Detected:', analysis.value.modules);
}

const build = await buildImage({ path: './myapp', imageName: 'myapp:v1' });
const buildContext = await buildImageContext({ path: './myapp', imageName: 'myapp:v1', platform: 'linux/amd64' });
// buildContext returns build commands for the agent to execute
const scan = await scanImage({ imageId: 'myapp:v1' });
```

Expand Down Expand Up @@ -212,7 +213,7 @@ The server provides 13 MCP tools organized by functionality:
### Image Operations
| Tool | Description |
|------|-------------|
| `build-image` | Build Docker images from Dockerfiles with security analysis |
| `build-image-context` | Prepare Docker build context with security analysis and return build commands |
| `scan-image` | Scan Docker images for security vulnerabilities with remediation guidance (uses Trivy CLI) |
| `tag-image` | Tag Docker images with version and registry information |
| `push-image` | Push Docker images to a registry |
Expand Down
6 changes: 3 additions & 3 deletions docs/adr/001-result-pattern.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ type Result<T, E = Error> =
| { ok: false; error: E };

// Usage example
async function buildImage(config: BuildConfig): Promise<Result<Image>> {
async function buildImageContext(config: BuildConfig): Promise<Result<BuildContext>> {
const docker = await createDockerClient();
if (!docker.ok) {
return Failure('Docker client unavailable', docker.error);
}

// ... build logic
return Success(image);
// ... prepare build context
return Success(buildContext);
}
```

Expand Down
12 changes: 6 additions & 6 deletions docs/adr/002-tool-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ interface Tool<TSchema extends z.ZodType<any>, TOut> {
) => Promise<Result<TOut>>;
}

// src/tools/build-image/tool.ts
const tool: Tool<typeof buildImageSchema, BuildImageResult> = {
name: 'build-image',
description: 'Build Docker image with progress tracking',
// src/tools/build-image-context/tool.ts
const tool: Tool<typeof buildImageContextSchema, BuildImageContextResult> = {
name: 'build-image-context',
description: 'Prepare Docker build context with build command',
version: '2.0.0',
schema: buildImageSchema,
schema: buildImageContextSchema,
run: async (input, ctx) => {
// Implementation
return Success(result);
Expand All @@ -43,7 +43,7 @@ export default tool;

```
src/tools/
├── build-image/
├── build-image-context/
│ ├── tool.ts # Tool implementation
│ ├── schema.ts # Zod schema
│ └── index.ts # Re-export
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/005-mcp-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function createMCPServer<TTool extends Tool>(

2. **Developer Experience**
- Natural language interface: "Build and scan my Java application"
- AI automatically routes to correct tools (analyze-repo → generate-dockerfile → build-image → scan-image)
- AI automatically routes to correct tools (analyze-repo → generate-dockerfile → build-image-context → scan-image)
- Real-time progress updates during long operations

3. **Discoverability**
Expand Down
18 changes: 9 additions & 9 deletions docs/adr/006-infrastructure-organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ src/
├── image-building/
│ ├── docker-client.ts
│ ├── generate-dockerfile.ts
│ ├── build-image.ts
│ ├── build-image-context.ts
│ └── scan-image.ts
└── deployment/
├── kubernetes-client.ts
Expand Down Expand Up @@ -282,7 +282,7 @@ src/
│ ├── tool-helpers.ts # Tool execution helpers
│ └── platform.ts # Platform detection
├── tools/ # MCP tools
│ ├── build-image/
│ ├── build-image-context/
│ │ ├── tool.ts # Uses @infra/docker + @lib/*
│ │ ├── schema.ts
│ │ └── index.ts
Expand Down Expand Up @@ -311,9 +311,9 @@ src/
}
```

### Example: Build Image Tool
### Example: Build Image Context Tool

**src/tools/build-image/tool.ts:**
**src/tools/build-image-context/tool.ts:**
```typescript
// Infrastructure imports
import { createDockerClient, type DockerBuildOptions } from '@infra/docker/client';
Expand All @@ -329,12 +329,12 @@ import type { ToolContext } from '@mcp/context';
import { type Result, Success, Failure } from '@types';

// Local imports
import { type BuildImageParams, buildImageSchema } from './schema';
import { type BuildImageContextParams, buildImageContextSchema } from './schema';

async function run(
input: BuildImageParams,
input: BuildImageContextParams,
ctx: ToolContext
): Promise<Result<BuildImageResult>> {
): Promise<Result<BuildImageContextResult>> {
// 1. Use @lib utilities for validation
const pathValidation = await validatePathOrFail(input.path);
if (!pathValidation.ok) return pathValidation;
Expand All @@ -346,7 +346,7 @@ async function run(
const docker = dockerResult.value;

// 3. Orchestrate infrastructure and utilities
const buildResult = await docker.buildImage({ ... });
const buildContext = await docker.prepareBuildContext({ ... });

return Success({ ... });
}
Expand Down Expand Up @@ -393,7 +393,7 @@ The architecture is enforced through:
- [CLAUDE.md](../../CLAUDE.md) - Path alias conventions and import guidelines
- [src/infra/docker/client.ts](../../src/infra/docker/client.ts) - Example infrastructure client
- [src/lib/validation-helpers.ts](../../src/lib/validation-helpers.ts) - Example pure utility
- [src/tools/build-image/tool.ts](../../src/tools/build-image/tool.ts) - Example tool orchestration
- [src/tools/build-image-context/tool.ts](../../src/tools/build-image-context/tool.ts) - Example tool orchestration
- [ADR-002: Unified Tool Interface](./002-tool-interface.md) - Related decision on tool structure

## Related Decisions
Expand Down
8 changes: 4 additions & 4 deletions docs/adr/007-sdk-decoupling.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ This decision complements, not replaces, ADR-005 (MCP Protocol Integration):
- Only pull in what you need

4. **Simpler Mental Model**
- SDK: `import { buildImage } from 'pkg/sdk'; await buildImage({...})`
- SDK: `import { buildImageContext } from 'pkg/sdk'; await buildImageContext({...})`
- MCP: Full server with protocol, transport, notifications
- Clear separation of concerns

Expand Down Expand Up @@ -220,14 +220,14 @@ See `docs/implementation-plans/sdk-decoupling-from-mcp-detailed.md` for step-by-
import {
analyzeRepo,
generateDockerfile,
buildImage,
buildImageContext,
scanImage,
// ... all 11 tools
} from 'containerization-assist-mcp/sdk';

// Simple function calls
const analysis = await analyzeRepo({ repositoryPath: './myapp' });
const build = await buildImage({ path: './myapp', imageName: 'myapp:v1' });
const buildCtx = await buildImageContext({ path: './myapp', imageName: 'myapp:v1' });

// With options
const result = await scanImage(
Expand All @@ -240,7 +240,7 @@ const result = await scanImage(

// Advanced: direct tool access
import { tools, executeTool } from 'containerization-assist-mcp/sdk';
const result = await executeTool(tools.buildImage, params, options);
const result = await executeTool(tools.buildImageContext, params, options);
```

## Related Decisions
Expand Down
25 changes: 12 additions & 13 deletions docs/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,27 @@ import { createToolHandler } from 'containerization-assist';

// Using a literal tool name gives you fully-typed callbacks!
server.tool(
'build-image',
buildImageTool.description,
buildImageTool.inputSchema,
createToolHandler(app, 'build-image', {
'build-image-context',
buildImageContextTool.description,
buildImageContextTool.inputSchema,
createToolHandler(app, 'build-image-context', {
onSuccess: (result, toolName, params) => {
// ✅ result is typed as BuildImageResult
console.log(`Built: ${result.imageId}, size: ${result.size} bytes`);
// ✅ result is typed as BuildImageContextResult
console.log(`Build command: ${result.nextAction.buildCommand.command}`);

// ✅ params is typed as BuildImageInput
// ✅ params is typed as BuildImageContextInput
console.log(`Image name: ${params.imageName}`);

// ✅ Full IntelliSense support!
telemetry.track({
tool: toolName,
imageSize: result.size,
buildTime: result.buildTime,
tags: result.tags
imageName: params.imageName,
contextPath: params.path
});
},
onError: (error, toolName, params) => {
// ✅ params is also typed in error handler
console.error(`Failed to build ${params.imageName}`);
console.error(`Failed to prepare build for ${params.imageName}`);
}
})
);
Expand Down Expand Up @@ -196,7 +195,7 @@ import {
analyzeRepoTool, // Repository analysis and framework detection
generateDockerfileTool, // AI-powered Dockerfile generation
fixDockerfileTool, // Fix and optimize existing Dockerfiles
buildImageTool, // Docker image building with progress
buildImageContextTool, // Docker build context provider (returns command)
scanImageTool, // Security vulnerability scanning
tagImageTool, // Docker image tagging
pushImageTool, // Push images to registry
Expand All @@ -214,7 +213,7 @@ Use these string names when defining aliases:
- `'analyze-repo'` - Repository analysis
- `'generate-dockerfile'` - Dockerfile generation
- `'fix-dockerfile'` - Dockerfile fixes
- `'build-image'` - Docker build
- `'build-image-context'` - Docker build context provider
- `'scan-image'` - Security scanning
- `'tag-image'` - Image tagging
- `'push-image'` - Registry push
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/policy-example/PLATFORM_AND_TAG_POLICY_USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ All 11 tests pass:
2. Tags are applied when running `docker build -t myimage:demo`
3. The LABEL serves as documentation and policy enforcement

When using the `build-image` tool, make sure to specify the tag:
When using the `build-image-context` tool, make sure to specify the tag:

```bash
# The build-image tool should tag the image as "demo"
# The build-image-context tool should tag the image as "demo"
# Policy ensures the Dockerfile has LABEL tag="demo" for consistency
```

Expand Down
Loading
Loading