-
Notifications
You must be signed in to change notification settings - Fork 19
feat(cli): add --memory-limit flag for configurable container memory #1243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -422,6 +422,23 @@ export function validateAllowHostPorts( | |
| return { valid: true }; | ||
| } | ||
|
|
||
| /** | ||
| * Parses and validates a Docker memory limit string. | ||
| * Valid formats: positive integer followed by b, k, m, or g (e.g., "2g", "512m", "4g"). | ||
| */ | ||
| export function parseMemoryLimit(input: string): { value: string; error?: undefined } | { value?: undefined; error: string } { | ||
| const pattern = /^(\d+)([bkmg])$/i; | ||
| const match = input.match(pattern); | ||
| if (!match) { | ||
| return { error: `Invalid --memory-limit value "${input}". Expected format: <number><unit> (e.g., 2g, 512m, 4g)` }; | ||
| } | ||
| const num = parseInt(match[1], 10); | ||
| if (num <= 0) { | ||
| return { error: `Invalid --memory-limit value "${input}". Memory limit must be a positive number.` }; | ||
| } | ||
| return { value: input.toLowerCase() }; | ||
| } | ||
|
|
||
| /** | ||
| * Parses and validates DNS servers from a comma-separated string | ||
| * @param input - Comma-separated DNS server string (e.g., "8.8.8.8,1.1.1.1") | ||
|
|
@@ -780,6 +797,11 @@ program | |
| '--container-workdir <dir>', | ||
| 'Working directory inside the container (should match GITHUB_WORKSPACE for path consistency)' | ||
| ) | ||
| .option( | ||
| '--memory-limit <limit>', | ||
| 'Memory limit for the agent container (e.g., 1g, 2g, 4g, 512m). Default: 2g', | ||
| '2g' | ||
| ) | ||
|
Comment on lines
+800
to
+804
|
||
| .option( | ||
| '--dns-servers <servers>', | ||
| 'Comma-separated list of trusted DNS servers. DNS traffic is ONLY allowed to these servers (default: 8.8.8.8,8.8.4.4)', | ||
|
|
@@ -1067,6 +1089,13 @@ program | |
| logger.warn('⚠️ SSL Bump intercepts HTTPS traffic. Only use for trusted workloads.'); | ||
| } | ||
|
|
||
| // Validate memory limit | ||
| const memoryLimit = parseMemoryLimit(options.memoryLimit); | ||
| if (memoryLimit.error) { | ||
| logger.error(memoryLimit.error); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // Validate agent image option | ||
| const agentImageResult = processAgentImageOption(options.agentImage, options.buildLocal); | ||
| if (agentImageResult.error) { | ||
|
|
@@ -1096,6 +1125,7 @@ program | |
| volumeMounts, | ||
| containerWorkDir: options.containerWorkdir, | ||
| dnsServers, | ||
| memoryLimit: memoryLimit.value, | ||
| proxyLogsDir: options.proxyLogsDir, | ||
| enableHostAccess: options.enableHostAccess, | ||
| allowHostPorts: options.allowHostPorts, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -912,8 +912,8 @@ export function generateDockerCompose( | |
| 'apparmor:unconfined', | ||
| ], | ||
| // Resource limits to prevent DoS attacks (conservative defaults) | ||
| mem_limit: '4g', // 4GB memory limit | ||
| memswap_limit: '4g', // No swap (same as mem_limit) | ||
| mem_limit: config.memoryLimit || '2g', | ||
| memswap_limit: config.memoryLimit || '2g', // No swap (same as mem_limit) | ||
|
Comment on lines
+915
to
+916
|
||
| pids_limit: 1000, // Max 1000 processes | ||
| cpu_shares: 1024, // Default CPU share | ||
| stdin_open: true, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parseMemoryLimit matches the input string as-is; unlike other parsers in this file (e.g., DNS parsing), it doesn’t trim whitespace first. This causes values like "2g " (or values copied with trailing whitespace) to be rejected even though they’re otherwise valid. Consider normalizing with input.trim() (and returning the normalized value) before applying the regex.