diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4da50fb --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +# Copy to .env and fill values +APP_ENV=development +PORT=3000 diff --git a/.github/workflows/standard-ci.yml b/.github/workflows/standard-ci.yml new file mode 100644 index 0000000..8120338 --- /dev/null +++ b/.github/workflows/standard-ci.yml @@ -0,0 +1,43 @@ +name: Standard CI + +on: + pull_request: + push: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + if: ${{ hashFiles('package.json') != '' }} + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Python + if: ${{ hashFiles('requirements.txt') != '' }} + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Node deps + if: ${{ hashFiles('package.json') != '' }} + run: | + npm install -g pnpm || true + if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else npm ci || npm install; fi + + - name: Install Python deps + if: ${{ hashFiles('requirements.txt') != '' }} + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pytest || true + + - name: Run tests + run: | + chmod +x scripts/test.sh || true + if [ -f scripts/test.sh ]; then ./scripts/test.sh; else echo "No scripts/test.sh"; fi diff --git a/scripts/check-env.sh b/scripts/check-env.sh new file mode 100755 index 0000000..873f048 --- /dev/null +++ b/scripts/check-env.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +required=(APP_ENV) + +if [[ -f .env ]]; then + # shellcheck disable=SC1091 + source .env +fi + +missing=() +for key in "${required[@]}"; do + if [[ -z "${!key:-}" ]]; then + missing+=("$key") + fi +done + +if (( ${#missing[@]} > 0 )); then + echo "Missing required env vars: ${missing[*]}" >&2 + exit 1 +fi + +echo "Environment looks good" diff --git a/scripts/e2e.sh b/scripts/e2e.sh new file mode 100755 index 0000000..a022b93 --- /dev/null +++ b/scripts/e2e.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "[e2e] Running end-to-end checks" + +if [[ -f package.json ]]; then + if command -v pnpm >/dev/null 2>&1; then + pnpm run e2e + else + npm run e2e + fi + exit 0 +fi + +echo "[e2e] No e2e runner configured" diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..fb689e8 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "[setup] Starting project setup" + +if [[ -f package.json ]]; then + if command -v pnpm >/dev/null 2>&1; then + pnpm install + elif command -v npm >/dev/null 2>&1; then + npm install + else + echo "[setup][error] node package manager not found" >&2 + exit 1 + fi +fi + +if [[ -f requirements.txt ]]; then + if [[ ! -d .venv ]]; then + python3 -m venv .venv + fi + # shellcheck disable=SC1091 + source .venv/bin/activate + pip install --upgrade pip + pip install -r requirements.txt +fi + +./scripts/check-env.sh || true + +echo "[setup] Done" diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100755 index 0000000..11402b2 --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "[start] Starting app" + +if [[ -f package.json ]]; then + if command -v pnpm >/dev/null 2>&1; then + exec pnpm start + else + exec npm start + fi +fi + +if [[ -f app.py ]]; then + if [[ -d .venv ]]; then + # shellcheck disable=SC1091 + source .venv/bin/activate + fi + export FLASK_APP=app.py + exec flask run --host 0.0.0.0 --port "${PORT:-5000}" +fi + +echo "[start][error] No known app entrypoint found" >&2 +exit 1 diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..710b72c --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "[test] Running unit/integration tests" + +if [[ -f package.json ]]; then + if command -v pnpm >/dev/null 2>&1; then + pnpm test + else + npm test + fi + exit 0 +fi + +if compgen -G "tests/*.py" >/dev/null || compgen -G "test_*.py" >/dev/null; then + if [[ -d .venv ]]; then + # shellcheck disable=SC1091 + source .venv/bin/activate + fi + python -m pytest + exit 0 +fi + +echo "[test] No tests detected"