Skip to content

Runbook: Onboard a Repository to the DevSecOps Pipeline

Estimated time: 1–2 hours
Audience: DevOps engineers, team leads
Prerequisites: Azure DevOps Project Administrator access, SonarCloud organization access


Overview

This runbook walks through every step required to connect a new repository or new service to the centralized 16-stage DevSecOps pipeline template.

Repo setup → SonarCloud → Pipeline YAML → ADO pipeline → First run

Step 1 — Verify Repository Structure

Before onboarding, confirm the repository contains the expected structure:

Backend (.NET) repositories:

RepoRoot/
├── {ServiceName}.Apis/
│   ├── Dockerfile           ← Required
│   └── {ServiceName}.Apis.csproj
├── {ServiceName}.Application/
├── {ServiceName}.Domain/
├── {ServiceName}.Infrastructure/
└── {ServiceName}.Tests/
    └── {ServiceName}.Tests.csproj

Frontend (Angular) repositories:

RepoRoot/
├── src/
├── angular.json
├── package.json
└── Dockerfile              ← Required (for containerised frontends)

No Dockerfile = no pipeline

The DevSecOps template requires a Dockerfile to run Stages 8 (Docker build) and 9 (Trivy scan). If your service is library-only (no container), use the libraryOnly: true parameter — but this is rare. Confirm with the DevOps team.


Step 2 — Create the SonarCloud Project

SonarCloud is used in Stage 3 (SAST). Each repository needs its own SonarCloud project.

  1. Open sonarcloud.io → Organization: microtec
  2. Click +Analyze new project
  3. Choose Azure DevOps → Select the repository
  4. Configure:
FieldValue
Project Keymicrotec_{service-name} (e.g., microtec_hr-service)
Display Name{ServiceName}
LanguageC# (backend) or TypeScript (frontend)
Quality GateMicrotec ERP Standard
  1. Note the Project Key — you will need it in Step 4.

Required Quality Gate

The Microtec ERP Standard Quality Gate must be applied. It enforces:

MetricThreshold
Coverage on new code≥ 80%
Duplicated lines< 5%
Maintainability ratingA
Reliability ratingA
Security ratingA
Security hotspots reviewed100%

If the gate does not appear in the dropdown, contact the DevOps team to create it at the organization level.


Step 3 — Configure Gitleaks

Gitleaks runs in Stage 1 to detect hardcoded secrets. The default ruleset covers 800+ patterns. Most repositories work with the default configuration.

If the repository has known false positives (e.g., test fixture files with fake API keys), create a .gitleaks.toml in the repository root:

toml
[allowlist]
  description = "Known false positives"
  files       = ["tests/fixtures/test-secrets.json"]
  paths       = ["tests/e2e/mock-data/"]
  regexes     = ["EXAMPLE_ONLY_.*"]

Never allowlist real secrets

Allowlisting should only be used for test data with clearly fake values (e.g., sk_test_XXXXXXXXXXXXXXXX). If a real secret is found, rotate it immediately — do not allowlist it.


Step 4 — Create the Pipeline YAML

Create the pipeline entrypoint file in the Devops/ repository (not in the service repository):

Devops/azure/pipelines/{service-name}/deploy-{service-name}.yml

Backend (.NET) example

yaml
# deploy-hr-service.yml
name: $(Build.BuildId)

trigger:
  branches:
    include:
      - main
      - stage
      - PreProd
      - production
  paths:
    include:
      - Platforms/Src/InfrastructureServices/HR/**

pr:
  branches:
    include:
      - main
  paths:
    include:
      - Platforms/Src/InfrastructureServices/HR/**

parameters:
  - name: environment
    type: string
    default: dev
    values: [dev, stage, preprod, uat, production]
  - name: forceFullPipeline
    type: boolean
    default: false

extends:
  template: ../../templates/devsecops/pipeline-template.yml
  parameters:
    # ── Required ──────────────────────────────────────────────
    serviceName:       hr-service
    dockerfilePath:    Platforms/Src/InfrastructureServices/HR/HR.Apis/Dockerfile
    testProjectPath:   Platforms/Src/InfrastructureServices/HR/HR.Tests/HR.Tests.csproj
    sonarProjectKey:   microtec_hr-service

    # ── Optional overrides ────────────────────────────────────
    environment:          ${{ parameters.environment }}
    forceFullPipeline:    ${{ parameters.forceFullPipeline }}
    coverageThreshold:    80           # default; override for bootstrapping
    networkProfile:       private      # 'public' for gateway/keycloak
    enableDastScan:       true
    enableIntegrationTests: false      # Set true when Postman collection exists

Frontend (Angular) example

yaml
# deploy-apps-hr-frontend.yml
extends:
  template: ../../templates/devsecops/pipeline-template.yml
  parameters:
    serviceName:      apps-hr
    serviceType:      frontend          # Switches to npm build instead of dotnet
    dockerfilePath:   FrontApps/projects/apps-hr/Dockerfile
    sonarProjectKey:  microtec_apps-hr
    environment:      ${{ parameters.environment }}
    networkProfile:   public

Available Parameters

ParameterRequiredDefaultDescription
serviceNameYesMatches the name in services-config.json
dockerfilePathYesRelative path to Dockerfile from repo root
sonarProjectKeyYesSonarCloud project key from Step 2
testProjectPathBackend onlyPath to the .NET test project
serviceTypeNobackendbackend or frontend
environmentNodevTarget environment
networkProfileNoprivateprivate or public (ACA profile)
coverageThresholdNo80Minimum coverage percentage (Stage 6)
enableDastScanNotrueRun OWASP ZAP in Stage 13
enableIntegrationTestsNofalseRun Postman/Newman in Stage 12
forceFullPipelineNofalseSkip change detection; run all stages

Step 5 — Register the Pipeline in Azure DevOps

  1. In Azure DevOps, go to Pipelines → New Pipeline
  2. Choose Azure Repos Git (or GitHub, if applicable)
  3. Select the Devops repository
  4. Choose Existing Azure Pipelines YAML file
  5. Path: /azure/pipelines/{service-name}/deploy-{service-name}.yml
  6. Click Save (do not run yet)
  7. Rename the pipeline: deploy-{service-name}

Connect to Variable Groups

In the pipeline's VariablesVariable Groups, link:

  • microtec-erp-dev
  • microtec-erp-stage
  • microtec-erp-preprod
  • microtec-erp-uat
  • microtec-erp-production

Step 6 — Configure Branch Policies (PRs)

Set up a required status check on the target branch so that PRs cannot merge without passing the pipeline:

  1. Azure DevOps → Repos → Branches → main → Branch Policies
  2. Add Build Validation:
FieldValue
Build pipelinedeploy-{service-name}
TriggerAutomatic
Policy requirementRequired
Build expiration12 hours
Display nameDevSecOps: {service-name}

Step 7 — Verify the Pipeline

Trigger the first run manually:

bash
az pipelines run \
  --name "deploy-{service-name}" \
  --parameters "environment=dev" \
  --branch main

Monitor the run. Expected stage progression on a healthy new service:

StageExpected DurationCommon First-Run Issue
1. Secret scan1–2 minFalse positive from test fixtures (see Step 3)
2. Dependency audit3–5 minMissing nuget.config
3. SonarCloud3–8 minProject key mismatch
4. License check1–2 minGPL dependency (must resolve before proceeding)
5–6. Tests + coverage2–10 minCoverage below 80% (use coverageThreshold override for bootstrapping)
7–10. Build + push5–15 minNuGet PAT not in variable group
11. Deploy dev3–5 minService not in services-config.json

Step 8 — Add to the Repo Registry

Update Devops/azure/docs/repo-registry.md (or the equivalent registry file) with the new repository entry:

markdown
| {service-name} | {Repository URL} | {Team} | deploy-{service-name} | microtec_{service-name} |

Checklist

  • [ ] Repository structure verified (Dockerfile present)
  • [ ] SonarCloud project created with correct project key
  • [ ] Microtec ERP Standard quality gate applied
  • [ ] Gitleaks false-positive suppressions configured (if needed)
  • [ ] Pipeline YAML created in Devops/azure/pipelines/{service-name}/
  • [ ] Pipeline registered in Azure DevOps and renamed
  • [ ] Variable groups linked
  • [ ] Branch policy set on main
  • [ ] First pipeline run succeeded (all stages green)
  • [ ] Repo registry updated

Troubleshooting

SymptomLikely CauseFix
Stage 1 fails with git-secrets foundReal or false-positive secretRotate if real; add to .gitleaks.toml if false positive
Stage 3 fails Quality Gate failedCoverage < 80% on new codeAdd tests; or use coverageThreshold: 60 temporarily
Stage 3: Project not foundWrong sonarProjectKeyVerify key in SonarCloud project settings
Stage 9 fails with CRITICAL CVEOutdated base imageUse mcr.microsoft.com/dotnet/aspnet:8.0 and run docker pull to get latest patch
Stage 11 fails ContainerApp not foundService not in services-config.jsonAdd entry; re-run pipeline

Internal Documentation — Microtec Platform Team