Enable extension CI builds — daily + PR#7497
Conversation
baccf05 to
3929c5d
Compare
There was a problem hiding this comment.
Pull request overview
Adds an internal CI path for producing “rolling” unsigned extension builds from main, publishing them to stable *-dev GitHub release tags, and providing a dev registry JSON that points azd’s extension installer at those artifacts.
Changes:
- Adds a
publish-extension-dev.ymlstage that packages CI-built extension binaries and publishes them to a{SanitizedExtensionId}-devGitHub prerelease. - Wires the dev publish stage into the extension release pipeline template for internal CI runs (
IndividualCI/BatchedCI). - Introduces
cli/azd/extensions/registry-dev.jsonas a static registry pointing at the dev release download URLs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| eng/pipelines/templates/stages/release-azd-extension.yml | Conditionally includes the new dev publish stage for internal CI builds. |
| eng/pipelines/templates/stages/publish-extension-dev.yml | New stage to delete/recreate a *-dev GitHub prerelease and upload packaged artifacts. |
| cli/azd/extensions/registry-dev.json | New dev registry pointing to *-dev release artifacts for 8 extensions. |
3929c5d to
dbc0e49
Compare
dbc0e49 to
5be88af
Compare
8e87775 to
2d132f5
Compare
jongio
left a comment
There was a problem hiding this comment.
Version override (set-extension-version-cd.yml) only runs in GenerateReleaseArtifacts, not in the per-platform build/cross-build jobs. The core CLI runs this in all 3 job types. Binaries get the base version while the registry lists the daily version.
Issues to address:
- build-and-test-azd-extension.yml:113 - version override missing from BuildExtension and CrossBuild jobs
- Update-ExtensionDailyRegistry.ps1:202 - non-404 azcopy failures silently wipe the registry
- Update-ExtensionDailyRegistry.ps1:211 - concurrent extension pipelines race on registry-daily.json
- Update-ExtensionDailyRegistry.ps1:100 - regex YAML parser won't handle multi-line values or inline comments
Addressed review comments. Requesting re-review.
jongio
left a comment
There was a problem hiding this comment.
Solid PR - per-extension registry entries cleanly avoid the concurrent blob mutation problem. Version stamping is consistent across all build and cross-build jobs now, and the pipeline flow (BuildAndTest -> Sign -> PublishDaily) checks out.
One observation:
- eng/pipelines/templates/steps/publish-extension.yml:15 - parameter defaults create a silent skip trap for future callers (see inline)
Previous feedback from jongio and hemarina looks addressed.
wbreza
left a comment
There was a problem hiding this comment.
Code Review — PR #7497
Enable dev extension builds on CI by @rajeshkamal5050
Summary
Great addition to the extension dev workflow! The per-extension daily registry pattern is a clean solution that avoids the concurrent blob mutation problem entirely. The overall architecture — version stamping → build → sign → publish → registry — mirrors the established core CLI daily build pattern well.
Previous feedback from @jongio, @hemarina, and @vhvb1989 has been largely addressed. Two new findings below, plus a few maintenance items.
Prior Review Regression Check
| # | Prior Finding | Author | Status |
|---|---|---|---|
| 1 | Version override missing from build/cross-build jobs | @jongio | ✅ Resolved |
| 2 | azcopy failure silently wipes registry | @jongio | ✅ Resolved |
| 3 | Concurrent race on shared blob | @jongio | ✅ Resolved |
| 4 | _manifest removal conditional gap | @hemarina | ✅ Resolved |
| 5 | Missing usage validation | @hemarina | ✅ Resolved |
| 6 | Regex YAML parsing fragility | @jongio | ⏳ Open |
| 7 | CreateGitHubRelease defaults trap | @jongio | ⏳ Open |
Findings Summary
| Priority | Count |
|---|---|
| High | 2 |
| Medium | 3 |
| Low | 1 |
| Total | 6 |
✅ What Looks Good
- Per-extension registry entries elegantly eliminate the concurrent blob race condition
- SHA256 checksums from signed artifacts ensure supply chain integrity
- Version stamping mirrors the core CLI daily build pattern correctly
- JSON validated locally before upload;
Continue = 'Stop'prevents silent failures - Clean stage separation: build → sign → publish
This is a great improvement to the extension dev workflow — having daily builds available mirrors what the core CLI already offers and will significantly improve the inner loop for extension development and testing.
Overall Assessment: Comment — High findings warrant discussion, but the core pattern is solid and well-designed.
Review performed with GitHub Copilot CLI
eng/pipelines/templates/steps/update-extension-daily-registry.yml
Outdated
Show resolved
Hide resolved
danieljurek
left a comment
There was a problem hiding this comment.
We'll need to test this e2e to make sure it works before merging it.
jongio
left a comment
There was a problem hiding this comment.
Issues to address:
- cli/azd/extensions/azure.ai.agents/extension.yaml - version field still says 0.1.20-preview but version.txt was bumped to 0.1.21-preview. All other extensions were synced in both files.
- eng/scripts/Update-ExtensionDailyRegistry.ps1:155 - raw string replacement of ${USAGE} into the JSON template doesn't JSON-escape the value. Current extension.yaml files are fine, but if any usage field ever contains a double-quote or backslash, the generated JSON breaks silently. ConvertFrom-Json catches it downstream, but the error won't point at the cause.
Per-extension registry approach is solid - cleanly avoids the concurrent blob mutation problem.
wbreza
left a comment
There was a problem hiding this comment.
Code Re-Review — PR #7497
Enable dev extension builds on CI by @rajeshkamal5050
Re-review after force-push
Changes since my Apr 7 review (b3e211d) are in commit fe4304a:
- Regex → powershell-yaml for proper YAML parsing (addresses my prior finding)
- Registry format wrapped in
{ extensions: [...] }for azd compatibility - CreateGitHubRelease default flipped to false (safe default)
- Idempotency guard for version script pipeline retries
- Null checks + file-exists guards throughout
- Template moved to eng/templates/ with split copy steps
Prior Review: All ✅ Resolved
| # | Priority | Finding | Status |
|---|---|---|---|
| 1 | High | Regex YAML parsing fragility | ✅ Replaced with powershell-yaml |
| 2 | High | Per-extension registry entries (race condition fix) | ✅ Already resolved |
| 3 | Medium | Version override in build/cross-build jobs | ✅ Resolved |
| 4 | Medium | _manifest removal | ✅ Unconditional |
| 5 | Low | Usage validation | ✅ Added |
✅ What Looks Good
- powershell-yaml replaces fragile regex parsing — proper YAML handling
- Per-extension registry entries elegantly eliminate concurrent blob mutation
- SHA256 checksums from signed artifacts ensure supply chain integrity
- Safe defaults: CreateGitHubRelease=false, explicit true in release caller
- Idempotency guard prevents duplicate version suffixes on retries
- Daily publish stage correctly scoped to CI builds (IndividualCI/BatchedCI) — PR builds skip it
Overall Assessment: Re-approve — all findings addressed, no new issues. Pending @danieljurek's E2E validation.
Review performed with GitHub Copilot CLI
Mirrors the core CLI daily build pattern. On CI builds (push to main),
sign and upload extension binaries to Azure Storage.
- publish-extension-daily.yml — new stage, depends on Sign, uploads to
{ext-id}/daily (latest) and {ext-id}/daily/archive/{version} (history)
- publish-extension.yml — add CreateGitHubRelease param (default true)
so daily can skip GitHub Release and just upload to storage
- release-azd-extension.yml — wire daily publish for CI builds
- update-daily-registry.yml — download existing registry-daily.json from
storage, merge in the current extension entry with checksums and
storage URLs, upload back. Self-maintaining across extension builds.
Closes #7317
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pipeline changes:
- publish-extension-daily.yml — daily stage, depends on Sign, uploads
to {ext-id}/daily and {ext-id}/daily/archive/{version}
- publish-extension.yml — add CreateGitHubRelease param so daily can
skip GitHub Release and just upload to storage
- release-azd-extension.yml — wire daily publish for CI builds
- update-extension-daily-registry.yml — calls Update-ExtensionDailyRegistry.ps1
to merge extension entry into registry-daily.json on storage
- extension-registry-daily-template.json — JSON template with placeholders
Version bumps:
- Bump all extension version.txt and extension.yaml so daily builds
are ahead of the last released versions
Closes #7317
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mirrors core CLI pattern: appends -daily.<BuildId> for CI builds, -pr.<BuildId> for PR builds, skips for Manual (release) builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Trim version.txt on read (Set-ExtensionVersionVariable, Set-ExtensionVersionInBuild) - Validate empty version.txt in Set-ExtensionVersionInBuild - Make BuildReason/BuildId mandatory params - Wrap Get-FileHash in try/catch - Validate required YAML fields (namespace, displayName, description) after parsing - Log parsed extension metadata for pipeline diagnostics - Fix upload error handling (don't set ErrorActionPreference=Continue before upload) - Guard CreateGitHubRelease against empty TagPrefix/TagVersion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… fix, usage validation
- Add set-extension-version-cd.yml to build and cross-build jobs so
binaries get the daily version suffix (not just release artifacts)
- Switch from shared registry-daily.json to per-extension entries
(daily-registry-entries/{id}.json) to avoid race condition when
multiple extension pipelines run concurrently
- Make _manifest removal unconditional before conditional blocks
- Add usage to required fields validation in registry script
- Document YAML regex parsing limitation in code comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…andling
- Replace regex YAML parsing with powershell-yaml for proper parsing
- Wrap JSON output in { extensions: [...] } registry format for azd compatibility
- Move template to eng/templates/, copy scripts into release-metadata artifact
- Flip CreateGitHubRelease default to false, explicit true in release caller
- Add idempotency guard in version script for pipeline retries
- Add placeholder validation, null checks, and file-exists guards
- Split copy steps for clearer error attribution in CI
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add publish-extension-pr.yml stage for PR builds - Add update-extension-pr-registry.yml step for per-extension PR registry - Wire PR publish into release-azd-extension.yml pipeline - Add PR number validation guard for empty/unexpanded values - Add unsigned binary warning to PR comment - Add ConvertTo-JsonSafeString for JSON-safe template replacements - Bump azure.ai.agents version to 0.1.22-preview Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
86a6faa to
49986ec
Compare
|
@danieljurek all 9 extension pipelines should be on the internal ADO project right? currently only azure.ai.models and azure.appservice are internal, the rest run on public and skip sign + publish stages. these did not get PublishForPR:
|
azd Extension Install Instructions —
|
| Platform | Download |
|---|---|
| Linux x86_64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-linux-amd64.tar.gz |
| Linux ARM64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-linux-arm64.tar.gz |
| macOS x86_64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-darwin-amd64.zip |
| macOS ARM64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-darwin-arm64.zip |
| Windows x86_64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-windows-amd64.zip |
| Windows ARM64 | https://azuresdkartifacts.z5.web.core.windows.net/azd/extensions/azure-appservice/pr/7497/azure-appservice-windows-arm64.zip |
What
Daily and PR extension builds to Azure Storage, mirrors core CLI build pattern.
On CI push to main — extensions get signed and uploaded to storage with per-extension registry entries.
On PR builds — same thing but scoped to the PR number, with install instructions posted as a PR comment.
Changes
publish-extension-daily.yml— daily publish stage, depends on Sign, uploads to storagepublish-extension-pr.yml— PR publish stage, uploads to PR-scoped storage, posts install commentpublish-extension.yml—CreateGitHubReleaseparam so daily/PR can skip itrelease-azd-extension.yml— wired daily + PR publish for CI and PR buildsSet-ExtensionVersionInBuild.ps1— appends-daily.or-pr.suffix per build reasonUpdate-ExtensionDailyRegistry.ps1+ JSON template — generates per-extension registry entries with checksumsupdate-extension-pr-registry.yml— uploads PR-scoped registry entryPer-extension registry
Each extension uploads its own entry. No shared blob, no race condition when multiple extensions build concurrently.
How to use — daily builds
Daily registry entries at:
Install a daily build:
How to use — PR builds
PR builds post a comment on the PR with install instructions. Registry entries at:
Install a PR build:
Closes #7317