Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 126 additions & 46 deletions .github/workflows/buildandpush.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,85 +10,165 @@ on:
#- 'setup.sh'
- 'startup.sh'
- 'Dockerfile'
- 'tests/**'
- '.github/workflows/buildandpush.yml'
pull_request:
branches: [ "main" ]
paths:
#- 'setup.sh'
- 'startup.sh'
- 'Dockerfile'
- 'tests/**'
- '.github/workflows/buildandpush.yml'

jobs:
update-version:
# Resolve the versions once, from the webservice pom, and hand them to every
# later job. Nothing downstream re-reads the pom, so all jobs are guaranteed to
# agree on which release is being built.
resolve-version:
runs-on: ubuntu-latest
outputs:
bdbversion: ${{ steps.versions.outputs.bdbversion }}
wsversion: ${{ steps.versions.outputs.wsversion }}
steps:
-
name: Checkout
uses: actions/checkout@v6
-
name: Retrieve JAR version name
- name: Retrieve BridgeDb and webservice versions from the pom
id: versions
run: |
wget https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
echo "BDBVERSION=$(cat pom.xml | grep -m 1 -oP "(?<=<bridgedb-version>).*" | sed 's|</bridgedb-version>||g')" >> $GITHUB_ENV
wget -q -O pom.xml https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
BDBVERSION=$(grep -m 1 -oP "(?<=<bridgedb-version>).*" pom.xml | sed 's|</bridgedb-version>||g')
WSVERSION=$(grep -m 1 -oP "(?<=<version>).*" pom.xml | sed 's|</version>||g')
if [ -z "$BDBVERSION" ] || [ -z "$WSVERSION" ]; then
echo "ERROR: could not parse the versions out of the webservice pom." >&2
exit 1
fi
echo "bdbversion=$BDBVERSION" >> $GITHUB_OUTPUT
echo "wsversion=$WSVERSION" >> $GITHUB_OUTPUT
echo "Building for BridgeDb ${BDBVERSION}, webservice ${WSVERSION}"

-
name: Retrieve WebService version name
# Fail before the (hour-long) image build rather than part-way through it
# if the release asset the image downloads has not been published yet.
- name: Verify the webservice release JAR exists
run: |
wget https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
echo "BRIDGEDBWSVERSION=$(cat pom.xml | grep -m 1 -oP "(?<=<version>).*" | sed 's|</version>||g')" >> $GITHUB_ENV
URL="https://github.com/bridgedb/BridgeDbWebservice/releases/download/${{ steps.versions.outputs.wsversion }}/BridgeDbWebservice-${{ steps.versions.outputs.wsversion }}-jar-with-dependencies.jar"
if ! curl -sfIL -o /dev/null "$URL"; then
echo "ERROR: release asset not found: $URL" >&2
echo "The webservice release for ${{ steps.versions.outputs.wsversion }} is probably not published yet." >&2
exit 1
fi
echo "Release asset is available."

- name: Update setup.sh with BDBWSVERSION
update-version:
runs-on: ubuntu-latest
needs: resolve-version
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Update setup.sh with the resolved webservice version
run: |
cat setup.sh | sed 's|BRIDGEDBWSVERSION=".\+"|BRIDGEDBWSVERSION="${{ env.BRIDGEDBWSVERSION }}"|g' > setup_tmp.sh
mv setup_tmp.sh setup.sh

sed -i 's|BRIDGEDBWSVERSION=".\+"|BRIDGEDBWSVERSION="${{ needs.resolve-version.outputs.wsversion }}"|g' setup.sh

- name: commit and push setup.sh
if: github.ref == 'refs/heads/main'
run: |
git config --local user.name actions-user
git config --local user.email "actions@github.com"
git add setup.sh
git diff --cached --quiet || git commit -m "Updated setup.sh with ${{ env.BDBVERSION }}-${{ env.BRIDGEDBWSVERSION }}"
git diff --cached --quiet || git commit -m "Updated setup.sh with ${{ needs.resolve-version.outputs.bdbversion }}-${{ needs.resolve-version.outputs.wsversion }}"
git push origin main

echo New release tag: ${{ env.BDBWSVERSION }}
env:
REPO_KEY: ${{secrets.GITHUB_TOKEN}}
username: github-actions

docker:
runs-on: ubuntu-latest
needs: update-version
steps:
-
name: Checkout
needs: resolve-version
steps:
- name: Checkout
uses: actions/checkout@v6
-
name: Set up QEMU

# The version is pinned here, in this job's own workspace, instead of
# relying on the commit that update-version makes. checkout resolves the
# SHA that triggered the run, which predates that commit, so taking the
# version from the checked-out setup.sh silently builds the PREVIOUS
# release's JAR while tagging the image with the current version.
- name: Pin setup.sh to the resolved webservice version
run: |
sed -i 's|BRIDGEDBWSVERSION=".\+"|BRIDGEDBWSVERSION="${{ needs.resolve-version.outputs.wsversion }}"|g' setup.sh
PINNED=$(grep -m1 -E '^export BRIDGEDBWSVERSION=' setup.sh | sed -e 's/.*="//' -e 's/".*//')
if [ "$PINNED" != "${{ needs.resolve-version.outputs.wsversion }}" ]; then
echo "ERROR: setup.sh pins '$PINNED' but this build is for '${{ needs.resolve-version.outputs.wsversion }}'." >&2
exit 1
fi
echo "setup.sh pinned to $PINNED"

- name: Set up QEMU
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
-
name: Login to Docker Hub

- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Retrieve tags
run: |
wget https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
echo "BDBVERSION=$(cat pom.xml | grep -m 1 -oP "(?<=<bridgedb-version>).*" | sed 's|</bridgedb-version>||g')" >> $GITHUB_ENV
wget https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
echo "BRIDGEDBWSVERSION=$(cat pom.xml | grep -m 1 -oP "(?<=<version>).*" | sed 's|</version>||g')" >> $GITHUB_ENV
-
name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: bigcatum/bridgedb:${{ env.BDBVERSION }}-${{ env.BRIDGEDBWSVERSION }}
-
name: Build and push

# One build, one digest. This previously ran twice -- once for the version
# tag and once for :latest -- so the two tags were different images and
# :latest was never verifiably the release it claimed to be. :latest is no
# longer pushed here; it is promoted in test-and-promote once tests pass.
- name: Build and push the version tag
uses: docker/build-push-action@v7
with:
push: true
tags: bigcatum/bridgedb:latest
push: ${{ github.event_name != 'pull_request' }}
tags: bigcatum/bridgedb:${{ needs.resolve-version.outputs.bdbversion }}-${{ needs.resolve-version.outputs.wsversion }}

# Verify the image that was actually published, then point :latest at it. A
# broken or mislabelled build therefore never becomes :latest.
test-and-promote:
runs-on: ubuntu-latest
needs: [resolve-version, docker]
if: github.event_name != 'pull_request'
steps:
- name: Checkout
uses: actions/checkout@v6

# The image unpacks to roughly 9 GB of Derby databases, which does not fit
# alongside the runner's preinstalled toolchains.
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/share/boost
df -h /

- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Verify the published image
run: |
IMAGE=bigcatum/bridgedb:${{ needs.resolve-version.outputs.bdbversion }}-${{ needs.resolve-version.outputs.wsversion }}
docker pull "$IMAGE"
tests/verify-image.sh "$IMAGE" "${{ needs.resolve-version.outputs.wsversion }}"

# Re-tag by digest rather than rebuilding, so :latest is bit-for-bit the
# image that was just tested.
- name: Promote the tested image to :latest
run: |
docker buildx imagetools create \
--tag bigcatum/bridgedb:latest \
bigcatum/bridgedb:${{ needs.resolve-version.outputs.bdbversion }}-${{ needs.resolve-version.outputs.wsversion }}

- name: Confirm :latest and the version tag are the same image
run: |
TAG=bigcatum/bridgedb:${{ needs.resolve-version.outputs.bdbversion }}-${{ needs.resolve-version.outputs.wsversion }}
VERSION_DIGEST=$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$TAG")
LATEST_DIGEST=$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' bigcatum/bridgedb:latest)
echo "version tag: $VERSION_DIGEST"
echo "latest: $LATEST_DIGEST"
if [ "$VERSION_DIGEST" != "$LATEST_DIGEST" ]; then
echo "ERROR: :latest does not point at the tested image." >&2
exit 1
fi
53 changes: 53 additions & 0 deletions .github/workflows/verify-published-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Verify published image

# Checks the image that is actually on Docker Hub, independently of any build.
# This catches a tag that is mislabelled, was overwritten by hand, or has rotted
# relative to the current webservice release.

on:
workflow_dispatch:
inputs:
image:
description: 'Image to verify (default: bigcatum/bridgedb:latest)'
required: false
default: 'bigcatum/bridgedb:latest'
expected_version:
description: 'Expected webservice version (default: read from the webservice pom)'
required: false
default: ''
schedule:
# Weekly, Monday 06:00 UTC.
- cron: '0 6 * * 1'

jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

# The image unpacks to roughly 9 GB of Derby databases, which does not fit
# alongside the runner's preinstalled toolchains.
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/share/boost
df -h /

- name: Determine image and expected version
id: target
run: |
IMAGE="${{ github.event.inputs.image }}"
[ -z "$IMAGE" ] && IMAGE="bigcatum/bridgedb:latest"
EXPECTED="${{ github.event.inputs.expected_version }}"
if [ -z "$EXPECTED" ]; then
wget -q -O pom.xml https://github.com/@raw/bridgedb/BridgeDbWebservice/main/pom.xml
EXPECTED=$(grep -m 1 -oP "(?<=<version>).*" pom.xml | sed 's|</version>||g')
fi
echo "image=$IMAGE" >> $GITHUB_OUTPUT
echo "expected=$EXPECTED" >> $GITHUB_OUTPUT
echo "Verifying $IMAGE against webservice version $EXPECTED"

- name: Verify the published image
run: |
docker pull "${{ steps.target.outputs.image }}"
tests/verify-image.sh "${{ steps.target.outputs.image }}" "${{ steps.target.outputs.expected }}"
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,40 @@ To stop a container, enter the following line. This will automatically remove th
docker stop bridgedb
```

## Testing an image

`tests/` holds the checks that CI runs, and they can be run by hand against any
image or any running service.

To check a complete image — what is baked into it, plus its behaviour once
started:

```
tests/verify-image.sh bigcatum/bridgedb:3.0.31-2.1.9
```

The expected webservice version is taken from the tag; pass it explicitly as a
second argument for an image whose tag does not carry it (such as `:latest`):

```
tests/verify-image.sh bigcatum/bridgedb:latest 2.1.9
```

To test a service that is already running (a container, or a deployed host):

```
tests/smoke-test.sh http://localhost:8183 2.1.9
```

The checks cover the version the service reports for itself, the organism and
datasource catalogues, and real Derby-backed identifier mappings for human and
mouse. Both scripts exit non-zero when a check fails.

Note that the webservice answers **HTTP 200 for unknown paths**, returning an
"Unrecognized query" page rather than a 404, so these checks assert on response
bodies. Any new check should do the same — asserting on the status code alone
would pass against a server that resolves nothing at all.

In CI, `verify-published-image.yml` runs the same checks weekly against the
image on Docker Hub, and can be started manually for any tag.

Loading
Loading