@@ -59,62 +59,124 @@ runs:
59
59
echo "IMAGE_NAME=$IMAGE_NAME" >> $GITHUB_ENV
60
60
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
61
61
62
+ # TODO (@NickLarsenNZ): Make this a reusable action in .github/actions/push-and-sign/action.yml
62
63
- name : Push Image to repo.stackable.tech and sign via cosign
63
64
shell : bash
64
65
run : |
65
66
set -euo pipefail
66
- docker image push "$(< bake-target-tags)"
67
+ TARGET_TAG="$(< bake-target-tags)"
68
+ docker image push "$TARGET_TAG"
67
69
# Obtain the digest of the image, because signing by tag is deprecated and will be removed from cosign in the future
68
- DIGEST=$(docker images --digests "$(< bake-target-tags)" --format '{{.Digest}}')
69
- echo "DIGEST=$DIGEST" >> $GITHUB_ENV
70
+ # This must be done after a push, otherwise the repo digest is empty.
71
+ # Find the digest for the image. Notice the architecture at the end of TAG
72
+ # IMAGE_VERSION does not contain the architecture (otherwise we could have used ${IMAGE_NAME}:${IMAGE_VERSION})
73
+ # Given:
74
+ # IMAGE_NAME: docker.stackable.tech/stackable/hello-world
75
+ # TARGET_TAG: docker.stackable.tech/stackable/hello-world:0.0.1-SNAPSHOT-stackable0.0.0-dev-arm64
76
+ # Expect:
77
+ # STDOUT: docker.stackable.tech/stackable/hello-world@sha256:917f800259ef4915f976e93987b752fd64debf347568610d7f685d20220fc88a
78
+ REPO_DIGEST=$(
79
+ docker inspect "$TARGET_TAG" --format json | \
80
+ jq -r \
81
+ --arg IMAGE_NAME "$IMAGE_NAME" \
82
+ --arg TARGET_TAG "$TARGET_TAG" \
83
+ '
84
+ map(select(.RepoTags[] | contains($TARGET_TAG)))[0]
85
+ | .RepoDigests[]
86
+ | select(. | startswith($IMAGE_NAME))
87
+ '
88
+ )
89
+ # Ensure REPO_DIGEST is not empty
90
+ if [[ -z "$REPO_DIGEST" ]]; then
91
+ >&2 echo "Repo Digest is empty, but is required for signing"
92
+ exit 1
93
+ fi
94
+
95
+ # Needed by future steps
96
+ echo "REPO_DIGEST=$REPO_DIGEST" | tee -a $GITHUB_ENV
97
+
70
98
# Refer to image via its digest (docker.stackable.tech/stackable/airflow@sha256:0a1b2c...)
71
99
# This generates a signature and publishes it to the registry, next to the image
72
100
# Uses the keyless signing flow with Github Actions as identity provider
73
- cosign sign -y "$IMAGE_NAME@$DIGEST "
101
+ cosign sign -y "${REPO_DIGEST} "
74
102
75
103
- name : Generate SBOM for the Nexus Image
76
104
shell : bash
77
105
run : |
78
106
set -euo pipefail
79
- syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${{ inputs.product }}" --source-version "$TAG_NAME" "$IMAGE_NAME@$DIGEST";
107
+ syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${{ inputs.product }}" --source-version "$TAG_NAME" "${REPO_DIGEST}";
108
+ # The DIGEST is the right side of `REPO_DIGEST` (split by '@')
109
+ DIGEST=${REPO_DIGEST#*@}
80
110
# Determine the PURL for the image
81
111
PURL="pkg:docker/stackable/${{ inputs.product }}@$DIGEST?repository_url=docker.stackable.tech";
82
112
# Get metadata from the image
83
- IMAGE_METADATA_DESCRIPTION=$(docker inspect --format='{{.Config.Labels.description}}' "$IMAGE_NAME@$DIGEST ");
84
- IMAGE_METADATA_NAME=$(docker inspect --format='{{.Config.Labels.name}}' "$IMAGE_NAME@$DIGEST ");
113
+ IMAGE_METADATA_DESCRIPTION=$(docker inspect --format='{{.Config.Labels.description}}' "${REPO_DIGEST} ");
114
+ IMAGE_METADATA_NAME=$(docker inspect --format='{{.Config.Labels.name}}' "${REPO_DIGEST} ");
85
115
# Merge the SBOM with the metadata for the image
86
116
jq -s '{"metadata":{"component":{"description":"'"$IMAGE_METADATA_NAME. $IMAGE_METADATA_DESCRIPTION"'","supplier":{"name":"Stackable GmbH","url":["https://stackable.tech/"]},"author":"Stackable GmbH","purl":"'"$PURL"'","publisher":"Stackable GmbH"}}} * .[0]' sbom.json > sbom.merged.json;
87
117
# Attest the SBOM to the image
88
- cosign attest -y --predicate sbom.merged.json --type cyclonedx "$IMAGE_NAME@$DIGEST "
118
+ cosign attest -y --predicate sbom.merged.json --type cyclonedx "${REPO_DIGEST} "
89
119
120
+ # TODO (@NickLarsenNZ): Make this a reusable action in .github/actions/push-and-sign/action.yml
90
121
- name : Push Image to oci.stackable.tech and sign via cosign
91
122
shell : bash
92
123
run : |
93
124
set -euo pipefail
125
+ # Update the registry
94
126
IMAGE_NAME=oci.stackable.tech/sdp/${{ inputs.product }}
95
- echo "image: $IMAGE_NAME"
96
- docker tag "$(< bake-target-tags)" "$IMAGE_NAME:$TAG_NAME"
97
- docker image push "$(< bake-target-tags)"
127
+ # IMAGE_NAME is needed by future steps
128
+ echo "IMAGE_NAME=$IMAGE_NAME" | tee -a $GITHUB_ENV
129
+ OLD_TARGET_TAG="$(< bake-target-tags)"
130
+ TARGET_TAG="$IMAGE_NAME:$TAG_NAME"
131
+ docker tag "$OLD_TARGET_TAG" "$TARGET_TAG"
132
+ docker image push "$TARGET_TAG"
98
133
# Obtain the digest of the image, because signing by tag is deprecated and will be removed from cosign in the future
99
- DIGEST=$(docker images --digests "$(< bake-target-tags)" --format '{{.Digest}}')
100
- echo "DIGEST=$DIGEST" >> $GITHUB_ENV
134
+ # This must be done after a push, otherwise the repo digest is empty.
135
+ # Find the digest for the image. Notice the architecture at the end of TAG
136
+ # IMAGE_VERSION does not contain the architecture (otherwise we could have used ${IMAGE_NAME}:${IMAGE_VERSION})
137
+ # Given:
138
+ # IMAGE_NAME: oci.stackable.tech/sdp/hello-world
139
+ # TARGET_TAG: oci.stackable.tech/sdp/hello-world:0.0.1-SNAPSHOT-stackable0.0.0-dev-arm64
140
+ # Expect:
141
+ # STDOUT: oci.stackable.tech/sdp/hello-world@sha256:917f800259ef4915f976e93987b752fd64debf347568610d7f685d20220fc88a
142
+ REPO_DIGEST=$(
143
+ docker inspect "$TARGET_TAG" --format json | \
144
+ jq -r \
145
+ --arg IMAGE_NAME "$IMAGE_NAME" \
146
+ --arg TARGET_TAG "$TARGET_TAG" \
147
+ '
148
+ map(select(.RepoTags[] | contains($TARGET_TAG)))[0]
149
+ | .RepoDigests[]
150
+ | select(. | startswith($IMAGE_NAME))
151
+ '
152
+ )
153
+ # Ensure REPO_DIGEST is not empty
154
+ if [[ -z "$REPO_DIGEST" ]]; then
155
+ >&2 echo "Repo Digest is empty, but is required for signing"
156
+ exit 1
157
+ fi
158
+
159
+ # REPO_DIGEST is needed by future steps
160
+ echo "REPO_DIGEST=$REPO_DIGEST" | tee -a $GITHUB_ENV
161
+
101
162
# Refer to image via its digest (oci.stackable.tech/sdp/airflow@sha256:0a1b2c...)
102
163
# This generates a signature and publishes it to the registry, next to the image
103
164
# Uses the keyless signing flow with Github Actions as identity provider
104
- cosign sign -y "$IMAGE_NAME@$DIGEST "
165
+ cosign sign -y "${REPO_DIGEST} "
105
166
106
167
- name : Generate SBOM for the Harbor Image
107
168
shell : bash
108
169
run : |
109
170
set -euo pipefail
110
- IMAGE_NAME=oci.stackable.tech/sdp/${{ inputs.product }}
111
- syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${{ inputs.product }}" --source-version "$TAG_NAME" "$IMAGE_NAME@$DIGEST";
171
+ syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${{ inputs.product }}" --source-version "$TAG_NAME" "${REPO_DIGEST}";
172
+ # The DIGEST is the right side of `REPO_DIGEST` (split by '@')
173
+ DIGEST=${REPO_DIGEST#*@}
112
174
# Determine the PURL for the image
113
175
PURL="pkg:docker/sdp/${{ inputs.product }}@$DIGEST?repository_url=oci.stackable.tech";
114
176
# Get metadata from the image
115
- IMAGE_METADATA_DESCRIPTION=$(docker inspect --format='{{.Config.Labels.description}}' "$IMAGE_NAME@$DIGEST ");
116
- IMAGE_METADATA_NAME=$(docker inspect --format='{{.Config.Labels.name}}' "$IMAGE_NAME@$DIGEST ");
177
+ IMAGE_METADATA_DESCRIPTION=$(docker inspect --format='{{.Config.Labels.description}}' "${REPO_DIGEST} ");
178
+ IMAGE_METADATA_NAME=$(docker inspect --format='{{.Config.Labels.name}}' "${REPO_DIGEST} ");
117
179
# Merge the SBOM with the metadata for the image
118
180
jq -s '{"metadata":{"component":{"description":"'"$IMAGE_METADATA_NAME. $IMAGE_METADATA_DESCRIPTION"'","supplier":{"name":"Stackable GmbH","url":["https://stackable.tech/"]},"author":"Stackable GmbH","purl":"'"$PURL"'","publisher":"Stackable GmbH"}}} * .[0]' sbom.json > sbom.merged.json;
119
181
# Attest the SBOM to the image
120
- cosign attest -y --predicate sbom.merged.json --type cyclonedx "$IMAGE_NAME@$DIGEST "
182
+ cosign attest -y --predicate sbom.merged.json --type cyclonedx "${REPO_DIGEST} "
0 commit comments