@peterhauge/apiops-cli 0.1.7-alpha.0 → 0.2.1-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/LICENSE.md +22 -22
- package/README.md +169 -169
- package/dist/cli/init-command.d.ts.map +1 -1
- package/dist/cli/init-command.js +2 -1
- package/dist/cli/init-command.js.map +1 -1
- package/dist/clients/apim-client.d.ts +25 -1
- package/dist/clients/apim-client.d.ts.map +1 -1
- package/dist/clients/apim-client.js +173 -9
- package/dist/clients/apim-client.js.map +1 -1
- package/dist/clients/iapim-client.d.ts +6 -0
- package/dist/clients/iapim-client.d.ts.map +1 -1
- package/dist/lib/config-loader.d.ts +0 -4
- package/dist/lib/config-loader.d.ts.map +1 -1
- package/dist/lib/config-loader.js +290 -51
- package/dist/lib/config-loader.js.map +1 -1
- package/dist/lib/resource-path.d.ts.map +1 -1
- package/dist/lib/resource-path.js +20 -2
- package/dist/lib/resource-path.js.map +1 -1
- package/dist/lib/resource-uri.d.ts.map +1 -1
- package/dist/lib/resource-uri.js +24 -4
- package/dist/lib/resource-uri.js.map +1 -1
- package/dist/lib/workspace-link.d.ts +46 -0
- package/dist/lib/workspace-link.d.ts.map +1 -0
- package/dist/lib/workspace-link.js +93 -0
- package/dist/lib/workspace-link.js.map +1 -0
- package/dist/models/config.d.ts +80 -44
- package/dist/models/config.d.ts.map +1 -1
- package/dist/models/resource-types.d.ts +14 -1
- package/dist/models/resource-types.d.ts.map +1 -1
- package/dist/models/resource-types.js +11 -3
- package/dist/models/resource-types.js.map +1 -1
- package/dist/services/api-extractor.d.ts +19 -0
- package/dist/services/api-extractor.d.ts.map +1 -1
- package/dist/services/api-extractor.js +87 -6
- package/dist/services/api-extractor.js.map +1 -1
- package/dist/services/api-publisher.d.ts.map +1 -1
- package/dist/services/api-publisher.js +251 -60
- package/dist/services/api-publisher.js.map +1 -1
- package/dist/services/filter-service.d.ts +1 -0
- package/dist/services/filter-service.d.ts.map +1 -1
- package/dist/services/filter-service.js +101 -40
- package/dist/services/filter-service.js.map +1 -1
- package/dist/services/identity-guide-service.d.ts +1 -1
- package/dist/services/identity-guide-service.d.ts.map +1 -1
- package/dist/services/identity-guide-service.js +37 -518
- 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 +51 -19
- package/dist/services/init-service.js.map +1 -1
- package/dist/services/override-merger.d.ts +3 -7
- package/dist/services/override-merger.d.ts.map +1 -1
- package/dist/services/override-merger.js +198 -47
- package/dist/services/override-merger.js.map +1 -1
- package/dist/services/product-extractor.d.ts +20 -0
- package/dist/services/product-extractor.d.ts.map +1 -1
- package/dist/services/product-extractor.js +101 -5
- package/dist/services/product-extractor.js.map +1 -1
- package/dist/services/product-publisher.d.ts.map +1 -1
- package/dist/services/product-publisher.js +23 -6
- package/dist/services/product-publisher.js.map +1 -1
- package/dist/services/publish-service.d.ts.map +1 -1
- package/dist/services/publish-service.js +55 -7
- package/dist/services/publish-service.js.map +1 -1
- package/dist/services/resource-extractor.d.ts.map +1 -1
- package/dist/services/resource-extractor.js +1 -52
- package/dist/services/resource-extractor.js.map +1 -1
- package/dist/services/resource-publisher.d.ts.map +1 -1
- package/dist/services/resource-publisher.js +179 -2
- package/dist/services/resource-publisher.js.map +1 -1
- package/dist/services/transitive-resolver.d.ts.map +1 -1
- package/dist/services/transitive-resolver.js +4 -4
- package/dist/services/transitive-resolver.js.map +1 -1
- package/dist/services/workspace-extractor.d.ts.map +1 -1
- package/dist/services/workspace-extractor.js +50 -7
- package/dist/services/workspace-extractor.js.map +1 -1
- package/dist/templates/azure-devops/extract-pipeline.d.ts +2 -1
- package/dist/templates/azure-devops/extract-pipeline.d.ts.map +1 -1
- package/dist/templates/azure-devops/extract-pipeline.js +147 -88
- package/dist/templates/azure-devops/extract-pipeline.js.map +1 -1
- package/dist/templates/azure-devops/publish-pipeline.d.ts.map +1 -1
- package/dist/templates/azure-devops/publish-pipeline.js +116 -89
- package/dist/templates/azure-devops/publish-pipeline.js.map +1 -1
- package/dist/templates/configs/filter-config.d.ts +1 -1
- package/dist/templates/configs/filter-config.d.ts.map +1 -1
- package/dist/templates/configs/filter-config.js +109 -44
- 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 +90 -37
- package/dist/templates/configs/override-config.js.map +1 -1
- package/dist/templates/copilot/identity-setup-prompt.d.ts +4 -3
- package/dist/templates/copilot/identity-setup-prompt.d.ts.map +1 -1
- package/dist/templates/copilot/identity-setup-prompt.js +59 -269
- package/dist/templates/copilot/identity-setup-prompt.js.map +1 -1
- package/dist/templates/generated/embedded-markdown.d.ts +12 -0
- package/dist/templates/generated/embedded-markdown.d.ts.map +1 -0
- package/dist/templates/generated/embedded-markdown.js +14 -0
- package/dist/templates/generated/embedded-markdown.js.map +1 -0
- package/dist/templates/github-actions/extract-workflow.js +118 -118
- package/dist/templates/github-actions/publish-workflow.d.ts.map +1 -1
- package/dist/templates/github-actions/publish-workflow.js +104 -90
- package/dist/templates/github-actions/publish-workflow.js.map +1 -1
- package/package.json +69 -66
|
@@ -0,0 +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,2mPAA08O,CAAC;AAE1gP,eAAO,MAAM,6CAA6C,EAAG,gsHAAysH,CAAC;AAEvwH,eAAO,MAAM,oCAAoC,EAAG,yihBAAwihB,CAAC;AAE7lhB,eAAO,MAAM,kCAAkC,EAAG,65FAAu5F,CAAC;AAE18F,eAAO,MAAM,gCAAgC,EAAG,wrLAAisL,CAAC;AAElvL,eAAO,MAAM,mDAAmD,EAAG,+wBAAwxB,CAAC;AAE51B,eAAO,MAAM,8CAA8C,EAAG,4UAAqV,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
/**
|
|
4
|
+
* AUTO-GENERATED FILE.
|
|
5
|
+
* Generated by scripts/embed-markdown-templates.mjs
|
|
6
|
+
*/
|
|
7
|
+
export 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 — 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🔐 Tool Authentication Status:\n\n| Tool | Status | Account/User | Subscription/Org | Tenant/Details |\n|------|--------|--------------|------------------|----------------|\n| Azure CLI | ✅ Logged in | user@example.com | my-subscription | abc-123-... |\n| GitHub CLI | ✅ Logged in | username | github.com | — |\n```\n\n**Status indicators:**\n- ✅ Logged in — tool is authenticated and ready\n- ❌ Not logged in — tool needs authentication\n- ⚠️ Not installed — 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 — 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 — Create Azure AD Application & Service Principal\n\n> ⚠️ **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 — 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 — Create Federated Credentials for GitHub OIDC\n\n> ⚠️ **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 — Create GitHub Environments\n\n```bash\n{{ENVIRONMENT_CREATION_COMMANDS}}\n```\n\n---\n\n## Step 6 — Set GitHub Repository Secrets\n\n> ⚠️ **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 — Verify\n\n> ⚠️ **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** → **Run APIM Extractor** → **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 → Secrets and variables → 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` — App registration client ID (shared across all environments)\n- `AZURE_TENANT_ID` — Azure AD tenant ID (shared across all environments)\n\n### Per-Environment Secrets\n{{ENV_SECRETS_REFERENCE}}\n";
|
|
8
|
+
export 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```";
|
|
9
|
+
export 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> ⚠️ **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";
|
|
10
|
+
export 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 → Secrets and variables → 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 — 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";
|
|
11
|
+
export const azureDevOpsIdentityGuideTemplate = "# Azure DevOps Identity Setup Guide\n\n{{AZURE_DEVOPS_CORE_STEPS}}\n\n## Step 10: Enable Pipeline Contributions\n\nGrant the Build Service permission to contribute to the repository. This allows pipelines to push commits (e.g., extracted API artifacts).\n\nFirst, get the project and repository IDs:\n\n**PowerShell:**\n```powershell\n$PROJECT_ID = az devops project show --project $AZDO_PROJECT --query id -o tsv\n$REPO_NAME = $AZDO_PROJECT # Change if your repo name differs from project name\n$REPO_ID = az repos show --repository $REPO_NAME --query id -o tsv\n```\n\n**Git Bash:**\n```bash\nPROJECT_ID=$(az devops project show --project \"$AZDO_PROJECT\" --query id -o tsv)\nREPO_NAME=\"$AZDO_PROJECT\" # Change if your repo name differs from project name\nREPO_ID=$(az repos show --repository \"$REPO_NAME\" --query id -o tsv)\n```\n\nNext, find the Build Service identity descriptor:\n\n**PowerShell:**\n```powershell\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\n**Git Bash:**\n```bash\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```\n\nFinally, grant the Contribute permission (bit 4) on the repository:\n\n**PowerShell:**\n```powershell\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\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\nVerify the permission was set:\n\n**PowerShell:**\n```powershell\naz devops security permission show --namespace-id $GIT_REPOS_NAMESPACE --subject $BUILD_SERVICE_DESCRIPTOR --token $TOKEN --query \"[].acesDictionary.*.resolvedPermissions\" -o json\n```\n\n**Git Bash:**\n```bash\naz devops security permission show --namespace-id \"$GIT_REPOS_NAMESPACE\" --subject \"$BUILD_SERVICE_DESCRIPTOR\" --token \"$TOKEN\" --query \"[].acesDictionary.*.resolvedPermissions\" -o json\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\n**Environments:**\n\n**PowerShell:**\n```powershell\n(az devops invoke --area environments --resource environments --route-parameters project=$AZDO_PROJECT --http-method GET --api-version 7.1 -o json | ConvertFrom-Json).value | Select-Object name\n```\n\n**Git Bash:**\n```bash\naz devops invoke --area environments --resource environments --route-parameters project=\"$AZDO_PROJECT\" --http-method GET --api-version 7.1 -o json | grep -o '\"name\": *\"[^\"]*\"' | cut -d'\"' -f4\n```\n\n**Service Principal Role Assignment:**\n\n**PowerShell:**\n```powershell\naz role assignment list --assignee $APP_ID --query \"[].{Role:roleDefinitionName, Scope:scope}\" -o table\n```\n\n**Git Bash:**\n```bash\naz role assignment list --assignee \"$APP_ID\" --query \"[].{Role:roleDefinitionName, Scope:scope}\" -o table\n```\n\n**Final Test:** Run the extract pipeline manually to verify end-to-end authentication and permissions.\n\n---\n\n## Step 12: Create Pipelines\n\nCreate Azure Pipelines from the YAML files in your repository.\n\n**Prerequisites:** Ensure your pipeline YAML files are committed to the repository (e.g., `.azdo/pipelines/run-apim-extractor.yml`, `.azdo/pipelines/run-apim-publisher.yml`).\n\n**Create Extract Pipeline:**\n\n**PowerShell:**\n```powershell\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\n```\n\n**Git Bash:**\n```bash\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\n```\n\n**Create Publish Pipeline:**\n\n**PowerShell:**\n```powershell\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\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**Verify pipelines were created:**\n```bash\naz pipelines list --query \"[].name\" -o table\n```\n\n**Run the extract pipeline:**\n\n**PowerShell:**\n```powershell\naz pipelines run --name \"apiops-extract\"\n```\n\n**Git Bash:**\n```bash\naz pipelines run --name \"apiops-extract\"\n```\n\n---\n\n## Security Notes\n- Enable environment approvals for production deployments\n- Prefer workload identity federation (OIDC) over client secrets\n- Review RBAC assignments regularly\n";
|
|
12
|
+
export 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";
|
|
13
|
+
export 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";
|
|
14
|
+
//# sourceMappingURL=embedded-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-markdown.js","sourceRoot":"","sources":["../../../src/templates/generated/embedded-markdown.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC;;;GAGG;AAEH,MAAM,CAAC,MAAM,+CAA+C,GAAG,i8OAA08O,CAAC;AAE1gP,MAAM,CAAC,MAAM,6CAA6C,GAAG,gsHAAysH,CAAC;AAEvwH,MAAM,CAAC,MAAM,oCAAoC,GAAG,+hhBAAwihB,CAAC;AAE7lhB,MAAM,CAAC,MAAM,kCAAkC,GAAG,84FAAu5F,CAAC;AAE18F,MAAM,CAAC,MAAM,gCAAgC,GAAG,wrLAAisL,CAAC;AAElvL,MAAM,CAAC,MAAM,mDAAmD,GAAG,+wBAAwxB,CAAC;AAE51B,MAAM,CAAC,MAAM,8CAA8C,GAAG,4UAAqV,CAAC"}
|
|
@@ -5,124 +5,124 @@
|
|
|
5
5
|
* Generates extract workflow with manual trigger, configuration choice, and auto-PR creation
|
|
6
6
|
*/
|
|
7
7
|
export function generateExtractWorkflow(config) {
|
|
8
|
-
return `name: Run APIM Extractor
|
|
9
|
-
|
|
10
|
-
on:
|
|
11
|
-
workflow_dispatch:
|
|
12
|
-
inputs:
|
|
13
|
-
ENVIRONMENT:
|
|
14
|
-
description: 'Choose which environment to extract from'
|
|
15
|
-
required: true
|
|
16
|
-
type: choice
|
|
17
|
-
default: dev
|
|
18
|
-
options:
|
|
19
|
-
- dev
|
|
20
|
-
- prod
|
|
21
|
-
CONFIGURATION_YAML_PATH:
|
|
22
|
-
description: 'Choose whether to extract all APIs or use the extraction configuration file'
|
|
23
|
-
required: true
|
|
24
|
-
type: choice
|
|
25
|
-
options:
|
|
26
|
-
- Extract All APIs
|
|
27
|
-
- configuration.
|
|
28
|
-
|
|
29
|
-
permissions:
|
|
30
|
-
id-token: write
|
|
31
|
-
contents: write
|
|
32
|
-
pull-requests: write
|
|
33
|
-
|
|
34
|
-
jobs:
|
|
35
|
-
extract:
|
|
36
|
-
runs-on: ubuntu-latest
|
|
37
|
-
environment: \${{ github.event.inputs.ENVIRONMENT }}
|
|
38
|
-
env:
|
|
39
|
-
APIM_RESOURCE_GROUP: \${{ (github.event.inputs.ENVIRONMENT == 'dev' && secrets.APIM_RESOURCE_GROUP_DEV) || (github.event.inputs.ENVIRONMENT == 'prod' && secrets.APIM_RESOURCE_GROUP_PROD) }}
|
|
40
|
-
APIM_SERVICE_NAME: \${{ (github.event.inputs.ENVIRONMENT == 'dev' && secrets.APIM_SERVICE_NAME_DEV) || (github.event.inputs.ENVIRONMENT == 'prod' && secrets.APIM_SERVICE_NAME_PROD) }}
|
|
41
|
-
steps:
|
|
42
|
-
- name: Validate required secrets
|
|
43
|
-
run: |
|
|
44
|
-
if [ -z "\${{ env.APIM_RESOURCE_GROUP }}" ]; then
|
|
45
|
-
echo "::error::APIM_RESOURCE_GROUP secret is not set for environment '\${{ github.event.inputs.ENVIRONMENT }}'"
|
|
46
|
-
echo "Please configure APIM_RESOURCE_GROUP_\${{ github.event.inputs.ENVIRONMENT == 'dev' && 'DEV' || 'PROD' }} secret in the \${{ github.event.inputs.ENVIRONMENT }} environment"
|
|
47
|
-
exit 1
|
|
48
|
-
fi
|
|
49
|
-
if [ -z "\${{ env.APIM_SERVICE_NAME }}" ]; then
|
|
50
|
-
echo "::error::APIM_SERVICE_NAME secret is not set for environment '\${{ github.event.inputs.ENVIRONMENT }}'"
|
|
51
|
-
echo "Please configure APIM_SERVICE_NAME_\${{ github.event.inputs.ENVIRONMENT == 'dev' && 'DEV' || 'PROD' }} secret in the \${{ github.event.inputs.ENVIRONMENT }} environment"
|
|
52
|
-
exit 1
|
|
53
|
-
fi
|
|
54
|
-
echo "✓ All required secrets are configured"
|
|
55
|
-
echo " Environment: \${{ github.event.inputs.ENVIRONMENT }}"
|
|
56
|
-
echo " Resource Group: \${{ env.APIM_RESOURCE_GROUP }}"
|
|
57
|
-
echo " Service Name: \${{ env.APIM_SERVICE_NAME }}"
|
|
58
|
-
|
|
59
|
-
- name: Checkout repository
|
|
60
|
-
uses: actions/checkout@v4
|
|
61
|
-
|
|
62
|
-
- name: Setup Node.js
|
|
63
|
-
uses: actions/setup-node@v4
|
|
64
|
-
with:
|
|
65
|
-
node-version: '22'
|
|
66
|
-
|
|
67
|
-
- name: Install dependencies
|
|
68
|
-
run: npm install
|
|
69
|
-
|
|
70
|
-
- name: Azure Login (Federated Credential)
|
|
71
|
-
uses: azure/login@v2
|
|
72
|
-
with:
|
|
73
|
-
client-id: \${{ secrets.AZURE_CLIENT_ID }}
|
|
74
|
-
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
|
|
75
|
-
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
76
|
-
|
|
77
|
-
- name: Run APIM Extract (All APIs)
|
|
78
|
-
if: \${{ github.event.inputs.CONFIGURATION_YAML_PATH == 'Extract All APIs' }}
|
|
79
|
-
run: |
|
|
80
|
-
npx apiops extract \\
|
|
81
|
-
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
82
|
-
--resource-group \${{ env.APIM_RESOURCE_GROUP }} \\
|
|
83
|
-
--service-name \${{ env.APIM_SERVICE_NAME }} \\
|
|
84
|
-
--output ${config.artifactDir}
|
|
85
|
-
|
|
86
|
-
- name: Run APIM Extract (With Configuration)
|
|
87
|
-
if: \${{ github.event.inputs.CONFIGURATION_YAML_PATH != 'Extract All APIs' }}
|
|
88
|
-
run: |
|
|
89
|
-
npx apiops extract \\
|
|
90
|
-
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
91
|
-
--resource-group \${{ env.APIM_RESOURCE_GROUP }} \\
|
|
92
|
-
--service-name \${{ env.APIM_SERVICE_NAME }} \\
|
|
93
|
-
--output ${config.artifactDir} \\
|
|
94
|
-
--filter configuration.
|
|
95
|
-
|
|
96
|
-
- name: Upload artifacts
|
|
97
|
-
uses: actions/upload-artifact@v4
|
|
98
|
-
with:
|
|
99
|
-
name: apim-artifacts
|
|
100
|
-
path: ${config.artifactDir}
|
|
101
|
-
retention-days: 30
|
|
102
|
-
|
|
103
|
-
create-pull-request:
|
|
104
|
-
needs: extract
|
|
105
|
-
runs-on: ubuntu-latest
|
|
106
|
-
steps:
|
|
107
|
-
- name: Checkout repository
|
|
108
|
-
uses: actions/checkout@v4
|
|
109
|
-
|
|
110
|
-
- name: Download artifacts
|
|
111
|
-
uses: actions/download-artifact@v4
|
|
112
|
-
with:
|
|
113
|
-
name: apim-artifacts
|
|
114
|
-
path: ${config.artifactDir}
|
|
115
|
-
|
|
116
|
-
- name: Create pull request
|
|
117
|
-
uses: peter-evans/create-pull-request@v6
|
|
118
|
-
with:
|
|
119
|
-
token: \${{ secrets.GITHUB_TOKEN }}
|
|
120
|
-
commit-message: "chore: update APIM artifacts from extract"
|
|
121
|
-
title: "APIM Extract - Update artifacts"
|
|
122
|
-
body: >
|
|
123
|
-
This PR is auto-generated by the APIM extract workflow.
|
|
124
|
-
labels: extract, automated pr
|
|
125
|
-
branch: apim-extract-\${{ github.run_id }}
|
|
8
|
+
return `name: Run APIM Extractor
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
ENVIRONMENT:
|
|
14
|
+
description: 'Choose which environment to extract from'
|
|
15
|
+
required: true
|
|
16
|
+
type: choice
|
|
17
|
+
default: dev
|
|
18
|
+
options:
|
|
19
|
+
- dev
|
|
20
|
+
- prod
|
|
21
|
+
CONFIGURATION_YAML_PATH:
|
|
22
|
+
description: 'Choose whether to extract all APIs or use the extraction configuration file'
|
|
23
|
+
required: true
|
|
24
|
+
type: choice
|
|
25
|
+
options:
|
|
26
|
+
- Extract All APIs
|
|
27
|
+
- configuration.extractor.yaml
|
|
28
|
+
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write
|
|
31
|
+
contents: write
|
|
32
|
+
pull-requests: write
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
extract:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment: \${{ github.event.inputs.ENVIRONMENT }}
|
|
38
|
+
env:
|
|
39
|
+
APIM_RESOURCE_GROUP: \${{ (github.event.inputs.ENVIRONMENT == 'dev' && secrets.APIM_RESOURCE_GROUP_DEV) || (github.event.inputs.ENVIRONMENT == 'prod' && secrets.APIM_RESOURCE_GROUP_PROD) }}
|
|
40
|
+
APIM_SERVICE_NAME: \${{ (github.event.inputs.ENVIRONMENT == 'dev' && secrets.APIM_SERVICE_NAME_DEV) || (github.event.inputs.ENVIRONMENT == 'prod' && secrets.APIM_SERVICE_NAME_PROD) }}
|
|
41
|
+
steps:
|
|
42
|
+
- name: Validate required secrets
|
|
43
|
+
run: |
|
|
44
|
+
if [ -z "\${{ env.APIM_RESOURCE_GROUP }}" ]; then
|
|
45
|
+
echo "::error::APIM_RESOURCE_GROUP secret is not set for environment '\${{ github.event.inputs.ENVIRONMENT }}'"
|
|
46
|
+
echo "Please configure APIM_RESOURCE_GROUP_\${{ github.event.inputs.ENVIRONMENT == 'dev' && 'DEV' || 'PROD' }} secret in the \${{ github.event.inputs.ENVIRONMENT }} environment"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
if [ -z "\${{ env.APIM_SERVICE_NAME }}" ]; then
|
|
50
|
+
echo "::error::APIM_SERVICE_NAME secret is not set for environment '\${{ github.event.inputs.ENVIRONMENT }}'"
|
|
51
|
+
echo "Please configure APIM_SERVICE_NAME_\${{ github.event.inputs.ENVIRONMENT == 'dev' && 'DEV' || 'PROD' }} secret in the \${{ github.event.inputs.ENVIRONMENT }} environment"
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
echo "✓ All required secrets are configured"
|
|
55
|
+
echo " Environment: \${{ github.event.inputs.ENVIRONMENT }}"
|
|
56
|
+
echo " Resource Group: \${{ env.APIM_RESOURCE_GROUP }}"
|
|
57
|
+
echo " Service Name: \${{ env.APIM_SERVICE_NAME }}"
|
|
58
|
+
|
|
59
|
+
- name: Checkout repository
|
|
60
|
+
uses: actions/checkout@v4
|
|
61
|
+
|
|
62
|
+
- name: Setup Node.js
|
|
63
|
+
uses: actions/setup-node@v4
|
|
64
|
+
with:
|
|
65
|
+
node-version: '22'
|
|
66
|
+
|
|
67
|
+
- name: Install dependencies
|
|
68
|
+
run: npm install
|
|
69
|
+
|
|
70
|
+
- name: Azure Login (Federated Credential)
|
|
71
|
+
uses: azure/login@v2
|
|
72
|
+
with:
|
|
73
|
+
client-id: \${{ secrets.AZURE_CLIENT_ID }}
|
|
74
|
+
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
|
|
75
|
+
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
76
|
+
|
|
77
|
+
- name: Run APIM Extract (All APIs)
|
|
78
|
+
if: \${{ github.event.inputs.CONFIGURATION_YAML_PATH == 'Extract All APIs' }}
|
|
79
|
+
run: |
|
|
80
|
+
npx apiops extract \\
|
|
81
|
+
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
82
|
+
--resource-group \${{ env.APIM_RESOURCE_GROUP }} \\
|
|
83
|
+
--service-name \${{ env.APIM_SERVICE_NAME }} \\
|
|
84
|
+
--output ${config.artifactDir}
|
|
85
|
+
|
|
86
|
+
- name: Run APIM Extract (With Configuration)
|
|
87
|
+
if: \${{ github.event.inputs.CONFIGURATION_YAML_PATH != 'Extract All APIs' }}
|
|
88
|
+
run: |
|
|
89
|
+
npx apiops extract \\
|
|
90
|
+
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
91
|
+
--resource-group \${{ env.APIM_RESOURCE_GROUP }} \\
|
|
92
|
+
--service-name \${{ env.APIM_SERVICE_NAME }} \\
|
|
93
|
+
--output ${config.artifactDir} \\
|
|
94
|
+
--filter configuration.extractor.yaml
|
|
95
|
+
|
|
96
|
+
- name: Upload artifacts
|
|
97
|
+
uses: actions/upload-artifact@v4
|
|
98
|
+
with:
|
|
99
|
+
name: apim-artifacts
|
|
100
|
+
path: ${config.artifactDir}
|
|
101
|
+
retention-days: 30
|
|
102
|
+
|
|
103
|
+
create-pull-request:
|
|
104
|
+
needs: extract
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- name: Checkout repository
|
|
108
|
+
uses: actions/checkout@v4
|
|
109
|
+
|
|
110
|
+
- name: Download artifacts
|
|
111
|
+
uses: actions/download-artifact@v4
|
|
112
|
+
with:
|
|
113
|
+
name: apim-artifacts
|
|
114
|
+
path: ${config.artifactDir}
|
|
115
|
+
|
|
116
|
+
- name: Create pull request
|
|
117
|
+
uses: peter-evans/create-pull-request@v6
|
|
118
|
+
with:
|
|
119
|
+
token: \${{ secrets.GITHUB_TOKEN }}
|
|
120
|
+
commit-message: "chore: update APIM artifacts from extract"
|
|
121
|
+
title: "APIM Extract - Update artifacts"
|
|
122
|
+
body: >
|
|
123
|
+
This PR is auto-generated by the APIM extract workflow.
|
|
124
|
+
labels: extract, automated pr
|
|
125
|
+
branch: apim-extract-\${{ github.run_id }}
|
|
126
126
|
`;
|
|
127
127
|
}
|
|
128
128
|
//# sourceMappingURL=extract-workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../../src/templates/github-actions/publish-workflow.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../../src/templates/github-actions/publish-workflow.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAoH7E"}
|
|
@@ -7,101 +7,115 @@
|
|
|
7
7
|
export function generatePublishWorkflow(config) {
|
|
8
8
|
const envChoices = config.environments.map((env) => ` - ${env}`).join('\n');
|
|
9
9
|
const envJobs = config.environments.map((env, idx) => {
|
|
10
|
+
const envUpper = env.toUpperCase();
|
|
10
11
|
const autoDeployComment = idx === 0
|
|
11
|
-
? ` # To enable automatic deployment on push to main, uncomment the condition below:
|
|
12
|
+
? ` # To enable automatic deployment on push to main, uncomment the condition below:
|
|
12
13
|
# if: github.event.inputs.ENVIRONMENT == '${env}' || github.event_name == 'push'`
|
|
13
|
-
: ` # To enable automatic deployment on push to main, uncomment the condition below:
|
|
14
|
-
# if: github.event.inputs.ENVIRONMENT == '${env}' || github.event_name == 'push'
|
|
14
|
+
: ` # To enable automatic deployment on push to main, uncomment the condition below:
|
|
15
|
+
# if: github.event.inputs.ENVIRONMENT == '${env}' || github.event_name == 'push'
|
|
15
16
|
# And change needs to: needs: [get-commit, publish-${config.environments[idx - 1]}]`;
|
|
16
|
-
return ` publish-${env}:
|
|
17
|
-
${autoDeployComment}
|
|
18
|
-
if: github.event.inputs.ENVIRONMENT == '${env}'
|
|
19
|
-
runs-on: ubuntu-latest
|
|
20
|
-
environment: ${env}
|
|
21
|
-
needs: get-commit
|
|
22
|
-
steps:
|
|
23
|
-
- name: Checkout repository
|
|
24
|
-
uses: actions/checkout@v4
|
|
25
|
-
with:
|
|
26
|
-
fetch-depth: 2
|
|
27
|
-
|
|
28
|
-
- name: Setup Node.js
|
|
29
|
-
uses: actions/setup-node@v4
|
|
30
|
-
with:
|
|
31
|
-
node-version: '22'
|
|
32
|
-
|
|
33
|
-
- name: Install dependencies
|
|
34
|
-
run: npm install
|
|
35
|
-
|
|
36
|
-
- name: Azure Login (Federated Credential)
|
|
37
|
-
uses: azure/login@v2
|
|
38
|
-
with:
|
|
39
|
-
client-id: \${{ secrets.AZURE_CLIENT_ID }}
|
|
40
|
-
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
|
|
41
|
-
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
42
|
-
|
|
43
|
-
- name:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
--
|
|
59
|
-
--
|
|
60
|
-
--
|
|
17
|
+
return ` publish-${env}:
|
|
18
|
+
${autoDeployComment}
|
|
19
|
+
if: github.event.inputs.ENVIRONMENT == '${env}'
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
environment: ${env}
|
|
22
|
+
needs: get-commit
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout repository
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 2
|
|
28
|
+
|
|
29
|
+
- name: Setup Node.js
|
|
30
|
+
uses: actions/setup-node@v4
|
|
31
|
+
with:
|
|
32
|
+
node-version: '22'
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: npm install
|
|
36
|
+
|
|
37
|
+
- name: Azure Login (Federated Credential)
|
|
38
|
+
uses: azure/login@v2
|
|
39
|
+
with:
|
|
40
|
+
client-id: \${{ secrets.AZURE_CLIENT_ID }}
|
|
41
|
+
tenant-id: \${{ secrets.AZURE_TENANT_ID }}
|
|
42
|
+
subscription-id: \${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
43
|
+
|
|
44
|
+
- name: Substitute tokens in configuration.${env}.yaml
|
|
45
|
+
uses: cschleiden/replace-tokens@v1.3
|
|
46
|
+
with:
|
|
47
|
+
tokenPrefix: '{#['
|
|
48
|
+
tokenSuffix: ']#}'
|
|
49
|
+
files: '["configuration.${env}.yaml"]'
|
|
50
|
+
# Example token mapping for ${env} (uncomment and customize when needed):
|
|
51
|
+
# env:
|
|
52
|
+
# MY_SECRET: \${{ secrets.MY_SECRET_${envUpper} }}
|
|
53
|
+
# ANOTHER_TOKEN: \${{ secrets.ANOTHER_TOKEN_${envUpper} }}
|
|
54
|
+
|
|
55
|
+
- name: Publish to ${env} (incremental - last commit only)
|
|
56
|
+
if: \${{ github.event.inputs.COMMIT_ID_CHOICE != 'publish-all-artifacts-in-repo' }}
|
|
57
|
+
run: |
|
|
58
|
+
npx apiops publish \\
|
|
59
|
+
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
60
|
+
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
|
|
61
|
+
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
|
|
62
|
+
--source ${config.artifactDir} \\
|
|
63
|
+
--overrides configuration.${env}.yaml \\
|
|
64
|
+
--commit-id \${{ needs.get-commit.outputs.commit_id }}
|
|
65
|
+
|
|
66
|
+
- name: Publish to ${env} (all artifacts)
|
|
67
|
+
if: \${{ github.event.inputs.COMMIT_ID_CHOICE == 'publish-all-artifacts-in-repo' }}
|
|
68
|
+
run: |
|
|
69
|
+
npx apiops publish \\
|
|
70
|
+
--subscription-id \${{ secrets.AZURE_SUBSCRIPTION_ID }} \\
|
|
71
|
+
--resource-group \${{ secrets.APIM_RESOURCE_GROUP_${envUpper} }} \\
|
|
72
|
+
--service-name \${{ secrets.APIM_SERVICE_NAME_${envUpper} }} \\
|
|
73
|
+
--source ${config.artifactDir} \\
|
|
74
|
+
--overrides configuration.${env}.yaml
|
|
61
75
|
`;
|
|
62
76
|
}).join('\n');
|
|
63
|
-
return `name: Run APIM Publisher
|
|
64
|
-
|
|
65
|
-
on:
|
|
66
|
-
push:
|
|
67
|
-
branches:
|
|
68
|
-
- main
|
|
69
|
-
paths:
|
|
70
|
-
- '${config.artifactDir}/**'
|
|
71
|
-
- 'configuration.*.yaml'
|
|
72
|
-
workflow_dispatch:
|
|
73
|
-
inputs:
|
|
74
|
-
COMMIT_ID_CHOICE:
|
|
75
|
-
description: 'Choose "publish-all-artifacts-in-repo" only when you want to force republishing all artifacts (e.g. after build failure). Otherwise stick with the default behavior of "publish-artifacts-in-last-commit"'
|
|
76
|
-
required: true
|
|
77
|
-
type: choice
|
|
78
|
-
default: publish-artifacts-in-last-commit
|
|
79
|
-
options:
|
|
80
|
-
- publish-artifacts-in-last-commit
|
|
81
|
-
- publish-all-artifacts-in-repo
|
|
82
|
-
ENVIRONMENT:
|
|
83
|
-
description: 'Choose which environment to publish to'
|
|
84
|
-
required: true
|
|
85
|
-
type: choice
|
|
86
|
-
default: ${config.environments[0]}
|
|
87
|
-
options:
|
|
88
|
-
${envChoices}
|
|
89
|
-
|
|
90
|
-
permissions:
|
|
91
|
-
id-token: write
|
|
92
|
-
contents: read
|
|
93
|
-
|
|
94
|
-
jobs:
|
|
95
|
-
get-commit:
|
|
96
|
-
runs-on: ubuntu-latest
|
|
97
|
-
outputs:
|
|
98
|
-
commit_id: \${{ steps.commit.outputs.commit_id }}
|
|
99
|
-
steps:
|
|
100
|
-
- name: Set the Commit Id
|
|
101
|
-
id: commit
|
|
102
|
-
run: echo "commit_id=\${GITHUB_SHA}" >> $GITHUB_OUTPUT
|
|
103
|
-
|
|
104
|
-
${envJobs}
|
|
77
|
+
return `name: Run APIM Publisher
|
|
78
|
+
|
|
79
|
+
on:
|
|
80
|
+
push:
|
|
81
|
+
branches:
|
|
82
|
+
- main
|
|
83
|
+
paths:
|
|
84
|
+
- '${config.artifactDir}/**'
|
|
85
|
+
- 'configuration.*.yaml'
|
|
86
|
+
workflow_dispatch:
|
|
87
|
+
inputs:
|
|
88
|
+
COMMIT_ID_CHOICE:
|
|
89
|
+
description: 'Choose "publish-all-artifacts-in-repo" only when you want to force republishing all artifacts (e.g. after build failure). Otherwise stick with the default behavior of "publish-artifacts-in-last-commit"'
|
|
90
|
+
required: true
|
|
91
|
+
type: choice
|
|
92
|
+
default: publish-artifacts-in-last-commit
|
|
93
|
+
options:
|
|
94
|
+
- publish-artifacts-in-last-commit
|
|
95
|
+
- publish-all-artifacts-in-repo
|
|
96
|
+
ENVIRONMENT:
|
|
97
|
+
description: 'Choose which environment to publish to'
|
|
98
|
+
required: true
|
|
99
|
+
type: choice
|
|
100
|
+
default: ${config.environments[0]}
|
|
101
|
+
options:
|
|
102
|
+
${envChoices}
|
|
103
|
+
|
|
104
|
+
permissions:
|
|
105
|
+
id-token: write
|
|
106
|
+
contents: read
|
|
107
|
+
|
|
108
|
+
jobs:
|
|
109
|
+
get-commit:
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
outputs:
|
|
112
|
+
commit_id: \${{ steps.commit.outputs.commit_id }}
|
|
113
|
+
steps:
|
|
114
|
+
- name: Set the Commit Id
|
|
115
|
+
id: commit
|
|
116
|
+
run: echo "commit_id=\${GITHUB_SHA}" >> $GITHUB_OUTPUT
|
|
117
|
+
|
|
118
|
+
${envJobs}
|
|
105
119
|
`;
|
|
106
120
|
}
|
|
107
121
|
//# sourceMappingURL=publish-workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-workflow.js","sourceRoot":"","sources":["../../../src/templates/github-actions/publish-workflow.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC;;;GAGG;AAOH,MAAM,UAAU,uBAAuB,CAAC,MAA6B;IACnE,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErF,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACnD,MAAM,iBAAiB,GAAG,GAAG,KAAK,CAAC;YACjC,CAAC,CAAC;gDACwC,GAAG,kCAAkC;YAC/E,CAAC,CAAC;gDACwC,GAAG;yDACM,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QAErF,OAAO,aAAa,GAAG;EACzB,iBAAiB;8CAC2B,GAAG;;mBAE9B,GAAG;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"publish-workflow.js","sourceRoot":"","sources":["../../../src/templates/github-actions/publish-workflow.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAClC;;;GAGG;AAOH,MAAM,UAAU,uBAAuB,CAAC,MAA6B;IACnE,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErF,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,iBAAiB,GAAG,GAAG,KAAK,CAAC;YACjC,CAAC,CAAC;gDACwC,GAAG,kCAAkC;YAC/E,CAAC,CAAC;gDACwC,GAAG;yDACM,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QAErF,OAAO,aAAa,GAAG;EACzB,iBAAiB;8CAC2B,GAAG;;mBAE9B,GAAG;;;;;;;;;;;;;;;;;;;;;;;mDAuB6B,GAAG;;;;;oCAKlB,GAAG;wCACC,GAAG;;kDAEO,QAAQ;0DACA,QAAQ;;2BAEvC,GAAG;;;;;gEAKkC,QAAQ;4DACZ,QAAQ;uBAC7C,MAAM,CAAC,WAAW;wCACD,GAAG;;;2BAGhB,GAAG;;;;;gEAKkC,QAAQ;4DACZ,QAAQ;uBAC7C,MAAM,CAAC,WAAW;wCACD,GAAG;CAC1C,CAAC;IACA,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;;;WAOE,MAAM,CAAC,WAAW;;;;;;;;;;;;;;;;mBAgBV,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;;EAEvC,UAAU;;;;;;;;;;;;;;;;EAgBV,OAAO;CACR,CAAC;AACF,CAAC"}
|