Skip to content

CI

CI #1449

Workflow file for this run

name: CI
on: [push, pull_request, workflow_dispatch]
# Prevent intermediate images from being used by another run.
# Concurrency group is unique:
# 1. to this workflow (github.workflow)
# 2. per event ref (github.ref)
# 3. per run on the default branch (github.run_id)
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch && github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nextstrain/.github/actions/shellcheck@master
# Build multi-platform builder and final images with caching from Docker Hub
# and GitHub Container Registry; push to GitHub Container Registry.
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '>=3.8'
- name: Set $CACHE_DATE
run: echo "CACHE_DATE=$(date --utc +%Y%m%dT%H%M%SZ)" | tee -a "$GITHUB_ENV"
- if: github.event_name != 'pull_request' && github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch
name: Set $TAG (default branch)
run: echo "TAG=build-$CACHE_DATE" | tee -a "$GITHUB_ENV"
- if: env.TAG == ''
name: Set $TAG (PRs, non-default branch)
# From `man docker-image-tag`: The tag name must be valid ASCII and may
# contain lowercase and uppercase letters, digits, underscores, periods
# and hyphens.
run: echo "TAG=branch-${GITHUB_REF_NAME//[^A-Za-z0-9._-]/-}" | tee -a "$GITHUB_ENV"
- uses: docker/setup-qemu-action@v3
# GITHUB_TOKEN is unreliable¹ so use a token from nextstrain-bot.
# ¹ https://github.com/docker/build-push-action/issues/463#issuecomment-939394233
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: nextstrain-bot
password: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}
- run: ./devel/build -p linux/amd64,linux/arm64 -r ghcr.io -t "$TAG" -l logs/
- if: always()
name: Upload build logs as artifacts
uses: actions/upload-artifact@v4
with:
name: build-logs
path: logs/
- if: always()
name: Summarize build logs for the GitHub Actions run summary page
run: |
for log in logs/*; do
{
echo "## $(basename "$log")"
echo ''
echo '```'
./devel/summarize-buildkit-output "$log" 2>&1
echo '```'
echo ''
} >> "$GITHUB_STEP_SUMMARY"
done
outputs:
tag: ${{ env.TAG }}
# Run tests with the final image from GitHub Container Registry.
test:
name: test (${{ matrix.platform }})
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
platform:
- linux/amd64
- linux/arm64
permissions:
contents: read
id-token: write
steps:
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: nextstrain-bot
password: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::827581582529:role/GitHubActionsRoleNextstrainTmpBucket
- run: aws sts get-caller-identity
- uses: actions/setup-python@v5
with:
python-version: ~3
# The ubuntu-latest runner is linux/amd64 so anything else will
# run with emulation, which is still better than nothing.
- if: matrix.platform != 'linux/amd64'
uses: docker/setup-qemu-action@v3
- uses: actions/checkout@v4
- run: pip install cram
- run: make test
env:
IMAGE: ghcr.io/nextstrain/base:${{ needs.build.outputs.tag }}
DOCKER_DEFAULT_PLATFORM: ${{ matrix.platform }}
- uses: nextstrain/.github/actions/setup-nextstrain-cli@master
- name: Run zika-tutorial
run: |
git clone https://github.com/nextstrain/zika-tutorial
nextstrain build --image ghcr.io/nextstrain/base:${{ needs.build.outputs.tag }} zika-tutorial -F
env:
DOCKER_DEFAULT_PLATFORM: ${{ matrix.platform }}
validate-platforms:
name: Validate platforms
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/login-action@v3
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" (copy) the builder and final images from GitHub Container Registry to
# Docker Hub, where they will persist. Do this regardless of test results.
push-branch:
if: startsWith(needs.build.outputs.tag, 'branch-') && github.event_name != 'pull_request'
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: nextstrain-bot
password: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}
- uses: docker/login-action@v3
with:
registry: docker.io
username: nextstrainbot
password: ${{ secrets.DOCKER_TOKEN }}
- name: Copy $TAG images to Docker Hub
run: ./devel/copy-images -i ghcr.io -o docker.io -t ${{ needs.build.outputs.tag }}
# "Push" (copy) the builder and final images from GitHub Container Registry to
# Docker Hub, where they will persist. Only do this if tests pass.
push-build:
if: startsWith(needs.build.outputs.tag, 'build-')
needs: [build, test, validate-platforms]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: nextstrain-bot
password: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}
- uses: docker/login-action@v3
with:
registry: docker.io
username: nextstrainbot
password: ${{ secrets.DOCKER_TOKEN }}
- name: Copy $TAG + latest images to Docker Hub
run: |
./devel/copy-images -i ghcr.io -o docker.io -t ${{ needs.build.outputs.tag }} -l
# Run pathogen repo CI builds with the final image
# This is running pathogen-repo-ci@v0 for pathogen repos that do not conform
# to the standard pathogen repo structure and is not expected to be updated.
# Any new pathogen repos should be added to the job using the latest version
# of the pathogen-repo-ci below.
test-pathogen-repo-ci-v0:
# Only one of push-{branch,build} runs for any given workflow run, and
# we're ok with either of them.
needs: [build, push-branch, push-build]
if: |2
success()
|| needs.push-branch.result == 'success'
|| needs.push-build.result == 'success'
strategy:
matrix:
include:
- { pathogen: avian-flu, build-args: --configfile config/gisaid.yaml -pf test_target }
- { pathogen: ebola }
- { pathogen: mumps }
- { pathogen: ncov, build-args: all_regions -j 2 --profile nextstrain_profiles/nextstrain-ci }
- { pathogen: rsv }
- { pathogen: seasonal-flu, build-args: --configfile profiles/ci/builds.yaml -p }
name: test-pathogen-repo-ci-v0 (${{ matrix.pathogen }})
uses: nextstrain/.github/.github/workflows/pathogen-repo-ci.yaml@v0
with:
repo: nextstrain/${{ matrix.pathogen }}
build-args: ${{ matrix.build-args }}
runtimes: |
- docker
env: |
NEXTSTRAIN_DOCKER_IMAGE: nextstrain/base:${{ needs.build.outputs.tag }}
artifact-name: ${{ matrix.pathogen }}-outputs
continue-on-error: true
secrets: inherit
# Run pathogen repo CI builds with the final image
# This is running pathogen-repo-ci@master for pathogen repos that _do_ follow
# standard pathogen repo structure and new pathogens should be added here
# to be supported for future updates such as testing on multiple platforms.
test-pathogen-repo-ci:
# Only one of push-{branch,build} runs for any given workflow run, and
# we're ok with either of them.
needs: [build, push-branch, push-build]
if: |2
success()
|| needs.push-branch.result == 'success'
|| needs.push-build.result == 'success'
strategy:
# XXX TODO: Test on multiple platforms via the matrix too, as above?
matrix:
pathogen:
- dengue
- lassa
- measles
- mpox
- seasonal-cov
- zika
name: test-pathogen-repo-ci (${{ matrix.pathogen }})
uses: nextstrain/.github/.github/workflows/pathogen-repo-ci.yaml@master
with:
repo: nextstrain/${{ matrix.pathogen }}
runtimes: |
- docker
env: |
NEXTSTRAIN_DOCKER_IMAGE: nextstrain/base:${{ needs.build.outputs.tag }}
artifact-name: ${{ matrix.pathogen }}-outputs
continue-on-error: true
secrets: inherit
# Delete the builder and final images from GitHub Container Registry.
cleanup-registry:
if: always()
needs: [build, test, validate-platforms, push-branch, push-build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}
script: |
const script = require('./devel/delete-from-ghcr.js');
const tag = "${{ needs.build.outputs.tag }}";
const token = "${{ secrets.GH_TOKEN_NEXTSTRAIN_BOT_MANAGE_PACKAGES }}";
script({fetch, octokit: github, tag, token});