Skip to content

Commit

Permalink
CI: Validate images across platforms
Browse files Browse the repository at this point in the history
Start off by checking software in which versions are known to be
non-deterministic.
  • Loading branch information
victorlin committed Mar 6, 2023
1 parent d59452c commit ae982d4
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 2 deletions.
22 changes: 20 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ jobs:
env:
DOCKER_DEFAULT_PLATFORM: ${{ matrix.platform }}

validate-platforms:
name: Validate platforms
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: docker/setup-qemu-action@v2

- uses: docker/login-action@v2
with:
registry: ghcr.io
username: nextstrain-bot
password: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}

- name: Validate final images
run: ./devel/validate-platforms -r ghcr.io -t ${{ needs.build.outputs.tag }}

push-branch:
if: startsWith(needs.build.outputs.tag, 'branch-') && github.event_name != 'pull_request'
needs: build
Expand All @@ -103,7 +121,7 @@ jobs:

push-build:
if: startsWith(needs.build.outputs.tag, 'build-')
needs: [build, test]
needs: [build, test, validate-platforms]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -126,7 +144,7 @@ jobs:
cleanup-registry:
if: always()
needs: [build, test, push-branch, push-build]
needs: [build, test, validate-platforms, push-branch, push-build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand Down
118 changes: 118 additions & 0 deletions devel/validate-platforms
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash
#
# Validate different platform builds of the final Nextstrain image.
#
set -euo pipefail

# Set default values.
registry=localhost:5000
tag=latest

# Read command-line arguments.
while getopts "r:t:" opt; do
case "$opt" in
r) registry="$OPTARG";;
t) tag="$OPTARG";;
*) echo "Usage: $0 [-r <registry>] [-t <tag>]" 1>&2; exit 1;;
esac
done

IMAGE="$registry/nextstrain/base:$tag"

main() {
report_names=()

version_commands=(
"nextclade --version"
"augur --version"
"auspice --version"
"pip show evofr | grep Version"
"datasets --version"
"dataformat version"
)

for platform in linux/amd64 linux/arm64; do
echo "[$platform] Pulling image..."
docker pull -q --platform "$platform" "$IMAGE"

echo "[$platform] Checking that the platform is expected..."
check-platform "$platform"

# Initialize a report file for each platform.
normalized_platform="$(normalize-platform "$platform")"
report_name="report_$normalized_platform"
:> "$report_name"
report_names+=("$report_name")

# Check software where downloaded versions are not deterministic at
# different points in time (e.g. if "latest" is downloaded).
echo "[$platform] Determining software versions..."
for command in "${version_commands[@]}"; do
report-output "$platform" "$command" >> "$report_name"
done
done

# Compare contents of the first platform's report file against others.

first_report="${report_names[0]}"
echo "The first report ($first_report) has the following contents:"
cat "$first_report"

echo "Comparing against other platforms..."
for report in "${report_names[@]:1}"; do
diff -U 1 "$first_report" "$report"
done

echo "Success!"

# TODO: cleanup on error
rm -rf "${report_names[@]}"
}

report-output() {
# Print a section of the report for the output of a given command.
local platform="$1"
local command="$2"

echo "Output of \"$command\":"
echo "$(docker-run "$platform" "$command")"
echo
}

normalize-platform() {
local platform="$1"

# Replace '/' with '_'
echo "${platform//\//_}"
}

check-platform() {
# Check that the platform is actually what we expect it to be.
local platform="$1"

python_platform_string="$(docker-run "$platform" "python -c \"import platform; print(platform.platform())\"")"

case "$platform" in
linux/amd64)
if [[ "$python_platform_string" != *"x86_64"* ]]; then
echo "Platform $platform not detected." 1>&2; exit 1
fi;;
linux/arm64)
if [[ "$python_platform_string" != *"aarch64"* ]]; then
echo "Platform $platform not detected." 1>&2; exit 1
fi;;
*)
echo "Platform $platform not supported." 1>&2; exit 1;;
esac
}

docker-run() {
# Run a command under the final Nextstrain image built for a specific
# platform.
local platform="$1"
local command="$2"

docker run --platform "$platform" "$IMAGE" bash -c "$command"
}

main

0 comments on commit ae982d4

Please sign in to comment.