Skip to content

Commit 9abc4f6

Browse files
committed
Feature: Add release docker image
Signed-off-by: Leonard Jonathan Oh <[email protected]>
1 parent 60ee190 commit 9abc4f6

File tree

5 files changed

+241
-33
lines changed

5 files changed

+241
-33
lines changed

.github/workflows/docker.yml

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
name: docker
2+
on:
3+
push:
4+
# TODO: Build on main?
5+
branches:
6+
- main
7+
tags:
8+
- '**'
9+
# TODO: Remove pull_request before merging
10+
pull_request:
11+
branches:
12+
- main
13+
14+
permissions:
15+
contents: read
16+
packages: write
17+
# Ensure cosign can request for Github's OIDC JWT ID token
18+
# See: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-cloud-providers#adding-permissions-settings
19+
id-token: write
20+
21+
jobs:
22+
# This job builds the binaries and uploads it as github artifacts.
23+
# This allows us to use the same binaries for any release CI jobs.
24+
build:
25+
name: Build all linux architectures
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: setup go
29+
uses: actions/setup-go@v3
30+
with:
31+
go-version: ${{ env.GO_VERSION }}
32+
33+
- uses: actions/checkout@v3
34+
with:
35+
# Fetch all tags
36+
fetch-depth: 0
37+
38+
- name: Build on all supported architectures
39+
run: |
40+
set -e
41+
./scripts/release.sh
42+
43+
- uses: actions/upload-artifact@v3
44+
with:
45+
name: binaries-${{ github.sha }}
46+
path: |
47+
release*/*
48+
49+
# This job downloads the binaries previously uploaded as artifacts, and builds multi-arch images
50+
build-docker-image:
51+
needs: [build]
52+
runs-on: ubuntu-latest
53+
steps:
54+
- name: Checkout
55+
uses: actions/checkout@v3
56+
with:
57+
# Fetch all tags
58+
fetch-depth: 0
59+
60+
- name: Prepare
61+
id: prep
62+
run: |
63+
set -e
64+
TAG=$( git describe --tags --dirty ) # E.g. v1.2.0-23-g60ee190
65+
echo "TAG=$TAG" >> $GITHUB_ENV
66+
67+
# This step generates the docker tags
68+
- name: Docker meta
69+
id: meta
70+
uses: docker/metadata-action@v4
71+
with:
72+
images: |
73+
${{ github.repository }}
74+
ghcr.io/${{ github.repository }}
75+
# type=ref,event=pr generates tag(s) on PRs only. E.g. 'pr-123', 'pr-123-abc0123'
76+
# type=ref,event=branch generates tag(s) on branch only. E.g. 'main-abc0123'
77+
# type=semver generates tag(s) on tags only. E.g. 'v0', 'v0.0', 'v0.0.0', and 'latest'
78+
tags: |
79+
type=ref,event=pr
80+
type=ref,suffix=-{{sha}},event=branch
81+
type=semver,pattern=v{{major}}
82+
type=semver,pattern=v{{major}}.{{minor}}
83+
type=semver,pattern=v{{major}}.{{minor}}.{{patch}}
84+
# The rest of the org.opencontainers.image.xxx labels are dynamically generated
85+
labels: |
86+
org.opencontainers.image.description=CNI Plugins
87+
org.opencontainers.image.licenses=Apache License 2.0
88+
89+
# See: https://github.com/docker/build-push-action/blob/v2.6.1/docs/advanced/cache.md#github-cache
90+
- name: Set up QEMU
91+
uses: docker/setup-qemu-action@v2
92+
93+
- name: Set up Docker Buildx
94+
id: buildx
95+
uses: docker/setup-buildx-action@v2
96+
97+
- name: Cache Docker layers
98+
uses: actions/cache@v3
99+
with:
100+
path: /tmp/.buildx-cache
101+
key: ${{ runner.os }}-buildx-${{ github.sha }}
102+
restore-keys: |
103+
${{ runner.os }}-buildx-
104+
105+
- name: Login to Docker Hub registry
106+
uses: docker/login-action@v2
107+
with:
108+
username: ${{ secrets.DOCKERHUB_USERNAME }}
109+
password: ${{ secrets.DOCKERHUB_TOKEN }}
110+
111+
- name: Login to GitHub Container Registry
112+
uses: docker/login-action@v2
113+
with:
114+
registry: ghcr.io
115+
username: ${{ github.actor }}
116+
password: ${{ secrets.GITHUB_TOKEN }}
117+
118+
- uses: actions/download-artifact@v3
119+
with:
120+
name: binaries-${{ github.sha }}
121+
122+
- run: |
123+
ls -al release*/
124+
125+
- name: Build and push
126+
id: build-and-push
127+
# TODO: Remove pull_request before merging
128+
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
129+
uses: docker/build-push-action@v3
130+
with:
131+
build-args: |
132+
TAG=${{ env.TAG }}
133+
context: '.'
134+
file: Dockerfile
135+
platforms: linux/amd64,linux/arm,linux/arm64,linux/mips64le,linux/ppc64le,linux/riscv64,linux/s390x
136+
push: true
137+
tags: ${{ steps.meta.outputs.tags }}
138+
labels: ${{ steps.meta.outputs.labels }}
139+
cache-from: type=local,src=/tmp/.buildx-cache
140+
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
141+
142+
- name: Install cosign
143+
uses: sigstore/cosign-installer@c3667d99424e7e6047999fb6246c0da843953c65 # v3.0.1
144+
145+
# This signs the image using ACTIONS_ID_TOKEN_REQUEST_TOKEN
146+
- name: Sign the published Docker image
147+
run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign --yes {}@${{ steps.build-and-push.outputs.digest }}
148+
149+
# Temp fix
150+
# https://github.com/docker/build-push-action/issues/252
151+
# https://github.com/moby/buildkit/issues/1896
152+
- name: Move cache
153+
run: |
154+
rm -rf /tmp/.buildx-cache
155+
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

Dockerfile

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
# In this container we test the install script
21
FROM busybox as test
32

43
ADD docker-installer/install_cni_plugins.sh /script/install_cni_plugins.sh
54
ADD docker-installer/test_install_cni_plugins.sh /script/test_install_cni_plugins.sh
65
WORKDIR /script
76
RUN /script/test_install_cni_plugins.sh
87

9-
# In this container we build the plug-ins
10-
FROM golang:1.15 as build
11-
12-
ENV BRANCH_OR_TAG=master
13-
14-
WORKDIR /go/src/app
15-
ADD . .
16-
RUN ./build_linux.sh
8+
FROM busybox as build
9+
ARG TAG
10+
# Get buildx automatic platform vars: https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
11+
ARG TARGETPLATFORM
12+
ARG TARGETOS
13+
ARG TARGETARCH
14+
ARG TARGETVARIANT
15+
ARG BUILDPLATFORM
16+
ARG BUILDOS
17+
ARG BUILDARCH
18+
ARG BUILDVARIANT
19+
RUN echo TARGETPLATFORM=$TARGETPLATFORM
20+
RUN echo TARGETOS=$TARGETOS
21+
RUN echo TARGETARCH=$TARGETARCH
22+
RUN echo TARGETVARIANT=$TARGETVARIANT
23+
RUN echo BUILDPLATFORM=$BUILDPLATFORM
24+
RUN echo BUILDOS=$BUILDOS
25+
RUN echo BUILDARCH=$BUILDARCH
26+
RUN echo BUILDVARIANT=$BUILDVARIANT
27+
# Use buildx automatic platform vars
28+
COPY release-$TAG/cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz
29+
COPY release-$TAG/cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz.sha512 cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz.sha512
30+
RUN set -eux; \
31+
sha512sum -c cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz.sha512; \
32+
mkdir -p /opt/cni/bin; \
33+
tar -xvf cni-plugins-$TARGETOS-$TARGETARCH-$TAG.tgz -C /opt/cni/bin;
1734

1835
# This is the final, minimal container
19-
FROM busybox
20-
COPY --from=build /go/src/app/bin /opt/cni/bin
36+
FROM busybox as final
37+
COPY docker-installer/install_cni_plugins.sh /script/install_cni_plugins.sh
38+
COPY --from=build /opt/cni/bin /opt/cni/bin
39+
ENV FORCE=
40+
WORKDIR /opt/cni/bin
2141
VOLUME /host/opt/cni/bin
22-
ADD docker-installer/install_cni_plugins.sh /script/install_cni_plugins.sh
2342
CMD ["/script/install_cni_plugins.sh","/opt/cni/bin","/host/opt/cni/bin"]

docker-installer/install_cni_plugins.sh

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
#!/bin/sh
22

3-
set -e
3+
set -eu
44

55
if [ $# -ne 2 ]; then
66
echo "USAGE: $0 source-dir dest-dir"
7+
echo "Env vars:"
8+
echo " FORCE Overwrite existing binaries"
79
exit 1
810
fi
911

1012
SRC=$1
1113
DST=$2
14+
FORCE=${FORCE:-}
1215

1316
install_cni_plugin() {
1417
NAME=$1
@@ -17,34 +20,41 @@ install_cni_plugin() {
1720
if [ ! -e $DST/$NAME.by_cni_installer_image ]; then
1821
# The file already exists but there's no marker that
1922
# it was installed by this installer -> keep untouched
20-
echo "* '$NAME' ignored (exists but not installed by me)"
21-
return
22-
fi
23-
OTHER_MD5=$( md5sum $DST/$NAME | awk '{ print $1 }' )
24-
INSTALLED_MD5=$( cat $DST/$NAME.by_cni_installer_image )
25-
26-
if [ "$OTHER_MD5" != "$INSTALLED_MD5" ]; then
27-
# The file was previously installed by this installer
28-
# but later changed -> keep untouched
29-
echo "* '$NAME' ignored (previously installed by me but changed by someone else)"
30-
return
31-
fi
23+
if [ -z "$FORCE" ]; then
24+
echo "* '$NAME' ignored (exists but not installed by me)"
25+
return
26+
fi
27+
else
28+
OTHER_MD5=$( md5sum $DST/$NAME | awk '{ print $1 }' )
29+
INSTALLED_MD5=$( cat $DST/$NAME.by_cni_installer_image )
30+
31+
if [ "$OTHER_MD5" != "$INSTALLED_MD5" ]; then
32+
# The file was previously installed by this installer
33+
# but later changed -> keep untouched
34+
if [ -z "$FORCE" ]; then
35+
echo "* '$NAME' ignored (previously installed by me but changed by someone else)"
36+
return
37+
fi
38+
fi
3239

33-
if [ "$OTHER_MD5" == "$MD5" ]; then
34-
# The file was previously installed by this installer
35-
# and is up-to-date
36-
echo "* '$NAME' is up-to-date"
37-
return
40+
if [ "$OTHER_MD5" == "$MD5" ]; then
41+
# The file was previously installed by this installer
42+
# and is up-to-date
43+
echo "* '$NAME' is up-to-date"
44+
return
45+
fi
3846
fi
3947

4048
# The file was previously installed by this installer
4149
# but needs an update
42-
cp -a $SRC/$NAME $DST/$NAME
50+
cp -a $SRC/$NAME $DST/.$NAME.new
51+
mv $DST/.$NAME.new $DST/$NAME
4352
echo $MD5 > $DST/$NAME.by_cni_installer_image
4453
echo "* '$NAME' updated"
4554

4655
else
47-
cp -a $SRC/$NAME $DST/$NAME
56+
cp -a $SRC/$NAME $DST/.$NAME.new
57+
mv $DST/.$NAME.new $DST/$NAME
4858
echo $MD5 > $DST/$NAME.by_cni_installer_image
4959
echo "* '$NAME' installed"
5060
fi

docker-installer/test_install_cni_plugins.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,30 @@ echo "Test passed."
123123

124124
#############################################################
125125

126+
prepare "Force install overwrites plugin installed by someone else"
127+
128+
echo "cni1.other" > test/dst/cni1
129+
echo "cni1.0" > test/src/cni1
130+
FORCE=1 ./install_cni_plugins.sh test/src test/dst
131+
132+
assert_file_content cni1 "cni1.0"
133+
assert_file_content cni1.by_cni_installer_image "7ec08d6ee0e5237cb34be4a31d9146c1"
134+
135+
prepare "Force install overwrites plugin installed by me, altered by someone else"
136+
137+
echo "cni1.0" > test/src/cni1
138+
./install_cni_plugins.sh test/src test/dst
139+
echo "cni1.other" > test/dst/cni1
140+
141+
FORCE=1 ./install_cni_plugins.sh test/src test/dst
142+
143+
assert_file_content cni1 "cni1.0"
144+
assert_file_content cni1.by_cni_installer_image "7ec08d6ee0e5237cb34be4a31d9146c1"
145+
146+
echo
147+
echo "Test passed."
148+
149+
#############################################################
126150

127151
echo
128152
echo "All tests passed."

scripts/release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ rm -Rf ${SRC_DIR}/${RELEASE_DIR}
1616
mkdir -p ${SRC_DIR}/${RELEASE_DIR}
1717
mkdir -p ${OUTPUT_DIR}
1818

19-
$DOCKER run -ti -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins:z --rm golang:1.18-alpine \
19+
$DOCKER run -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins:z --rm golang:1.18-alpine \
2020
/bin/sh -xe -c "\
2121
apk --no-cache add bash tar;
2222
cd /go/src/github.com/containernetworking/plugins; umask 0022;

0 commit comments

Comments
 (0)