Refactor config-writer directory provisioning into a shared ensureDirectory helper#3696
Conversation
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Smoke Test Results✅ GitHub MCP — PR #3689: fix(api-proxy): generalize deprecated header stripping for any provider/header Status: PASS
|
There was a problem hiding this comment.
Pull request overview
This PR refactors src/config-writer.ts to centralize directory provisioning/permission logic into a shared ensureDirectory helper, aiming to preserve existing security-sensitive behaviors (ownership changes, chmod fallbacks, and existing-directory handling) while reducing duplicated code.
Changes:
- Introduces
ensureDirectory(dirPath, options)with hooks for create/exist/after-ensure behavior. - Replaces repeated directory setup blocks for workDir and multiple log/state directories with
ensureDirectorycalls. - Extends unit tests to cover squid
chown-failure fallback behavior and MCP logs permission correction.
Show a summary per file
| File | Description |
|---|---|
src/config-writer.ts |
Adds ensureDirectory helper and updates directory creation/permission logic to use it. |
src/config-writer.test.ts |
Adds/adjusts tests around directory setup behaviors (squid fallback + MCP log perms). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 3
| function ensureDirectory(dirPath: string, options: EnsureDirectoryOptions = {}): boolean { | ||
| const { mode, onCreate, onExists, onAfterEnsure } = options; | ||
| const created = !fs.existsSync(dirPath); | ||
|
|
||
| if (created) { | ||
| fs.mkdirSync(dirPath, mode === undefined ? { recursive: true } : { recursive: true, mode }); | ||
| onCreate?.(); | ||
| } else { | ||
| onExists?.(); | ||
| } |
| // Clean up tempDir and the chroot-home sibling directory that writeConfigs creates. | ||
| fs.rmSync(tempDir, { recursive: true, force: true }); | ||
| fs.rmSync(`${tempDir}-chroot-home`, { recursive: true, force: true }); | ||
| fs.rmSync('/tmp/gh-aw/mcp-logs', { recursive: true, force: true }); |
| (fs.chownSync as unknown as jest.Mock).mockImplementation((targetPath: fs.PathLike) => { | ||
| if (String(targetPath) === proxyLogsDir) { | ||
| throw new Error('chown failed'); | ||
| } | ||
| }); | ||
|
|
||
| await writeConfigs({ | ||
| workDir: tempDir, | ||
| sslBump: false, | ||
| allowedDomains: [], | ||
| agentCommand: 'echo test', | ||
| logLevel: 'info', | ||
| keepContainers: false, | ||
| buildLocal: false, | ||
| imageRegistry: 'ghcr.io/github/gh-aw-firewall', | ||
| imageTag: 'latest', | ||
| proxyLogsDir, | ||
| }); | ||
|
|
||
| const squidLogsDirMode = fs.statSync(proxyLogsDir).mode & 0o777; | ||
| expect(squidLogsDirMode).toBe(0o777); |
This comment has been minimized.
This comment has been minimized.
|
@copilot address review feedback |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Addressed in commit 3682f20. Implemented the review feedback by:
Also added a targeted test for symlink rejection and re-ran lint/build/targeted tests plus CodeQL (no alerts). |
Smoke Test Results✅ GitHub API (2 PR entries) Result: PASS
|
Smoke Test Results: BYOK Offline Mode✅ GitHub MCP: Retrieved PR #3704 ("Reduce Documentation Maintainer workflow prompt/tool overhead") Mode: COPILOT_OFFLINE=true (BYOK) via api-proxy sidecar Status:
|
|
Smoke Test Codex: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "registry.npmjs.org"See Network Configuration for more information.
|
Service Connectivity Test Results ❌Status: FAIL — Services unreachable from AWF sandbox
Neither service container is reachable via
|
Chroot Runtime Version ComparisonTested runtime versions between host and chroot environments:
Result: Chroot environment has different versions for Python and Node.js. Only Go matches between host and chroot. Full version stringsHost:
Chroot:
|
🏗️ Build Test Suite ResultsAll ecosystems tested successfully! ✅
Overall: 8/8 ecosystems passed — ✅ PASS Test Details
|
|
Gemini Smoke Test: FAIL (Connectivity 400, MCP missing) Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
src/config-writer.tsrepeated security-sensitive directory creation/permission logic across multiple paths, with small behavioral differences (ownership, chmod fallback, existing-dir handling). This change consolidates that logic into one helper while preserving each call site’s semantics.What changed
ensureDirectory(dirPath, options)to centralize:existsSync+mkdirSync)onCreate)onExists)onAfterEnsure)workDiragent-logsagent-session-statesquid-logsapi-proxy-logscli-proxy-logs/tmp/gh-aw/mcp-logsBehavior preserved (critical paths)
chownattempts for agent/session directories (with non-root-safe swallow behavior).chownto proxy UID/GID withchmod 0o777fallback on chown failure.0o777when directory already exists.Targeted test coverage updates
chown-failure fallback mode behavior.0o777.