Artifacts

Overview

🌱 Artifacts is an alpha feature. The enable-artifacts feature flag must be set to "true" to read or write artifacts in a step.

Artifacts provide a way to track the origin of data produced and consumed within your Tekton Tasks.

Artifact Provenance Data

Artifacts fall into two categories:

  • Inputs: Artifacts downloaded and used by the Step/Task.
  • Outputs: Artifacts created and uploaded by the Step/Task.

Example Structure:

{  "inputs":[  {  "name": "<input-category-name>",  "values": [  {  "uri": "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c",  "digest": { "sha256": "b35caccc..." }  }  ]  }  ],  "outputs": [  {  "name": "<output-category-name>",  "values": [  {  "uri": "pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library",  "digest": {  "sha256": "df85b9e3...",  "sha1": "95588b8f..."  }  }  ]  }  ] } 

The content is written by the Step to a file $(step.artifacts.path):

apiVersion: tekton.dev/v1 kind: TaskRun metadata:  generateName: step-artifacts- spec:  taskSpec:  description: |   A simple task that populates artifacts to TaskRun stepState  steps:  - name: artifacts-producer  image: bash:latest  script: |  cat > $(step.artifacts.path) << EOF  {  "inputs":[  {  "name":"source",  "values":[  {  "uri":"pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c",  "digest":{  "sha256":"b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  }  }  ]  }  ],  "outputs":[  {  "name":"image",  "values":[  {  "uri":"pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library",  "digest":{  "sha256":"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48",  "sha1":"95588b8f34c31eb7d62c92aaa4e6506639b06ef2"  }  }  ]  }  ]  }  EOF 

It is recommended to use purl format for artifacts uri as shown in the example.

Output Artifacts in SLSA Provenance

Artifacts are classified as either:

  • Build Outputs - packages, images, etc. that are being published by the build.
  • Build Byproducts - logs, caches, etc. that are incidental artifacts that are produced by the build.

By default, Tekton Chains will consider all output artifacts as byProducts when generating in the SLSA provenance. In order to treat an artifact as a subject of the build, you must set a boolean field "buildOutput": true for the output artifact.

e.g.

apiVersion: tekton.dev/v1 kind: TaskRun metadata:  generateName: step-artifacts- spec:  taskSpec:  description: |   A simple task that populates artifacts to TaskRun stepState  steps:  - name: artifacts-producer  image: bash:latest  script: |  cat > $(artifacts.path) << EOF  {  "outputs":[  {  "name":"image",  "buildOutput": true,  "values":[  {  "uri":"pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library",  "digest":{  "sha256":"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48",  "sha1":"95588b8f34c31eb7d62c92aaa4e6506639b06ef2"  }  }  ]  }  ]  }  EOF 

This informs Tekton Chains your desire to handle the artifact.

[!TIP] When authoring a StepAction or a Task, you can parametrize this field to allow users to indicate their desire depending on what they are uploading - this can be useful for actions that may produce either a build output or a byproduct depending on the context!

Passing Artifacts between Steps

You can pass artifacts from one step to the next using:

  • Specific Artifact: $(steps.<step-name>.inputs.<artifact-category-name>) or $(steps.<step-name>.outputs.<artifact-category-name>)

The example below shows how to access the previous’ step artifacts from another step in the same task

apiVersion: tekton.dev/v1 kind: TaskRun metadata:  generateName: step-artifacts- spec:  taskSpec:  description: |   A simple task that populates artifacts to TaskRun stepState  steps:  - name: artifacts-producer  image: bash:latest  script: |  # the script is for creating the output artifacts  cat > $(step.artifacts.path) << EOF  {  "inputs":[  {  "name":"source",  "values":[  {  "uri":"pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c",  "digest":{  "sha256":"b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  }  }  ]  }  ],  "outputs":[  {  "name":"image",  "values":[  {  "uri":"pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library",  "digest":{  "sha256":"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48",  "sha1":"95588b8f34c31eb7d62c92aaa4e6506639b06ef2"  }  }  ]  }  ]  }  EOF  - name: artifacts-consumer  image: bash:latest  script: |   echo $(steps.artifacts-producer.outputs.image) 

The resolved value of $(steps.<step-name>.outputs.<artifact-category-name>) is the values of an artifact. For this example, $(steps.artifacts-producer.outputs.image) is resolved to

[  {  "uri":"pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library",  "digest":{  "sha256":"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48",  "sha1":"95588b8f34c31eb7d62c92aaa4e6506639b06ef2"  }  } ] 

Upon resolution and execution of the TaskRun, the Status will look something like:

{  "artifacts": {  "inputs": [  {  "name": "source",  "values": [  {  "digest": {  "sha256": "b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  },  "uri": "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c"  }  ]  }  ],  "outputs": [  {  "name": "image",  "values": [  {  "digest": {  "sha1": "95588b8f34c31eb7d62c92aaa4e6506639b06ef2",  "sha256": "df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48"  },  "uri": "pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library"  }  ]  }  ]  },  "steps": [  {  "container": "step-artifacts-producer",  "imageID": "docker.io/library/bash@sha256:5353512b79d2963e92a2b97d9cb52df72d32f94661aa825fcfa0aede73304743",  "inputs": [  {  "name": "source",  "values": [  {  "digest": {  "sha256": "b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  },  "uri": "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c"  }  ]  }  ],  "name": "artifacts-producer",  "outputs": [  {  "name": "image",  "values": [  {  "digest": {  "sha1": "95588b8f34c31eb7d62c92aaa4e6506639b06ef2",  "sha256": "df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48"  },  "uri": "pkg:oci/nginx:stable-alpine3.17-slim?repository_url=docker.io/library"  }  ]  }  ],  "terminated": {  "containerID": "containerd://010f02d103d1db48531327a1fe09797c87c1d50b6a216892319b3af93e0f56e7",  "exitCode": 0,  "finishedAt": "2024-03-18T17:05:06Z",  "message": "...",  "reason": "Completed",  "startedAt": "2024-03-18T17:05:06Z"  },  "terminationReason": "Completed"  },  {  "container": "step-artifacts-consumer",  "imageID": "docker.io/library/bash@sha256:5353512b79d2963e92a2b97d9cb52df72d32f94661aa825fcfa0aede73304743",  "name": "artifacts-consumer",  "terminated": {  "containerID": "containerd://42428aa7e5a507eba924239f213d185dd4bc0882b6f217a79e6792f7fec3586e",  "exitCode": 0,  "finishedAt": "2024-03-18T17:05:06Z",  "reason": "Completed",  "startedAt": "2024-03-18T17:05:06Z"  },  "terminationReason": "Completed"  }  ] } 

Passing Artifacts between Tasks

You can pass artifacts from one task to the another using:

  • Specific Artifact: $(tasks.<task-name>.inputs.<artifact-category-name>) or $(tasks.<task-name>.outputs.<artifact-category-name>)

The example below shows how to access the previous’ task artifacts from another task in a pipeline

apiVersion: tekton.dev/v1 kind: PipelineRun metadata:  generateName: pipelinerun-consume-tasks-artifacts spec:  pipelineSpec:  tasks:  - name: produce-artifacts-task  taskSpec:  description: |   A simple task that produces artifacts  steps:  - name: produce-artifacts  image: bash:latest  script: |  #!/usr/bin/env bash  cat > $(artifacts.path) << EOF  {  "inputs":[  {  "name":"input-artifacts",  "values":[  {  "uri":"pkg:example.github.com/inputs",  "digest":{  "sha256":"b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  }  }  ]  }  ],  "outputs":[  {  "name":"image",  "values":[  {  "uri":"pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c",  "digest":{  "sha256":"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48",  "sha1":"95588b8f34c31eb7d62c92aaa4e6506639b06ef2"  }  }  ]  }  ]  }  EOF  - name: consume-artifacts  runAfter:  - produce-artifacts-task  taskSpec:  steps:  - name: artifacts-consumer-python  image: python:latest  script: |  #!/usr/bin/env python3  import json  data = json.loads('$(tasks.produce-artifacts-task.outputs.image)')  if data[0]['uri'] != "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c":  exit(1) 

Similar to Step Artifacts. The resolved value of $(tasks.<task-name>.outputs.<artifact-category-name>) is the values of an artifact. For this example, $(tasks.produce-artifacts-task.outputs.image) is resolved to

[  {  "uri":"pkg:example.github.com/inputs",  "digest":{  "sha256":"b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  }  } ] 

Upon resolution and execution of the TaskRun, the Status will look something like:

{  "artifacts": {  "inputs": [  {  "name": "input-artifacts",  "values": [  {  "digest": {  "sha256": "b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0"  },  "uri": "pkg:example.github.com/inputs"  }  ]  }  ],  "outputs": [  {  "name": "image",  "values": [  {  "digest": {  "sha1": "95588b8f34c31eb7d62c92aaa4e6506639b06ef2",  "sha256": "df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48"  },  "uri": "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c"  }  ]  }  ]  },  "completionTime": "2024-05-28T14:10:58Z",  "conditions": [  {  "lastTransitionTime": "2024-05-28T14:10:58Z",  "message": "All Steps have completed executing",  "reason": "Succeeded",  "status": "True",  "type": "Succeeded"  }  ],  "podName": "pipelinerun-consume-tasks-a41ee44e4f964e95adfd3aea417d52f90-pod",  "provenance": {  "featureFlags": {  "awaitSidecarReadiness": true,  "coschedule": "workspaces",  "disableCredsInit": false,  "disableInlineSpec": "",  "enableAPIFields": "beta",  "enableArtifacts": true,  "enableCELInWhenExpression": false,  "enableConciseResolverSyntax": false,  "enableKeepPodOnCancel": false,  "enableParamEnum": false,  "enableProvenanceInStatus": true,  "enableStepActions": true,  "enableTektonOCIBundles": false,  "enforceNonfalsifiability": "none",  "maxResultSize": 4096,  "requireGitSSHSecretKnownHosts": false,  "resultExtractionMethod": "termination-message",  "runningInEnvWithInjectedSidecars": true,  "scopeWhenExpressionsToTask": false,  "sendCloudEventsForRuns": false,  "setSecurityContext": false,  "verificationNoMatchPolicy": "ignore"  }  },  "startTime": "2024-05-28T14:10:48Z",  "steps": [  {  "container": "step-produce-artifacts",  "imageID": "docker.io/library/bash@sha256:23f90212fd89e4c292d7b41386ef1a6ac2b8a02bbc6947680bfe184cbc1a2899",  "name": "produce-artifacts",  "terminated": {  "containerID": "containerd://1291ce07b175a7897beee6ba62eaa1528427bacb1f76b31435eeba68828c445a",  "exitCode": 0,  "finishedAt": "2024-05-28T14:10:57Z",  "message": "...",  "reason": "Completed",  "startedAt": "2024-05-28T14:10:57Z"  },  "terminationReason": "Completed"  }  ],  "taskSpec": {  "description": "A simple task that produces artifacts\n",  "steps": [  {  "computeResources": {},  "image": "bash:latest",  "name": "produce-artifacts",  "script": "#!/usr/bin/env bash\ncat > /tekton/artifacts/provenance.json << EOF\n{\n \"inputs\":[\n {\n \"name\":\"input-artifacts\",\n \"values\":[\n {\n \"uri\":\"pkg:example.github.com/inputs\",\n \"digest\":{\n \"sha256\":\"b35cacccfdb1e24dc497d15d553891345fd155713ffe647c281c583269eaaae0\"\n }\n }\n ]\n }\n ],\n \"outputs\":[\n {\n \"name\":\"image\",\n \"values\":[\n {\n \"uri\":\"pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c\",\n \"digest\":{\n \"sha256\":\"df85b9e3983fe2ce20ef76ad675ecf435cc99fc9350adc54fa230bae8c32ce48\",\n \"sha1\":\"95588b8f34c31eb7d62c92aaa4e6506639b06ef2\"\n }\n }\n ]\n }\n ]\n}\nEOF\n"  }  ]  } }