Add Custom Task Images to Selector

This guide explains how to configure selector options for the image parameter in the UI Task form, covering two scenarios:

  • Adding images for hub Tasks
  • Adding images for your own namespace Tasks.

Feature Overview

  • Each selector option comes from a ConfigMap with data.name (label) and data.image (value).
  • Task-specific labels (for example, catalog.tekton.dev/tool-image-python) make the UI match ConfigMaps to the right Task parameter.
  • The UI queries the namespace specified in the Task annotation (for example, kube-public) using the label selector defined in the Task descriptor, then renders the selector with the results.

Use Cases

  • Add an customize registry mirror image for a Task selector.
  • Introduce a new runtime minor alongside existing selector options.
  • Provide a hardened image option for a custom Task.

Prerequisites

  • Tekton Pipelines is installed.
  • You can create ConfigMaps in kube-public.
  • You can set style.tekton.dev/descriptors on the target Task (Hub Tasks already provide it; custom Tasks need you to add it).

Scenario A: Add images to a Hub Task selector

Use this path when extending the selector of a Hub Task.

1. Find the label selector from the Task descriptor

Locate the style.tekton.dev/descriptors annotation on the Task and find the entry whose path points to the image parameter.

The descriptor ending with urn:alm:descriptor:expression:props.options:api includes a labelSelector=... query; the label key there must be present on your ConfigMap.

In the following example, you need to create a ConfigMap with the catalog.tekton.dev/tool-image-python label in the kube-public namespace.

kind: Task
metadata:
  name: python
  labels:
    app.kubernetes.io/version: "0.1"
  annotations:
    style.tekton.dev/descriptors: |
      - path: params.PYTHON_IMAGE
        x-descriptors:
          ...
          - urn:alm:descriptor:expression:props.options:api:/kubernetes/${context.cluster}/api/v1/namespaces/kube-public/configmaps?labelSelector=catalog.tekton.dev%2Ftool-image-python
          ...

For more information of style.tekton.dev/descriptors, see How to Configure Dynamic Forms.

2. Create a ConfigMap in kube-public

Create a ConfigMap using that label key.

Default Tasks ship ConfigMaps labeled catalog.tekton.dev/source: system to indicate platform-provided entries. Do not modify or delete those, and your custom ConfigMaps should not include this label.

apiVersion: v1
kind: ConfigMap
metadata:
  name: tekton-task-python-custom
  namespace: kube-public
  labels:
    catalog.tekton.dev/tool-image-python: "3.10"
data:
  name: "Python 3.10"
  image: "registry.example.com/tekton/python:3.10"

3. Apply and verify

kubectl apply -f tekton-task-python-custom.yaml
# configmap/tekton-task-python-custom created

kubectl -n kube-public get configmap -l catalog.tekton.dev/tool-image-python=3.10
# NAME                             DATA   AGE
# tekton-task-python-custom        2      15s

Open the Task form; the selector should now include Python 3.10 and set the image to registry.example.com/tekton/python:3.10.

Scenario B: Add images to your own Task selector

Use this path when you control the Task definition and need to configure descriptors plus ConfigMaps.

1. Configure style.tekton.dev/descriptors on the Task

Example Task descriptor for an image selector:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: python
  labels:
    app.kubernetes.io/version: "0.1"
  annotations:
    style.tekton.dev/descriptors: |
      - path: params.PYTHON_IMAGE
        x-descriptors:
          - urn:alm:descriptor:label:en:PYTHON_IMAGE
          - urn:alm:descriptor:description:en:The used Python image.
          - urn:alm:descriptor:com.tectonic.ui:select:image
          - urn:alm:descriptor:expression:props.options:api:/kubernetes/${context.cluster}/api/v1/namespaces/kube-public/configmaps?labelSelector=catalog.tekton.dev%2Ftool-image-python-custom
          - urn:alm:descriptor:props:select:allowCreate
          - urn:alm:descriptor:expression:props.options:path:items
          - urn:alm:descriptor:expression:props.options:label:path:data.name
          - urn:alm:descriptor:expression:props.options:value:path:data.image
          - urn:alm:descriptor:com.tectonic.ui:validation:required
spec:
  params:
    - name: PYTHON_IMAGE
      description: Image used for Python steps.
      type: string
  steps:
    - name: python-script
      image: $(params.PYTHON_IMAGE)
      script: |
        #!/bin/sh
        # Define your task script

Descriptor items and meanings:

Descriptor entryPurposeExampleRemark
pathPoints to the parameter rendered as a selector.params.PYTHON_IMAGE
urn:alm:descriptor:label:enEnglish field label shown in the form.PYTHON_IMAGE
urn:alm:descriptor:description:enEnglish help text for the field.The used Python image.
urn:alm:descriptor:com.tectonic.ui:select:imageRenders the field as an image selector.No change needed.
urn:alm:descriptor:expression:props.options:apiAPI to fetch selector options (namespace + label selector)./kubernetes/${context.cluster}/api/v1/namespaces/kube-public/configmaps?labelSelector=catalog.tekton.dev%2Ftool-image-python-customIn the example, fetches ConfigMaps in kube-public with label catalog.tekton.dev/tool-image-python-custom.
urn:alm:descriptor:props:select:allowCreateAllows manual input in addition to selector options.
urn:alm:descriptor:expression:props.options:pathPoints to the list path in the API response.urn:alm:descriptor:expression:props.options:path:itemsIn the example, the List API is used, so the values are taken from items.
urn:alm:descriptor:expression:props.options:label:pathReads selector display text from the item.urn:alm:descriptor:expression:props.options:label:path:data.nameIn the example, the value is taken from data.name of the ConfigMap.
urn:alm:descriptor:expression:props.options:value:pathReads selector value (image) from the item.urn:alm:descriptor:expression:props.options:value:path:data.imageIn the example, the value is taken from data.image of the ConfigMap.
urn:alm:descriptor:com.tectonic.ui:validation:requiredMarks the field as required.

For more information of style.tekton.dev/descriptors, see How to Configure Dynamic Forms.

2. Create a matching ConfigMap in kube-public

Use the same label key that your descriptor queries. For custom Tasks, prefer a label key that does not conflict with default Task selectors to avoid accidental display in Hub Tasks.

Default Tasks ship ConfigMaps labeled catalog.tekton.dev/source: system to indicate platform-provided entries. Do not modify or delete those, and your custom ConfigMaps should not include this label.

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-task-python-3-13
  namespace: kube-public
  labels:
    catalog.tekton.dev/tool-image-python-custom: "3.13-team"
data:
  name: "Python 3.13 (Team Edition)"
  image: "registry.example.com/internal/python:3.13"

You can also place the ConfigMap in any other namespace you prefer; you just need to make sure that the ConfigMap's namespace is the same as the namespace specified in the Task's style.tekton.dev/descriptors annotation. For example, you can set the Task's annotation as in the example below, please replace <NAMESPACE> with your namespace.

kind: Task
metadata:
  name: python
  labels:
    app.kubernetes.io/version: "0.1"
  annotations:
    # replace <NAMESPACE> with your namespace
    style.tekton.dev/descriptors: |
      - path: params.PYTHON_IMAGE
        x-descriptors:
          ...
          - urn:alm:descriptor:expression:props.options:api:/kubernetes/${context.cluster}/api/v1/namespaces/<NAMESPACE>/configmaps?labelSelector=catalog.tekton.dev%2Ftool-image-python-custom
          ...

3. Apply and validate

kubectl apply -f custom-task-python-3-13.yaml
# configmap/custom-task-python-3-13 created

kubectl -n kube-public get configmap -l catalog.tekton.dev/tool-image-python-custom=3.13-team
# NAME                             DATA   AGE
# custom-task-python-3-13          2      15s

Open your Task form; the selector should list Python 3.13 (Team Edition) and set the image to registry.example.com/internal/python:3.13.

Maintenance tips

  • Update a custom option by editing and re-applying its ConfigMap.
  • Retire an option by deleting only your custom ConfigMap; leave any ConfigMap with catalog.tekton.dev/source: system untouched.