Skip to content

feat(docker): pre-seed Maven/Gradle/sbt proxy config in agent container#991

Merged
Mossaka merged 2 commits intomainfrom
jvm-proxy-config
Feb 24, 2026
Merged

feat(docker): pre-seed Maven/Gradle/sbt proxy config in agent container#991
Mossaka merged 2 commits intomainfrom
jvm-proxy-config

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Feb 21, 2026

Summary

  • Pre-seed Maven, Gradle, and sbt proxy configuration in the agent container entrypoint
  • Java build tools do not honor HTTP_PROXY/HTTPS_PROXY env vars

Changes

  • ~/.m2/settings.xml — Maven proxy pointing to Squid proxy
  • ~/.gradle/gradle.properties — Gradle system proxy properties
  • JAVA_TOOL_OPTIONS — JVM proxy flags for sbt and generic Java tools

Key implementation details:

  • Proxy host/port extracted from HTTP_PROXY env var (supports randomized subnets)
  • Chroot-aware paths (writes to /host$HOME/ in chroot mode, $HOME/ otherwise)
  • Files owned by awfuser for correct permissions

Impact

From the AWF build/test experiment v4 (173 repos, 19 languages):

  • Java: 3/13 → expected 9+/13 builds (agent had to discover proxy manually)
  • Kotlin: 0/5 → expected 3+/5 builds
  • Clojure: 0/3 → expected 2+/3 builds
  • Scala: 0/5 → expected 3+/5 builds

The 3 Java repos that succeeded (gson, jackson-databind, HikariCP) did so because the Copilot agent independently discovered Maven proxy settings. Making this automatic eliminates the inconsistency.

Test plan

  • Java Maven project builds (e.g., gson)
  • Java Gradle project builds (e.g., caffeine)
  • Proxy config files exist in the container at startup
  • Non-Java workflows unaffected

🤖 Generated with Claude Code

Java build tools do not honor HTTP_PROXY/HTTPS_PROXY env vars and need
explicit proxy configuration. Pre-seed these files in the container
entrypoint so JVM-based builds work automatically:

- ~/.m2/settings.xml (Maven proxy)
- ~/.gradle/gradle.properties (Gradle proxy)
- JAVA_TOOL_OPTIONS with proxy JVM flags (sbt/generic Java)

This unblocks Java, Kotlin, Clojure, and Scala builds without requiring
the agent to discover the proxy configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 21, 2026 01:01
@github-actions
Copy link
Contributor

github-actions bot commented Feb 21, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 82.30% 82.45% 📈 +0.15%
Statements 82.23% 82.37% 📈 +0.14%
Functions 82.74% 82.74% ➡️ +0.00%
Branches 74.46% 74.55% 📈 +0.09%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 83.2% → 83.8% (+0.55%) 82.5% → 83.0% (+0.54%)

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

This PR aims to improve Java ecosystem build reliability inside the AWF agent container by automatically pre-seeding proxy configuration for common JVM build tools that don’t consistently honor HTTP_PROXY/HTTPS_PROXY.

Changes:

  • Create ~/.m2/settings.xml with Maven proxy settings during agent container startup.
  • Create ~/.gradle/gradle.properties with Gradle proxy settings during agent container startup.
  • Append JVM proxy -D flags to JAVA_TOOL_OPTIONS for sbt and other JVM tools.
Comments suppressed due to low confidence (1)

containers/agent/entrypoint.sh:215

  • This overwrites ~/.gradle/gradle.properties unconditionally, which may clobber existing Gradle configuration (e.g., org.gradle.jvmargs, build cache settings, private repo credentials). Safer options are: only create if missing, or append/update just the proxy-related systemProp keys when they aren't already set.
  # Gradle proxy config (~/.gradle/gradle.properties)
  mkdir -p "${JVM_HOME_PREFIX}/.gradle"
  cat > "${JVM_HOME_PREFIX}/.gradle/gradle.properties" << GRADLE_EOF
systemProp.http.proxyHost=${PROXY_HOST}
systemProp.http.proxyPort=${PROXY_PORT}
systemProp.https.proxyHost=${PROXY_HOST}
systemProp.https.proxyPort=${PROXY_PORT}
GRADLE_EOF

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

Comment on lines 169 to 173
# Extract proxy host and port from HTTP_PROXY (format: http://IP:PORT)
PROXY_HOST="${HTTP_PROXY#http://}"
PROXY_HOST="${PROXY_HOST%:*}"
PROXY_PORT="${SQUID_PROXY_PORT:-3128}"

Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

The proxy host extraction from HTTP_PROXY is brittle (doesn't handle https:// scheme, credentials like user:pass@, IPv6, or paths) and ignores the actual port embedded in HTTP_PROXY. Since the agent env already provides SQUID_PROXY_HOST/SQUID_PROXY_PORT, prefer using those directly (or parse HTTP_PROXY more robustly) so the generated configs always point at the intended proxy.

Suggested change
# Extract proxy host and port from HTTP_PROXY (format: http://IP:PORT)
PROXY_HOST="${HTTP_PROXY#http://}"
PROXY_HOST="${PROXY_HOST%:*}"
PROXY_PORT="${SQUID_PROXY_PORT:-3128}"
# Determine proxy host and port for JVM tools.
# Prefer SQUID_PROXY_HOST/SQUID_PROXY_PORT if provided; otherwise, parse HTTP_PROXY robustly.
if [ -n "$SQUID_PROXY_HOST" ] && [ -n "$SQUID_PROXY_PORT" ]; then
PROXY_HOST="$SQUID_PROXY_HOST"
PROXY_PORT="$SQUID_PROXY_PORT"
else
PROXY_INFO="$(python3 - << 'PYEOF'
import os, sys
from urllib.parse import urlparse
url = os.environ.get("HTTP_PROXY") or os.environ.get("http_proxy")
if not url:
sys.exit(1)
if "://" not in url:
url = "http://" + url
parsed = urlparse(url)
host = parsed.hostname or ""
port = parsed.port or 3128
if not host:
sys.exit(1)
print(f"{host}:{port}")
PYEOF
)" || PROXY_INFO=""
PROXY_HOST="${PROXY_INFO%:*}"
PROXY_PORT="${PROXY_INFO##*:}"
fi

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Addressed. Now preferring SQUID_PROXY_HOST/SQUID_PROXY_PORT directly (set by docker-manager.ts), with a more robust fallback parser that handles https://, credentials (user:pass@), and defaults the port. Avoided the Python approach to keep the entrypoint dependency-free.

Comment on lines 183 to 186
# Maven proxy config (~/.m2/settings.xml)
mkdir -p "${JVM_HOME_PREFIX}/.m2"
cat > "${JVM_HOME_PREFIX}/.m2/settings.xml" << MAVEN_EOF
<settings>
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This always overwrites ~/.m2/settings.xml on container start, which can destroy user/workflow-provided Maven settings (mirrors, repositories, auth, profiles). Consider creating the file only if it doesn't exist, or updating it in a way that preserves existing settings while ensuring the awf proxy entries are present.

This issue also appears on line 208 of the same file.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Addressed. Both Maven settings.xml and Gradle gradle.properties are now only created if the file does not already exist (if [ ! -f ... ]), preserving any user-provided configuration (mirrors, repositories, auth, profiles, jvmargs, etc.).

Comment on lines 221 to 222
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dhttp.proxyHost=${PROXY_HOST} -Dhttp.proxyPort=${PROXY_PORT} -Dhttps.proxyHost=${PROXY_HOST} -Dhttps.proxyPort=${PROXY_PORT}"
echo "[entrypoint] ✓ Set JAVA_TOOL_OPTIONS with proxy flags"
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

JAVA_TOOL_OPTIONS sets JVM proxy properties but doesn't set http.nonProxyHosts/https.nonProxyHosts, so JVM tools may attempt to proxy localhost/127.0.0.1 (and other bypass targets listed in NO_PROXY), which can break tests that talk to local services. Consider deriving Java nonProxyHosts from the existing NO_PROXY/no_proxy env (converting comma-separated hosts into Java's '|' pattern) and including it here.

Suggested change
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dhttp.proxyHost=${PROXY_HOST} -Dhttp.proxyPort=${PROXY_PORT} -Dhttps.proxyHost=${PROXY_HOST} -Dhttps.proxyPort=${PROXY_PORT}"
echo "[entrypoint] ✓ Set JAVA_TOOL_OPTIONS with proxy flags"
NON_PROXY_RAW="${NO_PROXY:-${no_proxy}}"
if [ -n "$NON_PROXY_RAW" ]; then
# Convert comma-separated NO_PROXY to Java's '|' separated nonProxyHosts format
NON_PROXY_HOSTS=$(printf '%s' "$NON_PROXY_RAW" | tr ',' '|' | tr -d ' ')
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dhttp.proxyHost=${PROXY_HOST} -Dhttp.proxyPort=${PROXY_PORT} -Dhttps.proxyHost=${PROXY_HOST} -Dhttps.proxyPort=${PROXY_PORT} -Dhttp.nonProxyHosts=${NON_PROXY_HOSTS} -Dhttps.nonProxyHosts=${NON_PROXY_HOSTS}"
echo "[entrypoint] ✓ Set JAVA_TOOL_OPTIONS with proxy and nonProxyHosts flags"
else
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-} -Dhttp.proxyHost=${PROXY_HOST} -Dhttp.proxyPort=${PROXY_PORT} -Dhttps.proxyHost=${PROXY_HOST} -Dhttps.proxyPort=${PROXY_PORT}"
echo "[entrypoint] ✓ Set JAVA_TOOL_OPTIONS with proxy flags"
fi

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Addressed. Now reading NO_PROXY/no_proxy env var, converting the comma-separated list to Java's pipe-separated nonProxyHosts format, and including both -Dhttp.nonProxyHosts and -Dhttps.nonProxyHosts in JAVA_TOOL_OPTIONS. This prevents JVM tools from proxying localhost, 127.0.0.1, and the other bypass targets set by docker-manager.ts.

@github-actions
Copy link
Contributor

🦀 Rust Build Test Results

Project Build Tests Status
fd 1/1 PASS
zoxide 1/1 PASS

Overall: ✅ PASS

Generated by Build Test Rust for issue #991

@github-actions
Copy link
Contributor

Deno Build Test Results

Project Tests Status
oak 1/1 ✅ PASS
std 1/1 ✅ PASS

Overall: ✅ PASS

Test output

oak:

running 1 test from ./test.ts
oak test ... ok (0ms)
ok | 1 passed | 0 failed (2ms)
````

**std:**
````
running 1 test from ./test.ts
std test ... ok (0ms)
ok | 1 passed | 0 failed (2ms)

Generated by Build Test Deno for issue #991

@github-actions
Copy link
Contributor

🤖 Smoke test results for @Mossaka

✅ GitHub MCP — Last 2 merged PRs: #981 "docs: add releasing.md link to CLAUDE.md", #977 "fix: add iptables bypass for container self-traffic"
✅ Playwright — github.com title contains "GitHub"
✅ File write — /tmp/gh-aw/agent/smoke-test-copilot-22247167198.txt created
✅ Bash — file read back successfully

Overall: PASS

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

@github-actions
Copy link
Contributor

Go Build Test Results

Project Download Tests Status
color 1/1 PASS
env 1/1 PASS
uuid 1/1 PASS

Overall: PASS

Generated by Build Test Go for issue #991

@github-actions
Copy link
Contributor

.NET Build Test Results

Project Restore Build Run Status
hello-world PASS
json-parse PASS

Overall: PASS

Run output

hello-world: Hello, World!

json-parse:

{
  "Name": "AWF Test",
  "Version": 1,
  "Success": true
}
Name: AWF Test, Success: True

Generated by Build Test .NET for issue #991

@github-actions
Copy link
Contributor

Smoke Test Results

Overall: PASS

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

@github-actions
Copy link
Contributor

Bun Build Test Results

Project Install Tests Status
elysia 1/1 PASS
hono 1/1 PASS

Overall: PASS

Tested with Bun v1.3.9

Generated by Build Test Bun for issue #991

@github-actions
Copy link
Contributor

C++ Build Test Results

Project CMake Build Status
fmt PASS
json PASS

Overall: PASS

Generated by Build Test C++ for issue #991

@github-actions
Copy link
Contributor

PR titles:
Pre-seed Maven/Gradle/sbt proxy config in agent container
chore(deps): bump the all-github-actions group across 1 directory with 12 updates
GitHub MCP merged PRs: ✅ | safeinputs-gh PR list: ✅
Playwright title: ✅ | Tavily search: ❌
File write: ✅ | Bash cat verify: ✅
Discussion comment: ✅ | Build (npm ci && npm run build): ✅
Overall status: FAIL

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

@github-actions
Copy link
Contributor

Java Build Test Results

Project Compile Tests Status
gson 1/1 PASS
caffeine 1/1 PASS

Overall: PASS

Generated by Build Test Java for issue #991

@github-actions
Copy link
Contributor

Node.js Build Test Results

Project Install Tests Status
clsx All passed ✅ PASS
execa All passed ✅ PASS
p-limit All passed ✅ PASS

Overall: ✅ PASS

Generated by Build Test Node.js for issue #991

@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.13.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Result: Some versions differ between host and chroot. Go matches, but Python and Node.js versions differ. The chroot environment uses the system-installed versions from the Ubuntu image, while the host runner has newer versions.

Tested by Smoke Chroot for issue #991

- Use SQUID_PROXY_HOST/SQUID_PROXY_PORT directly instead of brittle HTTP_PROXY
  parsing; keep improved fallback that handles https://, credentials, and IPv6
- Only create Maven settings.xml and Gradle gradle.properties if they don't
  already exist, to avoid clobbering user-provided configuration
- Derive Java nonProxyHosts from NO_PROXY env var (comma-to-pipe conversion)
  so JVM tools don't attempt to proxy localhost/127.0.0.1 traffic

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka
Copy link
Collaborator Author

Mossaka commented Feb 24, 2026

Addressed all review comments in commit 2d8ac64. Changes:

  1. Robust proxy host/port extraction -- Now uses SQUID_PROXY_HOST/SQUID_PROXY_PORT directly (already set by docker-manager.ts), with a fallback parser that handles https://, credentials, and IPv6. Kept it pure bash (no Python dependency).

  2. No-clobber for Maven and Gradle configs -- Both ~/.m2/settings.xml and ~/.gradle/gradle.properties are now only created if they don't already exist, preserving user-provided configuration (mirrors, repos, auth, profiles, jvmargs, build cache settings, etc.).

  3. Java nonProxyHosts from NO_PROXY -- Reads NO_PROXY/no_proxy env var, converts comma-separated hosts to Java's pipe-separated format, and adds -Dhttp.nonProxyHosts / -Dhttps.nonProxyHosts to JAVA_TOOL_OPTIONS. This prevents JVM tools from proxying localhost/127.0.0.1 traffic that could break tests talking to local services.

All unit tests pass (795/795). No TypeScript changes in this commit (entrypoint.sh only).

@Mossaka Mossaka changed the title Pre-seed Maven/Gradle/sbt proxy config in agent container feat(docker): pre-seed Maven/Gradle/sbt proxy config in agent container Feb 24, 2026
@github-actions
Copy link
Contributor

Rust Build Test Results

Project Build Tests Status
fd 1/1 PASS
zoxide 1/1 PASS

Overall: ✅ PASS

Generated by Build Test Rust for issue #991

@github-actions
Copy link
Contributor

Build Test: Bun ✅

Project Install Tests Status
elysia 1/1 PASS
hono 1/1 PASS

Overall: PASS

Bun version: 1.3.9

Generated by Build Test Bun for issue #991

@github-actions
Copy link
Contributor

Build Test: Node.js ✅

Project Install Tests Status
clsx All passed PASS
execa All passed PASS
p-limit All passed PASS

Overall: PASS

Generated by Build Test Node.js for issue #991

@github-actions
Copy link
Contributor

Build Test: Deno Results

Project Tests Status
oak 1/1 ✅ PASS
std 1/1 ✅ PASS

Overall: ✅ PASS

Generated by Build Test Deno for issue #991

@github-actions
Copy link
Contributor

Merged PRs: docs: update runner and architecture compatibility; chore: remove _codeql_detected_source_root

  1. GitHub MCP merged PRs ✅
  2. safeinputs-gh pr list ✅
  3. Playwright title check ✅
  4. Tavily web search ❌ (tool unavailable)
  5. File write + cat ✅
  6. Bash tool verification ✅
  7. Discussion query + comment ✅
  8. npm ci && npm run build ✅
    Overall status: FAIL

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

@github-actions
Copy link
Contributor

Smoke Test Results

✅ GitHub MCP: #992 docs: update runner and architecture compatibility, #980 chore(deps): bump the all-github-actions group
✅ Playwright: Page title contains "GitHub"
✅ File write: /tmp/gh-aw/agent/smoke-test-claude-22333554473.txt created
✅ Bash verify: File contents confirmed

Overall: PASS

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

@github-actions
Copy link
Contributor

.NET Build Test Results

Project Restore Build Run Status
hello-world PASS
json-parse PASS

Overall: PASS

Run Output

hello-world:

Hello, World!
````

**json-parse:**
````
{
  "Name": "AWF Test",
  "Version": 1,
  "Success": true
}
Name: AWF Test, Success: True

Generated by Build Test .NET for issue #991

@github-actions
Copy link
Contributor

C++ Build Test Results

Project CMake Build Status
fmt PASS
json PASS

Overall: PASS

Generated by Build Test C++ for issue #991

@github-actions
Copy link
Contributor

Go Build Test Results

Project Download Tests Status
color 1/1 PASS
env 1/1 PASS
uuid 1/1 PASS

Overall: ✅ PASS

Generated by Build Test Go for issue #991

@github-actions
Copy link
Contributor

Java Build Test Results

Project Compile Tests Status
gson 1/1 PASS
caffeine 1/1 PASS

Overall: PASS

Generated by Build Test Java for issue #991

@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.13.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

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

Tested by Smoke Chroot for issue #991

@github-actions
Copy link
Contributor

Smoke Test Results — Copilot Engine

Test Result
GitHub MCP (last 2 merged PRs) #992 "docs: update runner and architecture compatibility", #981 "docs: add releasing.md link to CLAUDE.md"
Playwright (github.com title) ❌ Timeout (network blocked)
File write + read /tmp/gh-aw/agent/smoke-test-copilot-22333554485.txt
Bash verification

Overall: PASS (1 expected ❌ — Playwright blocked by firewall)

PR author: @Mossaka | No assignees

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

@Mossaka Mossaka merged commit 5f89cff into main Feb 24, 2026
98 of 100 checks passed
@Mossaka Mossaka deleted the jvm-proxy-config branch February 24, 2026 18:27
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.

2 participants