This commit is contained in:
Oli Passey
2025-06-27 11:12:24 +01:00
parent 191184ba5e
commit 448af85a38
4 changed files with 544 additions and 0 deletions

View File

@@ -0,0 +1,251 @@
trigger:
branches:
include:
- main
- develop
paths:
include:
- src/*
- templates/*
- requirements.txt
- Dockerfile
- config.json
- main.py
pr:
branches:
include:
- main
paths:
include:
- src/*
- templates/*
- requirements.txt
- Dockerfile
- config.json
- main.py
variables:
# Container registry service connection
dockerRegistryServiceConnection: 'dock-ptslondon-connection'
imageRepository: 'price-tracker'
containerRegistry: 'dock.ptslondon.co.uk'
dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
# Agent VM image name
vmImageName: 'ubuntu-latest'
stages:
- stage: Build
displayName: 'Build and Test'
jobs:
- job: Build
displayName: 'Build Docker Image'
pool:
vmImage: $(vmImageName)
variables:
tag: '$(Build.BuildId)'
steps:
- checkout: self
displayName: 'Checkout source code'
- task: Docker@2
displayName: 'Build Docker image'
inputs:
command: 'build'
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
tags: |
$(tag)
latest
- script: |
echo "Running container tests..."
# Start container for testing
docker run -d --name price-tracker-test -p 5000:5000 $(imageRepository):$(tag)
# Wait for container to be ready
echo "Waiting for container to start..."
for i in {1..30}; do
if curl -f http://localhost:5000/ > /dev/null 2>&1; then
echo "Container is ready!"
break
fi
echo "Waiting... ($i/30)"
sleep 2
done
# Run basic health checks
echo "Running health checks..."
curl -f http://localhost:5000/ || (echo "Health check failed" && exit 1)
# Cleanup
docker stop price-tracker-test
docker rm price-tracker-test
echo "All tests passed!"
displayName: 'Test Docker container'
- task: Docker@2
displayName: 'Push to registry'
inputs:
command: 'push'
repository: $(imageRepository)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
latest
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
- stage: SecurityScan
displayName: 'Security Scanning'
dependsOn: Build
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
jobs:
- job: VulnerabilityScan
displayName: 'Vulnerability Scan'
pool:
vmImage: $(vmImageName)
variables:
tag: '$(Build.BuildId)'
steps:
- task: Docker@2
displayName: 'Pull image for scanning'
inputs:
command: 'pull'
arguments: '$(containerRegistry)/$(imageRepository):$(tag)'
containerRegistry: $(dockerRegistryServiceConnection)
- script: |
# Install Trivy
sudo apt-get update
sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy -y
# Run vulnerability scan
trivy image --exit-code 0 --severity LOW,MEDIUM --format table $(containerRegistry)/$(imageRepository):$(tag)
trivy image --exit-code 1 --severity HIGH,CRITICAL --format table $(containerRegistry)/$(imageRepository):$(tag)
displayName: 'Run Trivy vulnerability scan'
continueOnError: true
- stage: DeployDev
displayName: 'Deploy to Development'
dependsOn:
- Build
- SecurityScan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
jobs:
- deployment: DeployToDev
displayName: 'Deploy to Development Environment'
environment: 'price-tracker-dev'
pool:
vmImage: $(vmImageName)
variables:
tag: '$(Build.BuildId)'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: Docker@2
displayName: 'Pull latest image'
inputs:
command: 'pull'
arguments: '$(containerRegistry)/$(imageRepository):$(tag)'
containerRegistry: $(dockerRegistryServiceConnection)
- script: |
# Create deployment directory
mkdir -p ~/price-tracker-deployment
cd ~/price-tracker-deployment
# Copy deployment files
cp $(Pipeline.Workspace)/s/docker-compose.yml .
cp $(Pipeline.Workspace)/s/config.json .
# Update image tag in docker-compose
sed -i "s/price-tracker:latest/$(containerRegistry)\/$(imageRepository):$(tag)/g" docker-compose.yml
# Deploy using docker-compose
docker-compose down || true
docker-compose up -d
# Wait for deployment
sleep 10
# Verify deployment
curl -f http://localhost:5000/ || (echo "Deployment verification failed" && exit 1)
echo "Deployment to development completed successfully!"
displayName: 'Deploy to development'
- stage: DeployProd
displayName: 'Deploy to Production'
dependsOn:
- Build
- SecurityScan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToProd
displayName: 'Deploy to Production Environment'
environment: 'price-tracker-prod'
pool:
vmImage: $(vmImageName)
variables:
tag: '$(Build.BuildId)'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- task: Docker@2
displayName: 'Pull latest image'
inputs:
command: 'pull'
arguments: '$(containerRegistry)/$(imageRepository):$(tag)'
containerRegistry: $(dockerRegistryServiceConnection)
- script: |
# Production deployment script
echo "Deploying to production..."
# Create deployment directory
mkdir -p ~/price-tracker-production
cd ~/price-tracker-production
# Copy deployment files
cp $(Pipeline.Workspace)/s/docker-compose.yml .
cp $(Pipeline.Workspace)/s/config.json .
# Update image tag in docker-compose for production
sed -i "s/price-tracker:latest/$(containerRegistry)\/$(imageRepository):$(tag)/g" docker-compose.yml
# Production-specific environment settings
export FLASK_ENV=production
# Deploy with zero-downtime strategy
docker-compose pull
docker-compose up -d
# Health check
sleep 15
for i in {1..10}; do
if curl -f http://localhost:5000/; then
echo "Production deployment successful!"
break
fi
echo "Waiting for production deployment... ($i/10)"
sleep 5
done
displayName: 'Deploy to production'
- script: |
# Post-deployment notifications (optional)
echo "Production deployment completed at $(date)"
# You can add notification webhooks here
displayName: 'Post-deployment tasks'