diff --git a/.github/actions/run-integration-tests/action.yaml b/.github/actions/run-integration-tests/action.yaml new file mode 100644 index 00000000..fc57d382 --- /dev/null +++ b/.github/actions/run-integration-tests/action.yaml @@ -0,0 +1,66 @@ +name: "Run integration tests" +description: "Run integration tests against a provided BASE_URL" + +runs: + using: "composite" + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Python project + uses: ./.github/actions/setup-python-project + with: + python-version: ${{ inputs.python_version }} + + - name: Run integration tests script + shell: bash + env: + BASE_URL: ${{ inputs.base_url }} + AWS_REGION: ${{ inputs.aws_region }} + MTLS_SECRET_ID: ${{ inputs.mtls_secret_id }} + PREVIEW_MTLS_CERT: ${{ inputs.preview_mtls_cert }} + PREVIEW_MTLS_KEY: ${{ inputs.preview_mtls_key }} + TEST_COMMAND: ${{ inputs.test_target }} + run: | + # call the inline script so everything is visible in logs + set -euo pipefail + + echo "Base URL: $BASE_URL" + # write repo-provided certs if present + if [ -n "${PREVIEW_MTLS_CERT:-}" ] && [ -n "${PREVIEW_MTLS_KEY:-}" ]; then + printf '%s\n' "$PREVIEW_MTLS_CERT" > /tmp/mtls_cert.pem + printf '%s\n' "$PREVIEW_MTLS_KEY" > /tmp/mtls_key.pem + chmod 600 /tmp/mtls_cert.pem /tmp/mtls_key.pem + export MTLS_CERT_FILE=/tmp/mtls_cert.pem + export MTLS_KEY_FILE=/tmp/mtls_key.pem + echo "Wrote mTLS cert/key from inputs" + fi + + # If an AWS Secrets Manager secret id is provided, fetch and write cert/key + if [ -n "${MTLS_SECRET_ID:-}" ]; then + echo "Fetching mTLS secret from Secrets Manager: $MTLS_SECRET_ID" + SECRET_JSON=$(aws secretsmanager get-secret-value --secret-id "$MTLS_SECRET_ID" --region "$AWS_REGION" --query SecretString --output text) + echo "$SECRET_JSON" > /tmp/secret.json + CERT=$(jq -r '.cert' /tmp/secret.json) + KEY=$(jq -r '.key' /tmp/secret.json) + printf '%s\n' "$CERT" > /tmp/mtls_cert.pem + printf '%s\n' "$KEY" > /tmp/mtls_key.pem + chmod 600 /tmp/mtls_cert.pem /tmp/mtls_key.pem + export MTLS_CERT_FILE=/tmp/mtls_cert.pem + export MTLS_KEY_FILE=/tmp/mtls_key.pem + echo "Wrote mTLS cert/key from Secrets Manager secret" + fi + + if [ -z "${BASE_URL:-}" ]; then + echo "ERROR: BASE_URL input is empty" + exit 2 + fi + + # Accepts a custom test command, otherwise default to make test-integration + if [ -n "${TEST_COMMAND:-}" ]; then + echo "Running test command: $TEST_TARGET" + eval "$TEST_COMMAND" + else + echo "Running make test-integration" + make test-integration + fi diff --git a/.github/workflows/preview-env.yml b/.github/workflows/preview-env.yml index 4c6f1151..009ef1f0 100644 --- a/.github/workflows/preview-env.yml +++ b/.github/workflows/preview-env.yml @@ -231,6 +231,17 @@ jobs: echo "http_result=unexpected-status" >> "$GITHUB_OUTPUT" exit 0 + - name: Run integration tests (composite action) + if: github.event.action != 'closed' + uses: ./.github/actions/run-integration-tests + with: + base_url: ${{ steps.tf-output.outputs.preview_url }} + aws_region: ${{ env.AWS_REGION }} + mtls_secret_id: ${{ secrets.PREVIEW_MTLS_SECRET_ID }} + python_version: ${{ env.python_version }} + test_command: "make test-integration" + + - name: Comment function name on PR if: github.event_name == 'pull_request' && github.event.action != 'closed' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd diff --git a/gateway-api/tests/conftest.py b/gateway-api/tests/conftest.py index 5facb089..56dd63e9 100644 --- a/gateway-api/tests/conftest.py +++ b/gateway-api/tests/conftest.py @@ -28,11 +28,18 @@ def send_to_get_structured_record_endpoint(self, payload: str) -> requests.Respo """ url = f"{self.base_url}/patient/$gpc.getstructuredrecord" headers = {"Content-Type": "application/fhir+json"} + + # If the runner environment provides MTLS cert/key file paths, use them. + cert_file = os.getenv("MTLS_CERT_FILE") + key_file = os.getenv("MTLS_KEY_FILE") + cert = (cert_file, key_file) if cert_file and key_file else None + return requests.post( url=url, data=payload, headers=headers, timeout=self._timeout, + cert=cert, ) def send_health_check(self) -> requests.Response: