From 38966ea51e87474625993f4ee41452f78891fe08 Mon Sep 17 00:00:00 2001 From: Lynn Date: Sun, 8 Mar 2026 15:13:16 -0700 Subject: [PATCH 01/18] feat: Add GitHub token support to devcontainer and automate GitHub CLI authentication in setup script. --- templates/.devcontainer/devcontainer.json | 3 ++- templates/scripts/setup-env.sh | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/templates/.devcontainer/devcontainer.json b/templates/.devcontainer/devcontainer.json index 454ddf6..edceb9c 100644 --- a/templates/.devcontainer/devcontainer.json +++ b/templates/.devcontainer/devcontainer.json @@ -30,7 +30,8 @@ }, "postAttachCommand": "code README.md AGENTS.md", "containerEnv": { - "GEMINI_API_KEY": "${localEnv:GEMINI_API_KEY}" + "GEMINI_API_KEY": "${localEnv:GEMINI_API_KEY}", + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" }, "postStartCommand": "/bin/bash ./.devcontainer/boot-check.sh" } \ No newline at end of file diff --git a/templates/scripts/setup-env.sh b/templates/scripts/setup-env.sh index d1944df..a4edb6e 100644 --- a/templates/scripts/setup-env.sh +++ b/templates/scripts/setup-env.sh @@ -33,6 +33,10 @@ echo "You can get a Fine-grained PAT from: https://github.com/settings/tokens?ty echo "It needs 'Pull Requests: Read-only' and 'Contents: Read-only' access to relevant repositories." read -p "Enter your GitHub Token (press Enter to skip): " GITHUB_TOKEN +if [ -n "$GITHUB_TOKEN" ]; then + echo "To authenticate the GitHub CLI, run: echo \$GITHUB_TOKEN | gh auth login --with-token" +fi + # Portable sed: works on both macOS (BSD sed) and Linux (GNU sed) portable_sed() { if sed --version 2>/dev/null | grep -q GNU; then @@ -76,6 +80,11 @@ fi if [ -n "$GITHUB_TOKEN" ]; then update_env "GITHUB_TOKEN" "$GITHUB_TOKEN" + # Authenticate GitHub CLI if we are in an environment where gh is available + if command -v gh &> /dev/null; then + echo "$GITHUB_TOKEN" | gh auth login --with-token + echo "GitHub CLI authenticated." + fi fi # Update the LICENSE file if it exists From 097bb8fe18c0e089a21babbfe6a450160a439cb1 Mon Sep 17 00:00:00 2001 From: Lynn Date: Sun, 8 Mar 2026 15:33:38 -0700 Subject: [PATCH 02/18] feat: Introduce `start-container.sh` as the devcontainer `postStartCommand` to streamline environment setup and Git integration. --- install.sh | 2 +- templates/.devcontainer/boot-check.sh | 5 +++++ templates/.devcontainer/devcontainer.json | 2 +- templates/.githooks/commit-msg | 0 templates/.githooks/pre-commit | 0 templates/AGENTS.md | 10 +++++++++- templates/README.md | 9 +++++---- templates/scripts/setup-env.sh | 3 ++- templates/scripts/setup-gemini.sh | 8 ++++++-- templates/scripts/start-container.sh | 14 ++++++++++++++ 10 files changed, 43 insertions(+), 10 deletions(-) mode change 100644 => 100755 templates/.githooks/commit-msg mode change 100644 => 100755 templates/.githooks/pre-commit create mode 100755 templates/scripts/start-container.sh diff --git a/install.sh b/install.sh index 069b05f..582a55c 100644 --- a/install.sh +++ b/install.sh @@ -25,7 +25,7 @@ fi mkdir -p docs/decisions # Make scripts executable -chmod +x .devcontainer/boot-check.sh scripts/setup-env.sh scripts/setup-gemini.sh +chmod +x .devcontainer/boot-check.sh scripts/setup-env.sh scripts/setup-gemini.sh scripts/start-container.sh chmod +x .githooks/* echo "βœ… Bootstrap complete. Open in VS Code or Antigravity to start the Devcontainer." \ No newline at end of file diff --git a/templates/.devcontainer/boot-check.sh b/templates/.devcontainer/boot-check.sh index 6560424..0ec767c 100644 --- a/templates/.devcontainer/boot-check.sh +++ b/templates/.devcontainer/boot-check.sh @@ -28,4 +28,9 @@ else git config --global user.signingkey "key::${SSH_PUBLIC_KEY}" git config --global commit.gpgsign true fi + + # Configure GitHub CLI as credential helper if token is present + if [ -n "${GITHUB_TOKEN:-}" ] && command -v gh &> /dev/null; then + gh auth setup-git + fi fi \ No newline at end of file diff --git a/templates/.devcontainer/devcontainer.json b/templates/.devcontainer/devcontainer.json index edceb9c..7e6f448 100644 --- a/templates/.devcontainer/devcontainer.json +++ b/templates/.devcontainer/devcontainer.json @@ -33,5 +33,5 @@ "GEMINI_API_KEY": "${localEnv:GEMINI_API_KEY}", "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" }, - "postStartCommand": "/bin/bash ./.devcontainer/boot-check.sh" + "postStartCommand": "/bin/bash ./scripts/start-container.sh" } \ No newline at end of file diff --git a/templates/.githooks/commit-msg b/templates/.githooks/commit-msg old mode 100644 new mode 100755 diff --git a/templates/.githooks/pre-commit b/templates/.githooks/pre-commit old mode 100644 new mode 100755 diff --git a/templates/AGENTS.md b/templates/AGENTS.md index 430bd4f..0b3358d 100644 --- a/templates/AGENTS.md +++ b/templates/AGENTS.md @@ -29,6 +29,14 @@ Before implementing any significant change: - **Pragmatism (YAGNI & KISS):** Build for current requirements. Avoid premature abstraction (Rule of Three) and over-engineering. - **Observability:** Code is not complete until it emits the necessary telemetry (logs/traces). +## πŸ”„ Devcontainer Lifecycle Scripts + +When adding or modifying automation scripts for the devcontainer, you must adhere to the following execution contexts defined in `devcontainer.json`: + +1. **`postCreateCommand`**: Use for heavy, one-time global installations (e.g., global `npm` packages, binaries) that should be baked into the image after the `Dockerfile` completes. Examples: `setup-gemini.sh`. This runs *only once* when the container is built. +2. **`postStartCommand`**: Use for fast, idempotent environment checks and initializations that must be present every time the developer connects. Examples: `start-container.sh` (which configures git hooks and reads `.env`). This runs *every time* the container starts or wakes up. +3. **Manual Interactive Scripts**: Any script that requires user interaction (e.g., using `read -p`) must **never** be added to an automated lifecycle hook. If added to `postStartCommand`, the container boot process will hang indefinitely waiting for input on a detached TTY. Examples: `setup-env.sh`. Instead, ensure the idempotent `start-container.sh` script checks for the required state and warns the user to run the interactive script manually. + ## πŸ— Coding Standards - **Linting:** Run Prettier before every commit. The pre-commit hook (`.githooks/pre-commit`) runs `make lint` automatically. @@ -47,7 +55,7 @@ Before implementing any significant change: ## πŸ€– Token Optimization & CLI Usage -- **GitHub CLI:** The `gh` command is available in this container and authenticated if you need to create/review PRs, manage issues, or check GitHub Actions status. See [.env.example](.env.example) for required `GITHUB_TOKEN` scopes. +- **GitHub CLI:** The `gh` command is available in this container. If a `GITHUB_TOKEN` is provided in `.env`, the host's CLI will be authenticated and `gh auth setup-git` will automatically configure it as your Git credential helper. This enables seamless HTTPS Git operations in the environment. See [.env.example](.env.example) for required `GITHUB_TOKEN` scopes. - **Offload Structured Edge-Tasks:** To preserve your context window (tokens) for complex logic, use the Gemini CLI (`@google/gemini-cli`) installed in this container for well-structured tasks. - **Usage:** Run `gemini` in the terminal to start an interactive session, or `gemini -p ""` for one-shot tasks. - **Examples:** Ask the CLI to review code, analyze architecture, or investigate issuesβ€”this keeps your IDE context window focused on the primary task. diff --git a/templates/README.md b/templates/README.md index 8d8a3a8..24d1798 100644 --- a/templates/README.md +++ b/templates/README.md @@ -33,8 +33,9 @@ Here's what was installed and why: β”‚ └── commit-msg # Enforces Conventional Commits format β”‚ β”œβ”€β”€ scripts/ # βš™οΈ Setup & automation scripts -β”‚ β”œβ”€β”€ setup-env.sh # Interactive setup for Git credentials & API keys -β”‚ └── setup-gemini.sh # Installs Gemini CLI +β”‚ β”œβ”€β”€ start-container.sh # [postStartCommand] Fast, idempotent environment checks (runs every boot) +β”‚ β”œβ”€β”€ setup-env.sh # [Manual] Interactive setup for Git credentials & API keys (prompts user) +β”‚ └── setup-gemini.sh # [postCreateCommand] Heavy, one-time global installations (runs once on build) β”‚ β”œβ”€β”€ docs/ β”‚ └── decisions/ # πŸ“ Architecture Decision Records (ADRs) @@ -82,7 +83,7 @@ Once the container is ready, open a terminal and run: ./scripts/setup-env.sh ``` -This will configure your Git identity, SSH signing, and prompt for any required API keys (Gemini, GitHub). +This will configure your Git identity, SSH signing, and prompt for any required API keys (Gemini, GitHub). Providing a GitHub Token locally inside this environment will automatically authenticate the `gh` CLI and set it up as your Git credential helper for seamless HTTPS operations. Then activate the git hooks and project setup: @@ -90,7 +91,7 @@ Then activate the git hooks and project setup: make setup ``` -> **Note:** If your devcontainer seems to hang after building, or if `git` complains about missing user name and email, you can manually run `./.devcontainer/boot-check.sh` to apply `.env` variables to your environment. +> **Note:** If your devcontainer seems to hang after building, or if `git` complains about missing user name and email, you can manually run `./scripts/start-container.sh` to apply `.env` variables and verify hooks. ### 4. Build Something Great diff --git a/templates/scripts/setup-env.sh b/templates/scripts/setup-env.sh index a4edb6e..8a9179c 100644 --- a/templates/scripts/setup-env.sh +++ b/templates/scripts/setup-env.sh @@ -83,7 +83,8 @@ if [ -n "$GITHUB_TOKEN" ]; then # Authenticate GitHub CLI if we are in an environment where gh is available if command -v gh &> /dev/null; then echo "$GITHUB_TOKEN" | gh auth login --with-token - echo "GitHub CLI authenticated." + gh auth setup-git + echo "GitHub CLI authenticated and configured as Git credential helper." fi fi diff --git a/templates/scripts/setup-gemini.sh b/templates/scripts/setup-gemini.sh index b17fc03..6c74282 100644 --- a/templates/scripts/setup-gemini.sh +++ b/templates/scripts/setup-gemini.sh @@ -2,7 +2,11 @@ set -euo pipefail # Install Gemini CLI globally -echo "Installing Gemini CLI..." -npm install -g @google/gemini-cli +if command -v gemini &> /dev/null; then + echo "Gemini CLI is already installed." +else + echo "Installing Gemini CLI..." + npm install -g @google/gemini-cli +fi echo "βœ… Gemini CLI setup complete! Run 'gemini' to start." diff --git a/templates/scripts/start-container.sh b/templates/scripts/start-container.sh new file mode 100755 index 0000000..a15fe57 --- /dev/null +++ b/templates/scripts/start-container.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -euo pipefail + +echo "πŸš€ Starting Antigravity Devcontainer environment..." + +# 1. Check existing environment variables and apply Git configuration +echo "Checking environment variables..." +bash ./.devcontainer/boot-check.sh + +# 2. Configure Git hooks via Makefile +echo "Ensuring Git hooks are configured..." +make setup + +echo "βœ… Container startup complete." From e3770b143a3d97caaf2e92c5423369fd03868c5d Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:12:00 +0000 Subject: [PATCH 03/18] fix(container): resolve project root in start-container.sh --- scripts/start-container.sh | 17 +++++++++++++++++ templates/scripts/start-container.sh | 3 +++ 2 files changed, 20 insertions(+) create mode 100755 scripts/start-container.sh diff --git a/scripts/start-container.sh b/scripts/start-container.sh new file mode 100755 index 0000000..940fa80 --- /dev/null +++ b/scripts/start-container.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +# Change to the repository root relative to the script's location +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +echo "πŸš€ Starting Antigravity Devcontainer environment..." + +# 1. Check existing environment variables and apply Git configuration +echo "Checking environment variables..." +bash ./.devcontainer/boot-check.sh + +# 2. Configure Git hooks via Makefile +echo "Ensuring Git hooks are configured..." +make setup + +echo "βœ… Container startup complete." diff --git a/templates/scripts/start-container.sh b/templates/scripts/start-container.sh index a15fe57..940fa80 100755 --- a/templates/scripts/start-container.sh +++ b/templates/scripts/start-container.sh @@ -1,6 +1,9 @@ #!/bin/bash set -euo pipefail +# Change to the repository root relative to the script's location +cd "$(dirname "${BASH_SOURCE[0]}")/.." + echo "πŸš€ Starting Antigravity Devcontainer environment..." # 1. Check existing environment variables and apply Git configuration From 49a61ccab3244bcb4b20a00a0017423b92ec0916 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:12:10 +0000 Subject: [PATCH 04/18] chore: add root .gitignore from template --- .gitignore | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b99ae2b --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Environment +.env +.env.* +!.env.example + +# Node +node_modules/ +dist/ +build/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.eslintcache + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +venv/ + +# Go +bin/ +obj/ +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out + +# Mac +.DS_Store + +# IDEs +.idea/ +.vscode/ +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.swp From fe162a44a2dffd12d7c7a412aa644b14c24732a7 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:12:16 +0000 Subject: [PATCH 05/18] chore(scripts): make setup scripts executable --- scripts/setup-env.sh | 84 +++++++++++++++++++++++++++++++ scripts/setup-gemini.sh | 12 +++++ templates/scripts/setup-env.sh | 20 ++------ templates/scripts/setup-gemini.sh | 0 4 files changed, 99 insertions(+), 17 deletions(-) create mode 100755 scripts/setup-env.sh create mode 100755 scripts/setup-gemini.sh mode change 100644 => 100755 templates/scripts/setup-env.sh mode change 100644 => 100755 templates/scripts/setup-gemini.sh diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh new file mode 100755 index 0000000..31465d6 --- /dev/null +++ b/scripts/setup-env.sh @@ -0,0 +1,84 @@ +#!/bin/bash +set -euo pipefail + +# Re-runnable script to initialize or update .env +if [ ! -f .env.example ]; then + echo "Error: .env.example not found. Please create it first." + exit 1 +fi + +if [ ! -f .env ]; then + cp .env.example .env + echo ".env created from template." +fi + +echo "Setting up environment variables..." +read -p "Enter your Git Name: " GIT_NAME +read -p "Enter your Git Email: " GIT_EMAIL + +echo "" +echo "Optional: SSH Public Key for commit signing." +echo "If you use 1Password as your SSH agent, you can copy the public key string directly." +echo "(e.g., ssh-ed25519 AAAAC3Nz...)" +read -p "Enter your SSH Public Key (press Enter to skip): " SSH_PUBLIC_KEY + +echo "" +echo "Optional: The Gemini API Key is used by the Gemini CLI inside this Devcontainer." +echo "You can get an API key from: https://aistudio.google.com/app/apikey" +read -p "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY + +echo "" +echo "Optional: Authenticate with GitHub CLI for automations inside the Devcontainer." +echo "To authenticate, you can run: gh auth login" + +# Portable sed: works on both macOS (BSD sed) and Linux (GNU sed) +portable_sed() { + if sed --version 2>/dev/null | grep -q GNU; then + sed -i "$@" + else + sed -i '' "$@" + fi +} + +# Function to securely update or append inside .env +update_env() { + local key=$1 + local value=$2 + if grep -q "^${key}=" .env; then + portable_sed "s|^${key}=.*|${key}=${value}|" .env + else + echo "${key}=${value}" >> .env + fi +} + +update_env "GIT_NAME" "$GIT_NAME" +update_env "GIT_EMAIL" "$GIT_EMAIL" + +if [ -n "$SSH_PUBLIC_KEY" ]; then + update_env "SSH_PUBLIC_KEY" "$SSH_PUBLIC_KEY" +fi + +# Also configure git locally for the current environment +git config --global user.name "$GIT_NAME" +git config --global user.email "$GIT_EMAIL" + +if [ -n "$SSH_PUBLIC_KEY" ]; then + git config --global gpg.format ssh + git config --global user.signingkey "key::${SSH_PUBLIC_KEY}" + git config --global commit.gpgsign true +fi + +if [ -n "$GEMINI_API_KEY" ]; then + update_env "GEMINI_API_KEY" "$GEMINI_API_KEY" +fi + + + +# Update the LICENSE file if it exists +if [ -f "LICENSE" ] && [ -n "$GIT_NAME" ]; then + CURRENT_YEAR=$(date +"%Y") + portable_sed "s|\[Year\]|${CURRENT_YEAR}|g" LICENSE + portable_sed "s|\[Full Name\]|${GIT_NAME}|g" LICENSE +fi + +echo "βœ… Configuration complete. Restart your terminal or source the .env file." \ No newline at end of file diff --git a/scripts/setup-gemini.sh b/scripts/setup-gemini.sh new file mode 100755 index 0000000..6c74282 --- /dev/null +++ b/scripts/setup-gemini.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail + +# Install Gemini CLI globally +if command -v gemini &> /dev/null; then + echo "Gemini CLI is already installed." +else + echo "Installing Gemini CLI..." + npm install -g @google/gemini-cli +fi + +echo "βœ… Gemini CLI setup complete! Run 'gemini' to start." diff --git a/templates/scripts/setup-env.sh b/templates/scripts/setup-env.sh old mode 100644 new mode 100755 index 8a9179c..31465d6 --- a/templates/scripts/setup-env.sh +++ b/templates/scripts/setup-env.sh @@ -28,14 +28,8 @@ echo "You can get an API key from: https://aistudio.google.com/app/apikey" read -p "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY echo "" -echo "Optional: The GitHub Token is used by the GitHub CLI and automations inside the Devcontainer." -echo "You can get a Fine-grained PAT from: https://github.com/settings/tokens?type=beta" -echo "It needs 'Pull Requests: Read-only' and 'Contents: Read-only' access to relevant repositories." -read -p "Enter your GitHub Token (press Enter to skip): " GITHUB_TOKEN - -if [ -n "$GITHUB_TOKEN" ]; then - echo "To authenticate the GitHub CLI, run: echo \$GITHUB_TOKEN | gh auth login --with-token" -fi +echo "Optional: Authenticate with GitHub CLI for automations inside the Devcontainer." +echo "To authenticate, you can run: gh auth login" # Portable sed: works on both macOS (BSD sed) and Linux (GNU sed) portable_sed() { @@ -78,15 +72,7 @@ if [ -n "$GEMINI_API_KEY" ]; then update_env "GEMINI_API_KEY" "$GEMINI_API_KEY" fi -if [ -n "$GITHUB_TOKEN" ]; then - update_env "GITHUB_TOKEN" "$GITHUB_TOKEN" - # Authenticate GitHub CLI if we are in an environment where gh is available - if command -v gh &> /dev/null; then - echo "$GITHUB_TOKEN" | gh auth login --with-token - gh auth setup-git - echo "GitHub CLI authenticated and configured as Git credential helper." - fi -fi + # Update the LICENSE file if it exists if [ -f "LICENSE" ] && [ -n "$GIT_NAME" ]; then diff --git a/templates/scripts/setup-gemini.sh b/templates/scripts/setup-gemini.sh old mode 100644 new mode 100755 From 848a3f45ff343c338733d674e6ec4c5a3844da11 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:12:21 +0000 Subject: [PATCH 06/18] feat(scripts): add troubleshooting diagnostic script --- scripts/troubleshooting.sh | 84 ++++++++++++++++++++++++++++ templates/scripts/troubleshooting.sh | 84 ++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100755 scripts/troubleshooting.sh create mode 100755 templates/scripts/troubleshooting.sh diff --git a/scripts/troubleshooting.sh b/scripts/troubleshooting.sh new file mode 100755 index 0000000..3c96f03 --- /dev/null +++ b/scripts/troubleshooting.sh @@ -0,0 +1,84 @@ +#!/bin/bash +set -u + +echo "πŸ” Starting Devcontainer Troubleshooting..." +echo "----------------------------------------" + +# Change to the repository root relative to the script's location +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +ISSUE_FOUND=0 + +# 1. Check for .env file +echo "Checking for .env file..." +if [ ! -f .env ]; then + echo "❌ Error: .env file is missing." + if [ -f .env.example ]; then + echo " -> .env.example found. Creating .env from template..." + cp .env.example .env + echo " βœ… .env created. Please run './scripts/setup-env.sh' to populate it." + else + echo " ❌ Error: .env.example is also missing. Cannot create .env block automatically." + ISSUE_FOUND=1 + fi +else + # Basic check to see if .env has been filled out (checking for placeholder values or empty critical values) + if grep -q "YOUR_GIT_NAME_HERE" .env || grep -q "YOUR_GIT_EMAIL_HERE" .env; then + echo "⚠️ Warning: .env file contains placeholder values." + echo " -> Please run './scripts/setup-env.sh' to configure your environment variables." + ISSUE_FOUND=1 + else + echo "βœ… .env file found and appears to be configured." + fi +fi +echo "----------------------------------------" + +# 2. Check script permissions +echo "Checking script permissions..." +PERM_ISSUE=0 +for script in scripts/*.sh templates/scripts/*.sh; do + if [ -f "$script" ]; then + if [ ! -x "$script" ]; then + echo "❌ Error: $script is missing execute permissions." + PERM_ISSUE=1 + fi + fi +done + +if [ $PERM_ISSUE -eq 1 ]; then + echo " -> Attempting to fix permissions..." + chmod +x scripts/*.sh templates/scripts/*.sh 2>/dev/null || true + echo " βœ… Added execute permissions to scripts." +else + echo "βœ… All scripts have correct execute permissions." +fi +echo "----------------------------------------" + +# 3. Check for specific dependencies (e.g., Make, Git) +echo "Checking dependencies..." +if ! command -v make &> /dev/null; then + echo "❌ Error: 'make' is not installed." + echo " -> Please ensure your Devcontainer has the necessary build tools." + ISSUE_FOUND=1 +else + echo "βœ… 'make' is installed." +fi + +if ! command -v git &> /dev/null; then + echo "❌ Error: 'git' is not installed." + echo " -> Git is required for this Devcontainer." + ISSUE_FOUND=1 +else + echo "βœ… 'git' is installed." +fi +echo "----------------------------------------" + +# Final summary +if [ $ISSUE_FOUND -eq 1 ]; then + echo "⚠️ Troubleshooting complete, but some issues require your attention." + echo " Please review the warnings and errors above." + exit 1 +else + echo "πŸš€ Troubleshooting complete. Everything looks good!" + exit 0 +fi diff --git a/templates/scripts/troubleshooting.sh b/templates/scripts/troubleshooting.sh new file mode 100755 index 0000000..3c96f03 --- /dev/null +++ b/templates/scripts/troubleshooting.sh @@ -0,0 +1,84 @@ +#!/bin/bash +set -u + +echo "πŸ” Starting Devcontainer Troubleshooting..." +echo "----------------------------------------" + +# Change to the repository root relative to the script's location +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +ISSUE_FOUND=0 + +# 1. Check for .env file +echo "Checking for .env file..." +if [ ! -f .env ]; then + echo "❌ Error: .env file is missing." + if [ -f .env.example ]; then + echo " -> .env.example found. Creating .env from template..." + cp .env.example .env + echo " βœ… .env created. Please run './scripts/setup-env.sh' to populate it." + else + echo " ❌ Error: .env.example is also missing. Cannot create .env block automatically." + ISSUE_FOUND=1 + fi +else + # Basic check to see if .env has been filled out (checking for placeholder values or empty critical values) + if grep -q "YOUR_GIT_NAME_HERE" .env || grep -q "YOUR_GIT_EMAIL_HERE" .env; then + echo "⚠️ Warning: .env file contains placeholder values." + echo " -> Please run './scripts/setup-env.sh' to configure your environment variables." + ISSUE_FOUND=1 + else + echo "βœ… .env file found and appears to be configured." + fi +fi +echo "----------------------------------------" + +# 2. Check script permissions +echo "Checking script permissions..." +PERM_ISSUE=0 +for script in scripts/*.sh templates/scripts/*.sh; do + if [ -f "$script" ]; then + if [ ! -x "$script" ]; then + echo "❌ Error: $script is missing execute permissions." + PERM_ISSUE=1 + fi + fi +done + +if [ $PERM_ISSUE -eq 1 ]; then + echo " -> Attempting to fix permissions..." + chmod +x scripts/*.sh templates/scripts/*.sh 2>/dev/null || true + echo " βœ… Added execute permissions to scripts." +else + echo "βœ… All scripts have correct execute permissions." +fi +echo "----------------------------------------" + +# 3. Check for specific dependencies (e.g., Make, Git) +echo "Checking dependencies..." +if ! command -v make &> /dev/null; then + echo "❌ Error: 'make' is not installed." + echo " -> Please ensure your Devcontainer has the necessary build tools." + ISSUE_FOUND=1 +else + echo "βœ… 'make' is installed." +fi + +if ! command -v git &> /dev/null; then + echo "❌ Error: 'git' is not installed." + echo " -> Git is required for this Devcontainer." + ISSUE_FOUND=1 +else + echo "βœ… 'git' is installed." +fi +echo "----------------------------------------" + +# Final summary +if [ $ISSUE_FOUND -eq 1 ]; then + echo "⚠️ Troubleshooting complete, but some issues require your attention." + echo " Please review the warnings and errors above." + exit 1 +else + echo "πŸš€ Troubleshooting complete. Everything looks good!" + exit 0 +fi From 3cd67b89af98bc489b5d32091a3dc64a1de5f704 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:12:30 +0000 Subject: [PATCH 07/18] chore(env): replace pat prompt with gh auth instructions and add recommended extensions --- .env.example | 14 ++++++++++++++ .vscode/extensions.json | 12 ++++++++++++ AGENTS.md | 6 ++++++ templates/.devcontainer/devcontainer.json | 5 ++++- templates/.env.example | 4 ---- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 .vscode/extensions.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1bd53a5 --- /dev/null +++ b/.env.example @@ -0,0 +1,14 @@ +# Project Environment Variables +# Copy to .env and fill in your details + +# Git Configuration (for signing commits within container) +GIT_NAME= +GIT_EMAIL= +SSH_PUBLIC_KEY= + +# Gemini CLI API Key (for AI tooling inside the Devcontainer) +# Get your key at: https://aistudio.google.com/app/apikey +GEMINI_API_KEY= + + +# Add project specific secrets below diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..067d376 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "bierner.markdown-mermaid", + "mechatroner.rainbow-csv", + "ms-vscode.makefile-tools" + "ms-azuretools.vscode-containers", + "ms-azuretools.vscode-docker", + "github.vscode-github-actions", + "github.vscode-pull-request-github" + ] +} \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index cb59757..3d0d7d5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,12 @@ The repository is divided into two distinct parts: 1. **The Generator (`install.sh`)**: The script users curl and pipe to bash. It acts as the mechanism for fetching the repository's tarball and extracting the inner `/templates` directory safely onto the user's host machine. 2. **The Payload (`/templates/`)**: This directory contains the exact file structure, dotfiles, and scripts that will become the root directory of the _new downstream project_. +### Devcontainer Boundaries + +It is critical to distinguish between the two development environments in this repository: +- **Root Devcontainer (`/.devcontainer`)**: This environment is used *only* for developing the `bootstrap` repository itself (e.g., testing `install.sh`, committing updates to the payload). +- **Template Devcontainer (`/templates/.devcontainer`)**: This is the payload that gets extracted to user machines. Editing files here modifies the *future* environment of generated projects. **Changes to the root devcontainer are not inherited by downstream templates automatically.** + ### Modifying the Payload (`/templates/`) - Any file added or modified within `templates/` will automatically be downloaded by future users. There is no need to update `install.sh` when simply adding a new file to the template payload. diff --git a/templates/.devcontainer/devcontainer.json b/templates/.devcontainer/devcontainer.json index 7e6f448..1c6f7d4 100644 --- a/templates/.devcontainer/devcontainer.json +++ b/templates/.devcontainer/devcontainer.json @@ -18,10 +18,13 @@ "vscode": { "extensions": [ "esbenp.prettier-vscode", - "GitHub.github-vscode-theme", "bierner.markdown-mermaid", "mechatroner.rainbow-csv", "ms-vscode.makefile-tools" + "ms-azuretools.vscode-containers", + "ms-azuretools.vscode-docker", + "github.vscode-github-actions", + "github.vscode-pull-request-github" ], "settings": { "workbench.startupEditor": "none" diff --git a/templates/.env.example b/templates/.env.example index 42be933..1bd53a5 100644 --- a/templates/.env.example +++ b/templates/.env.example @@ -10,9 +10,5 @@ SSH_PUBLIC_KEY= # Get your key at: https://aistudio.google.com/app/apikey GEMINI_API_KEY= -# GitHub Token (for GitHub CLI and AI agents interacting with PRs/Issues) -# Generate a Fine-grained PAT: https://github.com/settings/tokens?type=beta -# Required scopes: 'Pull Requests: Read-only' and 'Contents: Read-only' -GITHUB_TOKEN= # Add project specific secrets below From dc5e1a586f32b48e8d8c8bafa5a36c6a4d92b406 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:13:26 +0000 Subject: [PATCH 08/18] chore: track root dev environment and git hooks --- .devcontainer/Dockerfile | 12 +++++++++++ .devcontainer/boot-check.sh | 36 ++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 37 +++++++++++++++++++++++++++++++++ .githooks/commit-msg | 36 ++++++++++++++++++++++++++++++++ .githooks/pre-commit | 12 +++++++++++ Makefile | 29 ++++++++++++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/boot-check.sh create mode 100644 .devcontainer/devcontainer.json create mode 100755 .githooks/commit-msg create mode 100755 .githooks/pre-commit create mode 100644 Makefile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..aaaaa29 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,12 @@ +FROM mcr.microsoft.com/devcontainers/base:bookworm + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + +# [Optional] Uncomment if you want to install an additional version of node using nvm +# ARG EXTRA_NODE_VERSION=10 +# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" + +# [Optional] Uncomment if you want to install more global node modules +# RUN su node -c "npm install -g " diff --git a/.devcontainer/boot-check.sh b/.devcontainer/boot-check.sh new file mode 100644 index 0000000..0ec767c --- /dev/null +++ b/.devcontainer/boot-check.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -euo pipefail + +if [ ! -f .env ]; then + echo "⚠️ WARNING: .env file not found." + echo "Please run './scripts/setup-env.sh' in the terminal to initialize your environment variables." +else + echo "βœ… .env found. Exporting variables safely..." + while IFS='=' read -r key value; do + # Skip empty lines and comments + if [[ -n "$key" && ! "$key" =~ ^# ]]; then + # Trim leading/trailing whitespace from key and value + key=$(echo "$key" | xargs) + value=$(echo "$value" | xargs) + export "$key=$value" + fi + done < ".env" + + # Configure Git if found in .env + if [ -n "${GIT_NAME:-}" ]; then + git config --global user.name "$GIT_NAME" + fi + if [ -n "${GIT_EMAIL:-}" ]; then + git config --global user.email "$GIT_EMAIL" + fi + if [ -n "${SSH_PUBLIC_KEY:-}" ]; then + git config --global gpg.format ssh + git config --global user.signingkey "key::${SSH_PUBLIC_KEY}" + git config --global commit.gpgsign true + fi + + # Configure GitHub CLI as credential helper if token is present + if [ -n "${GITHUB_TOKEN:-}" ] && command -v gh &> /dev/null; then + gh auth setup-git + fi +fi \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..bd60c9b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,37 @@ +{ + "name": "bootstrap", + "build": { + "dockerfile": "Dockerfile", + "args": { "VARIANT": "latest" } + }, + "forwardPorts": [3000, 9222], + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "configureZshAsDefaultShell": true + }, + "ghcr.io/devcontainers/features/git:1": {}, + "ghcr.io/devcontainers/features/node:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {} + }, + "postCreateCommand": "bash ./scripts/setup-gemini.sh", + "customizations": { + "vscode": { + "extensions": [ + "esbenp.prettier-vscode", + "GitHub.github-vscode-theme", + "bierner.markdown-mermaid", + "mechatroner.rainbow-csv", + "ms-vscode.makefile-tools" + ], + "settings": { + "workbench.startupEditor": "none" + } + } + }, + "postAttachCommand": "code README.md AGENTS.md", + "containerEnv": { + "GEMINI_API_KEY": "${localEnv:GEMINI_API_KEY}", + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" + }, + "postStartCommand": "/bin/bash ./scripts/start-container.sh" +} \ No newline at end of file diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 0000000..f3cd3aa --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,36 @@ +#!/bin/bash +# Commit message hook: enforces Conventional Commits format. +# Installed automatically by `make setup`. +# +# Valid prefixes: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert +# Format: [optional scope]: +# Examples: +# feat: add user authentication +# fix(api): handle null response from endpoint +# docs: update README with setup instructions + +commit_msg_file="$1" +commit_msg=$(cat "$commit_msg_file") + +# Allow merge commits and fixup/squash commits +if echo "$commit_msg" | grep -qE "^(Merge|fixup!|squash!)"; then + exit 0 +fi + +# Validate conventional commit format +pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .{1,}" + +if ! echo "$commit_msg" | head -1 | grep -qE "$pattern"; then + echo "❌ Commit message does not follow Conventional Commits format." + echo "" + echo "Expected: [optional scope]: " + echo "Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert" + echo "" + echo "Examples:" + echo " feat: add user authentication" + echo " fix(api): handle null response" + echo " docs: update README with setup instructions" + echo "" + echo "Your message: $commit_msg" + exit 1 +fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..dd8ad56 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,12 @@ +#!/bin/bash +# Pre-commit hook: runs lint checks before allowing a commit. +# Installed automatically by `make setup`. + +# Only lint staged files if make lint is available +if make lint 2>/dev/null; then + echo "βœ… Lint checks passed." +else + echo "⚠️ Lint check failed or not configured. Skipping pre-commit lint." + # Exit 0 so commits aren't blocked before the stack is configured + exit 0 +fi diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4f807d4 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +.PHONY: help setup dev test build lint clean + +# Default variables +APP_NAME := {{PROJECT_NAME}} + +help: ## Show available make targets + @echo "Available targets:" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' + +setup: ## Install dependencies and configure git hooks + @git config core.hooksPath .githooks + @chmod +x .githooks/* + @echo "βœ… Git hooks configured." + @echo "⚠️ Run your package manager's install command to finish setup." + +dev: ## Start the development server + @echo "Dev target not implemented yet β€” update after choosing your tech stack" + +test: ## Run the test suite + @echo "Test target not implemented yet β€” update after choosing your tech stack" + +build: ## Create a production build + @echo "Build target not implemented yet β€” update after choosing your tech stack" + +lint: ## Run code formatting & linting + @echo "Lint target not implemented yet β€” update after choosing your tech stack" + +clean: ## Remove build artifacts + @echo "Clean target not implemented yet β€” update after choosing your tech stack" From 546d32dd639f1d5bf6940c8cacd376a0f035c4fa Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:16:56 +0000 Subject: [PATCH 09/18] docs: add AI agent guidelines to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3d18dbf..d33cabb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ > **The "Gold Standard" repository template for launching new projects.** +> [!CAUTION] +> **AI AGENT INSTRUCTIONS:** If you have been directed to this repository to learn about "best practices", you MUST examine the contents of the `/templates` directory. The `/templates` directory contains the actual scaffolding and files that become a new downstream project. Do NOT examine the root-level files (such as `install.sh`, `Makefile`, etc.) to learn about project setup, as those files are strictly for managing the bootstrap repository itself. + This repository is designed to instantly bootstrap a fully configured project environment characterized by zero-host dependencies, secure-by-default workflows, and structural guardrails that enforce elite engineering practices. It is explicitly designed to be heavily supported by IDE-based AI Agents. --- From 7d5d7c6479ffe024a2d31a84b1094c91e516d13b Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:37:51 +0000 Subject: [PATCH 10/18] feat(ci): add E2E install verification workflow and fix install.sh tar extraction --- .github/workflows/e2e-install.yml | 52 +++++++++++++++++++++++++++++++ install.sh | 4 +-- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/e2e-install.yml diff --git a/.github/workflows/e2e-install.yml b/.github/workflows/e2e-install.yml new file mode 100644 index 0000000..81bbf4b --- /dev/null +++ b/.github/workflows/e2e-install.yml @@ -0,0 +1,52 @@ +name: E2E Install Verification + +on: + push: + branches: [ main, booting ] + pull_request: + branches: [ main ] + +jobs: + test-install: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run installer + run: | + mkdir test-project + cd test-project + # We point to the local install.sh but it will still try to download a tarball. + # To test the logic of the script using the CURRENT branch changes, + # we override REPO_TAR_URL to point to this repository's current commit. + export REPO_TAR_URL="https://github.com/${{ github.repository }}/tarball/${{ github.sha }}" + bash ../install.sh + env: + BOOTSTRAP_DEV: 1 + + - name: Verify files + run: | + cd test-project + echo "Verifying critical files exist..." + test -d .devcontainer + test -f .gitignore + test -f Makefile + test -f README.md + test -f AGENTS.md + test -d scripts + test -f scripts/setup-env.sh + test -f scripts/troubleshooting.sh + + echo "Verifying execute permissions..." + test -x scripts/setup-env.sh + test -x scripts/start-container.sh + test -x scripts/troubleshooting.sh + + echo "Verifying no root-only files leaked..." + if [ -f "install.sh" ]; then + echo "Error: install.sh should not be in the project root." + exit 1 + fi + + echo "βœ… E2E Verification Passed!" diff --git a/install.sh b/install.sh index 582a55c..7a02462 100644 --- a/install.sh +++ b/install.sh @@ -3,7 +3,7 @@ set -euo pipefail # Usage: curl -sSL https://raw.githubusercontent.com/penguinranch/bootstrap/main/install.sh | bash -REPO_TAR_URL="https://github.com/penguinranch/bootstrap/tarball/main" +REPO_TAR_URL="${REPO_TAR_URL:-https://github.com/penguinranch/bootstrap/tarball/main}" echo "πŸš€ Initializing Gold Standard Environment..." @@ -16,7 +16,7 @@ fi # Download and extract the templates directory echo "Downloading the latest templates..." -if ! curl -sL "$REPO_TAR_URL" | tar -xz --strip-components=2 "*/templates/"; then +if ! curl -sL "$REPO_TAR_URL" | tar -xz --wildcards --strip-components=2 "*/templates/"; then echo "❌ Failed to download or extract templates. Check your network connection." exit 1 fi From 432df5995a1cae70193c99af1fcd078d3f6a0d22 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:38:26 +0000 Subject: [PATCH 11/18] chore: ignore .tmp-test directory --- .gitignore | 3 +++ templates/.gitignore | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index b99ae2b..2cb575b 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ obj/ !.vscode/launch.json !.vscode/extensions.json *.swp + +# Testing +.tmp-test/ diff --git a/templates/.gitignore b/templates/.gitignore index b99ae2b..2cb575b 100644 --- a/templates/.gitignore +++ b/templates/.gitignore @@ -58,3 +58,6 @@ obj/ !.vscode/launch.json !.vscode/extensions.json *.swp + +# Testing +.tmp-test/ From 5d8213ddb478862119d567aaee6c5bce87cf6a4a Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:39:51 +0000 Subject: [PATCH 12/18] feat(lint): add shellcheck for shell script verification --- .devcontainer/Dockerfile | 4 ++-- .github/workflows/shellcheck.yml | 18 ++++++++++++++++++ Makefile | 4 +++- scripts/setup-env.sh | 8 ++++---- scripts/troubleshooting.sh | 2 +- templates/scripts/setup-env.sh | 8 ++++---- templates/scripts/troubleshooting.sh | 2 +- 7 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/shellcheck.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index aaaaa29..1fd5d2a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,8 +1,8 @@ FROM mcr.microsoft.com/devcontainers/base:bookworm # [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends shellcheck # [Optional] Uncomment if you want to install an additional version of node using nvm # ARG EXTRA_NODE_VERSION=10 diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 0000000..8ea2752 --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,18 @@ +name: Shell Script Linting + +on: + push: + branches: [ main, booting ] + pull_request: + branches: [ main ] + +jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run shellcheck + run: | + shellcheck install.sh .devcontainer/*.sh scripts/*.sh templates/scripts/*.sh diff --git a/Makefile b/Makefile index 4f807d4..ffeaaef 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,9 @@ build: ## Create a production build @echo "Build target not implemented yet β€” update after choosing your tech stack" lint: ## Run code formatting & linting - @echo "Lint target not implemented yet β€” update after choosing your tech stack" + @echo "πŸ” Linting shell scripts..." + @shellcheck install.sh .devcontainer/*.sh scripts/*.sh templates/scripts/*.sh || (echo "❌ Shellcheck failed. Fix errors above." && exit 1) + @echo "βœ… Shell scripts linted." clean: ## Remove build artifacts @echo "Clean target not implemented yet β€” update after choosing your tech stack" diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh index 31465d6..15a4137 100755 --- a/scripts/setup-env.sh +++ b/scripts/setup-env.sh @@ -13,19 +13,19 @@ if [ ! -f .env ]; then fi echo "Setting up environment variables..." -read -p "Enter your Git Name: " GIT_NAME -read -p "Enter your Git Email: " GIT_EMAIL +read -rp "Enter your Git Name: " GIT_NAME +read -rp "Enter your Git Email: " GIT_EMAIL echo "" echo "Optional: SSH Public Key for commit signing." echo "If you use 1Password as your SSH agent, you can copy the public key string directly." echo "(e.g., ssh-ed25519 AAAAC3Nz...)" -read -p "Enter your SSH Public Key (press Enter to skip): " SSH_PUBLIC_KEY +read -rp "Enter your SSH Public Key (press Enter to skip): " SSH_PUBLIC_KEY echo "" echo "Optional: The Gemini API Key is used by the Gemini CLI inside this Devcontainer." echo "You can get an API key from: https://aistudio.google.com/app/apikey" -read -p "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY +read -rp "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY echo "" echo "Optional: Authenticate with GitHub CLI for automations inside the Devcontainer." diff --git a/scripts/troubleshooting.sh b/scripts/troubleshooting.sh index 3c96f03..3b89574 100755 --- a/scripts/troubleshooting.sh +++ b/scripts/troubleshooting.sh @@ -5,7 +5,7 @@ echo "πŸ” Starting Devcontainer Troubleshooting..." echo "----------------------------------------" # Change to the repository root relative to the script's location -cd "$(dirname "${BASH_SOURCE[0]}")/.." +cd "$(dirname "${BASH_SOURCE[0]}")/.." || exit ISSUE_FOUND=0 diff --git a/templates/scripts/setup-env.sh b/templates/scripts/setup-env.sh index 31465d6..15a4137 100755 --- a/templates/scripts/setup-env.sh +++ b/templates/scripts/setup-env.sh @@ -13,19 +13,19 @@ if [ ! -f .env ]; then fi echo "Setting up environment variables..." -read -p "Enter your Git Name: " GIT_NAME -read -p "Enter your Git Email: " GIT_EMAIL +read -rp "Enter your Git Name: " GIT_NAME +read -rp "Enter your Git Email: " GIT_EMAIL echo "" echo "Optional: SSH Public Key for commit signing." echo "If you use 1Password as your SSH agent, you can copy the public key string directly." echo "(e.g., ssh-ed25519 AAAAC3Nz...)" -read -p "Enter your SSH Public Key (press Enter to skip): " SSH_PUBLIC_KEY +read -rp "Enter your SSH Public Key (press Enter to skip): " SSH_PUBLIC_KEY echo "" echo "Optional: The Gemini API Key is used by the Gemini CLI inside this Devcontainer." echo "You can get an API key from: https://aistudio.google.com/app/apikey" -read -p "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY +read -rp "Enter your Gemini API Key (press Enter to skip): " GEMINI_API_KEY echo "" echo "Optional: Authenticate with GitHub CLI for automations inside the Devcontainer." diff --git a/templates/scripts/troubleshooting.sh b/templates/scripts/troubleshooting.sh index 3c96f03..3b89574 100755 --- a/templates/scripts/troubleshooting.sh +++ b/templates/scripts/troubleshooting.sh @@ -5,7 +5,7 @@ echo "πŸ” Starting Devcontainer Troubleshooting..." echo "----------------------------------------" # Change to the repository root relative to the script's location -cd "$(dirname "${BASH_SOURCE[0]}")/.." +cd "$(dirname "${BASH_SOURCE[0]}")/.." || exit ISSUE_FOUND=0 From d3c22ee206b60a557f09f33479da198ad36aab30 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:42:35 +0000 Subject: [PATCH 13/18] feat(format): add prettier for repo-wide formatting and fix json syntax --- .github/workflows/prettier.yml | 23 +++++++++++++++++++++++ .prettierrc | 7 +++++++ .vscode/extensions.json | 2 +- Makefile | 9 ++++++++- templates/.devcontainer/devcontainer.json | 4 ++-- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/prettier.yml create mode 100644 .prettierrc diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 0000000..cba7f49 --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,23 @@ +name: Formatting Check + +on: + push: + branches: [main, booting] + pull_request: + branches: [main] + +jobs: + prettier: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Run Prettier check + run: | + npx -y prettier --check "**/*.{md,json,yml}" diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ca8527e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2 +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 067d376..b1ae22b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,7 +3,7 @@ "esbenp.prettier-vscode", "bierner.markdown-mermaid", "mechatroner.rainbow-csv", - "ms-vscode.makefile-tools" + "ms-vscode.makefile-tools", "ms-azuretools.vscode-containers", "ms-azuretools.vscode-docker", "github.vscode-github-actions", diff --git a/Makefile b/Makefile index ffeaaef..c24257c 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,14 @@ build: ## Create a production build lint: ## Run code formatting & linting @echo "πŸ” Linting shell scripts..." @shellcheck install.sh .devcontainer/*.sh scripts/*.sh templates/scripts/*.sh || (echo "❌ Shellcheck failed. Fix errors above." && exit 1) - @echo "βœ… Shell scripts linted." + @echo "πŸ” Checking file formatting..." + @npx -y prettier --check "**/*.{md,json,yml}" || (echo "❌ Formatting check failed. Run 'make format' to fix." && exit 1) + @echo "βœ… All lint checks passed." + +format: ## Format all files + @echo "🧹 Formatting files..." + @npx -y prettier --write "**/*.{md,json,yml}" + @echo "βœ… Formatting complete." clean: ## Remove build artifacts @echo "Clean target not implemented yet β€” update after choosing your tech stack" diff --git a/templates/.devcontainer/devcontainer.json b/templates/.devcontainer/devcontainer.json index 1c6f7d4..8284394 100644 --- a/templates/.devcontainer/devcontainer.json +++ b/templates/.devcontainer/devcontainer.json @@ -20,7 +20,7 @@ "esbenp.prettier-vscode", "bierner.markdown-mermaid", "mechatroner.rainbow-csv", - "ms-vscode.makefile-tools" + "ms-vscode.makefile-tools", "ms-azuretools.vscode-containers", "ms-azuretools.vscode-docker", "github.vscode-github-actions", @@ -37,4 +37,4 @@ "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" }, "postStartCommand": "/bin/bash ./scripts/start-container.sh" -} \ No newline at end of file +} From db937dc9a9ae722e00bf9f8e42ef56fa839de1d4 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:43:19 +0000 Subject: [PATCH 14/18] chore: Apply Prettier formatting across repository --- .agents/workflows/test-install.md | 17 +++++----- .devcontainer/devcontainer.json | 2 +- .github/workflows/e2e-install.yml | 10 +++--- .github/workflows/shellcheck.yml | 4 +-- AGENTS.md | 5 +-- .../.github/ISSUE_TEMPLATE/bug_report.md | 2 +- .../.github/ISSUE_TEMPLATE/feature_request.md | 2 +- templates/.github/dependabot.yml | 12 +++---- templates/.github/workflows/ci.yml | 8 ++--- templates/.github/workflows/security.yml | 6 ++-- templates/AGENTS.md | 4 +-- templates/CONTRIBUTING.md | 25 +++++++------- templates/README.md | 34 +++++++++---------- templates/SECURITY.md | 6 ++-- 14 files changed, 70 insertions(+), 67 deletions(-) diff --git a/.agents/workflows/test-install.md b/.agents/workflows/test-install.md index 5a58c6d..bdfd4b5 100644 --- a/.agents/workflows/test-install.md +++ b/.agents/workflows/test-install.md @@ -9,30 +9,31 @@ Run this workflow to verify that `install.sh` correctly extracts the `templates/ ## Steps 1. Create and enter a temporary test directory: + ```bash mkdir -p /tmp/test-bootstrap && cd /tmp/test-bootstrap && git init ``` -// turbo -2. Run the install script from the bootstrap repo (using local copy, not remote): +// turbo 2. Run the install script from the bootstrap repo (using local copy, not remote): + ```bash BOOTSTRAP_DEV=1 bash /Users/lynnwallenstein/workspace/penguinranch/bootstrap/install.sh ``` -// turbo -3. Verify the expected file structure exists: +// turbo 3. Verify the expected file structure exists: + ```bash ls -la /tmp/test-bootstrap/.devcontainer/ /tmp/test-bootstrap/scripts/ /tmp/test-bootstrap/docs/decisions/ && echo "βœ… Structure intact" || echo "❌ Missing files" ``` -// turbo -4. Verify key files are present: +// turbo 4. Verify key files are present: + ```bash for f in AGENTS.md Makefile .editorconfig .env.example .gitattributes .gitignore .prettierrc CHANGELOG.md LICENSE CODE_OF_CONDUCT.md README.md; do [ -f "/tmp/test-bootstrap/$f" ] && echo "βœ… $f" || echo "❌ $f MISSING"; done ``` -// turbo -5. Clean up: +// turbo 5. Clean up: + ```bash rm -rf /tmp/test-bootstrap ``` diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bd60c9b..72d0e17 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -34,4 +34,4 @@ "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" }, "postStartCommand": "/bin/bash ./scripts/start-container.sh" -} \ No newline at end of file +} diff --git a/.github/workflows/e2e-install.yml b/.github/workflows/e2e-install.yml index 81bbf4b..38b482d 100644 --- a/.github/workflows/e2e-install.yml +++ b/.github/workflows/e2e-install.yml @@ -2,9 +2,9 @@ name: E2E Install Verification on: push: - branches: [ main, booting ] + branches: [main, booting] pull_request: - branches: [ main ] + branches: [main] jobs: test-install: @@ -37,16 +37,16 @@ jobs: test -d scripts test -f scripts/setup-env.sh test -f scripts/troubleshooting.sh - + echo "Verifying execute permissions..." test -x scripts/setup-env.sh test -x scripts/start-container.sh test -x scripts/troubleshooting.sh - + echo "Verifying no root-only files leaked..." if [ -f "install.sh" ]; then echo "Error: install.sh should not be in the project root." exit 1 fi - + echo "βœ… E2E Verification Passed!" diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 8ea2752..9d94caf 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -2,9 +2,9 @@ name: Shell Script Linting on: push: - branches: [ main, booting ] + branches: [main, booting] pull_request: - branches: [ main ] + branches: [main] jobs: shellcheck: diff --git a/AGENTS.md b/AGENTS.md index 3d0d7d5..a6fe64a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,8 +28,9 @@ The repository is divided into two distinct parts: ### Devcontainer Boundaries It is critical to distinguish between the two development environments in this repository: -- **Root Devcontainer (`/.devcontainer`)**: This environment is used *only* for developing the `bootstrap` repository itself (e.g., testing `install.sh`, committing updates to the payload). -- **Template Devcontainer (`/templates/.devcontainer`)**: This is the payload that gets extracted to user machines. Editing files here modifies the *future* environment of generated projects. **Changes to the root devcontainer are not inherited by downstream templates automatically.** + +- **Root Devcontainer (`/.devcontainer`)**: This environment is used _only_ for developing the `bootstrap` repository itself (e.g., testing `install.sh`, committing updates to the payload). +- **Template Devcontainer (`/templates/.devcontainer`)**: This is the payload that gets extracted to user machines. Editing files here modifies the _future_ environment of generated projects. **Changes to the root devcontainer are not inherited by downstream templates automatically.** ### Modifying the Payload (`/templates/`) diff --git a/templates/.github/ISSUE_TEMPLATE/bug_report.md b/templates/.github/ISSUE_TEMPLATE/bug_report.md index 984661e..8b581f5 100644 --- a/templates/.github/ISSUE_TEMPLATE/bug_report.md +++ b/templates/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: "\U0001F41B Bug Report" about: Report a bug or unexpected behavior -title: "[BUG] " +title: '[BUG] ' labels: bug assignees: '' --- diff --git a/templates/.github/ISSUE_TEMPLATE/feature_request.md b/templates/.github/ISSUE_TEMPLATE/feature_request.md index f0a94c4..6b5aa02 100644 --- a/templates/.github/ISSUE_TEMPLATE/feature_request.md +++ b/templates/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,7 +1,7 @@ --- name: "\U0001F680 Feature Request" about: Suggest a new feature or improvement -title: "[FEATURE] " +title: '[FEATURE] ' labels: enhancement assignees: '' --- diff --git a/templates/.github/dependabot.yml b/templates/.github/dependabot.yml index 782a0ad..5acbdac 100644 --- a/templates/.github/dependabot.yml +++ b/templates/.github/dependabot.yml @@ -1,10 +1,10 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: 'npm' + directory: '/' schedule: - interval: "weekly" - - package-ecosystem: "github-actions" - directory: "/" + interval: 'weekly' + - package-ecosystem: 'github-actions' + directory: '/' schedule: - interval: "weekly" + interval: 'weekly' diff --git a/templates/.github/workflows/ci.yml b/templates/.github/workflows/ci.yml index 7a76dd3..fd24ec7 100644 --- a/templates/.github/workflows/ci.yml +++ b/templates/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI Pipeline on: push: - branches: ["main"] + branches: ['main'] pull_request: - branches: ["main"] + branches: ['main'] # Cancel redundant runs on the same branch concurrency: @@ -24,8 +24,8 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: "20.x" - cache: "npm" + node-version: '20.x' + cache: 'npm' - name: Install dependencies run: npm ci --ignore-scripts diff --git a/templates/.github/workflows/security.yml b/templates/.github/workflows/security.yml index d1e383b..46b4bc9 100644 --- a/templates/.github/workflows/security.yml +++ b/templates/.github/workflows/security.yml @@ -2,9 +2,9 @@ name: Security Scan on: push: - branches: ["main"] + branches: ['main'] pull_request: - branches: ["main"] + branches: ['main'] # Cancel redundant runs on the same branch concurrency: @@ -37,6 +37,6 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v4 if: always() && hashFiles('trivy-results.sarif') != '' - continue-on-error: true # SARIF upload requires GitHub Advanced Security (paid for private repos) + continue-on-error: true # SARIF upload requires GitHub Advanced Security (paid for private repos) with: sarif_file: 'trivy-results.sarif' diff --git a/templates/AGENTS.md b/templates/AGENTS.md index 0b3358d..4532310 100644 --- a/templates/AGENTS.md +++ b/templates/AGENTS.md @@ -33,8 +33,8 @@ Before implementing any significant change: When adding or modifying automation scripts for the devcontainer, you must adhere to the following execution contexts defined in `devcontainer.json`: -1. **`postCreateCommand`**: Use for heavy, one-time global installations (e.g., global `npm` packages, binaries) that should be baked into the image after the `Dockerfile` completes. Examples: `setup-gemini.sh`. This runs *only once* when the container is built. -2. **`postStartCommand`**: Use for fast, idempotent environment checks and initializations that must be present every time the developer connects. Examples: `start-container.sh` (which configures git hooks and reads `.env`). This runs *every time* the container starts or wakes up. +1. **`postCreateCommand`**: Use for heavy, one-time global installations (e.g., global `npm` packages, binaries) that should be baked into the image after the `Dockerfile` completes. Examples: `setup-gemini.sh`. This runs _only once_ when the container is built. +2. **`postStartCommand`**: Use for fast, idempotent environment checks and initializations that must be present every time the developer connects. Examples: `start-container.sh` (which configures git hooks and reads `.env`). This runs _every time_ the container starts or wakes up. 3. **Manual Interactive Scripts**: Any script that requires user interaction (e.g., using `read -p`) must **never** be added to an automated lifecycle hook. If added to `postStartCommand`, the container boot process will hang indefinitely waiting for input on a detached TTY. Examples: `setup-env.sh`. Instead, ensure the idempotent `start-container.sh` script checks for the required state and warns the user to run the interactive script manually. ## πŸ— Coding Standards diff --git a/templates/CONTRIBUTING.md b/templates/CONTRIBUTING.md index 6977438..2e3c79e 100644 --- a/templates/CONTRIBUTING.md +++ b/templates/CONTRIBUTING.md @@ -13,6 +13,7 @@ Thank you for considering contributing to this project! This guide will help you ### 1. Create an Issue Before starting work, create or find a GitHub issue describing the change. Use the provided issue templates: + - **πŸ› Bug Report** for bugs - **πŸš€ Feature Request** for new features @@ -30,12 +31,12 @@ Use `docs/decisions/000-template.md` as a starting point. Use scoped branch naming: -| Prefix | Use Case | -| ------------ | --------------------------- | -| `feat/...` | New features | -| `fix/...` | Bug fixes | -| `task/...` | Chores, refactors, cleanup | -| `docs/...` | Documentation-only changes | +| Prefix | Use Case | +| ---------- | -------------------------- | +| `feat/...` | New features | +| `fix/...` | Bug fixes | +| `task/...` | Chores, refactors, cleanup | +| `docs/...` | Documentation-only changes | ### 4. Write Code @@ -64,12 +65,12 @@ The `commit-msg` hook enforces this automatically. ## Standards -| Tool | Purpose | -| ----------------- | -------------------------------- | -| **EditorConfig** | Consistent whitespace & encoding | -| **Prettier** | Code formatting | -| **Makefile** | Universal task runner | -| **Git hooks** | Automated quality gates | +| Tool | Purpose | +| ---------------- | -------------------------------- | +| **EditorConfig** | Consistent whitespace & encoding | +| **Prettier** | Code formatting | +| **Makefile** | Universal task runner | +| **Git hooks** | Automated quality gates | ## Need Help? diff --git a/templates/README.md b/templates/README.md index 24d1798..2333e2d 100644 --- a/templates/README.md +++ b/templates/README.md @@ -97,28 +97,28 @@ make setup Start developing! Use the universal `Makefile` targets: -| Command | Purpose | -| ------------ | ----------------------------- | -| `make help` | Show all available targets | -| `make setup` | Install deps & configure hooks| -| `make dev` | Start the development server | -| `make test` | Run the test suite | -| `make build` | Create a production build | -| `make lint` | Run code formatting & linting | -| `make clean` | Remove build artifacts | +| Command | Purpose | +| ------------ | ------------------------------ | +| `make help` | Show all available targets | +| `make setup` | Install deps & configure hooks | +| `make dev` | Start the development server | +| `make test` | Run the test suite | +| `make build` | Create a production build | +| `make lint` | Run code formatting & linting | +| `make clean` | Remove build artifacts | --- ## πŸ“š Key Files to Know -| File | What It Does | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`AGENTS.md`** | Instructions for AI assistants β€” coding standards, workflow rules, and architectural philosophy. | -| **`Makefile`** | Maps your stack-specific commands to universal targets. Update this once you choose your tech stack. | -| **`.env.example`** | Lists all required environment variables. Copy to `.env` and fill in your values. | -| **`CODEOWNERS`** | Defines who must approve PRs for critical paths (CI, ADRs, Devcontainer). | -| **`CONTRIBUTING.md`** | How to contribute: branch naming, conventional commits, ADR workflow, and PR process. | -| **`SECURITY.md`** | How to report vulnerabilities. Replace `[SECURITY_EMAIL]` with your contact. | +| File | What It Does | +| --------------------- | ---------------------------------------------------------------------------------------------------- | +| **`AGENTS.md`** | Instructions for AI assistants β€” coding standards, workflow rules, and architectural philosophy. | +| **`Makefile`** | Maps your stack-specific commands to universal targets. Update this once you choose your tech stack. | +| **`.env.example`** | Lists all required environment variables. Copy to `.env` and fill in your values. | +| **`CODEOWNERS`** | Defines who must approve PRs for critical paths (CI, ADRs, Devcontainer). | +| **`CONTRIBUTING.md`** | How to contribute: branch naming, conventional commits, ADR workflow, and PR process. | +| **`SECURITY.md`** | How to report vulnerabilities. Replace `[SECURITY_EMAIL]` with your contact. | --- diff --git a/templates/SECURITY.md b/templates/SECURITY.md index b1c4914..5d1acf1 100644 --- a/templates/SECURITY.md +++ b/templates/SECURITY.md @@ -23,9 +23,9 @@ Include as much of the following information as possible: ## Supported Versions -| Version | Supported | -| ------- | ------------------ | -| Latest | βœ… Yes | +| Version | Supported | +| ------- | --------- | +| Latest | βœ… Yes | ## Security Measures in This Project From d5c7fa6634091f3703f0bf7a18d9f95f454ce992 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:44:04 +0000 Subject: [PATCH 15/18] feat(ci): add dependabot configuration for root and templates --- .github/dependabot.yml | 13 +++++++++++++ templates/.github/dependabot.yml | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e6b08db --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + # Maintain GitHub Actions used in this repo + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'weekly' + + # Maintain Docker base images in the root devcontainer + - package-ecosystem: 'docker' + directory: '/.devcontainer' + schedule: + interval: 'weekly' diff --git a/templates/.github/dependabot.yml b/templates/.github/dependabot.yml index 5acbdac..0ba72df 100644 --- a/templates/.github/dependabot.yml +++ b/templates/.github/dependabot.yml @@ -8,3 +8,7 @@ updates: directory: '/' schedule: interval: 'weekly' + - package-ecosystem: 'docker' + directory: '/.devcontainer' + schedule: + interval: 'weekly' From 51a568eea3b5a753d01b0e351ea2c637ec2738a0 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:45:07 +0000 Subject: [PATCH 16/18] feat(ci): add Devcontainer build validation workflow --- .github/workflows/devcontainer-test.yml | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/devcontainer-test.yml diff --git a/.github/workflows/devcontainer-test.yml b/.github/workflows/devcontainer-test.yml new file mode 100644 index 0000000..30f824a --- /dev/null +++ b/.github/workflows/devcontainer-test.yml @@ -0,0 +1,32 @@ +name: Devcontainer Build Validation + +on: + push: + branches: [ main, booting ] + pull_request: + branches: [ main ] + +jobs: + build-root: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build root devcontainer + uses: devcontainers/ci@v0.3 + with: + subFolder: . + push: never + + build-template: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build template devcontainer + uses: devcontainers/ci@v0.3 + with: + subFolder: templates + push: never From ca97c4e5485c25b5b8a0eae8b59dc700c11bba0b Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:50:32 +0000 Subject: [PATCH 17/18] chore: Apply final polish and gold standard improvements from audit --- .devcontainer/boot-check.sh | 8 +++++--- .devcontainer/devcontainer.json | 6 +++++- .env.example | 1 - .github/workflows/devcontainer-test.yml | 4 ++-- AGENTS.md | 2 +- install.sh | 2 +- scripts/setup-env.sh | 2 -- templates/.env.example | 1 - templates/.github/CODEOWNERS | 3 ++- templates/AGENTS.md | 2 +- templates/CONTRIBUTING.md | 2 +- templates/Makefile | 3 +++ templates/README.md | 12 +++++++----- 13 files changed, 28 insertions(+), 20 deletions(-) diff --git a/.devcontainer/boot-check.sh b/.devcontainer/boot-check.sh index 0ec767c..dc74b67 100644 --- a/.devcontainer/boot-check.sh +++ b/.devcontainer/boot-check.sh @@ -9,9 +9,11 @@ else while IFS='=' read -r key value; do # Skip empty lines and comments if [[ -n "$key" && ! "$key" =~ ^# ]]; then - # Trim leading/trailing whitespace from key and value - key=$(echo "$key" | xargs) - value=$(echo "$value" | xargs) + # Trim leading/trailing whitespace + key="${key#"${key%%[![:space:]]*}"}" + key="${key%"${key##*[![:space:]]}"}" + value="${value#"${value%%[![:space:]]*}"}" + value="${value%"${value##*[![:space:]]}"}" export "$key=$value" fi done < ".env" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 72d0e17..7ea54a0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,11 @@ "GitHub.github-vscode-theme", "bierner.markdown-mermaid", "mechatroner.rainbow-csv", - "ms-vscode.makefile-tools" + "ms-vscode.makefile-tools", + "ms-azuretools.vscode-containers", + "ms-azuretools.vscode-docker", + "github.vscode-github-actions", + "github.vscode-pull-request-github" ], "settings": { "workbench.startupEditor": "none" diff --git a/.env.example b/.env.example index 1bd53a5..5e3e53d 100644 --- a/.env.example +++ b/.env.example @@ -10,5 +10,4 @@ SSH_PUBLIC_KEY= # Get your key at: https://aistudio.google.com/app/apikey GEMINI_API_KEY= - # Add project specific secrets below diff --git a/.github/workflows/devcontainer-test.yml b/.github/workflows/devcontainer-test.yml index 30f824a..82da4d3 100644 --- a/.github/workflows/devcontainer-test.yml +++ b/.github/workflows/devcontainer-test.yml @@ -2,9 +2,9 @@ name: Devcontainer Build Validation on: push: - branches: [ main, booting ] + branches: [main, booting] pull_request: - branches: [ main ] + branches: [main] jobs: build-root: diff --git a/AGENTS.md b/AGENTS.md index a6fe64a..c4a929e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,7 +41,7 @@ It is critical to distinguish between the two development environments in this r ### Modifying the Generator (`install.sh`) - Changes to `install.sh` should be extremely rare. It must remain lightweight. -- Ensure that the tarball extraction logic (`tar -xz --strip-components=2 "*/templates/"`) remains robust. It relies on GitHub's tarball structure. +- Ensure that the tarball extraction logic (utilizing `--wildcards` for the `/templates` directory) remains robust. It relies on GitHub's tarball structure. ## πŸ“ Contribution & Maintenance Rules diff --git a/install.sh b/install.sh index 7a02462..8aa6ff9 100644 --- a/install.sh +++ b/install.sh @@ -25,7 +25,7 @@ fi mkdir -p docs/decisions # Make scripts executable -chmod +x .devcontainer/boot-check.sh scripts/setup-env.sh scripts/setup-gemini.sh scripts/start-container.sh +chmod +x .devcontainer/boot-check.sh scripts/setup-env.sh scripts/setup-gemini.sh scripts/start-container.sh scripts/troubleshooting.sh chmod +x .githooks/* echo "βœ… Bootstrap complete. Open in VS Code or Antigravity to start the Devcontainer." \ No newline at end of file diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh index 15a4137..ccf8b6a 100755 --- a/scripts/setup-env.sh +++ b/scripts/setup-env.sh @@ -72,8 +72,6 @@ if [ -n "$GEMINI_API_KEY" ]; then update_env "GEMINI_API_KEY" "$GEMINI_API_KEY" fi - - # Update the LICENSE file if it exists if [ -f "LICENSE" ] && [ -n "$GIT_NAME" ]; then CURRENT_YEAR=$(date +"%Y") diff --git a/templates/.env.example b/templates/.env.example index 1bd53a5..5e3e53d 100644 --- a/templates/.env.example +++ b/templates/.env.example @@ -10,5 +10,4 @@ SSH_PUBLIC_KEY= # Get your key at: https://aistudio.google.com/app/apikey GEMINI_API_KEY= - # Add project specific secrets below diff --git a/templates/.github/CODEOWNERS b/templates/.github/CODEOWNERS index 50f0ca5..80674e8 100644 --- a/templates/.github/CODEOWNERS +++ b/templates/.github/CODEOWNERS @@ -1,4 +1,5 @@ -# Default owners for everything +# Default owners for everything. Note: team slugs like @core-maintainers +# are placeholders and must be updated to match teams in your GitHub organization. * @core-maintainers # Architecture decisions require Tech Lead review diff --git a/templates/AGENTS.md b/templates/AGENTS.md index 4532310..a1d33f4 100644 --- a/templates/AGENTS.md +++ b/templates/AGENTS.md @@ -55,7 +55,7 @@ When adding or modifying automation scripts for the devcontainer, you must adher ## πŸ€– Token Optimization & CLI Usage -- **GitHub CLI:** The `gh` command is available in this container. If a `GITHUB_TOKEN` is provided in `.env`, the host's CLI will be authenticated and `gh auth setup-git` will automatically configure it as your Git credential helper. This enables seamless HTTPS Git operations in the environment. See [.env.example](.env.example) for required `GITHUB_TOKEN` scopes. +- **GitHub CLI:** The `gh` command is available in this container. Use `gh auth login` to authenticate. This enables seamless GitHub operations and can configure Git as your credential helper. - **Offload Structured Edge-Tasks:** To preserve your context window (tokens) for complex logic, use the Gemini CLI (`@google/gemini-cli`) installed in this container for well-structured tasks. - **Usage:** Run `gemini` in the terminal to start an interactive session, or `gemini -p ""` for one-shot tasks. - **Examples:** Ask the CLI to review code, analyze architecture, or investigate issuesβ€”this keeps your IDE context window focused on the primary task. diff --git a/templates/CONTRIBUTING.md b/templates/CONTRIBUTING.md index 2e3c79e..ee952d6 100644 --- a/templates/CONTRIBUTING.md +++ b/templates/CONTRIBUTING.md @@ -68,7 +68,7 @@ The `commit-msg` hook enforces this automatically. | Tool | Purpose | | ---------------- | -------------------------------- | | **EditorConfig** | Consistent whitespace & encoding | -| **Prettier** | Code formatting | +| **Prettier** | Code formatting (`make format`) | | **Makefile** | Universal task runner | | **Git hooks** | Automated quality gates | diff --git a/templates/Makefile b/templates/Makefile index 4f807d4..50e673a 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -25,5 +25,8 @@ build: ## Create a production build lint: ## Run code formatting & linting @echo "Lint target not implemented yet β€” update after choosing your tech stack" +format: ## Format all files + @echo "Format target not implemented yet β€” update after choosing your tech stack" + clean: ## Remove build artifacts @echo "Clean target not implemented yet β€” update after choosing your tech stack" diff --git a/templates/README.md b/templates/README.md index 2333e2d..5f1a8e0 100644 --- a/templates/README.md +++ b/templates/README.md @@ -33,9 +33,10 @@ Here's what was installed and why: β”‚ └── commit-msg # Enforces Conventional Commits format β”‚ β”œβ”€β”€ scripts/ # βš™οΈ Setup & automation scripts -β”‚ β”œβ”€β”€ start-container.sh # [postStartCommand] Fast, idempotent environment checks (runs every boot) -β”‚ β”œβ”€β”€ setup-env.sh # [Manual] Interactive setup for Git credentials & API keys (prompts user) -β”‚ └── setup-gemini.sh # [postCreateCommand] Heavy, one-time global installations (runs once on build) +β”‚ β”œβ”€β”€ start-container.sh # [postStartCommand] Fast, idempotent checks +β”‚ β”œβ”€β”€ setup-env.sh # [Manual] Interactive setup for credentials +β”‚ β”œβ”€β”€ troubleshooting.sh # [Manual] Diagnose common environment issues +β”‚ └── setup-gemini.sh # [postCreateCommand] Global tool installations β”‚ β”œβ”€β”€ docs/ β”‚ └── decisions/ # πŸ“ Architecture Decision Records (ADRs) @@ -69,7 +70,8 @@ Before opening the Devcontainer, define your tech stack. The language and framew > _1. Fill out the `001-initial-tech-stack.md` ADR._ > _2. Update the `.devcontainer/` configuration (Dockerfile and devcontainer.json) for our chosen stack, and replace the `{{PROJECT_NAME}}` placeholder in `devcontainer.json` with the project name._ > _3. Configure the universal `Makefile` and setup `dependabot.yml`._ -> _4. Rewrite `README.md` to describe this new project and how to run it."_ +> _4. Update `SECURITY.md` with your contact details._ +> _5. Rewrite `README.md` to describe this new project and how to run it."_ ### 2. Open in a Devcontainer @@ -83,7 +85,7 @@ Once the container is ready, open a terminal and run: ./scripts/setup-env.sh ``` -This will configure your Git identity, SSH signing, and prompt for any required API keys (Gemini, GitHub). Providing a GitHub Token locally inside this environment will automatically authenticate the `gh` CLI and set it up as your Git credential helper for seamless HTTPS operations. +This will configure your Git identity and prompt for any required API keys (Gemini). For GitHub operations, run `gh auth login` inside the container for seamless HTTPS authentication. Then activate the git hooks and project setup: From b89da3d93fe9ee2dc27564e8c801ef1ad89ac643 Mon Sep 17 00:00:00 2001 From: Lynn Wallenstein Date: Sun, 8 Mar 2026 23:51:17 +0000 Subject: [PATCH 18/18] chore: add root PR template --- .github/PULL_REQUEST_TEMPLATE.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..431ded7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,27 @@ +## Description + +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. + +## Type of Change + +- [ ] πŸ› Bug fix (non-breaking change which fixes an issue) +- [ ] πŸš€ New feature (non-breaking change which adds functionality) +- [ ] 🧹 Chore (refactoring, formatting, dependencies) +- [ ] πŸ“– Documentation update +- [ ] πŸ— Infrastructure / Environment change + +## How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. + +- [ ] Local manual test +- [ ] CI Automated tests (E2E, Linting, Build) + +## Checklist + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] Any dependent changes have been merged and published in downstream modules