Skip to content

Commit 5cd8f39

Browse files
committed
feat: Implement environment validation with Docker labels
- Add enhanced Docker labels with JSON metadata for runtime and CI/CD variables - Create env-validator.py for cross-file consistency checking - Add runtime validation to start.sh - Fix deploy-app-runner.sh to only pass runtime variables (remove MXCP_DATA_*) - Add validation steps to both GitHub workflows - Update README.md with self-documenting environment approach - Delete redundant ENVIRONMENT.md.template - Add validate-env task to justfile with critical path dependencies This provides clear separation between CI/CD and runtime secrets, with automatic validation to catch configuration errors early.
1 parent f553d59 commit 5cd8f39

File tree

11 files changed

+294
-216
lines changed

11 files changed

+294
-216
lines changed

.github/scripts/deploy-app-runner.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ echo "CPU: $CPU_SIZE"
4949
echo "Memory: $MEMORY_SIZE"
5050

5151
# Build runtime environment variables JSON
52-
# Start with basic vars
52+
# Only include variables meant for runtime, NOT CI/CD secrets
5353
RUNTIME_ENV_JSON='{"PORT": "8000", "PYTHONUNBUFFERED": "1"'
5454

55-
# Add any API keys that are set
56-
for var in OPENAI_API_KEY ANTHROPIC_API_KEY VERTEC_API_KEY MXCP_DATA_ACCESS_KEY_ID MXCP_DATA_SECRET_ACCESS_KEY; do
55+
# Add only runtime API keys (exclude MXCP_DATA_* which are CI/CD only)
56+
for var in OPENAI_API_KEY ANTHROPIC_API_KEY VERTEC_API_KEY; do
5757
if [ -n "${!var}" ]; then
5858
# Escape the value for JSON
5959
ESCAPED_VALUE=$(echo "${!var}" | sed 's/"/\\"/g')

.github/workflows/deploy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ jobs:
104104
echo "📝 Validating YAML configurations..."
105105
python -c "import yaml; yaml.safe_load(open('mxcp-site.yml')); print('✅ mxcp-site.yml is valid')"
106106
python -c "import yaml, glob; [yaml.safe_load(open(f)) for f in glob.glob('tools/*.yml')]; print('✅ All tool configurations valid')"
107+
108+
- name: Validate environment consistency
109+
run: |
110+
echo "🔍 Checking environment variable consistency..."
111+
python deployment/env-validator.py
107112
echo "✅ Pre-flight checks passed"
108113
109114
deploy:

.squirro/workflows/build-and-push-to-ecr.yml.template

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ jobs:
9393
- name: Run configuration validation
9494
run: |
9595
just validate-config
96+
97+
- name: Validate environment consistency
98+
run: |
99+
echo "🔍 Checking environment variable consistency..."
100+
python deployment/env-validator.py
96101

97102
build-and-push:
98103
needs: [check-secrets, validate-config]

ENVIRONMENT.md.template

Lines changed: 0 additions & 200 deletions
This file was deleted.

README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,13 +1022,59 @@ gh secret set OPENAI_API_KEY --body "sk-..."
10221022
gh secret set AWS_ACCESS_KEY_ID --body "AKIA..."
10231023
```
10241024

1025+
## Environment Variables
1026+
1027+
This project uses a self-documenting approach for environment variables through Docker labels.
1028+
1029+
### Discovering Requirements
1030+
1031+
```bash
1032+
# List all runtime variables (passed to container)
1033+
docker inspect your-image:latest | jq -r '
1034+
.[] | .Config.Labels | to_entries[] |
1035+
select(.key | startswith("env.runtime")) |
1036+
.key + " = " + .value'
1037+
1038+
# List all CI/CD variables (used during deployment)
1039+
docker inspect your-image:latest | jq -r '
1040+
.[] | .Config.Labels | to_entries[] |
1041+
select(.key | startswith("env.cicd")) |
1042+
.key + " = " + .value'
1043+
1044+
# Parse the JSON metadata for a specific variable
1045+
docker inspect your-image:latest | jq -r '
1046+
.[] | .Config.Labels."env.runtime.OPENAI_API_KEY" | fromjson'
1047+
```
1048+
1049+
### Setting Up Your Project
1050+
1051+
1. **GitHub Secrets** (for CI/CD):
1052+
- `AWS_ACCESS_KEY_ID` (required)
1053+
- `AWS_SECRET_ACCESS_KEY` (required)
1054+
- `MXCP_DATA_ACCESS_KEY_ID` (optional - for S3 data)
1055+
- `MXCP_DATA_SECRET_ACCESS_KEY` (optional - for S3 data)
1056+
1057+
2. **Runtime Secrets** (automatically passed to App Runner):
1058+
- `OPENAI_API_KEY` (required)
1059+
- `ANTHROPIC_API_KEY` (optional)
1060+
- `VERTEC_API_KEY` (optional - API projects)
1061+
1062+
3. **GitHub Variables** (non-sensitive config):
1063+
- `AWS_REGION`, `ECR_REPOSITORY`, etc. (see config.env.template)
1064+
1065+
### Important Notes
1066+
1067+
- CI/CD secrets (AWS_*) are NEVER passed to the running container
1068+
- Runtime secrets are injected by App Runner, not baked into the image
1069+
- Run `python deployment/env-validator.py` to check consistency
1070+
10251071
## What's Included vs What's Not
10261072

10271073
### ✅ What This Template Provides
10281074

10291075
- **Health Check**: Basic `/health` endpoint for App Runner monitoring
1030-
- **Logging**: stdout/stderr captured by AWS App Runner (viewable in CloudWatch)
1031-
- **Configuration**: Secure management of API keys and settings
1076+
- **Environment Validation**: Runtime checks and consistency validation
1077+
- **Configuration**: Secure management via config.env + GitHub Secrets
10321078
- **Testing**: 4-tier testing framework (data → tools → API → LLM)
10331079
- **CI/CD**: Automated deployment pipeline
10341080

deployment/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ RUN groupadd -r mxcp && useradd -r -g mxcp -m -d /home/mxcp mxcp
2020
COPY requirements.txt ./requirements.txt
2121
RUN pip install --no-cache-dir -r requirements.txt
2222

23+
# Document runtime environment variables (injected by App Runner)
24+
LABEL env.runtime.OPENAI_API_KEY='{"required": true, "type": "secret", "description": "OpenAI API key for LLM calls", "example": "sk-..."}'
25+
LABEL env.runtime.ANTHROPIC_API_KEY='{"required": false, "type": "secret", "description": "Anthropic API key for Claude models", "example": "sk-ant-..."}'
26+
LABEL env.runtime.VERTEC_API_KEY='{"required": false, "type": "secret", "description": "Vertec API key (API projects only)", "example": "vtc_..."}'
27+
28+
# Document CI/CD environment variables (used during deployment only)
29+
LABEL env.cicd.AWS_ACCESS_KEY_ID='{"required": true, "type": "secret", "description": "AWS access key for deployment", "example": "AKIA..."}'
30+
LABEL env.cicd.AWS_SECRET_ACCESS_KEY='{"required": true, "type": "secret", "description": "AWS secret key for deployment", "example": "..."}'
31+
LABEL env.cicd.MXCP_DATA_ACCESS_KEY_ID='{"required": false, "type": "secret", "description": "AWS key for S3 data download", "example": "AKIA..."}'
32+
LABEL env.cicd.MXCP_DATA_SECRET_ACCESS_KEY='{"required": false, "type": "secret", "description": "AWS secret for S3 data download", "example": "..."}'
33+
2334
# Copy the entire project
2435
COPY . .
2536

0 commit comments

Comments
 (0)