Skip to content

Commit afb8821

Browse files
authored
Merge pull request #14 from Azure/build-deploy
0.2.1b7
2 parents 3882a8a + 8f1d7c4 commit afb8821

96 files changed

Lines changed: 16937 additions & 7916 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
strategy:
7070
fail-fast: false
7171
matrix:
72-
python-version: ["3.10", "3.11", "3.12"]
72+
python-version: ["3.10", "3.11", "3.12", "3.13"]
7373

7474
steps:
7575
- uses: actions/checkout@v4

HISTORY.rst

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,93 @@
33
Release History
44
===============
55

6+
0.2.1b7
7+
+++++++
8+
9+
Build stage re-entry fix
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
* **QA remediation failure now retries on re-entry** — fixed a bug where
12+
``mark_stage_generated()`` was called after each remediation attempt
13+
inside ``_run_stage_qa()``, leaving the stage with status ``"generated"``
14+
even when QA subsequently failed. On re-entry, the stage was skipped
15+
instead of retried. Changed to ``mark_stage_validating()`` so failed
16+
stages remain in the retry list.
17+
18+
QA checklist hardening
19+
~~~~~~~~~~~~~~~~~~~~~~~~
20+
* **Aligned response_export_values directive** — QA checklist now requires
21+
``response_export_values = ["*"]`` on EVERY ``azapi_resource``, matching
22+
the terraform agent's mandatory rule (was conditional on output usage).
23+
* **Added deploy.sh -state= flag check** — QA checklist now flags use of
24+
``terraform output -state=`` which was removed in Terraform 1.9.
25+
* **Added UUID hex validation** — QA checklist now checks that UUID values
26+
in role assignment names contain only valid hex characters ``[0-9a-f]``.
27+
28+
Full stage retry on QA exhaustion
29+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30+
* **Full stage retry when QA remediation fails** -- when QA remediation
31+
exhausts all attempts for a stage, the build now retries the entire
32+
stage from scratch (clean artifacts, regenerate, QA) instead of
33+
stopping the build immediately. Previous QA findings are injected
34+
into the new generation prompt — framed as guidance rather than
35+
file-specific instructions — so the model avoids the same classes
36+
of mistakes on the fresh attempt.
37+
38+
In practice, the same generation prompt produces passing code ~90%
39+
of the time. The remaining ~10% failure rate is stochastic — not a
40+
systematic prompt deficiency — meaning a fresh generation with
41+
knowledge of what went wrong almost always succeeds. Without this
42+
retry, that 10% forces the user to manually re-run the entire build,
43+
losing the progress of all previously generated stages. The retry
44+
doubles the token cost of one stage in the worst case, but saves
45+
the full cost of restarting a 16-stage build from scratch.
46+
47+
Controlled by ``_MAX_FULL_STAGE_ATTEMPTS`` (default 2: 1 initial
48+
+ 1 fresh retry).
49+
50+
Generation prompt improvements
51+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52+
* **Front-loaded remote state no-dead-code directive** — when upstream
53+
stages exist, a ``CROSS-STAGE DEPENDENCIES — NO DEAD CODE`` section
54+
now appears before the architecture context in the generation prompt,
55+
reducing unused ``terraform_remote_state`` data sources.
56+
57+
Agent-level service filtering
58+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59+
* **Agent governance checks now filter by service namespace** — added
60+
``stage_services`` field to ``AgentContext``, populated by
61+
``_agent_build_context()``. ``_apply_governance_check()`` now passes
62+
stage services to ``validate_response()``, reducing false positive
63+
anti-pattern warnings for irrelevant service namespaces.
64+
65+
ReDoS fix in transform handlers
66+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67+
* **Replaced nested-quantifier regex with brace counting** — extracted
68+
shared ``_find_azapi_blocks()`` helper and rewrote
69+
``_add_response_export_values``, ``_add_resource_group_parent_id``,
70+
and ``_remove_private_endpoint_resources`` to use it. Eliminates
71+
potential exponential backtracking on pathological input.
72+
73+
Test suite consolidation
74+
~~~~~~~~~~~~~~~~~~~~~~~~~~
75+
* **Consolidated and enhanced unit test coverage** — migrated flat test
76+
files to a mirrored directory structure (1:1 test-to-source mapping),
77+
merged split test files, and removed ~114 duplicate tests across 10
78+
files. Test suite reduced from 3,644 to 3,530 tests with zero loss
79+
of unique coverage.
80+
81+
QA review continuation for large stages
82+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
83+
* **QA review collects complete response before evaluating** — when the
84+
QA review response is truncated (``finish_reason=length``), the build
85+
session now continues requesting until the full review is received,
86+
then evaluates the concatenated result. Uses the existing
87+
``_execute_with_continuation()`` pattern with a review-specific
88+
continuation prompt that prevents the QA agent from generating code
89+
in the continuation. Conversation history is saved and restored
90+
around QA calls to prevent review messages from contaminating
91+
subsequent stage generation.
92+
693
0.2.1b6
794
+++++++
895

azext_prototype/agents/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class AgentContext:
8181
artifacts: dict[str, Any] = field(default_factory=dict)
8282
shared_state: dict[str, Any] = field(default_factory=dict)
8383
mcp_manager: Any = None # MCPManager | None — typed as Any to avoid circular import
84+
stage_services: list[str] | None = None # ARM namespaces for service filtering
8485

8586
def add_artifact(self, key: str, value: Any):
8687
"""Store an artifact for other agents to reference."""
@@ -299,7 +300,7 @@ def _apply_governance_check(self, response: AIResponse, context: AgentContext) -
299300
avoid duplicating the governance warning block.
300301
"""
301302
iac_tool = context.project_config.get("project", {}).get("iac_tool") if context.project_config else None
302-
warnings = self.validate_response(response.content, iac_tool=iac_tool, services=None)
303+
warnings = self.validate_response(response.content, iac_tool=iac_tool, services=context.stage_services)
303304
if warnings:
304305
for w in warnings:
305306
logger.warning("Governance: %s", w)

azext_prototype/agents/builtin/qa_engineer.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ def _encode_image(path: str) -> str:
233233
- [ ] deploy.sh includes error handling (set -euo pipefail, trap)
234234
- [ ] deploy.sh exports outputs to JSON file for downstream stages
235235
- [ ] deploy.sh includes Azure login verification
236+
- [ ] deploy.sh does NOT use `terraform output -state=` — this flag was removed
237+
in Terraform 1.9. Use `jq` on the state file or `cd` into the stage directory
236238
237239
### 4. Output Completeness
238240
- [ ] outputs.tf exports resource group name(s)
@@ -251,8 +253,8 @@ def _encode_image(path: str) -> str:
251253
- [ ] All referenced variables are defined in variables.tf
252254
- [ ] All referenced locals are defined in locals.tf
253255
- [ ] Application code includes all referenced classes/models/DTOs
254-
- [ ] Every azapi_resource whose `.output.properties` is referenced in
255-
outputs.tf MUST have `response_export_values = ["*"]` declared
256+
- [ ] EVERY `azapi_resource` block MUST have `response_export_values = ["*"]`
257+
declared — no exceptions, even if outputs.tf does not reference its properties
256258
- [ ] No .tf file is empty or contains only comments (dead files)
257259
258260
### 7. Terraform File Structure
@@ -314,6 +316,8 @@ def _encode_image(path: str) -> str:
314316
**NOT** string interpolation on the storage account ID
315317
- [ ] RBAC assignments for the worker identity (Stage 1) are **unconditional**
316318
(no `count`). The worker identity exists before any service stage runs.
319+
- [ ] UUID values in role assignment names contain only valid hex characters
320+
`[0-9a-f]` — letters `g`-`z` are invalid and ARM rejects with `InvalidName`
317321
318322
### 13. Application Code (app stages only)
319323
- [ ] Application source code is syntactically correct and complete

azext_prototype/ai/token_tracker.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,35 @@
4444
# GitHub Copilot Premium Request Unit (PRU) multipliers.
4545
# Each API call costs (1 × multiplier) PRUs. Only applies to the
4646
# Copilot provider — models not in this table produce 0 PRUs.
47-
# Source: https://docs.github.com/en/copilot/concepts/billing/copilot-requests
47+
# Source: https://docs.github.com/en/copilot/managing-copilot/monitoring-usage-and-entitlements/about-premium-requests
48+
# Last updated: 2026-04-08
4849
_PRU_MULTIPLIERS: dict[str, float] = {
4950
# Included with paid plans (0 PRUs)
5051
"gpt-5-mini": 0,
5152
"gpt-4.1": 0,
5253
"gpt-4o": 0,
54+
"raptor-mini": 0,
5355
# Low-cost (0.25–0.33 PRUs per request)
5456
"grok-code-fast-1": 0.25,
5557
"claude-haiku-4.5": 0.33,
5658
"gemini-3-flash": 0.33,
57-
"gpt-5.1-codex-mini": 0.33,
5859
"gpt-5.4-mini": 0.33,
5960
# Standard (1 PRU per request)
6061
"claude-sonnet-4": 1,
6162
"claude-sonnet-4.5": 1,
6263
"claude-sonnet-4.6": 1,
64+
"gemini-2.5-pro": 1,
6365
"gemini-3-pro": 1,
64-
"gemini-3-pro-1.5": 1,
66+
"gemini-3.1-pro": 1,
6567
"gpt-5.1": 1,
6668
"gpt-5.2": 1,
69+
"gpt-5.2-codex": 1,
70+
"gpt-5.3-codex": 1,
6771
"gpt-5.4": 1,
6872
# Premium (3+ PRUs per request)
6973
"claude-opus-4.5": 3,
7074
"claude-opus-4.6": 3,
75+
"claude-opus-4.6-fast": 30,
7176
}
7277

7378

azext_prototype/azext_metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"azext.isPreview": true,
33
"azext.minCliCoreVersion": "2.50.0",
44
"name": "prototype",
5-
"version": "0.2.1b6",
5+
"version": "0.2.1b7",
66
"azext.summary": "Azure CLI extension for building rapid prototypes with GitHub Copilot.",
77
"license": "MIT",
88
"classifiers": [

0 commit comments

Comments
 (0)