Skip to content

fix: NPE caused by error handling code (#1925) #921

fix: NPE caused by error handling code (#1925)

fix: NPE caused by error handling code (#1925) #921

name: Build and test the Docker image
on:
pull_request:
types: [ opened, synchronize, ready_for_review ]
push:
branches: [ "main" ]
workflow_dispatch:
env:
TEST_IMAGE_NAME: 'local/openrouteservice:test'
BUILD_PLATFORMS: 'linux/amd64,linux/arm64'
jobs:
# This way the env variables are accessible in the individual jobs
prepare_environment:
name: Prepare the environment variables
runs-on: ubuntu-latest
outputs:
test_image_name: ${{ env.TEST_IMAGE_NAME }}
build_platforms: ${{ env.BUILD_PLATFORMS }}
steps:
- run: |
echo "Publish environment variables"
build_docker_images:
name: Build the docker images
runs-on: ubuntu-latest
needs:
- prepare_environment
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get and save the UID
run: |
echo "UID=$(id -u)" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: ${{ needs.prepare_environment.outputs.build_platforms }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up JDK 17
id: setup-java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Cache Maven packages
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Prepare the maven cache dependencies
run: |
echo "Sync the maven dependencies"
mvn package -Dmaven.test.skip=true -B dependency:go-offline dependency:resolve-plugins dependency:resolve -q
# Replace all RUN mvn with RUN --mount=type=cache,target=/root/.m2 mvn
sed -i 's/RUN mvn /RUN --mount=type=cache,target=\/root\/.m2 mvn /g' Dockerfile
- name: inject maven-build-cache into docker
uses: reproducible-containers/[email protected]
with:
cache-map: |
{
"/home/runner/.m2": "/root/.m2"
}
- name: Build image for platforms ${{ needs.prepare_environment.outputs.build_platforms }}
uses: docker/build-push-action@v6
with:
context: .
push: false
load: false
tags: ${{ needs.prepare_environment.outputs.test_image_name }}
platforms: "${{ needs.prepare_environment.outputs.build_platforms }}"
cache-from: type=gha
cache-to: type=gha,mode=max
run_docker_image_tests:
name: Run & test ${{ matrix.platform }}
runs-on: ${{ matrix.image }}
needs:
- prepare_environment
- build_docker_images
strategy:
matrix:
platform: [ linux/amd64,linux/arm64 ]
image: [ ubuntu-latest ]
# linux/arm64 is emulated with qemu and takes ages to build the graph.
# Only run linux/arm64 tests on ready PR and main.
isDraftPR:
- ${{ github.event_name == 'pull_request' && github.event.pull_request.draft == true }}
exclude:
- isDraftPR: true
platform: linux/arm64
steps:
- run: |
echo "Run docker test for platform ${{ matrix.platform }}"
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get and save the UID
run: |
echo "UID=$(id -u)" >> $GITHUB_ENV
- name: Set the wait time for arm64
run: |
if [[ "${{ matrix.platform }}" == 'linux/arm64' ]]; then
# arm64 is emulated and takes longer to build the graph
echo "Set HEALTH_WAIT_TIME to 600 for arm64"
echo "HEALTH_WAIT_TIME=600" >> $GITHUB_ENV
else
echo "Set HEALTH_WAIT_TIME to 260 for non-arm64"
echo "HEALTH_WAIT_TIME=260" >> $GITHUB_ENV
fi
- name: Set up QEMU for ${{ matrix.platform }}
if: ${{ matrix.platform == 'linux/arm64' }}
uses: docker/setup-qemu-action@v3
with:
platforms: ${{ matrix.platform }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Maven packages
uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Prepare the maven cache dependencies
run: |
# Replace all RUN mvn with RUN --mount=type=cache,target=/root/.m2 mvn
sed -i 's/RUN mvn /RUN --mount=type=cache,target=\/root\/.m2 mvn /g' Dockerfile
- name: inject maven-build-cache into docker
uses: reproducible-containers/[email protected]
with:
cache-map: |
{
"/home/runner/.m2": "/root/.m2"
}
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
build-args: UID=${{ env.UID }}
push: false
load: true
tags: ${{ needs.prepare_environment.outputs.test_image_name }}
platforms: "${{ matrix.platform }}"
cache-from: type=gha
- name: Start container from previously build image and wait for successful checks
run: |
mkdir -p $(pwd)/ors-docker/graphs $(pwd)/ors-docker/config $(pwd)/ors-docker/elevation_cache
chown -R $UID $(pwd)/ors-docker/graphs $(pwd)/ors-docker/config $(pwd)/ors-docker $(pwd)/ors-docker/elevation_cache
# Place cached elevation file where docker compose expects it to mount into the image
cp ors-api/src/test/files/elevation/srtm_38_03.gh $(pwd)/ors-docker/elevation_cache
# Replace image: in the docker-compose.yml with the test image. The value of image: can vary.
sed -i "s|image:.*|image: ${{ needs.prepare_environment.outputs.test_image_name }}|" docker-compose.yml
sed -i "s|#logging.level.org.heigit: INFO|logging.level.org.heigit: DEBUG|" docker-compose.yml
# Start the first build with the docker-compose setup
docker compose up -d
# Check for health to turn 200 after the graphs are build and spring-boot completely started
./.github/utils/url_check.sh 127.0.0.1 8080 /ors/v2/health 200 ${{ env.HEALTH_WAIT_TIME }}
# Stop the compose setup and continue with docker run
docker compose down
# Set graphs data access to MMAPP
sudo yq '.ors.engine.graphs_data_access = "MMAP"' -i $(pwd)/ors-docker/config/ors-config.yml
# Start the container with the test image and the raw docker run command
docker run -it -d -p 8080:8082 -v $(pwd)/ors-docker/graphs:/home/ors/graphs -v $(pwd)/ors-docker/config:/home/ors/config -v $(pwd)/ors-api/src/test/files/elevation:/home/ors/elevation_cache --name ors-instance ${{ needs.prepare_environment.outputs.test_image_name }}
# Check for health to turn 200 after the graphs are build and spring-boot completely started
./.github/utils/url_check.sh 127.0.0.1 8080 /ors/v2/health 200 ${{ env.HEALTH_WAIT_TIME }}
# Check for correct preflight settings to avoid CORS issues with ORIGIN wildcard from the example config
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.org" 200 10
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.com" 200 10
echo "Adjust the config file and set ORIGIN to https://example.org"
sudo yq '.ors.cors.allowed_origins = "https://example.org, https://test.com, http://localhost:8080"' -i $(pwd)/ors-docker/config/ors-config.yml
# Restart the container to apply the config changes
docker restart ors-instance
# Request preflight with https://example.com and https://example.org to see if it gets applied correctly
# If matrix platform is arm64, the health check will take longer
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.org" 200 ${{ env.HEALTH_WAIT_TIME }}
# It should fail with http code 403 for https://example.com since the Origin is not covered.
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.com" 403 10
echo "Recreate the container to test if the graph can be properly read again"
docker stop ors-instance
docker container prune -f
docker run -it -d -p 8080:8082 -v $(pwd)/ors-docker/graphs:/home/ors/graphs -v $(pwd)/ors-docker/config:/home/ors/config -e ors.cors.allowed_origins=https://example.org --name ors-instance ${{ needs.prepare_environment.outputs.test_image_name }}
# Request preflight with https://example.com and https://example.org to see if it gets applied correctly
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.org" 200 ${{ env.HEALTH_WAIT_TIME }}
# It should fail with http code 403 for https://example.com since the Origin is not covered.
./.github/utils/cors_check.sh 127.0.0.1 8080 /ors/v2/isochrones/geojson "https://example.com" 403 10