Tanzu Platform Self-Managed 10.1

Add custom tasks to a build

Last Updated March 03, 2025

You can use the ContainerAppBuildPlan configuration to define the processes or tasks that run when you run tanzu build to build an application on a Kubernetes Space.

Tanzu Platform provides a default ContainerAppBuildPlan named simple.tanzu.vmware.com, which you can use as a reference to create a custom ContainerAppBuildPlan for a specific Project. When you create a ContainerAppBuildPlan for a Project, it is available to all Spaces in that Project.

For information about Projects, see Add projects and assign users for Tanzu Platform. For information about ContainerApps, see What is a ContainerApp, and the ContainerAppBuildPlan API reference for the full ContainerAppBuildPlan specification.

Before you begin

  • Install Tanzu CLI v1.5.3 or later. See Installing the Tanzu CLI in the Tanzu CLI documentation.

  • If it is not present, install the Tanzu CLI app-developer plug-in group by running:

    tanzu plugin install --group vmware-tanzu/app-developer:v1.1
    

    If the app-developer plug-in group is already installed, verify that you have the latest version of the build plug-in by running:

    tanzu plugin upgrade build
    

Create a ContainerAppBuildPlan file

You create a ContainerAppBuildPlan file by creating a copy of the default build plan from a Project and updating it with your customizations.

  1. Log in to Tanzu Platform with the Tanzu CLI by running:

    tanzu login
    
  2. Set the Tanzu CLI to your Project context by running:

    tanzu project use PROJECT-NAME
    
  3. Set KUBECONFIG by running:

    export KUBECONFIG=~/.config/tanzu/kube/config
    
  4. Retrieve the default ContainerAppBuildPlan from the Project by running:

    kubectl get containerappbuildplans.build.tanzu.vmware.com simple.tanzu.vmware.com -oyaml
    
  5. Save the ContainerAppBuildPlan as a YAML file and add your customizations.

    For example, save it as my-custom-conatinerappbuildplan.yaml.

    This example shows the default ContainerAppBuildPlan in YAML format.

    apiVersion: build.tanzu.vmware.com/v1
    kind: ContainerAppBuildPlan
    metadata:
      name: simple.tanzu.vmware.com
    spec:
      buildpacks:
        builderName: base-jammy-offline.tanzu.vmware.com
      postBuildSteps:
      - namedTask: containerapp-defaults.tanzu.vmware.com
      - namedTask: spring-boot.tanzu.vmware.com
      runtimes:
      - name: kubernetes-carvel-package
        description: create a carvel package for deploying on kubernetes
        steps:
        - namedTask: kubernetes-deployment.tanzu.vmware.com
        - namedTask: kubernetes-carvel-package.tanzu.vmware.com
      - name: kubernetes-plain
        description: create kubernetes yaml files for deploying on kubernetes
        steps:
        - namedTask: kubernetes-deployment.tanzu.vmware.com
      - name: container-image
        description: write image to file for use with container runtime (i.e docker run)
        steps:
        - namedTask: container-image.tanzu.vmware.com
    

    For an example of how to update a ContainerAppBuildPlan to add a NamedTask or ContainerTask, see Add a custom task to a ContainerAppBuildPlan later in this topic.

  6. Create the custom ContainerAppBuildPlan in your Project by running:

    kubectl apply -f my-custom-conatinerappbuildplan.yaml
    
  7. Build your application with the updated ContainerAppBuildPlan by running:

    tanzu build
    

Add a custom task to a ContainerAppBuildPlan

The example in this section shows a custom ContainerAppBuildPlan named custom-buildplan-2, that adds a customNamedTask to the plan. NamedTasks reference resources of the type NamedTask.build.tanzu.vmware.comin the current Project and run a one-off task in the post-build step of a build plan, using a container image and a set of instructions.

Create the custom task

A custom task is any image that is run as a step in the post-build process. The task will have a workspace that contains the container app, the software bill of materials (SBOM) from the build, and any output from previous post-build steps.

The SBOM is available for buildpack builds only in this release.

The workspace directory is provided to the container through the environment variable $TANZU_BUILD_WORKSPACE_DIR. Inside this directory is the following structure immediately following the build phase:

$TANZU_BUILD_WORKSPACE_DIR
├── tanzu.yml
├── output/
│   └── containerapp.yml
└── build/
    └── sbom/
        └── sbom-files

This directory structure might change as post-build steps are run.

Custom tasks can change the container app or anything in output and can generate new content in the output directory.

Add the task to the ContainerAppBuildPlan

Example NamedTask named my-custom-task:

apiVersion: build.tanzu.vmware.com/v1
kind: NamedTask
metadata:
  name: my-custom-task
spec:
  description: a custom task that adds an environment variable to the ContainerApp
  image: my-registry.io/container-app-modifier
  command: ["/cnb/process/container-app-modifier"]
  args: ["some-env-name=some-env-value"]

Example custom ContainerAppBuildPlan using my-custom-task:

apiVersion: build.tanzu.vmware.com/v1
kind: ContainerAppBuildPlan
metadata:
  name: custom-buildplan-2
spec:
  buildpacks:
    builderName: base-jammy-offline.tanzu.vmware.com
  postBuildSteps:
  - namedTask: containerapp-defaults.tanzu.vmware.com
  - namedTask: spring-boot.tanzu.vmware.com
  - namedTask: my-custom-task
  runtimes:
  - name: kubernetes-carvel-package
    description: create a carvel package for deploying on kubernetes
    steps:
    - namedTask: kubernetes-deployment.tanzu.vmware.com
    - namedTask: kubernetes-carvel-package.tanzu.vmware.com
  - name: kubernetes-plain
    description: create kubernetes yaml files for deploying on kubernetes
    steps:
    - namedTask: kubernetes-deployment.tanzu.vmware.com
  - name: container-image
    description: write image to file for use with container runtime (i.e docker run)
    steps:
    - namedTask: container-image.tanzu.vmware.com

This example custom ContainerAppBuildPlan adds the NamedTask called my-custom-task in spec.postBuildSteps as highlighted in the following extract.

postBuildSteps:
  - namedTask: containerapp-defaults.tanzu.vmware.com
  - namedTask: spring-boot.tanzu.vmware.com
  - namedTask: my-custom-task

If you run tanzu build with this ContainerAppBuildPlan, it runs the new task my-custom-task after the other post-build steps.

You can also add custom tasks in-line inside the ContainerAppBuildPlan by using a ContainerTask. The following example shows an equivalent postBuildSteps to the example shown earlier, with a ContainerTask instead of a NamedTask. There is no functional difference between the two, but using a NamedTask enables you to reuse the task across multiple custom build plans in the Project.

Example ContainerTask named my-custom-task in spec.postBuildSteps:

postBuildSteps:
  - namedTask: containerapp-defaults.tanzu.vmware.com
  - namedTask: spring-boot.tanzu.vmware.com
  - name: my-custom-task
    containerTask:
      image: my-registry.io/container-app-modifier
      command: ["/cnb/process/container-app-modifier"]
      args: ["some-env-name=some-env-value"]

The ContainerAppBuildPlan also allows you to customize spec.runtimes, which specifies the steps to run during the build. For the full ContainerAppBuildPlan specification, see the ContainerAppBuildPlan API reference.

Set a custom ContainerAppBuildPlan as the default in a Project

The BuildConfiguration in each Project allows you to set a default ContainerAppBuildPlan. A ContainerApp can override this default if it specifies that a different ContainerAppBuildPlan is used instead.

To set the Project-wide default, configure the field spec.defaultBuildPlanName in the Project BuildConfiguration to the name of your custom ContainerAppBuildPlan.

Specify a build plan in a ContainerApp

This section tells you how to specify the build plan you want to use for your container app.

Discover available builds plans

The tanzu build plug-in allows for basic interaction with ContainerAppBuildPlans to help you to discover the plans you can use.

  • To get a list of build plans in a Project, run:

    tanzu build plan list
    

    For example:

    $ tanzu build plan list
    
    NAME                      DESCRIPTION               DEFAULT
    simple.tanzu.vmware.com   tanzu provided buildplan
    custom-buildplan-1        company a default plan      *
    custom-buildplan-2        custom plan for ai apps
    
  • To see more information about a build plan:

    tanzu build plan get PLAN-NAME
    

    For example:

    $ tanzu build plan get simple.tanzu.vmware.com
    
    Metadata
    Name:       simple.tanzu.vmware.com
    Builder:    base-jammy-offline.tanzu.vmware.com
    Default:    false
    
    Post Build Steps
    - containerapp-defaults.tanzu.vmware.com
    - spring-boot.tanzu.vmware.com
    
    Runtimes (default = kubernetes-carvel-package)
    - Name:           kubernetes-carvel-package
    Description:    create a carvel package for deploying on kubernetes
    Steps:
    - kubernetes-deployment.tanzu.vmware.com
    - kubernetes-carvel-package.tanzu.vmware.com
    
    - Name:           kubernetes-plain
    Description:    create kubernetes yaml files for deploying on kubernetes
    Steps:
    - kubernetes-deployment.tanzu.vmware.com
    
    - Name:           container-image
    Description:    write image to file for use with container runtime (i.e docker run)
    Steps:
    - container-image.tanzu.vmware.com
    

Override the default build plan

To set the default ContainerAppBuildPlan for a ContainerApp, configure the field spec.build.buildPlanName in the ContainerApp to the name of the ContainerAppBuildPlan you want.

If the ContainerApp needs to be built in another Project, that Project must also have a ContainerAppBuildPlan of the same name or build errors will occur.

The following is an example ContainerApp using a non-default build plan:

apiVersion: apps.tanzu.vmware.com/v1
kind: ContainerApp
metadata:
  name: test-app
spec:
  build:
    buildPlanName: custom-buildplan-2
    buildpacks: {}
    path: ..
  ports:
  - name: main
    port: 8080