Skip to content

Commit b6ab344

Browse files
authored
feat(ISV-5783): use new SBOM generation workflow (#950)
The SBOM generation logic is now dependent on fewer tasks. Signed-off-by: Martin Jediny <jedinym@proton.me>
1 parent 546494e commit b6ab344

20 files changed

+157
-533
lines changed

pipelines/managed/rh-advisories/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ the rh-push-to-registry-redhat-io pipeline.
2828
| trustedArtifactsDebug | Flag to enable debug logging in trusted artifacts. Set to a non-empty string to enable | Yes | "" |
2929
| dataDir | The location where data will be stored | Yes | /var/workdir/release |
3030

31+
## Changes in 2.0.8
32+
* The `update-component-sbom` and `create-product-sbom` tasks are refactored to
33+
use the new SBOM generation workflow. They no longer depend on
34+
`push-rpm-data-to-pyxis` and `populate-release-notes`.
35+
3136
## Changes in 2.0.7
3237
* Target for SBOM upload has been changed from Atlas v1 to Atlas v2.
3338

pipelines/managed/rh-advisories/rh-advisories.yaml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ kind: Pipeline
44
metadata:
55
name: rh-advisories
66
labels:
7-
app.kubernetes.io/version: "2.0.7"
7+
app.kubernetes.io/version: "2.0.8"
88
annotations:
99
tekton.dev/pipelines.minVersion: "0.12.1"
1010
tekton.dev/tags: release
@@ -707,14 +707,12 @@ spec:
707707
- name: data
708708
workspace: release-workspace
709709
params:
710-
- name: sbomJsonPath
711-
value: "$(tasks.populate-release-notes.results.sbomDataPath)"
712-
- name: downloadedSbomPath
713-
value: "$(tasks.push-rpm-data-to-pyxis.results.sbomPath)"
710+
- name: snapshotSpec
711+
value: "$(tasks.collect-data.results.snapshotSpec)"
714712
- name: ociStorage
715713
value: $(params.ociStorage)
716714
- name: sourceDataArtifact
717-
value: "$(tasks.push-rpm-data-to-pyxis.results.sourceDataArtifact)"
715+
value: "$(tasks.apply-mapping.results.sourceDataArtifact)"
718716
- name: subdirectory
719717
value: $(tasks.collect-data.results.subdirectory)
720718
- name: dataDir
@@ -727,17 +725,17 @@ spec:
727725
value: "$(params.taskGitRevision)"
728726
runAfter:
729727
- collect-data
728+
- apply-mapping
730729
- collect-atlas-params
731-
- push-rpm-data-to-pyxis
732-
- populate-release-notes
730+
- push-snapshot
733731
- name: upload-component-sbom
734732
when:
735733
- input: "$(tasks.collect-atlas-params.results.secretName)"
736734
operator: notin
737735
values: [""]
738736
params:
739737
- name: sbomDir
740-
value: "$(tasks.push-rpm-data-to-pyxis.results.sbomPath)"
738+
value: "$(tasks.update-component-sbom.results.sbomPath)"
741739
- name: atlasSecretName
742740
value: "$(tasks.collect-atlas-params.results.secretName)"
743741
- name: ssoTokenUrl
@@ -747,7 +745,7 @@ spec:
747745
- name: ociStorage
748746
value: $(params.ociStorage)
749747
- name: sourceDataArtifact
750-
value: "$(tasks.apply-mapping.results.sourceDataArtifact)"
748+
value: "$(tasks.update-component-sbom.results.sourceDataArtifact)"
751749
- name: subdirectory
752750
value: $(tasks.collect-data.results.subdirectory)
753751
- name: dataDir
@@ -889,12 +887,14 @@ spec:
889887
operator: notin
890888
values: [""]
891889
params:
892-
- name: dataJsonPath
890+
- name: dataPath
893891
value: "$(tasks.collect-data.results.data)"
892+
- name: snapshotSpec
893+
value: "$(tasks.collect-data.results.snapshotSpec)"
894894
- name: ociStorage
895895
value: $(params.ociStorage)
896896
- name: sourceDataArtifact
897-
value: "$(tasks.populate-release-notes.results.sourceDataArtifact)"
897+
value: "$(tasks.apply-mapping.results.sourceDataArtifact)"
898898
- name: dataDir
899899
value: $(params.dataDir)
900900
- name: trustedArtifactsDebug
@@ -916,16 +916,18 @@ spec:
916916
- name: data
917917
workspace: release-workspace
918918
runAfter:
919+
- apply-mapping
920+
- collect-data
919921
- collect-atlas-params
920-
- populate-release-notes
922+
- push-snapshot
921923
- name: upload-product-sbom
922924
when:
923925
- input: "$(tasks.collect-atlas-params.results.secretName)"
924926
operator: notin
925927
values: [""]
926928
params:
927929
- name: sbomDir
928-
value: "$(tasks.create-product-sbom.results.productSBOMPath)"
930+
value: "$(tasks.create-product-sbom.results.sbomPath)"
929931
- name: atlasSecretName
930932
value: "$(tasks.collect-atlas-params.results.secretName)"
931933
- name: ssoTokenUrl

tasks/managed/create-product-sbom/README.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@ releaseNotes content.
55

66
## Parameters
77

8-
| Name | Description | Optional | Default value |
9-
|-------------------------|----------------------------------------------------------------------------------------------------------------------------|------------|-------------------------|
10-
| dataJsonPath | Path to the JSON string of the merged data containing the release notes | No | - |
11-
| ociStorage | The OCI repository where the Trusted Artifacts are stored | Yes | empty |
12-
| ociArtifactExpiresAfter | Expiration date for the trusted artifacts created in the OCI repository. An empty string means the artifacts do not expire | Yes | 1d |
13-
| trustedArtifactsDebug | Flag to enable debug logging in trusted artifacts. Set to a non-empty string to enable | Yes | "" |
14-
| orasOptions | oras options to pass to Trusted Artifacts calls | Yes | "" |
15-
| sourceDataArtifact | Location of trusted artifacts to be used to populate data directory | Yes | "" |
16-
| dataDir | The location where data will be stored | Yes | $(workspaces.data.path) |
17-
| taskGitUrl | The url to the git repo where the release-service-catalog tasks and stepactions to be used are stored | No | "" |
18-
| taskGitRevision | The revision in the taskGitUrl repo to be used | No | "" |
8+
| Name | Description | Optional | Default value |
9+
|-------------------------|----------------------------------------------------------------------------------------------------------------------------|----------|-------------------------|
10+
| sbomPath | Path in the data directory to store the created SBOM to | Yes | sboms |
11+
| dataPath | Path to the data file from collect-data | No | |
12+
| snapshotSpec | Path to the mapped snapshot spec | No | - |
13+
| ociStorage | The OCI repository where the Trusted Artifacts are stored | Yes | empty |
14+
| ociArtifactExpiresAfter | Expiration date for the trusted artifacts created in the OCI repository. An empty string means the artifacts do not expire | Yes | 1d |
15+
| trustedArtifactsDebug | Flag to enable debug logging in trusted artifacts. Set to a non-empty string to enable | Yes | "" |
16+
| orasOptions | oras options to pass to Trusted Artifacts calls | Yes | "" |
17+
| sourceDataArtifact | Location of trusted artifacts to be used to populate data directory | Yes | "" |
18+
| dataDir | The location where data will be stored | Yes | $(workspaces.data.path) |
19+
| taskGitUrl | The url to the git repo where the release-service-catalog tasks and stepactions to be used are stored | No | "" |
20+
| taskGitRevision | The revision in the taskGitUrl repo to be used | No | "" |
21+
22+
## Changes in 2.0.0
23+
* Task was refactored to use the new SBOM workflow. SBOMs are now generated from the mapped snapshot spec.
24+
* Renamed `productSBOMPath` result to `sbomPath` and param `dataJsonPath` to `dataPath`.
25+
* Added optional `sbomPath` param specifying the path to store the created SBOM to.
26+
* Added `snapshotSpec` param specifying the path to the mapped snapshot spec.
27+
* Fixed executable to run script as module.
1928

2029
## Changes in 1.0.0
2130
* This task now supports Trusted artifacts

tasks/managed/create-product-sbom/create-product-sbom.yaml

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@ kind: Task
44
metadata:
55
name: create-product-sbom
66
labels:
7-
app.kubernetes.io/version: "1.0.0"
7+
app.kubernetes.io/version: "2.0.0"
88
annotations:
99
tekton.dev/pipelines.minVersion: "0.12.1"
1010
tekton.dev/tags: release
1111
spec:
1212
description: >-
13-
Create product-level SBOM from release notes.
13+
Create product-level SBOM from mapped snapshot spec and release notes.
1414
params:
15-
- name: dataJsonPath
15+
- name: dataPath
1616
description: Relative path to the JSON data file in the workspace.
1717
type: string
18+
- name: snapshotSpec
19+
type: string
20+
description: Path to the mapped snapshot spec.
21+
- name: sbomPath
22+
description: Path to store the updated SBOMs to.
23+
type: string
24+
default: "sboms"
1825
- name: ociStorage
1926
description: The OCI repository where the Trusted Artifacts are stored.
2027
type: string
@@ -50,7 +57,7 @@ spec:
5057
- name: data
5158
description: Workspace to save the product-level SBOM to.
5259
results:
53-
- name: productSBOMPath
60+
- name: sbomPath
5461
description: >-
5562
Relative path to the directory containing the created product-level SBOM
5663
in the data workspace.
@@ -103,36 +110,20 @@ spec:
103110
- name: sourceDataArtifact
104111
value: $(params.sourceDataArtifact)
105112
- name: create-sbom
106-
image: quay.io/konflux-ci/release-service-utils:3a1280476a414c7a1538b2db846bcd1fb59176fd
113+
image: quay.io/konflux-ci/release-service-utils:991c2db1fe04f2fddd940605b5383a17692eb4a5
107114
script: |
108115
#!/usr/bin/env bash
109116
set -eux
110117
111-
# the SBOM is first created in a temporary file, because the name of the
112-
# final SBOM depends on its contents; namely the product name and
113-
# version
114-
tmp_sbom="$(mktemp)"
115-
create_product_sbom --data-path "$(params.dataDir)/$(params.dataJsonPath)" \
116-
--output-path "$tmp_sbom"
117-
118-
product_name="$(jq -r '.packages[0].name' "$tmp_sbom")"
119-
product_version="$(jq -r '.packages[0].versionInfo' "$tmp_sbom")"
120-
121-
# replace whitespace with dashes
122-
normalized_name="$(echo -n "${product_name}" | tr '[:space:]' '-')"
123-
124-
sbom_dir="product-sboms"
125-
# the combination of name + version is later used as an ID in Atlas
126-
sbom_path="${sbom_dir}/${normalized_name}-${product_version}.json"
127-
128-
# takes into account the subdirectory of the data.json if any
129-
subdir_sbom_path="$(dirname "$(params.dataJsonPath)")/${sbom_path}"
118+
sbom_path="$(params.dataDir)/$(params.sbomPath)"
119+
mkdir -p "$sbom_path"
130120
131-
output_path=$(params.dataDir)/${subdir_sbom_path}
132-
mkdir -p "$(dirname "$output_path")"
133-
mv "$tmp_sbom" "$output_path"
121+
create_product_sbom \
122+
--data-path "$(params.dataDir)/$(params.dataPath)" \
123+
--snapshot-path "$(params.dataDir)/$(params.snapshotSpec)" \
124+
--output-path "$sbom_path"
134125
135-
echo -n "$(dirname "$subdir_sbom_path")" > "$(results.productSBOMPath.path)"
126+
echo -n "$(params.sbomPath)" > "$(results.sbomPath.path)"
136127
- name: create-trusted-artifact
137128
ref:
138129
resolver: "git"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function create_product_sbom() {
2+
echo Mock create_product_sbom called with: "$*"
3+
echo "$*" >> "$(params.dataDir)/mock_create.txt"
4+
5+
if [[ "$1" != "--data-path" ]] ||
6+
[[ "$2" != "$(params.dataDir)/data.json" ]] ||
7+
[[ "$3" != "--snapshot-path" ]] ||
8+
[[ "$4" != "$(params.dataDir)/snapshot_spec.json" ]] ||
9+
[[ "$5" != "--output-path" ]] ||
10+
[[ "$6" != "$(params.dataDir)/sboms" ]]; then
11+
echo "Error: Unexpected call"
12+
exit 1
13+
fi
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
3+
TASK_PATH=$1
4+
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
5+
6+
yq -i '.spec.steps[2].script = load_str("'$SCRIPT_DIR'/mocks.sh") + .spec.steps[2].script' "$TASK_PATH"

tasks/managed/create-product-sbom/tests/test-create-product-sbom-basic.yaml

Lines changed: 13 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,6 @@ spec:
5454
- name: "DEBUG"
5555
value: "$(params.trustedArtifactsDebug)"
5656
steps:
57-
- name: setup
58-
image: quay.io/konflux-ci/release-service-utils:3a1280476a414c7a1538b2db846bcd1fb59176fd
59-
script: |
60-
#!/usr/bin/env sh
61-
set -eux
62-
63-
mkdir -p "$(params.dataDir)/$(context.pipelineRun.uid)"
64-
cat > "$(params.dataDir)/$(context.pipelineRun.uid)"/data.json << EOF
65-
{
66-
"releaseNotes": {
67-
"product_name": "Red Hat Openstack Product",
68-
"product_version": "123",
69-
"cpe": "cpe:/a:example:openstack:el8",
70-
"content": {
71-
"images": [
72-
{
73-
"component": "test-component-1",
74-
"purl": "test-component-1-purl-1"
75-
},
76-
{
77-
"component": "test-component-2",
78-
"purl": "test-component-2-purl-1"
79-
}
80-
]
81-
}
82-
}
83-
}
84-
EOF
8557
- name: skip-trusted-artifact-operations
8658
ref:
8759
name: skip-trusted-artifact-operations
@@ -112,8 +84,12 @@ spec:
11284
taskRef:
11385
name: create-product-sbom
11486
params:
115-
- name: dataJsonPath
116-
value: "$(context.pipelineRun.uid)/data.json"
87+
- name: dataPath
88+
value: "data.json"
89+
- name: snapshotSpec
90+
value: "snapshot_spec.json"
91+
- name: sbomPath
92+
value: "sboms"
11793
- name: ociStorage
11894
value: $(params.ociStorage)
11995
- name: orasOptions
@@ -139,7 +115,7 @@ spec:
139115
workspace: tests-workspace
140116
params:
141117
- name: sbomDir
142-
value: $(tasks.run-task.results.productSBOMPath)
118+
value: $(tasks.run-task.results.sbomPath)
143119
- name: sourceDataArtifact
144120
value: "$(tasks.run-task.results.sourceDataArtifact)=$(params.dataDir)"
145121
- name: dataDir
@@ -186,43 +162,16 @@ spec:
186162
- name: sourceDataArtifact
187163
value: $(params.sourceDataArtifact)
188164
- name: check-result
189-
image: quay.io/konflux-ci/release-service-utils:3a1280476a414c7a1538b2db846bcd1fb59176fd
165+
image: quay.io/konflux-ci/release-service-utils:991c2db1fe04f2fddd940605b5383a17692eb4a5
190166
script: |
191167
#!/usr/bin/env bash
192168
set -eux
193169
194-
cp "$(params.dataDir)/$(params.sbomDir)/Red-Hat-Openstack-Product-123.json" sbom.json
195-
196-
test "$(jq -r '.name' sbom.json)" == "Red Hat Openstack Product 123"
197-
198-
# Check product SPDX package and relationship
199-
test "$(jq -r '.packages[0].SPDXID' sbom.json)" == "SPDXRef-product"
200-
test "$(jq -r '.packages[0].name' sbom.json)" == "Red Hat Openstack Product"
201-
test "$(jq -r '.packages[0].versionInfo' sbom.json)" == "123"
202-
test "$(jq -r '.packages[0].externalRefs[0].referenceLocator' sbom.json)" == \
203-
"cpe:/a:example:openstack:el8"
204-
205-
test "$(jq -r '.relationships[0].relationshipType' sbom.json)" == "DESCRIBES"
206-
test "$(jq -r '.relationships[0].relatedSpdxElement' sbom.json)" == "SPDXRef-product"
207-
208-
# Check component SPDX packages and relationships
209-
# Component 1
210-
test "$(jq -r '.packages[1].name' sbom.json)" == "test-component-1"
211-
test "$(jq -r '.packages[1].externalRefs[0].referenceLocator' sbom.json)" == \
212-
"test-component-1-purl-1"
213-
214-
test "$(jq -r '.relationships[1].relationshipType' sbom.json)" == "PACKAGE_OF"
215-
test "$(jq -r '.relationships[1].spdxElementId' sbom.json)" == "SPDXRef-component-0"
216-
217-
# Component 2
218-
test "$(jq -r '.packages[2].name' sbom.json)" == "test-component-2"
219-
test "$(jq -r '.packages[2].externalRefs[0].referenceLocator' sbom.json)" == \
220-
"test-component-2-purl-1"
221-
222-
test "$(jq -r '.relationships[2].relationshipType' sbom.json)" == "PACKAGE_OF"
223-
test "$(jq -r '.relationships[2].spdxElementId' sbom.json)" == "SPDXRef-component-1"
170+
if [ "$(wc -l < "$(params.dataDir)/mock_create.txt")" != 1 ]; then
171+
echo Error: create_product_sbom was expected to be called 1 time. Actual calls:
172+
cat "$(params.dataDir)/mock_update.txt"
173+
exit 1
174+
fi
224175
225-
test "$(jq -r '.packages | length' sbom.json)" == 3
226-
test "$(jq -r '.relationships | length' sbom.json)" == 3
227176
runAfter:
228177
- run-task

0 commit comments

Comments
 (0)