diff --git a/Artifact-to-ADO-feed.yml b/Artifact-to-ADO-feed.yml new file mode 100644 index 000000000..0f1510ed5 --- /dev/null +++ b/Artifact-to-ADO-feed.yml @@ -0,0 +1,48 @@ + +pool: + vmImage: 'ubuntu-latest' + +variables: + feedName: 'Test-feed' # <-- Replace with your Azure Artifacts feed + packageName: 'flask-sample-app' # <-- Name for the universal package + packageVersion: '1.0.$(Build.BuildId)' + +steps: + +# 1️⃣ Checkout your GitHub repo +- checkout: self + displayName: 'Checkout repository' + +# 2️⃣ Optional: Debug repo contents +- script: | + echo "Repo root: $(Build.SourcesDirectory)" + echo "Contents:" + ls -la $(Build.SourcesDirectory) + displayName: 'List repo root contents' + +# 3️⃣ Ensure artifact staging directory exists +- script: mkdir -p $(Build.ArtifactStagingDirectory) + displayName: 'Ensure artifact staging directory exists' + +# 4️⃣ Archive the entire repo into a zip +- task: ArchiveFiles@2 + inputs: + rootFolderOrFile: '$(Build.SourcesDirectory)' # <-- This is the correct folder + includeRootFolder: false # <-- Include only contents + archiveType: 'zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/flask-app.zip' + replaceExistingArchive: true + displayName: 'Archive repository' + +# 5️⃣ Publish the zip as a Universal Package +- task: UniversalPackages@0 + inputs: + command: publish + publishDirectory: '$(Build.ArtifactStagingDirectory)' + feedsToUsePublish: 'internal' + vstsFeedPublish: 'DevOpsAZ400 Pratice (Agile one)/Test-Feed' + vstsFeedPackagePublish: '$(packageName)' + versionOption: 'custom' + versionPublish: '$(packageVersion)' + packagePublishDescription: 'Simple Flask sample app packaged as Universal Package' + displayName: 'Publish Universal Package' diff --git a/Deploy-SQL.yml b/Deploy-SQL.yml new file mode 100644 index 000000000..7eef0c3a0 --- /dev/null +++ b/Deploy-SQL.yml @@ -0,0 +1,110 @@ +trigger: +- main + +variables: + resourceGroup: my-sql-rg + location: uksouth + sqlServer: mysqlserver12345 + sqlDatabase: mydatabase + adminUser: sqladmin + adminPassword: $(SQL_ADMIN_PASSWORD) + dacpacPath: $(Build.SourcesDirectory)/database/database.dacpac + +stages: +- stage: DeploySQL + jobs: + + - job: CheckResourceGroup + pool: + vmImage: ubuntu-latest + steps: + - task: AzureCLI@2 + inputs: + azureSubscription: 'SPN-Dev-01' + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + if az group exists --name $(resourceGroup); then + echo "Resource Group already exists" + else + az group create --name $(resourceGroup) --location $(location) + fi + + - job: CheckSQLServer + dependsOn: CheckResourceGroup + pool: + vmImage: ubuntu-latest + steps: + - task: AzureCLI@2 + inputs: + azureSubscription: 'SPN-Dev-01' + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + if az sql server show --name $(sqlServer) --resource-group $(resourceGroup) > /dev/null 2>&1; then + echo "SQL Server already exists" + else + az sql server create \ + --name $(sqlServer) \ + --resource-group $(resourceGroup) \ + --location $(location) \ + --admin-user $(adminUser) \ + --admin-password $(adminPassword) + fi + + - job: CheckDatabase + dependsOn: CheckSQLServer + pool: + vmImage: ubuntu-latest + steps: + - task: AzureCLI@2 + inputs: + azureSubscription: 'SPN-Dev-01' + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + if az sql db show --name $(sqlDatabase) --server $(sqlServer) --resource-group $(resourceGroup) > /dev/null 2>&1; then + echo "Database already exists" + else + az sql db create \ + --resource-group $(resourceGroup) \ + --server $(sqlServer) \ + --name $(sqlDatabase) \ + --service-objective S0 + fi + + - job: ConfigureFirewall + dependsOn: CheckDatabase + pool: + vmImage: ubuntu-latest + steps: + - task: AzureCLI@2 + inputs: + azureSubscription: 'SPN-Dev-01' + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + az sql server firewall-rule create \ + --resource-group $(resourceGroup) \ + --server $(sqlServer) \ + --name AllowAllAzureIPs \ + --start-ip-address 0.0.0.0 \ + --end-ip-address 0.0.0.0 + + - job: DeployDacpac + dependsOn: ConfigureFirewall + pool: + vmImage: ubuntu-latest + steps: + - task: SqlAzureDacpacDeployment@1 + displayName: Deploy DACPAC + inputs: + azureSubscription: 'SPN-Dev-01' + AuthenticationType: server + ServerName: $(sqlServer).database.windows.net + DatabaseName: $(sqlDatabase) + SqlUsername: $(adminUser) + SqlPassword: $(adminPassword) + deployType: DacpacTask + DeploymentAction: Publish + DacpacFile: $(dacpacPath) \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 000000000..20a7b246b --- /dev/null +++ b/app.py @@ -0,0 +1,7 @@ +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def home(): + return "Hello from Flask!If you can see this, the code has been deployed to your webapp. Test to see if all pipelines run again 2x" diff --git a/delete.yml b/delete.yml new file mode 100644 index 000000000..f53e97b6b --- /dev/null +++ b/delete.yml @@ -0,0 +1,19 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: ubuntu-latest + +steps: +- script: echo Hello, world! + displayName: 'Run a one-line script' + +- script: | + echo Add other tasks to build, test, and deploy your project. + echo See https://aka.ms/yaml + displayName: 'Run a multi-line script' diff --git a/environments-play.yml b/environments-play.yml new file mode 100644 index 000000000..68e575340 --- /dev/null +++ b/environments-play.yml @@ -0,0 +1,40 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +#trigger removed to avoid it all running and taking up microsoft agents + +pool: + vmImage: ubuntu-latest + +stages: +#Build Stage +- stage: Build + jobs: + - job: BuildJob + steps: + - script: echo "Hey there, this is the building stage!" +#Dev Environment +- stage: Dev + dependsOn: Build + jobs: + - deployment: DeployDev + environment: Dev + strategy: + runOnce: + deploy: + steps: + - script: echo "Deploying to Dev!" + +#Prod Environment +- stage: Prod + dependsOn: Dev + jobs: + - deployment: DeployProd + environment: Prod + strategy: + runOnce: + deploy: + steps: + - script: echo "Deploying to Prod!" diff --git a/k8s.yaml b/k8s.yaml new file mode 100644 index 000000000..97d927433 --- /dev/null +++ b/k8s.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flaskapp +spec: + replicas: 1 + selector: + matchLabels: + app: flaskapp + template: + metadata: + labels: + app: flaskapp + spec: + containers: + - name: flaskapp + image: myacr12345gd.azurecr.io/flaskapp:v1 + ports: + - containerPort: 5000 + +--- +apiVersion: v1 +kind: Service +metadata: + name: flaskapp-service +spec: + type: LoadBalancer + selector: + app: flaskapp + ports: + - port: 80 + targetPort: 5000 diff --git a/requirements.txt b/requirements.txt index e3e9a71d9..cdd7590ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -Flask +Flask==2.3.0 +gunicorn==20.1.0 diff --git a/schema.sql b/schema.sql new file mode 100644 index 000000000..017554ee4 --- /dev/null +++ b/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE Users ( + Id INT PRIMARY KEY, + Name NVARCHAR(100), + Email NVARCHAR(100) +); + +INSERT INTO Users (Id, Name, Email) +VALUES (1, 'Test User', 'test@email.com'); diff --git a/test-and-coverage-report.yml b/test-and-coverage-report.yml new file mode 100644 index 000000000..fbb11b64e --- /dev/null +++ b/test-and-coverage-report.yml @@ -0,0 +1,36 @@ + +pool: + vmImage: ubuntu-latest + +jobs: +- job: TestAndCoverage + displayName: 'Run Python Tests and collect Coverage' + strategy: + matrix: + Python38: + python.version: '3.8' + Python39: + python.version: '3.9' + steps: + # Install Python and the coverage checker + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python.version)' + + - script: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pytest pytest-cov + displayName: 'Install dependencies' + + # Run tests and collect coverage + - script: | + pytest --cov=. --cov-report=xml + displayName: 'Run Tests and Coverage' + + # Publish coverage results + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: 'Cobertura' + summaryFileLocation: 'coverage.xml' + displayName: 'Publish Code Coverage to ADO' diff --git a/web-app-creation-and-app-deployment.yml b/web-app-creation-and-app-deployment.yml new file mode 100644 index 000000000..65cc7fcae --- /dev/null +++ b/web-app-creation-and-app-deployment.yml @@ -0,0 +1,77 @@ +# Pipeline to create webapp, build, deploy, and reminder + +pool: + vmImage: ubuntu-latest + +stages: +# =============================== +# Stage 1: Create Web App +# =============================== +- stage: CreateWebApp + displayName: Create Web App on Azure + jobs: + - job: CreateApp + displayName: Create app via CLI + steps: + - task: AzureCLI@2 + displayName: "Create Web App if not exists" + inputs: + azureSubscription: SPN-Dev-01 + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + if az webapp show --name flaskappgmd28 --resource-group AZ400-play &>/dev/null; then + echo "Web app already exists, skipping creation" + else + az webapp create --resource-group AZ400-play --plan ASP-AzureAppIncidentProjectgroup-8d3f --name flaskappgmd28 --runtime "PYTHON:3.10" + fi + +# =============================== +# Stage 2: Build Python App +# =============================== +- stage: BuildApp + displayName: 'Build Python Stage' + dependsOn: CreateWebApp + jobs: + - job: BuildAppOnDevops + displayName: 'Build App on DevOps' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.10' + addToPath: true + - script: | + python -m pip install --upgrade pip + pip install -r requirements.txt + displayName: 'Install dependencies' + +# =============================== +# Stage 3: Deploy App +# =============================== +- stage: DeployApp + displayName: 'Deploy App Stage' + dependsOn: BuildApp + jobs: + - job: DeployToAzure + displayName: 'Deploy Build App to Azure' + steps: + - task: AzureWebApp@1 + inputs: + azureSubscription: SPN-Dev-01 + appType: webApp + appName: flaskappgmd28 + package: '$(System.DefaultWorkingDirectory)' + startupCommand: 'gunicorn --bind 0.0.0.0:8000 app:app' + +# =============================== +# Stage 4: Reminder +# =============================== +- stage: ReminderToDelete + displayName: 'Reminder to delete' + dependsOn: DeployApp + jobs: + - job: Reminder + displayName: 'Text reminder' + steps: + - script: | + echo "Delete or at least stop"