Skip to content

Commit 224baa8

Browse files
committed
feat: pro rock in ACR (WIP)
Jobs to be done: Rebuild, Continuous scanning
1 parent 3eeecd0 commit 224baa8

11 files changed

Lines changed: 397 additions & 62 deletions

File tree

.github/actions/commit-releases-json/action.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ runs:
4747
git config user.name "${{ inputs.actor }}"
4848
4949
git add oci/${{ inputs.image-name }}/_releases.json
50+
if [[ -f oci/${{ inputs.image-name }}/_pro_releases.json ]]; then
51+
git add oci/${{ inputs.image-name }}/_pro_releases.json
52+
fi
5053
git commit -m "${{ inputs.message }}"
5154
5255
for i in {1..10}; do

.github/actions/fetch-releases-json/copy-releases-files.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ if [[ "$RUNNER_DEBUG" == "1" ]]; then
1414
fi
1515

1616
if [[ "$image_name" = "*" ]]; then
17-
echo "Copying all _releases.json files"
17+
echo "Copying all _releases.json (including _pro_releases.json) files"
1818
cd "$directory" || exit 1
1919
find . -name "_releases.json" -exec cp --parents {} "$OLDPWD" \;
20+
find . -name "_pro_releases.json" -exec cp --parents {} "$OLDPWD" \;
2021
cd "$OLDPWD" || exit 1
2122
elif [[ -f "$directory/oci/$image_name/_releases.json" ]]; then
2223
cp "$directory/oci/$image_name/_releases.json" "oci/$image_name/_releases.json"
24+
if [[ -f "$directory/oci/$image_name/_pro_releases.json" ]]; then
25+
cp "$directory/oci/$image_name/_pro_releases.json" "oci/$image_name/_pro_releases.json"
26+
fi
2327
fi

.github/workflows/Image.yaml

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,11 @@ jobs:
197197
rock-repo-commit: ${{ matrix.commit }}
198198
rockfile-directory: ${{ matrix.directory }}
199199
lpci-fallback: true
200-
secrets: inherit
200+
pro-services: ${{ matrix.pro-services }}
201+
secrets:
202+
source-github-token: ${{ secrets.ROCKSBOT_TOKEN }}
203+
pro-token: ${{ secrets[matrix.pro-token] }}
204+
pro-artifact-passphrase: ${{ secrets[matrix.pro-artifact-passphrase] }}
201205

202206
test-rock:
203207
needs: [prepare-build, build-rock]
@@ -210,7 +214,8 @@ jobs:
210214
oci-archive-name: "${{ matrix.name }}_${{ matrix.commit }}_${{ matrix.dir_identifier }}"
211215
trivyignore-path: ${{ matrix.ignored-vulnerabilities == '' && format('oci/{0}/.trivyignore', matrix.name) || '' }}
212216
ignored-vulnerabilities: ${{ matrix.ignored-vulnerabilities }}
213-
secrets: inherit
217+
secrets:
218+
pro-artifact-passphrase: ${{ secrets[matrix.pro-artifact-passphrase] }}
214219

215220
prepare-upload:
216221
runs-on: self-hosted-linux-amd64-noble-private-endpoint-small
@@ -318,7 +323,7 @@ jobs:
318323
UMOCI_VERSION: "v0.4.7"
319324
UMOCI_BINARY: "umoci.amd64"
320325
outputs:
321-
artefacts-hashes: ${{ steps.artefacts-hashes.outputs.hashes }}
326+
artifacts-hashes: ${{ steps.artifacts-hashes.outputs.hashes }}
322327

323328
permissions:
324329
packages: write
@@ -350,7 +355,17 @@ jobs:
350355
with:
351356
name: ${{ env.OCI_ARCHIVE_NAME }}
352357

353-
- name: Name output artefact
358+
- name: Decrypt pro artifact
359+
if: ${{ matrix.pro-services != '' }}
360+
uses: ./.github/actions/crypt-artifact
361+
with:
362+
mode: decrypt
363+
input-path: ${{ env.OCI_ARCHIVE_NAME }}.gpg
364+
passphrase: ${{ secrets[matrix.pro-artifact-passphrase] }}
365+
output-path: ${{ env.OCI_ARCHIVE_NAME }}
366+
preserve-original: false
367+
368+
- name: Name output artifact
354369
id: rename-oci-archive
355370
run: |
356371
# Rename the OCI archive tarball
@@ -460,8 +475,8 @@ jobs:
460475
name: ${{ env.OCI_ARCHIVE_NAME }}${{ env.VULNERABILITY_REPORT_SUFFIX }}
461476

462477
# https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md
463-
- name: Calculate artefacts hashes
464-
id: artefacts-hashes
478+
- name: Calculate artifacts hashes
479+
id: artifacts-hashes
465480
env:
466481
VULN_REPORT: ${{ env.OCI_ARCHIVE_NAME }}${{ env.VULNERABILITY_REPORT_SUFFIX }}
467482
SBOMS: ${{ steps.generate-sboms.outputs.sboms }}
@@ -475,6 +490,7 @@ jobs:
475490
476491
- name: Login to GHCR
477492
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121
493+
if: ${{ matrix.pro-services == '' }}
478494
with:
479495
registry: ghcr.io
480496
username: ${{ github.actor }}
@@ -487,16 +503,26 @@ jobs:
487503
path: ${{ steps.generate-sboms.outputs.sboms }}
488504
if-no-files-found: error
489505

506+
- name: Encrypt pro artifact
507+
if: ${{ matrix.pro-services != '' }}
508+
uses: ./.github/actions/crypt-artifact
509+
with:
510+
mode: encrypt
511+
input-path: ${{ steps.rename-oci-archive.outputs.name }}
512+
passphrase: ${{ secrets[matrix.pro-artifact-passphrase] }}
513+
output-path: ${{ steps.rename-oci-archive.outputs.name }}.gpg
514+
490515
- name: Upload image
491516
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
492517
with:
493518
name: ${{ steps.rename-oci-archive.outputs.name }}
494-
path: ${{ steps.rename-oci-archive.outputs.name }}
519+
path: ${{ matrix.pro-services == '' && steps.rename-oci-archive.outputs.name || format('{0}.gpg', steps.rename-oci-archive.outputs.name) }}
495520
if-no-files-found: error
496521

497522
- name: Upload to GHCR
498523
id: upload-image
499524
uses: ./.github/actions/upload-rock
525+
if: ${{ matrix.pro-services == '' }}
500526
with:
501527
artifact_name: ${{ env.OCI_ARCHIVE_NAME }}
502528
name: ${{ github.repository_owner }}/oci-factory/${{ matrix.name }}
@@ -521,12 +547,14 @@ jobs:
521547
MATRIX_NAME: ${{ matrix.name }}
522548
MATRIX_TRACK: ${{ matrix.track }}
523549
MATRIX_REVISION: ${{ matrix.revision }}
550+
PRO_SERVICES: ${{ matrix.pro-services }}
524551
STEPS_GENERATE_SBOMS_OUTPUTS_SBOMS: ${{ steps.generate-sboms.outputs.sboms }}
525552
run: |
526553
jq --arg base "${MATRIX_BASE}" \
527554
--arg digest "${STEPS_UPLOAD_IMAGE_OUTPUTS_DIGEST}" \
528555
--arg ignored_vulnerabilities "${MATRIX_IGNORED_VULNERABILITIES}" \
529-
'. + {base: $base, digest: $digest, "ignored-vulnerabilities": $ignored_vulnerabilities}' \
556+
--arg pro_services "${PRO_SERVICES}" \
557+
'. + {base: $base, digest: $digest, "ignored-vulnerabilities": $ignored_vulnerabilities, "pro-services": $pro_services}' \
530558
<<< '${{ toJSON(matrix) }}' > build_metadata.json
531559
./src/uploads/upload_to_swift.sh \
532560
"${MATRIX_NAME}" \
@@ -694,7 +722,7 @@ jobs:
694722
# contents: write # Needed for release uploads
695723
# uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@7f4fdb871876c23e455853d694197440c5a91506
696724
# with:
697-
# base64-subjects: "${{ needs.upload.outputs.artefacts-hashes }}"
725+
# base64-subjects: "${{ needs.upload.outputs.artifacts-hashes }}"
698726

699727
notify:
700728
runs-on: ubuntu-22.04

.github/workflows/Release.yaml

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ jobs:
8585
needs: [validate-push-release-request]
8686
outputs:
8787
gh-releases-matrix: ${{ steps.release-image.outputs.gh-releases-matrix }}
88+
is-public-release: ${{ steps.release-type.outputs.is-public-release }}
89+
is-pro-release: ${{ steps.release-type.outputs.is-pro-release }}
8890
env:
8991
IS_PROD: ${{ ! startsWith(inputs.oci-image-name, 'mock-') }}
9092
RELEASES_BRANCH: _releases
@@ -108,6 +110,62 @@ jobs:
108110
key: ${{ inputs.image-trigger-cache-key }}
109111
fail-on-cache-miss: true
110112

113+
114+
# Use yq to find out if `pro-release` is present and non-empty in the image trigger.
115+
- name: Release type
116+
id: release-type
117+
run: |
118+
set -e
119+
if [[ "$RUNNER_DEBUG" == "1" ]]; then
120+
set -x
121+
fi
122+
source src/shared/logs.sh
123+
image_trigger_file="oci/${INPUTS_OCI_IMAGE_NAME}/image.yaml"
124+
yq eval '.["pro-release"] | length > 0' "$image_trigger_file" > is_pro_release.txt
125+
yq eval '.["release"] | length > 0' "$image_trigger_file" > is_public_release.txt
126+
is_pro_release=$(cat is_pro_release.txt)
127+
echo "is-pro-release=$is_pro_release" >> "$GITHUB_OUTPUT"
128+
is_public_release=$(cat is_public_release.txt)
129+
echo "is-public-release=$is_public_release" >> "$GITHUB_OUTPUT"
130+
env:
131+
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
132+
133+
# Download the image if `pro-release` is present and non-empty in the image trigger.
134+
# pattern should match <image_name>_<version>-<base>_*, e.g., mock-rock_1.2-22.04_*
135+
- name: Download image artifact
136+
id: download-image-artifact
137+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
138+
if: ${{ steps.release-type.outputs.is-pro-release == 'true' }}
139+
env:
140+
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
141+
with:
142+
pattern: +([A-Za-z0-9-])_+([A-Za-z0-9.-])-[0-9][0-9].[0-9][0-9]_+([0-9])
143+
merge-multiple: true
144+
145+
# Decrypt the Pro image artifact being downloaded.
146+
# They are encrypted with GPG, and has the same name as the downloaded artifact, but with .gpg extension.
147+
# put a for loop to use the script ./.github/action/crypt-artifact/crypt-artifact.sh to decrypt the artifact,
148+
- name: Decrypt Pro image artifact
149+
id: decrypt-pro-image-artifact
150+
if: ${{ steps.release-type.outputs.is-pro-release == 'true' }}
151+
run: |
152+
set -e
153+
if [[ "$RUNNER_DEBUG" == "1" ]]; then
154+
set -x
155+
fi
156+
source src/shared/logs.sh
157+
artifact_path="${{ steps.download-image-artifact.outputs.download-path }}"
158+
for artifact in $artifact_path/*.gpg; do
159+
if [ -f "$artifact" ]; then
160+
log_info "Decrypting artifact: $artifact"
161+
./.github/actions/crypt-artifact/crypt-artifact.sh decrypt \
162+
-i "$artifact" \
163+
-p "${{ secrets.ROCKS_PRO_ARTIFACT_PASSPHRASE }}"
164+
else
165+
log_info "No .gpg artifacts found to decrypt."
166+
fi
167+
done
168+
111169
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
112170
with:
113171
python-version: "3.x"
@@ -139,6 +197,7 @@ jobs:
139197

140198
- name: Do releases from ${{ inputs.oci-image-name }}
141199
id: release-image
200+
if: ${{ steps.release-type.outputs.is-public-release == 'true' }}
142201
env:
143202
# GH has issues with boolean expressions
144203
# https://github.com/actions/runner/issues/1483
@@ -174,7 +233,34 @@ jobs:
174233
--all-revision-tags "${STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE}" \
175234
--ghcr-repo "${{ github.repository_owner }}/oci-factory"
176235
236+
- name: Do Pro releases from ${{ inputs.oci-image-name }}
237+
if: ${{ steps.release-type.outputs.is-pro-release == 'true' }}
238+
id: release-pro-image
239+
env:
240+
# GH has issues with boolean expressions
241+
ACR_CREDS_USR: ${{ env.IS_PROD == 'true' && secrets.ACR_CREDS_USR || secrets.ACR_CREDS_USR_DEV }}
242+
ACR_CREDS_PSW: ${{ env.IS_PROD == 'true' && secrets.ACR_CREDS_PSW || secrets.ACR_CREDS_PSW_DEV }}
243+
ACR_REGISTRY: ${{ env.IS_PROD == 'true' && 'ubuntu.azurecr.io' || secrets.ACR_REGISTRY_DEV }}
244+
PYTHONUNBUFFERED: 1
245+
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
246+
STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE: ${{ steps.get-all-canonical-tags.outputs.canonical-tags-file }}
247+
run: |
248+
set -e
249+
if [[ "$RUNNER_DEBUG" == "1" ]]; then
250+
set -x
251+
fi
252+
source src/shared/logs.sh
253+
log_info "Running in production? $([[ "$IS_PROD" == "true" ]] && echo YES || echo NO)"
254+
255+
python3 -m src.image.release \
256+
--image-trigger oci/${INPUTS_OCI_IMAGE_NAME}/image.yaml \
257+
--image-name ${INPUTS_OCI_IMAGE_NAME} \
258+
--all-releases oci/${INPUTS_OCI_IMAGE_NAME}/_releases.json \
259+
--all-revision-tags "${STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE}" \
260+
--pro
261+
177262
- name: Update _releases.json
263+
if: ${{ steps.release-type.outputs.is-public-release == 'true' }}
178264
run: |
179265
python3 -m src.image.release \
180266
--image-trigger oci/${INPUTS_OCI_IMAGE_NAME}/image.yaml \
@@ -186,27 +272,53 @@ jobs:
186272
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
187273
STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE: ${{ steps.get-all-canonical-tags.outputs.canonical-tags-file }}
188274

275+
- name: Update _pro_releases.json
276+
if: ${{ steps.release-type.outputs.is-pro-release == 'true' }}
277+
run: |
278+
python3 -m src.image.release \
279+
--image-trigger oci/${INPUTS_OCI_IMAGE_NAME}/image.yaml \
280+
--image-name ${INPUTS_OCI_IMAGE_NAME} \
281+
--all-releases oci/${INPUTS_OCI_IMAGE_NAME}/_pro_releases.json \
282+
--all-revision-tags "${STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE}" \
283+
--update-releases-json \
284+
--pro
285+
env:
286+
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
287+
STEPS_GET_ALL_CANONICAL_TAGS_OUTPUTS_CANONICAL_TAGS_FILE: ${{ steps.get-all-canonical-tags.outputs.canonical-tags-file }}
288+
189289
- name: Overwrite _releases.json
290+
if: ${{ steps.release-type.outputs.is-public-release == 'true' }}
190291
run: |
191292
mkdir -p ${{ env.RELEASE_REPO_DIR }}/oci/${INPUTS_OCI_IMAGE_NAME}
192293
cp oci/${INPUTS_OCI_IMAGE_NAME}/_releases.json ${{ env.RELEASE_REPO_DIR }}/oci/${INPUTS_OCI_IMAGE_NAME}/_releases.json
193294
env:
194295
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
195296

297+
- name: Overwrite _pro_releases.json
298+
if: ${{ steps.release-type.outputs.is-pro-release == 'true' }}
299+
run: |
300+
mkdir -p ${{ env.RELEASE_REPO_DIR }}/oci/${INPUTS_OCI_IMAGE_NAME}
301+
cp oci/${INPUTS_OCI_IMAGE_NAME}/_pro_releases.json ${{ env.RELEASE_REPO_DIR }}/oci/${INPUTS_OCI_IMAGE_NAME}/_pro_releases.json
302+
env:
303+
INPUTS_OCI_IMAGE_NAME: ${{ inputs.oci-image-name }}
304+
196305
# Commit with actor's GitHub noreply email to pass CLA and keep the privacy of the actor
197306
# Use force push, to bypass the branch protection rules
198307
- name: Commit oci/${{ inputs.oci-image-name }}/_releases.json
199308
uses: ./.github/actions/commit-releases-json
200309
with:
201310
directory: ${{ env.RELEASE_REPO_DIR }}
202311
image-name: ${{ inputs.oci-image-name }}
203-
message: 'ci: automatically update oci/${{ inputs.oci-image-name }}/_releases.json, from ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
312+
message: 'ci: automatically update releases in oci/${{ inputs.oci-image-name }}/, from ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
204313
email: '${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com'
205314

206315

207316
update-documentation:
208317
name: Update documentation
209318
needs: [do-releases]
319+
# Documentation should only be updated for public releases, not for pro releases.
320+
# As ACR does not have a Web UI.
321+
if: ${{ needs.do-releases.outputs.is-public-release == 'true' }}
210322
uses: ./.github/workflows/Documentation.yaml
211323
with:
212324
oci-image-name: "${{ inputs.oci-image-name }}"

oci/mock-rock/image.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ upload:
5555
ignored-vulnerabilities:
5656
- "CVE-2023-1234"
5757
- "CVE-2023-5678"
58+
- source: "canonical/rocks-toolbox"
59+
commit: eee5f5ebeff62848903156fb3fe93c5d37174085
60+
directory: mock_rock/1.2
61+
pro:
62+
services:
63+
- esm-infra
64+
- esm-apps
65+
config:
66+
token: secrets.ROCKS_PRO_TOKEN
67+
artifact-passphrase: secrets.ROCKS_PRO_ARTIFACT_PASSPHRASE
68+
release:
69+
1.2-22.04:
70+
end-of-life: "2030-05-01T00:00:00Z"
71+
risks:
72+
- beta
73+
ignored-vulnerabilities:
74+
- "CVE-2023-1234"
75+
- "CVE-2023-5678"
5876
# TODO: Restore the devel release once the https://github.com/canonical/rockcraft/issues/1262 is resolved.
5977
# - source: "canonical/rocks-toolbox"
6078
# commit: bb9138fbe81f893b4303a0e29df7cf9581069de0

0 commit comments

Comments
 (0)