From 45fa40c62b4dcf5a78c0eb477eee63862f947ab2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:02:11 +0000 Subject: [PATCH 1/7] Add ci-cd-api-validation sample with Dev Proxy configurations Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../.devproxy/api-specs/api.contoso.com.json | 272 ++++++++++++++++++ .../.github/workflows/api-validation.yml | 139 +++++++++ samples/ci-cd-api-validation/README.md | 167 +++++++++++ samples/ci-cd-api-validation/assets/README.md | 21 ++ .../ci-cd-api-validation/assets/sample.json | 87 ++++++ .../ci-cd-api-validation/azure-pipelines.yml | 149 ++++++++++ samples/ci-cd-api-validation/devproxyrc.json | 53 ++++ .../openapi-generation.json | 15 + .../permission-validation.json | 29 ++ samples/ci-cd-api-validation/run.sh | 93 ++++++ .../shadow-api-detection.json | 33 +++ 11 files changed, 1058 insertions(+) create mode 100644 samples/ci-cd-api-validation/.devproxy/api-specs/api.contoso.com.json create mode 100644 samples/ci-cd-api-validation/.github/workflows/api-validation.yml create mode 100644 samples/ci-cd-api-validation/README.md create mode 100644 samples/ci-cd-api-validation/assets/README.md create mode 100644 samples/ci-cd-api-validation/assets/sample.json create mode 100644 samples/ci-cd-api-validation/azure-pipelines.yml create mode 100644 samples/ci-cd-api-validation/devproxyrc.json create mode 100644 samples/ci-cd-api-validation/openapi-generation.json create mode 100644 samples/ci-cd-api-validation/permission-validation.json create mode 100644 samples/ci-cd-api-validation/run.sh create mode 100644 samples/ci-cd-api-validation/shadow-api-detection.json diff --git a/samples/ci-cd-api-validation/.devproxy/api-specs/api.contoso.com.json b/samples/ci-cd-api-validation/.devproxy/api-specs/api.contoso.com.json new file mode 100644 index 0000000..e7d152a --- /dev/null +++ b/samples/ci-cd-api-validation/.devproxy/api-specs/api.contoso.com.json @@ -0,0 +1,272 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Contoso API", + "description": "Sample Contoso API for demonstrating permission validation in CI/CD pipelines", + "version": "v1.0" + }, + "servers": [ + { + "url": "https://api.contoso.com" + } + ], + "components": { + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "tokenUrl": "https://login.microsoftonline.com/common/oauth2/token", + "scopes": { + "customer.read": "Grants access to read customer info", + "customer.readwrite": "Grants access to read and write customer info", + "order.read": "Grants access to read order info", + "order.readwrite": "Grants access to read and write order info" + } + } + } + } + }, + "schemas": { + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + }, + "Order": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "customerId": { + "type": "string" + }, + "total": { + "type": "number" + }, + "status": { + "type": "string" + } + } + } + } + }, + "paths": { + "/customers": { + "get": { + "summary": "Get all customers", + "operationId": "getCustomers", + "security": [ + { + "OAuth2": [ + "customer.read" + ] + }, + { + "OAuth2": [ + "customer.readwrite" + ] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Customer" + } + } + } + } + } + } + }, + "post": { + "summary": "Create a customer", + "operationId": "createCustomer", + "security": [ + { + "OAuth2": [ + "customer.readwrite" + ] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Customer" + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Customer" + } + } + } + } + } + } + }, + "/customers/{customer-id}": { + "get": { + "summary": "Get customer by ID", + "operationId": "getCustomerById", + "security": [ + { + "OAuth2": [ + "customer.read" + ] + }, + { + "OAuth2": [ + "customer.readwrite" + ] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Customer" + } + } + } + } + } + }, + "patch": { + "summary": "Update customer by ID", + "operationId": "updateCustomerById", + "security": [ + { + "OAuth2": [ + "customer.readwrite" + ] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Customer" + } + } + } + }, + "responses": { + "204": { + "description": "No Content" + } + } + }, + "parameters": [ + { + "name": "customer-id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ] + }, + "/orders": { + "get": { + "summary": "Get all orders", + "operationId": "getOrders", + "security": [ + { + "OAuth2": [ + "order.read" + ] + }, + { + "OAuth2": [ + "order.readwrite" + ] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Order" + } + } + } + } + } + } + } + }, + "/orders/{order-id}": { + "get": { + "summary": "Get order by ID", + "operationId": "getOrderById", + "security": [ + { + "OAuth2": [ + "order.read" + ] + }, + { + "OAuth2": [ + "order.readwrite" + ] + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + } + } + }, + "parameters": [ + { + "name": "order-id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ] + } + } +} diff --git a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml new file mode 100644 index 0000000..614904b --- /dev/null +++ b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml @@ -0,0 +1,139 @@ +name: API validation + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + shadow-api-detection: + name: Shadow API detection + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Dev Proxy + uses: dev-proxy-tools/actions/setup@v1 + + - name: Start Dev Proxy + uses: dev-proxy-tools/actions/start@v1 + with: + config-file: shadow-api-detection.json + auto-record: true + + # Replace with your test commands + - name: Run API tests + run: | + # Example: make requests through Dev Proxy + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders + env: + AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} + AZURE_RESOURCE_GROUP_NAME: ${{ vars.AZURE_RESOURCE_GROUP_NAME }} + AZURE_APIC_INSTANCE_NAME: ${{ vars.AZURE_APIC_INSTANCE_NAME }} + + - name: Stop Dev Proxy + uses: dev-proxy-tools/actions/stop@v1 + + - name: Upload reports + uses: actions/upload-artifact@v4 + with: + name: shadow-api-reports + path: ./*Reporter* + + - name: Write summary + run: | + if [ -f "ApiCenterOnboardingPlugin_MarkdownReporter.md" ]; then + cat ApiCenterOnboardingPlugin_MarkdownReporter.md >> $GITHUB_STEP_SUMMARY + fi + + permission-validation: + name: Permission validation + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Dev Proxy + uses: dev-proxy-tools/actions/setup@v1 + + - name: Start Dev Proxy + uses: dev-proxy-tools/actions/start@v1 + with: + config-file: permission-validation.json + auto-record: true + + # Replace with your test commands + - name: Run API tests + run: | + # Example: make requests through Dev Proxy + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers/1 + + - name: Stop Dev Proxy + uses: dev-proxy-tools/actions/stop@v1 + + - name: Upload reports + uses: actions/upload-artifact@v4 + with: + name: permission-reports + path: ./*Reporter* + + - name: Write summary + run: | + if [ -f "MinimalPermissionsPlugin_MarkdownReporter.md" ]; then + cat MinimalPermissionsPlugin_MarkdownReporter.md >> $GITHUB_STEP_SUMMARY + fi + + openapi-generation: + name: Generate OpenAPI spec + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Dev Proxy + uses: dev-proxy-tools/actions/setup@v1 + + - name: Start Dev Proxy + uses: dev-proxy-tools/actions/start@v1 + with: + config-file: openapi-generation.json + auto-record: true + + # Replace with your test commands + - name: Run API tests + run: | + # Example: make requests through Dev Proxy + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers/1 + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders/1 + + - name: Stop Dev Proxy + uses: dev-proxy-tools/actions/stop@v1 + + - name: Upload OpenAPI spec + uses: actions/upload-artifact@v4 + with: + name: openapi-spec + path: ./*.json + exclude: | + devproxyrc.json + shadow-api-detection.json + permission-validation.json + openapi-generation.json + + # Optional: Commit generated spec to repository + # - name: Commit OpenAPI spec + # run: | + # git config user.name "GitHub Actions" + # git config user.email "actions@github.com" + # git add ./*.json + # git commit -m "chore: update generated OpenAPI spec" || echo "No changes to commit" + # git push diff --git a/samples/ci-cd-api-validation/README.md b/samples/ci-cd-api-validation/README.md new file mode 100644 index 0000000..f533481 --- /dev/null +++ b/samples/ci-cd-api-validation/README.md @@ -0,0 +1,167 @@ +# Integrate Dev Proxy in CI/CD pipelines for API validation + +## Summary + +This sample demonstrates how to integrate Dev Proxy in CI/CD pipelines for API validation. It includes configurations for shadow API detection, permission validation, and OpenAPI spec generation, along with example GitHub Actions workflows and Azure Pipelines YAML files. + +![Dev Proxy CI/CD API validation showing GitHub Actions workflow results](./assets/screenshot.png) + +## Compatibility + +![Dev Proxy v2.0.0](https://aka.ms/devproxy/badge/v2.0.0) + +## Contributors + +- [GitHub Copilot](https://github.com/copilot) + +## Version history + +Version|Date|Comments +-------|----|-------- +1.0|January 6, 2026|Initial release + +## Prerequisites + +- [Azure API Center](https://learn.microsoft.com/azure/api-center/) (for shadow API detection) +- Azure CLI or Azure PowerShell authenticated for API Center access +- CI/CD platform (GitHub Actions or Azure Pipelines) + +## Minimal path to awesome + +- Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/proxy-samples/tree/main/samples/ci-cd-api-validation) then unzip it) +- Update the configuration files with your API URLs: + - In `devproxyrc.json`, `shadow-api-detection.json`, `permission-validation.json`, and `openapi-generation.json`, update the `urlsToWatch` property to match your API endpoints +- For shadow API detection with Azure API Center: + - Create an Azure API Center instance + - Set up the required environment variables/secrets (see CI/CD configuration sections below) +- For permission validation: + - Add your OpenAPI specs to the `.devproxy/api-specs` folder +- Copy the workflow/pipeline files to your repository and customize as needed + +## Features + +Using this sample you can use the Dev Proxy to: + +1. **Detect shadow APIs** - Find APIs that your application uses but aren't registered in Azure API Center +2. **Validate API permissions** - Check if your app uses minimal permissions to call APIs +3. **Generate OpenAPI specs** - Automatically generate OpenAPI specifications from recorded API requests + +## Configuration Files + +This sample includes several configuration files for different validation scenarios: + +| File | Description | +|------|-------------| +| `devproxyrc.json` | Combined configuration with all plugins enabled | +| `shadow-api-detection.json` | Configuration for detecting unregistered APIs using Azure API Center | +| `permission-validation.json` | Configuration for validating API permissions | +| `openapi-generation.json` | Configuration for generating OpenAPI specifications | + +## GitHub Actions + +The sample includes a GitHub Actions workflow (`.github/workflows/api-validation.yml`) that runs three parallel jobs: + +1. **Shadow API detection** - Detects unregistered APIs +2. **Permission validation** - Validates API permissions +3. **OpenAPI generation** - Generates OpenAPI specs from requests + +### Required secrets and variables + +To use the workflow with Azure API Center, configure the following: + +| Type | Name | Description | +|------|------|-------------| +| Variable | `AZURE_SUBSCRIPTION_ID` | Azure subscription ID containing API Center | +| Variable | `AZURE_RESOURCE_GROUP_NAME` | Resource group name containing API Center | +| Variable | `AZURE_APIC_INSTANCE_NAME` | API Center instance name | + +See [Creating configuration variables for a repository](https://docs.github.com/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository) for instructions on setting up variables. + +## Azure Pipelines + +The sample includes an Azure Pipelines configuration (`azure-pipelines.yml`) with three parallel stages: + +1. **Shadow API detection** - Detects unregistered APIs +2. **Permission validation** - Validates API permissions +3. **OpenAPI generation** - Generates OpenAPI specs from requests + +### Required variables + +To use the pipeline with Azure API Center, configure the following pipeline variables: + +| Name | Description | +|------|-------------| +| `AZURE_SUBSCRIPTION_ID` | Azure subscription ID containing API Center | +| `AZURE_RESOURCE_GROUP_NAME` | Resource group name containing API Center | +| `AZURE_APIC_INSTANCE_NAME` | API Center instance name | + +See [Set variables in a pipeline](https://learn.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbash) for instructions on setting up variables. + +## Local testing + +To test the configurations locally: + +1. Start Dev Proxy with the desired configuration: + + ```bash + devproxy --config-file shadow-api-detection.json --record + ``` + +2. Make API requests using curl through Dev Proxy: + + ```bash + curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers + ``` + +3. Stop recording by pressing S +4. Stop Dev Proxy by pressing Ctrl + C +5. Review the generated reports + +## Customization + +### Adding your APIs + +1. Update the `urlsToWatch` in each configuration file to match your API endpoints +2. If using permission validation, add your OpenAPI specs to `.devproxy/api-specs` + +### Integrating with your tests + +Replace the example curl commands in the workflow files and `run.sh` script with your actual test commands: + +```yaml +- name: Run API tests + run: | + npm test + # or + dotnet test + # or + python -m pytest +``` + +### Failing the pipeline on issues + +To fail the pipeline when shadow APIs or permission issues are found, add validation logic after Dev Proxy completes: + +```bash +# Check for shadow APIs +if grep -q "New APIs" ApiCenterOnboardingPlugin_MarkdownReporter.md; then + echo "Shadow APIs detected!" + exit 1 +fi +``` + +## Help + +We do not support samples, but this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues. + +You can try looking at [issues related to this sample](https://github.com/pnp/proxy-samples/issues?q=label%3A%22sample%3A%20ci-cd-api-validation%22) to see if anybody else is having the same issues. + +If you encounter any issues using this sample, [create a new issue](https://github.com/pnp/proxy-samples/issues/new). + +Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/proxy-samples/issues/new). + +## Disclaimer + +**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.** + +![](https://m365-visitor-stats.azurewebsites.net/SamplesGallery/pnp-devproxy-ci-cd-api-validation) diff --git a/samples/ci-cd-api-validation/assets/README.md b/samples/ci-cd-api-validation/assets/README.md new file mode 100644 index 0000000..11b9477 --- /dev/null +++ b/samples/ci-cd-api-validation/assets/README.md @@ -0,0 +1,21 @@ +# Assets + +This folder should contain the following assets: + +## screenshot.png + +A screenshot showing the Dev Proxy CI/CD API validation in action. + +**Recommended specifications:** +- Resolution: 1920x1080 +- Content: Show a GitHub Actions or Azure Pipelines run with Dev Proxy reports + +**Suggested screenshot content:** +- GitHub Actions workflow job summary displaying Dev Proxy validation reports +- Terminal output showing shadow API detection or permission validation results +- Generated OpenAPI spec or markdown reports + +To create the screenshot: +1. Set up the sample in a GitHub repository with API Center configured +2. Run the GitHub Actions workflow +3. Capture the workflow summary page showing the generated reports diff --git a/samples/ci-cd-api-validation/assets/sample.json b/samples/ci-cd-api-validation/assets/sample.json new file mode 100644 index 0000000..4f2be32 --- /dev/null +++ b/samples/ci-cd-api-validation/assets/sample.json @@ -0,0 +1,87 @@ +[ + { + "name": "pnp-devproxy-ci-cd-api-validation", + "source": "pnp", + "title": "Integrate Dev Proxy in CI/CD pipelines for API validation", + "shortDescription": "This sample demonstrates how to integrate Dev Proxy in CI/CD pipelines for API validation. It includes configurations for shadow API detection, permission validation, and OpenAPI spec generation, along with example GitHub Actions workflows and Azure Pipelines YAML files.", + "url": "https://github.com/pnp/proxy-samples/tree/main/samples/ci-cd-api-validation", + "downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/proxy-samples/tree/main/samples/ci-cd-api-validation", + "longDescription": [ + "This sample demonstrates how to integrate Dev Proxy in CI/CD pipelines for API validation. It includes configurations for shadow API detection, permission validation, and OpenAPI spec generation, along with example GitHub Actions workflows and Azure Pipelines YAML files." + ], + "creationDateTime": "2026-01-06", + "updateDateTime": "2026-01-06", + "products": [ + "Dev Proxy" + ], + "metadata": [ + { + "key": "SAMPLE ID", + "value": "ci-cd-api-validation" + }, + { + "key": "PRESET", + "value": "Yes" + }, + { + "key": "MOCKS", + "value": "No" + }, + { + "key": "PLUGIN", + "value": "No" + }, + { + "key": "PROXY VERSION", + "value": "v2.0.0" + } + ], + "thumbnails": [ + { + "type": "image", + "order": 100, + "url": "https://github.com/pnp/proxy-samples/raw/main/samples/ci-cd-api-validation/assets/screenshot.png", + "alt": "Dev Proxy CI/CD API validation showing GitHub Actions workflow results" + } + ], + "authors": [ + { + "gitHubAccount": "copilot", + "pictureUrl": "https://github.com/copilot.png", + "name": "GitHub Copilot" + } + ], + "references": [ + { + "name": "Get started with the Dev Proxy", + "description": "The tutorial will introduce you to the Dev Proxy and show you how to use its features.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/get-started" + }, + { + "name": "Use Dev Proxy in CI/CD scenarios", + "description": "Learn how to use Dev Proxy with GitHub Actions and Azure Pipelines.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/how-to/use-dev-proxy-in-ci-cd-overview" + }, + { + "name": "Use Dev Proxy with GitHub Actions", + "description": "Instructions on how to integrate Dev Proxy into your GitHub Actions workflows.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/how-to/use-dev-proxy-with-github-actions" + }, + { + "name": "Use Dev Proxy with Azure Pipelines", + "description": "Instructions on how to use Dev Proxy with Azure Pipelines.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/how-to/use-dev-proxy-with-azure-pipelines" + }, + { + "name": "ApiCenterOnboardingPlugin reference", + "description": "Learn more about the ApiCenterOnboardingPlugin for shadow API detection.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/technical-reference/apicenteronboardingplugin" + }, + { + "name": "MinimalPermissionsPlugin reference", + "description": "Learn more about the MinimalPermissionsPlugin for permission validation.", + "url": "https://learn.microsoft.com/microsoft-cloud/dev/dev-proxy/technical-reference/minimalpermissionsplugin" + } + ] + } +] diff --git a/samples/ci-cd-api-validation/azure-pipelines.yml b/samples/ci-cd-api-validation/azure-pipelines.yml new file mode 100644 index 0000000..f81150e --- /dev/null +++ b/samples/ci-cd-api-validation/azure-pipelines.yml @@ -0,0 +1,149 @@ +trigger: +- main +- dev + +pr: +- main + +pool: + vmImage: ubuntu-latest + +variables: +- name: LOG_FILE + value: devproxy.log +- name: DEV_PROXY_VERSION + value: v2.0.0 +- name: DEV_PROXY_CACHE_RESTORED + value: 'false' + +stages: +- stage: ShadowApiDetection + displayName: 'Shadow API detection' + jobs: + - job: DetectShadowApis + displayName: 'Check for shadow APIs' + steps: + - task: Cache@2 + inputs: + key: '"dev-proxy-$(DEV_PROXY_VERSION)"' + path: ./devproxy + cacheHitVar: DEV_PROXY_CACHE_RESTORED + displayName: 'Cache Dev Proxy' + + - script: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- $DEV_PROXY_VERSION + displayName: 'Install Dev Proxy' + condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') + + - script: bash ./run.sh shadow-api-detection.json + displayName: 'Run API validation' + env: + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) + AZURE_RESOURCE_GROUP_NAME: $(AZURE_RESOURCE_GROUP_NAME) + AZURE_APIC_INSTANCE_NAME: $(AZURE_APIC_INSTANCE_NAME) + + - task: PublishPipelineArtifact@1 + displayName: 'Upload Dev Proxy logs' + inputs: + targetPath: $(LOG_FILE) + artifact: shadow-api-logs + + - script: | + mkdir -p $(Build.ArtifactStagingDirectory)/ShadowApiReports + for file in *Reporter*; do + if [ -f "$file" ]; then + cp "$file" $(Build.ArtifactStagingDirectory)/ShadowApiReports + fi + done + displayName: 'Copy reports to artifact directory' + + - task: PublishPipelineArtifact@1 + displayName: 'Upload shadow API reports' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/ShadowApiReports' + artifact: 'ShadowApiReports' + +- stage: PermissionValidation + displayName: 'Permission validation' + dependsOn: [] + jobs: + - job: ValidatePermissions + displayName: 'Validate API permissions' + steps: + - task: Cache@2 + inputs: + key: '"dev-proxy-$(DEV_PROXY_VERSION)"' + path: ./devproxy + cacheHitVar: DEV_PROXY_CACHE_RESTORED + displayName: 'Cache Dev Proxy' + + - script: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- $DEV_PROXY_VERSION + displayName: 'Install Dev Proxy' + condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') + + - script: bash ./run.sh permission-validation.json + displayName: 'Run permission validation' + + - task: PublishPipelineArtifact@1 + displayName: 'Upload Dev Proxy logs' + inputs: + targetPath: $(LOG_FILE) + artifact: permission-logs + + - script: | + mkdir -p $(Build.ArtifactStagingDirectory)/PermissionReports + for file in *Reporter*; do + if [ -f "$file" ]; then + cp "$file" $(Build.ArtifactStagingDirectory)/PermissionReports + fi + done + displayName: 'Copy reports to artifact directory' + + - task: PublishPipelineArtifact@1 + displayName: 'Upload permission reports' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/PermissionReports' + artifact: 'PermissionReports' + +- stage: OpenApiGeneration + displayName: 'OpenAPI spec generation' + dependsOn: [] + jobs: + - job: GenerateOpenApiSpec + displayName: 'Generate OpenAPI spec' + steps: + - task: Cache@2 + inputs: + key: '"dev-proxy-$(DEV_PROXY_VERSION)"' + path: ./devproxy + cacheHitVar: DEV_PROXY_CACHE_RESTORED + displayName: 'Cache Dev Proxy' + + - script: bash -c "$(curl -sL https://aka.ms/devproxy/setup.sh)" -- $DEV_PROXY_VERSION + displayName: 'Install Dev Proxy' + condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') + + - script: bash ./run.sh openapi-generation.json + displayName: 'Run OpenAPI generation' + + - task: PublishPipelineArtifact@1 + displayName: 'Upload Dev Proxy logs' + inputs: + targetPath: $(LOG_FILE) + artifact: openapi-logs + + - script: | + mkdir -p $(Build.ArtifactStagingDirectory)/OpenApiSpecs + for file in *.json; do + if [[ "$file" != "devproxyrc.json" && "$file" != "shadow-api-detection.json" && "$file" != "permission-validation.json" && "$file" != "openapi-generation.json" ]]; then + if [ -f "$file" ]; then + cp "$file" $(Build.ArtifactStagingDirectory)/OpenApiSpecs + fi + fi + done + displayName: 'Copy OpenAPI specs to artifact directory' + + - task: PublishPipelineArtifact@1 + displayName: 'Upload generated OpenAPI specs' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/OpenApiSpecs' + artifact: 'OpenApiSpecs' diff --git a/samples/ci-cd-api-validation/devproxyrc.json b/samples/ci-cd-api-validation/devproxyrc.json new file mode 100644 index 0000000..9a85dcb --- /dev/null +++ b/samples/ci-cd-api-validation/devproxyrc.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/rc.schema.json", + "plugins": [ + { + "name": "ApiCenterOnboardingPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", + "configSection": "apiCenterOnboardingPlugin" + }, + { + "name": "MinimalPermissionsPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", + "configSection": "minimalPermissionsPlugin" + }, + { + "name": "OpenApiSpecGeneratorPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + }, + { + "name": "JsonReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + }, + { + "name": "MarkdownReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + }, + { + "name": "PlainTextReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + } + ], + "urlsToWatch": [ + "https://api.contoso.com/*" + ], + "apiCenterOnboardingPlugin": { + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/apicenteronboardingplugin.schema.json", + "subscriptionId": "@AZURE_SUBSCRIPTION_ID", + "resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME", + "serviceName": "@AZURE_APIC_INSTANCE_NAME", + "workspaceName": "default", + "createApicEntryForNewApis": false + }, + "minimalPermissionsPlugin": { + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/minimalpermissionsplugin.schema.json", + "apiSpecsFolderPath": "./.devproxy/api-specs" + }, + "logLevel": "information" +} diff --git a/samples/ci-cd-api-validation/openapi-generation.json b/samples/ci-cd-api-validation/openapi-generation.json new file mode 100644 index 0000000..f39570e --- /dev/null +++ b/samples/ci-cd-api-validation/openapi-generation.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/rc.schema.json", + "plugins": [ + { + "name": "OpenApiSpecGeneratorPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + } + ], + "urlsToWatch": [ + "https://api.contoso.com/*" + ], + "rate": 0, + "logLevel": "information" +} diff --git a/samples/ci-cd-api-validation/permission-validation.json b/samples/ci-cd-api-validation/permission-validation.json new file mode 100644 index 0000000..f7637f7 --- /dev/null +++ b/samples/ci-cd-api-validation/permission-validation.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/rc.schema.json", + "plugins": [ + { + "name": "MinimalPermissionsPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", + "configSection": "minimalPermissionsPlugin" + }, + { + "name": "JsonReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + }, + { + "name": "MarkdownReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + } + ], + "urlsToWatch": [ + "https://api.contoso.com/*" + ], + "minimalPermissionsPlugin": { + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/minimalpermissionsplugin.schema.json", + "apiSpecsFolderPath": "./.devproxy/api-specs" + }, + "logLevel": "information" +} diff --git a/samples/ci-cd-api-validation/run.sh b/samples/ci-cd-api-validation/run.sh new file mode 100644 index 0000000..c229317 --- /dev/null +++ b/samples/ci-cd-api-validation/run.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# enable job control so that we can send SIGINT to Dev Proxy +set -m + +log_file=devproxy.log +config_file=${1:-devproxyrc.json} + +echo "Using config file: $config_file" + +echo "Ensuring Dev Proxy rootCert folder..." +mkdir -p ~/.config/dev-proxy/rootCert + +echo "Starting Dev Proxy..." + +# start Dev Proxy in the background +# log Dev Proxy output to the log file +# log stdout and stderr to the file +./devproxy/devproxy --config-file "$config_file" --record > $log_file 2>&1 & + +proxy_pid=$! + +echo "Waiting for Dev Proxy to start..." +while true; do + if grep -q "Listening on 127.0.0.1:8000" $log_file; then + break + fi + if grep -q "Recording" $log_file; then + break + fi + # timeout after 60 seconds + if [ $SECONDS -gt 60 ]; then + echo "Timeout waiting for Dev Proxy to start" + cat $log_file + exit 1 + fi + sleep 1 +done + +echo "Dev Proxy started successfully!" + +# export the Dev Proxy's Root Certificate +echo "Exporting the Dev Proxy's Root Certificate..." +openssl pkcs12 -in ~/.config/dev-proxy/rootCert.pfx -clcerts -nokeys -out dev-proxy-ca.crt -passin pass:"" + +# install root certificate +echo "Installing the Dev Proxy's Root Certificate..." +sudo cp dev-proxy-ca.crt /usr/local/share/ca-certificates/ + +# update CA certificates +echo "Updating the CA certificates..." +sudo update-ca-certificates + +# set proxy environment variables +export http_proxy=http://127.0.0.1:8000 +export https_proxy=http://127.0.0.1:8000 + +echo "Running API tests..." + +# Add your test commands here +# Example: +# npm test +# dotnet test +# python -m pytest + +# For demonstration, making sample curl requests +curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers || true +curl -ikx http://127.0.0.1:8000 https://api.contoso.com/customers/1 || true +curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders || true +curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders/1 || true + +# stop Dev Proxy +echo "Stopping Dev Proxy..." +curl -s -X POST http://localhost:8897/proxy/stop || kill -INT $proxy_pid + +echo "Waiting for Dev Proxy to complete..." +while true; do + if grep -q -e "DONE" -e "No requests to process" -e "An error occurred in a plugin" $log_file; then + break + fi + # timeout after 60 seconds + if [ $SECONDS -gt 120 ]; then + echo "Timeout waiting for Dev Proxy to complete" + cat $log_file + exit 1 + fi + sleep 1 +done + +echo "Dev Proxy completed!" +echo "" +echo "Generated reports:" +ls -la *Reporter* 2>/dev/null || echo "No reports generated" diff --git a/samples/ci-cd-api-validation/shadow-api-detection.json b/samples/ci-cd-api-validation/shadow-api-detection.json new file mode 100644 index 0000000..d46b17d --- /dev/null +++ b/samples/ci-cd-api-validation/shadow-api-detection.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/rc.schema.json", + "plugins": [ + { + "name": "ApiCenterOnboardingPlugin", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", + "configSection": "apiCenterOnboardingPlugin" + }, + { + "name": "JsonReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + }, + { + "name": "MarkdownReporter", + "enabled": true, + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" + } + ], + "urlsToWatch": [ + "https://api.contoso.com/*" + ], + "apiCenterOnboardingPlugin": { + "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/apicenteronboardingplugin.schema.json", + "subscriptionId": "@AZURE_SUBSCRIPTION_ID", + "resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME", + "serviceName": "@AZURE_APIC_INSTANCE_NAME", + "workspaceName": "default", + "createApicEntryForNewApis": false + }, + "logLevel": "information" +} From 3bf4f46dcf449bcdfdcf7d2c2a1348562846abce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:04:15 +0000 Subject: [PATCH 2/7] Fix code review issues in run.sh and workflow files Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../.github/workflows/api-validation.yml | 18 ++++++++++++------ samples/ci-cd-api-validation/run.sh | 6 ++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml index 614904b..1534d70 100644 --- a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml +++ b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml @@ -118,16 +118,22 @@ jobs: - name: Stop Dev Proxy uses: dev-proxy-tools/actions/stop@v1 + - name: Collect OpenAPI specs + run: | + mkdir -p generated-specs + for file in *.json; do + if [[ "$file" != "devproxyrc.json" && "$file" != "shadow-api-detection.json" && "$file" != "permission-validation.json" && "$file" != "openapi-generation.json" ]]; then + if [ -f "$file" ]; then + cp "$file" generated-specs/ + fi + fi + done + - name: Upload OpenAPI spec uses: actions/upload-artifact@v4 with: name: openapi-spec - path: ./*.json - exclude: | - devproxyrc.json - shadow-api-detection.json - permission-validation.json - openapi-generation.json + path: generated-specs/ # Optional: Commit generated spec to repository # - name: Commit OpenAPI spec diff --git a/samples/ci-cd-api-validation/run.sh b/samples/ci-cd-api-validation/run.sh index c229317..d2f1c54 100644 --- a/samples/ci-cd-api-validation/run.sh +++ b/samples/ci-cd-api-validation/run.sh @@ -5,6 +5,7 @@ set -m log_file=devproxy.log config_file=${1:-devproxyrc.json} +start_time=$SECONDS echo "Using config file: $config_file" @@ -29,7 +30,7 @@ while true; do break fi # timeout after 60 seconds - if [ $SECONDS -gt 60 ]; then + if [ $((SECONDS - start_time)) -gt 60 ]; then echo "Timeout waiting for Dev Proxy to start" cat $log_file exit 1 @@ -73,13 +74,14 @@ curl -ikx http://127.0.0.1:8000 https://api.contoso.com/orders/1 || true echo "Stopping Dev Proxy..." curl -s -X POST http://localhost:8897/proxy/stop || kill -INT $proxy_pid +stop_time=$SECONDS echo "Waiting for Dev Proxy to complete..." while true; do if grep -q -e "DONE" -e "No requests to process" -e "An error occurred in a plugin" $log_file; then break fi # timeout after 60 seconds - if [ $SECONDS -gt 120 ]; then + if [ $((SECONDS - stop_time)) -gt 60 ]; then echo "Timeout waiting for Dev Proxy to complete" cat $log_file exit 1 From ea3bb085d697a62e2a94c659ad5c36768b44ce16 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 08:34:02 +0000 Subject: [PATCH 3/7] Restructure sample to follow copilot-instructions.md guidelines Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../{ => .devproxy}/openapi-generation.json | 0 .../{ => .devproxy}/permission-validation.json | 2 +- .../{ => .devproxy}/shadow-api-detection.json | 0 .../.github/workflows/api-validation.yml | 8 ++++---- samples/ci-cd-api-validation/README.md | 10 +++++----- samples/ci-cd-api-validation/azure-pipelines.yml | 8 ++++---- 6 files changed, 14 insertions(+), 14 deletions(-) rename samples/ci-cd-api-validation/{ => .devproxy}/openapi-generation.json (100%) rename samples/ci-cd-api-validation/{ => .devproxy}/permission-validation.json (94%) rename samples/ci-cd-api-validation/{ => .devproxy}/shadow-api-detection.json (100%) diff --git a/samples/ci-cd-api-validation/openapi-generation.json b/samples/ci-cd-api-validation/.devproxy/openapi-generation.json similarity index 100% rename from samples/ci-cd-api-validation/openapi-generation.json rename to samples/ci-cd-api-validation/.devproxy/openapi-generation.json diff --git a/samples/ci-cd-api-validation/permission-validation.json b/samples/ci-cd-api-validation/.devproxy/permission-validation.json similarity index 94% rename from samples/ci-cd-api-validation/permission-validation.json rename to samples/ci-cd-api-validation/.devproxy/permission-validation.json index f7637f7..30cfeff 100644 --- a/samples/ci-cd-api-validation/permission-validation.json +++ b/samples/ci-cd-api-validation/.devproxy/permission-validation.json @@ -23,7 +23,7 @@ ], "minimalPermissionsPlugin": { "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/minimalpermissionsplugin.schema.json", - "apiSpecsFolderPath": "./.devproxy/api-specs" + "apiSpecsFolderPath": "./api-specs" }, "logLevel": "information" } diff --git a/samples/ci-cd-api-validation/shadow-api-detection.json b/samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json similarity index 100% rename from samples/ci-cd-api-validation/shadow-api-detection.json rename to samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json diff --git a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml index 1534d70..a3cdc22 100644 --- a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml +++ b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml @@ -23,7 +23,7 @@ jobs: - name: Start Dev Proxy uses: dev-proxy-tools/actions/start@v1 with: - config-file: shadow-api-detection.json + config-file: .devproxy/shadow-api-detection.json auto-record: true # Replace with your test commands @@ -65,7 +65,7 @@ jobs: - name: Start Dev Proxy uses: dev-proxy-tools/actions/start@v1 with: - config-file: permission-validation.json + config-file: .devproxy/permission-validation.json auto-record: true # Replace with your test commands @@ -103,7 +103,7 @@ jobs: - name: Start Dev Proxy uses: dev-proxy-tools/actions/start@v1 with: - config-file: openapi-generation.json + config-file: .devproxy/openapi-generation.json auto-record: true # Replace with your test commands @@ -122,7 +122,7 @@ jobs: run: | mkdir -p generated-specs for file in *.json; do - if [[ "$file" != "devproxyrc.json" && "$file" != "shadow-api-detection.json" && "$file" != "permission-validation.json" && "$file" != "openapi-generation.json" ]]; then + if [[ "$file" != "devproxyrc.json" ]]; then if [ -f "$file" ]; then cp "$file" generated-specs/ fi diff --git a/samples/ci-cd-api-validation/README.md b/samples/ci-cd-api-validation/README.md index f533481..208576d 100644 --- a/samples/ci-cd-api-validation/README.md +++ b/samples/ci-cd-api-validation/README.md @@ -30,7 +30,7 @@ Version|Date|Comments - Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/proxy-samples/tree/main/samples/ci-cd-api-validation) then unzip it) - Update the configuration files with your API URLs: - - In `devproxyrc.json`, `shadow-api-detection.json`, `permission-validation.json`, and `openapi-generation.json`, update the `urlsToWatch` property to match your API endpoints + - In `devproxyrc.json` and the configuration files in `.devproxy/` folder, update the `urlsToWatch` property to match your API endpoints - For shadow API detection with Azure API Center: - Create an Azure API Center instance - Set up the required environment variables/secrets (see CI/CD configuration sections below) @@ -53,9 +53,9 @@ This sample includes several configuration files for different validation scenar | File | Description | |------|-------------| | `devproxyrc.json` | Combined configuration with all plugins enabled | -| `shadow-api-detection.json` | Configuration for detecting unregistered APIs using Azure API Center | -| `permission-validation.json` | Configuration for validating API permissions | -| `openapi-generation.json` | Configuration for generating OpenAPI specifications | +| `.devproxy/shadow-api-detection.json` | Configuration for detecting unregistered APIs using Azure API Center | +| `.devproxy/permission-validation.json` | Configuration for validating API permissions | +| `.devproxy/openapi-generation.json` | Configuration for generating OpenAPI specifications | ## GitHub Actions @@ -104,7 +104,7 @@ To test the configurations locally: 1. Start Dev Proxy with the desired configuration: ```bash - devproxy --config-file shadow-api-detection.json --record + devproxy --config-file .devproxy/shadow-api-detection.json --record ``` 2. Make API requests using curl through Dev Proxy: diff --git a/samples/ci-cd-api-validation/azure-pipelines.yml b/samples/ci-cd-api-validation/azure-pipelines.yml index f81150e..628ce15 100644 --- a/samples/ci-cd-api-validation/azure-pipelines.yml +++ b/samples/ci-cd-api-validation/azure-pipelines.yml @@ -34,7 +34,7 @@ stages: displayName: 'Install Dev Proxy' condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') - - script: bash ./run.sh shadow-api-detection.json + - script: bash ./run.sh .devproxy/shadow-api-detection.json displayName: 'Run API validation' env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) @@ -80,7 +80,7 @@ stages: displayName: 'Install Dev Proxy' condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') - - script: bash ./run.sh permission-validation.json + - script: bash ./run.sh .devproxy/permission-validation.json displayName: 'Run permission validation' - task: PublishPipelineArtifact@1 @@ -122,7 +122,7 @@ stages: displayName: 'Install Dev Proxy' condition: ne(variables.DEV_PROXY_CACHE_RESTORED, 'true') - - script: bash ./run.sh openapi-generation.json + - script: bash ./run.sh .devproxy/openapi-generation.json displayName: 'Run OpenAPI generation' - task: PublishPipelineArtifact@1 @@ -134,7 +134,7 @@ stages: - script: | mkdir -p $(Build.ArtifactStagingDirectory)/OpenApiSpecs for file in *.json; do - if [[ "$file" != "devproxyrc.json" && "$file" != "shadow-api-detection.json" && "$file" != "permission-validation.json" && "$file" != "openapi-generation.json" ]]; then + if [[ "$file" != "devproxyrc.json" ]]; then if [ -f "$file" ]; then cp "$file" $(Build.ArtifactStagingDirectory)/OpenApiSpecs fi From 3807be7c69e99888547171a08fc6d2ccbbe52093 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 10:13:46 +0000 Subject: [PATCH 4/7] Update author to waldekmastykarz and dates to 2026-01-10 Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- samples/ci-cd-api-validation/README.md | 4 ++-- samples/ci-cd-api-validation/assets/sample.json | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/samples/ci-cd-api-validation/README.md b/samples/ci-cd-api-validation/README.md index 208576d..cd09f63 100644 --- a/samples/ci-cd-api-validation/README.md +++ b/samples/ci-cd-api-validation/README.md @@ -12,13 +12,13 @@ This sample demonstrates how to integrate Dev Proxy in CI/CD pipelines for API v ## Contributors -- [GitHub Copilot](https://github.com/copilot) +- [Waldek Mastykarz](https://github.com/waldekmastykarz) ## Version history Version|Date|Comments -------|----|-------- -1.0|January 6, 2026|Initial release +1.0|January 10, 2026|Initial release ## Prerequisites diff --git a/samples/ci-cd-api-validation/assets/sample.json b/samples/ci-cd-api-validation/assets/sample.json index 4f2be32..85960cc 100644 --- a/samples/ci-cd-api-validation/assets/sample.json +++ b/samples/ci-cd-api-validation/assets/sample.json @@ -9,8 +9,8 @@ "longDescription": [ "This sample demonstrates how to integrate Dev Proxy in CI/CD pipelines for API validation. It includes configurations for shadow API detection, permission validation, and OpenAPI spec generation, along with example GitHub Actions workflows and Azure Pipelines YAML files." ], - "creationDateTime": "2026-01-06", - "updateDateTime": "2026-01-06", + "creationDateTime": "2026-01-10", + "updateDateTime": "2026-01-10", "products": [ "Dev Proxy" ], @@ -46,9 +46,9 @@ ], "authors": [ { - "gitHubAccount": "copilot", - "pictureUrl": "https://github.com/copilot.png", - "name": "GitHub Copilot" + "gitHubAccount": "waldekmastykarz", + "pictureUrl": "https://github.com/waldekmastykarz.png", + "name": "Waldek Mastykarz" } ], "references": [ From 92145fa0d05620580848e6915da7295e065b4758 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:42:37 +0000 Subject: [PATCH 5/7] Add screenshot showing Dev Proxy CI/CD validation output Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- samples/ci-cd-api-validation/assets/README.md | 21 +++++------------- .../assets/screenshot.png | Bin 0 -> 110392 bytes 2 files changed, 6 insertions(+), 15 deletions(-) create mode 100644 samples/ci-cd-api-validation/assets/screenshot.png diff --git a/samples/ci-cd-api-validation/assets/README.md b/samples/ci-cd-api-validation/assets/README.md index 11b9477..d9d4b9a 100644 --- a/samples/ci-cd-api-validation/assets/README.md +++ b/samples/ci-cd-api-validation/assets/README.md @@ -1,21 +1,12 @@ # Assets -This folder should contain the following assets: +This folder contains assets for the ci-cd-api-validation sample. ## screenshot.png -A screenshot showing the Dev Proxy CI/CD API validation in action. +A screenshot showing the Dev Proxy CI/CD API validation terminal output, including: +- Shadow API detection results +- Registered vs. unregistered API analysis +- Generated report file names -**Recommended specifications:** -- Resolution: 1920x1080 -- Content: Show a GitHub Actions or Azure Pipelines run with Dev Proxy reports - -**Suggested screenshot content:** -- GitHub Actions workflow job summary displaying Dev Proxy validation reports -- Terminal output showing shadow API detection or permission validation results -- Generated OpenAPI spec or markdown reports - -To create the screenshot: -1. Set up the sample in a GitHub repository with API Center configured -2. Run the GitHub Actions workflow -3. Capture the workflow summary page showing the generated reports +The screenshot demonstrates the output when running Dev Proxy with the `ApiCenterOnboardingPlugin` for shadow API detection in a CI/CD pipeline. diff --git a/samples/ci-cd-api-validation/assets/screenshot.png b/samples/ci-cd-api-validation/assets/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..9010ede441c031f05605923cfa6aa6c557f41a7c GIT binary patch literal 110392 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 PRKZN^*;ctC&kg?u#onHP literal 0 HcmV?d00001 From 6f15efa34d16b2a74063edb6f7bd94dacfe1c6e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 14:54:54 +0000 Subject: [PATCH 6/7] Move all Dev Proxy configs to .devproxy folder and remove default values Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- .../ci-cd-api-validation/{ => .devproxy}/devproxyrc.json | 6 ++---- .../ci-cd-api-validation/.devproxy/openapi-generation.json | 4 +--- .../.devproxy/permission-validation.json | 3 +-- .../.devproxy/shadow-api-detection.json | 4 +--- .../.github/workflows/api-validation.yml | 6 ++---- samples/ci-cd-api-validation/README.md | 4 ++-- samples/ci-cd-api-validation/azure-pipelines.yml | 6 ++---- samples/ci-cd-api-validation/run.sh | 2 +- 8 files changed, 12 insertions(+), 23 deletions(-) rename samples/ci-cd-api-validation/{ => .devproxy}/devproxyrc.json (93%) diff --git a/samples/ci-cd-api-validation/devproxyrc.json b/samples/ci-cd-api-validation/.devproxy/devproxyrc.json similarity index 93% rename from samples/ci-cd-api-validation/devproxyrc.json rename to samples/ci-cd-api-validation/.devproxy/devproxyrc.json index 9a85dcb..0cfb396 100644 --- a/samples/ci-cd-api-validation/devproxyrc.json +++ b/samples/ci-cd-api-validation/.devproxy/devproxyrc.json @@ -42,12 +42,10 @@ "subscriptionId": "@AZURE_SUBSCRIPTION_ID", "resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME", "serviceName": "@AZURE_APIC_INSTANCE_NAME", - "workspaceName": "default", "createApicEntryForNewApis": false }, "minimalPermissionsPlugin": { "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/minimalpermissionsplugin.schema.json", - "apiSpecsFolderPath": "./.devproxy/api-specs" - }, - "logLevel": "information" + "apiSpecsFolderPath": "./api-specs" + } } diff --git a/samples/ci-cd-api-validation/.devproxy/openapi-generation.json b/samples/ci-cd-api-validation/.devproxy/openapi-generation.json index f39570e..1e6d074 100644 --- a/samples/ci-cd-api-validation/.devproxy/openapi-generation.json +++ b/samples/ci-cd-api-validation/.devproxy/openapi-generation.json @@ -9,7 +9,5 @@ ], "urlsToWatch": [ "https://api.contoso.com/*" - ], - "rate": 0, - "logLevel": "information" + ] } diff --git a/samples/ci-cd-api-validation/.devproxy/permission-validation.json b/samples/ci-cd-api-validation/.devproxy/permission-validation.json index 30cfeff..3a76050 100644 --- a/samples/ci-cd-api-validation/.devproxy/permission-validation.json +++ b/samples/ci-cd-api-validation/.devproxy/permission-validation.json @@ -24,6 +24,5 @@ "minimalPermissionsPlugin": { "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v2.0.0/minimalpermissionsplugin.schema.json", "apiSpecsFolderPath": "./api-specs" - }, - "logLevel": "information" + } } diff --git a/samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json b/samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json index d46b17d..edfd0ee 100644 --- a/samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json +++ b/samples/ci-cd-api-validation/.devproxy/shadow-api-detection.json @@ -26,8 +26,6 @@ "subscriptionId": "@AZURE_SUBSCRIPTION_ID", "resourceGroupName": "@AZURE_RESOURCE_GROUP_NAME", "serviceName": "@AZURE_APIC_INSTANCE_NAME", - "workspaceName": "default", "createApicEntryForNewApis": false - }, - "logLevel": "information" + } } diff --git a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml index a3cdc22..3dc18e9 100644 --- a/samples/ci-cd-api-validation/.github/workflows/api-validation.yml +++ b/samples/ci-cd-api-validation/.github/workflows/api-validation.yml @@ -122,10 +122,8 @@ jobs: run: | mkdir -p generated-specs for file in *.json; do - if [[ "$file" != "devproxyrc.json" ]]; then - if [ -f "$file" ]; then - cp "$file" generated-specs/ - fi + if [ -f "$file" ]; then + cp "$file" generated-specs/ fi done diff --git a/samples/ci-cd-api-validation/README.md b/samples/ci-cd-api-validation/README.md index cd09f63..3099e9a 100644 --- a/samples/ci-cd-api-validation/README.md +++ b/samples/ci-cd-api-validation/README.md @@ -30,7 +30,7 @@ Version|Date|Comments - Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/proxy-samples/tree/main/samples/ci-cd-api-validation) then unzip it) - Update the configuration files with your API URLs: - - In `devproxyrc.json` and the configuration files in `.devproxy/` folder, update the `urlsToWatch` property to match your API endpoints + - In the configuration files in `.devproxy/` folder, update the `urlsToWatch` property to match your API endpoints - For shadow API detection with Azure API Center: - Create an Azure API Center instance - Set up the required environment variables/secrets (see CI/CD configuration sections below) @@ -52,7 +52,7 @@ This sample includes several configuration files for different validation scenar | File | Description | |------|-------------| -| `devproxyrc.json` | Combined configuration with all plugins enabled | +| `.devproxy/devproxyrc.json` | Combined configuration with all plugins enabled | | `.devproxy/shadow-api-detection.json` | Configuration for detecting unregistered APIs using Azure API Center | | `.devproxy/permission-validation.json` | Configuration for validating API permissions | | `.devproxy/openapi-generation.json` | Configuration for generating OpenAPI specifications | diff --git a/samples/ci-cd-api-validation/azure-pipelines.yml b/samples/ci-cd-api-validation/azure-pipelines.yml index 628ce15..7e1e487 100644 --- a/samples/ci-cd-api-validation/azure-pipelines.yml +++ b/samples/ci-cd-api-validation/azure-pipelines.yml @@ -134,10 +134,8 @@ stages: - script: | mkdir -p $(Build.ArtifactStagingDirectory)/OpenApiSpecs for file in *.json; do - if [[ "$file" != "devproxyrc.json" ]]; then - if [ -f "$file" ]; then - cp "$file" $(Build.ArtifactStagingDirectory)/OpenApiSpecs - fi + if [ -f "$file" ]; then + cp "$file" $(Build.ArtifactStagingDirectory)/OpenApiSpecs fi done displayName: 'Copy OpenAPI specs to artifact directory' diff --git a/samples/ci-cd-api-validation/run.sh b/samples/ci-cd-api-validation/run.sh index d2f1c54..6be5f19 100644 --- a/samples/ci-cd-api-validation/run.sh +++ b/samples/ci-cd-api-validation/run.sh @@ -4,7 +4,7 @@ set -m log_file=devproxy.log -config_file=${1:-devproxyrc.json} +config_file=${1:-.devproxy/devproxyrc.json} start_time=$SECONDS echo "Using config file: $config_file" From 94a9f84a1f63ad677ce34dffaff49cc757b91e1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 18 Jan 2026 15:04:42 +0000 Subject: [PATCH 7/7] Fix PRESET metadata to No - sample is scenario-specific Co-authored-by: waldekmastykarz <11164679+waldekmastykarz@users.noreply.github.com> --- samples/ci-cd-api-validation/assets/sample.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ci-cd-api-validation/assets/sample.json b/samples/ci-cd-api-validation/assets/sample.json index 85960cc..c670721 100644 --- a/samples/ci-cd-api-validation/assets/sample.json +++ b/samples/ci-cd-api-validation/assets/sample.json @@ -21,7 +21,7 @@ }, { "key": "PRESET", - "value": "Yes" + "value": "No" }, { "key": "MOCKS",