Skip to content

Latest commit

 

History

History
153 lines (126 loc) · 7.42 KB

convert-quickstarter-component.adoc

File metadata and controls

153 lines (126 loc) · 7.42 KB

Converting an ODS quickstarter based component from Jenkins to ODS Pipeline

This guide explains how you can start to use ODS pipeline in a repository that has been created through an ODS quickstarter, and therefore uses Jenkins as CI/CD solution. It is assumed you have read the introduction and have aleady installed ODS pipeline in an OpenShift project.

The following assumes that you have selected the Go quickstarter and have a repository named foo-backend in your Bitbucket project. Other quickstarters are converted following the same steps, simply adjust the instructions below.

On a high level, converting an ODS component consists of the following steps:

  1. Replace Jenkinsfile with ods.yaml

  2. Create Helm Chart

  3. Configure Webhook

Replace Jenkinsfile with ods.yaml

The Jenkinsfile describes the Jenkins pipeline to run using stages provided by the ODS Jenkins Shared Library as well as custom Go tool instructions. The file might look like this:

Jenkinsfile
@Library('[email protected]') _

odsComponentPipeline(
  imageStreamTag: 'ods/jenkins-agent-golang:4.x',
  branchToEnvironmentMapping: [
    'master': 'dev',
  ]
) { context ->
  odsComponentStageImportOpenShiftImageOrElse(context) {
    stageCheckFormat(context)
    stageLint(context)
    stageUnitTest(context)
    stageBuild(context)
    odsComponentStageScanWithSonar(context)
    odsComponentStageBuildOpenShiftImage(context)
  }
  odsComponentStageRolloutOpenShiftDeployment(context)
}

def stageCheckFormat(def context) {
  stage('Check Format') {
    def unformatted = sh(script: 'gofmt -l .', returnStdout: true)
    if (unformatted) {
      println "Unformatted files:\n${unformatted}"
      error 'All files need to be gofmt\'d. Please run: gofmt -w .'
    }
  }
}

def stageLint(def context) {
  stage('Lint') {
    withEnv(["CGO_ENABLED=0", "GOCACHE=${WORKSPACE}/.cache"]) {
      sh "golangci-lint run"
    }
  }
}

def stageBuild(def context) {
  stage('Build') {
    def binary = "app_linux_amd64"
    withEnv(["CGO_ENABLED=0", "GOCACHE=${WORKSPACE}/.cache"]) {
      sh "go build -o docker/${binary}"
    }
  }
}

def stageUnitTest(def context) {
  stage('Unit Test') {
    withEnv(["CGO_ENABLED=0", "GOCACHE=${WORKSPACE}/.cache"]) {
      sh 'mkdir -p build/test-results/test'
      def gopkgs = sh(script: 'go list ./... | grep -v /vendor', returnStdout: true).trim()
      withEnv(["GOPKGS=${gopkgs}"]) {
        def status = sh(script: 'go test -v -coverprofile=coverage.out $GOPKGS 2>&1 > test-results.txt', returnStatus: true)
        sh 'cat test-results.txt | go-junit-report > build/test-results/test/report.xml'
        if (status != 0) {
          error "go test failed!"
        }
      }
    }
  }
}

Compared to Jenkins, you cannot define any scripts directly in the ods.yaml file describing your Tekton pipeline. You may only reference existing tasks and adjust their parameters. As a consequence, the build related stages (stageCheckFormat, stageLint, stageUnitTest, stageBuild) are provided by a task (named ods-pipeline-go-build) instead.

An roughly equivalent ods.yaml for the above Jenkinsfile looks like this:

ods.yaml
pipelines:
  - 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

What has been done in Jenkins in stageCheckFormat, stageLint, stageUnitTest, stageBuild and odsComponentStageScanWithSonar is now done by the ods-pipeline-go-build task. If you have modified how the application is tested and built, or added further steps, you will need to create your own Tekton tasks reflecting those changes. See the authoring tasks guide.

Building the container image is now done in ods-pipeline-image-package instead of in odsComponentStageBuildOpenShiftImage. The task continues to use the existing docker/Dockerfile file, which does not need to change much if at all. Consult the task reference in question for more information. In the case of Go, the ods-pipeline-go-build task reference states that the resulting Go binary is named app and placed into the docker directory. Make sure that your docker/Dockerfile copies app, not e.g. app_linux_amd64 (as is the default for an ODS 4.x based Go quickstarter).

Create Helm Chart

Finally, the application is deployed in ods-pipeline-helm-deploy as opposed to odsComponentStageRolloutOpenShiftDeployment. Let’s look at this deployment piece in detail. The new Tekton task makes use of Helm to define and deploy the Kubernetes resources to use. Your existing repository might not define Kubernetes resources at all (this is the default), or they might be expressed as OpenShift templates (in a folder named openshift) and applied with Tailor. ODS pipeline only supports Helm at the moment, and requires the Kubernetes resources (the Helm "chart") to be under version control. It is recommended to start with the sample chart provided in this repository. If the existing component controlled resources via Tailor, please see the ODS Quickstarter Migration Guide of Tailor as well.

Configure Webhook

The final step is to create a Bitbucket webhook pointing to the ODS pipeline installation. To do this, go to "Repository Settings > Webhooks" and create a new webhook:

  • "Name": choose any name you wish, e.g. ods-pipeline

  • "URL": enter the URL of the route of your event listener, followed by /bitbucket, e.g. https://ods-pipeline.example.com/bitbucket

  • "Secret": enter the value of the secret field in the OpenShift ods-bitbucket-webhook Secret.

Select the "Repository: Push" and "Pull request: Opened" events and save the configuration.

Any existing Jenkins webhook setting can be disabled now. After that, any push to the repository will trigger the pipeline described in ods.yaml.

Next Steps

Once you have done your first steps, consult the ods.yaml reference and the tasks reference for more information.

For an end-to-end example, have a look at the example project.