Skip to content

Commit dddbb44

Browse files
[NDR-324] Add dev container (#927)
Co-authored-by: Kris Bloe <[email protected]>
1 parent 8dd57bc commit dddbb44

File tree

17 files changed

+5181
-18
lines changed

17 files changed

+5181
-18
lines changed

.devcontainer/Dockerfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/python:3.11
2+
3+
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
4+
git \
5+
jq \
6+
rsync \
7+
tree \
8+
unzip \
9+
wget \
10+
strip-nondeterminism \
11+
uuid-runtime \
12+
parallel \
13+
bc
14+
15+
# Install Node.js (needed for Cypress)
16+
RUN apt-get update && apt-get install -y curl gnupg && \
17+
curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && \
18+
apt-get install -y nodejs
19+
20+
# Install Cypress GUI dependencies
21+
RUN apt-get install -y \
22+
xvfb \
23+
libgtk-3-0 \
24+
libnss3 \
25+
libatk1.0-0 \
26+
libatk-bridge2.0-0 \
27+
libasound2
28+
29+
RUN wget https://github.com/mikefarah/yq/releases/download/v4.48.2/yq_linux_amd64 -O /usr/bin/yq && chmod +x /usr/bin/yq
30+
RUN wget https://github.com/asdf-vm/asdf/releases/download/v0.18.0/asdf-v0.18.0-linux-amd64.tar.gz -O - | tar xz && sudo mv asdf /usr/local/bin/asdf
31+
32+
# Install Cypress globally
33+
RUN npm install -g [email protected]
34+
35+
# Installing ASDF
36+
USER vscode
37+
RUN echo "export ASDF_DATA_DIR=/home/vscode/.asdf" >> ~/.bashrc
38+
RUN echo ". <(asdf completion bash)" >> ~/.bashrc
39+
40+
# Install poetry
41+
RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=2.2.1 python3
42+
43+
# ASDF and poetry added to path in devcontainer.json

.devcontainer/devcontainer.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"build": {
3+
"dockerfile": "Dockerfile"
4+
},
5+
"containerEnv": {
6+
"AWS_VAULT_BACKEND": "file",
7+
"AWS_VAULT_FILE_PASSPHRASE": "default"
8+
},
9+
"features": {
10+
"ghcr.io/devcontainers/features/docker-in-docker:2.12.4": {
11+
"moby": false,
12+
"version": "latest",
13+
"dockerDashComposeVersion": "latest"
14+
}
15+
},
16+
"remoteEnv": {
17+
"PATH": "${containerEnv:PATH}:/home/vscode/.asdf:/home/vscode/.asdf/shims:/home/vscode/.local/bin"
18+
},
19+
"customizations": {
20+
"vscode": {
21+
"extensions": [
22+
"ms-python.black-formatter",
23+
"ms-python.mypy-type-checker",
24+
"ms-python.python",
25+
"ms-python.vscode-pylance",
26+
"4ops.terraform",
27+
"maattdd.gitless",
28+
"ms-python.python",
29+
"rogalmic.bash-debug",
30+
"sidp.strict-whitespace",
31+
"streetsidesoftware.code-spell-checker",
32+
"tamasfe.even-better-toml",
33+
"timonwong.shellcheck",
34+
"hashicorp.terraform",
35+
"GitHub.copilot",
36+
"GitHub.copilot-chat",
37+
"LittleFoxTeam.vscode-python-test-adapter",
38+
"charliermarsh.ruff",
39+
"github.vscode-github-actions",
40+
"esbenp.prettier-vscode"
41+
],
42+
"settings": {}
43+
}
44+
},
45+
"mounts": [
46+
"source=${env:HOME}${env:USERPROFILE}/.aws,target=/home/vscode/.aws,type=bind",
47+
"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
48+
"source=${localEnv:HOME}/.gnupg,target=/home/vscode/.gnupg,type=bind,consistency=cached"
49+
],
50+
"postCreateCommand": "HOST_PWD=${localWorkspaceFolder} bash -c '.devcontainer/src/create.sh' ",
51+
52+
"runArgs": [
53+
"-e", "DISPLAY",
54+
"-v", "/tmp/.X11-unix:/tmp/.X11-unix",
55+
"--platform=linux/amd64"
56+
]
57+
}

.devcontainer/src/create.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
echo "Installing ASDF plugins and tools defined in .tool-versions."
4+
echo "If this is the first time you've launched this devcontainer it might take a little while."
5+
echo
6+
7+
# Install all the asdf plugins needed for tooling in the .tool-versions file.
8+
make install-dev
9+
10+
# Add MOTD style helper
11+
BASENAME=$(basename "$HOST_PWD")
12+
echo -e "\n. /workspaces/$BASENAME/.devcontainer/src/motd.sh\n" | tee -a ~/.bashrc ~/.profile
13+
echo 'alias av="aws-vault"' | tee -a ~/.bashrc ~/.profile
14+
15+
# Required for code signing and is in '' to delay evaluation intentionally
16+
# shellcheck disable=SC2016
17+
echo 'export GPG_TTY=$(tty)' | tee -a ~/.bashrc ~/.profile
18+
19+
# Preserve/append history across subshells
20+
echo 'shopt -s histappend' | tee -a ~/.bashrc ~/.profile
21+
echo "PROMPT_COMMAND='history -a'" | tee -a ~/.bashrc ~/.profile

.devcontainer/src/motd.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
# shellcheck disable=SC1003,SC2028
3+
check_aws_authentication() {
4+
caller_identity=$(aws sts get-caller-identity 2>/dev/null)
5+
6+
if [[ -z "$caller_identity" ]]; then
7+
echo "No valid session. Please make sure the devcontainer was run with authorised AWS STS session"
8+
echo
9+
fi
10+
11+
echo "Valid AWS CLI session for AWS account: $(aws sts get-caller-identity | jq -r '.Account')"
12+
return 0
13+
}
14+
15+
echo ' __ _ _____ _____ '
16+
echo ' | \ | | __ \| _ \ '
17+
echo ' | \ \ | | | | | | \ | '
18+
echo ' | \ \| | | | | |_/ / '
19+
echo ' | | \ | |__| | | \ \ '
20+
echo ' |_| \__|_____/|_| \_\ '
21+
echo ' '
22+
echo "You can list configured AWS profiles like this:"
23+
echo " 'aws-vault list'"
24+
echo
25+
echo "Export the AWS Environment Variables for a your session like this:"
26+
echo " 'aws-vault exec replace-this-with-my-aws-profile'"
27+
echo
28+
echo "If your session times out, simply exit the subshell and do it again:"
29+
echo " 'exit'"
30+
echo " 'aws-vault exec replace-this-with-my-aws-profile'"
31+
echo

.tool-versions

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
python 3.11.11
2+
aws-vault 7.2.0
3+
awscli 2.28.17
4+
gitleaks 8.28.0
5+
shellcheck 0.11.0
6+
terraform 1.13.0
7+
terraform-docs 0.20.0
8+
trivy 0.65.0
9+
nodejs 24.6.0
10+
pre-commit 4.3.0
11+
poetry 2.2.1
12+
awsume 4.5.4

Makefile

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ LAMBDA_LAYER_PYTHON_PATH=python/lib/python$(PYTHON_VERSION)/site-packages
1616

1717
ZIP_BASE_PATH = ./$(LAMBDAS_BUILD_PATH)/$(lambda_name)/tmp
1818
ZIP_COMMON_FILES = lambdas/utils lambdas/models lambdas/services lambdas/repositories lambdas/enums lambdas/scripts
19+
CONTAINER ?= false
20+
21+
.PHONY: install clean help format list requirements ruff
1922

2023
default: help
2124

@@ -70,33 +73,62 @@ download-api-certs: ## Downloads mTLS certificates (use with dev envs only). Usa
7073
./scripts/aws/download-api-certs.sh $(WORKSPACE)
7174

7275
test-api-e2e:
76+
ifeq ($(CONTAINER), true)
77+
cd ./lambdas && PYTHONPATH=. poetry run pytest tests/e2e/api --ignore=tests/e2e/api/fhir -vv
78+
else
7379
cd ./lambdas && ./venv/bin/python3 -m pytest tests/e2e/api --ignore=tests/e2e/api/fhir -vv
80+
endif
7481

75-
test-fhir-api-e2e: ## Runs FHIR API E2E tests. Usage: make test-fhir-api-e2e WORKSPACE=<workspace>
76-
./scripts/test/run-e2e-fhir-api-tests.sh --workspace $(WORKSPACE)
82+
test-fhir-api-e2e: ## Runs FHIR API E2E tests. Usage: make test-fhir-api-e2e WORKSPACE=<workspace> CONTAINER=<true|false>
83+
./scripts/test/run-e2e-fhir-api-tests.sh --workspace $(WORKSPACE) --container $(CONTAINER)
7784
rm -rf ./lambdas/mtls_env_certs/$(WORKSPACE)
7885

7986
test-apim-e2e: ## Runs APIM E2E tests for National Document Repository FHIR R4 API against ndr-dev.
80-
./scripts/test/run-apim-e2e-tests.sh
87+
./scripts/test/run-apim-e2e-tests.sh --container $(CONTAINER)
8188

8289
test-api-e2e-snapshots:
90+
ifeq ($(CONTAINER), true)
91+
cd ./lambdas && PYTHONPATH=. poetry run pytest tests/e2e/api --ignore=tests/e2e/api/fhir --snapshot-update
92+
else
8393
cd ./lambdas && ./venv/bin/python3 -m pytest tests/e2e/api --ignore=tests/e2e/api/fhir --snapshot-update
94+
endif
8495

8596
test-bulk-upload-e2e:
97+
ifeq ($(CONTAINER), true)
98+
cd ./lambdas && PYTHONPATH=. poetry run pytest tests/e2e/bulk_upload -vv
99+
else
86100
cd ./lambdas && ./venv/bin/python3 -m pytest tests/e2e/bulk_upload -vv
101+
endif
87102

88103
test-unit:
104+
ifeq ($(CONTAINER), true)
105+
cd ./lambdas && \
106+
PYTHONPATH=. poetry run pytest tests/unit ../scripts/github/checklist_validator/tests
107+
else
89108
cd ./lambdas && \
90109
PYTHONPATH=.. ./venv/bin/python3 -m pytest tests/unit ../scripts/github/checklist_validator/tests
110+
endif
91111

92112
test-unit-coverage:
113+
ifeq ($(CONTAINER), true)
114+
cd ./lambdas && PYTHONPATH=. poetry run pytest tests/unit --cov=. --cov-report xml:coverage.xml
115+
else
93116
cd ./lambdas && ./venv/bin/python3 -m pytest tests/unit --cov=. --cov-report xml:coverage.xml
117+
endif
94118

95119
test-unit-coverage-html:
120+
ifeq ($(CONTAINER), true)
121+
cd ./lambdas && poetry run coverage run --source=. --omit="tests/*" -m pytest -v tests/unit && coverage report && coverage html
122+
else
96123
cd ./lambdas && coverage run --source=. --omit="tests/*" -m pytest -v tests/unit && coverage report && coverage html
124+
endif
97125

98126
test-unit-collect:
127+
ifeq ($(CONTAINER), true)
128+
cd ./lambdas && PYTHONPATH=. poetry run pytest tests/unit --collect-only
129+
else
99130
cd ./lambdas && ./venv/bin/python3 -m pytest tests/unit --collect-only
131+
endif
100132

101133
env:
102134
@echo "Removing old venv."
@@ -164,6 +196,23 @@ install-pdfjs:
164196
unzip -o -d ./app/public/pdfjs ./app/public/pdfjs/pdfjs.zip
165197
rm ./app/public/pdfjs/pdfjs.zip
166198

199+
# Environment tooling targets:
200+
install-asdf:
201+
echo "Setting up ASDF and related dependencies"
202+
cut -d ' ' -f1 .tool-versions | xargs -I {} asdf plugin add {} || true
203+
asdf install
204+
205+
install-poetry:
206+
echo "Installing all poetry dependencies to local environment"
207+
poetry install
208+
209+
echo "Generating 'requirements.txt' files"
210+
$(MAKE) requirements
211+
212+
install-dev: install-asdf install-poetry install-cypress
213+
git config --unset-all core.hooksPath || true
214+
pre-commit install --config src/config/pre-commit.yml --install-hooks
215+
167216
start:
168217
npm --prefix ./app start
169218

@@ -189,11 +238,13 @@ docker-down:
189238
docker-compose -f ./app/docker-compose.yml down
190239

191240
cypress-open:
192-
TZ=GMT npm --prefix ./app run cypress
241+
xvfb-run -- npm --prefix ./app run cypress
193242

194243
cypress-run:
195-
TZ=GMT npm --prefix ./app run cypress-run
244+
xvfb-run -- npm --prefix ./app run cypress-run
196245

197246
cypress-report:
198-
TZ=GMT npm --prefix ./app run cypress-report
247+
xvfb-run -- npm --prefix ./app run cypress-report
199248

249+
install-cypress:
250+
npm install --save-dev cypress

README.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,61 @@
66
- [React User Interface README.md](app/README.md).
77
- [E2E test README.md](lambdas/tests/e2e/README.md) (we have E2E tests for our FHIR endpoints and APIM setup).
88

9-
## Installation
9+
## Running Locally
10+
11+
The dev container option standardises tools for both python (via poetry) and node via asdf.
12+
13+
> [!WARNING]
14+
> Once you have the dev container running, you will need to install your git credentials for signing your commits.
15+
16+
<!-- -->
17+
> If the dev container build errors on docker, check your config at `~/.docker/config.json`, which should have something similar to:
18+
>
19+
> ```json
20+
> {
21+
> "auths": {}
22+
> }
23+
> ```
24+
>
25+
> Remove any lines that mention `desktop`.
26+
27+
### Pre-requisites
28+
29+
The following tools are required for all options:
1030
1131
- [Git](https://git-scm.com/)
32+
- Docker (e.g. via [Brew](https://formulae.brew.sh/formula/docker))
33+
34+
### Method 1 - Dev container within VS Code (recommended)
35+
36+
> [!IMPORTANT]
37+
> This **will not work** within a VS Code Workspace.
38+
39+
1. Install the `Dev Containers` VSCode extension.
40+
1. Press `Ctrl+Shift+P`.
41+
1. Select `Dev Containers: Rebuild and Reopen in Container`.
42+
43+
### Method 2 - Dev container (not using VS Code)
44+
45+
If you don't use VSCode, run the following commands:
46+
47+
```bash
48+
npm install -g @devcontainers/cli
49+
devcontainer build --workspace-folder .
50+
devcontainer up --workspace-folder .
51+
devcontainer exec --workspace-folder . bash
52+
```
53+
54+
### Method 3 - Manual installation
55+
1256
- [Terraform](https://formulae.brew.sh/formula/terraform)
13-
- [docker](https://formulae.brew.sh/formula/docker)
1457
- [docker-compose](https://formulae.brew.sh/formula/docker-compose)
1558
- [AWS CLI](https://aws.amazon.com/cli/)
1659
- [Awsume](https://formulae.brew.sh/formula/awsume)
1760
- [ruff](https://formulae.brew.sh/formula/ruff)
1861
- [Node@24](https://formulae.brew.sh/formula/node@24)
1962
- [[email protected]](https://formulae.brew.sh/formula/[email protected])
2063

21-
_Note: It is recommended to use [Homebrew](https://brew.sh/) to install most of these._
22-
2364
## Monitoring
2465

2566
We have configured AWS CloudWatch to provide alarm notifications whenever one of a number of metrics exceeds its normal

lambdas/tests/e2e/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ output=json
3636

3737
Make sure your AWS profile has access to the required resources.
3838

39+
## Using the dev container
40+
41+
All of the below make commands can be used in the dev container. To run the below commands you need to append `CONTAINER=true`.
42+
3943
## 🔧 Available Make Commands
4044

4145
- `make test-fhir-api-e2e WORKSPACE=<workspace>` — Runs the FHIR API E2E tests with mTLS against a given workspace

0 commit comments

Comments
 (0)