Add AOAI Entra smoke workflow for Copilot#38706
Conversation
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
|
/smoke-copilot-aoai-entra |
There was a problem hiding this comment.
Pull request overview
Adds a new Agentic Workflows “smoke” workflow variant intended to validate Copilot’s Azure OpenAI (AOAI) BYOK path using Microsoft Entra (GitHub OIDC → Azure), mirroring the existing AOAI API-key smoke workflow.
Changes:
- Added a new Entra/OIDC-based smoke workflow definition (
smoke-copilot-aoai-entra.md) alongside the existing AOAI API-key smoke path. - Added the compiled lock workflow (
smoke-copilot-aoai-entra.lock.yml) including network allowlisting forlogin.microsoftonline.com.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/smoke-copilot-aoai-entra.md | New smoke workflow frontmatter + prompt content for AOAI via Entra/OIDC auth. |
| .github/workflows/smoke-copilot-aoai-entra.lock.yml | Generated compiled workflow intended to execute the new Entra smoke test under the firewall. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 1/2 changed files
- Comments generated: 2
| # shellcheck disable=SC1003 | ||
| sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:${RUNNER_TEMP}/gh-aw/safeoutputs/upload-artifacts:rw" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env AWF_AUTH_AZURE_CLIENT_ID --exclude-env AWF_AUTH_AZURE_TENANT_ID --exclude-env COPILOT_PROVIDER_BASE_URL --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ | ||
| -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}"; export PATH="$(find "$GH_AW_TOOL_CACHE" /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --autopilot --max-autopilot-continues 2 --allow-all-tools --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --no-custom-instructions --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log | ||
| env: | ||
| AWF_AUTH_PROVIDER: azure | ||
| AWF_AUTH_TYPE: github-oidc | ||
| AWF_REFLECT_ENABLED: 1 | ||
| COPILOT_AGENT_RUNNER_TYPE: STANDALONE | ||
| COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode | ||
| COPILOT_MODEL: o4-mini-aw | ||
| COPILOT_PROVIDER_BASE_URL: ${{ secrets.FOUNDRY_OPENAI_ENDPOINT }} | ||
| COPILOT_PROVIDER_WIRE_API: responses | ||
| GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} |
There was a problem hiding this comment.
Addressed in a subsequent commit. The frontmatter was updated to use literal credential values (azure-tenant-id: 398a6654-… / azure-client-id: adb907fd-…) instead of secrets references, so the compiled lock file now sets AWF_AUTH_AZURE_CLIENT_ID and AWF_AUTH_AZURE_TENANT_ID directly in the Execute GitHub Copilot CLI step env block (lock file lines 1881–1882).
| # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"4376e810e0b59637c3749f90175382d30d7325ed4ebb3eb012ed69094d16c005","body_hash":"544a4bb8ccad1f2b14e10c580fbd23705eb8196559fb5606a048c9f8415a9b0c","agent_id":"copilot","agent_model":"o4-mini-aw","engine_versions":{"copilot":"1.0.60"}} | ||
| # gh-aw-manifest: {"version":1,"secrets":["FOUNDRY_OPENAI_ENDPOINT","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.2","digest":"sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.2@sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"},{"image":"ghcr.io/github/serena-mcp-server:latest","digest":"sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5","pinned_image":"ghcr.io/github/serena-mcp-server:latest@sha256:bf343399e3725c45528f531a230f3a04521d4cdef29f9a5af6282ff0d3c393c5"}]} | ||
| # ___ _ _ |
There was a problem hiding this comment.
Obsolete after the frontmatter change. AZURE_CLIENT_ID and AZURE_TENANT_ID are now inline literals in the frontmatter (not secret references), so they are correctly absent from the manifest's secrets list — the manifest only tracks ${{ secrets.* }} references.
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
🧪 Test Quality Sentinel completed test quality analysis. No test files were added or modified in PR #38706. The PR adds two workflow files: smoke-copilot-aoai-entra.md (workflow source) and smoke-copilot-aoai-entra.lock.yml (compiled lock file). Neither are Go (_test.go) or JavaScript (.test.cjs/.test.js) test files. Test Quality Sentinel skipped. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #38706 does not have the 'implementation' label and has 0 new lines of code in business logic directories (≤100 threshold). |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
REQUEST_CHANGES — The compiled lock file has two blocking correctness issues that will cause silent auth failure at runtime.
### Blocking issues
1. Compiler bug: missing Azure credential env bindings (lock file line 1884, 2543)
The agent and detection execution steps both use --exclude-env AWF_AUTH_AZURE_CLIENT_ID --exclude-env AWF_AUTH_AZURE_TENANT_ID to keep credentials out of the sandboxed container, but never set these variables in the step env: block. Compare with the apikey variant, which correctly has COPILOT_PROVIDER_API_KEY: ${{ secrets.FOUNDRY_API_KEY }} before excluding it from the container. The source frontmatter (smoke-copilot-aoai-entra.md lines 39–40) correctly declares both fields — this is a gh aw compile bug where the github-oidc auth path fails to emit the corresponding env bindings.
2. Detection job missing environment: aoai-model (lock file line 2376)
Every other job using Azure OIDC auth — agent, conclusion, pre_activation, safe_outputs — declares environment: aoai-model. The detection job does not. If Azure credentials are scoped to that GitHub Environment, detection's OIDC token exchange will fail even after the compiler bug is fixed.
### Non-blocking observation
The gh-aw-manifest at the top of the lock file omits AZURE_CLIENT_ID and AZURE_TENANT_ID from its secrets array, so audit tooling won't flag these as required credentials for the Entra path. Worth fixing when addressing the above.
The markdown source (smoke-copilot-aoai-entra.md) looks correct; the fix belongs in the compiler and/or a recompile.
🔎 Code quality review by PR Code Quality Reviewer · ⌖ 13.5 AIC
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnose and /grill-with-docs — requesting changes on a correctness bug that will cause runtime auth failure.
📋 Key Themes & Highlights
Blocking Issue
Azure credential env vars are silently stripped from the compiled lock file. The smoke workflow will fail at runtime when awf tries to perform the GitHub OIDC → Azure token exchange — it needs AWF_AUTH_AZURE_TENANT_ID and AWF_AUTH_AZURE_CLIENT_ID in the runner environment, but FilterEnvForSecrets removes them because CopilotEngine.GetRequiredSecretNames does not include AZURE_TENANT_ID or AZURE_CLIENT_ID in its allowed list. See inline comment on .md line 40 for the full diagnosis and suggested fix in copilot_engine.go.
This is a compiler gap exposed by the first use of engine.auth.type: github-oidc + provider: azure in this repo. The API key variant worked fine because COPILOT_PROVIDER_API_KEY is already in the allowed list.
Secondary Observations
send_slack_messageenvironment gate: The stub job picks upenvironment: aoai-modelas a compiler side-effect (frontmatterenvironmentpropagating to safe-output jobs). This differs from the API key variant and could cause the stub to block on deployment protection rules. See lock file line 2895.- Step cross-reference typo: Output step 4 references
aw_smoke_discussionas coming from "step 11" — it is created in step 10. See.mdline 237.
Positive Highlights
- ✅ The diff against
smoke-copilot-aoai-apikey.mdis surgical and minimal — exactly the right approach. - ✅ The inline comment explaining
COPILOT_PROVIDER_WIRE_API: responses(o4-mini is a reasoning model; Azure rejects the legacycompletionswire API) is excellent and prevents future confusion. - ✅
login.microsoftonline.comis correctly added to both theGH_AW_INFO_ALLOWED_DOMAINSmetadata and the expanded squid allow-list JSON. - ✅ All container images are pinned to SHA digests.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 1.7K AIC · ⌖ 14.1 AIC
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
|
@copilot change the frontmatter to directly specify AZURE_CLIENT_ID: adb907fd-188c-4029-b67f-2559d96b2f1b and AZURE_TENANT_ID: 398a6654-997b-47e9-b12b-9515b896b4de as they are not secrets (matching https://github.com/github/gh-aw/blob/main/.github/workflows/aoai-endpoint-smoke-test.yml) |
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
Updated the frontmatter to use literal Azure credentials instead of secrets. The compiled workflow now correctly sets |
|
Smoke beat. Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
|
@copilot run pr-finisher |
Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #38706 does not have the 'implementation' label (has_implementation_label=false) and has only 12 new lines in business logic directories, well below the 100-line threshold (requires_adr_by_default_volume=false). |
|
|
|
Hey
If you'd like a hand, you can assign this prompt to your coding agent:
|
…vironment wiring Co-authored-by: zarenner <13670625+zarenner@users.noreply.github.com>
Matches the existing AWF test in https://github.com/github/gh-aw-firewall/actions/workflows/smoke-copilot-byok-aoai-entra.lock.yml
Adds the missing Microsoft Entra variant of the Copilot AOAI smoke workflow. This mirrors the existing AOAI API key smoke path while exercising the frontmatter users should rely on for GitHub OIDC → Azure authentication.
New Entra smoke workflow
.github/workflows/smoke-copilot-aoai-entra.md.o4-mini-awmodel.FOUNDRY_API_KEY.OIDC and environment wiring
aoai-modelGitHub Actions environment so OIDC subject claims match Azure federation rules.id-token: write.engine.authfrontmatter with literal Azure credential values (matching the pattern inaoai-endpoint-smoke-test.yml):.lock.ymlfor the new workflow.login.microsoftonline.comnetwork access required for Azure token exchange.AWF_AUTH_AZURE_CLIENT_IDandAWF_AUTH_AZURE_TENANT_IDas environment variables.✨ PR Review Safe Output Test - Run 27385890715
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.