fix(ci): inject bcrypt hash via compose environment with $$ escaping, remove dynamic hash generation
This commit is contained in:
@@ -12,19 +12,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
# ── Generate a bcrypt hash for the CI test password ────────────────────
|
# ── Write a minimal .env required by env_file: .env in docker-compose.yml ─
|
||||||
- name: Generate CI password hash
|
# AUTH_PASSWORD_HASH is NOT set here — it's injected via docker-compose.ci.yml
|
||||||
id: pwhash
|
# environment section using $$ escaping to avoid docker-compose $VAR expansion.
|
||||||
run: |
|
|
||||||
pip install --quiet passlib bcrypt
|
|
||||||
HASH=$(python3 -c "from passlib.context import CryptContext; print(CryptContext(schemes=['bcrypt']).hash('ci-password-123'))")
|
|
||||||
echo "hash=$HASH" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
# ── Write a minimal .env consumed by docker-compose.yml ───────────────
|
|
||||||
- name: Write .env
|
- name: Write .env
|
||||||
# PW_HASH is set as an env var so bash does not expand the '$' chars in the bcrypt hash
|
|
||||||
env:
|
|
||||||
PW_HASH: ${{ steps.pwhash.outputs.hash }}
|
|
||||||
run: |
|
run: |
|
||||||
{
|
{
|
||||||
echo "SECRET_KEY=ci-only-secret-key-not-for-production"
|
echo "SECRET_KEY=ci-only-secret-key-not-for-production"
|
||||||
@@ -34,19 +25,17 @@ jobs:
|
|||||||
echo "STATUS_CHECKER_INTERVAL=300"
|
echo "STATUS_CHECKER_INTERVAL=300"
|
||||||
echo "MCP_API_KEY=ci-mcp-key"
|
echo "MCP_API_KEY=ci-mcp-key"
|
||||||
echo "MCP_SERVICE_KEY=ci-svc-key"
|
echo "MCP_SERVICE_KEY=ci-svc-key"
|
||||||
echo "AUTH_USERNAME=admin"
|
|
||||||
printf 'AUTH_PASSWORD_HASH=%s\n' "$PW_HASH"
|
|
||||||
} > .env
|
} > .env
|
||||||
|
|
||||||
# ── Build + start backend and frontend (skip mcp) ─────────────────────
|
# ── Build + start backend and frontend (skip mcp) ─────────────────────────
|
||||||
# docker-compose.ci.yml adds ports: 8000:8000 so the runner can reach the backend
|
# docker-compose.ci.yml: exposes port 8000 + injects AUTH_* env vars
|
||||||
- name: Build images
|
- name: Build images
|
||||||
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml build backend frontend
|
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml build backend frontend
|
||||||
|
|
||||||
- name: Start stack
|
- name: Start stack
|
||||||
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d backend frontend
|
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d backend frontend
|
||||||
|
|
||||||
# ── Wait for backend to be healthy (max 60 s) ─────────────────────────
|
# ── Wait for backend to be healthy (max 60 s) ─────────────────────────────
|
||||||
- name: Wait for backend health
|
- name: Wait for backend health
|
||||||
run: |
|
run: |
|
||||||
echo "Waiting for backend..."
|
echo "Waiting for backend..."
|
||||||
@@ -58,16 +47,16 @@ jobs:
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
echo "Backend did not become healthy in time" >&2
|
echo "Backend did not become healthy in time" >&2
|
||||||
docker compose logs backend
|
docker compose -f docker-compose.yml -f docker-compose.ci.yml logs backend
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
# ── Smoke: frontend serves HTML ────────────────────────────────────────
|
# ── Smoke: frontend serves HTML ───────────────────────────────────────────
|
||||||
- name: Smoke — frontend returns 200
|
- name: Smoke — frontend returns 200
|
||||||
run: |
|
run: |
|
||||||
STATUS=$(curl -so /dev/null -w "%{http_code}" http://localhost:3000/)
|
STATUS=$(curl -so /dev/null -w "%{http_code}" http://localhost:3000/)
|
||||||
[ "$STATUS" = "200" ] || { echo "Frontend returned $STATUS"; exit 1; }
|
[ "$STATUS" = "200" ] || { echo "Frontend returned $STATUS"; exit 1; }
|
||||||
|
|
||||||
# ── Tier 3: integration tests against the live stack ──────────────────
|
# ── Tier 3: integration tests against the live stack ──────────────────────
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
@@ -79,12 +68,12 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
INTEGRATION_BASE_URL: http://localhost:8000
|
INTEGRATION_BASE_URL: http://localhost:8000
|
||||||
INTEGRATION_USERNAME: admin
|
INTEGRATION_USERNAME: admin
|
||||||
INTEGRATION_PASSWORD: ci-password-123
|
INTEGRATION_PASSWORD: admin
|
||||||
run: |
|
run: |
|
||||||
cd backend
|
cd backend
|
||||||
pytest tests/test_integration.py -v
|
pytest tests/test_integration.py -v
|
||||||
|
|
||||||
# ── Teardown ───────────────────────────────────────────────────────────
|
# ── Teardown ──────────────────────────────────────────────────────────────
|
||||||
- name: Dump logs on failure
|
- name: Dump logs on failure
|
||||||
if: failure()
|
if: failure()
|
||||||
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml logs
|
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml logs
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
# CI override — exposes backend port 8000 so smoke/integration tests can reach it.
|
# CI override — exposes backend port 8000 and injects credentials.
|
||||||
# Usage: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d backend frontend
|
# Usage: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d backend frontend
|
||||||
|
#
|
||||||
|
# AUTH_PASSWORD_HASH uses $$ escaping: docker-compose converts $$ → $ before
|
||||||
|
# passing to the container, so the backend receives a valid bcrypt hash.
|
||||||
|
# This avoids the project .env file being subject to docker-compose $VAR expansion.
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
AUTH_USERNAME: admin
|
||||||
|
# bcrypt hash of "admin" — $$ is docker-compose escape for literal $
|
||||||
|
AUTH_PASSWORD_HASH: $$2b$$12$$RtMbyw17l4N5UGzeXMNAWuzCaVV.XFBY7ZetWheQhxcBDcxahapkG
|
||||||
|
|||||||
Reference in New Issue
Block a user