Skip to content

Commit e2558f0

Browse files
authored
Merge 9dd8d9a into 94c7c10
2 parents 94c7c10 + 9dd8d9a commit e2558f0

8 files changed

Lines changed: 514 additions & 518 deletions

File tree

.github/workflows/smoke-codex.lock.yml

Lines changed: 415 additions & 507 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/smoke-codex.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ tools:
3232
edit:
3333
bash:
3434
- "*"
35-
sandbox:
36-
mcp:
37-
container: "ghcr.io/github/gh-aw-mcpg"
3835
safe-outputs:
3936
add-comment:
4037
hide-older-comments: true

docs-site/src/content/docs/reference/cli-reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ awf [options] -- <command>
3535
| `--skip-pull` | flag | `false` | Use local images without pulling from registry |
3636
| `-e, --env <KEY=VALUE>` | string | `[]` | Environment variable (repeatable) |
3737
| `--env-all` | flag | `false` | Pass all host environment variables |
38+
| `--exclude-env <name>` | string | `[]` | Exclude a variable from `--env-all` passthrough (repeatable) |
3839
| `-v, --mount <host:container[:mode]>` | string | `[]` | Volume mount (repeatable) |
3940
| `--container-workdir <dir>` | string | User home | Working directory inside container |
4041
| `--dns-servers <servers>` | string | `8.8.8.8,8.8.4.4` | Trusted DNS servers (comma-separated) |

scripts/ci/postprocess-smoke-workflows.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const workflowPaths = [
3838
// - "Install awf binary" or "Install AWF binary" step at any indent level
3939
// - run command invoking install_awf_binary.sh with a version
4040
const installStepRegex =
41-
/^(\s*)- name: Install [Aa][Ww][Ff] binary\n\1\s*run: bash \/opt\/gh-aw\/actions\/install_awf_binary\.sh v[0-9.]+\n/m;
41+
/^(\s*)- name: Install [Aa][Ww][Ff] binary\n\1\s*run: bash (?:\/opt\/gh-aw|\$\{RUNNER_TEMP\}\/gh-aw)\/actions\/install_awf_binary\.sh v[0-9.]+\n/m;
4242
const installStepRegexGlobal = new RegExp(installStepRegex.source, 'gm');
4343

4444
function buildLocalInstallSteps(indent: string): string {
@@ -102,18 +102,12 @@ for (const workflowPath of workflowPaths) {
102102
// Replace "Install awf binary" step with local build steps
103103
const matches = content.match(installStepRegexGlobal);
104104
if (matches) {
105-
if (matches.length !== 1) {
106-
throw new Error(
107-
`Expected exactly one awf install step in ${workflowPath}, found ${matches.length}. ` +
108-
'Ensure the workflow has a single "Install awf binary" step in the agent job.'
109-
);
110-
}
111105
content = content.replace(
112106
installStepRegexGlobal,
113107
(_match, indent: string) => buildLocalInstallSteps(indent)
114108
);
115109
modified = true;
116-
console.log(` Replaced awf install step with local build`);
110+
console.log(` Replaced ${matches.length} awf install step(s) with local build`);
117111
}
118112

119113
// Remove sparse-checkout from agent job checkout (need full repo for npm build)

src/cli.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,12 @@ program
12701270
'Pass all host environment variables to container (excludes system vars like PATH)',
12711271
false
12721272
)
1273+
.option(
1274+
'--exclude-env <name>',
1275+
'Exclude a specific environment variable from --env-all passthrough (repeatable)',
1276+
(value: string, previous: string[] = []) => [...previous, value],
1277+
[]
1278+
)
12731279
.option(
12741280
'--env-file <path>',
12751281
'Read environment variables from a file (KEY=VALUE format, one per line)'
@@ -1706,6 +1712,7 @@ program
17061712
imageTag: options.imageTag,
17071713
additionalEnv: Object.keys(additionalEnv).length > 0 ? additionalEnv : undefined,
17081714
envAll: options.envAll,
1715+
excludeEnv: options.excludeEnv && options.excludeEnv.length > 0 ? options.excludeEnv : undefined,
17091716
envFile: options.envFile,
17101717
volumeMounts,
17111718
containerWorkDir: options.containerWorkdir,

src/docker-manager.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,77 @@ describe('docker-manager', () => {
12951295
}
12961296
});
12971297

1298+
it('should exclude specified variables when excludeEnv is set with envAll', () => {
1299+
process.env.CUSTOM_HOST_VAR = 'test_value';
1300+
process.env.SECRET_TOKEN = 'super-secret';
1301+
1302+
try {
1303+
const configWithExcludeEnv = { ...mockConfig, envAll: true, excludeEnv: ['SECRET_TOKEN'] };
1304+
const result = generateDockerCompose(configWithExcludeEnv, mockNetworkConfig);
1305+
const env = result.services.agent.environment as Record<string, string>;
1306+
1307+
// Should pass through non-excluded vars
1308+
expect(env.CUSTOM_HOST_VAR).toBe('test_value');
1309+
// Should NOT pass through excluded var
1310+
expect(env.SECRET_TOKEN).toBeUndefined();
1311+
} finally {
1312+
delete process.env.CUSTOM_HOST_VAR;
1313+
delete process.env.SECRET_TOKEN;
1314+
}
1315+
});
1316+
1317+
it('should exclude multiple variables when excludeEnv contains multiple names', () => {
1318+
process.env.TOKEN_A = 'value-a';
1319+
process.env.TOKEN_B = 'value-b';
1320+
process.env.SAFE_VAR = 'safe';
1321+
1322+
try {
1323+
const configWithExcludeEnv = { ...mockConfig, envAll: true, excludeEnv: ['TOKEN_A', 'TOKEN_B'] };
1324+
const result = generateDockerCompose(configWithExcludeEnv, mockNetworkConfig);
1325+
const env = result.services.agent.environment as Record<string, string>;
1326+
1327+
expect(env.TOKEN_A).toBeUndefined();
1328+
expect(env.TOKEN_B).toBeUndefined();
1329+
expect(env.SAFE_VAR).toBe('safe');
1330+
} finally {
1331+
delete process.env.TOKEN_A;
1332+
delete process.env.TOKEN_B;
1333+
delete process.env.SAFE_VAR;
1334+
}
1335+
});
1336+
1337+
it('should have no effect when excludeEnv is set but envAll is false', () => {
1338+
process.env.SECRET_TOKEN = 'super-secret';
1339+
1340+
try {
1341+
const configWithExcludeEnv = { ...mockConfig, envAll: false, excludeEnv: ['SECRET_TOKEN'] };
1342+
const result = generateDockerCompose(configWithExcludeEnv, mockNetworkConfig);
1343+
const env = result.services.agent.environment as Record<string, string>;
1344+
1345+
// envAll is false so SECRET_TOKEN was never going to be injected anyway
1346+
expect(env.SECRET_TOKEN).toBeUndefined();
1347+
} finally {
1348+
delete process.env.SECRET_TOKEN;
1349+
}
1350+
});
1351+
1352+
it('should exclude GITHUB_TOKEN from env-all passthrough when specified in excludeEnv', () => {
1353+
const prevToken = process.env.GITHUB_TOKEN;
1354+
process.env.GITHUB_TOKEN = 'ghp_test_token';
1355+
1356+
try {
1357+
const configWithExcludeEnv = { ...mockConfig, envAll: true, excludeEnv: ['GITHUB_TOKEN'] };
1358+
const result = generateDockerCompose(configWithExcludeEnv, mockNetworkConfig);
1359+
const env = result.services.agent.environment as Record<string, string>;
1360+
1361+
// GITHUB_TOKEN should be excluded from the env-all passthrough
1362+
expect(env.GITHUB_TOKEN).toBeUndefined();
1363+
} finally {
1364+
if (prevToken !== undefined) process.env.GITHUB_TOKEN = prevToken;
1365+
else delete process.env.GITHUB_TOKEN;
1366+
}
1367+
});
1368+
12981369
it('should auto-inject GH_HOST from GITHUB_SERVER_URL when envAll is true', () => {
12991370
const prevServerUrl = process.env.GITHUB_SERVER_URL;
13001371
const prevGhHost = process.env.GH_HOST;

src/docker-manager.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,13 @@ export function generateDockerCompose(
593593
environment.AWF_BUN_INSTALL = process.env.BUN_INSTALL;
594594
}
595595

596+
// If --exclude-env names were specified, add them to the excluded set
597+
if (config.excludeEnv && config.excludeEnv.length > 0) {
598+
for (const name of config.excludeEnv) {
599+
EXCLUDED_ENV_VARS.add(name);
600+
}
601+
}
602+
596603
// If --env-all is specified, pass through all host environment variables (except excluded ones)
597604
if (config.envAll) {
598605
for (const [key, value] of Object.entries(process.env)) {

src/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,17 @@ export interface WrapperConfig {
247247
*/
248248
envAll?: boolean;
249249

250+
/**
251+
* Additional environment variable names to exclude when using --env-all
252+
*
253+
* When `envAll` is true, these variable names are excluded from the host environment
254+
* passthrough in addition to the built-in exclusion list (PATH, HOME, etc.).
255+
* Has no effect when `envAll` is false.
256+
*
257+
* @example ['GITHUB_MCP_SERVER_TOKEN', 'GH_AW_GITHUB_TOKEN']
258+
*/
259+
excludeEnv?: string[];
260+
250261
/**
251262
* Path to a file containing environment variables to inject into the container
252263
*

0 commit comments

Comments
 (0)