The goal of this document is to provide a concrete example how a complete application can be built and deployed using ods-pipeline
. You may configure things differently for your own project, but the example here contains some best practices and you are encouraged to align your setup where it makes sense.
For this example, we assume that we deal with a simple todo application. The project key in Bitbucket is TODO
. The application is made up of two components, a backend (repository todo-backend
) written in Go, and a frontend (repository todo-frontend
) written in TypeScript.
The example project is deployed on a single OpenShift cluster which has three OpenShift projects to deploy into: todo-dev
, todo-qa
and todo-prod
. ODS Pipelines is installed in the todo-cd
project as per the Installation Guide.
The backend and frontend components are configured to build and package the component on all branches. This gives developers confidence that changes to the application in pull requests can be built and that all tests pass. Further, it ensures that linting, static code analysis, security vulnerability checks etc. are executed and feedback is available in the pull request.
Pushes to the master
branch should deploy the respective component directly into todo-dev
. This is achieved by the following ODS pipeline configuration:
todo-backend/.ods.yaml
pipelines:
- triggers:
- branches: ["master"]
params:
- name: finish.artifact-target
value: dev-artifacts
- name: deploy.namespace
value: todo-dev
- branches: ["*"]
tasks:
- name: build
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-go.git }
- { name: revision, value: v0.1.2 }
- { name: pathInRepo, value: tasks/build.yaml }
workspaces:
- name: source
workspace: shared-workspace
- name: package
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-image.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/package.yaml }
runAfter:
- build
workspaces:
- name: source
workspace: shared-workspace
- name: deploy
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-helm.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/deploy.yaml }
runAfter:
- package
workspaces:
- name: source
workspace: shared-workspace
todo-frontend/.ods.yaml
pipelines:
- triggers:
- branches: ["master"]
params:
- name: finish.artifact-target
value: dev-artifacts
- name: deploy.namespace
value: todo-dev
- branches: ["*"]
tasks:
- name: build
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-npm.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/build.yaml }
workspaces:
- name: source
workspace: shared-workspace
- name: package
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-image.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/package.yaml }
runAfter:
- build
workspaces:
- name: source
workspace: shared-workspace
- name: deploy
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-helm.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/deploy.yaml }
runAfter:
- package
workspaces:
- name: source
workspace: shared-workspace
Both pipelines are almost identical, only the build task differs. Both Bitbucket repositories have a webhook configured, pointing to the event listener in the todo-cd
namespace.
Both Bitbucket repositories contain a Helm chart (in the chart
directory). The Helm chart contains default values in values.yaml
. Values that only apply to the todo-dev
environment are stored in values.todo-dev.yaml
.
Events triggered from pushes in the master
branch set the namespace
parameter of the deploy`
task, which tells Helm to deploy into this namespace. The trigger also sets the artifact-target
parameter of the finish
task which is automatically added to each pipeline run. This causes the task to upload all created artifacts into the dev-artifacts
Nexus repository. This repository has to be created in Nexus upfront.
In order to deploy the application into todo-qa
and todo-prod
, another repository is used, serving as an "umbrella" for the whole application. This repository is named todo-app
.
Typically, it is desired that the artifacts such as container images are not rebuilt for each environment. To assist with this, the component pipelines configured their master
branch pipeline to upload artifacts into the dev-artifacts
Nexus repository. The configuration in todo-app
makes use of the previously uploaded artifacts by referencing this repository as the artifact source of the pipeline.
todo-app/.ods.yaml
repositories:
- name: todo-backend
branch: master
- name: todo-frontend
branch: master
pipelines:
- triggers:
- branches: ["master"]
params:
- name: start.artifact-source
value: qa-artifacts
- name: finish.artifact-target
value: prod-artifacts
- name: deploy.namespace
value: todo-prod
- branches: ["*"]
params:
- name: start.artifact-source
value: dev-artifacts
- name: finish.artifact-target
value: qa-artifacts
- name: deploy.namespace
value: todo-qa
tasks:
- name: deploy
taskRef:
resolver: git
params:
- { name: url, value: https://github.com/opendevstack/ods-pipeline-helm.git }
- { name: revision, value: v0.1.0 }
- { name: pathInRepo, value: tasks/deploy.yaml }
workspaces:
- name: source
workspace: shared-workspace
When a commit is pushed into any branch except the master
branch, a deploy is triggerd into the todo-qa
project. The deployment uses the Helm chart defined in the todo-app
repository. That chart does not contain any resource templates itself, as all Kubernetes resources are defined in the charts in the components todo-backend
and todo-frontend
. However, the umbrella chart has to supply values which are specific to the todo-qa
namespace. This can be done via a values.todo-qa.yaml
file. Values in that file can set values for subcharts (like the backend
component) by nesting the values under the respective key, as shown in the following example. Assume we have the following values.yaml
file in the todo-backend
application:
todo-backend/chart/values.yaml
max_connections: 10
The todo-app
repository can set a different value for the QA environment like this:
todo-app/chart/values.todo-qa.yaml
backend:
max_connections: 20
For more information on this, see scope, dependencies, and values.
The todo-prod
environment is configured in the same way as the todo-qa
environment. Any pushes into the master
branch will trigger a deployment into "prod".
The configuration of the different Nexus repositories (component master
pipeline runs pushing into dev-artifacts
, todo-app
non-master
pipelines runs pushing into qa-artifacts
and todo-app
master
pipelines pushing into prod-artifacts
) has the benefit that ODS Pipelines prevents deployments into the PROD environment without a prior deployment into the QA environment. This is ensured through the start
task, which checks for successful pipeline runs of all configured subrepositories when the artifact-source
parameter is provided.
Note
|
In this example, merges into the master branch in the todo-app repository must be done using a fast-forward merge. If a merge commit were created, the start task would not find a successful pipeline run artifact for this new commit hash and fail. This is by design to protect from accidental changes to the master branch.
|