TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.
This project will create all of the required infrastructure in Azure programatically. The resoureces in the TDD environment will be torn down after automated testing is completed. The UAT and Prod resources will remain. There is an Octopus variable EnsureEnvironmentsExist that will tell Octopus to create all of the resources. If the variable is set to True Octopus will create all of the resources, if the variable is set to something else, Octopus will not create the resources. EnsureEnvironmentsExist should always be set to True for the TDD environment. This variable should be set to False (or anything other than True) for UAT and Prod to save time and preserve the existing resources during subsequent deployments.
- Github
- Azure
- Octopus Deploy Environment Setup:
- Octopus Deploy Project Setup:
- Azure DevOps Setup:
- Octopus Deploy Runbook Setup:
Requirements:
- Octopus Deploy
- Azure
- Github
- Azure DevOps
Create a new repository using the onion-architecture-maui-azure-dotnet-8 template repo
Name the resource group something identifiable and different than the application environments. e.g. onion-architecture-container-apps-acr The resource groups for the application environments will be created and destroyed programatically, the container registry should be kept separate.
When creating the container registry, a Basic SKU is sufficient. Name the container registry something identifiable. e.g. onion-architecture-container-apps
- In Azure AD select App Registrations
- Select New Registration
- Name the Registration something identifiable. e.g. Onion-Containers-Octo
- A Redirect URI is not needed
- Select Register
- Select Certificates and Secrets
- New Client Secret
- Provide a description and select add
- Save the client secret Value. It will be used in Octopus.
- In your Azure subscription, navigate to Access Control (IAM), and add a role assignment
- Select Privileged administrator roles, then Contributor
- In the Members tab use the + Select Members page to select the App Registration that was created
- Press Review + assign
- Press Review + assign again to save
- In Octopus Deploy navigate to Infrastructure -> Accounts
- Add an Azure Subscription Account
- Name the account Azure-Onion-Containers
- Fill in the Subscription ID
- This can be found in the Subscription Overview page in the Azure web portal
- Leave the Authentication Method as 'Use a Service Principal'
- Fill in the Tenant ID
- This can be found in the Overview page of the App Registration in the Azure web portal
- Fill in the Application ID
- This is the Application (client) ID from the App registration that was just created. This can be found in the Overview page in the Azure web portal
- Fill in the Application Password / Key
- This is the client secret value that was created previously
In Octopus Deploy create 3 environments.
- TDD
- UAT
- Prod
No Deployment targets need to be created.
Create a Lifecycle that uses those three environments promoting from TDD -> UAT -> Prod
Create a Personal Access Token with repo access only. Save the token for use in Octopus
Create Git Credentials using the GitHub Personal Access Token
- Create a new project, ensure the "Use version control for this project" box is checked
- Use the Lifecycle that was just created
-
Click Save AND CONFIGURE VCS
- Skip the "How do you intend to use this project" popup
-
Set the Git Repository URL to the URL of the forked repo
-
Use the Library Git Credentials that were created earlier
- Click CONFIGURE and push the initial commit to convert the project
In the deployment process Octopus will setup Azure App Insights to monitor the availability of the app. If the healthcheck endpoint returns unhealthy an alert will be created that triggers an Octopus Runbook. To configure the Runbook integration:
- There is a variable in the project named OctoRunbookName this is the name of the Runbook that Azure will run. Create a Runbook with the same name. e.g. Unhealthy app alert
- In the project create a variable named azrunbookAPI Set the value to Sensitive and provide an API key that has access to the project
- Update OctoInstanceURL with the URL of your Octopus instance
Create a new project
Install the Octopus Deploy Integration (https://marketplace.visualstudio.com/items?itemName=octopusdeploy.octopus-deploy-build-release-tasks)
To create a service connection
- Go to Project Settings in the bottom left
- Under the Pipelines heading, select Service Connections
- Select Create Service Connection
- Select Azure Resource Manager as the new service connection type
- Use the Service Principal (automatic) authentication method
- Select your Azure Subscriptoin
- Leave the Resource Group section blank
- Name the Service Connection: onion-architecture-maui-azure-dotnet-8
- Check 'Grant access permission to all pipelines'
- Save the service connection
- In Octopus Deploy create an API key (https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key)
- In Azure DevOps select New Service Connection, choose Octopus Deploy as the type
- Fill in the URL of your Octopus instance
- Fill in the API key that was created
- Name the service connection: OctoServiceConnection
- Check 'Grant access permission to all pipelines'
- Save the service connection
- Select New Service Connection, choose Docker Registry as the type
- Configure the registry
- Choose Azure Container Registy as the type
- Choose Service Principal as the Authentication Type
- Select your Azure Subscription
- Select the container registry that was created
- Name the service connection: OnionArchACRServiceConnection
- Select 'Grant access permission to all pipelines'
- Save the Service Connection
- In the Azure DevOps project: Go to Artifacts, then select + Create Feed
- Name the feed something relevant, scope it to the current project, select create
- Set the Project Build Service identity to be a Contributor on your feed (https://learn.microsoft.com/en-us/azure/devops/artifacts/feeds/feed-permissions?view=azure-devops#configure-feed-settings)
- Create an Azure DevOps Personal Access Token https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows
- Give the token the Packaging Read scope
- Save the token for use in Octopus
- Navigate to the Artifacts page.
- Select the 'Connect to Feed' button
- Select Nuget.exe as the feed type
- In the Project Setup section, copy the URL from the value field
- Navigate to Library -> External Feeds and select ADD FEED
- Set the Feed type to NuGet Feed
- Name the feed Onion-Architecture-MAUI-Azure-dotnet-8
- Paste in the URL that was copied from Azure DevOps
- Provide something in the Feed username field. It can be anything other than an empty string. It's not actually used.
- Provide the personal access token from Azure DevOps as the Feed Password
In the Octopus Project navigate to Variables -> Project
- Create a variable named DatabasePassword Set the values to Sensitive and enter passwords for TDD, UAT, and Prod environments
- Update registry_login_server to the login server of the Azure Container Registry that was created
- This login server can be found in the Overview page of the container registry in the Azure Web Portal
- Update EnsureEnvironmentsExist to True for Prod/UAT to ensure that all resources will be created the first time.
- In the Azure DevOps project: Go to Pipelines -> Library
-
Create a variable group named Integration-Build
- Create a variable called FeedName. The value will be <Azure DevOps project name>/<Azure DevOps feed name>
- Create a variable called OctoProjectGroup with the value being the Project Group that houses your Octopus Project.
- Create a variable called OctoProjectName with the value being the name of your Octopus Project.
- Create a variable called OctoSpace with the value being the name of your Octopus Space.
- Save the variable group
- From the variable group page select the Pipeline permissions tab at the top
- Select the hamburger menu, and select Open Access
- Select Open access to allow all pipelines in the project to use the variable group
- Go to Pipelines -> Environments
- Select New environment
- Create three environments.
- TDD
- UAT
- Prod
- In the UAT and Prod environments, add an approval check and select the users that need to approve the appropriate deploy stages.
- Go to Pipelines -> Pipelines
- Select Create Pipeline
- Select Github as the location for your code
- Accept and allow Github and Azure DevOps to connect
- Select the forked repo when asked to select a repository
- Select Approve & Install to allow Azure Pipelines to connect to GitHub
- When reviewing the pipeline YAML select Run to create and run the Pipeline for the first time
The pipeline will build the application, create all of the resources in the TDD environment, deploy the app to TDD, test the app, then destroy the TDD resources. Then the Azure resources in UAT will be created, and the app will be deployed to TDD. Ultimately Prod resources will be created, and the app will be deployed to Prod
In the ChurchBulletin.Scripts package that is created there is a script called ScaleInfrastructure.ps1. When provided with appReplicas and/or serviceObjective values the script will set the min and max number of replicas of the container app and the service objective of the database. This is used with Octopus Runbooks (Runbooks Documentation) to scale up and down the infrastructure for day and nighttime loads.
In your Octopus Deploy project, create two new variables
- ContainerAppScaledUpReplicas and give it an integer value. e.g. 2
- ContainerAppScaledUpCPU and give it a float value. e.g. 0.5
- ContainerAppScaledUpMem and give it a float value. e.g. 1.0
- DBScaledUpPerformanceLevel and give it service objective value. e.g. S0
Commit these variables to main. Variables not in the default branch will not be accessible to runbooks
-
In your Octopus Deploy project, navigate to Operations -> Runbooks and select ADD RUNBOOK
-
Name the runbook Scale Up Infrastructure
-
Select DEFINE YOUR RUNBOOK PROCESS near the upper right
-
And then select ADD STEP
-
Use the run az Azure Script step template
-
Select ADD
-
Name the step Scale Up Infrastructure
-
Leave Execution Location, Worker Pool, Container Image, and Azure Tools as default
-
Under Azure -> Account select the chain links icon to bind the account value to a variable. Then set the value to #{AzureAccount}
- Under Script Source select Script file inside a package
- Under Script File in Package set the Package feed to the feed that was created.
- Set the Package ID to ChurchBulletin.Script
- Set the Script file name to ScaleInfrastructure.ps1
- Set the Script parameters to -appReplicas #{ContainerAppScaledUpReplicas} -cpu #{ContainerAppScaledUpCPU} -mem #{ContainerAppScaledUpMem} -serviceObjective #{DBScaledUpPerformanceLevel}
Leave the rest of the settings at default, and select SAVE
Create another runbook named Scale Down Container App using the same directions.
- Change the Step Name to Scale Down Infrastructure
- Leave the Script Parameters blank
Runbooks must be published before they can be consumed by triggers.
- Navigate to the Scale Up Infrastructure runbook. Select PUBLISH
- Leave the default settings, and select PUBLISH
- Do the same for Scale Down Infrastructure
(Runbook Triggers Documentation)
- Navigate to Operations -> Triggers
- Select ADD SCHEDULED TRIGGER
- Name the trigger Scale Up Morning
- Under Runbook select Scale Up Infrastructure
- Under Target Environments select Prod
- Leave the schedule at Daily
- Under Run Days uncheck Saturday and Sunday
- Set Schedule Timezone to your timezone
- Leave the Interval at once
- Set the Start Time to 8:00 AM
- Click Save
- Create another trigger named Scale Down Evening
- Use the Scale Down Container App runbook
- Under Target Environments select Prod
- Under Run Days uncheck Saturday and Sunday
- Set Schedule Timezone to your timezone
- Set the Start Time to 6:00 PM
- Click Save
Now the container app and database will automatically be scaled up every morning, and scaled down every evening
TODO: Describe and show how to build your code and run the tests.
TODO: Explain how other users and developers can contribute to make your code better.
If you want to learn more about creating good readme files then refer the following guidelines. You can also seek inspiration from the below readme files: