Skip to content

Adapt CI for use with Geo.ca #9

Adapt CI for use with Geo.ca

Adapt CI for use with Geo.ca #9

Workflow file for this run

name: CI
on:
push:
pull_request:
workflow_dispatch:
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/nominatim
IMAGE_NAME: ${{ github.repository_owner }}/nominatim
jobs:
build:
name: Build docker image
runs-on: ubuntu-latest
outputs:
NOMINATIM_VERSION: ${{ steps.get_version.outputs.NOMINATIM_VERSION }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract Nominatim Version
id: get_version
run: echo "NOMINATIM_VERSION=$(grep -oP '(?<=ARG NOMINATIM_VERSION=)[0-9.]+' Dockerfile)" >> $GITHUB_OUTPUT
- name: Build and export image
uses: docker/build-push-action@v5
with:
context: .
tags: nominatim:${{ steps.get_version.outputs.NOMINATIM_VERSION }}
outputs: type=docker,dest=/tmp/nominatim.tar
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: nominatim-${{ steps.get_version.outputs.NOMINATIM_VERSION }}
path: /tmp/nominatim.tar
test:
name: Test docker image
needs: build
runs-on: ubuntu-latest
env:
NOMINATIM_VERSION: ${{ needs.build.outputs.NOMINATIM_VERSION }}
strategy:
matrix:
test_scenario:
- name: Import with PBF_URL and update
commands: |-
# get the data from four days ago to make sure there really are updates to apply
four_days_ago=`date --date="4 days ago" +%y%m%d`
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-${four_days_ago}.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-p 8001:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8001/search?q=avenue%20pasteur"
docker exec -i nominatim sudo -u nominatim nominatim replication --project-dir /nominatim --once
./assert-non-empty-json "http://localhost:8001/search?q=avenue%20pasteur"
- name: Import with volume mount
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-v nominatim-data:/var/lib/postgresql/16/main \
-p 8002:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8002/search?q=avenue%20pasteur"
- name: Import with bind-mount, container restart & update
commands: |-
# get the data from four days ago to make sure there really are updates to apply
four_days_ago=`date --date="4 days ago" +%y%m%d`
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-${four_days_ago}.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-v /tmp/nominatim-data:/var/lib/postgresql/16/main \
-p 8003:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8003/search?q=avenue%20pasteur"
# Stop container
docker stop nominatim
# the container needs a few seconds to shutdown cleanly apparently
sleep 15
# import to bind mount is done previously
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-${four_days_ago}.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-v /tmp/nominatim-data:/var/lib/postgresql/16/main \
-p 8004:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8004/search?q=avenue%20pasteur"
docker exec -i nominatim sudo -u nominatim nominatim replication --project-dir /nominatim --once
./assert-non-empty-json "http://localhost:8004/search?q=avenue%20pasteur"
- name: UPDATE_MODE=once with volume
commands: |-
# get the data from four days ago to make sure there really are updates to apply
four_days_ago=`date --date="4 days ago" +%y%m%d`
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-${four_days_ago}.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-e UPDATE_MODE=once \
-v nominatim-update-volume:/var/lib/postgresql/16/main \
-p 8004:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8004/search?q=avenue%20pasteur"
echo -n "check replication log for Update completed. Count:"
docker exec nominatim /bin/bash -c 'tail -f /var/log/replication.log | grep -m 1 -c "Update completed." '
- name: UPDATE_MODE=continuous with bind-mount
commands: |-
# get the data from few days ago to make sure there really are updates to apply
days_ago=`date --date="4 days ago" +%y%m%d`
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-${days_ago}.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-e UPDATE_MODE=continuous \
-v /tmp/nominatim-update-bindmount:/var/lib/postgresql/16/main \
-p 8004:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8004/search?q=avenue%20pasteur"
echo -n "check replication log for Update completed. Count:"
docker exec nominatim /bin/bash -c 'tail -f /var/log/replication.log | grep -m 1 -c "Update completed." '
- name: Import full style
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-e IMPORT_STYLE=full \
-p 8005:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8005/search?q=hotel%20de%20paris"
- name: Import admin style
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-e IMPORT_STYLE=admin \
-p 8006:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-empty-json "http://localhost:8006/search?q=hotel%20de%20paris"
- name: Import with PBF_PATH
commands: |-
wget --cut-dirs=1 -nH -xP /tmp/data https://download.geofabrik.de/europe/monaco-latest.osm.pbf
docker run -i --rm \
-e PBF_PATH=/nominatim/data/monaco-latest.osm.pbf \
-e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
-v nominatim7-data:/var/lib/postgresql/16/main \
-v /tmp/data:/nominatim/data \
-p 8007:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8007/search?q=avenue%20pasteur"
- name: REPLICATION_URL is blank
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-p 8008:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8008/search?q=avenue%20pasteur"
- name: FREEZE
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e FREEZE="true" \
-p 8009:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8009/search?q=avenue%20pasteur"
- name: GB postcode import
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/united-kingdom/england/rutland-latest.osm.pbf \
-e IMPORT_GB_POSTCODES="true" \
-p 8010:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8010/search?postalcode=LE15+8TX"
./assert-non-empty-json "http://localhost:8010/search?postalcode=PE9+3SY"
./assert-non-empty-json "http://localhost:8010/search?postalcode=PE9+4ES"
- name: REVERSE_ONLY
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e REVERSE_ONLY="true" \
-p 8011:8080 \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8011/reverse?lat=43.734&lon=7.42&format=jsonv2"
- name: Check for clean shutdown
commands: |-
docker run --detach --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-p 8009:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION
./assert-non-empty-json "http://localhost:8009/search?q=avenue%20pasteur"
# Shutdown the container
docker stop -t 60 nominatim
# Verify that the exit code is zero
CONTAINER_EXIT_CODE=$(docker inspect nominatim --format='{{.State.ExitCode}}')
test "$CONTAINER_EXIT_CODE" -eq 0
- name: WARMUP_ON_STARTUP=true
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e WARMUP_ON_STARTUP=true \
-p 8012:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8012/search?q=avenue%20pasteur"
docker logs nominatim | grep "Warming finished"
- name: WARMUP_ON_STARTUP=false
commands: |-
docker run -i --rm \
-e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
-e WARMUP_ON_STARTUP=false \
-p 8013:8080 \
--name nominatim \
nominatim:$NOMINATIM_VERSION &
./assert-non-empty-json "http://localhost:8013/search?q=avenue%20pasteur"
docker logs nominatim | grep "Skipping cache warmup"
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: nominatim-${{ needs.build.outputs.NOMINATIM_VERSION }}
path: /tmp
- name: Load image
run: |
docker load --input /tmp/nominatim.tar
docker image ls -a
- name: Checkout
uses: actions/checkout@v4
# Excute the test scenario
- name: ${{ matrix.test_scenario.name }}
working-directory: .github/workflows
run: ${{ matrix.test_scenario.commands }}
publish:
name: Publish docker image
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Install the cosign tool (for main-nrcan branch pushes only)
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: ${{ github.ref == 'refs/heads/main-nrcan' && github.repository_owner == 'Canadian-Geospatial-Platform' }}
uses: sigstore/cosign-installer@v4.0.0
- name: Extract Nominatim Version
id: get_version
run: |
echo "NOMINATIM_VERSION=$(grep -oP '(?<=ARG NOMINATIM_VERSION=)[0-9.]+' Dockerfile)" >> $GITHUB_OUTPUT
echo "NOMINATIM_VERSION_MINOR=$(grep -oP '(?<=ARG NOMINATIM_VERSION=)[0-9]+\.[0-9]+' Dockerfile)" >> $GITHUB_OUTPUT
# Compute the Docker tags and labels to apply to the built image
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
# List of Docker images to use as base name for tags
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Disable generation of latest tag
flavor: |
latest=false
# Add simple tag with nominatim version + tag with custom date format
tags: |
type=raw,value=${{ steps.get_version.outputs.NOMINATIM_VERSION }}
type=raw,value=${{ steps.get_version.outputs.NOMINATIM_VERSION }}-{{date 'YYYY-MM-DDTHH-mm'}}
type=raw,value=${{ steps.get_version.outputs.NOMINATIM_VERSION_MINOR }}
type=raw,value=${{ steps.get_version.outputs.NOMINATIM_VERSION_MINOR }}-{{date 'YYYY-MM-DDTHH-mm'}}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login against a Docker registry (for main-nrcan branch pushes only)
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: ${{ github.ref == 'refs/heads/main-nrcan' && github.repository_owner == 'Canadian-Geospatial-Platform' }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Build and push Docker image with Buildx (for main-nrcan branch pushes only)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
push: ${{ github.ref == 'refs/heads/main-nrcan' && github.repository_owner == 'Canadian-Geospatial-Platform' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.ref == 'refs/heads/main-nrcan' && github.repository_owner == 'Canadian-Geospatial-Platform' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}