Skip to content

Latest commit

 

History

History
194 lines (166 loc) · 8.28 KB

example-project.adoc

File metadata and controls

194 lines (166 loc) · 8.28 KB

Example Project

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.

Overview

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.

Pipeline Configuration

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.

Promotion

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.