@peterhauge/apiops-cli 0.3.0-alpha.0 → 0.4.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +166 -0
- package/README.md +6 -0
- package/dist/cli/init-command.js +5 -5
- package/dist/cli/init-command.js.map +1 -1
- package/dist/lib/render-template.d.ts +10 -0
- package/dist/lib/render-template.d.ts.map +1 -0
- package/dist/lib/render-template.js +14 -0
- package/dist/lib/render-template.js.map +1 -0
- package/dist/services/api-extractor.d.ts.map +1 -1
- package/dist/services/api-extractor.js +10 -6
- package/dist/services/api-extractor.js.map +1 -1
- package/dist/services/extract-service.d.ts.map +1 -1
- package/dist/services/extract-service.js +4 -2
- package/dist/services/extract-service.js.map +1 -1
- package/dist/services/identity-guide-service.d.ts +3 -4
- package/dist/services/identity-guide-service.d.ts.map +1 -1
- package/dist/services/identity-guide-service.js +6 -40
- package/dist/services/identity-guide-service.js.map +1 -1
- package/dist/services/init-service.d.ts.map +1 -1
- package/dist/services/init-service.js +61 -28
- package/dist/services/init-service.js.map +1 -1
- package/dist/services/product-extractor.d.ts.map +1 -1
- package/dist/services/product-extractor.js +4 -2
- package/dist/services/product-extractor.js.map +1 -1
- package/dist/services/publish-service.d.ts.map +1 -1
- package/dist/services/publish-service.js +30 -0
- package/dist/services/publish-service.js.map +1 -1
- package/dist/services/resource-publisher.d.ts +5 -0
- package/dist/services/resource-publisher.d.ts.map +1 -1
- package/dist/services/resource-publisher.js +15 -1
- package/dist/services/resource-publisher.js.map +1 -1
- package/dist/services/secret-redaction-guard.d.ts +40 -0
- package/dist/services/secret-redaction-guard.d.ts.map +1 -0
- package/dist/services/secret-redaction-guard.js +92 -0
- package/dist/services/secret-redaction-guard.js.map +1 -0
- package/dist/services/secret-redactor.d.ts +18 -0
- package/dist/services/secret-redactor.d.ts.map +1 -1
- package/dist/services/secret-redactor.js +172 -0
- package/dist/services/secret-redactor.js.map +1 -1
- package/dist/templates/azure-devops/publish-pipeline.d.ts.map +1 -1
- package/dist/templates/azure-devops/publish-pipeline.js +62 -28
- package/dist/templates/azure-devops/publish-pipeline.js.map +1 -1
- package/dist/templates/configs/filter-config.d.ts.map +1 -1
- package/dist/templates/configs/filter-config.js +6 -118
- package/dist/templates/configs/filter-config.js.map +1 -1
- package/dist/templates/configs/override-config.d.ts.map +1 -1
- package/dist/templates/configs/override-config.js +7 -92
- package/dist/templates/configs/override-config.js.map +1 -1
- package/dist/templates/configs/schema-ref.d.ts +18 -0
- package/dist/templates/configs/schema-ref.d.ts.map +1 -0
- package/dist/templates/configs/schema-ref.js +26 -0
- package/dist/templates/configs/schema-ref.js.map +1 -0
- package/dist/templates/copilot/configure-filter-prompt.d.ts +10 -0
- package/dist/templates/copilot/configure-filter-prompt.d.ts.map +1 -0
- package/dist/templates/copilot/configure-filter-prompt.js +14 -0
- package/dist/templates/copilot/configure-filter-prompt.js.map +1 -0
- package/dist/templates/copilot/configure-overrides-prompt.d.ts +7 -0
- package/dist/templates/copilot/configure-overrides-prompt.d.ts.map +1 -0
- package/dist/templates/copilot/configure-overrides-prompt.js +12 -0
- package/dist/templates/copilot/configure-overrides-prompt.js.map +1 -0
- package/dist/templates/copilot/identity-setup-prompt.d.ts.map +1 -1
- package/dist/templates/copilot/identity-setup-prompt.js +19 -24
- package/dist/templates/copilot/identity-setup-prompt.js.map +1 -1
- package/dist/templates/generated/embedded-markdown.d.ts +8 -5
- package/dist/templates/generated/embedded-markdown.d.ts.map +1 -1
- package/dist/templates/generated/embedded-markdown.js +8 -5
- package/dist/templates/generated/embedded-markdown.js.map +1 -1
- package/dist/templates/github-actions/extract-workflow.js +4 -4
- package/dist/templates/github-actions/publish-workflow.d.ts +2 -1
- package/dist/templates/github-actions/publish-workflow.d.ts.map +1 -1
- package/dist/templates/github-actions/publish-workflow.js +103 -78
- package/dist/templates/github-actions/publish-workflow.js.map +1 -1
- package/package.json +8 -5
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* AUTO-GENERATED FILE.
|
|
3
3
|
* Generated by scripts/embed-markdown-templates.mjs
|
|
4
4
|
*/
|
|
5
|
-
export declare const copilotGitHubActionsIdentitySetupPromptTemplate: "# Setup GitHub Actions Identity for APIOps\n\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\n> Copilot to help you run through the steps. Copilot will prompt you for\n> the required values and generate the exact CLI commands for your environment.\n\n## Goal\n\nConfigure Azure AD federated credentials and GitHub repository secrets so the\nAPIOps extract and publish workflows can authenticate to Azure using OIDC\n(no stored client secrets needed).\n\n---\n\n## Step 0 \u2014 Tool Authentication Check\n\n**Copilot: Before proceeding, verify that all required tools are installed and authenticated.**\n\nRun these checks and present results in a table:\n\n### Check Azure CLI\n```bash\naz version\naz account show --query \"{Subscription:name, Account:user.name, TenantId:tenantId}\" -o json\n```\n\n### Check GitHub CLI\n```bash\ngh auth status\n```\n\n### Present Status Table\n\nPresent the results to the user in this format:\n\n```\n\uD83D\uDD10 Tool Authentication Status:\n\n| Tool | Status | Account/User | Subscription/Org | Tenant/Details |\n|------|--------|--------------|------------------|----------------|\n| Azure CLI | \u2705 Logged in | user@example.com | my-subscription | abc-123-... |\n| GitHub CLI | \u2705 Logged in | username | github.com | \u2014 |\n```\n\n**Status indicators:**\n- \u2705 Logged in \u2014 tool is authenticated and ready\n- \u274C Not logged in \u2014 tool needs authentication\n- \u26A0\uFE0F Not installed \u2014 tool is missing entirely\n\n### Fix Missing Authentication\n\n**If Azure CLI is not logged in:**\n> \"Azure CLI is required for this setup. Run `az login` to authenticate, then I'll continue.\"\n\n**If GitHub CLI is not logged in:**\n> \"GitHub CLI is required for configuring repository secrets. Run `gh auth login` to authenticate.\"\n\n**If any required tool is not installed:**\n- Azure CLI: Install from https://aka.ms/installazurecli\n- GitHub CLI: Install from https://cli.github.com\n\nOnce both tools are authenticated, ask the user to confirm:\n> \"Does this authentication look correct? (yes / need to switch accounts)\"\n\nIf the user needs to switch accounts, help them with:\n- Azure CLI: `az account set --subscription <id>` or `az login --tenant <tenant-id>`\n- GitHub CLI: `gh auth logout` then `gh auth login`\n\nOnce confirmed, proceed to Step 1.\n\n---\n\n## Step 1 \u2014 Gather Information\n\nCopilot, please ask the user for the following values before proceeding. Store\neach answer for use in later steps.\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n{{ENV_SUBSCRIPTION_TABLE_ROWS}}\n| `AZURE_TENANT_ID` | Azure AD tenant ID (same for all environments) | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |\n| `GITHUB_ORG` | GitHub organization or user that owns the repo | `my-org` |\n| `GITHUB_REPO` | GitHub repository name | `apim-artifacts` |\n| `APP_NAME` | Display name for the Azure AD application | `apiops-github-sp` |\n{{ENV_APIM_TABLE_ROWS}}\n\n---\n\n## Step 2 \u2014 Create Azure AD Application & Service Principal\n\n> \u26A0\uFE0F **Error Handling:** If any command fails, stop immediately and show the user the full error output verbatim. Do NOT retry silently. Common issues include insufficient permissions (requires Application Administrator or Global Administrator role in Azure AD).\n\n**On macOS/Linux (Bash):**\n```bash\n# Create the Azure AD application\nAPP_ID=$(az ad app create \\\n --display-name \"${APP_NAME}\" \\\n --query appId -o tsv)\n\n# Create the service principal for the application\naz ad sp create --id \"$APP_ID\"\n\necho \"Application (client) ID: $APP_ID\"\necho \"Tenant ID: $(az account show --query tenantId -o tsv)\"\n```\n\n**On Windows (PowerShell):**\n```powershell\n# Create the Azure AD application\n$APP_ID = az ad app create `\n --display-name \"${APP_NAME}\" `\n --query appId -o tsv\n\n# Create the service principal for the application\naz ad sp create --id $APP_ID\n\nWrite-Host \"Application (client) ID: $APP_ID\"\nWrite-Host \"Tenant ID: $(az account show --query tenantId -o tsv)\"\n```\n\n---\n\n## Step 3 \u2014 Assign RBAC Roles\n\nGrant the service principal the required permissions:\n1. **Reader** role on each resource group (to read resource groups and resources)\n2. **API Management Service Contributor** on each APIM instance (to manage APIM resources)\n\n> **Note:** Each environment can be in a different Azure subscription. The service principal will be granted access to all environments.\n\n### Grant Reader role on each resource group\n\n{{ENV_READER_ROLE_SNIPPETS}}\n\n### Grant API Management Service Contributor on each APIM instance\n\n{{ENV_APIM_ROLE_SNIPPETS}}\n\n---\n\n## Step 4 \u2014 Create Federated Credentials for GitHub OIDC\n\n> \u26A0\uFE0F **Platform Note:** The JSON parameters for federated credentials require different escaping on Windows PowerShell vs macOS/Linux Bash. Use the appropriate command block for your platform.\n\n### Main branch (for push-triggered publish workflow)\n\n**On macOS/Linux (Bash):**\n```bash\naz ad app federated-credential create \\\n --id \"$APP_ID\" \\\n --parameters '{\n \"name\": \"github-main-branch\",\n \"issuer\": \"https://token.actions.githubusercontent.com\",\n \"subject\": \"repo:'\"${GITHUB_ORG}\"'/'\"${GITHUB_REPO}\"':ref:refs/heads/main\",\n \"audiences\": [\"api://AzureADTokenExchange\"]\n }'\n```\n\n**On Windows (PowerShell):**\n```powershell\naz ad app federated-credential create `\n --id $APP_ID `\n --parameters '{\\\"name\\\":\\\"github-main-branch\\\",\\\"issuer\\\":\\\"https://token.actions.githubusercontent.com\\\",\\\"subject\\\":\\\"repo:'${GITHUB_ORG}'/'${GITHUB_REPO}':ref:refs/heads/main\\\",\\\"audiences\\\":[\\\"api://AzureADTokenExchange\\\"]}'\n```\n\n{{ENV_FEDERATED_CREDENTIALS}}\n\n---\n\n## Step 5 \u2014 Create GitHub Environments\n\n```bash\n{{ENVIRONMENT_CREATION_COMMANDS}}\n```\n\n---\n\n## Step 6 \u2014 Set GitHub Repository Secrets\n\n> \u26A0\uFE0F **Platform Note:** GitHub CLI secret commands work identically on all platforms, but variable syntax differs between Bash and PowerShell.\n\n**On macOS/Linux (Bash):**\n```bash\n# Repository-level secrets (shared across all workflows)\ngh secret set AZURE_CLIENT_ID --body \"$APP_ID\"\ngh secret set AZURE_TENANT_ID --body \"${AZURE_TENANT_ID}\"\n\n{{GH_SECRET_ENV_COMMANDS}}\n```\n\n**On Windows (PowerShell):**\n```powershell\n# Repository-level secrets (shared across all workflows)\ngh secret set AZURE_CLIENT_ID --body $APP_ID\ngh secret set AZURE_TENANT_ID --body \"${AZURE_TENANT_ID}\"\n\n{{GH_SECRET_ENV_COMMANDS}}\n```\n\n---\n\n## Step 7 \u2014 Verify\n\n> \u26A0\uFE0F **Important:** If any verification step fails, show the user the full error output and help troubleshoot before proceeding. Common issues include RBAC permissions not yet propagated (can take 5-10 minutes) or missing secrets.\n\n1. Go to **Actions** \u2192 **Run APIM Extractor** \u2192 **Run workflow**\n2. Fill in the resource group and service name for your dev environment\n3. Confirm the workflow completes and a pull request is created\n\nIf the workflow fails with authentication errors:\n- Check that all secrets are set correctly in GitHub: Settings \u2192 Secrets and variables \u2192 Actions\n- Verify RBAC role assignments have propagated (wait 5-10 minutes and retry)\n- Confirm the federated credentials were created: `az ad app federated-credential list --id $APP_ID`\n\n---\n\n## Secrets Reference\n\nThe generated workflows expect these secrets:\n\n### Repository Secrets\n- `AZURE_CLIENT_ID` \u2014 App registration client ID (shared across all environments)\n- `AZURE_TENANT_ID` \u2014 Azure AD tenant ID (shared across all environments)\n\n### Per-Environment Secrets\n{{ENV_SECRETS_REFERENCE}}\n";
|
|
6
|
-
export declare const copilotAzureDevOpsIdentitySetupPromptTemplate: "# Setup Azure DevOps Identity for APIOps\n\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\n> Copilot to help you run through the steps. Copilot will prompt you for\n> required values and generate exact CLI commands for your environment.\n\n## Goal\n\nConfigure workload identity federation (OIDC), Azure DevOps federated service connections,\nand variable groups\nfor APIOps extract and publish pipelines.\n\n{{AZURE_DEVOPS_CORE_STEPS}}\n\n## Step 10: Enable Pipeline Contributions\n\nGrant the Build Service permission to contribute to the repository.\n\n**PowerShell:**\n```powershell\n$PROJECT_ID = az devops project show --project $AZDO_PROJECT --query id -o tsv\n$REPO_NAME = $AZDO_PROJECT\n$REPO_ID = az repos show --repository $REPO_NAME --query id -o tsv\n\n$GRAPH_USERS = az devops invoke --area graph --resource users --query-parameters 'api-version=7.1-preview.1' --http-method GET -o json | ConvertFrom-Json\n$BUILD_SERVICE_NAME = \"$AZDO_PROJECT Build Service ($ORG_NAME)\"\n$BUILD_SERVICE_DESCRIPTOR = ($GRAPH_USERS.value | Where-Object { $_.displayName -eq $BUILD_SERVICE_NAME }).descriptor\n\n$GIT_REPOS_NAMESPACE = az devops security permission namespace list --query \"[?name=='Git Repositories'].namespaceId\" -o tsv\n$TOKEN = \"repoV2/$PROJECT_ID/$REPO_ID\"\naz devops security permission update --namespace-id $GIT_REPOS_NAMESPACE --subject $BUILD_SERVICE_DESCRIPTOR --token $TOKEN --allow-bit 4\n```\n\n**Git Bash:**\n```bash\nPROJECT_ID=$(az devops project show --project \"$AZDO_PROJECT\" --query id -o tsv)\nREPO_NAME=\"$AZDO_PROJECT\"\nREPO_ID=$(az repos show --repository \"$REPO_NAME\" --query id -o tsv)\n\nBUILD_SERVICE_NAME=\"$AZDO_PROJECT Build Service ($ORG_NAME)\"\nBUILD_SERVICE_DESCRIPTOR=$(az devops invoke --area graph --resource users --query-parameters 'api-version=7.1-preview.1' --http-method GET -o json | grep -B5 \"\\\"displayName\\\": \\\"$BUILD_SERVICE_NAME\\\"\" | grep '\"descriptor\"' | head -1 | cut -d'\"' -f4)\n\nGIT_REPOS_NAMESPACE=$(az devops security permission namespace list --query \"[?name=='Git Repositories'].namespaceId\" -o tsv)\nTOKEN=\"repoV2/$PROJECT_ID/$REPO_ID\"\naz devops security permission update --namespace-id \"$GIT_REPOS_NAMESPACE\" --subject \"$BUILD_SERVICE_DESCRIPTOR\" --token \"$TOKEN\" --allow-bit 4\n```\n\n---\n\n## Step 11: Verify Setup\n\nVerify all resources were created correctly:\n\n**Service Connections:**\n```bash\naz devops service-endpoint list --query \"[].name\" -o table\n```\n\n**Variable Groups:**\n```bash\naz pipelines variable-group list --query \"[].name\" -o table\n```\n\nRun the APIOps pipelines and confirm they can authenticate and access APIM resources.\n\n---\n\n## Step 12: Create Pipelines\n\nCreate Azure Pipelines from the YAML files in your repository.\n\n**PowerShell:**\n```powershell\n$REPO_NAME = $AZDO_PROJECT\n\naz pipelines create --name \"apiops-extract\" --repository $REPO_NAME --branch main --yml-path \".azdo/pipelines/run-apim-extractor.yml\" --repository-type tfsgit --skip-first-run true\naz pipelines create --name \"apiops-publish\" --repository $REPO_NAME --branch main --yml-path \".azdo/pipelines/run-apim-publisher.yml\" --repository-type tfsgit --skip-first-run true\n```\n\n**Git Bash:**\n```bash\nREPO_NAME=\"$AZDO_PROJECT\"\n\naz pipelines create --name \"apiops-extract\" --repository \"$REPO_NAME\" --branch main --yml-path \".azdo/pipelines/run-apim-extractor.yml\" --repository-type tfsgit --skip-first-run true\naz pipelines create --name \"apiops-publish\" --repository \"$REPO_NAME\" --branch main --yml-path \".azdo/pipelines/run-apim-publisher.yml\" --repository-type tfsgit --skip-first-run true\n```\n\nVerify pipelines were created:\n```bash\naz pipelines list --query \"[].name\" -o table\n```";
|
|
7
|
-
export declare const azureDevOpsIdentitySetupCoreTemplate: "## Prerequisites\n- Azure DevOps organization and project\n- Azure CLI installed and authenticated (`az login`)\n- `az devops` extension (`az extension add --name azure-devops`)\n\nThis flow is designed for Microsoft-hosted or self-hosted agents and uses workload identity federation (OIDC) instead of managed identity.\n\n> **Note:** All commands are shown for both **PowerShell** and **Git Bash** where syntax differs.\n\n---\n\n## Step 1: Gather Per-Environment Information\n\n**Copilot:** Ask the user for the following values before proceeding. Store each answer for use in later steps.\n\nFor each environment, provide either **Option A** (three separate values) or **Option B** (a single full APIM resource ID in the form `/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>`). Copilot will parse Option B into the individual components automatically.\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `APP_NAME` | Display name for the Entra application | `apiops-azdo-sp` |\n| `AZDO_ORG` | Azure DevOps organization URL | `https://dev.azure.com/my-org` |\n| `AZDO_PROJECT` | Azure DevOps project name | `my-project` |\n| `TENANT_ID` | Tenant ID that should own the app/service connection | `11111111-2222-3333-4444-555555555555` |\n\nFor each environment in the configured list, gather these values (where `<ENV_UPPER>` is the upper-case environment name):\n- `APIM_SUBSCRIPTION_<ENV_UPPER>`\n- `APIM_RG_<ENV_UPPER>`\n- `APIM_NAME_<ENV_UPPER>`\n- `APIM_RESOURCE_ID_<ENV_UPPER>` *(optional Option B shorthand)*\n\n---\n\n## Step 2: Set Variables\n\n**PowerShell:**\n```powershell\n$APP_NAME = \"apiops-azdo-sp\"\n$AZDO_ORG = \"<your-azdo-org-url>\"\n$AZDO_PROJECT = \"<your-project>\"\n$TENANT_ID = \"<your-tenant-id>\"\n$ENVIRONMENTS = @({{ENVIRONMENTS_ARRAY_POWERSHELL}})\n\n# Fill these maps with values for each environment.\n$APIM_SUBSCRIPTIONS = @{}\n$APIM_RESOURCE_GROUPS = @{}\n$APIM_SERVICE_NAMES = @{}\n\nforeach ($env in $ENVIRONMENTS) {\n # Option A: provide values directly.\n $APIM_SUBSCRIPTIONS[$env] = \"<subscription-id-for-$env>\"\n $APIM_RESOURCE_GROUPS[$env] = \"<resource-group-for-$env>\"\n $APIM_SERVICE_NAMES[$env] = \"<service-name-for-$env>\"\n\n # Option B: if APIM resource ID is provided, parse it into the same maps.\n # $resourceId = \"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>\"\n # if ($resourceId) {\n # $parts = $resourceId.Trim('/') -split '/'\n # $APIM_SUBSCRIPTIONS[$env] = $parts[1]\n # $APIM_RESOURCE_GROUPS[$env] = $parts[3]\n # $APIM_SERVICE_NAMES[$env] = $parts[7]\n # }\n}\n```\n\n**Git Bash:**\n```bash\nAPP_NAME=\"apiops-azdo-sp\"\nAZDO_ORG=\"<your-azdo-org-url>\"\nAZDO_PROJECT=\"<your-project>\"\nTENANT_ID=\"<your-tenant-id>\"\nENVIRONMENTS=({{ENVIRONMENTS_ARRAY_BASH}})\n\n# Fill these maps with values for each environment.\ndeclare -A APIM_SUBSCRIPTIONS\ndeclare -A APIM_RESOURCE_GROUPS\ndeclare -A APIM_SERVICE_NAMES\n\nfor env in \"${ENVIRONMENTS[@]}\"; do\n # Option A: provide values directly.\n APIM_SUBSCRIPTIONS[\"$env\"]=\"<subscription-id-for-$env>\"\n APIM_RESOURCE_GROUPS[\"$env\"]=\"<resource-group-for-$env>\"\n APIM_SERVICE_NAMES[\"$env\"]=\"<service-name-for-$env>\"\n\n # Option B: if APIM resource ID is provided, parse it into the same maps.\n # resource_id=\"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>\"\n # if [[ -n \"$resource_id\" ]]; then\n # IFS='/' read -r _ subscriptions sub resourceGroups rg providers provider service svc <<< \"$resource_id\"\n # APIM_SUBSCRIPTIONS[\"$env\"]=\"$sub\"\n # APIM_RESOURCE_GROUPS[\"$env\"]=\"$rg\"\n # APIM_SERVICE_NAMES[\"$env\"]=\"$svc\"\n # fi\ndone\n```\n\n---\n\n## Step 3: Configure Azure DevOps CLI\n\nInstall the extension (works in both shells):\n```bash\naz extension add --name azure-devops\n```\n\nInstall the Azure DevOps Replace Tokens extension (required by publish pipeline):\n\n**PowerShell:**\n```powershell\naz devops extension install --publisher-id qetza --extension-id replacetokens\n```\n\n**Git Bash:**\n```bash\naz devops extension install --publisher-id qetza --extension-id replacetokens\n```\n\nSet organization defaults:\n\nFor self-hosted Azure DevOps Server, use your server/collection URL format:\n- `https://<server>/<collection>`\n\n**PowerShell:**\n```powershell\naz devops configure --defaults organization=$AZDO_ORG project=$AZDO_PROJECT\n$ORG_NAME = $AZDO_ORG -replace 'https://dev\\.azure\\.com/', ''\n```\n\n**Git Bash:**\n```bash\naz devops configure --defaults organization=\"$AZDO_ORG\" project=\"$AZDO_PROJECT\"\nORG_NAME=\"${AZDO_ORG##*/}\"\n```\n\n**Self-hosted note:** If your server URL includes a collection segment (for example, `https://ado.contoso.local/DefaultCollection`), set `ORG_NAME` to the value expected in the Build Service identity display name for your server/project.\n\n---\n\n## Step 4: Verify Tenant ID\n\nBefore creating identity objects, confirm you are logged into the intended tenant.\n\n**PowerShell:**\n```powershell\n$CURRENT_TENANT_ID = az account show --query tenantId -o tsv\nWrite-Host \"Current tenant: $CURRENT_TENANT_ID\"\nif ($CURRENT_TENANT_ID -ne $TENANT_ID) {\n throw \"Tenant mismatch. Expected $TENANT_ID but got $CURRENT_TENANT_ID. Run: az login --tenant $TENANT_ID\"\n}\n```\n\n**Git Bash:**\n```bash\nCURRENT_TENANT_ID=$(az account show --query tenantId -o tsv)\necho \"Current tenant: $CURRENT_TENANT_ID\"\nif [[ \"$CURRENT_TENANT_ID\" != \"$TENANT_ID\" ]]; then\n echo \"Tenant mismatch. Expected $TENANT_ID but got $CURRENT_TENANT_ID\"\n echo \"Run: az login --tenant $TENANT_ID\"\n exit 1\nfi\n```\n\n---\n\n## Step 5: Create Entra Application and Service Principal (No Secret)\n\n> \u26A0\uFE0F **Error Handling:** If any command fails, stop immediately and show the user the full error output verbatim. Do NOT retry silently.\n\n**PowerShell:**\n```powershell\naz ad app create --display-name $APP_NAME | Out-Null\n$APP_ID = az ad app list --display-name $APP_NAME --query \"[0].appId\" -o tsv\naz ad sp create --id $APP_ID | Out-Null\nWrite-Host \"App ID: $APP_ID\"\nWrite-Host \"Tenant ID: $TENANT_ID\"\n```\n\n**Git Bash:**\n```bash\naz ad app create --display-name \"$APP_NAME\" >/dev/null\nAPP_ID=$(az ad app list --display-name \"$APP_NAME\" --query \"[0].appId\" -o tsv)\naz ad sp create --id \"$APP_ID\" >/dev/null\necho \"App ID: $APP_ID\"\necho \"Tenant ID: $TENANT_ID\"\n```\n\nNo client secret is required in this flow.\n\n---\n\n## Step 6: Assign RBAC Roles Per Environment\n\nGrant the service principal **Reader** on each resource group and **API Management Service Contributor** on each APIM instance.\n\n### PowerShell\n```powershell\nforeach ($env in $ENVIRONMENTS) {\n az role assignment create --assignee \"$APP_ID\" --role \"Reader\" --scope \"/subscriptions/$($APIM_SUBSCRIPTIONS[$env])/resourceGroups/$($APIM_RESOURCE_GROUPS[$env])\"\n az role assignment create --assignee \"$APP_ID\" --role \"API Management Service Contributor\" --scope \"/subscriptions/$($APIM_SUBSCRIPTIONS[$env])/resourceGroups/$($APIM_RESOURCE_GROUPS[$env])/providers/Microsoft.ApiManagement/service/$($APIM_SERVICE_NAMES[$env])\"\n}\n```\n\n### Git Bash\n```bash\nfor env in \"${ENVIRONMENTS[@]}\"; do\n az role assignment create --assignee \"$APP_ID\" --role \"Reader\" --scope \"/subscriptions/${APIM_SUBSCRIPTIONS[$env]}/resourceGroups/${APIM_RESOURCE_GROUPS[$env]}\"\n az role assignment create --assignee \"$APP_ID\" --role \"API Management Service Contributor\" --scope \"/subscriptions/${APIM_SUBSCRIPTIONS[$env]}/resourceGroups/${APIM_RESOURCE_GROUPS[$env]}/providers/Microsoft.ApiManagement/service/${APIM_SERVICE_NAMES[$env]}\"\ndone\n```\n\n---\n\n## Step 7: Create Workload Identity Federation Service Connections\n\nCreate one service connection per environment, each scoped to that environment's subscription,\nusing Azure Resource Manager with Workload Identity Federation.\n\nThis step is fully automatable with `az devops service-endpoint create`.\nAfter each endpoint is created, capture its generated issuer/subject and create\nthe corresponding federated credential in Entra.\n\n**PowerShell:**\n```powershell\nforeach ($env in $ENVIRONMENTS) {\n $envUpper = $env.ToUpper()\n $name = \"AZURE_SERVICE_CONNECTION_$envUpper\"\n $subscriptionName = az account show --subscription $($APIM_SUBSCRIPTIONS[$env]) --query name -o tsv\n\n $payload = @{\n name = $name\n type = \"azurerm\"\n url = \"https://management.azure.com/\"\n authorization = @{\n scheme = \"WorkloadIdentityFederation\"\n parameters = @{\n tenantid = $TENANT_ID\n serviceprincipalid = $APP_ID\n }\n }\n data = @{\n environment = \"AzureCloud\"\n identityType = \"AppRegistrationManual\"\n scopeLevel = \"Subscription\"\n subscriptionId = $APIM_SUBSCRIPTIONS[$env]\n subscriptionName = $subscriptionName\n }\n } | ConvertTo-Json -Depth 8\n\n $file = \"se-$env.json\"\n $payload | Out-File -Encoding utf8 -FilePath $file\n az devops service-endpoint create --service-endpoint-configuration $file | Out-Null\n Remove-Item $file -ErrorAction SilentlyContinue\n\n $endpoint = az devops service-endpoint list --query \"[?name=='$name'] | [0]\" -o json | ConvertFrom-Json\n $issuer = $endpoint.authorization.parameters.workloadIdentityFederationIssuer\n $subject = $endpoint.authorization.parameters.workloadIdentityFederationSubject\n\n $FED_CRED_NAME = \"azdo-$env\"\n\n $payload = @{\n name = $FED_CRED_NAME\n issuer = $issuer\n subject = $subject\n audiences = @(\"api://AzureADTokenExchange\")\n } | ConvertTo-Json -Depth 5\n\n az ad app federated-credential create --id $APP_ID --parameters $payload\n}\n```\n\n**Git Bash:**\n```bash\nfor env in \"${ENVIRONMENTS[@]}\"; do\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\n name=\"AZURE_SERVICE_CONNECTION_$env_upper\"\n subscription_name=$(az account show --subscription \"${APIM_SUBSCRIPTIONS[$env]}\" --query name -o tsv)\n\n cat > \"se-$env.json\" <<JSON\n{\n \"name\": \"$name\",\n \"type\": \"azurerm\",\n \"url\": \"https://management.azure.com/\",\n \"authorization\": {\n \"scheme\": \"WorkloadIdentityFederation\",\n \"parameters\": {\n \"tenantid\": \"$TENANT_ID\",\n \"serviceprincipalid\": \"$APP_ID\"\n }\n },\n \"data\": {\n \"environment\": \"AzureCloud\",\n \"identityType\": \"AppRegistrationManual\",\n \"scopeLevel\": \"Subscription\",\n \"subscriptionId\": \"${APIM_SUBSCRIPTIONS[$env]}\",\n \"subscriptionName\": \"$subscription_name\"\n }\n}\nJSON\n\n az devops service-endpoint create --service-endpoint-configuration \"se-$env.json\" >/dev/null\n rm -f \"se-$env.json\"\n\n issuer=$(az devops service-endpoint list --query \"[?name=='$name'] | [0].authorization.parameters.workloadIdentityFederationIssuer\" -o tsv)\n subject=$(az devops service-endpoint list --query \"[?name=='$name'] | [0].authorization.parameters.workloadIdentityFederationSubject\" -o tsv)\n\n FED_CRED_NAME=\"azdo-$env\"\n\n az ad app federated-credential create \\\n --id \"$APP_ID\" \\\n --parameters \"{\\\"name\\\":\\\"$FED_CRED_NAME\\\",\\\"issuer\\\":\\\"$issuer\\\",\\\"subject\\\":\\\"$subject\\\",\\\"audiences\\\":[\\\"api://AzureADTokenExchange\\\"]}\"\ndone\n```\n\nAuthorize service connections for all pipelines (prevents first-run permission prompts):\n\n**PowerShell:**\n```powershell\nforeach ($env in $ENVIRONMENTS) {\n $envUpper = $env.ToUpper()\n $name = \"AZURE_SERVICE_CONNECTION_$envUpper\"\n $id = az devops service-endpoint list --query \"[?name=='$name'].id | [0]\" -o tsv\n if ($id) {\n az devops service-endpoint update --id $id --enable-for-all true | Out-Null\n }\n}\n```\n\n**Git Bash:**\n```bash\nfor env in \"${ENVIRONMENTS[@]}\"; do\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\n name=\"AZURE_SERVICE_CONNECTION_$env_upper\"\n id=$(az devops service-endpoint list --query \"[?name=='$name'].id | [0]\" -o tsv)\n if [[ -n \"$id\" ]]; then\n az devops service-endpoint update --id \"$id\" --enable-for-all true >/dev/null\n fi\ndone\n```\n\nVerify:\n```bash\naz devops service-endpoint list --query \"[].name\" -o table\n```\n\n---\n\n## Step 8: Create Variable Groups\n\nCreate one variable group per environment. Each group uses the **non-suffixed** variable names expected by the pipelines (`APIM_RESOURCE_GROUP`, `APIM_SERVICE_NAME`, `AZURE_SUBSCRIPTION_ID`, `AZURE_SERVICE_CONNECTION`).\n\n**PowerShell:**\n```powershell\nforeach ($env in $ENVIRONMENTS) {\n $envUpper = $env.ToUpper()\n az pipelines variable-group create --name \"apim-$env\" --variables AZURE_SUBSCRIPTION_ID=$($APIM_SUBSCRIPTIONS[$env]) APIM_RESOURCE_GROUP=$($APIM_RESOURCE_GROUPS[$env]) APIM_SERVICE_NAME=$($APIM_SERVICE_NAMES[$env]) AZURE_SERVICE_CONNECTION=\"AZURE_SERVICE_CONNECTION_$envUpper\"\n}\n```\n\n**Git Bash:**\n```bash\nfor env in \"${ENVIRONMENTS[@]}\"; do\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\n az pipelines variable-group create --name \"apim-$env\" --variables AZURE_SUBSCRIPTION_ID=\"${APIM_SUBSCRIPTIONS[$env]}\" APIM_RESOURCE_GROUP=\"${APIM_RESOURCE_GROUPS[$env]}\" APIM_SERVICE_NAME=\"${APIM_SERVICE_NAMES[$env]}\" AZURE_SERVICE_CONNECTION=\"AZURE_SERVICE_CONNECTION_$env_upper\"\ndone\n```\n\nAuthorize all groups for pipeline use:\n\n**PowerShell:**\n```powershell\n$groupIds = az pipelines variable-group list --query \"[].id\" -o tsv\nforeach ($id in $groupIds) {\n az pipelines variable-group update --group-id $id --authorize true\n}\n```\n\n**Git Bash:**\n```bash\nfor id in $(az pipelines variable-group list --query \"[].id\" -o tsv); do\n az pipelines variable-group update --group-id \"$id\" --authorize true\ndone\n```\n\nVerify:\n```bash\naz pipelines variable-group list --query \"[].name\" -o table\n```\n\n---\n\n## Step 9 (in pipeline): Create Environments\n\nCreate deployment environments in Azure DevOps:\n\n**PowerShell:**\n```powershell\nforeach ($env in $ENVIRONMENTS) {\n $body = \"{\\\"name\\\": \\\"$env\\\"}\"\n $body | Out-File -Encoding utf8 -FilePath env-body.json\n az devops invoke --area environments --resource environments --route-parameters project=$AZDO_PROJECT --http-method POST --api-version 7.1 --in-file env-body.json\n}\nRemove-Item env-body.json -ErrorAction SilentlyContinue\n```\n\n**Git Bash:**\n```bash\nfor env in \"${ENVIRONMENTS[@]}\"; do\n echo \"{\\\"name\\\": \\\"$env\\\"}\" > env-body.json\n az devops invoke --area environments --resource environments --route-parameters project=\"$AZDO_PROJECT\" --http-method POST --api-version 7.1 --in-file env-body.json\ndone\nrm -f env-body.json\n```\n\nAuthorize each environment for all pipelines (prevents first-run permission prompts):\n\n**PowerShell:**\n```powershell\n$ADO_RESOURCE = \"499b84ac-1321-427f-aa17-267ca6975798\"\n$TOKEN = az account get-access-token --resource $ADO_RESOURCE --query accessToken -o tsv\n\nforeach ($env in $ENVIRONMENTS) {\n $envId = az devops invoke --area environments --resource environments --route-parameters project=$AZDO_PROJECT --query-parameters \"api-version=7.1\" --query \"value[?name=='$env'].id | [0]\" -o tsv\n if ($envId) {\n $url = \"$AZDO_ORG/$AZDO_PROJECT/_apis/pipelines/pipelinePermissions/environment/$envId?api-version=7.1-preview.1\"\n $body = '{\"allPipelines\":{\"authorized\":true}}'\n Invoke-RestMethod -Method Patch -Uri $url -Headers @{ Authorization = \"Bearer $TOKEN\" } -ContentType \"application/json\" -Body $body | Out-Null\n }\n}\n```\n\n**Git Bash:**\n```bash\nADO_RESOURCE=\"499b84ac-1321-427f-aa17-267ca6975798\"\nTOKEN=$(az account get-access-token --resource \"$ADO_RESOURCE\" --query accessToken -o tsv)\n\nfor env in \"${ENVIRONMENTS[@]}\"; do\n env_id=$(az devops invoke --area environments --resource environments --route-parameters project=\"$AZDO_PROJECT\" --query-parameters \"api-version=7.1\" --query \"value[?name=='$env'].id | [0]\" -o tsv)\n if [[ -n \"$env_id\" ]]; then\n curl -sS -X PATCH \\\n -H \"Authorization: Bearer $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n \"$AZDO_ORG/$AZDO_PROJECT/_apis/pipelines/pipelinePermissions/environment/$env_id?api-version=7.1-preview.1\" \\\n -d '{\"allPipelines\":{\"authorized\":true}}' >/dev/null\n fi\ndone\n```\n\n**Note:** Environment approvals and checks still must be configured via the Azure DevOps UI.\n\n---\n";
|
|
8
|
-
export declare const githubActionsIdentityGuideTemplate: "# GitHub Actions Identity Setup Guide\n\n## Prerequisites\n- Azure subscription: {{SUBSCRIPTION_ID}}\n- Resource group: {{RESOURCE_GROUP}}\n- GitHub repository with OIDC enabled\n\n## Step 1: Create Service Principal\n\nRun the following Azure CLI commands to create a service principal with federated credentials:\n\n```bash\n# Set variables\nSUBSCRIPTION_ID=\"{{SUBSCRIPTION_ID}}\"\nRESOURCE_GROUP=\"{{RESOURCE_GROUP}}\"\nAPP_NAME=\"apiops-github-sp\"\nGITHUB_ORG=\"<your-github-org>\"\nGITHUB_REPO=\"<your-github-repo>\"\n\n# Create Azure AD Application\nAPP_ID=$(az ad app create \\\n --display-name \"$APP_NAME\" \\\n --query appId -o tsv)\n\n# Create Service Principal\naz ad sp create --id \"$APP_ID\"\n\n# Get Service Principal Object ID\nSP_OBJECT_ID=$(az ad sp show --id \"$APP_ID\" --query id -o tsv)\n\necho \"Application (client) ID: $APP_ID\"\necho \"Service Principal Object ID: $SP_OBJECT_ID\"\n```\n\n## Step 2: Assign RBAC Roles\n\nGrant the service principal \"API Management Service Contributor\" role on your APIM instance:\n\n```bash\n# Get APIM resource ID\nAPIM_RESOURCE_ID=$(az apim show \\\n --resource-group \"$RESOURCE_GROUP\" \\\n --name \"<your-apim-service-name>\" \\\n --query id -o tsv)\n\n# Assign role\naz role assignment create \\\n --assignee \"$APP_ID\" \\\n --role \"API Management Service Contributor\" \\\n --scope \"$APIM_RESOURCE_ID\"\n```\n\n## Step 3: Configure Federated Credentials\n\nSet up OIDC federation for GitHub Actions:\n\n```bash\n# For main branch deployments\naz ad app federated-credential create \\\n --id \"$APP_ID\" \\\n --parameters '{\n \"name\": \"github-main-branch\",\n \"issuer\": \"https://token.actions.githubusercontent.com\",\n \"subject\": \"repo:'\"$GITHUB_ORG\"'/'\"$GITHUB_REPO\"':ref:refs/heads/main\",\n \"audiences\": [\"api://AzureADTokenExchange\"]\n }'\n\n# For environment deployments (repeat for each environment)\n{{FEDERATED_CREDENTIALS_PER_ENV}}\n```\n\n## Step 4: Configure GitHub Secrets\n\nAdd the following secrets to your GitHub repository (Settings \u2192 Secrets and variables \u2192 Actions):\n\n### Repository Secrets:\n- `AZURE_CLIENT_ID`: $APP_ID (from Step 1)\n- `AZURE_TENANT_ID`: Run `az account show --query tenantId -o tsv`\n- `AZURE_SUBSCRIPTION_ID`: {{SUBSCRIPTION_ID}}\n\n### Environment-Specific Secrets:\n{{ENVIRONMENT_SECRETS}}\n\n### Extract Workflow Secrets:\n- `APIM_RESOURCE_GROUP`: Default resource group for extract\n- `APIM_SERVICE_NAME`: Default APIM service name for extract\n\n## Step 5: Verify Setup\n\nTest the authentication by running a workflow manually or pushing to main branch.\n\n## Security Notes\n- Use GitHub Environments for production deployments with required reviewers\n- Review federated credential subjects periodically (no secrets to rotate \u2014 OIDC authentication has no stored credentials)\n- Review RBAC role assignments regularly and remove any no longer needed\n- Use least-privilege RBAC assignments\n";
|
|
9
|
-
export declare const
|
|
5
|
+
export declare const copilotGitHubActionsIdentitySetupPromptTemplate: "# Setup GitHub Actions Identity for APIOps\r\n\r\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\r\n> Copilot to help you run through the steps. Copilot will prompt you for\r\n> the required values and generate the exact CLI commands for your environment.\r\n\r\n> **Important identity distinction:** `GITHUB_TOKEN` handles pull request creation automatically. The Azure app registration/service principal in this flow is only for Azure and APIM access.\r\n\r\n## Agent Behavior\r\n\r\n- **One step at a time.** Complete each step fully before moving to the next.\r\n- **Confirm information.** After gathering user input, summarize what was provided and ask the user to confirm it is correct before proceeding.\r\n- **Ask before proceeding.** At the end of each step, ask: \"Step N is complete. Ready to proceed to Step N+1?\"\r\n- **Never combine steps.** Do not run commands from multiple steps together, even if they could be batched.\r\n- **Stop on errors.** If any command fails, show the full error output and wait for the user to decide how to proceed.\r\n\r\n## Goal\r\n\r\nConfigure Azure AD federated credentials and GitHub repository secrets so the\r\nAPIOps extract and publish workflows can authenticate to Azure using OIDC\r\n(no stored client secrets needed).\r\n\r\n---\r\n\r\n## Step 0 \u2014 Tool Authentication Check\r\n\r\n**Copilot: Before proceeding, verify that all required tools are installed and authenticated.**\r\n\r\nRun these checks and present results in a table:\r\n\r\n### Check Azure CLI\r\n```bash\r\naz version\r\naz account show --query \"{Subscription:name, Account:user.name, TenantId:tenantId}\" -o json\r\n```\r\n\r\n### Check GitHub CLI\r\n```bash\r\ngh auth status\r\n```\r\n\r\n### Present Status Table\r\n\r\nPresent the results to the user in this format:\r\n\r\n```\r\n\uD83D\uDD10 Tool Authentication Status:\r\n\r\n| Tool | Status | Account/User | Subscription/Org | Tenant/Details |\r\n|------|--------|--------------|------------------|----------------|\r\n| Azure CLI | \u2705 Logged in | user@example.com | my-subscription | abc-123-... |\r\n| GitHub CLI | \u2705 Logged in | username | github.com | \u2014 |\r\n```\r\n\r\n**Status indicators:**\r\n- \u2705 Logged in \u2014 tool is authenticated and ready\r\n- \u274C Not logged in \u2014 tool needs authentication\r\n- \u26A0\uFE0F Not installed \u2014 tool is missing entirely\r\n\r\n### Fix Missing Authentication\r\n\r\n**If Azure CLI is not logged in:**\r\n> \"Azure CLI is required for this setup. Run `az login` to authenticate, then I'll continue.\"\r\n\r\n**If GitHub CLI is not logged in:**\r\n> \"GitHub CLI is required for configuring repository secrets. Run `gh auth login` to authenticate.\"\r\n\r\n**If any required tool is not installed:**\r\n- Azure CLI: Install from https://aka.ms/installazurecli\r\n- GitHub CLI: Install from https://cli.github.com\r\n\r\nOnce both tools are authenticated, ask the user to confirm:\r\n> \"Does this authentication look correct? (yes / need to switch accounts)\"\r\n\r\nIf the user needs to switch accounts, help them with:\r\n- Azure CLI: `az account set --subscription <id>` or `az login --tenant <tenant-id>`\r\n- GitHub CLI: `gh auth logout` then `gh auth login`\r\n\r\nOnce confirmed, proceed to Step 1.\r\n\r\n---\r\n\r\n## Step 1 \u2014 Gather Information\r\n\r\nCopilot, please ask the user for the following values before proceeding. Store\r\neach answer for use in later steps.\r\n\r\n| Variable | Description | Example |\r\n|----------|-------------|---------|\r\n{{ENV_SUBSCRIPTION_TABLE_ROWS}}\r\n| `AZURE_TENANT_ID` | Azure AD tenant ID (same for all environments) | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |\r\n| `GITHUB_ORG` | GitHub organization or user that owns the repo | `my-org` |\r\n| `GITHUB_REPO` | GitHub repository name | `apim-artifacts` |\r\n| `APP_NAME` | Display name for the Azure AD application | `apiops-github-sp` |\r\n{{ENV_APIM_TABLE_ROWS}}\r\n\r\n**Copilot:** After collecting all values, present a summary table and ask: \"Please confirm these values are correct before I proceed.\"\r\n\r\n---\r\n\r\n## Step 2 \u2014 Create Azure AD Application & Service Principal\r\n\r\n> \u26A0\uFE0F **Error Handling:** If any command fails, stop immediately and show the user the full error output verbatim. Do NOT retry silently. Common issues include insufficient permissions (requires Application Administrator or Global Administrator role in Azure AD).\r\n\r\n**On macOS/Linux (Bash):**\r\n```bash\r\n# Create the Azure AD application\r\nAPP_ID=$(az ad app create \\\r\n --display-name \"${APP_NAME}\" \\\r\n --query appId -o tsv)\r\n\r\n# Create the service principal for the application\r\naz ad sp create --id \"$APP_ID\"\r\n\r\necho \"Application (client) ID: $APP_ID\"\r\necho \"Tenant ID: $(az account show --query tenantId -o tsv)\"\r\n```\r\n\r\n**On Windows (PowerShell):**\r\n```powershell\r\n# Create the Azure AD application\r\n$APP_ID = az ad app create `\r\n --display-name \"${APP_NAME}\" `\r\n --query appId -o tsv\r\n\r\n# Create the service principal for the application\r\naz ad sp create --id $APP_ID\r\n\r\nWrite-Host \"Application (client) ID: $APP_ID\"\r\nWrite-Host \"Tenant ID: $(az account show --query tenantId -o tsv)\"\r\n```\r\n\r\n---\r\n\r\n## Step 3 \u2014 Assign RBAC Roles\r\n\r\nGrant the service principal the required permissions:\r\n1. **Reader** role on each resource group (to read resource groups and resources)\r\n2. **API Management Service Contributor** on each APIM instance (to manage APIM resources)\r\n\r\n> **Note:** Each environment can be in a different Azure subscription. The service principal will be granted access to all environments.\r\n\r\n### Grant Reader role on each resource group\r\n\r\n{{ENV_READER_ROLE_SNIPPETS}}\r\n\r\n### Grant API Management Service Contributor on each APIM instance\r\n\r\n{{ENV_APIM_ROLE_SNIPPETS}}\r\n\r\n---\r\n\r\n## Step 4 \u2014 Create Federated Credentials for GitHub OIDC\r\n\r\n> \u26A0\uFE0F **Platform Note:** The JSON parameters for federated credentials require different escaping on Windows PowerShell vs macOS/Linux Bash. Use the appropriate command block for your platform.\r\n\r\n### Main branch (for push-triggered publish workflow)\r\n\r\n**On macOS/Linux (Bash):**\r\n```bash\r\naz ad app federated-credential create \\\r\n --id \"$APP_ID\" \\\r\n --parameters '{\r\n \"name\": \"github-main-branch\",\r\n \"issuer\": \"https://token.actions.githubusercontent.com\",\r\n \"subject\": \"repo:'\"${GITHUB_ORG}\"'/'\"${GITHUB_REPO}\"':ref:refs/heads/main\",\r\n \"audiences\": [\"api://AzureADTokenExchange\"]\r\n }'\r\n```\r\n\r\n**On Windows (PowerShell):**\r\n```powershell\r\naz ad app federated-credential create `\r\n --id $APP_ID `\r\n --parameters '{\\\"name\\\":\\\"github-main-branch\\\",\\\"issuer\\\":\\\"https://token.actions.githubusercontent.com\\\",\\\"subject\\\":\\\"repo:'${GITHUB_ORG}'/'${GITHUB_REPO}':ref:refs/heads/main\\\",\\\"audiences\\\":[\\\"api://AzureADTokenExchange\\\"]}'\r\n```\r\n\r\n{{ENV_FEDERATED_CREDENTIALS}}\r\n\r\n---\r\n\r\n## Step 5 \u2014 Create GitHub Environments\r\n\r\n```bash\r\n{{ENVIRONMENT_CREATION_COMMANDS}}\r\n```\r\n\r\n---\r\n\r\n## Step 6 \u2014 Set GitHub Repository Secrets\r\n\r\n> \u26A0\uFE0F **Platform Note:** GitHub CLI secret commands work identically on all platforms, but variable syntax differs between Bash and PowerShell.\r\n\r\n**On macOS/Linux (Bash):**\r\n```bash\r\n# Repository-level secrets (shared across all workflows)\r\ngh secret set AZURE_CLIENT_ID --body \"$APP_ID\"\r\ngh secret set AZURE_TENANT_ID --body \"${AZURE_TENANT_ID}\"\r\n\r\n{{GH_SECRET_ENV_COMMANDS}}\r\n```\r\n\r\n**On Windows (PowerShell):**\r\n```powershell\r\n# Repository-level secrets (shared across all workflows)\r\ngh secret set AZURE_CLIENT_ID --body $APP_ID\r\ngh secret set AZURE_TENANT_ID --body \"${AZURE_TENANT_ID}\"\r\n\r\n{{GH_SECRET_ENV_COMMANDS}}\r\n```\r\n\r\n---\r\n\r\n## Step 7 \u2014 Verify\r\n\r\n> \u26A0\uFE0F **Important:** If any verification step fails, show the user the full error output and help troubleshoot before proceeding. Common issues include RBAC permissions not yet propagated (can take 5-10 minutes) or missing secrets.\r\n\r\n1. Go to **Actions** \u2192 **Run APIM Extractor** \u2192 **Run workflow**\r\n2. Fill in the resource group and service name for your dev environment\r\n3. Confirm the workflow completes and a pull request is created\r\n\r\nIf the workflow fails with authentication errors:\r\n- Check that all secrets are set correctly in GitHub: Settings \u2192 Secrets and variables \u2192 Actions\r\n- Verify RBAC role assignments have propagated (wait 5-10 minutes and retry)\r\n- Confirm the federated credentials were created: `az ad app federated-credential list --id $APP_ID`\r\n\r\n---\r\n\r\n## Secrets Reference\r\n\r\nThe generated workflows expect these secrets:\r\n\r\n### Repository Secrets\r\n- `AZURE_CLIENT_ID` \u2014 App registration client ID (shared across all environments)\r\n- `AZURE_TENANT_ID` \u2014 Azure AD tenant ID (shared across all environments)\r\n\r\n### Per-Environment Secrets\r\n{{ENV_SECRETS_REFERENCE}}\r\n";
|
|
6
|
+
export declare const copilotAzureDevOpsIdentitySetupPromptTemplate: "# Setup Azure DevOps Identity for APIOps\r\n\r\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\r\n> Copilot to help you run through the steps. Copilot will prompt you for\r\n> required values and generate exact CLI commands for your environment.\r\n\r\n> **Important identity distinction:** The Azure app registration/service principal created in this flow is only for Azure and APIM access. Repository contributions and pull request creation come from the Azure DevOps Build Service identity, which must be granted repo permissions separately.\r\n\r\n## Agent Behavior\r\n\r\n- **One step at a time.** Complete each step fully before moving to the next.\r\n- **Confirm information.** After gathering user input, summarize what was provided and ask the user to confirm it is correct before proceeding.\r\n- **Ask before proceeding.** At the end of each step, ask: \"Step N is complete. Ready to proceed to Step N+1?\"\r\n- **Never combine steps.** Do not run commands from multiple steps together, even if they could be batched.\r\n- **Stop on errors.** If any command fails, show the full error output and wait for the user to decide how to proceed.\r\n\r\n## Goal\r\n\r\nConfigure workload identity federation (OIDC), Azure DevOps federated service connections,\r\nand variable groups\r\nfor APIOps extract and publish pipelines.\r\n\r\n## Prerequisites\r\n- Azure DevOps organization and project\r\n- Azure CLI installed and authenticated (`az login`)\r\n- `az devops` extension (`az extension add --name azure-devops`)\r\n\r\nThis flow is designed for Microsoft-hosted or self-hosted agents and uses workload identity federation (OIDC) instead of managed identity.\r\n\r\n> **Note:** All commands are shown for both **PowerShell** and **Git Bash** where syntax differs.\r\n\r\n---\r\n\r\n## Step 1: Gather Per-Environment Information\r\n\r\n**Copilot:** Ask the user for the following values before proceeding. Store each answer for use in later steps.\r\n\r\nFor each environment, provide either **Option A** (three separate values) or **Option B** (a single full APIM resource ID in the form `/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>`). Copilot will parse Option B into the individual components automatically.\r\n\r\n| Variable | Description | Example |\r\n|----------|-------------|---------|\r\n| `APP_NAME` | Display name for the Entra application | `apiops-azdo-sp` |\r\n| `AZDO_ORG` | Azure DevOps organization URL | `https://dev.azure.com/my-org` |\r\n| `AZDO_PROJECT` | Azure DevOps project name | `my-project` |\r\n| `TENANT_ID` | Tenant ID that should own the app/service connection | `11111111-2222-3333-4444-555555555555` |\r\n\r\nFor each environment in the configured list, gather these values (where `<ENV_UPPER>` is the upper-case environment name):\r\n- `APIM_SUBSCRIPTION_<ENV_UPPER>`\r\n- `APIM_RG_<ENV_UPPER>`\r\n- `APIM_NAME_<ENV_UPPER>`\r\n- `APIM_RESOURCE_ID_<ENV_UPPER>` *(optional Option B shorthand)*\r\n\r\n**Copilot:** After collecting all values, present a summary table and ask: \"Please confirm these values are correct before I proceed.\"\r\n\r\n---\r\n\r\n## Step 2: Set Variables\r\n\r\n**PowerShell:**\r\n```powershell\r\n$APP_NAME = \"apiops-azdo-sp\"\r\n$AZDO_ORG = \"<your-azdo-org-url>\"\r\n$AZDO_PROJECT = \"<your-project>\"\r\n$TENANT_ID = \"<your-tenant-id>\"\r\n$ENVIRONMENTS = @({{ENVIRONMENTS_ARRAY_POWERSHELL}})\r\n\r\n# Fill these maps with values for each environment.\r\n$APIM_SUBSCRIPTIONS = @{}\r\n$APIM_RESOURCE_GROUPS = @{}\r\n$APIM_SERVICE_NAMES = @{}\r\n\r\nforeach ($env in $ENVIRONMENTS) {\r\n # Option A: provide values directly.\r\n $APIM_SUBSCRIPTIONS[$env] = \"<subscription-id-for-$env>\"\r\n $APIM_RESOURCE_GROUPS[$env] = \"<resource-group-for-$env>\"\r\n $APIM_SERVICE_NAMES[$env] = \"<service-name-for-$env>\"\r\n\r\n # Option B: if APIM resource ID is provided, parse it into the same maps.\r\n # $resourceId = \"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>\"\r\n # if ($resourceId) {\r\n # $parts = $resourceId.Trim('/') -split '/'\r\n # $APIM_SUBSCRIPTIONS[$env] = $parts[1]\r\n # $APIM_RESOURCE_GROUPS[$env] = $parts[3]\r\n # $APIM_SERVICE_NAMES[$env] = $parts[7]\r\n # }\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nAPP_NAME=\"apiops-azdo-sp\"\r\nAZDO_ORG=\"<your-azdo-org-url>\"\r\nAZDO_PROJECT=\"<your-project>\"\r\nTENANT_ID=\"<your-tenant-id>\"\r\nENVIRONMENTS=({{ENVIRONMENTS_ARRAY_BASH}})\r\n\r\n# Fill these maps with values for each environment.\r\ndeclare -A APIM_SUBSCRIPTIONS\r\ndeclare -A APIM_RESOURCE_GROUPS\r\ndeclare -A APIM_SERVICE_NAMES\r\n\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n # Option A: provide values directly.\r\n APIM_SUBSCRIPTIONS[\"$env\"]=\"<subscription-id-for-$env>\"\r\n APIM_RESOURCE_GROUPS[\"$env\"]=\"<resource-group-for-$env>\"\r\n APIM_SERVICE_NAMES[\"$env\"]=\"<service-name-for-$env>\"\r\n\r\n # Option B: if APIM resource ID is provided, parse it into the same maps.\r\n # resource_id=\"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ApiManagement/service/<name>\"\r\n # if [[ -n \"$resource_id\" ]]; then\r\n # IFS='/' read -r _ subscriptions sub resourceGroups rg providers provider service svc <<< \"$resource_id\"\r\n # APIM_SUBSCRIPTIONS[\"$env\"]=\"$sub\"\r\n # APIM_RESOURCE_GROUPS[\"$env\"]=\"$rg\"\r\n # APIM_SERVICE_NAMES[\"$env\"]=\"$svc\"\r\n # fi\r\ndone\r\n```\r\n\r\n---\r\n\r\n## Step 3: Configure Azure DevOps CLI\r\n\r\nInstall the extension (works in both shells):\r\n```bash\r\naz extension add --name azure-devops\r\n```\r\n\r\nInstall the Azure DevOps Replace Tokens extension (required by publish pipeline):\r\n\r\n**PowerShell:**\r\n```powershell\r\naz devops extension install --publisher-id qetza --extension-id replacetokens\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\naz devops extension install --publisher-id qetza --extension-id replacetokens\r\n```\r\n\r\nSet organization defaults:\r\n\r\nFor self-hosted Azure DevOps Server, use your server/collection URL format:\r\n- `https://<server>/<collection>`\r\n\r\n**PowerShell:**\r\n```powershell\r\naz devops configure --defaults organization=$AZDO_ORG project=$AZDO_PROJECT\r\n$ORG_NAME = $AZDO_ORG -replace 'https://dev\\.azure\\.com/', ''\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\naz devops configure --defaults organization=\"$AZDO_ORG\" project=\"$AZDO_PROJECT\"\r\nORG_NAME=\"${AZDO_ORG##*/}\"\r\n```\r\n\r\n**Self-hosted note:** If your server URL includes a collection segment (for example, `https://ado.contoso.local/DefaultCollection`), set `ORG_NAME` to the value expected in the Build Service identity display name for your server/project.\r\n\r\n---\r\n\r\n## Step 4: Verify Tenant ID\r\n\r\nBefore creating identity objects, confirm you are logged into the intended tenant.\r\n\r\n**PowerShell:**\r\n```powershell\r\n$CURRENT_TENANT_ID = az account show --query tenantId -o tsv\r\nWrite-Host \"Current tenant: $CURRENT_TENANT_ID\"\r\nif ($CURRENT_TENANT_ID -ne $TENANT_ID) {\r\n throw \"Tenant mismatch. Expected $TENANT_ID but got $CURRENT_TENANT_ID. Run: az login --tenant $TENANT_ID\"\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nCURRENT_TENANT_ID=$(az account show --query tenantId -o tsv)\r\necho \"Current tenant: $CURRENT_TENANT_ID\"\r\nif [[ \"$CURRENT_TENANT_ID\" != \"$TENANT_ID\" ]]; then\r\n echo \"Tenant mismatch. Expected $TENANT_ID but got $CURRENT_TENANT_ID\"\r\n echo \"Run: az login --tenant $TENANT_ID\"\r\n exit 1\r\nfi\r\n```\r\n\r\n---\r\n\r\n## Step 5: Create Entra Application and Service Principal (No Secret)\r\n\r\n> \u26A0\uFE0F **Error Handling:** If any command fails, stop immediately and show the user the full error output verbatim. Do NOT retry silently.\r\n\r\n**PowerShell:**\r\n```powershell\r\naz ad app create --display-name $APP_NAME | Out-Null\r\n$APP_ID = az ad app list --display-name $APP_NAME --query \"[0].appId\" -o tsv\r\naz ad sp create --id $APP_ID | Out-Null\r\nWrite-Host \"App ID: $APP_ID\"\r\nWrite-Host \"Tenant ID: $TENANT_ID\"\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\naz ad app create --display-name \"$APP_NAME\" >/dev/null\r\nAPP_ID=$(az ad app list --display-name \"$APP_NAME\" --query \"[0].appId\" -o tsv)\r\naz ad sp create --id \"$APP_ID\" >/dev/null\r\necho \"App ID: $APP_ID\"\r\necho \"Tenant ID: $TENANT_ID\"\r\n```\r\n\r\nNo client secret is required in this flow.\r\n\r\n---\r\n\r\n## Step 6: Assign RBAC Roles Per Environment\r\n\r\nGrant the service principal **Reader** on each resource group and **API Management Service Contributor** on each APIM instance.\r\n\r\n### PowerShell\r\n```powershell\r\nforeach ($env in $ENVIRONMENTS) {\r\n az role assignment create --assignee \"$APP_ID\" --role \"Reader\" --scope \"/subscriptions/$($APIM_SUBSCRIPTIONS[$env])/resourceGroups/$($APIM_RESOURCE_GROUPS[$env])\"\r\n az role assignment create --assignee \"$APP_ID\" --role \"API Management Service Contributor\" --scope \"/subscriptions/$($APIM_SUBSCRIPTIONS[$env])/resourceGroups/$($APIM_RESOURCE_GROUPS[$env])/providers/Microsoft.ApiManagement/service/$($APIM_SERVICE_NAMES[$env])\"\r\n}\r\n```\r\n\r\n### Git Bash\r\n```bash\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n az role assignment create --assignee \"$APP_ID\" --role \"Reader\" --scope \"/subscriptions/${APIM_SUBSCRIPTIONS[$env]}/resourceGroups/${APIM_RESOURCE_GROUPS[$env]}\"\r\n az role assignment create --assignee \"$APP_ID\" --role \"API Management Service Contributor\" --scope \"/subscriptions/${APIM_SUBSCRIPTIONS[$env]}/resourceGroups/${APIM_RESOURCE_GROUPS[$env]}/providers/Microsoft.ApiManagement/service/${APIM_SERVICE_NAMES[$env]}\"\r\ndone\r\n```\r\n\r\n---\r\n\r\n## Step 7: Create Workload Identity Federation Service Connections\r\n\r\nCreate one service connection per environment, each scoped to that environment's subscription,\r\nusing Azure Resource Manager with Workload Identity Federation.\r\n\r\nThis step is fully automatable with `az devops service-endpoint create`.\r\nAfter each endpoint is created, capture its generated issuer/subject and create\r\nthe corresponding federated credential in Entra.\r\n\r\n**PowerShell:**\r\n```powershell\r\nforeach ($env in $ENVIRONMENTS) {\r\n $envUpper = $env.ToUpper()\r\n $name = \"AZURE_SERVICE_CONNECTION_$envUpper\"\r\n $subscriptionName = az account show --subscription $($APIM_SUBSCRIPTIONS[$env]) --query name -o tsv\r\n\r\n $payload = @{\r\n name = $name\r\n type = \"azurerm\"\r\n url = \"https://management.azure.com/\"\r\n authorization = @{\r\n scheme = \"WorkloadIdentityFederation\"\r\n parameters = @{\r\n tenantid = $TENANT_ID\r\n serviceprincipalid = $APP_ID\r\n }\r\n }\r\n data = @{\r\n environment = \"AzureCloud\"\r\n identityType = \"AppRegistrationManual\"\r\n scopeLevel = \"Subscription\"\r\n subscriptionId = $APIM_SUBSCRIPTIONS[$env]\r\n subscriptionName = $subscriptionName\r\n }\r\n } | ConvertTo-Json -Depth 8\r\n\r\n $file = \"se-$env.json\"\r\n $payload | Out-File -Encoding utf8 -FilePath $file\r\n az devops service-endpoint create --service-endpoint-configuration $file | Out-Null\r\n Remove-Item $file -ErrorAction SilentlyContinue\r\n\r\n $endpoint = az devops service-endpoint list --query \"[?name=='$name'] | [0]\" -o json | ConvertFrom-Json\r\n $issuer = $endpoint.authorization.parameters.workloadIdentityFederationIssuer\r\n $subject = $endpoint.authorization.parameters.workloadIdentityFederationSubject\r\n\r\n $FED_CRED_NAME = \"azdo-$env\"\r\n\r\n $payload = @{\r\n name = $FED_CRED_NAME\r\n issuer = $issuer\r\n subject = $subject\r\n audiences = @(\"api://AzureADTokenExchange\")\r\n } | ConvertTo-Json -Depth 5\r\n\r\n az ad app federated-credential create --id $APP_ID --parameters $payload\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\r\n name=\"AZURE_SERVICE_CONNECTION_$env_upper\"\r\n subscription_name=$(az account show --subscription \"${APIM_SUBSCRIPTIONS[$env]}\" --query name -o tsv)\r\n\r\n cat > \"se-$env.json\" <<JSON\r\n{\r\n \"name\": \"$name\",\r\n \"type\": \"azurerm\",\r\n \"url\": \"https://management.azure.com/\",\r\n \"authorization\": {\r\n \"scheme\": \"WorkloadIdentityFederation\",\r\n \"parameters\": {\r\n \"tenantid\": \"$TENANT_ID\",\r\n \"serviceprincipalid\": \"$APP_ID\"\r\n }\r\n },\r\n \"data\": {\r\n \"environment\": \"AzureCloud\",\r\n \"identityType\": \"AppRegistrationManual\",\r\n \"scopeLevel\": \"Subscription\",\r\n \"subscriptionId\": \"${APIM_SUBSCRIPTIONS[$env]}\",\r\n \"subscriptionName\": \"$subscription_name\"\r\n }\r\n}\r\nJSON\r\n\r\n az devops service-endpoint create --service-endpoint-configuration \"se-$env.json\" >/dev/null\r\n rm -f \"se-$env.json\"\r\n\r\n issuer=$(az devops service-endpoint list --query \"[?name=='$name'] | [0].authorization.parameters.workloadIdentityFederationIssuer\" -o tsv)\r\n subject=$(az devops service-endpoint list --query \"[?name=='$name'] | [0].authorization.parameters.workloadIdentityFederationSubject\" -o tsv)\r\n\r\n FED_CRED_NAME=\"azdo-$env\"\r\n\r\n az ad app federated-credential create \\\r\n --id \"$APP_ID\" \\\r\n --parameters \"{\\\"name\\\":\\\"$FED_CRED_NAME\\\",\\\"issuer\\\":\\\"$issuer\\\",\\\"subject\\\":\\\"$subject\\\",\\\"audiences\\\":[\\\"api://AzureADTokenExchange\\\"]}\"\r\ndone\r\n```\r\n\r\nAuthorize service connections for all pipelines (prevents first-run permission prompts):\r\n\r\n**PowerShell:**\r\n```powershell\r\nforeach ($env in $ENVIRONMENTS) {\r\n $envUpper = $env.ToUpper()\r\n $name = \"AZURE_SERVICE_CONNECTION_$envUpper\"\r\n $id = az devops service-endpoint list --query \"[?name=='$name'].id | [0]\" -o tsv\r\n if ($id) {\r\n az devops service-endpoint update --id $id --enable-for-all true | Out-Null\r\n }\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\r\n name=\"AZURE_SERVICE_CONNECTION_$env_upper\"\r\n id=$(az devops service-endpoint list --query \"[?name=='$name'].id | [0]\" -o tsv)\r\n if [[ -n \"$id\" ]]; then\r\n az devops service-endpoint update --id \"$id\" --enable-for-all true >/dev/null\r\n fi\r\ndone\r\n```\r\n\r\nVerify:\r\n```bash\r\naz devops service-endpoint list --query \"[].name\" -o table\r\n```\r\n\r\n---\r\n\r\n## Step 8: Create Variable Groups\r\n\r\nCreate one variable group per environment. Each group includes the extractor pipeline's **non-suffixed** variables (`APIM_RESOURCE_GROUP`, `APIM_SERVICE_NAME`, `AZURE_SUBSCRIPTION_ID`, `AZURE_SERVICE_CONNECTION`) plus the publish pipeline's environment-suffixed APIM variables (`APIM_RESOURCE_GROUP_<ENV_UPPER>`, `APIM_SERVICE_NAME_<ENV_UPPER>`).\r\n\r\n**PowerShell:**\r\n```powershell\r\nforeach ($env in $ENVIRONMENTS) {\r\n $envUpper = $env.ToUpper()\r\n az pipelines variable-group create --name \"apim-$env\" --variables AZURE_SUBSCRIPTION_ID=$($APIM_SUBSCRIPTIONS[$env]) APIM_RESOURCE_GROUP=$($APIM_RESOURCE_GROUPS[$env]) APIM_SERVICE_NAME=$($APIM_SERVICE_NAMES[$env]) APIM_RESOURCE_GROUP_$envUpper=$($APIM_RESOURCE_GROUPS[$env]) APIM_SERVICE_NAME_$envUpper=$($APIM_SERVICE_NAMES[$env]) AZURE_SERVICE_CONNECTION=\"AZURE_SERVICE_CONNECTION_$envUpper\"\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n env_upper=$(echo \"$env\" | tr '[:lower:]' '[:upper:]')\r\n az pipelines variable-group create --name \"apim-$env\" --variables AZURE_SUBSCRIPTION_ID=\"${APIM_SUBSCRIPTIONS[$env]}\" APIM_RESOURCE_GROUP=\"${APIM_RESOURCE_GROUPS[$env]}\" APIM_SERVICE_NAME=\"${APIM_SERVICE_NAMES[$env]}\" APIM_RESOURCE_GROUP_$env_upper=\"${APIM_RESOURCE_GROUPS[$env]}\" APIM_SERVICE_NAME_$env_upper=\"${APIM_SERVICE_NAMES[$env]}\" AZURE_SERVICE_CONNECTION=\"AZURE_SERVICE_CONNECTION_$env_upper\"\r\ndone\r\n```\r\n\r\nAuthorize all groups for pipeline use:\r\n\r\n**PowerShell:**\r\n```powershell\r\n$groupIds = az pipelines variable-group list --query \"[].id\" -o tsv\r\nforeach ($id in $groupIds) {\r\n az pipelines variable-group update --group-id $id --authorize true\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nfor id in $(az pipelines variable-group list --query \"[].id\" -o tsv); do\r\n az pipelines variable-group update --group-id \"$id\" --authorize true\r\ndone\r\n```\r\n\r\nVerify:\r\n```bash\r\naz pipelines variable-group list --query \"[].name\" -o table\r\n```\r\n\r\n---\r\n\r\n## Step 9 (in pipeline): Create Environments\r\n\r\nCreate deployment environments in Azure DevOps:\r\n\r\n**PowerShell:**\r\n```powershell\r\nforeach ($env in $ENVIRONMENTS) {\r\n $body = \"{\\\"name\\\": \\\"$env\\\"}\"\r\n $body | Out-File -Encoding utf8 -FilePath env-body.json\r\n az devops invoke --area environments --resource environments --route-parameters project=$AZDO_PROJECT --http-method POST --api-version 7.1 --in-file env-body.json\r\n}\r\nRemove-Item env-body.json -ErrorAction SilentlyContinue\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n echo \"{\\\"name\\\": \\\"$env\\\"}\" > env-body.json\r\n az devops invoke --area environments --resource environments --route-parameters project=\"$AZDO_PROJECT\" --http-method POST --api-version 7.1 --in-file env-body.json\r\ndone\r\nrm -f env-body.json\r\n```\r\n\r\nAuthorize each environment for all pipelines (prevents first-run permission prompts):\r\n\r\n**PowerShell:**\r\n```powershell\r\n$ADO_RESOURCE = \"499b84ac-1321-427f-aa17-267ca6975798\"\r\n$TOKEN = az account get-access-token --resource $ADO_RESOURCE --query accessToken -o tsv\r\n\r\nforeach ($env in $ENVIRONMENTS) {\r\n $envId = az devops invoke --area environments --resource environments --route-parameters project=$AZDO_PROJECT --query-parameters \"api-version=7.1\" --query \"value[?name=='$env'].id | [0]\" -o tsv\r\n if ($envId) {\r\n $url = \"$AZDO_ORG/$AZDO_PROJECT/_apis/pipelines/pipelinePermissions/environment/$envId?api-version=7.1-preview.1\"\r\n $body = '{\"allPipelines\":{\"authorized\":true}}'\r\n Invoke-RestMethod -Method Patch -Uri $url -Headers @{ Authorization = \"Bearer $TOKEN\" } -ContentType \"application/json\" -Body $body | Out-Null\r\n }\r\n}\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nADO_RESOURCE=\"499b84ac-1321-427f-aa17-267ca6975798\"\r\nTOKEN=$(az account get-access-token --resource \"$ADO_RESOURCE\" --query accessToken -o tsv)\r\n\r\nfor env in \"${ENVIRONMENTS[@]}\"; do\r\n env_id=$(az devops invoke --area environments --resource environments --route-parameters project=\"$AZDO_PROJECT\" --query-parameters \"api-version=7.1\" --query \"value[?name=='$env'].id | [0]\" -o tsv)\r\n if [[ -n \"$env_id\" ]]; then\r\n curl -sS -X PATCH \\\r\n -H \"Authorization: Bearer $TOKEN\" \\\r\n -H \"Content-Type: application/json\" \\\r\n \"$AZDO_ORG/$AZDO_PROJECT/_apis/pipelines/pipelinePermissions/environment/$env_id?api-version=7.1-preview.1\" \\\r\n -d '{\"allPipelines\":{\"authorized\":true}}' >/dev/null\r\n fi\r\ndone\r\n```\r\n\r\n**Note:** Environment approvals and checks still must be configured via the Azure DevOps UI.\r\n\r\n---\r\n\r\n## Step 10: Enable Pipeline Contributions\r\n\r\nGrant the Build Service permission to contribute to the repository.\r\n\r\n**PowerShell:**\r\n```powershell\r\n$PROJECT_ID = az devops project show --project $AZDO_PROJECT --query id -o tsv\r\n$REPO_NAME = $AZDO_PROJECT\r\n$REPO_ID = az repos show --repository $REPO_NAME --query id -o tsv\r\n\r\n$GRAPH_USERS = az devops invoke --area graph --resource users --query-parameters 'api-version=7.1-preview.1' --http-method GET -o json | ConvertFrom-Json\r\n$BUILD_SERVICE_NAME = \"$AZDO_PROJECT Build Service ($ORG_NAME)\"\r\n$BUILD_SERVICE_DESCRIPTOR = ($GRAPH_USERS.value | Where-Object { $_.displayName -eq $BUILD_SERVICE_NAME }).descriptor\r\n\r\n$GIT_REPOS_NAMESPACE = az devops security permission namespace list --query \"[?name=='Git Repositories'].namespaceId\" -o tsv\r\n$TOKEN = \"repoV2/$PROJECT_ID/$REPO_ID\"\r\naz devops security permission update --namespace-id $GIT_REPOS_NAMESPACE --subject $BUILD_SERVICE_DESCRIPTOR --token $TOKEN --allow-bit 4\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nPROJECT_ID=$(az devops project show --project \"$AZDO_PROJECT\" --query id -o tsv)\r\nREPO_NAME=\"$AZDO_PROJECT\"\r\nREPO_ID=$(az repos show --repository \"$REPO_NAME\" --query id -o tsv)\r\n\r\nBUILD_SERVICE_NAME=\"$AZDO_PROJECT Build Service ($ORG_NAME)\"\r\nBUILD_SERVICE_DESCRIPTOR=$(az devops invoke --area graph --resource users --query-parameters 'api-version=7.1-preview.1' --http-method GET -o json | grep -B5 \"\\\"displayName\\\": \\\"$BUILD_SERVICE_NAME\\\"\" | grep '\"descriptor\"' | head -1 | cut -d'\"' -f4)\r\n\r\nGIT_REPOS_NAMESPACE=$(az devops security permission namespace list --query \"[?name=='Git Repositories'].namespaceId\" -o tsv)\r\nTOKEN=\"repoV2/$PROJECT_ID/$REPO_ID\"\r\naz devops security permission update --namespace-id \"$GIT_REPOS_NAMESPACE\" --subject \"$BUILD_SERVICE_DESCRIPTOR\" --token \"$TOKEN\" --allow-bit 4\r\n```\r\n\r\n---\r\n\r\n## Step 11: Verify Setup\r\n\r\nVerify all resources were created correctly:\r\n\r\n**Service Connections:**\r\n```bash\r\naz devops service-endpoint list --query \"[].name\" -o table\r\n```\r\n\r\n**Variable Groups:**\r\n```bash\r\naz pipelines variable-group list --query \"[].name\" -o table\r\n```\r\n\r\nRun the APIOps pipelines and confirm they can authenticate and access APIM resources.\r\n\r\n---\r\n\r\n## Step 12: Create Pipelines\r\n\r\nCreate Azure Pipelines from the YAML files in your repository.\r\n\r\n**PowerShell:**\r\n```powershell\r\n$REPO_NAME = $AZDO_PROJECT\r\n\r\naz pipelines create --name \"apiops-extract\" --repository $REPO_NAME --branch main --yml-path \".azdo/pipelines/run-apiops-extractor.yml\" --repository-type tfsgit --skip-first-run true\r\naz pipelines create --name \"apiops-publish\" --repository $REPO_NAME --branch main --yml-path \".azdo/pipelines/run-apiops-publisher.yml\" --repository-type tfsgit --skip-first-run true\r\n```\r\n\r\n**Git Bash:**\r\n```bash\r\nREPO_NAME=\"$AZDO_PROJECT\"\r\n\r\naz pipelines create --name \"apiops-extract\" --repository \"$REPO_NAME\" --branch main --yml-path \".azdo/pipelines/run-apiops-extractor.yml\" --repository-type tfsgit --skip-first-run true\r\naz pipelines create --name \"apiops-publish\" --repository \"$REPO_NAME\" --branch main --yml-path \".azdo/pipelines/run-apiops-publisher.yml\" --repository-type tfsgit --skip-first-run true\r\n```\r\n\r\nVerify pipelines were created:\r\n```bash\r\naz pipelines list --query \"[].name\" -o table\r\n```";
|
|
7
|
+
export declare const copilotConfigureFilterPromptTemplate: "---\r\nmode: 'agent'\r\ndescription: 'Configure APIOps resource extraction filters'\r\n---\r\n\r\n# Configure APIOps Extractor Filters\r\n\r\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\r\n> Copilot to help you design a `configuration.extractor.yaml` file for your\r\n> repository.\r\n\r\n## Goal\r\n\r\nCreate a `configuration.extractor.yaml` file that limits APIOps extraction to\r\nthe Azure API Management resources your team wants to manage in source control.\r\n\r\n---\r\n\r\n## How Copilot must work through this prompt\r\n\r\nThese rules apply to **every** step below. Follow them strictly:\r\n\r\n1. **Confirm before proceeding.** At the end of every step, summarize what you\r\n learned or propose, then **STOP and wait for the user to confirm** before\r\n moving to the next step. Never chain steps together without an explicit\r\n \"yes\" / \"go ahead\" from the user.\r\n - **Hard stop rule:** When you ask for confirmation, end the response there.\r\n Do **not** include the next question, next resource type, or any forward\r\n action in the same message.\r\n - This hard stop applies to **step boundaries** (Step 0, Step 2, Step 3,\r\n Step 4). In Step 1, follow the single-resource-type cadence below.\r\n2. **Never assume or invent names.** Do not invent API, product, backend,\r\n named value, or any other resource names. Use only names that come from the\r\n live APIM instance or that the user explicitly provides. The local artifact\r\n directory is not authoritative \u2014 it may be stale or empty. When unsure, ask.\r\n3. **Default is extract-everything.** APIOps extracts **all** resources of a\r\n type when that type is **omitted** from the filter. Only add a type to the\r\n filter when the user wants to narrow it (SOME) or exclude it (NONE). Do not\r\n add a type just to list every resource.\r\n4. **Empty array means exclude all.** Setting a type to `[]` excludes every\r\n resource of that type. Use this only when the user explicitly wants NONE.\r\n5. **The JSON schema is the source of structure.** To determine which resource\r\n types support sub-entries and what those sub-entries are (for example,\r\n `apis` \u2192 `operations`, `diagnostics`, `schemas`, `releases`), consult the\r\n `extractor-config` JSON schema referenced in the file's\r\n `# yaml-language-server: $schema=...` comment (the public schema URL).\r\n\r\n---\r\n\r\n## Step 0 \u2014 Determine the Authoritative Resource List\r\n\r\nThe filter runs at **extraction time against the live Azure API Management\r\ninstance**. The local artifact directory may be stale, partial, or empty, so it\r\nis **not** an authoritative list of what exists in Azure. Establish the source\r\nof truth first:\r\n\r\n1. **Prefer querying the live APIM instance.** Ask the user for (or reuse if\r\n already known) the subscription ID, resource group, and APIM service name,\r\n and whether the Azure CLI is logged in. If Azure is reachable, enumerate the\r\n resource types and names directly from the instance (for example with\r\n `az apim` / `az rest` calls) and use that as the source of truth.\r\n2. **Fallback when Azure cannot be queried.** Do **not** treat the local\r\n artifacts as the definitive list. Instead, in Step 1 ask the user\r\n type-by-type; for SOME, the user must provide the resource (and\r\n sub-resource) names themselves.\r\n3. Check whether `configuration.extractor.yaml` already exists (it may have\r\n been created by `apiops init`). If it exists, note its current contents \u2014\r\n you will update it in place rather than overwriting it.\r\n\r\nTell the user which mode you will use (live-Azure list vs. user-provided\r\nnames), and confirm the connection details if querying Azure.\r\n\r\n**STOP. Do not proceed until the user confirms the source of truth.**\r\n\r\n---\r\n\r\n## Step 1 \u2014 Decide Scope Per Resource Type (one type at a time)\r\n\r\nWalk through the resource types **one type at a time**. For each type, ask the\r\nuser which scope they want:\r\n\r\n- **Extract ALL** \u2014 include every resource of this type. Leave this type\r\n **out** of the filter (APIOps extracts everything by default).\r\n- **Extract NONE** \u2014 exclude all resources of this type. Add the type with an\r\n empty array: `tags: []`.\r\n- **Extract SOME** \u2014 include only specific resources. The user provides which\r\n names (or wildcard patterns) to include. Matching is case-insensitive and\r\n supports `*` and `?` wildcards.\r\n\r\n**Single-resource-type cadence for Step 1:**\r\n\r\n- Ask about exactly **one** resource type at a time. Do not batch multiple\r\n types into one prompt.\r\n- **Ask ALL / NONE / SOME first.** Do **not** enumerate or query any names up\r\n front. For ALL or NONE, record the answer and move on \u2014 no enumeration is\r\n needed.\r\n- **Only when the user answers SOME**, then gather names:\r\n - If you can query the live APIM instance, list that type's names from Azure\r\n to help the user choose.\r\n - Otherwise, ask the user to provide the names/patterns. Do **not** invent\r\n names or pull them from the local artifacts.\r\n- When the user answers a type unambiguously, record the decision and move to\r\n the next type.\r\n- **Update `configuration.extractor.yaml` immediately after each decision that\r\n affects the file** (SOME or NONE adds/updates that type's section; ALL means\r\n no change since the type is omitted). Keep the file in sync as you go rather\r\n than waiting until the end.\r\n- Only pause for clarification when the answer is ambiguous.\r\n\r\nResource types to consider (ask only about types that exist in the\r\ninstance/artifacts or that the user mentions):\r\n\r\n`apis`, `products`, `namedValues`, `backends`, `loggers`, `diagnostics`,\r\n`tags`, `versionSets`, `policyFragments`, `gateways`, `groups`,\r\n`subscriptions`, `schemas`, `policies`, `workspaces`.\r\n\r\n> **APIs can be filtered at the sub-resource level.** Whenever `apis` is SOME\r\n> and specific API names are listed in the filter, **ask about each listed\r\n> API's sub-resources** \u2014 `operations`, `diagnostics`, `schemas`, and\r\n> `releases`. The user may want everything for that API, or only a subset\r\n> (for example, a single revision or release). Omit a sub-filter to include\r\n> all of that sub-type; set it to `[]` to exclude all.\r\n\r\n> **Workspaces apply only if the APIM instance uses workspaces.** Skip this\r\n> type entirely if there are no workspaces. When a user wants SOME for\r\n> `workspaces`, each workspace can also be narrowed by its own sub-resources\r\n> (`apis`, `backends`, `diagnostics`, `groups`, `loggers`, `namedValues`,\r\n> `policyFragments`, `products`, `schemas`, `subscriptions`, `tags`,\r\n> `versionSets`). Omit a sub-filter to include all of that sub-type; set it to\r\n> `[]` to exclude all. Only offer this depth if the user wants it.\r\n\r\n> **Service-level `policies` is effectively a single global policy.** For this\r\n> type, ask only **include (ALL)** or **exclude (NONE)** \u2014 SOME does not apply.\r\n\r\nAfter all types are decided, summarize the per-type decisions and **STOP for\r\nconfirmation** before generating YAML.\r\n\r\n---\r\n\r\n## Step 2 \u2014 Propose a Filter Strategy\r\n\r\nBased on the recorded decisions:\r\n\r\n1. Recommend the smallest filter that safely captures the intended scope\r\n (remember: omitted types are fully extracted, so only NONE/SOME types\r\n appear in the file).\r\n2. Explain any tradeoffs between broad and narrow filters.\r\n3. Call out any risk of accidentally excluding required dependencies \u2014 for\r\n example, excluding a named value or backend that an included API's policy\r\n references.\r\n\r\nIf the user is unsure, recommend a conservative filter that is easy to refine,\r\nthen **STOP for confirmation**.\r\n\r\n---\r\n\r\n## Step 3 \u2014 Generate `configuration.extractor.yaml`\r\n\r\n> **Note:** The file `configuration.extractor.yaml` may already exist if the\r\n> user ran `apiops init`. If it exists, **update it in place** rather than\r\n> overwriting unrelated content.\r\n\r\nCreate the YAML file content reflecting the confirmed decisions.\r\n\r\nRequirements:\r\n\r\n- **Preserve the existing schema comment.** If the file already has a\r\n `# yaml-language-server: $schema=...` line (as `apiops init` generates), keep\r\n it **exactly as-is** \u2014 it already points at the correct schema version. Only\r\n if the file has **no** schema comment, add one referencing the current schema\r\n version:\r\n `# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/apiops-cli/main/schemas/v1/extractor-config.schema.json`\r\n- Output valid YAML.\r\n- Only include resource types the user chose to narrow (SOME) or exclude\r\n (NONE). Leave ALL types out of the file.\r\n- Use only names/patterns that exist in the artifacts or that the user\r\n provided \u2014 do not invent names.\r\n- Add a short comment only when it explains a non-obvious choice.\r\n\r\nShow the generated file and **STOP for confirmation** before treating it as\r\nfinal.\r\n\r\n---\r\n\r\n## Step 4 \u2014 Validate the Result\r\n\r\nBefore finishing:\r\n\r\n1. Review the generated YAML for syntax issues and schema validity.\r\n2. Confirm the filters align with the user's intended extraction scope, and\r\n that no type the user wanted is accidentally excluded or fully extracted.\r\n3. Remind the user to run the extractor and inspect the artifact output.\r\n\r\nIf the extractor output is too broad or too narrow, help the user refine the\r\nfilter file iteratively.\r\n";
|
|
8
|
+
export declare const copilotConfigureOverridesPromptTemplate: "---\r\nmode: 'agent'\r\ndescription: 'Configure APIOps environment overrides'\r\n---\r\n\r\n# Configure APIOps Environment Overrides\r\n\r\n> **How to use:** Open this file in VS Code with GitHub Copilot and ask\r\n> Copilot to help you create environment-specific APIOps override files.\r\n\r\n## Goal\r\n\r\nCreate one `configuration.{environment}.yaml` file per deployment environment\r\nso APIOps publish runs can promote the same artifacts across environments with\r\nenvironment-specific settings.\r\n\r\n---\r\n\r\n## How Copilot must work through this prompt\r\n\r\nThese rules apply to **every** step below. Follow them strictly:\r\n\r\n1. **Confirm before proceeding.** At the end of every step, summarize what you\r\n learned or propose, then **STOP and wait for the user to confirm** before\r\n moving to the next step. Never chain steps together without an explicit\r\n \"yes\" / \"go ahead\" from the user.\r\n - **Hard stop rule:** When you ask for confirmation, end the response there.\r\n Do **not** include the next question, next override, or any forward action\r\n in the same message.\r\n - This hard stop applies to **step boundaries** (Step 0, Step 1, Step 2,\r\n Step 3, Step 5, Step 6). In Step 4, follow the single-setting cadence below.\r\n2. **Never assume a value.** Do not invent backend URLs, service URLs,\r\n resource IDs, instrumentation keys, secret names, Key Vault URLs, or token\r\n names. If you don't know a value, **ask the user**.\r\n3. **Do not tokenize everything.** A `{#[TOKEN_NAME]#}` placeholder is only for\r\n values the user explicitly wants injected by the pipeline (see Step 4 for\r\n how to classify each value). Many values are plain, non-sensitive settings\r\n that should be written literally.\r\n4. **Ask, don't guess, about pipeline tokens.** Only use a token after the user\r\n has told you that token exists (or will be added) in their pipeline.\r\n5. **The JSON schema is the source of structure.** To determine the valid\r\n shape of an override entry and its nested properties (for example a Key\r\n Vault named value's `keyVault.secretIdentifier` / `identityClientId`),\r\n consult the `override-config` JSON schema referenced in each file's\r\n `# yaml-language-server: $schema=...` comment (the public schema URL). Do\r\n **not** rely on the `apiops-cli` source repository \u2014 end users only have\r\n the built npm package and the published schema URL.\r\n\r\n---\r\n\r\n## Step 0 \u2014 Detect and Confirm Environments\r\n\r\nBefore asking the user anything else, look for existing environment\r\nconfiguration files in the repository:\r\n\r\n1. Search for files matching `configuration.*.yaml` (excluding\r\n `configuration.extractor.yaml`). The `*` portion is the environment name.\r\n2. Also check CI/CD workflow files (`.github/workflows/` or\r\n `.azdo/pipelines/`) for environment references.\r\n\r\nThen **present the detected environments to the user** and ask which ones they\r\nwant override files for:\r\n\r\n> \"I found these environments: `<list>`. Which of these do you want to create\r\n> or update override files for? If you deploy to other environments I didn't\r\n> detect, list them too.\"\r\n\r\nIf no config files are found, ask:\r\n> \"What environments do you deploy to? Common patterns include `dev, stage, prod`\r\n> or `stage, prod` (if dev shares the same APIM instance as stage).\"\r\n\r\n**STOP. Do not proceed until the user has explicitly confirmed the exact list\r\nof environments to work on.**\r\n\r\n---\r\n\r\n## Step 1 \u2014 Gather Information\r\n\r\nOnce the environment list is confirmed, collect the following:\r\n\r\n1. **Existing override config files** \u2014 If `configuration.{env}.yaml` files\r\n already exist:\r\n - Use those as the starting point.\r\n - Ask whether the user wants to update them or start fresh.\r\n\r\n2. **APIM artifacts location** \u2014 Ask the user where the APIOps artifact\r\n directory is (default: `./apim-artifacts`). You will inspect the artifacts\r\n in the next step.\r\n\r\nSummarize what you've learned and **STOP for confirmation** before continuing.\r\n\r\n---\r\n\r\n## Step 2 \u2014 Investigate Artifacts and Create Stub Override Files\r\n\r\nUsing the artifact directory confirmed in Step 1:\r\n\r\n1. Scan the artifacts for references to **external resources** \u2014 the things\r\n that typically differ between environments. Examples:\r\n - API `serviceUrl` values\r\n - Backend service URLs and linked `resourceId`s\r\n - Named values (secrets and plain config values)\r\n - Logger `resourceId`s and credentials\r\n - Diagnostic `loggerId` references\r\n - Gateway or VNet references\r\n - Policy fragment references to external endpoints\r\n - Workspace-scoped resources (only if the APIM instance uses **workspaces**)\r\n \u2014 workspaces can contain their own APIs, backends, named values, loggers,\r\n etc. that may need per-environment overrides\r\n\r\n > **Note:** References to sub-resources of the same APIM instance (e.g.,\r\n > one API referencing another API's policy) are handled automatically by\r\n > APIOps and do **not** need overrides.\r\n\r\n2. Produce a **plain list of override candidates** grouped by resource type\r\n (e.g., \"APIs needing a serviceUrl: `src-graphql-passthrough`,\r\n `src-rest-versioned-v1`\u2026\"). Do **not** decide yet which are tokens versus\r\n literals \u2014 that happens in Step 3.\r\n\r\n3. Present this list and ask the user to confirm which items actually need\r\n per-environment overrides and which can be left as-is.\r\n\r\n4. Once the candidate list is confirmed, **create the stub override files** \u2014\r\n one `configuration.{env}.yaml` per confirmed environment \u2014 containing every\r\n confirmed candidate as an entry with the correct `name` and structure but\r\n **blank values** (e.g., empty strings `\"\"` or empty `properties`). This\r\n shows the shape of each file; the actual values are filled in during\r\n Step 4. **Preserve any existing schema comment.** If a file already has a\r\n `# yaml-language-server: $schema=...` line (as `apiops init` generates),\r\n keep it **exactly as-is** \u2014 it already points at the correct schema version.\r\n Only when creating a brand-new file with no schema comment, add one\r\n referencing the current schema version:\r\n `# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/apiops-cli/main/schemas/v1/override-config.schema.json`\r\n\r\n**STOP for confirmation before continuing to Step 3.**\r\n\r\n---\r\n\r\n## Step 3 \u2014 Confirm Available Pipeline Tokens\r\n\r\nBefore filling in any value, **ask the user** which environment variables /\r\npipeline variables are available for this environment, and get the **exact,\r\ncase-sensitive** token names.\r\n\r\n**Known `apiops init` tokens.** If the user scaffolded the repo with\r\n`apiops init`, the generated publish pipeline already wires up a standard set\r\nof pipeline variables / secrets that are usable as `{#[...]#}` tokens. You may\r\n**ask** whether the user has these (substitute `<ENV>` with the uppercased\r\nenvironment name, e.g. `STAGE`):\r\n\r\n- `AZURE_SUBSCRIPTION_ID_<ENV>` (e.g., `AZURE_SUBSCRIPTION_ID_STAGE`)\r\n- `APIM_RESOURCE_GROUP_<ENV>` (e.g., `APIM_RESOURCE_GROUP_STAGE`)\r\n- `APIM_SERVICE_NAME_<ENV>` (e.g., `APIM_SERVICE_NAME_STAGE`)\r\n- GitHub Actions only: `AZURE_CLIENT_ID`, `AZURE_TENANT_ID` (used for login;\r\n rarely needed inside override files)\r\n\r\n> Note: some repos use `AZURE_SUBSCRIPTION_ID` (global, no env suffix) as the\r\n> default init-generated name. Others customize to `AZURE_SUBSCRIPTION_ID_<ENV>`.\r\n> Ask the user which naming pattern exists in their pipeline.\r\n\r\nAsk the user to **confirm which of these they actually have**, then ask whether\r\nthere are **any other** tokens:\r\n\r\n> \"If you ran `apiops init`, you may already have these pipeline variables:\r\n> `AZURE_SUBSCRIPTION_ID` (or `AZURE_SUBSCRIPTION_ID_STAGE`),\r\n> `APIM_RESOURCE_GROUP_STAGE`, `APIM_SERVICE_NAME_STAGE`.\r\n> Which of these do you have? And are there any other pipeline variables (with\r\n> their exact, case-sensitive names) I should use as tokens?\"\r\n\r\n> **Beyond the known `init` tokens, do NOT propose, guess, or pre-populate\r\n> tokens.** Do not invent token names for secrets, URLs, or resource segments.\r\n> Let the user tell you what else exists.\r\n\r\nRecord this list of confirmed tokens. You may **only** use these token names\r\nlater. Never invent a token, and never wrap a value in `{#[TOKEN_NAME]#}`\r\nunless its token is on this confirmed list. The publish step fails if a token\r\nhas no matching pipeline variable.\r\n\r\n**STOP and confirm the token list before continuing to Step 4.**\r\n\r\n---\r\n\r\n## Step 4 \u2014 Fill In Each Override With the User\r\n\r\nWalk through the stub entries created in Step 2 **one setting/property at a\r\ntime** (for example one `resourceId` or one `value` field), not one whole\r\noverride object at a time. Do not batch multiple settings in a single prompt.\r\n\r\n**Single-setting cadence for Step 4:**\r\n\r\n- Ask for exactly one setting when information is missing.\r\n- If the user provides that setting unambiguously, write it immediately.\r\n- After writing it, proceed by asking for the next single missing setting.\r\n- Only pause for confirmation when the user explicitly asks for confirmation,\r\n or when the value is ambiguous and you need clarification.\r\n- Do not ask the user to reconfirm a setting they just provided unless there is\r\n a concrete ambiguity.\r\n\r\nFor each override value, classify how it should be supplied using the confirmed\r\ntoken list from Step 3. There are three kinds of values \u2014 do not default to\r\ntokens:\r\n\r\n| Kind | When to use | How it's written |\r\n| --- | --- | --- |\r\n| **Literal value** | Non-sensitive settings that are safe to commit \u2014 API/backend URLs, resource IDs, Application Insights logger resource IDs, **Application Insights instrumentation keys** (telemetry ingestion keys, **not secrets**), feature flags. | Plain YAML value, e.g. `url: \"https://api.contoso.com\"` |\r\n| **Pipeline token** | Secrets or values the user wants injected at publish time from the pipeline's secret store (GitHub Actions secrets / Azure DevOps variable groups). | `value: \"{#[TOKEN_NAME]#}\"` \u2014 only use a token the user confirms exists |\r\n| **Key Vault reference** | Secrets stored centrally in Azure Key Vault and referenced by named values. | A `keyVault.secretIdentifier` URL (see pattern below) |\r\n\r\nFor each candidate value, ask the user something like:\r\n\r\n> \"For `<resource>.<property>`, what is the value in **<env>**? Is it a fixed\r\n> value I can write directly, a secret your pipeline injects via a token, or a\r\n> Key Vault secret?\"\r\n\r\nConcrete guidance to follow while classifying:\r\n\r\n- **API service URLs and backend URLs** \u2014 Ask the user for the actual URL per\r\n environment. These are usually plain literal values, **not tokens**, unless\r\n the user specifically wants them injected by the pipeline.\r\n- **Application Insights instrumentation keys** \u2014 These are **not secrets**.\r\n Write the value the user provides directly, or leave the extracted value in\r\n place. Do **not** wrap them in `{#[TOKEN_NAME]#}` unless the user asks.\r\n- **Resource IDs (loggers, backends, diagnostics)** \u2014 Usually literal values.\r\n Only the subscription ID / resource group / service name segments need\r\n tokenizing if the user wants them injected; ask first.\r\n- **Connection strings, API keys, passwords** \u2014 These are secrets. Use a\r\n pipeline token or a Key Vault reference based on the user's preference.\r\n\r\n### Key Vault reference \u2014 the correct pattern\r\n\r\nA Key Vault-backed named value uses a **`keyVault.secretIdentifier`** that is a\r\n**full secret URL**. Do **not** create a separate named value just to hold a\r\nKey Vault base URL, and do **not** concatenate a token with a secret name.\r\n\r\nCorrect \u2014 literal full secret identifier:\r\n\r\n```yaml\r\nnamedValues:\r\n - name: db-connection-string\r\n properties:\r\n keyVault:\r\n secretIdentifier: \"https://prod-kv.vault.azure.net/secrets/db-conn\"\r\n identityClientId: \"{#[MANAGED_IDENTITY_CLIENT_ID]#}\"\r\n```\r\n\r\nAlso acceptable \u2014 tokenize the whole secret identifier when the user wants the\r\npipeline to supply it:\r\n\r\n```yaml\r\nnamedValues:\r\n - name: db-connection-string\r\n properties:\r\n keyVault:\r\n secretIdentifier: \"{#[DB_CONN_SECRET_IDENTIFIER]#}\"\r\n identityClientId: \"{#[MANAGED_IDENTITY_CLIENT_ID]#}\"\r\n```\r\n\r\nAs you fill in each override, write it into the stub file using the right form:\r\n\r\n- Write literal values directly; use `{#[TOKEN_NAME]#}` only for confirmed\r\n tokens; use full `keyVault.secretIdentifier` URLs for Key Vault secrets.\r\n- Never commit real secret values \u2014 those must be tokens or Key Vault\r\n references.\r\n\r\nContinue setting-by-setting until there are no missing values.\r\n\r\n---\r\n\r\n## Step 5 \u2014 Finalize and Review the Override Files\r\n\r\nOnce every stub override has been filled in across all environments:\r\n\r\n- Re-read each `configuration.{env}.yaml` file and confirm it is valid YAML\r\n with no leftover blank values from the stubs.\r\n- Confirm the schema comment is present as the first line of each file.\r\n- Keep files easy to compare across environments and avoid duplicating\r\n unchanged base configuration.\r\n\r\nShow the finalized files and **STOP for confirmation** before treating them as\r\nfinal.\r\n\r\n---\r\n\r\n## Step 6 \u2014 Validate the Promotion Model\r\n\r\nBefore finishing:\r\n\r\n1. Verify every generated override file matches the intended environment.\r\n2. Verify all **secrets** use either `{#[TOKEN_NAME]#}` or a Key Vault\r\n reference \u2014 and that non-secrets (URLs, resource IDs, instrumentation keys)\r\n are written as plain values, not tokens.\r\n3. Confirm every `{#[TOKEN_NAME]#}` used corresponds to a token the user said\r\n exists in their pipeline.\r\n4. Remind the user to add any `{#[TOKEN_NAME]#}` tokens to their pipeline's\r\n secret store (GitHub Actions Secrets or Azure DevOps variable groups).\r\n Help with this if they ask. Note that the pipeline fails with an error if\r\n any tokens are missing.\r\n5. Remind the user to test publish for a lower environment before promoting\r\n further.\r\n";
|
|
9
|
+
export declare const githubActionsIdentityGuideTemplate: "# APIOps GitHub Actions identity setup guide\r\n\r\n> Prefer an automated walkthrough? Open `.github/prompts/apiops-setup-workflow-identity.prompt.md` in VS Code with GitHub Copilot and ask Copilot to guide or automate the setup for you.\r\n\r\n> **Important identity distinction:** In GitHub Actions, the Azure app registration/service principal is only for Azure and APIM access. Pull request creation is handled separately by the workflow's `GITHUB_TOKEN`, so Azure RBAC alone will not give the workflow permission to open PRs.\r\n\r\n## Before you start\r\n\r\n- An Azure subscription with an API Management instance\r\n- GitHub repository admin access\r\n- Permission in Microsoft Entra ID to create or manage app registrations\r\n\r\nHelpful documentation:\r\n\r\n- [Use OpenID Connect with Azure Login in GitHub Actions](https://learn.microsoft.com/azure/developer/github/connect-from-azure-openid-connect)\r\n- [Create and manage app registrations in the Azure portal](https://learn.microsoft.com/entra/identity-platform/quickstart-register-app)\r\n- [Assign Azure roles using the Azure portal](https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal)\r\n- [Manage GitHub Actions secrets](https://docs.github.com/actions/security-guides/encrypted-secrets)\r\n- [Manage GitHub environments](https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment)\r\n\r\n## Step 1: Review the generated workflow files in GitHub\r\n\r\n1. Commit and push the generated files to your repository.\r\n2. Open your repository in the **GitHub web UI**.\r\n3. Go to **Actions** and confirm you can see:\r\n - **Run APIM Extractor**\r\n - **Run APIM Publisher**\r\n4. If your organization requires approval for new workflows, complete that approval before continuing.\r\n\r\n## Step 2: Create or choose an app registration in Azure portal\r\n\r\n> \uD83D\uDCD6 [Register an application in the Azure portal](https://learn.microsoft.com/entra/identity-platform/quickstart-register-app)\r\n\r\n1. Open the **Azure portal**.\r\n2. Go to **Microsoft Entra ID** \u2192 **App registrations** \u2192 **New registration**.\r\n3. Enter a friendly name such as `apiops-github-sp`.\r\n4. Register the application and open its overview page.\r\n5. Record these values for later:\r\n - **Application (client) ID**\r\n - **Directory (tenant) ID**\r\n\r\n## Step 3: Grant the Azure identity access to APIM\r\n\r\n> \uD83D\uDCD6 [Assign Azure roles using the Azure portal](https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal)\r\n\r\nFor each environment, do the following steps:\r\n\r\n1. In the **Azure portal**, open the resource group that contains the APIM instance for that environment.\r\n2. Go to **Access control (IAM)** \u2192 **Add role assignment**.\r\n3. Assign **Reader** on the resource group to the app registration.\r\n4. Open the APIM service itself and assign **API Management Service Contributor** to the app registration.\r\n5. Wait a few minutes for RBAC changes to propagate before you test the workflow.\r\n\r\n## Step 4: Add federated credentials in Azure portal\r\n\r\n> \uD83D\uDCD6 [Configure a federated identity credential on an app](https://learn.microsoft.com/entra/workload-id/workload-identity-federation-create-trust)\r\n\r\n1. Return to **Microsoft Entra ID** \u2192 **App registrations** \u2192 your app.\r\n2. Open **Certificates & secrets** \u2192 **Federated credentials** \u2192 **Add credential**.\r\n3. Add one credential for the main branch publish workflow:\r\n - **Scenario**: **GitHub Actions deploying Azure resources**\r\n - **Organization**: your GitHub org or user\r\n - **Repository**: your repository\r\n - **Entity type**: **Branch**\r\n - **Branch name**: `main`\r\n - **Credential name**: `github-main-branch`\r\n4. For each environment, add one additional federated credential:\r\n - **Entity type**: **Environment**\r\n - **Environment name**: the GitHub environment name (must match what you create in Step 5)\r\n - **Credential name**: `github-env-<environment>`\r\n\r\n## Step 5: Create GitHub environments in the web UI\r\n\r\n> \uD83D\uDCD6 [Using environments for deployment](https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment)\r\n\r\n1. In GitHub, go to **Settings** \u2192 **Environments**.\r\n2. For each environment, create a GitHub environment with the same name used during `apiops init`.\r\n3. Add protection rules such as required reviewers for production environments if your process needs approvals.\r\n\r\n## Step 6: Add repository and environment secrets in GitHub\r\n\r\n> \uD83D\uDCD6 [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions)\r\n\r\n1. Go to **Settings** \u2192 **Secrets and variables** \u2192 **Actions**.\r\n2. Under **Repository secrets**, create:\r\n - `AZURE_CLIENT_ID` \u2014 the Application (client) ID from the app registration\r\n - `AZURE_TENANT_ID` \u2014 the Directory (tenant) ID from the app registration\r\n3. For each environment, add the following **environment secrets**:\r\n - `AZURE_SUBSCRIPTION_ID` \u2014 the Azure subscription ID for that environment\r\n - `APIM_RESOURCE_GROUP_<ENV>` \u2014 the resource group containing the APIM instance (replace `<ENV>` with the upper-case environment name)\r\n - `APIM_SERVICE_NAME_<ENV>` \u2014 the APIM service name (replace `<ENV>` with the upper-case environment name)\r\n\r\n## Step 7: Verify the workflow end to end\r\n\r\n1. Go to **Actions** \u2192 **Run APIM Extractor** \u2192 **Run workflow**.\r\n2. Select the environment you configured in GitHub and choose whether to run **Extract All APIs** or use `configuration.extractor.yaml`.\r\n3. Confirm the workflow can authenticate to Azure, export artifacts, and create a pull request.\r\n4. If the Azure login succeeds but the PR step fails, review repository permissions for `GITHUB_TOKEN` and any branch protection rules because PR creation is not controlled by the Azure identity.\r\n\r\n## Security Notes\r\n\r\n- Prefer OIDC/federated credentials over client secrets so there is no stored Azure credential to rotate.\r\n- Grant the workflow identity only the Azure roles it actually needs by following a least-privilege approach.\r\n- Periodically review GitHub environments, repository secrets, and Azure role assignments.\r\n";
|
|
10
|
+
export declare const azureDevOpsIdentityGuideTemplate: "# Identity setup guide for APIOps extract and publish Azure DevOps Pipelines\r\n\r\n> Prefer an automated walkthrough? Open `.github/prompts/apiops-setup-pipeline-identity.prompt.md` in VS Code with GitHub Copilot and ask Copilot to guide or automate the setup for you.\r\n\r\n> **Important identity distinction:** In Azure DevOps, the Azure app registration/service principal is for Azure and APIM access only. Repository contributions and pull request creation come from the project **Build Service identity**, which must be granted repository permissions separately.\r\n\r\n## Before you start\r\n\r\n- Access to the **Azure portal**\r\n- Access to the **Azure DevOps web portal**\r\n- Permission to create or manage app registrations in Microsoft Entra ID\r\n- Permission to create Azure DevOps service connections, variable groups, environments, and pipelines\r\n\r\nHelpful documentation:\r\n\r\n- [Create and manage app registrations in the Azure portal](https://learn.microsoft.com/entra/identity-platform/quickstart-register-app)\r\n- [Assign Azure roles using the Azure portal](https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal)\r\n- [Create Azure Resource Manager service connections with workload identity federation](https://learn.microsoft.com/azure/devops/pipelines/library/connect-to-azure)\r\n- [Create variable groups in Azure Pipelines](https://learn.microsoft.com/azure/devops/pipelines/library/variable-groups)\r\n- [Set repository permissions in Azure DevOps](https://learn.microsoft.com/azure/devops/repos/git/set-git-repository-permissions)\r\n\r\n## Step 1: Review the generated pipeline files in your repo\r\n\r\n1. Commit and push the generated files to your Azure DevOps repository.\r\n2. Confirm these files are available in the repo browser:\r\n - `.azdo/pipelines/run-apiops-extractor.yml`\r\n - `.azdo/pipelines/run-apiops-publisher.yml`\r\n3. **IMPORTANT:** Note the environment names you chose when running `apiops init` because you will create matching service connections, variable groups, and approvals.\r\n\r\n## Step 2: Create or choose an app registration in Azure portal\r\n\r\n> \uD83D\uDCD6 [Register an application in the Azure portal](https://learn.microsoft.com/entra/identity-platform/quickstart-register-app)\r\n\r\n1. Open the **Azure portal**.\r\n2. Go to **Microsoft Entra ID** \u2192 **App registrations** \u2192 **New registration**.\r\n3. Enter a friendly name such as `apiops-azdo-sp`.\r\n4. Register the application and open its overview page.\r\n5. Record:\r\n - **Application (client) ID**\r\n - **Directory (tenant) ID**\r\n6. You do not need to create a client secret for this workload identity federation flow.\r\n\r\n## Step 3: Grant the Azure identity access to each APIM environment\r\n\r\n> \uD83D\uDCD6 [Assign Azure roles using the Azure portal](https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal)\r\n\r\nFor each environment, use the **Azure portal** to grant:\r\n\r\n- **Reader** on the resource group that contains the APIM instance\r\n- **API Management Service Contributor** on the APIM service itself\r\n\r\nUse **Access control (IAM)** on each resource group and APIM instance to create the assignments.\r\n\r\n## Step 4: Create one Azure service connection per environment\r\n\r\n> \uD83D\uDCD6 [Create an Azure Resource Manager service connection using workload identity federation](https://learn.microsoft.com/azure/devops/pipelines/library/connect-to-azure)\r\n\r\nFor each environment, do the following steps:\r\n\r\n1. In **Azure DevOps**, open **Project settings** \u2192 **Service connections** \u2192 **New service connection**.\r\n2. Choose **Azure Resource Manager**.\r\n3. Select **Workload identity federation**.\r\n4. Use the app registration from Step 2.\r\n5. Name the service connection `AZURE_SERVICE_CONNECTION_<ENV>` (replace `<ENV>` with the upper-case environment name) unless you plan to edit the generated pipeline YAML.\r\n6. Complete the validation flow in Azure DevOps so the service connection can issue the issuer and subject values required for federation.\r\n7. If Azure DevOps asks you to finish the federated credential in Azure, follow the linked experience or copy the issuer/subject into the app registration's **Federated credentials** blade in the Azure portal.\r\n\r\n## Step 5: Create variable groups in Azure DevOps\r\n\r\n> \uD83D\uDCD6 [Add and use variable groups in Azure Pipelines](https://learn.microsoft.com/azure/devops/pipelines/library/variable-groups)\r\n\r\nFor each environment, do the following steps:\r\n\r\n1. Go to **Pipelines** \u2192 **Library** \u2192 **+ Variable group**.\r\n2. Name the variable group `apim-<environment>` (e.g. `apim-dev`, `apim-prod`).\r\n3. Add the following variables:\r\n - `AZURE_SERVICE_CONNECTION` \u2014 the service connection name from Step 4\r\n - `AZURE_SUBSCRIPTION_ID` \u2014 the Azure subscription ID for that environment\r\n - `APIM_RESOURCE_GROUP` \u2014 the resource group containing the APIM instance\r\n - `APIM_SERVICE_NAME` \u2014 the APIM service name\r\n - `APIM_RESOURCE_GROUP_<ENV>` \u2014 same value, upper-case environment suffix (used by the publish pipeline)\r\n - `APIM_SERVICE_NAME_<ENV>` \u2014 same value, upper-case environment suffix (used by the publish pipeline)\r\n4. Authorize each variable group for pipeline use when Azure DevOps prompts you.\r\n\r\n## Step 6: Create Azure DevOps environments and approvals\r\n\r\n> \uD83D\uDCD6 [Create and target an environment](https://learn.microsoft.com/azure/devops/pipelines/process/environments)\r\n\r\n1. Go to **Pipelines** \u2192 **Environments**.\r\n2. Create an environment for each deployment target used by the publish pipeline.\r\n3. Add approvals and checks for production or other protected environments as needed by your release process.\r\n\r\n## Step 7: Grant repository permissions to the Build Service identity\r\n\r\n> \uD83D\uDCD6 [Set repository permissions in Azure DevOps](https://learn.microsoft.com/azure/devops/repos/git/set-git-repository-permissions)\r\n\r\n1. In **Azure DevOps**, open **Project settings** \u2192 **Repositories** \u2192 your repository \u2192 **Security**.\r\n2. Find the entry named **`<Project Name> Build Service (<Organization Name>)`**.\r\n3. Grant the minimum permissions required for your workflow, typically:\r\n - **Contribute**\r\n - **Create branch**\r\n - **Create pull request**\r\n4. If the pipeline can read APIM but cannot push extracted artifacts or open a PR, this is usually the missing step because the Build Service identity is separate from the Azure app registration.\r\n\r\n## Step 8: Create the pipelines in Azure DevOps\r\n\r\n> \uD83D\uDCD6 [Create your first pipeline](https://learn.microsoft.com/azure/devops/pipelines/create-first-pipeline)\r\n\r\n1. Go to **Pipelines** \u2192 **Create Pipeline**.\r\n2. Choose your repository.\r\n3. Select **Existing Azure Pipelines YAML file**.\r\n4. Create a pipeline for each generated YAML file:\r\n - `.azdo/pipelines/run-apiops-extractor.yml`\r\n - `.azdo/pipelines/run-apiops-publisher.yml`\r\n5. Save without running if you still need approvals or variable authorization.\r\n\r\n## Step 9: Verify the setup\r\n\r\n1. Run the extractor pipeline manually.\r\n2. Confirm the pipeline can authenticate to Azure and read/write the expected APIM resources.\r\n3. Confirm it can push artifacts and create a pull request in Azure DevOps.\r\n4. If Azure access works but PR creation fails, re-check repository permissions for the Build Service identity.\r\n\r\n## Security notes\r\n\r\n- Prefer workload identity federation over client secrets.\r\n- Scope Azure roles and service connections only to the subscriptions and APIM instances each environment needs.\r\n- Review Build Service repository permissions regularly and remove extra rights if they are no longer needed.\r\n";
|
|
10
11
|
export declare const copilotGithubEnvironmentFederatedCredentialTemplate: "### {{ENV}} environment\n\n**On macOS/Linux (Bash):**\n```bash\naz ad app federated-credential create \\\n --id \"$APP_ID\" \\\n --parameters '{\n \"name\": \"github-env-{{ENV}}\",\n \"issuer\": \"https://token.actions.githubusercontent.com\",\n \"subject\": \"repo:'\"${GITHUB_ORG}\"'/'\"${GITHUB_REPO}\"':environment:{{ENV}}\",\n \"audiences\": [\"api://AzureADTokenExchange\"]\n }'\n```\n\n**On Windows (PowerShell):**\n```powershell\naz ad app federated-credential create `\n --id $APP_ID `\n --parameters '{\\\"name\\\":\\\"github-env-{{ENV}}\\\",\\\"issuer\\\":\\\"https://token.actions.githubusercontent.com\\\",\\\"subject\\\":\\\"repo:'${GITHUB_ORG}'/'${GITHUB_REPO}':environment:{{ENV}}\\\",\\\"audiences\\\":[\\\"api://AzureADTokenExchange\\\"]}'\n```\n";
|
|
11
12
|
export declare const copilotGithubEnvironmentSecretCommandsTemplate: "# {{ENV}} environment secrets\ngh secret set AZURE_SUBSCRIPTION_ID --body \"${AZURE_SUBSCRIPTION_ID_{{ENV_UPPER}}}\" --env {{ENV}}\ngh secret set APIM_RESOURCE_GROUP_{{ENV_UPPER}} --body \"${APIM_RG_{{ENV_UPPER}}}\" --env {{ENV}}\ngh secret set APIM_SERVICE_NAME_{{ENV_UPPER}} --body \"${APIM_NAME_{{ENV_UPPER}}}\" --env {{ENV}}\n";
|
|
13
|
+
export declare const filterConfigTemplate: "# yaml-language-server: $schema={{SCHEMA_URL}}\r\n# APIM Extract Filter Configuration\r\n# Customize this file to control which resources are extracted\r\n# For full format details and examples, see:\r\n# https://github.com/Azure/apiops-cli/blob/main/docs/guides/filtering-resources.md\r\n\r\n# Extract only specific APIs by name (or wildcard pattern)\r\n# apis:\r\n# - echo-api\r\n# - petstore-api\r\n# - 'prod-*' # Wildcard: all APIs starting with prod-\r\n# - '*-internal-*' # Wildcard: all APIs containing -internal-\r\n\r\n# Advanced: Filter API sub-resources (operations, diagnostics, schemas, releases)\r\n# apis:\r\n# - echo-api # Include all sub-resources\r\n# - petstore-api: # Control sub-resources\r\n# operations:\r\n# - get-pets\r\n# - create-pet\r\n# - 'list-*' # Wildcard: all operations starting with list-\r\n# diagnostics:\r\n# - applicationinsights\r\n# schemas: [] # Exclude all schemas\r\n# releases:\r\n# - v1\r\n\r\n# Extract only specific products\r\n# products:\r\n# - starter\r\n# - unlimited\r\n\r\n# Extract only specific backends\r\n# backends:\r\n# - backend-api\r\n# - legacy-backend\r\n\r\n# Extract only specific named values\r\n# namedValues:\r\n# - api-key\r\n# - connection-string\r\n\r\n# Extract only specific loggers\r\n# loggers:\r\n# - appinsights-logger\r\n\r\n# Extract only specific diagnostics\r\n# diagnostics:\r\n# - applicationinsights\r\n\r\n# Extract only specific tags\r\n# tags:\r\n# - production\r\n# - external\r\n\r\n# Extract only specific policy fragments\r\n# policyFragments:\r\n# - rate-limit-fragment\r\n# - cors-fragment\r\n\r\n# Extract only specific gateways\r\n# gateways:\r\n# - default\r\n# - internal-gateway\r\n\r\n# Extract only specific version sets\r\n# versionSets:\r\n# - payments-v1\r\n\r\n# Extract only specific groups\r\n# groups:\r\n# - administrators\r\n\r\n# Extract only specific subscriptions\r\n# subscriptions:\r\n# - starter-subscription\r\n\r\n# Extract only specific schemas\r\n# schemas:\r\n# - pet-schema\r\n\r\n# Filter service-level policies\r\n# policies:\r\n# - policy\r\n\r\n# Extract only specific policy restrictions\r\n# policyRestrictions:\r\n# - global-policy-restriction\r\n\r\n# Extract only specific documentations\r\n# documentations:\r\n# - getting-started\r\n\r\n# Extract only specific workspaces\r\n# workspaces:\r\n# - dev-workspace\r\n\r\n# Advanced: Filter workspace sub-resources\r\n# workspaces:\r\n# - team-workspace:\r\n# apis:\r\n# - team-api-1\r\n# - team-api-2\r\n# backends:\r\n# - team-backend\r\n# namedValues:\r\n# - team-api-key\r\n\r\n# Filter behavior:\r\n# - Leave a section commented out to include ALL resources of that type\r\n# - Set a section to an empty array ([]) to exclude ALL resources of that type\r\n# Example:\r\n# gateways: []\r\n# subscriptions: []\r\n# - Use * to match any characters: prod-* matches prod-api, prod-users\r\n# - Use ? to match a single character: api-v? matches api-v1, api-v2\r\n# - Exact names and wildcard patterns can be mixed in the same list\r\n# - All matching is case-insensitive\r\n";
|
|
14
|
+
export declare const overrideConfigTemplate: "# yaml-language-server: $schema={{SCHEMA_URL}}\r\n# APIM Override Configuration for {{ENVIRONMENT}} environment\r\n# Customize resource properties for this specific environment\r\n# For full format details and examples, see:\r\n# https://github.com/Azure/apiops-cli/blob/main/docs/guides/environment-overrides.md\r\n\r\n# Override named values (e.g., API keys, connection strings)\r\n# namedValues:\r\n# - name: api-key\r\n# properties:\r\n# value: \"{{ENVIRONMENT}}-api-key-value\"\r\n# - name: connection-string\r\n# properties:\r\n# value: \"{#[DB_Connection_String]#}\"\r\n# - name: secret-from-keyvault\r\n# properties:\r\n# keyVault:\r\n# secretIdentifier: \"https://{{ENVIRONMENT}}-kv.vault.azure.net/secrets/my-secret\"\r\n# identityClientId: \"00000000-0000-0000-0000-000000000000\"\r\n\r\n# Override backend URLs per environment\r\n# backends:\r\n# - name: backend-api\r\n# properties:\r\n# url: \"https://{{ENVIRONMENT}}-api.example.com\"\r\n# - name: legacy-backend\r\n# properties:\r\n# url: \"https://{{ENVIRONMENT}}-legacy.example.com\"\r\n# resourceId: \"/subscriptions/.../sites/{{ENVIRONMENT}}-backend\"\r\n\r\n# Override API service URLs (with optional nested sub-resource overrides)\r\n# apis:\r\n# - name: echo-api\r\n# properties:\r\n# serviceUrl: \"https://{{ENVIRONMENT}}-echo.example.com\"\r\n# - name: petstore-api\r\n# properties:\r\n# serviceUrl: \"https://{{ENVIRONMENT}}-petstore.example.com\"\r\n# displayName: \"Petstore API ({{ENVIRONMENT}})\"\r\n# diagnostics:\r\n# - name: applicationinsights\r\n# properties:\r\n# loggerId: \"appinsights-logger-{{ENVIRONMENT}}\"\r\n# verbosity: Error\r\n# policies:\r\n# - name: policy\r\n# properties:\r\n# format: rawxml\r\n\r\n# Override diagnostic logger references\r\n# diagnostics:\r\n# - name: applicationinsights\r\n# properties:\r\n# loggerId: \"appinsights-logger-{{ENVIRONMENT}}\"\r\n# verbosity: Error\r\n\r\n# Override logger credentials or resource IDs\r\n# loggers:\r\n# - name: appinsights-logger\r\n# properties:\r\n# loggerType: applicationInsights\r\n# resourceId: \"/subscriptions/xxxxx/resourceGroups/{{ENVIRONMENT}}-rg/providers/microsoft.insights/components/{{ENVIRONMENT}}-appinsights\"\r\n# isBuffered: true\r\n# credentials:\r\n# instrumentationKey: \"<APP-INSIGHTS-INSTRUMENTATION-KEY>\"\r\n\r\n# Override service-level policies\r\n# policies:\r\n# - name: policy\r\n# properties:\r\n# format: rawxml\r\n\r\n# Override gateway properties\r\n# gateways:\r\n# - name: on-prem-gateway\r\n# properties:\r\n# locationData:\r\n# name: \"{{ENVIRONMENT}} datacenter\"\r\n\r\n# Override version sets, groups, subscriptions, products, tags, policy fragments\r\n# versionSets:\r\n# - name: my-version-set\r\n# properties:\r\n# displayName: \"My Version Set ({{ENVIRONMENT}})\"\r\n# products:\r\n# - name: starter\r\n# properties:\r\n# displayName: \"Starter Plan ({{ENVIRONMENT}})\"\r\n# tags:\r\n# - name: env-tag\r\n# properties:\r\n# displayName: \"{{ENVIRONMENT}}\"\r\n";
|
|
12
15
|
//# sourceMappingURL=embedded-markdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedded-markdown.d.ts","sourceRoot":"","sources":["../../../src/templates/generated/embedded-markdown.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,eAAO,MAAM,+CAA+C,EAAG,
|
|
1
|
+
{"version":3,"file":"embedded-markdown.d.ts","sourceRoot":"","sources":["../../../src/templates/generated/embedded-markdown.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,eAAO,MAAM,+CAA+C,EAAG,m+RAAk0R,CAAC;AAEl4R,eAAO,MAAM,6CAA6C,EAAG,gptBAA+otB,CAAC;AAE7stB,eAAO,MAAM,oCAAoC,EAAG,o9SAAw4S,CAAC;AAE77S,eAAO,MAAM,uCAAuC,EAAG,6ycAAqqc,CAAC;AAE7tc,eAAO,MAAM,kCAAkC,EAAG,i1MAAmtM,CAAC;AAEtwM,eAAO,MAAM,gCAAgC,EAAG,mvPAAimP,CAAC;AAElpP,eAAO,MAAM,mDAAmD,EAAG,+wBAAwxB,CAAC;AAE51B,eAAO,MAAM,8CAA8C,EAAG,4UAAqV,CAAC;AAEpZ,eAAO,MAAM,oBAAoB,EAAG,ixGAA0xG,CAAC;AAE/zG,eAAO,MAAM,sBAAsB,EAAG,+rGAAwsG,CAAC"}
|