Search code examples
javamaventektontekton-pipelinesopenshift-pipelines

Cache Maven dependencies in Tekton Maven Task from Tekton Hub


We want to build a Spring Boot-based project using Maven. We found the Maven Task on the Tekton Hub and already have a running Pipeline. In a shortened version our pipeline.yml looks like this:

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: buildpacks-test-pipeline
spec:
  params:
    - name: SOURCE_URL
      type: string
      description: A git repo url where the source code resides.
    - name: SOURCE_REVISION
      description: The branch, tag or SHA to checkout.
      default: ""

  workspaces:
    - name: maven-settings
    - name: source-workspace
  tasks:
    - name: fetch-repository
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: source-workspace
      params:
        - name: url
          value: "$(params.SOURCE_URL)"
        - name: revision
          value: "$(params.SOURCE_REVISION)"
        - name: subdirectory
          value: ""
        - name: deleteExisting
          value: "true"
    - name: maven
      taskRef:
        name: maven
      runAfter:
        - fetch-repository
      params:
        - name: GOALS
          value:
            - package
      workspaces:
        - name: source
          workspace: source-workspace
        - name: maven-settings
          workspace: maven-settings

And a PipelineRun is defined as:

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: buildpacks-test-pipeline-run-
spec:
  pipelineRef:
    name: buildpacks-test-pipeline
  workspaces:
    - name: maven-settings
      emptyDir: {}
    - name: source-workspace
      subPath: source
      persistentVolumeClaim:
        claimName: source-pvc
  params:
    - name: SOURCE_URL
      value: https://gitlab.com/jonashackt/microservice-api-spring-boot
    - name: SOURCE_REVISION
      value: 3c4131f8566ef157244881bacc474543ef96755d

The source-pvc PersistentVolumeClaim is defined as:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: source-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

Our project is being build fine, but the Task downloads all the project's Maven dependencies over and over again when we start another PipelineRun:

enter image description here

The Tekton Hub's Maven Task https://hub.tekton.dev/tekton/task/maven doesn't seem to support using a cache. How can we cache nevertheless?


Solution

  • There's an easy way to accomplish caching using Tekto Hub's Maven Task. Instead of specifying an empty directory in the maven-settings workspace with emptyDir: {} you need to create a new subPath inside your already defined source-pvc PersistentVolumeClaim. Also link the persistentVolumeClaim the same way as you already linked it for the source-workspace. Your PipelineRun now somehow looks like this:

    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: buildpacks-test-pipeline-run-
    spec:
      pipelineRef:
        name: buildpacks-test-pipeline
      workspaces:
        - name: maven-settings
          subPath: maven-repo-cache
          persistentVolumeClaim:
            claimName: source-pvc
        - name: source-workspace
          subPath: source
          persistentVolumeClaim:
            claimName: source-pvc
      params:
        - name: SOURCE_URL
          value: https://gitlab.com/jonashackt/microservice-api-spring-boot
        - name: SOURCE_REVISION
          value: 3c4131f8566ef157244881bacc474543ef96755d
    

    Now the new subPath is already available via the maven-settings workspace inside the Tekton Hub's Maven Task (which doesn't implement an extra cache workspace right now). We only need to tell Maven to use the path workspaces.maven-settings.path as the cache repository.

    Therefore we add -Dmaven.repo.local=$(workspaces.maven-settings.path) as a value to the GOALS parameter of the maven Task like this:

    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
      name: buildpacks-test-pipeline
    spec:
      params:
        - name: SOURCE_URL
          type: string
          description: A git repo url where the source code resides.
        - name: SOURCE_REVISION
          description: The branch, tag or SHA to checkout.
          default: ""
    
      workspaces:
        - name: maven-settings
        - name: source-workspace
      tasks:
        - name: fetch-repository # This task fetches a repository from github, using the `git-clone` task you installed
          taskRef:
            name: git-clone
          workspaces:
            - name: output
              workspace: source-workspace
          params:
            - name: url
              value: "$(params.SOURCE_URL)"
            - name: revision
              value: "$(params.SOURCE_REVISION)"
            - name: subdirectory
              value: ""
            - name: deleteExisting
              value: "true"
        - name: maven
          taskRef:
            name: maven
          runAfter:
            - fetch-repository
          params:
            - name: GOALS
              value:
                - -Dmaven.repo.local=$(workspaces.maven-settings.path)
                - verify
          workspaces:
            - name: source
              workspace: source-workspace
            - name: maven-settings
              workspace: maven-settings
    

    Now after the first pipeline execution every next run should re-use the Maven repository inside the maven-settings workspace. This should also prevent the log from beeing polluted with Maven Download statements and speeds up the pipeline depending on the number of dependencies:

    enter image description here

    Our simple example builds more than twice as fast.