Skip to content

feat: "boring baseline" app template — auth/RBAC + DB + CRUD (#3)#9

Open
PhilippWu wants to merge 1 commit into
mainfrom
feat/3-starter-template
Open

feat: "boring baseline" app template — auth/RBAC + DB + CRUD (#3)#9
PhilippWu wants to merge 1 commit into
mainfrom
feat/3-starter-template

Conversation

@PhilippWu
Copy link
Copy Markdown
Owner

Summary

Closes #3

Adds an optional starter app template that is automatically bootstrapped inside every new Coder workspace. The first template is fullstack-baseline, based on tiangolo/full-stack-fastapi-template.

What's new

  • STARTER_TEMPLATE config key — set to none (default) or fullstack-baseline in RVSconfig.yml / cloud-init, or pick it interactively in the configurator CLI
  • fullstack-baseline stack: FastAPI + SQLModel + PostgreSQL 16 + React/Vite + JWT auth + RBAC + CRUD scaffolding — starts via Docker Compose on first workspace launch (~2 min)
  • Idempotent: a .bootstrapped marker prevents re-cloning across workspace restarts
  • 251 tests pass (all green)

Files changed

File Change
configurator/validators.py validate_starter_template() + fix inherited orphan-body bug
configurator/generator.py starter_template in default_config(), _RVS_KEY_ORDER, _CLOUD_INIT_TEMPLATE
configurator/cli.py _ask_starter_template() step after AI Agents
configurator/tests/test_validators.py 6 new tests + fix _full_config() bug
coder/main.tf var.starter_template, container env, startup_script bootstrap block
infra/agents.sh STARTER_TEMPLATE added to agent-env
templates/fullstack-baseline/README.md New — stack docs, ports, credentials, lifecycle
docs/deployment.md Step 7 — Starter App Templates

…fastapi-template)

Closes #3

- configurator/validators.py: add validate_starter_template() (valid: none, fullstack-baseline);
  fix inherited orphan-body bug (missing 'def validate_api_key_optional' line)
- configurator/generator.py: add starter_template field to default_config(),
  _RVS_KEY_ORDER, and _CLOUD_INIT_TEMPLATE (STARTER_TEMPLATE env var in /etc/dev-server/env)
- configurator/cli.py: add _ask_starter_template() step after AI Agents in run()
- configurator/tests/test_validators.py: add TestValidateStarterTemplate (6 tests);
  fix inherited _full_config() missing coder_admin_password
- coder/main.tf: add var.starter_template Terraform variable; pass STARTER_TEMPLATE
  into workspace container env; add startup_script block that clones
  tiangolo/full-stack-fastapi-template and runs docker compose up -d on first launch
- infra/agents.sh: include STARTER_TEMPLATE in agent-env file
- templates/fullstack-baseline/README.md: document stack, ports, credentials, lifecycle
- docs/deployment.md: add Step 7 — Starter App Templates section
Copilot AI review requested due to automatic review settings April 10, 2026 13:30
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0addc08db6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +71 to +72
git clone --depth=1 https://github.com/tiangolo/full-stack-fastapi-template "$TMPL_DIR" 2>&1 | sed 's/^/[remotevibe] /'
cd "$TMPL_DIR"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent clone failures from aborting workspace startup

The starter-template block is in the main startup_script, so with set -e a failed git clone can stop the entire agent startup before code-server is launched. In the common failure path where GitHub is temporarily unreachable (or clone fails before the target dir exists), the next cd "$TMPL_DIR" exits non-zero and the workspace fails to come up even though this feature is optional. Wrapping clone/bootstrap in a non-fatal guard (log + continue) would avoid taking down the whole workspace.

Useful? React with 👍 / 👎.

Comment on lines +83 to +84
docker compose up -d 2>&1 | sed 's/^/[remotevibe] /'
touch "$TMPL_DIR/.bootstrapped"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Check compose result before creating bootstrap marker

docker compose up -d is piped through sed, but the script does not enable pipefail, so this pipeline is treated as successful when sed succeeds even if Compose fails. The code then immediately writes .bootstrapped, which suppresses full bootstrap on later starts and can leave users with a marked-as-complete template that never actually started. Capture and validate the Compose exit status (or enable set -o pipefail) before touching the marker.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional “starter app template” feature so new Coder workspaces can auto-bootstrap a production-ready baseline application (FastAPI/React/Postgres) based on tiangolo/full-stack-fastapi-template, controlled via a new STARTER_TEMPLATE config option.

Changes:

  • Introduces starter_template configuration across the configurator (defaults, CLI prompt, validation) and cloud-init generation.
  • Adds workspace bootstrap logic in the Coder template startup script to clone/configure/start the fullstack-baseline stack and make it idempotent via a .bootstrapped marker.
  • Updates provisioning/docs to propagate and document STARTER_TEMPLATE, plus adds template documentation.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
templates/fullstack-baseline/README.md Adds documentation for the fullstack-baseline starter template (stack, ports, credentials, lifecycle).
dev-server-provision/infra/agents.sh Propagates STARTER_TEMPLATE into the workspace-mounted agent-env file.
dev-server-provision/docs/deployment.md Documents the new optional Starter App Templates step and usage.
dev-server-provision/configurator/validators.py Adds validate_starter_template() (and adjusts optional API key validator placement).
dev-server-provision/configurator/tests/test_validators.py Adds tests for validate_starter_template() and fixes _full_config() to include the admin password.
dev-server-provision/configurator/generator.py Adds starter_template default, key ordering, and emits STARTER_TEMPLATE into generated cloud-init env file.
dev-server-provision/configurator/cli.py Adds an interactive “Starter App Template” selection step to the wizard.
dev-server-provision/coder/main.tf Adds starter_template variable/env wiring and implements the workspace startup bootstrap block.

Comment on lines +65 to +91
# ── Bootstrap starter app template ──────────────────────────────────────
STARTER_TEMPLATE="$${STARTER_TEMPLATE:-none}"
if [ "$STARTER_TEMPLATE" = "fullstack-baseline" ]; then
TMPL_DIR="/home/coder/fullstack-baseline"
if [ ! -f "$TMPL_DIR/.bootstrapped" ]; then
echo "[remotevibe] Bootstrapping fullstack-baseline (tiangolo/full-stack-fastapi-template)…"
git clone --depth=1 https://github.com/tiangolo/full-stack-fastapi-template "$TMPL_DIR" 2>&1 | sed 's/^/[remotevibe] /'
cd "$TMPL_DIR"

# Generate .env from the example — patch project name and secret key
cp .env "$TMPL_DIR/.env.bak" 2>/dev/null || true
sed \
-e "s|^PROJECT_NAME=.*|PROJECT_NAME=fullstack-baseline|" \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^FIRST_SUPERUSER=.*|FIRST_SUPERUSER=admin@example.com|" \
-e "s|^FIRST_SUPERUSER_PASSWORD=.*|FIRST_SUPERUSER_PASSWORD=changeme123|" \
.env > .env.patched && mv .env.patched .env

docker compose up -d 2>&1 | sed 's/^/[remotevibe] /'
touch "$TMPL_DIR/.bootstrapped"
echo "[remotevibe] fullstack-baseline stack started."
echo "[remotevibe] Frontend : http://localhost:5173"
echo "[remotevibe] API docs : http://localhost:8000/docs"
else
echo "[remotevibe] fullstack-baseline already bootstrapped — ensuring stack is up…"
docker compose -f "$TMPL_DIR/docker-compose.yml" up -d 2>&1 | sed 's/^/[remotevibe] /' || true
fi
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The startup script runs docker compose up -d inside the workspace container, but this template does not mount a Docker socket and the workspace image only installs the Docker CLI (no daemon). As a result, docker compose will fail to connect and the starter template bootstrap won’t work. Consider either mounting /var/run/docker.sock (and documenting the security tradeoff) or implementing the stack without requiring Docker-in-workspace (e.g., run services as additional Terraform-managed containers).

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +87
git clone --depth=1 https://github.com/tiangolo/full-stack-fastapi-template "$TMPL_DIR" 2>&1 | sed 's/^/[remotevibe] /'
cd "$TMPL_DIR"

# Generate .env from the example — patch project name and secret key
cp .env "$TMPL_DIR/.env.bak" 2>/dev/null || true
sed \
-e "s|^PROJECT_NAME=.*|PROJECT_NAME=fullstack-baseline|" \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^FIRST_SUPERUSER=.*|FIRST_SUPERUSER=admin@example.com|" \
-e "s|^FIRST_SUPERUSER_PASSWORD=.*|FIRST_SUPERUSER_PASSWORD=changeme123|" \
.env > .env.patched && mv .env.patched .env

docker compose up -d 2>&1 | sed 's/^/[remotevibe] /'
touch "$TMPL_DIR/.bootstrapped"
echo "[remotevibe] fullstack-baseline stack started."
echo "[remotevibe] Frontend : http://localhost:5173"
echo "[remotevibe] API docs : http://localhost:8000/docs"
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This starter-template bootstrap is optional, but set -e plus unguarded git clone, .env patching, and the first docker compose up -d means any transient failure will abort the entire agent startup and can leave the workspace in a failed state. Wrap the bootstrap block with error handling (log and continue), and consider writing .bootstrapped only after all required steps succeed.

Suggested change
git clone --depth=1 https://github.com/tiangolo/full-stack-fastapi-template "$TMPL_DIR" 2>&1 | sed 's/^/[remotevibe] /'
cd "$TMPL_DIR"
# Generate .env from the example — patch project name and secret key
cp .env "$TMPL_DIR/.env.bak" 2>/dev/null || true
sed \
-e "s|^PROJECT_NAME=.*|PROJECT_NAME=fullstack-baseline|" \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^FIRST_SUPERUSER=.*|FIRST_SUPERUSER=admin@example.com|" \
-e "s|^FIRST_SUPERUSER_PASSWORD=.*|FIRST_SUPERUSER_PASSWORD=changeme123|" \
.env > .env.patched && mv .env.patched .env
docker compose up -d 2>&1 | sed 's/^/[remotevibe] /'
touch "$TMPL_DIR/.bootstrapped"
echo "[remotevibe] fullstack-baseline stack started."
echo "[remotevibe] Frontend : http://localhost:5173"
echo "[remotevibe] API docs : http://localhost:8000/docs"
if git clone --depth=1 https://github.com/tiangolo/full-stack-fastapi-template "$TMPL_DIR" 2>&1 | sed 's/^/[remotevibe] /' \
&& cd "$TMPL_DIR" \
&& cp .env "$TMPL_DIR/.env.bak" 2>/dev/null || true \
&& sed \
-e "s|^PROJECT_NAME=.*|PROJECT_NAME=fullstack-baseline|" \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -hex 32)|" \
-e "s|^FIRST_SUPERUSER=.*|FIRST_SUPERUSER=admin@example.com|" \
-e "s|^FIRST_SUPERUSER_PASSWORD=.*|FIRST_SUPERUSER_PASSWORD=changeme123|" \
.env > .env.patched \
&& mv .env.patched .env \
&& docker compose up -d 2>&1 | sed 's/^/[remotevibe] /'; then
touch "$TMPL_DIR/.bootstrapped"
echo "[remotevibe] fullstack-baseline stack started."
echo "[remotevibe] Frontend : http://localhost:5173"
echo "[remotevibe] API docs : http://localhost:8000/docs"
else
echo "[remotevibe] WARNING: fullstack-baseline bootstrap failed; continuing workspace startup without starter stack."
fi

Copilot uses AI. Check for mistakes.


def validate_api_key_optional(value: str) -> str | bool:
"""Accept empty or any non-whitespace string."""
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate_api_key_optional() currently returns True for all inputs, including whitespace-only strings, which contradicts its docstring (“non-whitespace string”). Either implement the documented check (treat whitespace-only as invalid or as empty) or update the docstring to match the intended behavior.

Suggested change
"""Accept empty or any non-whitespace string."""
"""Accept empty or any non-whitespace string."""
value = value.strip()
if not value:
return True

Copilot uses AI. Check for mistakes.


# ---------------------------------------------------------------------------
# Step 4b — Starter app template
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section header says “Step 4b — Starter app template”, but run() invokes _ask_starter_template() after the AI agents step (labeled “5b” below). Update the step numbering/comment to avoid confusion when maintaining the wizard flow.

Suggested change
# Step 4b — Starter app template
# Step 5b — Starter app template

Copilot uses AI. Check for mistakes.
Comment on lines +221 to +226
Set `STARTER_TEMPLATE` in `/etc/dev-server/env` **before** provisioning:

```yaml
# In RVSconfig.yml / cloud-init.yaml:
STARTER_TEMPLATE: "fullstack-baseline"
```
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section says to set STARTER_TEMPLATE in /etc/dev-server/env before provisioning, but the example shown is YAML for RVSconfig.yml / cloud-init.yaml. Consider rewording to: set it in your cloud-init.yaml/RVSconfig.yml (which is rendered into /etc/dev-server/env during provisioning) to avoid implying manual edits to /etc/dev-server/env pre-provision.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: "Boring baseline" app template — auth/RBAC + DB + CRUD pre-deployed via config flag

2 participants