Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions .github/skills/integration-test-prerequisites/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: "integration-test-prerequisites"
description: "Set up Azure and GitHub prerequisites for integration workflows using a user-assigned managed identity, OIDC federated credentials, RBAC roles, and environment secrets. Use when troubleshooting AADSTS70025/AADSTS700213 or authorization failures during integration-test or integration-redact-secrets workflow runs."
description: "Set up Azure and GitHub prerequisites for integration and release-tests workflows using a user-assigned managed identity, OIDC federated credentials, RBAC roles, and environment secrets. Use when troubleshooting AADSTS70025/AADSTS700213 or authorization failures during integration-test or release-tests workflow runs."
domain: "ci-cd"
confidence: "high"
source: "manual + observed from integration-test OIDC and RBAC troubleshooting"
Expand All @@ -10,14 +10,19 @@ source: "manual + observed from integration-test OIDC and RBAC troubleshooting"

Use this skill when preparing or repairing prerequisites for:

- `.github/workflows/integration-test.yml`
- `.github/workflows/integration-redact-secrets.yml`
- `.github/workflows/test-round-trip.yml` — Extract→Publish round-trip
- `.github/workflows/test-redact-secrets.yml` — Secret redaction validation
- `.github/workflows/test-all.yml` — Orchestrator that calls CI, then both integration-test workflows sequentially

All integration-test workflows share the same GitHub environment (`integration-test`) and Azure identity. Setting up prerequisites once covers all three workflows.

These workflows expect:
- OIDC login through `azure/login@v2`
- GitHub environment `integration-test` (shared by both workflows)
- OIDC login through `azure/login@v3`
- GitHub environment `integration-test` (shared by all integration workflows)
- Azure identity with enough permissions to deploy resources and create role assignments in test resource groups

The `test-all.yml` orchestrator calls `ci.yml` (no Azure prereqs), then `test-round-trip.yml` and `test-redact-secrets.yml`. The called workflows access secrets directly from the `integration-test` environment — no secret pass-through from the orchestrator is needed.

Preferred identity model: user-assigned managed identity (UAMI).

## Required Inputs
Expand Down Expand Up @@ -135,12 +140,19 @@ gh secret set AZURE_SUBSCRIPTION_ID \
--env "${GITHUB_ENVIRONMENT}" \
--body "${SUBSCRIPTION_ID}"

# Optional — falls back to apim-integration-test@contoso.com if not set
gh secret set APIM_PUBLISHER_EMAIL \
--repo "${GITHUB_OWNER}/${GITHUB_REPO}" \
--env "${GITHUB_ENVIRONMENT}" \
--body "${APIM_PUBLISHER_EMAIL}"
```

### 6) Verify Called Workflows Can Access Environment Secrets

The `test-all.yml` orchestrator does **not** pass secrets to called workflows. Instead, the called workflows (`test-round-trip.yml`, `test-redact-secrets.yml`) access secrets directly via their `environment: integration-test` declaration. Each called workflow includes a "Validate Required Secrets" step that fails fast with a clear error if any secret is missing.

No repo-level secrets are required — all secrets are scoped to the `integration-test` environment.

## Verification

```bash
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
pull_request:
branches:
- main
workflow_call:

permissions:
contents: read
Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
# ===========================================================================
# Release Tests — Run all test suites in order before a release.
# ===========================================================================
# Executes unit tests, build-package integration tests, and the full
# extract→publish round-trip integration test sequentially. Fails fast:
# subsequent stages are skipped if any prior stage fails.
# ===========================================================================

name: "Test: Release Tests"

on:
schedule:
- cron: '0 9 1 * *' # 1st of every month at 9:00 UTC
workflow_dispatch:
inputs:
sku:
description: 'APIM SKU for all-types integration test'
required: true
type: choice
options:
- Standard
- StandardV2
- Premium
- PremiumV2
default: StandardV2
location:
description: 'Azure region for all-types integration test'
required: false
type: string
default: 'centralus'
log_level:
description: 'Log level'
required: false
type: choice
options:
- Info
- Verbose
- Debug
default: Verbose

permissions:
contents: read

jobs:
ci:
name: CI (Unit + Build Package Tests)
uses: ./.github/workflows/ci.yml

all-types-integration:
name: All-Types Integration Test
needs: ci
permissions:
contents: read
id-token: write
uses: ./.github/workflows/test-round-trip.yml
with:
sku: ${{ inputs.sku || vars.DEFAULT_SKU || 'StandardV2' }}
location: ${{ inputs.location || vars.DEFAULT_LOCATION || 'centralus' }}
log_level: ${{ inputs.log_level || vars.DEFAULT_LOG_LEVEL || 'Verbose' }}

redact-secrets-integration:
name: Redact Secrets Integration Test
needs: all-types-integration
permissions:
contents: read
id-token: write
uses: ./.github/workflows/test-redact-secrets.yml
with:
sku: ${{ inputs.sku || vars.DEFAULT_SKU || 'StandardV2' }}
location: ${{ inputs.location || vars.DEFAULT_LOCATION || 'centralus' }}
log_level: ${{ inputs.log_level || vars.DEFAULT_LOG_LEVEL || 'Verbose' }}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ on:
type: string
default: 'centralus'
log_level:
description: 'PowerShell log level (Info, Verbose, Debug)'
description: 'Log level'
required: false
type: string
type: choice
options:
- Info
- Verbose
- Debug
default: Verbose

workflow_call:
Expand All @@ -40,21 +44,10 @@ on:
type: string
default: 'centralus'
log_level:
description: 'PowerShell log level (Info, Verbose, Debug)'
description: 'Log level'
required: false
type: string
default: Verbose
secrets:
AZURE_CLIENT_ID:
required: true
AZURE_TENANT_ID:
required: true
AZURE_SUBSCRIPTION_ID:
required: true
APIM_PUBLISHER_EMAIL:
required: true
APIM_SKU:
required: false

permissions:
id-token: write
Expand All @@ -64,6 +57,10 @@ concurrency:
group: integration-redact-secrets
cancel-in-progress: false

env:
DEFAULT_LOCATION: centralus
DEFAULT_PUBLISHER_EMAIL: apim-integration-test@contoso.com

jobs:
redact-secrets-test:
name: Extract Secret Redaction
Expand All @@ -82,22 +79,17 @@ jobs:

- run: npm ci && npm run build

- name: Resolve Workflow Settings
id: settings
shell: pwsh
- name: Validate Required Secrets
shell: bash
run: |
$logLevel = '${{ inputs.log_level }}'
if ([string]::IsNullOrWhiteSpace($logLevel)) { $logLevel = 'Verbose' }
if ($logLevel -notin @('Info', 'Verbose', 'Debug')) {
throw "Invalid log_level '$logLevel'. Allowed values: Info, Verbose, Debug."
}

$skuName = '${{ secrets.APIM_SKU }}'
if ([string]::IsNullOrWhiteSpace($skuName)) { $skuName = '${{ inputs.sku }}' }
if ([string]::IsNullOrWhiteSpace($skuName)) { $skuName = 'StandardV2' }

"logLevel=$logLevel" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
"skuName=$skuName" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
missing=()
[[ -z "${{ secrets.AZURE_CLIENT_ID }}" ]] && missing+=("AZURE_CLIENT_ID")
[[ -z "${{ secrets.AZURE_TENANT_ID }}" ]] && missing+=("AZURE_TENANT_ID")
[[ -z "${{ secrets.AZURE_SUBSCRIPTION_ID }}" ]] && missing+=("AZURE_SUBSCRIPTION_ID")
if [[ ${#missing[@]} -gt 0 ]]; then
echo "::error::Missing required secrets: ${missing[*]}"
exit 1
fi

- name: Azure Login
uses: azure/login@v3
Expand All @@ -106,6 +98,17 @@ jobs:
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Validate Azure Region
shell: bash
run: |
LOCATION="${{ inputs.location }}"
if [[ -z "$LOCATION" ]]; then LOCATION="${{ env.DEFAULT_LOCATION }}"; fi
VALID_LOCATIONS=$(az account list-locations --query "[].name" -o tsv)
if ! echo "$VALID_LOCATIONS" | grep -qx "$LOCATION"; then
echo "::error::Invalid Azure region: '$LOCATION'. Run 'az account list-locations --query [].name' to see valid options."
exit 1
fi

- name: Run redaction integration test
shell: pwsh
env:
Expand All @@ -114,7 +117,7 @@ jobs:
run: |
./tests/integration/redact-secrets/run-redact-secrets-test.ps1 `
-SourceSubscriptionId '${{ secrets.AZURE_SUBSCRIPTION_ID }}' `
-PublisherEmail '${{ secrets.APIM_PUBLISHER_EMAIL }}' `
-SkuName '${{ steps.settings.outputs.skuName }}' `
-PublisherEmail '${{ secrets.APIM_PUBLISHER_EMAIL || env.DEFAULT_PUBLISHER_EMAIL }}' `
-SkuName '${{ inputs.sku }}' `
-Location '${{ inputs.location }}' `
-LogLevel '${{ steps.settings.outputs.logLevel }}'
-LogLevel '${{ inputs.log_level }}'
Loading