Skip to content

Commit 3b7b748

Browse files
authored
Pushing multi arch images to Nexus and Harbor (#738)
* Pushing multi arch images to Nexus and Harbor * Create manifest list, push it and sign it * Add build dependency to manifest creation * moving harbor destination to input variable for workflow_dipatch * Make job titles more speaking * Adding cosign install to manifest list creation * Using digest for manifest creation * Making shellcheck happy * Making shellcheck happy 2 * Making shellcheck happy 3 * Hardcoding harbor dest like nexus
1 parent a901f2e commit 3b7b748

File tree

1 file changed

+112
-41
lines changed

1 file changed

+112
-41
lines changed

.github/workflows/mirror.yaml

Lines changed: 112 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,115 @@
11
---
2-
name: Mirror container image
3-
on:
4-
workflow_dispatch:
5-
inputs:
6-
src:
7-
description: 'Location of the source image (example: registry.k8s.io/git-sync/git-sync:v3.6.4)'
8-
required: true
9-
dst:
10-
description: 'Name and tag of the destination image (example: git-sync:v3.6.4)'
11-
required: true
2+
name: Mirror container image
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
src:
7+
description: 'Location of the source image (example: registry.k8s.io/git-sync/git-sync:v3.6.4)'
8+
required: true
9+
dst:
10+
description: 'Name and tag of the destination image (example: git-sync:v3.6.4)'
11+
required: true
1212

13-
env:
14-
DST_REGISTRY: oci.stackable.tech
15-
DST_PROJECT: sdp
13+
env:
14+
DST_REGISTRY_HARBOR: oci.stackable.tech
15+
DST_REGISTRY_NEXUS: docker.stackable.tech
16+
DST_PROJECT_NEXUS: k8s
17+
DST_PROJECT_HARBOR: sdp
1618

17-
jobs:
18-
mirror-image:
19-
runs-on: ubuntu-latest
20-
permissions:
21-
id-token: write
22-
steps:
23-
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
24-
with:
25-
registry: ${{ env.DST_REGISTRY }}
26-
username: "robot$sdp+github-action-build"
27-
password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }}
28-
- name: Pull image from source registry
29-
run: docker pull "${{ github.event.inputs.src }}"
30-
- name: Retag image
31-
run: docker tag "${{ github.event.inputs.src }}" "$DST_REGISTRY/$DST_PROJECT/${{ github.event.inputs.dst }}"
32-
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
33-
- name: Push image to destination registry
34-
run: |
35-
DOCKER_OUTPUT=$(docker push "$DST_REGISTRY/$DST_PROJECT/${{ github.event.inputs.dst }}");
36-
# Obtain the digest of the pushed image from the output of `docker push`, because signing by tag is deprecated and will be removed from cosign in the future
37-
REPO_DIGEST_OF_IMAGE=$(echo "$DOCKER_OUTPUT" | awk '/^\S+: digest: sha256:[0-9a-f]{64} size: [0-9]+$/ { print $3 }');
38-
if [ -z "$REPO_DIGEST_OF_IMAGE" ]; then
39-
echo "Could not find repo digest for container image: $DST_REGISTRY/$DST_PROJECT/${{ github.event.inputs.dst }}"
40-
exit 1
41-
fi
42-
# This generates a signature and publishes it to the registry, next to the image
43-
# Uses the keyless signing flow with Github Actions as identity provider
44-
cosign sign -y "$DST_REGISTRY/$DST_PROJECT/${{ github.event.inputs.dst }}@$REPO_DIGEST_OF_IMAGE"
19+
jobs:
20+
mirror-image:
21+
name: Pull, Retag and Push dependencies for ${{ github.event.inputs.dst }}
22+
runs-on: ubuntu-latest
23+
strategy:
24+
matrix:
25+
architecture:
26+
- "amd64"
27+
- "arm64"
28+
permissions:
29+
id-token: write
30+
outputs:
31+
REPO_DIGEST_OF_IMAGE_HARBOR_amd64: ${{ steps.push.outputs.REPO_DIGEST_OF_IMAGE_HARBOR_amd64 }}
32+
REPO_DIGEST_OF_IMAGE_HARBOR_arm64: ${{ steps.push.outputs.REPO_DIGEST_OF_IMAGE_HARBOR_arm64 }}
33+
REPO_DIGEST_OF_IMAGE_NEXUS_amd64: ${{ steps.push.outputs.REPO_DIGEST_OF_IMAGE_NEXUS_amd64 }}
34+
REPO_DIGEST_OF_IMAGE_NEXUS_arm64: ${{ steps.push.outputs.REPO_DIGEST_OF_IMAGE_NEXUS_arm64 }}
35+
steps:
36+
- name: Login to Stackable Harbor
37+
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
38+
with:
39+
registry: ${{ env.DST_REGISTRY_HARBOR }}
40+
username: "robot$sdp+github-action-build"
41+
password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }}
42+
- name: Login to Stackable Nexus
43+
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
44+
with:
45+
registry: ${{ env.DST_REGISTRY_NEXUS }}
46+
username: github
47+
password: ${{ secrets.NEXUS_PASSWORD }}
48+
- name: Pull image from source registry
49+
run: docker pull "${{ github.event.inputs.src }}" --platform ${{ matrix.architecture }}
50+
- name: Retag image
51+
run: |
52+
# Tagging the same image two times to push to Nexus and Harbor
53+
docker tag "${{ github.event.inputs.src }}" "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-${{ matrix.architecture }}"
54+
docker tag "${{ github.event.inputs.src }}" "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-${{ matrix.architecture }}"
55+
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
56+
- name: Push image to destination registry
57+
id: push
58+
run: |
59+
DOCKER_OUTPUT_HARBOR="$(docker push "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-${{ matrix.architecture }}")";
60+
DOCKER_OUTPUT_NEXUS="$(docker push "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-${{ matrix.architecture }}")";
61+
# Obtain the digest of the pushed image from the output of `docker push`, because signing by tag is deprecated and will be removed from cosign in the future
62+
REPO_DIGEST_OF_IMAGE_HARBOR="$(echo "$DOCKER_OUTPUT_HARBOR" | awk '/^\S+: digest: sha256:[0-9a-f]{64} size: [0-9]+$/ { print $3 }')";
63+
REPO_DIGEST_OF_IMAGE_NEXUS="$(echo "$DOCKER_OUTPUT_NEXUS" | awk '/^\S+: digest: sha256:[0-9a-f]{64} size: [0-9]+$/ { print $3 }')";
64+
# Check both architectures to see if both are available
65+
if [ -z "$REPO_DIGEST_OF_IMAGE_HARBOR" ]; then
66+
echo "Could not find repo digest for container image: $DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-${{ matrix.architecture }}"
67+
exit 1
68+
fi
69+
if [ -z "$REPO_DIGEST_OF_IMAGE_NEXUS" ]; then
70+
echo "Could not find repo digest for container image: $DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-${{ matrix.architecture }}"
71+
exit 1
72+
fi
73+
# Generating output variables for later manifest list creation
74+
if [ ${{ matrix.architecture }} == "arm64" ]; then
75+
echo "REPO_DIGEST_OF_IMAGE_HARBOR_arm64=$REPO_DIGEST_OF_IMAGE_HARBOR" >> "$GITHUB_OUTPUT"
76+
echo "REPO_DIGEST_OF_IMAGE_NEXUS_arm64=$REPO_DIGEST_OF_IMAGE_NEXUS" >> "$GITHUB_OUTPUT"
77+
else
78+
echo "REPO_DIGEST_OF_IMAGE_HARBOR_amd64=$REPO_DIGEST_OF_IMAGE_HARBOR" >> "$GITHUB_OUTPUT"
79+
echo "REPO_DIGEST_OF_IMAGE_NEXUS_amd64=$REPO_DIGEST_OF_IMAGE_NEXUS" >> "$GITHUB_OUTPUT"
80+
fi
81+
# This generates a signature and publishes it to the registry, next to the image
82+
# Uses the keyless signing flow with Github Actions as identity provider
83+
cosign sign -y "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-${{ matrix.architecture }}@$REPO_DIGEST_OF_IMAGE_HARBOR"
84+
cosign sign -y "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-${{ matrix.architecture }}@$REPO_DIGEST_OF_IMAGE_NEXUS"
85+
mirror-multi-arch:
86+
name: Create and push manifest list for ${{ github.event.inputs.dst }}
87+
runs-on: ubuntu-latest
88+
needs: mirror-image
89+
permissions:
90+
id-token: write
91+
steps:
92+
- name: Login to Stackable Harbor
93+
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
94+
with:
95+
registry: ${{ env.DST_REGISTRY_HARBOR }}
96+
username: "robot$sdp+github-action-build"
97+
password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }}
98+
- name: Login to Stackable Nexus
99+
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
100+
with:
101+
registry: ${{ env.DST_REGISTRY_NEXUS }}
102+
username: github
103+
password: ${{ secrets.NEXUS_PASSWORD }}
104+
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
105+
- name: Build and push manifest list
106+
run: |
107+
# Create manifest list for Nexus and Harbor using digests from mirror-image step
108+
docker manifest create "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}" --amend "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-arm64@${{ needs.mirror-image.outputs.REPO_DIGEST_OF_IMAGE_HARBOR_arm64 }}" --amend "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}-amd64@${{ needs.mirror-image.outputs.REPO_DIGEST_OF_IMAGE_HARBOR_amd64 }}"
109+
docker manifest create "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}" --amend "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-arm64@${{ needs.mirror-image.outputs.REPO_DIGEST_OF_IMAGE_NEXUS_arm64 }}" --amend "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}-amd64@${{ needs.mirror-image.outputs.REPO_DIGEST_OF_IMAGE_NEXUS_amd64 }}"
110+
# Pushing manifest list to Nexus and Harbor, store manifest DIGEST for signing
111+
MANIFEST_SHA_HARBOR=$(docker manifest push "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}")
112+
MANIFEST_SHA_NEXUS=$(docker manifest push "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}")
113+
# Signing manifest lists for Nexus and Harbor
114+
cosign sign -y "$DST_REGISTRY_HARBOR/${{ env.DST_PROJECT_HARBOR }}/${{ github.event.inputs.dst }}@$MANIFEST_SHA_HARBOR"
115+
cosign sign -y "$DST_REGISTRY_NEXUS/$DST_PROJECT_NEXUS/${{ github.event.inputs.dst }}@$MANIFEST_SHA_NEXUS"

0 commit comments

Comments
 (0)