Skip to content

Require Pester 6 explicitly in local test tooling #169

Require Pester 6 explicitly in local test tooling

Require Pester 6 explicitly in local test tooling #169

Workflow file for this run

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# SECURITY PRECONDITION: The 'ftk-pr' GitHub environment MUST have required
# reviewers configured. The deploy jobs below run azure/login with Contributor +
# User Access Administrator on the subscription and build+deploy the PR's own
# code. For fork PRs (pull_request_target + 'Needs: Deployment' label) that code
# is untrusted, so the environment reviewer gate is the only control preventing a
# labeled fork from deploying malicious templates with CI credentials. This is
# configured by Initialize-CI.ps1; verify reviewers are set before enabling fork
# deployments. See src/scripts/README.md (Initialize-CI).
name: 'PR Deploy'
on:
pull_request:
types: [opened, synchronize, edited]
paths:
- 'src/templates/**'
- '!src/templates/**/README.md'
- '!src/templates/**/docs/**'
- '!src/templates/**/test/**'
pull_request_target:
types: [labeled]
env:
AZ_ACCOUNTS_VERSION: '2.19.0'
AZ_RESOURCES_VERSION: '6.16.2'
AZ_STORAGE_VERSION: '6.2.0'
concurrency:
group: ftk-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
#----------------------------------------------------------------------------
# Parse PR body checkboxes and determine what to deploy
#----------------------------------------------------------------------------
check-options:
name: Check deployment options
runs-on: ubuntu-latest
# Skip fork PRs unless they have the deployment label
if: >
(github.event_name == 'pull_request_target' && github.event.label.name == 'Needs: Deployment')
|| github.event_name == 'pull_request'
outputs:
deploy-adx: ${{ steps.parse.outputs.deploy-adx }}
deploy-fabric: ${{ steps.parse.outputs.deploy-fabric }}
deploy-manual: ${{ steps.parse.outputs.deploy-manual }}
deploy-nodata: ${{ steps.parse.outputs.deploy-nodata }}
deploy-workbooks: ${{ steps.parse.outputs.deploy-workbooks }}
deploy-alerts: ${{ steps.parse.outputs.deploy-alerts }}
fabric-uri: ${{ steps.parse.outputs.fabric-uri }}
templates-changed: ${{ steps.check-files.outputs.changed }}
steps:
- name: Check for template file changes
id: check-files
env:
GH_TOKEN: ${{ github.token }}
run: |
# For 'edited' events, paths filter doesn't apply — verify manually
changed=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only \
| grep -E '^src/templates/' \
| grep -v -E '(README\.md|/docs/|/test/)' \
| head -1)
if [ -n "$changed" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "changed=false" >> "$GITHUB_OUTPUT"
fi
- name: Verify fork PR safety
if: github.event.pull_request.head.repo.full_name != github.repository
env:
GH_TOKEN: ${{ github.token }}
run: |
# Block fork PRs that modify workflow or script files
modified=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only \
| grep -E '^(\.github/|src/scripts/)' \
| head -1)
if [ -n "$modified" ]; then
echo "::error::Fork PRs that modify .github/ or src/scripts/ files cannot use deployment CI."
exit 1
fi
- name: Parse deployment checkboxes
id: parse
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
# Writes "<name>=true|false" to GITHUB_OUTPUT. Always returns 0 — an
# unchecked box is a normal state, not an error, so it must not abort
# the step under `set -e`.
parse_checkbox() {
local pattern="$1"
local output_name="$2"
if echo "$PR_BODY" | grep -qE "\- \[x\] $pattern"; then
echo "$output_name=true" >> "$GITHUB_OUTPUT"
else
echo "$output_name=false" >> "$GITHUB_OUTPUT"
fi
}
parse_checkbox "Hubs \+ ADX \(managed\)" "deploy-adx"
parse_checkbox "Hubs \+ Fabric \(manual\)" "deploy-fabric"
parse_checkbox "Hubs \(manual\)" "deploy-manual"
parse_checkbox "Hubs \(no data\)" "deploy-nodata"
parse_checkbox "Workbooks" "deploy-workbooks"
parse_checkbox "Alerts" "deploy-alerts"
# Extract Fabric URI from the checkbox line
fabric_uri=$(echo "$PR_BODY" | grep -oP '(?<=Hubs \+ Fabric \(manual\) — URI: )\S+' || true)
echo "fabric-uri=$fabric_uri" >> "$GITHUB_OUTPUT"
#----------------------------------------------------------------------------
# Hub deployments
#----------------------------------------------------------------------------
# All deploy jobs use the ftk-pr environment, which MUST have required reviewers
# configured — see the SECURITY PRECONDITION note at the top of this file.
deploy-adx:
name: 'Hubs + ADX (managed)'
needs: check-options
if: needs.check-options.outputs.deploy-adx == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
run: |
./src/scripts/Deploy-Hub -PR ${{ github.event.pull_request.number }} -Name "adx" `
-Scope "${{ secrets.CI_SCOPE }}" -ManagedExports -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-adx"
if [ "${{ job.status }}" = "success" ]; then
body="**Hubs + ADX (managed)** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview)."
else
body="**Hubs + ADX (managed)** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"
deploy-fabric:
name: 'Hubs + Fabric (manual)'
needs: check-options
if: needs.check-options.outputs.deploy-fabric == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Validate Fabric URI
env:
FABRIC_URI: ${{ needs.check-options.outputs.fabric-uri }}
run: |
if [ -z "$FABRIC_URI" ]; then
echo "::error::Hubs + Fabric (manual) checkbox is checked but no URI was provided. Add the eventhouse query URI to the PR body."
exit 1
fi
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
env:
FABRIC_URI: ${{ needs.check-options.outputs.fabric-uri }}
run: |
./src/scripts/Deploy-Hub -PR ${{ github.event.pull_request.number }} -Name "fabric" `
-Fabric "$env:FABRIC_URI" `
-Scope "${{ secrets.CI_SCOPE }}" -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-fabric"
if [ "${{ job.status }}" = "success" ]; then
body="**Hubs + Fabric (manual)** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview). Fabric requires running KQL setup scripts manually."
else
body="**Hubs + Fabric (manual)** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"
deploy-manual:
name: 'Hubs (manual)'
needs: check-options
if: needs.check-options.outputs.deploy-manual == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
run: |
./src/scripts/Deploy-Hub -PR ${{ github.event.pull_request.number }} -Name "manual" `
-StorageOnly -Scope "${{ secrets.CI_SCOPE }}" -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-manual"
if [ "${{ job.status }}" = "success" ]; then
body="**Hubs (manual)** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview)."
else
body="**Hubs (manual)** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"
deploy-nodata:
name: Hubs (no data)
needs: check-options
if: needs.check-options.outputs.deploy-nodata == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
run: |
./src/scripts/Deploy-Hub -PR ${{ github.event.pull_request.number }} -Name "nodata" `
-StorageOnly -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-nodata"
if [ "${{ job.status }}" = "success" ]; then
body="**Hubs (no data)** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview)."
else
body="**Hubs (no data)** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"
#----------------------------------------------------------------------------
# Non-hub deployments
#----------------------------------------------------------------------------
deploy-workbooks:
name: Workbooks
needs: check-options
if: needs.check-options.outputs.deploy-workbooks == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
run: |
./src/scripts/Deploy-Toolkit "finops-workbooks" `
-ResourceGroup "pr-${{ github.event.pull_request.number }}-workbooks" -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-workbooks"
if [ "${{ job.status }}" = "success" ]; then
body="**Workbooks** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview)."
else
body="**Workbooks** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"
deploy-alerts:
name: Alerts
needs: check-options
if: needs.check-options.outputs.deploy-alerts == 'true' && needs.check-options.outputs.templates-changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'ftk-fork' || 'ftk-pr' }}
steps:
- name: Restore Az modules
id: az-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: /home/runner/.local/share/powershell/Modules
key: az-modules-${{ env.AZ_ACCOUNTS_VERSION }}-${{ env.AZ_RESOURCES_VERSION }}-${{ env.AZ_STORAGE_VERSION }}
- name: Install Az modules
if: steps.az-cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
Set-PSRepository PSGallery -InstallationPolicy Trusted
Install-Module -Name Az.Accounts -RequiredVersion $env:AZ_ACCOUNTS_VERSION -Force
Install-Module -Name Az.Resources -RequiredVersion $env:AZ_RESOURCES_VERSION -Force
Install-Module -Name Az.Storage -RequiredVersion $env:AZ_STORAGE_VERSION -Force
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Azure login
uses: azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6 # v2.3.1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Deploy
shell: pwsh
run: |
./src/scripts/Deploy-Toolkit "finops-alerts" `
-ResourceGroup "pr-${{ github.event.pull_request.number }}-alerts" -Build
- name: Post PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
pr=${{ github.event.pull_request.number }}
rg="pr-$pr-alerts"
if [ "${{ job.status }}" = "success" ]; then
body="**Alerts** deployed to [\`$rg\`](https://portal.azure.com/#@/resource/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$rg/overview)."
else
body="**Alerts** deployment failed. [View logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
fi
gh pr comment "$pr" --repo "${{ github.repository }}" --body "$body"