Skip to content

Commit 6d22820

Browse files
committed
ci: Build and publish container in CI
* Check that container builds on PR * Publish container from master branch
1 parent d3a096f commit 6d22820

File tree

7 files changed

+130
-1
lines changed

7 files changed

+130
-1
lines changed

.ci/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
CI Design guidelines
2+
3+
* It is more maintainable to create scripts in `.ci` and then call them from the workflows than to
4+
have scripts inline in the workflows. However, it is also good to split up scripts in multiple
5+
steps and jobs depending on what is being done.
6+
7+
* The docker image is rebuilt if the `Dockerfile` or `.containerversion` file is modified. (In case
8+
of a push event it is also automatically published to docker hub).
9+
10+
* If there are changes in the `Dockerfile`, then `.containerversion` must be updated with an
11+
unpublished version number.
12+
13+
* We listen to two kinds of events, `pull_request` and `push` using two different workflows,
14+
`pr-ci.yml` and `ci.yml`.
15+
* On pull request events, github will checkout a version of the tree that is the PR branch merged
16+
into the base branch. When we look for what is modifed we can diff HEAD^1 to HEAD. If github
17+
didn't do this, it would've missed commits added to the base branch since the PR branch was
18+
forked.
19+
20+
o--o--o--o <-- (base branch, typically 'master', parent 1)
21+
\ \
22+
\ o <-- (HEAD)
23+
\ /
24+
o----o <-- Pull requst branch (parent 2)
25+
26+
* On push events we get hashes of last commit before and after the push. When we look for what
27+
changed we can diff github.event.before with HEAD.
28+
29+
o--o--o--o--o--o <-- github.event.after (HEAD)
30+
\
31+
github.event.before

.ci/build-container

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
CONTAINER_REPO=shiftcrypto/firmware_v2
6+
CONTAINER_VERSION=$(cat .containerversion)
7+
8+
docker build --pull --no-cache -t $CONTAINER_REPO:latest -t $CONTAINER_REPO:$CONTAINER_VERSION .

.ci/check-container-sources-modified

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
#
3+
# This script works on merge commits. <rev>^1 means the first parent of <rev>.
4+
#
5+
# When the github action creates a temporary merge commit for a pull request, the first parent will
6+
# be the base (the branch being merged into).
7+
8+
set -e
9+
10+
if git diff --name-only HEAD^1 HEAD | grep -E '^(\.containerversion|Dockerfile)' >/dev/null; then
11+
echo "true"
12+
exit
13+
fi
14+
echo "false"

.ci/check-container-version-published

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
CONTAINER_REPO=shiftcrypto/firmware_v2
6+
CONTAINER_VERSION=$(cat .containerversion)
7+
8+
# docker manifest returns 1 (error) if the container doesn't exist and 0 (success) if it does.
9+
if docker manifest inspect $CONTAINER_REPO:$CONTAINER_VERSION > /dev/null; then
10+
>&2 echo Container version \'$CONTAINER_VERSION\' exists.
11+
echo true
12+
exit
13+
fi
14+
echo false

.ci/publish-container

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
CONTAINER_REPO=shiftcrypto/firmware_v2
6+
CONTAINER_VERSION=$(cat .containerversion)
7+
8+
docker push $CONTAINER_REPO:latest
9+
docker push $CONTAINER_REPO:$CONTAINER_VERSION

.github/workflows/ci.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
- master
99

1010
jobs:
11-
linux-docker:
11+
ci:
1212
runs-on: ubuntu-22.04
1313
steps:
1414
- name: Clone the repo
@@ -17,7 +17,28 @@ jobs:
1717
fetch-depth: 0
1818
fetch-tags: true
1919
submodules: recursive
20+
21+
- name: Check if container should be published
22+
id: checks
23+
run: echo container-published=$(./.ci/check-container-version-published) >> $GITHUB_OUTPUT
24+
25+
- name: Build container
26+
if: steps.checks.outputs.container-published == 'false'
27+
run: ./.ci/build-container
28+
29+
- name: Login to Docker Hub
30+
uses: docker/login-action@v3
31+
with:
32+
username: ${{ secrets.DOCKER_USERNAME }}
33+
password: ${{ secrets.DOCKER_TOKEN }}
34+
35+
- name: Publish container
36+
if: steps.checks.outputs.container-published == 'false'
37+
run: ./.ci/publish-container
38+
2039
- name: Pull CI container image
40+
if: steps.checks.outputs.container-published == 'true'
2141
run: ./.ci/pull-container
42+
2243
- name: Run CI in container
2344
run: ./.ci/run-container-ci ${{github.workspace}} ${{ github.event.before }}

.github/workflows/pr-ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,23 @@ jobs:
1414
submodules: recursive
1515
fetch-depth: 0
1616

17+
- name: Check if container files was modified and if container version already exists
18+
id: checks
19+
run: |
20+
echo modified=$(./.ci/check-container-sources-modified) >> "$GITHUB_OUTPUT"
21+
echo container-published=$(./.ci/check-container-version-published) >> "$GITHUB_OUTPUT"
22+
23+
- name: Build container image
24+
if: steps.checks.outputs.modified == 'true'
25+
run: |
26+
if "${{ steps.checks.outputs.container-published }}" == "true"; then
27+
echo "::error::Container modified but version $(cat .containerversion) already published"
28+
exit 1
29+
fi
30+
./.ci/build-container
31+
1732
- name: Pull container image
33+
if: steps.checks.outputs.modified == 'false'
1834
run: ./.ci/pull-container
1935

2036
- name: Run CI in container
@@ -66,7 +82,23 @@ jobs:
6682
# get the .ci scripts from there as well.
6783
git checkout -f ${{ github.event.pull_request.merge_commit_sha }} -- .ci .github
6884
85+
- name: Check if container files was modified and if container version already exists
86+
id: checks
87+
run: |
88+
echo modified=$(./.ci/check-container-sources-modified) >> "$GITHUB_OUTPUT"
89+
echo container-published=$(./.ci/check-container-version-published) >> "$GITHUB_OUTPUT"
90+
91+
- name: Build container image
92+
if: steps.checks.outputs.modified == 'true'
93+
run: |
94+
if "${{ steps.checks.outputs.container-published }}" == "true"; then
95+
echo "::error::Container modified but version $(cat .containerversion) already published"
96+
exit 1
97+
fi
98+
./.ci/build-container
99+
69100
- name: Pull container image
101+
if: steps.checks.outputs.modified == 'false'
70102
run: ./.ci/pull-container
71103

72104
- name: Run CI in container

0 commit comments

Comments
 (0)