[DevOps] PR Builds: PR deployment and cleanup workflows#2033
[DevOps] PR Builds: PR deployment and cleanup workflows#2033
Conversation
Creates two GitHub Actions workflows for per-PR template deployments:
ftk-pr-deploy.yml:
- Triggers on PRs that change src/templates/** files
- Parses PR body checkboxes to determine deployment variants
- Supports: ADX (managed), Fabric (manual), manual, no-data, workbooks, alerts
- Each variant deploys in parallel with isolated resource groups (pr-{number}-{variant})
- Posts PR comments with deployment status and portal links
- Supports fork PRs via "Needs: Deployment" label + pull_request_target
- Verifies fork PRs don't modify .github/ files
ftk-pr-cleanup.yml:
- Triggers on PR close (merged or not)
- Deletes all resource groups matching pr-{number}-*
- Posts cleanup confirmation comment
- Creates GitHub issue assigned to PR author if cleanup fails
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds GitHub Actions workflows to support per-PR Azure template deployments (FinOps hubs + variants, workbooks, alerts) and automatic cleanup of PR-specific resource groups, aligning with the toolkit’s CI automation goals for validating src/templates/** changes.
Changes:
- Introduces
ftk-pr-deploy.ymlto parse PR-body deployment checkboxes and run selected deployments with PR-scoped resource groups. - Introduces
ftk-pr-cleanup.ymlto delete PR-scoped resource groups on PR close and notify via PR comment / issue on failure.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
.github/workflows/ftk-pr-deploy.yml |
New per-PR deployment workflow (checkbox parsing, fork label gating, parallel deployment jobs, PR comments). |
.github/workflows/ftk-pr-cleanup.yml |
New cleanup workflow to remove pr-{number}-* resource groups and report failures. |
.github/workflows/ftk-pr-deploy.yml
Outdated
| - name: Parse deployment checkboxes | ||
| id: parse | ||
| run: | | ||
| body='${{ github.event.pull_request.body }}' | ||
|
|
||
| parse_checkbox() { | ||
| local pattern="$1" | ||
| local output_name="$2" | ||
| if echo "$body" | grep -qE "\- \[x\] $pattern"; then | ||
| echo "$output_name=true" >> "$GITHUB_OUTPUT" | ||
| return 0 | ||
| else | ||
| echo "$output_name=false" >> "$GITHUB_OUTPUT" | ||
| return 1 | ||
| fi | ||
| } | ||
|
|
||
| any=false | ||
|
|
||
| parse_checkbox "Hubs + ADX \(managed\)" "deploy-adx" && any=true | ||
| parse_checkbox "Hubs + Fabric \(manual\)" "deploy-fabric" && any=true | ||
| parse_checkbox "Hubs \(manual\)" "deploy-manual" && any=true | ||
| parse_checkbox "Hubs \(no data\)" "deploy-nodata" && any=true | ||
| parse_checkbox "Workbooks" "deploy-workbooks" && any=true | ||
| parse_checkbox "Alerts" "deploy-alerts" && any=true | ||
|
|
||
| echo "any-selected=$any" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
This workflow depends on PR-template checkboxes, but the current .github/PULL_REQUEST_TEMPLATE.md in the repo does not contain the referenced deployment options. As-is, any-selected will never become true and no deployments will run. Either include/update the PR template in this PR or ensure the checkbox text here matches the merged template exactly (and document the dependency).
There was a problem hiding this comment.
This is a known dependency. We're holding the PR in a draft state until #2031 is complete.
- Fix PR body script injection: use env var instead of inline interpolation - Escape literal + in regex patterns for checkbox matching - Fix azure/login: use @v2 release tag instead of branch ref - Fix job name typo: "Hubs + (manual)" → "Hubs (manual)" - Remove unused any-selected output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tighten pull_request_target condition to only fire on Needs: Deployment label - Expand fork safety check to block src/scripts/ changes - Add Fabric URI validation before deploy (fails fast as first step) - Change cleanup trigger to pull_request_target for fork PR secret access - Add -ErrorAction Stop to Remove-AzResourceGroup for proper error handling - Fix assignee fallback for external contributors on cleanup failure issues 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
🤖 [AI][Claude] PR Update Summary Addressed: 9 thread(s)
Changes:
Push-backs (code already correct):
|
| shell: pwsh | ||
| run: | | ||
| ./src/scripts/Deploy-Hub -PR -Name "${{ github.event.pull_request.number }}-fabric" ` | ||
| -Fabric "${{ needs.check-options.outputs.fabric-uri }}" ` |
There was a problem hiding this comment.
Script injection risk: fabric-uri is extracted from the PR body (user-controlled) and interpolated directly into a shell command via ${{ needs.check-options.outputs.fabric-uri }}. A malicious PR body could inject arbitrary PowerShell here.
This should use an environment variable (like the PR body fix in commit 2):
env:
FABRIC_URI: ${{ needs.check-options.outputs.fabric-uri }}
run: |
./src/scripts/Deploy-Hub -PR -Name "..." -Fabric "$env:FABRIC_URI" ...| enable-AzPSSession: true | ||
|
|
||
| - name: Deploy | ||
| shell: pwsh |
There was a problem hiding this comment.
pull_request_target + checkout head.sha security concern: This is the classic pull_request_target vulnerability pattern. The fork safety check blocks .github/ and src/scripts/ modifications, but an attacker could still modify Bicep templates in src/templates/ to deploy malicious ARM resources using the CI credentials (Contributor + User Access Administrator on the subscription). The safety check would need to be much more restrictive (or use an approval gate on the ftk-pr environment) to fully mitigate this.
|
|
||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} |
There was a problem hiding this comment.
Massive step duplication: The Az module install + Azure login + checkout + post-comment steps are copy-pasted across all 6 jobs (~50 lines each). A reusable workflow or composite action would cut this significantly and make future updates (e.g., bumping module versions) a single-line change.
| - name: Install Az modules | ||
| shell: pwsh | ||
| run: | | ||
| Set-PSRepository PSGallery -InstallationPolicy Trusted |
There was a problem hiding this comment.
No job timeout: None of the deployment jobs set timeout-minutes. ADX deployments in particular can run long, and without a cap this could lead to runaway CI costs. Consider adding timeout-minutes: 30 (or appropriate value) to each job.
| ref: ${{ github.event.pull_request.head.sha }} | ||
|
|
||
| - name: Azure login | ||
| uses: azure/login@v2 |
There was a problem hiding this comment.
Hardcoded Az module versions: Az.Accounts 2.19.0, Az.Resources 6.16.2, Az.Storage 6.2.0 are pinned across 6 jobs with no note about when/how to update. These will go stale — consider centralizing them as workflow-level env variables at minimum.
🛠️ Description
Adds two GitHub Actions workflows for per-PR template deployment CI:
ftk-pr-deploy.ymlsrc/templates/**files (excluding docs/tests)pr-{number}-{variant}):Needs: Deploymentlabel +pull_request_target(verifies no.github/modifications)ftk-pr-cleanup.ymlpr-{number}-*Dependencies
-PR,-Scope,-ManagedExportsparametersThis is PR D (final) of a multi-PR effort to add per-PR deployment CI.
📋 Checklist
🔬 How did you test this change?
🙋♀️ Do any of the following that apply?
📑 Did you update
docs/changelog.md?📖 Did you update documentation?