Skip to content
Open
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
69 changes: 52 additions & 17 deletions .github/workflows/preview-env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ env:
PYTHON_VERSION: 3.14
LAMBDA_RUNTIME: python3.14
LAMBDA_HANDLER: lambda_handler.handler
MOCK_LAMBDA_HANDLER: handler.handler
MOCK_LAMBDA_HANDLER: lambda_handler.handler
MTLS_SECRET_NAME: ${{ vars.PREVIEW_ENV_MTLS_SECRET_NAME }}
PROXYGEN_KEY_ID: ${{ vars.PREVIEW_ENV_PROXYGEN_KEY_ID }}
PROXYGEN_CLIENT_ID: ${{ vars.PREVIEW_ENV_PROXYGEN_CLIENT_ID }}
Expand Down Expand Up @@ -52,18 +52,10 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Package artifact
- name: Package artifacts
run: |
make build

# Place holder mock artifact packaging to allow testing of mock API in preview environment;
# can be extended to build a real mock Lambda if needed
- name: Package mock artifact
run: |
cd infrastructure/environments/preview
rm -f mock_artifact.zip
zip -r mock_artifact.zip .

- name: Select AWS role inputs
id: role-select
env:
Expand Down Expand Up @@ -207,12 +199,23 @@ jobs:
echo "url = ${{ steps.names.outputs.preview_url }}"

# ---------- Handle mock endpoints ----------
- name: Get Secrets for mocks
uses: aws-actions/aws-secretsmanager-get-secrets@a9a7eb4e2f2871d30dc5b892576fde60a2ecc802
with:
secret-ids: |
/cds/pathology/dev/jwks/secret
name-transformation: lowercase

- name: Create or update mock Lambda (on open/sync/reopen)
if: github.event.action != 'closed'
env:
TOKEN_EXPIRY_TIME: ${{ secrets.TOKEN_LIFETIME }}
AUTH_URL: "${{ steps.names.outputs.mock_preview_url }}/apim/oauth2/token"
JWKS_SECRET: ${{ env._cds_pathology_dev_jwks_secret }}
PUBLIC_KEY_URL: "https://example.com"
TOKEN_TABLE_NAME: "mock_services_dev"
run: |
cd infrastructure/environments/preview
cd mocks/target/
MFN="${{ steps.names.outputs.mock_function_name }}"
SAFE="${{ steps.branch.outputs.safe }}"
TOKEN_LIFETIME="${TOKEN_EXPIRY_TIME:-15m}"
Expand All @@ -237,18 +240,28 @@ jobs:
--handler "${{ env.MOCK_LAMBDA_HANDLER }}" \
--environment "Variables={CLIENT_PUBLIC_KEY_ARN=mock, \
DDB_INDEX_TAG=$SAFE, \
TOKEN_LIFETIME=$TOKEN_LIFETIME}" || true
TOKEN_LIFETIME=$TOKEN_LIFETIME, \
AUTH_URL=$AUTH_URL, \
PUBLIC_KEY_URL=$PUBLIC_KEY_URL, \
API_KEY=$JWKS_SECRET, \
TOKEN_TABLE_NAME=$TOKEN_TABLE_NAME \
}" || true
wait_for_lambda_ready
aws lambda update-function-code --function-name "$MFN" --zip-file "fileb://mock_artifact.zip" --publish
aws lambda update-function-code --function-name "$MFN" --zip-file "fileb://artifact.zip" --publish
else
aws lambda create-function --function-name "$MFN" \
--runtime "${{ env.LAMBDA_RUNTIME }}" \
--handler "${{ env.MOCK_LAMBDA_HANDLER }}" \
--zip-file "fileb://mock_artifact.zip" \
--zip-file "fileb://artifact.zip" \
--role "${{ steps.role-select.outputs.lambda_role }}" \
--environment "Variables={CLIENT_PUBLIC_KEY_ARN=mock, \
DDB_INDEX_TAG=$SAFE, \
TOKEN_LIFETIME=$TOKEN_LIFETIME}" \
TOKEN_LIFETIME=$TOKEN_LIFETIME, \
AUTH_URL=$AUTH_URL, \
PUBLIC_KEY_URL=$PUBLIC_KEY_URL, \
API_KEY=$JWKS_SECRET, \
TOKEN_TABLE_NAME=$TOKEN_TABLE_NAME, \
}" \
--publish
wait_for_lambda_ready
fi
Expand Down Expand Up @@ -472,6 +485,13 @@ jobs:
with:
path: pathology-api/test-artefacts/
merge-multiple: false
- name: "Download mock test coverage artefacts"
if: always() && github.event.action != 'closed'
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: mock-unit-test-results
path: mocks/test-artefacts/
merge-multiple: false
- name: "Merge coverage data"
if: always() && github.event.action != 'closed'
run: make test-coverage
Expand All @@ -480,20 +500,35 @@ jobs:
run: |
cd pathology-api/test-artefacts
mv coverage-merged.xml "${{ steps.create-name.outputs.artefact-name }}.xml"
cd ../..
cd mocks/test-artefacts
mv coverage-merged.xml ${{ steps.create-name.outputs.artefact-name }}-mocks.xml
- name: "Upload combined coverage report"
if: always() && github.event.action != 'closed'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ steps.create-name.outputs.artefact-name }}
path: pathology-api/test-artefacts
retention-days: 30

- name: "Upload mocks coverage report"
if: always() && github.event.action != 'closed'
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ steps.create-name.outputs.artefact-name }}-mocks
path: mocks/test-artefacts
retention-days: 30
- name: "Download merged coverage report"
if: always() && github.event.action != 'closed'
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: ${{ steps.create-name.outputs.artefact-name }}
path: coverage-reports/
- name: "Download mock coverage report"
if: always() && github.event.action != 'closed'
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: ${{ steps.create-name.outputs.artefact-name }}-mocks
path: mocks/
- name: "SonarCloud Scan"
if: always() && github.event.action != 'closed'
uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 #7.0.0
Expand Down Expand Up @@ -556,7 +591,7 @@ jobs:
'**Deployment Complete**',
`- Preview URL: [${url}](${url}) — [Status](${url}/_status)`,
` - Smoke Test: ${smokeReadable} (HTTP ${smokeStatus})`,
`- Mock URL: [${mock_url}](${mock_url})`,
`- Mock URL: [${mock_url}](${mock_url}) — [Status](${mock_url}/_status)`,
` - Smoke Mock Test: ${smokeMockReadable} (HTTP ${smokeMockStatus})`,
`- Proxy URL: [${proxy_url}](${proxy_url})`,
`- Lambda Function: ${fn}`,
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/stage-2-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,20 @@ jobs:
python-version: ${{ inputs.python_version }}
- name: "Run unit test suite"
run: make test-unit
- name: "Upload unit test results"
- name: "Upload unit test results for pathology-api"
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: unit-test-results
path: pathology-api/test-artefacts/
retention-days: 30
- name: "Upload unit test results for mocks"
if: always()
uses: actions/upload-artifact@v6
with:
name: mock-unit-test-results
path: mocks/test-artefacts/
retention-days: 30
- name: "Publish unit test results to summary"
if: always()
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4
Expand Down
1 change: 0 additions & 1 deletion .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ cd9c0efec38c5d63053dd865e5d4e207c0760d91:docs/guides/Perform_static_analysis.md:

pathology-api/pyproject.toml:ipv4:51
pathology-api/pyproject.toml:ipv4:50

mocks/pyproject.toml:ipv4:54
mocks/pyproject.toml:ipv4:55
105 changes: 96 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,41 @@ dockerNetwork := pathology-local
# Example CI/CD targets are: dependencies, build, publish, deploy, clean, etc.

.PHONY: dependencies
.ONESHELL:
dependencies: # Install dependencies needed to build and test the project @Pipeline
if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
eval "$$(pyenv init -)"; \
pyenv activate pathology; \
fi

cd pathology-api && poetry sync
cd ../

if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
pyenv deactivate pathology; \
fi

if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
pyenv activate pathology-mocks; \
fi

cd mocks && poetry sync
cd ../

if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
pyenv deactivate pathology-mocks; \
fi

.PHONY: build-pathology
.ONESHELL:
build-pathology:
@if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
eval "$$(pyenv init -)"; \
pyenv activate pathology; \
fi

.PHONY: build
build: clean-artifacts dependencies
@cd pathology-api
@echo "Starting build for pathology API..."
@echo "Running type checks..."
@rm -rf target && rm -rf dist
@poetry run mypy --no-namespace-packages .
Expand All @@ -35,38 +64,90 @@ build: clean-artifacts dependencies
@cd ./target/pathology-api
@zip -r "../artifact.zip" .

@if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
pyenv deactivate pathology; \
fi

.PHONY: build-mocks
.ONESHELL:
build-mocks:
@if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
eval "$$(pyenv init -)"; \
pyenv activate pathology-mocks; \
fi

@cd mocks
@echo "Starting build for mocks..."
@echo "Running type checks..."
@rm -rf target && rm -rf dist
@poetry run mypy --no-namespace-packages .
@echo "Packaging dependencies..."
@poetry build --format=wheel
VERSION=$$(poetry version -s)
@pip install "dist/pathology_api_mocks-$$VERSION-py3-none-any.whl" --target "./target/mocks" --platform manylinux2014_x86_64 --only-binary=:all:
# Copy lambda_handler file separately as it is not included within the package.
@cp lambda_handler.py ./target/mocks/
@cd ./target/mocks
@zip -r "../artifact.zip" .

@if [[ "$${IN_BUILD_CONTAINER}" == "true" ]]; then \
pyenv deactivate pathology-mocks; \
fi

.PHONY: build
build: clean-artifacts dependencies build-pathology build-mocks
@echo "Built artifacts for both pathology and mocks"


.PHONY: build-images
build-images: build # Build the project artefact @Pipeline
@mkdir -p infrastructure/images/pathology-api/resources/build
@cp -r pathology-api/target/pathology-api infrastructure/images/pathology-api/resources/build

@mkdir -p infrastructure/images/mocks/resources/build
@cp -r mocks/target/mocks infrastructure/images/mocks/resources/build

@echo "Building Docker image using Docker. Utilising python version: ${PYTHON_VERSION} ..."
@$(docker) buildx build --load --platform=linux/amd64 --provenance=false --build-arg PYTHON_VERSION=${PYTHON_VERSION} -t localhost/pathology-api-image infrastructure/images/pathology-api
@echo "Docker image 'pathology-api-image' built successfully!"

@echo "Building api-gateway-mock using Docker. Utilising python version: ${PYTHON_VERSION} ..."
@echo "Building api gateway image using Docker. Utilising python version: ${PYTHON_VERSION} ..."
@$(docker) buildx build --load --build-arg PYTHON_VERSION=${PYTHON_VERSION} -t localhost/api-gateway-mock-image infrastructure/images/api-gateway-mock
@echo "Docker image 'api-gateway-mock-image' built successfully!"

@echo "Building mocks Docker image using Docker. Utilising python version: ${PYTHON_VERSION} ..."
@$(docker) buildx build --load --platform=linux/amd64 --provenance=false --build-arg PYTHON_VERSION=${PYTHON_VERSION} -t localhost/mocks-image infrastructure/images/mocks
@echo "Docker image 'mocks-image' built successfully!"

publish: # Publish the project artefact @Pipeline
# TODO: Implement the artefact publishing step

deploy: clean-docker build-images # Deploy the project artefact to the target environment @Pipeline
$(docker) network create $(dockerNetwork) || echo "Docker network '$(dockerNetwork)' already exists."
$(docker) run --platform linux/amd64 --name pathology-api -p 5001:8080 --network $(dockerNetwork) -d localhost/pathology-api-image
$(docker) run --name api-gateway-mock -p 5002:5000 --network $(dockerNetwork) -d localhost/api-gateway-mock-image
$(docker) run --platform linux/amd64 --name pathology-api -p 5001:8080 --network $(dockerNetwork) -d localhost/pathology-api-image
$(docker) run --platform linux/amd64 --name mocks -p 5003:8080 --network $(dockerNetwork) -d localhost/mocks-image
$(docker) run --name pathology-api-gateway -p 5002:5000 -e TARGET_CONTAINER='PATHOLOGY_API' -e TARGET_URL='http://pathology-api:8080' --network $(dockerNetwork) -d localhost/api-gateway-mock-image
$(docker) run --name mocks-api-gateway -p 5005:5000 -e TARGET_CONTAINER='MOCKS' -e TARGET_URL='http://mocks:8080' --network $(dockerNetwork) -d localhost/api-gateway-mock-image

clean-artifacts:
@echo "Removing build artefacts..."
@rm -rf infrastructure/images/pathology-api/resources/build/
@rm -rf pathology-api/target && rm -rf pathology-api/dist
@rm -rf infrastructure/images/mocks/resources/build/
@rm -rf mocks/target && rm -rf mocks/dist

clean-docker: stop
@echo "Removing pathology API container..."
@$(docker) rm pathology-api || echo "No pathology API container currently exists."

@echo "Removing api-gateway-mock container..."
@$(docker) rm api-gateway-mock || echo "No api-gateway-mock container currently exists."
@echo "Removing pathology-api api-gateway container..."
@$(docker) rm pathology-api-gateway || echo "No pathology-api-gateway container currently exists."

@echo "Removing mocks container..."
@$(docker) rm mocks || echo "No mocks container currently exists."

@echo "Removing mocks api-gateway container..."
@$(docker) rm mocks-api-gateway || echo "No mocks-api-gateway container currently exists."

clean:: clean-artifacts clean-docker # Clean-up project resources (main) @Operations

Expand All @@ -75,8 +156,14 @@ stop:
@echo "Stopping pathology API container..."
@$(docker) stop pathology-api || echo "No pathology API container currently running."

@echo "Stopping api-gateway-mock container..."
@$(docker) stop api-gateway-mock || echo "No api-gateway-mock container currently running."
@echo "Stopping pathology-api-gateway container..."
@$(docker) stop pathology-api-gateway || echo "No pathology-api-gateway container currently running."

@echo "Stopping mocks container..."
@$(docker) stop mocks || echo "No mocks container currently running."

@echo "Stopping mocks-api-gateway container..."
@$(docker) stop mocks-api-gateway || echo "No mocks-api-gateway container currently running."

config:: # Configure development environment (main) @Configuration
# Configure poetry to trust dev certificate if specified
Expand Down
45 changes: 0 additions & 45 deletions infrastructure/environments/preview/handler.py

This file was deleted.

Loading
Loading