Skip to content
This repository was archived by the owner on Jun 22, 2024. It is now read-only.

Commit d0cb138

Browse files
Merge pull request #6 from seleniumhq-community/deploy-to-dockerhub
Setup CircleCI to build, test, and deploy Seleniarm images to Docker Hub
2 parents a61d860 + a1e9093 commit d0cb138

File tree

5 files changed

+235
-58
lines changed

5 files changed

+235
-58
lines changed

.circleci/config.yml

Lines changed: 131 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -24,46 +24,41 @@ jobs:
2424
BUILD_DATE: today
2525
PLATFORMS: << parameters.platforms >>
2626
steps:
27+
- run:
28+
name: "Prepare workflow environment variables"
29+
command: |
30+
echo 'export BRANCH="$CIRCLE_BRANCH"' >> $BASH_ENV
31+
cat $BASH_ENV
32+
source $BASH_ENV
33+
echo "Workflow environment variables:"
34+
echo $BRANCH
2735
- run: uname -a
2836
- run: docker info
29-
- run: |
30-
echo "CIRCLE_WORKFLOW_ID = " $CIRCLE_WORKFLOW_ID
31-
git clone https://github.com/seleniumhq-community/docker-seleniarm.git
32-
cd docker-seleniarm
33-
git checkout $CIRCLE_BRANCH
34-
echo $PWD
35-
- run: |
36-
echo "Install QEMU binaries"
37-
curl -L https://github.com/xpack-dev-tools/qemu-arm-xpack/releases/download/v6.2.0-2/xpack-qemu-arm-6.2.0-2-linux-$(uname -m | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/').tar.gz -o xpack-qemu-arm-6.2.0-2-linux-$(uname -m | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/').tar.gz \
38-
&& tar xvfz xpack-qemu-arm-6.2.0-2-linux-$(uname -m | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/').tar.gz \
39-
&& echo "export PATH=$PWD/xpack-qemu-arm-6.2.0-2/bin:$PATH" > ~/.bashrc \
40-
&& source ~/.bashrc \
41-
&& qemu-system-aarch64 --version
42-
- run: |
43-
echo "Build Docker images"
44-
cd docker-seleniarm
45-
echo $PWD
46-
export BRANCH=$CIRCLE_BRANCH
47-
#export PLATFORMS=
48-
NAME=${NAMESPACE} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} PLATFORMS=${PLATFORMS} make build_multi
49-
- run: |
50-
echo "Save Docker Images in Cache"
51-
export VERSION=$CIRCLE_BRANCH
52-
echo $NAMESPACE/base:$VERSION-$BUILD_DATE
53-
echo $NAMESPACE/node-base:$VERSION-$BUILD_DATE
54-
echo $NAMESPACE/hub:$VERSION-$BUILD_DATE
55-
echo $NAMESPACE/node-chromium:$VERSION-$BUILD_DATE
56-
echo $NAMESPACE/standalone-chromium:$VERSION-$BUILD_DATE
57-
echo $NAMESPACE/node-firefox:$VERSION-$BUILD_DATE
58-
echo $NAMESPACE/standalone-firefox:$VERSION-$BUILD_DATE
59-
docker save -o multi-arch-images.tar \
60-
$NAMESPACE/base:$VERSION-$BUILD_DATE \
61-
$NAMESPACE/node-base:$VERSION-$BUILD_DATE \
62-
$NAMESPACE/hub:$VERSION-$BUILD_DATE \
63-
$NAMESPACE/node-chromium:$VERSION-$BUILD_DATE \
64-
$NAMESPACE/standalone-chromium:$VERSION-$BUILD_DATE \
65-
$NAMESPACE/node-firefox:$VERSION-$BUILD_DATE \
66-
$NAMESPACE/standalone-firefox:$VERSION-$BUILD_DATE
37+
- checkout
38+
- run:
39+
name: "Build Docker images"
40+
command: |
41+
echo "Branch is $BRANCH"
42+
NAME=${NAMESPACE} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} PLATFORMS=${PLATFORMS} BUILD_ARGS=${BUILD_ARGS} make build_multi
43+
- run:
44+
name: "Save Docker Images in Cache"
45+
command: |
46+
export VERSION=$CIRCLE_BRANCH
47+
echo $NAMESPACE/base:$VERSION-$BUILD_DATE
48+
echo $NAMESPACE/node-base:$VERSION-$BUILD_DATE
49+
echo $NAMESPACE/hub:$VERSION-$BUILD_DATE
50+
echo $NAMESPACE/node-chromium:$VERSION-$BUILD_DATE
51+
echo $NAMESPACE/standalone-chromium:$VERSION-$BUILD_DATE
52+
echo $NAMESPACE/node-firefox:$VERSION-$BUILD_DATE
53+
echo $NAMESPACE/standalone-firefox:$VERSION-$BUILD_DATE
54+
docker save -o multi-arch-images.tar \
55+
$NAMESPACE/base:$VERSION-$BUILD_DATE \
56+
$NAMESPACE/node-base:$VERSION-$BUILD_DATE \
57+
$NAMESPACE/hub:$VERSION-$BUILD_DATE \
58+
$NAMESPACE/node-chromium:$VERSION-$BUILD_DATE \
59+
$NAMESPACE/standalone-chromium:$VERSION-$BUILD_DATE \
60+
$NAMESPACE/node-firefox:$VERSION-$BUILD_DATE \
61+
$NAMESPACE/standalone-firefox:$VERSION-$BUILD_DATE
6762
- save_cache:
6863
key: multi-arch-images-{{ .Branch }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}-<< parameters.platforms >>
6964
paths:
@@ -80,38 +75,102 @@ jobs:
8075
NAMESPACE: seleniarm
8176
BUILD_DATE: today
8277
steps:
78+
- checkout
8379
- restore_cache:
8480
keys:
8581
- multi-arch-images-{{ .Branch }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}-<< parameters.platforms >>
8682
- run: uname -a
8783
- run: docker info
88-
- run: |
89-
echo "CIRCLE_WORKFLOW_ID = " $CIRCLE_WORKFLOW_ID
90-
echo "Load built images into Docker"
91-
docker load -i multi-arch-images.tar
92-
- run: |
93-
git clone https://github.com/seleniumhq-community/docker-seleniarm.git
94-
cd docker-seleniarm
95-
git checkout $CIRCLE_BRANCH
96-
echo $PWD
97-
- run: |
98-
echo "Use Python3 and pip3 instead of Python2.7"
99-
cd docker-seleniarm
100-
sed -i 's/pip /pip3 /g' tests/bootstrap.sh
101-
sed -i 's/python /python3 /g' tests/bootstrap.sh
102-
sed -i 's/-m pip3 /-m pip /g' tests/bootstrap.sh
84+
- run:
85+
name: "Load built images from cache into Docker"
86+
command: |
87+
echo "CIRCLE_WORKFLOW_ID = " $CIRCLE_WORKFLOW_ID
88+
docker load -i multi-arch-images.tar
89+
- run:
90+
name: "Use Python3 and pip3 instead of Python2.7"
91+
command: |
92+
echo "Use Python3 and pip3 instead of Python2.7"
93+
sed -i 's/pip /pip3 /g' tests/bootstrap.sh
94+
sed -i 's/python /python3 /g' tests/bootstrap.sh
95+
sed -i 's/-m pip3 /-m pip /g' tests/bootstrap.sh
10396
- run:
97+
name: "Test Docker images"
10498
no_output_timeout: 2m
10599
command: |
106-
echo "Test Docker images"
107-
cd docker-seleniarm
108-
echo $PWD
109100
export USE_RANDOM_USER=false
110-
#export BUILD_DATE=$(date '+%Y%m%d')
111101
export BRANCH=$CIRCLE_BRANCH
112-
#export ARCH=`dpkg --print-architecture`
113102
USE_RANDOM_USER_ID=${USE_RANDOM_USER} NAMESPACE=${NAMESPACE} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} SKIP_BUILD=true make test_multi_arch
114103
104+
deploy-multi-arch:
105+
parameters:
106+
platforms:
107+
type: string
108+
build-args:
109+
type: string
110+
machine-type:
111+
type: executor
112+
executor: << parameters.machine-type >>
113+
environment:
114+
NAMESPACE: seleniarm
115+
PLATFORMS: << parameters.platforms >>
116+
BUILD_ARGS: << parameters.build-args >>
117+
DEPLOY_BRANCH: trunk
118+
GITHUB_USER: seleniumhq-community
119+
GITHUB_REPO: docker-seleniarm
120+
SELENIUM_VERSION: 4.1.3
121+
steps:
122+
- run:
123+
name: "Prepare workflow environment variables"
124+
command: |
125+
echo "Prepare workflow environment variables"
126+
echo 'export BRANCH="$SELENIUM_VERSION"' >> $BASH_ENV
127+
echo 'export GITHUB_REPO="$CIRCLE_PROJECT_REPONAME"' >> $BASH_ENV
128+
echo 'export GITHUB_USER="$CIRCLE_PROJECT_USERNAME"' >> $BASH_ENV
129+
echo 'export BUILD_DATE=$(date '+%Y%m%d')' >> $BASH_ENV
130+
echo 'export RELEASE_TAG="seleniarm-v`echo $BRANCH`-`echo $BUILD_DATE`"' >> $BASH_ENV
131+
cat $BASH_ENV
132+
source $BASH_ENV
133+
echo "Workflow environment variables:"
134+
echo BRANCH="$BRANCH"
135+
echo GITHUB_REPO="$GITHUB_REPO"
136+
echo GITHUB_USER="$GITHUB_USER"
137+
echo BUILD_DATE="$BUILD_DATE"
138+
echo RELEASE_TAG="$RELEASE_TAG"
139+
echo PLATFORMS="$PLATFORMS"
140+
echo BUILD_ARGS="$BUILD_ARGS"
141+
echo DEPLOY_BRANCH="$DEPLOY_BRANCH"
142+
- checkout
143+
- run: uname -a
144+
- run: docker info
145+
- run:
146+
name: "Check if branch is deployable (contains [deploy] in commit msg on $DEPLOY_BRANCH"
147+
command: |
148+
export CI_DEPLOY=`git log --format=oneline -n 1 | grep '\[deploy\]'` && echo "$CI_DEPLOY"
149+
if [ -z "$CI_DEPLOY" ] || [ "$CIRCLE_BRANCH" != "$DEPLOY_BRANCH" ]; then
150+
echo "Cancelling run. Pass [deploy] in commit message on $DEPLOY_BRANCH to deploy"
151+
circleci-agent step halt
152+
else
153+
echo "[deploy] is present in commit message to $DEPLOY_BRANCH. Running workflow to deploy container images"
154+
fi
155+
- run:
156+
name: "Build and Push Docker images"
157+
command: |
158+
echo "Login to Docker, and setup to use a buildx builder and push built multi-arch images"
159+
docker buildx use `docker buildx create`
160+
docker buildx ls
161+
docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
162+
NAME=${NAMESPACE} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} PLATFORMS=${PLATFORMS} BUILD_ARGS=${BUILD_ARGS} make build_multi
163+
- run:
164+
name: "Generate release notes"
165+
command: |
166+
export LATEST_TAG=$(git describe --tags --abbrev=0)
167+
sh generate_multi-arch-release_notes.sh $LATEST_TAG $CIRCLE_BRANCH $BRANCH $BUILD_DATE
168+
sudo apt-get update -y && sudo apt-get install python3-venv
169+
go install github.com/github-release/[email protected]
170+
cat release_notes.md
171+
export GITHUB_TOKEN=$(sh get-access-token.sh | tail -n 1)
172+
github-release release --tag $RELEASE_TAG --name $RELEASE_TAG --description "`cat release_notes.md`"
173+
115174
workflows:
116175
build-and-test-multi-arch:
117176
jobs:
@@ -133,5 +192,19 @@ workflows:
133192
requires: [build-multi-arch-amd64]
134193
platforms: linux/amd64
135194
machine-type: ubuntu2004amd64
195+
196+
deploy-multi-arch:
197+
jobs:
198+
- deploy-multi-arch:
199+
name: deploy-multi-arch
200+
platforms: linux/arm64,linux/amd64,linux/arm/v7
201+
build-args: --push
202+
machine-type: ubuntu2004arm64
203+
filters:
204+
branches:
205+
only:
206+
- trunk
207+
208+
136209

137210

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,4 @@ ENV/
147147

148148
# End of https://www.gitignore.io/api/python
149149
.DS_Store
150+
release_sandbox
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
3+
LATEST_TAG=$1
4+
HEAD_BRANCH=$2
5+
GRID_VERSION=$3
6+
BUILD_DATE=$4
7+
8+
TAG_VERSION=${GRID_VERSION}-${BUILD_DATE}
9+
10+
echo "" >> release_notes.md
11+
echo "### Changelog" > release_notes.md
12+
git --no-pager log "${LATEST_TAG}...${HEAD_BRANCH}" --pretty=format:"* [\`%h\`](http://github.com/seleniumhq-community/docker-seleniarm/commit/%H) - %s :: %an" --reverse >> release_notes.md
13+
14+
# Pull the other images so we populate the release notes
15+
docker pull seleniarm/base:${TAG_VERSION}
16+
docker pull seleniarm/hub:${TAG_VERSION}
17+
docker pull seleniarm/node-base:${TAG_VERSION}
18+
docker pull seleniarm/standalone-chromium:${TAG_VERSION}
19+
docker pull seleniarm/standalone-firefox:${TAG_VERSION}
20+
21+
CHROMIUM_VERSION=$(docker run --rm seleniarm/node-chromium:${TAG_VERSION} chromium --version | awk '{print $2}')
22+
CHROMEDRIVER_VERSION=$(docker run --rm seleniarm/node-chromium:${TAG_VERSION} chromedriver --version | awk '{print $2}')
23+
FIREFOX_VERSION=$(docker run --rm seleniarm/node-firefox:${TAG_VERSION} firefox --version | awk '{print $3}')
24+
GECKODRIVER_VERSION=$(docker run --rm seleniarm/node-firefox:${TAG_VERSION} geckodriver --version | awk 'NR==1{print $2}')
25+
26+
27+
echo "" >> release_notes.md
28+
echo "### Released versions" >> release_notes.md
29+
echo "* Selenium: ${GRID_VERSION}" >> release_notes.md
30+
echo "* Chromium: ${CHROMIUM_VERSION}" >> release_notes.md
31+
echo "* ChromiumDriver: ${CHROMEDRIVER_VERSION}" >> release_notes.md
32+
echo "* Firefox: ${FIREFOX_VERSION}" >> release_notes.md
33+
echo "* GeckoDriver: ${GECKODRIVER_VERSION}" >> release_notes.md
34+
35+
echo "" >> release_notes.md
36+
echo "### Published Docker images" >> release_notes.md
37+
echo "<details>" >> release_notes.md
38+
echo "<summary>Click to see published Docker images</summary>" >> release_notes.md
39+
echo "" >> release_notes.md
40+
echo '```' >> release_notes.md
41+
docker images --filter=reference='seleniarm/*:*' --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}" >> release_notes.md
42+
echo '```' >> release_notes.md
43+
echo "" >> release_notes.md
44+
echo "</details>" >> release_notes.md
45+

get-access-token.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import time
2+
from cryptography.hazmat.backends import default_backend
3+
import jwt
4+
import os
5+
import requests
6+
import logging
7+
8+
github_app_id = os.environ.get('GITHUB_APP_ID')
9+
github_installation_id = os.environ.get('GITHUB_INSTALLATION_ID')
10+
private_key = os.environ.get('GITHUB_APP_PEM')
11+
private_key = private_key.replace("\\n", "\n")
12+
13+
standard_error_msg = 'Seleniarm GitHub App installation environment variables are not set. '
14+
if github_app_id == '':
15+
raise Exception(standard_error_msg + 'Valid GITHUB_APP_ID is required to obtain an access token.')
16+
if github_installation_id == '':
17+
raise Exception(standard_error_msg + 'Valid GITHUB_INSTALLATION_ID is required to obtain an access token.')
18+
if private_key == '':
19+
raise Exception(standard_error_msg + 'Valid GITHUB_APP_PEM token is required to obtain an access token.')
20+
21+
22+
time_since_epoch_in_seconds = int(time.time())
23+
24+
payload = {
25+
# issued at time
26+
'iat': time_since_epoch_in_seconds,
27+
# JWT expiration time (10 minute maximum)
28+
'exp': time_since_epoch_in_seconds + (10 * 60),
29+
# GitHub App's identifier
30+
'iss': github_app_id
31+
}
32+
33+
actual_jwt = jwt.encode(payload, private_key, algorithm='RS256')
34+
35+
headers = {"Authorization": "Bearer " + actual_jwt,
36+
"Accept": "application/vnd.github.v3+json"}
37+
38+
resp = requests.post('https://api.github.com/app/installations/' + github_installation_id + '/access_tokens', headers=headers)
39+
40+
print(resp.json()['token'])

get-access-token.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
python3 -m venv release_sandbox
4+
. release_sandbox/bin/activate
5+
if [ -z "$VIRTUAL_ENV" ]; then
6+
echo "Virtual environment not activated."
7+
exit 1
8+
fi
9+
10+
pip3 install cryptography
11+
pip3 install requests
12+
pip3 install PyJWT
13+
14+
export GITHUB_APP_ID="$SELENIARM_GITHUB_APP_ID"
15+
export GITHUB_INSTALLATION_ID="$SELENIARM_GITHUB_INSTALLATION_ID"
16+
export GITHUB_APP_PEM="$SELENIARM_GITHUB_APP_PEM"
17+
18+
python3 get-access-token.py

0 commit comments

Comments
 (0)