Skip to content

Commit 8afb75f

Browse files
Claudelpcox
andcommitted
feat(cli): add GHES auto-populate integration test and docs
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
1 parent 8c45813 commit 8afb75f

2 files changed

Lines changed: 254 additions & 0 deletions

File tree

docs/enterprise-configuration.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,37 @@ When `GITHUB_SERVER_URL` is set to a non-github.com, non-ghe.com domain, AWF aut
124124
# AWF automatically uses: api.enterprise.githubcopilot.com
125125
```
126126

127+
### Auto-Population for GitHub Agentic Workflows
128+
129+
**New in v0.24.0:** When running agentic workflows with `engine.api-target` set (via the `ENGINE_API_TARGET` environment variable), AWF automatically adds GHES domains to the firewall allowlist. You no longer need to manually specify these domains in `--allow-domains` or `GH_AW_ALLOWED_DOMAINS`.
130+
131+
**Auto-added domains:**
132+
- The GHES base domain (e.g., `github.mycompany.com` from `https://api.github.mycompany.com`)
133+
- The GHES API subdomain (e.g., `api.github.mycompany.com`)
134+
- Copilot API domains required even on GHES:
135+
- `api.githubcopilot.com`
136+
- `api.enterprise.githubcopilot.com`
137+
- `telemetry.enterprise.githubcopilot.com`
138+
139+
**Example:**
140+
```bash
141+
# When ENGINE_API_TARGET=https://api.github.mycompany.com
142+
# AWF automatically adds these to the allowlist:
143+
# - github.mycompany.com
144+
# - api.github.mycompany.com
145+
# - api.githubcopilot.com
146+
# - api.enterprise.githubcopilot.com
147+
# - telemetry.enterprise.githubcopilot.com
148+
149+
# Before (manual configuration):
150+
export ENGINE_API_TARGET="https://api.github.mycompany.com"
151+
export GH_AW_ALLOWED_DOMAINS="github.mycompany.com,api.github.mycompany.com,api.githubcopilot.com,api.enterprise.githubcopilot.com,telemetry.enterprise.githubcopilot.com"
152+
153+
# After (automatic):
154+
export ENGINE_API_TARGET="https://api.github.mycompany.com"
155+
# No need to set GH_AW_ALLOWED_DOMAINS - domains are auto-populated!
156+
```
157+
127158
### Required Domains for GHES
128159

129160
```bash
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/**
2+
* GHES Auto-Populate Integration Tests
3+
*
4+
* Tests that ENGINE_API_TARGET environment variable (set by GitHub Agentic Workflows)
5+
* automatically adds GHES domains and Copilot API domains to the firewall allowlist.
6+
*/
7+
8+
/// <reference path="../jest-custom-matchers.d.ts" />
9+
10+
import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
11+
import { createRunner, AwfRunner } from '../fixtures/awf-runner';
12+
import { cleanup } from '../fixtures/cleanup';
13+
14+
describe('GHES Auto-Populate', () => {
15+
let runner: AwfRunner;
16+
17+
beforeAll(async () => {
18+
await cleanup(false);
19+
runner = createRunner();
20+
});
21+
22+
afterAll(async () => {
23+
await cleanup(false);
24+
});
25+
26+
test('should automatically add GHES domains when ENGINE_API_TARGET is set', async () => {
27+
const result = await runner.runWithSudo(
28+
'echo "Testing GHES domain auto-population"',
29+
{
30+
allowDomains: [], // Explicitly empty - domains should come from ENGINE_API_TARGET
31+
buildLocal: true,
32+
logLevel: 'debug',
33+
timeout: 60000,
34+
env: {
35+
ENGINE_API_TARGET: 'https://api.github.mycompany.com',
36+
},
37+
}
38+
);
39+
40+
// Should succeed without any network calls
41+
expect(result.exitCode).toBe(0);
42+
43+
// Should log the auto-added GHES domains
44+
expect(result.stderr).toContain('Auto-added GHES domains from engine.api-target');
45+
expect(result.stderr).toContain('github.mycompany.com');
46+
expect(result.stderr).toContain('api.github.mycompany.com');
47+
}, 120000);
48+
49+
test('should add Copilot API domains when ENGINE_API_TARGET is set', async () => {
50+
const result = await runner.runWithSudo(
51+
'curl -s https://api.githubcopilot.com',
52+
{
53+
allowDomains: [], // Explicitly empty
54+
buildLocal: true,
55+
logLevel: 'debug',
56+
timeout: 60000,
57+
env: {
58+
ENGINE_API_TARGET: 'https://api.github.enterprise.local',
59+
},
60+
}
61+
);
62+
63+
// Should allow Copilot API domains even on GHES
64+
expect(result).toAllowDomain('api.githubcopilot.com');
65+
}, 120000);
66+
67+
test('should add enterprise Copilot API domains when ENGINE_API_TARGET is set', async () => {
68+
const result = await runner.runWithSudo(
69+
'curl -s https://api.enterprise.githubcopilot.com',
70+
{
71+
allowDomains: [], // Explicitly empty
72+
buildLocal: true,
73+
logLevel: 'debug',
74+
timeout: 60000,
75+
env: {
76+
ENGINE_API_TARGET: 'https://api.github.enterprise.local',
77+
},
78+
}
79+
);
80+
81+
// Should allow enterprise Copilot API domains
82+
expect(result).toAllowDomain('api.enterprise.githubcopilot.com');
83+
}, 120000);
84+
85+
test('should add telemetry Copilot API domains when ENGINE_API_TARGET is set', async () => {
86+
const result = await runner.runWithSudo(
87+
'curl -s https://telemetry.enterprise.githubcopilot.com',
88+
{
89+
allowDomains: [], // Explicitly empty
90+
buildLocal: true,
91+
logLevel: 'debug',
92+
timeout: 60000,
93+
env: {
94+
ENGINE_API_TARGET: 'https://api.github.enterprise.local',
95+
},
96+
}
97+
);
98+
99+
// Should allow telemetry Copilot API domains
100+
expect(result).toAllowDomain('telemetry.enterprise.githubcopilot.com');
101+
}, 120000);
102+
103+
test('should not duplicate domains if already in allowlist', async () => {
104+
const result = await runner.runWithSudo(
105+
'echo "Testing no duplication"',
106+
{
107+
allowDomains: ['github.mycompany.com', 'api.githubcopilot.com'],
108+
buildLocal: true,
109+
logLevel: 'debug',
110+
timeout: 60000,
111+
env: {
112+
ENGINE_API_TARGET: 'https://api.github.mycompany.com',
113+
},
114+
}
115+
);
116+
117+
expect(result.exitCode).toBe(0);
118+
119+
// Count how many times each domain appears in the debug output
120+
const allowedDomainsLine = result.stderr
121+
.split('\n')
122+
.find(line => line.includes('Allowed domains:'));
123+
124+
expect(allowedDomainsLine).toBeDefined();
125+
126+
const ghesCount = ((allowedDomainsLine as string).match(/github\.mycompany\.com/g) || []).length;
127+
const copilotCount = ((allowedDomainsLine as string).match(/api\.githubcopilot\.com/g) || []).length;
128+
129+
// Each domain should appear exactly once
130+
expect(ghesCount).toBe(1);
131+
expect(copilotCount).toBe(1);
132+
}, 120000);
133+
134+
test('should combine ENGINE_API_TARGET domains with --allow-domains flag', async () => {
135+
const result = await runner.runWithSudo(
136+
'echo "Testing combined domains"',
137+
{
138+
allowDomains: ['example.com'],
139+
buildLocal: true,
140+
logLevel: 'debug',
141+
timeout: 60000,
142+
env: {
143+
ENGINE_API_TARGET: 'https://api.github.mycompany.com',
144+
},
145+
}
146+
);
147+
148+
expect(result.exitCode).toBe(0);
149+
150+
// Should include both explicit domains and auto-added GHES domains
151+
expect(result.stderr).toContain('example.com');
152+
expect(result.stderr).toContain('github.mycompany.com');
153+
expect(result.stderr).toContain('api.github.mycompany.com');
154+
expect(result.stderr).toContain('api.githubcopilot.com');
155+
}, 120000);
156+
157+
test('should handle ENGINE_API_TARGET without api. prefix', async () => {
158+
const result = await runner.runWithSudo(
159+
'echo "Testing non-api prefix"',
160+
{
161+
allowDomains: [],
162+
buildLocal: true,
163+
logLevel: 'debug',
164+
timeout: 60000,
165+
env: {
166+
ENGINE_API_TARGET: 'https://github.enterprise.local',
167+
},
168+
}
169+
);
170+
171+
expect(result.exitCode).toBe(0);
172+
173+
// Should still add Copilot API domains
174+
expect(result.stderr).toContain('api.githubcopilot.com');
175+
expect(result.stderr).toContain('api.enterprise.githubcopilot.com');
176+
expect(result.stderr).toContain('telemetry.enterprise.githubcopilot.com');
177+
178+
// Should add the hostname itself
179+
expect(result.stderr).toContain('github.enterprise.local');
180+
}, 120000);
181+
182+
test('should ignore invalid ENGINE_API_TARGET gracefully', async () => {
183+
const result = await runner.runWithSudo(
184+
'echo "Testing invalid ENGINE_API_TARGET"',
185+
{
186+
allowDomains: ['github.com'],
187+
buildLocal: true,
188+
logLevel: 'debug',
189+
timeout: 60000,
190+
env: {
191+
ENGINE_API_TARGET: 'not-a-valid-url',
192+
},
193+
}
194+
);
195+
196+
// Should succeed with just the explicit domains
197+
expect(result.exitCode).toBe(0);
198+
expect(result.stderr).toContain('github.com');
199+
200+
// Should not log GHES domain auto-population
201+
expect(result.stderr).not.toContain('Auto-added GHES domains from engine.api-target');
202+
}, 120000);
203+
204+
test('should work without ENGINE_API_TARGET set', async () => {
205+
const result = await runner.runWithSudo(
206+
'echo "Testing without ENGINE_API_TARGET"',
207+
{
208+
allowDomains: ['github.com'],
209+
buildLocal: true,
210+
logLevel: 'debug',
211+
timeout: 60000,
212+
// No ENGINE_API_TARGET in env
213+
}
214+
);
215+
216+
// Should succeed with just the explicit domains
217+
expect(result.exitCode).toBe(0);
218+
expect(result.stderr).toContain('github.com');
219+
220+
// Should not log GHES domain auto-population
221+
expect(result.stderr).not.toContain('Auto-added GHES domains from engine.api-target');
222+
}, 120000);
223+
});

0 commit comments

Comments
 (0)