diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3dc6f6e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,71 @@ +name: CI + +on: + workflow_dispatch: + push: + branches: + - 'master' + pull_request: + +jobs: + build: + if: github.repository == 'incendilabs/plan-executor' + + runs-on: ubuntu-24.04 + steps: + - + name: Checkout repo + uses: actions/checkout@v4 + - + name: Build docker image + run: docker build -t incendi/plan-executor:latest . + - + name: Run tests + run: | + mkdir -p logs html_summaries json_results + docker compose up -d spark + docker compose run --rm --no-deps plan_executor ./execute_all.sh 'http://spark:8080/fhir' r4 'html|json|stdout' + docker compose logs spark > logs/backend.log + - + name: Combine test results + if: ${{ always() }} + run: ./combine-test-results.sh json_results annotations.json + - + name: Attach test results + if: github.event_name != 'pull_request' + uses: yuzutech/annotations-action@v0.5.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + input: annotations.json + - + name: Archive logs + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: logs-r4-${{ github.sha }} + path: logs/*.log* + - + name: Archive test reports + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: html_summaries-r4-${{ github.sha }} + path: html_summaries/**/*.html + - + name: Archive JSON results + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: json_results-r4-${{ github.sha }} + path: json_results/**/*.json + - + name: Archive annotations file + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: annotations-r4-${{ github.sha }} + path: annotations.json + - + name: Cleanup + if: ${{ always() }} + run: cd tests/integration-tests && docker compose down \ No newline at end of file diff --git a/combine-test-results.sh b/combine-test-results.sh new file mode 100755 index 0000000..fcab1b9 --- /dev/null +++ b/combine-test-results.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +JSON_PATH=$1 +ANNOTATIONS_FILE=$2 + +function usage() { + me=`basename "$0"` + if [ ! -z "$1" ]; then + echo $1 + fi + echo "Usage: ./${me} path/to/input/json_results path/to/output/annotations.json" + exit 1 +} + +[ $# -eq 2 ] || usage + +[ ! -z "${JSON_PATH}" ] || usage + +[ -d "${JSON_PATH}" ] || usage "${JSON_PATH} must be a directory" + +touch $ANNOTATIONS_FILE || "$ANNOTATIONS_FILE is not writable" + +DIR=$(pwd) + +cd ${JSON_PATH} + +# Output summary to stdout + +ls _summary*.json | xargs jq -r '. | "PASS: \(.pass // 0) +FAIL: \(.fail // 0) +ERROR: \(.error // 0) +SKIP: \(.skip // 0)" +' + +# Have to use warning annotation level, notice isn't working anymore (but could be in future). + +SUMMARY=$(ls _summary*.json | xargs jq '[ . + | { "file": ".github/workflow/integration_tests.yml", "line": 1, "message": ("PASS: \(.pass // 0)\nFAIL: \(.fail // 0)\nERROR: \(.error // 0)\nSKIP: \(.skip // 0)"), "annotation_level": "warning" } +]') + +FAILURES=$(ls -I '_summary*.json' | xargs -I '{}' jq '[ .[] + | select(((.status == "skip") and (.message | contains("TODO") | not)) + or .status == "fail" + or .status == "error") + | .id as $id + | .status as $status + | .message as $message + | .description as $description + | .test_method as $method + | input_filename as $file + | { "file": ".github/workflow/integration_tests.yml", "line": 1, "message": ($id + ": " + $message), "annotation_level": "failure" } +]' '{}') + +cd $DIR + +jq 'reduce inputs as $i (.; . += $i)' <(echo "${SUMMARY}") <(echo "${FAILURES}") > ${ANNOTATIONS_FILE} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c8067d9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +version: "3" +services: + spark: + container_name: spark + restart: always + image: sparkfhir/spark:r4-latest + environment: + - StoreSettings__ConnectionString=mongodb://root:secret@mongodb:27017/spark?authSource=admin + - SparkSettings__Endpoint=http://spark:8080/fhir + - ASPNETCORE_URLS=http://+:8080 + - ASPNETCORE_HTTP_PORT=8080 + ports: + - "8000:8080" + - "8001:8081" + depends_on: + - mongodb + mongodb: + container_name: mongodb + image: sparkfhir/mongo:r4-latest + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: secret + ports: + - "17017:27017" + plan_executor: + container_name: plan_executor + image: incendi/plan_executor:latest + depends_on: + - spark + volumes: + - ./logs:/app/logs:rw + - ./html_summaries:/app/html_summaries:rw + - ./json_results:/app/json_results:rw