Pipeline workflows
The process of building to deploy in production a project happens in four stages:
flowchart LR
build(Build):::orange --> deployPrev(Deploy to preview)
deployPrev --> signoff(Validate & sign-off):::blue
signoff --> deployPRod(Deploy to production):::green
classDef orange fill:#ffe6cc,stroke:#d79e0f
classDef blue fill:#dae8fc,stroke:#7e9bc5
classDef green fill:#d5e8d4,stroke:#96be7f
The continuous integration pipeline will run our build orchestrator targets. The build system does everything needed except setting up the build environment.
Build
This stage happens for every type of build. Here we build all the deliveries and run automated tests. This is the core of the build system that developers will run locally as well as to validate pull requests.
---
title: Build
---
flowchart LR
prepare[Prepare environment] --> build[Build and test deliveries\nTarget 'Default']
build --> bundle[Bundle deliveries\nTarget 'Bundle']
bundle --> upload[Upload deliveries to CI]
classDef default fill:#ffe6cc,stroke:#d79e0f
Prepare environment
Setting up the building environment involves:
---
title: Prepare build environment
---
flowchart LR
classDef default fill:#ffe6cc,stroke:#d79e0f
clone[Get source code] --> sdks[Install .NET SDK]
sdks --> orch[Build orchestrator]
In most projects the steps to setup a dev environment are simple and the cost of automatizing may be larger. Consider this new technologies for it:
Build and test deliveries
The process of building and testing should be provided by the build system. The process is usually very similar for each technology or project delivery type. Consider implementing these steps for each delivery: .NET, Node.JS, DocFX docs, MSI installers, ...
---
title: Build and test per technology
---
flowchart LR
classDef default fill:#ffe6cc,stroke:#d79e0f
sdk[Install tech SDKs] --> restore[Restore dependencies\nConsider caching]
restore --> version[Define versiong]
version --> build[Build]
build --> test["Run tests\n(with code coverage)"]
test --> linter[Run linters\nCreate QA report]
linter --> bundle[Bundle artifacts]
Tip
You may want to skip some steps if you repeating the process on multiple platforms (e.g. testing cross-platform). For instance you may want to bundle only from one platform but run the tests in all of them.
Deploy
This stage only happens for preview and stable builds. From the proposed git flow this means that it starts when there are new commits in the main and release branch (if used).
---
title: Deploy (main branch)
---
flowchart LR
download[Download CI artifacts]
download --> deployNuGet[Deploy to preview / staging\nTarget 'Deploy']
Simple release variant
On small projects we can skip having a release branch at the expense of having to re-build the project. We can have a simple workflow from GitHub as follow:
---
title: Deploy (main branch)
---
flowchart LR
classDef blue fill:#dae8fc,stroke:#7e9bc5
classDef green fill:#d5e8d4,stroke:#96be7f
. --> tests[Run manual tests]:::blue
tests --> docs[Create GitHub release\nFill release notes]:::blue
docs --> signoff[Sign-off by\nconfirming release]:::blue
signoff --> tag[GitHub creates\nthe git tag]:::green
tag --> rebuild[New build & test flow\nrebuilding with final version]:::green
rebuild --> deployProd[Deploy to production\nTarget 'Deploy']:::green
Release branch variant
If the build is happening from a release branch then it's a release candidate, a potential stable build. The pipeline then blocks waiting for the user approval before resuming deploying to production.
---
title: Deploy (release branch)
---
flowchart LR
classDef blue fill:#dae8fc,stroke:#7e9bc5
classDef green fill:#d5e8d4,stroke:#96be7f
. --> tests[Run manual tests]:::blue
tests --> docs[Create release notes]:::blue
docs --> signoff[Sign-off]:::blue
signoff --> tag[Git tag]:::green
tag --> deployProd[Deploy to production\nTarget 'Deploy']:::green
The step to create release notes and sign-off may be different depending the project requirements. Some strategies:
- GitHub: it provides a way to create releases with its release notes.
PleOps Cake provides
tasks to export the release notes
from the current GitHub Release. This allows to use the feature of GitHub to
generate them automatically and then adjust manually. You can also use it as a
sign-off:
- Run the build pipeline and validate the artifacts.
- Create a GitHub release with the desired version number. Fill the release notes.
- Confirming the GitHub release will create a git tag, triggering the build pipeline.
- This pipeline will detect it's building from a git tag, deploying this time to production feeds.
- Consider reviewing GitHub Actions manual approvals
- Azure DevOps: it provides a
manual approval task.
The workflow would be then:
- Create the release notes documents as part of the development work (on each PR).
- The pipeline from release branches will finish with a manual approval task.
- Run tests and approve the task once it's ready.
- The pipeline will continue deploying to production.
Tip
One interesting design goal we should achieve is the ability to deploy in production without rebuilding the project. That is, the binaries we deploy are exactly the same we have tested and approved. This has several implications that affects the git flow and versioning. The proposed versioning and git flow (when using a release branch) support this scenario.
Tip
If you use Azure DevOps, consider retaining your build and release pipeline for traceability.