Skip to content

Commit 061cedd

Browse files
feat: scaffold code-quality-scan-demo-app with 5 demo apps, CI/CD, PBIP, and bootstrap scripts AB#0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0 parents  commit 061cedd

153 files changed

Lines changed: 14531 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
trigger: none
2+
3+
pr:
4+
branches:
5+
include:
6+
- main
7+
8+
pool:
9+
vmImage: 'ubuntu-latest'
10+
11+
steps:
12+
- checkout: self
13+
14+
- script: |
15+
npx mega-linter-runner --flavor dotnetweb -e VALIDATE_ALL_CODEBASE=false -e SARIF_REPORTER=true
16+
displayName: 'Run MegaLinter (changed files only)'
17+
18+
- script: |
19+
if [ -f "megalinter-reports/megalinter-report.sarif" ]; then
20+
HIGH_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' megalinter-reports/megalinter-report.sarif)
21+
if [ "$HIGH_COUNT" -gt 0 ]; then
22+
echo "##vso[task.logissue type=error]$HIGH_COUNT HIGH/CRITICAL findings detected — blocking merge"
23+
exit 1
24+
fi
25+
fi
26+
displayName: 'Check for HIGH/CRITICAL findings'
27+
28+
- task: AdvancedSecurity-Publish@1
29+
inputs:
30+
SarifFileDirectory: 'megalinter-reports'
31+
condition: always()
32+
displayName: 'Publish SARIF to Advanced Security'
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
trigger: none
2+
3+
schedules:
4+
- cron: '0 6 * * 1'
5+
displayName: 'Weekly Monday 6 AM UTC'
6+
branches:
7+
include:
8+
- main
9+
10+
pool:
11+
vmImage: 'ubuntu-latest'
12+
13+
variables:
14+
- template: variables/common.yml
15+
16+
strategy:
17+
matrix:
18+
app001:
19+
appId: '001'
20+
repoName: 'cq-demo-app-001'
21+
app002:
22+
appId: '002'
23+
repoName: 'cq-demo-app-002'
24+
app003:
25+
appId: '003'
26+
repoName: 'cq-demo-app-003'
27+
app004:
28+
appId: '004'
29+
repoName: 'cq-demo-app-004'
30+
app005:
31+
appId: '005'
32+
repoName: 'cq-demo-app-005'
33+
34+
steps:
35+
- checkout: self
36+
37+
- task: UsePythonVersion@0
38+
inputs:
39+
versionSpec: '3.12'
40+
41+
- script: |
42+
pip install lizard
43+
pip install jscpd
44+
displayName: 'Install scanning tools'
45+
46+
- script: |
47+
npx mega-linter-runner --flavor dotnetweb -e VALIDATE_ALL_CODEBASE=true -e SARIF_REPORTER=true
48+
displayName: 'Run MegaLinter on $(repoName)'
49+
workingDirectory: $(repoName)
50+
51+
- script: |
52+
lizard --csv $(repoName)/src/ > $(Build.ArtifactStagingDirectory)/lizard-output.csv
53+
python src/converters/lizard-to-sarif.py \
54+
--input $(Build.ArtifactStagingDirectory)/lizard-output.csv \
55+
--output $(Build.ArtifactStagingDirectory)/complexity-$(appId).sarif
56+
displayName: 'Run complexity analysis on $(repoName)'
57+
58+
- task: AdvancedSecurity-Publish@1
59+
inputs:
60+
SarifFileDirectory: '$(Build.ArtifactStagingDirectory)'
61+
displayName: 'Publish SARIF to Advanced Security'
62+
63+
- task: PublishBuildArtifacts@1
64+
inputs:
65+
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
66+
ArtifactName: 'sarif-results-$(appId)'
67+
displayName: 'Publish SARIF artifacts'
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
trigger: none
2+
3+
pool:
4+
vmImage: 'ubuntu-latest'
5+
6+
variables:
7+
- template: variables/common.yml
8+
9+
stages:
10+
- stage: Deploy
11+
displayName: 'Deploy All Demo Apps'
12+
jobs:
13+
- job: DeployApp001
14+
displayName: 'Deploy cq-demo-app-001'
15+
steps:
16+
- template: templates/deploy-app.yml
17+
parameters:
18+
appName: 'cq-demo-app-001'
19+
resourceGroup: 'rg-cq-demo-001'
20+
appDir: 'cq-demo-app-001'
21+
22+
- job: DeployApp002
23+
displayName: 'Deploy cq-demo-app-002'
24+
steps:
25+
- template: templates/deploy-app.yml
26+
parameters:
27+
appName: 'cq-demo-app-002'
28+
resourceGroup: 'rg-cq-demo-002'
29+
appDir: 'cq-demo-app-002'
30+
31+
- job: DeployApp003
32+
displayName: 'Deploy cq-demo-app-003'
33+
steps:
34+
- template: templates/deploy-app.yml
35+
parameters:
36+
appName: 'cq-demo-app-003'
37+
resourceGroup: 'rg-cq-demo-003'
38+
appDir: 'cq-demo-app-003'
39+
40+
- job: DeployApp004
41+
displayName: 'Deploy cq-demo-app-004'
42+
steps:
43+
- template: templates/deploy-app.yml
44+
parameters:
45+
appName: 'cq-demo-app-004'
46+
resourceGroup: 'rg-cq-demo-004'
47+
appDir: 'cq-demo-app-004'
48+
49+
- job: DeployApp005
50+
displayName: 'Deploy cq-demo-app-005'
51+
steps:
52+
- template: templates/deploy-app.yml
53+
parameters:
54+
appName: 'cq-demo-app-005'
55+
resourceGroup: 'rg-cq-demo-005'
56+
appDir: 'cq-demo-app-005'
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
trigger: none
2+
3+
schedules:
4+
- cron: '0 7 * * 1'
5+
displayName: 'Weekly Monday 7 AM UTC (after scan)'
6+
branches:
7+
include:
8+
- main
9+
10+
pool:
11+
vmImage: 'ubuntu-latest'
12+
13+
variables:
14+
- template: variables/common.yml
15+
16+
strategy:
17+
matrix:
18+
app001:
19+
appId: '001'
20+
repoName: 'cq-demo-app-001'
21+
app002:
22+
appId: '002'
23+
repoName: 'cq-demo-app-002'
24+
app003:
25+
appId: '003'
26+
repoName: 'cq-demo-app-003'
27+
app004:
28+
appId: '004'
29+
repoName: 'cq-demo-app-004'
30+
app005:
31+
appId: '005'
32+
repoName: 'cq-demo-app-005'
33+
34+
steps:
35+
- checkout: self
36+
37+
- task: UsePythonVersion@0
38+
inputs:
39+
versionSpec: '3.12'
40+
41+
- script: |
42+
pip install lizard
43+
displayName: 'Install scanning tools'
44+
45+
- script: |
46+
npx mega-linter-runner --flavor dotnetweb -e VALIDATE_ALL_CODEBASE=true -e SARIF_REPORTER=true
47+
displayName: 'Run MegaLinter on $(repoName)'
48+
workingDirectory: $(repoName)
49+
50+
- script: |
51+
lizard --csv $(repoName)/src/ > $(Build.ArtifactStagingDirectory)/lizard-output.csv
52+
python src/converters/lizard-to-sarif.py \
53+
--input $(Build.ArtifactStagingDirectory)/lizard-output.csv \
54+
--output $(Build.ArtifactStagingDirectory)/complexity-$(appId).sarif
55+
displayName: 'Run complexity analysis'
56+
57+
- task: AzureCLI@2
58+
inputs:
59+
azureSubscription: '$(serviceConnection)'
60+
scriptType: 'pscore'
61+
scriptPath: 'scripts/scan-and-store.ps1'
62+
arguments: >-
63+
-StorageAccountName $(storageAccountName)
64+
-ContainerName $(containerName)
65+
-SarifDir $(Build.ArtifactStagingDirectory)
66+
-AppId $(appId)
67+
displayName: 'Upload SARIF results to ADLS Gen2'
68+
69+
- task: AdvancedSecurity-Publish@1
70+
inputs:
71+
SarifFileDirectory: '$(Build.ArtifactStagingDirectory)'
72+
displayName: 'Publish SARIF to Advanced Security'
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
trigger: none
2+
3+
pool:
4+
vmImage: 'ubuntu-latest'
5+
6+
variables:
7+
- template: variables/common.yml
8+
9+
stages:
10+
- stage: Approve
11+
displayName: 'Approve Teardown'
12+
jobs:
13+
- deployment: ApproveDestroy
14+
displayName: 'Approve Resource Destruction'
15+
environment: 'prod'
16+
strategy:
17+
runOnce:
18+
deploy:
19+
steps:
20+
- script: echo "Teardown approved"
21+
displayName: 'Teardown approval confirmed'
22+
23+
- stage: Teardown
24+
displayName: 'Teardown All Demo Apps'
25+
dependsOn: Approve
26+
jobs:
27+
- job: TeardownApp001
28+
displayName: 'Teardown cq-demo-app-001'
29+
steps:
30+
- template: templates/teardown-app.yml
31+
parameters:
32+
resourceGroup: 'rg-cq-demo-001'
33+
34+
- job: TeardownApp002
35+
displayName: 'Teardown cq-demo-app-002'
36+
steps:
37+
- template: templates/teardown-app.yml
38+
parameters:
39+
resourceGroup: 'rg-cq-demo-002'
40+
41+
- job: TeardownApp003
42+
displayName: 'Teardown cq-demo-app-003'
43+
steps:
44+
- template: templates/teardown-app.yml
45+
parameters:
46+
resourceGroup: 'rg-cq-demo-003'
47+
48+
- job: TeardownApp004
49+
displayName: 'Teardown cq-demo-app-004'
50+
steps:
51+
- template: templates/teardown-app.yml
52+
parameters:
53+
resourceGroup: 'rg-cq-demo-004'
54+
55+
- job: TeardownApp005
56+
displayName: 'Teardown cq-demo-app-005'
57+
steps:
58+
- template: templates/teardown-app.yml
59+
parameters:
60+
resourceGroup: 'rg-cq-demo-005'
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
parameters:
2+
- name: appName
3+
type: string
4+
- name: resourceGroup
5+
type: string
6+
- name: appDir
7+
type: string
8+
9+
steps:
10+
- checkout: self
11+
12+
- task: AzureCLI@2
13+
displayName: 'Create Resource Group'
14+
inputs:
15+
azureSubscription: '$(serviceConnection)'
16+
scriptType: 'bash'
17+
scriptLocation: 'inlineScript'
18+
inlineScript: |
19+
az group create --name ${{ parameters.resourceGroup }} --location $(location)
20+
21+
- task: AzureCLI@2
22+
displayName: 'Deploy Infrastructure'
23+
name: infra
24+
inputs:
25+
azureSubscription: '$(serviceConnection)'
26+
scriptType: 'bash'
27+
scriptLocation: 'inlineScript'
28+
inlineScript: |
29+
outputs=$(az deployment group create \
30+
--resource-group ${{ parameters.resourceGroup }} \
31+
--template-file ${{ parameters.appDir }}/infra/main.bicep \
32+
--parameters appName=${{ parameters.appName }} \
33+
--query 'properties.outputs' -o json)
34+
acrName=$(echo $outputs | jq -r '.acrName.value')
35+
appServiceName=$(echo $outputs | jq -r '.appServiceName.value')
36+
echo "##vso[task.setvariable variable=acrName;isoutput=true]$acrName"
37+
echo "##vso[task.setvariable variable=appServiceName;isoutput=true]$appServiceName"
38+
39+
- task: AzureCLI@2
40+
displayName: 'Build and Push to ACR'
41+
inputs:
42+
azureSubscription: '$(serviceConnection)'
43+
scriptType: 'bash'
44+
scriptLocation: 'inlineScript'
45+
inlineScript: |
46+
az acr build \
47+
--registry $(infra.acrName) \
48+
--image ${{ parameters.appName }}:$(Build.BuildId) \
49+
--image ${{ parameters.appName }}:latest \
50+
${{ parameters.appDir }}
51+
52+
- task: AzureCLI@2
53+
displayName: 'Deploy to Web App for Containers'
54+
inputs:
55+
azureSubscription: '$(serviceConnection)'
56+
scriptType: 'bash'
57+
scriptLocation: 'inlineScript'
58+
inlineScript: |
59+
az webapp config container set \
60+
--name $(infra.appServiceName) \
61+
--resource-group ${{ parameters.resourceGroup }} \
62+
--container-image-name $(infra.acrName).azurecr.io/${{ parameters.appName }}:$(Build.BuildId)
63+
64+
- task: AzureCLI@2
65+
displayName: 'Health Check'
66+
inputs:
67+
azureSubscription: '$(serviceConnection)'
68+
scriptType: 'bash'
69+
scriptLocation: 'inlineScript'
70+
inlineScript: |
71+
APP_URL=$(az webapp show -g ${{ parameters.resourceGroup }} -n $(infra.appServiceName) --query defaultHostName -o tsv)
72+
sleep 30
73+
curl -sf --retry 5 --retry-delay 10 "https://$APP_URL" || exit 1
74+
echo "✅ ${{ parameters.appName }} deployed to https://$APP_URL"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
parameters:
2+
- name: resourceGroup
3+
type: string
4+
5+
steps:
6+
- task: AzureCLI@2
7+
displayName: 'Delete Resource Group ${{ parameters.resourceGroup }}'
8+
inputs:
9+
azureSubscription: '$(serviceConnection)'
10+
scriptType: 'bash'
11+
scriptLocation: 'inlineScript'
12+
inlineScript: |
13+
echo "Deleting resource group ${{ parameters.resourceGroup }}..."
14+
az group delete --name ${{ parameters.resourceGroup }} --yes --no-wait
15+
echo "🗑️ Resource group ${{ parameters.resourceGroup }} deletion initiated."
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
variables:
2+
location: 'canadacentral'
3+
serviceConnection: 'code-quality-scan-demo-app-ado-sc'
4+
storageAccountName: 'stcqscandata'
5+
containerName: 'scan-results'
6+
adoOrg: 'MngEnvMCAP675646'
7+
adoProject: 'Agentic Accelerator Framework'

0 commit comments

Comments
 (0)