Skip to content

feat(action): validate Azure setup instead of reporting a missing key - #70

Closed
theoephraim wants to merge 1 commit into
pullfrog:mainfrom
dmno-dev:feat/azure-setup-validation
Closed

feat(action): validate Azure setup instead of reporting a missing key#70
theoephraim wants to merge 1 commit into
pullfrog:mainfrom
dmno-dev:feat/azure-setup-validation

Conversation

@theoephraim

@theoephraim theoephraim commented Jul 28, 2026

Copy link
Copy Markdown

feel free to toss or reimplement. I got azure wired up successfully, but this is what came out of a review about improving pullfrog after doing so. I will note that azure foundry is pretty awkward, so it's easy to get this wrong... So better error messaging may help someone.


Context

Azure-hosted OpenAI models already work today with no changes to Pullfrog: resolveModel passes a slashed non-curated value through as a raw models.dev specifier, the BYOK gate is opencode models output rather than a fixed allowlist, and models.dev ships an azure provider (AZURE_RESOURCE_NAME + AZURE_API_KEY) carrying the GPT models. We're running our PR reviews on azure/gpt-5.6-sol this way.

This PR doesn't add Azure support. It makes the failure mode legible when the setup is wrong.

Problem

Because Azure has no curated alias, it carries no routing discriminant, so it skips the Bedrock and Vertex branches in validateAgentApiKey and lands on the generic buildMissingApiKeyError. That message is wrong for both ways Azure fails:

  1. A missing env var. Set AZURE_API_KEY but not AZURE_RESOURCE_NAME and you're told no API key was found, pointing at the key you just added.
  2. A deployment name mismatch. @ai-sdk/azure addresses a deployment, not a model, and uses the model id as the deployment name. Name your deployment sol-review instead of gpt-5.6-sol and it never enters the authorized set, so credentials that are completely fine report as a missing key.

The second one cost us the most time, and nothing in the output points at it.

Change

validateAzureSetup, sited beside the two existing validators and following their shape. It names whichever var is absent; when both are present it explains the deployment-name coupling and says exactly what the deployment must be called.

Rendered, for azure/gpt-5.6-sol with both vars set:

Azure is configured (AZURE_RESOURCE_NAME + AZURE_API_KEY are both set) but
OpenCode can't serve `azure/gpt-5.6-sol`.

the most likely cause is a deployment name mismatch. the Azure provider
addresses a *deployment*, not a model, and uses the model id as the deployment
name — so your deployment must be named exactly `gpt-5.6-sol`.

check Azure AI Foundry → Deployments and either rename the deployment to
`gpt-5.6-sol`, or select the model whose id matches the name you already have.

if the name does match, confirm `AZURE_RESOURCE_NAME` points at the resource
hosting that deployment.

Both models.dev Azure providers are covered (azure, azure-cognitive-services), since they differ only in env-var prefix. The validator returns without throwing for any non-Azure provider, so the generic error path is untouched elsewhere — there's a test pinning that.

Deliberately no docs.pullfrog.com/azure link, since that page doesn't exist yet. Happy to write one as a follow-up if you'd take it.

Tests

Six cases in utils/apiKeys.test.ts. Verified the four behavioral ones fail when the hook is disabled. pnpm typecheck clean, utils/ 282/282. Didn't run the full suite (no GitHub App credentials locally).

Branched off main, independent of #69.


Note

Low Risk
Changes are limited to pre-run validation error messaging in utils/apiKeys.ts with no auth or runtime behavior changes; non-Azure paths are explicitly no-ops.

Overview
When an OpenCode run uses an unauthorized azure/... or azure-cognitive-services/... model, validateAgentApiKey no longer falls through to the generic “no API key found” message. It now runs validateAzureSetup, aligned with the existing Bedrock/Vertex setup validators.

Missing AZURE_RESOURCE_NAME / AZURE_API_KEY (or the cognitive-services equivalents) produce errors that name the specific env vars and how to set them in GitHub Actions. If both are set but the model still isn’t authorized, the error calls out a likely deployment name mismatch (Azure uses the model id as the deployment name) instead of blaming a missing key. Non-Azure providers still get the generic missing-key path.

Tests cover authorized success, missing vars, deployment mismatch copy, both Azure provider prefixes, and that other providers are unchanged.

Reviewed by Cursor Bugbot for commit 21fa4cf. Bugbot is set up for automated code reviews on this repo. Configure here.

Azure models reach validateAgentApiKey as raw models.dev specifiers
(azure/<model-id>), so they never hit the Bedrock/Vertex routing branches
and fall through to the generic "no API key found" error. That copy is
wrong for both Azure failure modes: a missing AZURE_RESOURCE_NAME, and a
deployment whose name doesn't match the model id — the latter tells users
to add a key they already added.

Add validateAzureSetup alongside the Bedrock and Vertex validators. It
names whichever env var is absent, and when both are set it explains that
the provider addresses a deployment and uses the model id as the
deployment name, so the deployment must be renamed to match.

Covers both models.dev Azure providers (azure, azure-cognitive-services),
which differ only in env-var prefix. No-ops for every other provider, so
the generic error is unchanged elsewhere.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 21fa4cf. Configure here.

Comment thread utils/apiKeys.ts
missing,
envVars,
})
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Azure errors skip PR comment rendering

Medium Severity

validateAzureSetup throws messages that lack both the missing-key marker and a pass-through marker like MODEL_ACCESS_MARKER, so renderRunError treats them as generic failures. The PR comment collapses to a one-line logs link, and the job summary frames the setup guidance as an unexpected error. Before this change, Azure failures went through buildMissingApiKeyError and were mirrored onto the PR comment.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 21fa4cf. Configure here.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — a dedicated Azure setup validator that replaces the generic "missing key" error when an azure/* model is unauthorized, so the two real Azure failure modes (a missing env var vs. a deployment-name mismatch) each get accurate copy.

  • Add validateAzureSetup + buildAzureSetupError — sited beside the Bedrock/Vertex validators; throws for Azure providers and returns (no-op) for everything else, leaving the generic path untouched.
  • AZURE_PROVIDERS map — covers both models.dev Azure providers (azure, azure-cognitive-services), which differ only in env-var prefix.
  • Wire into the opencode branch — runs after the authorized.has(model) check in validateAgentApiKey, deriving the provider from the model prefix.
  • Six tests in utils/apiKeys.test.ts covering authorized success, each missing var, the deployment-mismatch copy, the cognitive-services prefix, and that non-Azure providers stay on the generic error.

I verified the surrounding integration beyond the diff: the provider/deployment split is safe because the earlier !params.model.includes("/") guard (apiKeys.ts:236) guarantees a / before this branch runs, and the new error deliberately omits the MISSING_KEY_MARKER, so isApiKeyAuthError correctly leaves it alone rather than re-routing it through the "rotate your key" copy. Test isolation also holds — the /_API_KEY$/ strip pattern already clears AZURE_API_KEY between cases. One awareness note below; nothing blocking.

ℹ️ Detailed Azure guidance lands in the Actions job summary, not the PR comment

Because the Azure setup error carries no MISSING_KEY_MARKER, it flows through the generic-failure branch in renderRunError — the full deployment-mismatch guidance renders in the GitHub Actions job summary, while the PR progress comment collapses to a one-line **Run failed.** [View the logs →]. This is identical to how the existing Bedrock/Vertex setup errors behave, so it's consistent, not a regression. Worth confirming it matches intent, since the generic missing-key path (which does carry the marker) surfaces its rich copy directly in the PR comment.

Technical details
# Azure setup error surfaces in job summary, not PR comment

## Affected sites
- `utils/runErrorRenderer.ts:227-266``isApiKeyAuthError(apiKeySource)` is false for the Azure error (no `MISSING_KEY_MARKER`), so it falls through to `formatGenericFailure``summary` = full message, `comment` = `formatMinimalFailureComment` (one-liner).
- `utils/apiKeys.ts:118-124` — deployment-mismatch copy that only reaches the `summary` surface.

## Required outcome
- No change required if parity with Bedrock/Vertex is the intended behavior.

## Open questions for the human
- Should the multi-var setup errors (Azure/Bedrock/Vertex) surface their detailed copy in the PR comment too, or is the job-summary-only placement acceptable? This is a shared design decision beyond this PR's scope.

Pullfrog  | View workflow run | Using Claude Opus (free via Pullfrog for OSS) | 𝕏

@theoephraim

Copy link
Copy Markdown
Author

Closing: superseded by the first-class Azure support that landed in 5f2ce64 (#1226). Its validateAzureSetup covers what this PR did and goes further, also requiring the deployment name and token limits. Great to see it shipped!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant