Skip to content

Commit d2fa006

Browse files
committed
ci: Add container image build workflow
Signed-off-by: Anastassios Nanos <ananos@nubificus.co.uk>
1 parent 500d3d0 commit d2fa006

2 files changed

Lines changed: 204 additions & 1 deletion

File tree

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
name: Build agent containers
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
agent:
7+
default: 'node'
8+
required: true
9+
type: string
10+
registry:
11+
default: 'harbor.nbfc.io'
12+
required: false
13+
type: string
14+
workflow_dispatch:
15+
inputs:
16+
agent:
17+
default: 'node'
18+
required: true
19+
type: string
20+
registry:
21+
default: 'harbor.nbfc.io'
22+
required: false
23+
type: string
24+
25+
concurrency:
26+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
27+
cancel-in-progress: true
28+
29+
env:
30+
REGISTRY: ${{ github.event.inputs.registry || 'harbor.nbfc.io' }}
31+
# NOTE: We assume that a project named after the repo owner exists in the
32+
# registry. The image will be uploaded as <repo_name> under the <repo_owner>
33+
# project.
34+
REGISTRY_IMAGE: ${{ github.event.inputs.registry || 'harbor.nbfc.io' }}/mlsysops/${{ inputs.agent }}-agent
35+
RUNNER_ARCH_MAP: '[{"amd64":"x86_64", "arm64":"aarch64", "arm":"armv7l"}]'
36+
37+
jobs:
38+
build:
39+
name: Build Docker Image
40+
runs-on: ${{ format('{0}-{1}', 'base-dind-2204', matrix.arch) }}
41+
strategy:
42+
matrix:
43+
arch: ["arm64", "amd64"]
44+
outputs:
45+
digest-amd64: ${{ steps.set-outputs.outputs.digest-amd64 }}
46+
digest-arm64: ${{ steps.set-outputs.outputs.digest-arm64 }}
47+
48+
steps:
49+
- name: Checkout repo
50+
uses: actions/checkout@v4
51+
52+
- name: Login to registry ${{ env.REGISTRY }}
53+
uses: docker/login-action@v3
54+
with:
55+
registry: ${{ env.REGISTRY }}
56+
username: ${{ secrets.HARBOR_USER }}
57+
password: ${{ secrets.HARBOR_SECRET }}
58+
59+
- name: Set up Docker Buildx
60+
uses: docker/setup-buildx-action@v3
61+
62+
- name: Extract Docker metadata
63+
id: meta
64+
uses: docker/metadata-action@v5
65+
with:
66+
images: ${{ env.REGISTRY_IMAGE }}
67+
tags: |
68+
type=sha,prefix=${{ matrix.arch }}-
69+
type=ref,event=branch,prefix=${{ matrix.arch }}-
70+
71+
- name: Build and push ${{ matrix.arch }} image
72+
id: build-and-push
73+
uses: docker/build-push-action@v6
74+
with:
75+
context: ./agents/${{ inputs.agent }}
76+
tags: ${{ steps.meta.outputs.tags }}
77+
labels: ${{ steps.meta.outputs.labels }}
78+
platforms: linux/${{ matrix.arch }}
79+
push: true
80+
file: ./agents/${{ inputs.agent }}/Dockerfile
81+
provenance: false
82+
build-args: |
83+
ARCHTAG=${{ fromJson(env.RUNNER_ARCH_MAP)[0][matrix.arch] }}
84+
BRANCH=${{ github.event.ref_name || github.ref_name }}
85+
86+
- name: Set ${{ matrix.arch }} digest output
87+
id: set-outputs
88+
run: |
89+
# Workaround for https://github.com/actions/runner/issues/2499
90+
echo "digest-${{ matrix.arch }}=${{ steps.build-and-push.outputs.digest }}" \
91+
>> "$GITHUB_OUTPUT"
92+
shell: bash
93+
94+
create-manifest:
95+
name: Create Merged Docker Image Manifest
96+
needs: [build]
97+
runs-on: 'base-dind-2204-amd64'
98+
outputs:
99+
digest-merged: ${{ steps.inspect.outputs.digest-merged }}
100+
101+
steps:
102+
- name: Checkout repo
103+
uses: actions/checkout@v4
104+
105+
- name: Login to registry ${{ inputs.REGISTRY }}
106+
uses: docker/login-action@v3
107+
with:
108+
registry: ${{ env.REGISTRY }}
109+
username: ${{ secrets.HARBOR_USER }}
110+
password: ${{ secrets.HARBOR_SECRET }}
111+
112+
- name: Set up Docker Buildx
113+
uses: docker/setup-buildx-action@v3
114+
115+
- name: Extract Docker metadata
116+
id: meta
117+
uses: docker/metadata-action@v5
118+
with:
119+
images: ${{ env.REGISTRY_IMAGE }}
120+
tags: |
121+
type=sha
122+
type=ref,event=branch
123+
type=raw,value=latest
124+
125+
- name: Create and push manifest
126+
run: |
127+
docker buildx imagetools create \
128+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< \
129+
"$DOCKER_METADATA_OUTPUT_JSON") \
130+
${{ env.REGISTRY_IMAGE }}@${{ needs.build.outputs.digest-amd64 }} \
131+
${{ env.REGISTRY_IMAGE }}@${{ needs.build.outputs.digest-arm64 }}
132+
shell: bash
133+
134+
- name: Inspect merged image
135+
id: inspect
136+
run: |
137+
docker buildx imagetools inspect \
138+
${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
139+
digest=$(docker buildx imagetools inspect \
140+
${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} \
141+
--format '{{json .Manifest}}' | jq -r '.digest')
142+
if [[ -z "${digest}" ]]; then
143+
echo "Could not get merged image digest"
144+
exit 1
145+
fi
146+
echo "digest-merged=${digest}" >> "$GITHUB_OUTPUT"
147+
shell: bash
148+
149+
sign:
150+
name: Sign Docker Images
151+
needs: [build, create-manifest]
152+
runs-on: 'base-dind-2204-amd64'
153+
permissions:
154+
contents: read
155+
id-token: write
156+
157+
steps:
158+
- name: Install Cosign
159+
uses: sigstore/cosign-installer@v3
160+
161+
- name: Verify Cosign installation
162+
run: cosign version
163+
164+
- name: Login to registry ${{ env.REGISTRY }}
165+
uses: docker/login-action@v3
166+
with:
167+
registry: ${{ env.REGISTRY }}
168+
username: ${{ secrets.HARBOR_USER }}
169+
password: ${{ secrets.HARBOR_SECRET }}
170+
171+
- name: Sign published Docker images
172+
env:
173+
DIGESTS: >-
174+
${{ needs.create-manifest.outputs.digest-merged }}
175+
${{ needs.build.outputs.digest-amd64 }}
176+
${{ needs.build.outputs.digest-arm64 }}
177+
run: |
178+
for digest in ${DIGESTS}; do
179+
cosign sign --yes ${{ env.REGISTRY_IMAGE }}@${digest} \
180+
-a "repo=${{ github.repository }}" \
181+
-a "workflow=${{ github.workflow }}" \
182+
-a "ref=${{ github.sha }}" \
183+
-a "author=Nubificus LTD"
184+
done
185+
shell: bash

.github/workflows/ci.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ concurrency:
1313
permissions:
1414
pull-requests: read
1515
contents: read
16+
id-token: write
17+
1618

1719

1820
jobs:
@@ -26,13 +28,29 @@ jobs:
2628

2729
build-agent-pkg:
2830
#needs: [validate-files-and-commits, lint]
29-
name: Build
31+
name: Build python pkg
3032
if: |
3133
contains(github.event.pull_request.labels.*.name, 'ok-to-test') &&
3234
!contains(github.event.pull_request.labels.*.name, 'skip-build')
3335
uses: ./.github/workflows/build-mlsysops-pkg.yml
3436
secrets: inherit
3537

38+
build-agent-containers:
39+
needs: [build-agent-pkg]
40+
name: Build containers
41+
if: |
42+
contains(github.event.pull_request.labels.*.name, 'ok-to-test') &&
43+
!contains(github.event.pull_request.labels.*.name, 'skip-build')
44+
strategy:
45+
matrix:
46+
agent: ["node", "cluster", "continuum"]
47+
uses: ./.github/workflows/build-containers.yml
48+
secrets: inherit
49+
with:
50+
agent: ${{ matrix.agent }}
51+
52+
53+
3654
# lint:
3755
# name: Lint code
3856
# if: |

0 commit comments

Comments
 (0)