diff --git a/.github/workflows/checkshell.yml b/.github/workflows/checkshell.yml index 012ee8c..9dcab46 100644 --- a/.github/workflows/checkshell.yml +++ b/.github/workflows/checkshell.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - run: docker run --rm -v "$(pwd)":/sh -w /sh mvdan/shfmt:v3 -sr -i 2 -l -w -ci . + - run: docker run --rm -v "$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -l -w -ci . - run: git diff --color --exit-code shellcheck: @@ -16,3 +16,11 @@ jobs: steps: - uses: actions/checkout@v6 - run: shellcheck *.sh + + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: DavidAnson/markdownlint-cli2-action@v18 + with: + globs: '*.md' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5066e48..a878e91 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,22 @@ repos: - - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.10.0.1 + - repo: local hooks: - - id: shellcheck + - id: shellcheck-docker + name: shellcheck (Docker) + entry: bash -c 'docker run --rm -v "$(pwd)":/mnt koalaman/shellcheck:stable "$@"' bash + language: system types: [shell] files: \.(sh|bats)$ - - repo: https://github.com/scop/pre-commit-shfmt - rev: v3.9.0-1 - hooks: - - id: shfmt - args: [-sr, -i, '2', -w, -ci] + - id: shfmt-docker + name: shfmt (Docker) + entry: bash -c 'docker run --rm -v "$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -w -ci "$@"' bash + language: system types: [shell] files: \.(sh|bats)$ - - repo: https://github.com/DavidAnson/markdownlint-cli2 - rev: v0.15.0 - hooks: - - id: markdownlint-cli2 + - id: markdownlint-docker + name: markdownlint-cli2 (Docker) + entry: bash -c 'docker run --rm -v "$(pwd)":/work -w /work node:lts-alpine npx markdownlint-cli2 "$@"' bash + language: system types: [markdown] diff --git a/AGENTS.md b/AGENTS.md index 16fdda6..bbc2cd4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -90,6 +90,63 @@ Checks for new Node.js versions to build: - Quick start: `pre-commit install` then hooks run automatically on commit - **Branch Protection:** main branch requires passing checks and code owner review +## Docker-Based Development + +All development tools run in official Docker containers. This approach requires only Docker; no local installation of shellcheck, shfmt, or Node.js needed. + +### Getting Started + +```bash +# Run all linters +make lint + +# Auto-fix formatting issues +make format + +# See all available commands +make help +``` + +### Makefile Targets + +The `Makefile` provides convenient targets for code quality checks: + +- `make lint` - Run all linters (shellcheck, shfmt, markdownlint) +- `make format` - Auto-fix shell script formatting with shfmt +- `make shellcheck` - Run shellcheck +- `make shfmt` - Check shell script formatting +- `make shfmt-fix` - Auto-fix shell formatting +- `make markdown-lint` - Check markdown files +- `make help` - Display all available targets + +### Pre-commit Hooks with Docker + +Pre-commit hooks are configured to run tools inside Docker containers for consistency: + +```bash +pre-commit install # Install hooks +pre-commit run --all-files # Run manually +``` + +Hooks automatically execute on commit using official Docker images. See [SETUP.md](./SETUP.md) for complete setup instructions. + +### For AI Agents + +To run development checks in an agent environment with only Docker available: + +```bash +# Run all linters via Makefile +make lint +make format + +# Or run individual Docker commands +docker run --rm -v "$(pwd)":/mnt koalaman/shellcheck:stable *.sh +docker run --rm -v "$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -l -ci *.sh +docker run --rm -v "$(pwd)":/work -w /work node:lts-alpine npx markdownlint-cli2 "*.md" +``` + +This approach requires only Docker to be installed in the agent's environment. + ## Testing ### Unit Tests diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d2f90e9 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +.PHONY: help lint shellcheck shfmt shfmt-fix markdown-lint format + +export DOCKER_CLI_HINTS=false + +help: + @echo "Available targets:" + @echo " lint Run all linters (shellcheck, shfmt, markdownlint)" + @echo " shellcheck Run shellcheck" + @echo " shfmt Check shell script formatting" + @echo " shfmt-fix Auto-fix shell script formatting" + @echo " markdown-lint Check markdown files" + @echo " format Auto-format shell scripts (alias for shfmt-fix)" + +shellcheck: + docker run --rm -v "$$(pwd)":/mnt koalaman/shellcheck:stable *.sh + +shfmt: + docker run --rm -v "$$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -l -ci *.sh + +shfmt-fix: + docker run --rm -v "$$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -w -ci *.sh + +markdown-lint: + docker run --rm -v "$$(pwd)":/work -w /work node:lts-alpine sh -c "npx markdownlint-cli2 '*.md'" + +format: shfmt-fix + +lint: shellcheck shfmt markdown-lint diff --git a/SETUP.md b/SETUP.md index f8ff09d..a7c733b 100644 --- a/SETUP.md +++ b/SETUP.md @@ -1,296 +1,251 @@ -# Developer Setup Guide - Pre-commit Hooks +# Developer Setup Guide - Docker-Based Development -This guide explains how to set up the pre-commit hooks for this repository on macOS. - -## Overview - -Pre-commit hooks automatically validate your code before each commit, catching issues early and ensuring consistent code quality. This repository enforces: - -- **shellcheck** - Validates shell script syntax and best practices -- **shfmt** - Auto-formats shell scripts consistently -- **markdownlint-cli2** - Enforces markdown style guidelines - -These same checks also run in GitHub Actions (checkshell.yml workflow), so using pre-commit hooks locally saves time by catching issues before pushing. +This guide explains how to set up the development environment for this repository using Docker. All development tools (shellcheck, shfmt, markdownlint-cli2) run in official Docker containers, requiring only Docker to be installed. ## Prerequisites -Before installing pre-commit hooks, ensure you have: - -- **Python 3.14+** - Required for the pre-commit framework -- **Homebrew** - macOS package manager -- **Node.js 22+ and npm** - Required for markdownlint-cli2 +### Docker -## Installation Instructions +You need Docker installed on your system. Docker provides containerized versions of all development tools, eliminating the need to install them locally. -Follow these steps to set up pre-commit hooks on macOS: - -### Step 1: Install Homebrew (if needed) - -If you don't have Homebrew installed: +**macOS** (Intel or Apple Silicon): ```bash -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -``` - -### Step 2: Install Required Tools via Homebrew +# Using Homebrew +brew install --cask docker -Install all necessary tools in one command: - -```bash -brew install pre-commit shellcheck shfmt +# Or download from https://www.docker.com/products/docker-desktop ``` -This installs: - -- **pre-commit 4.5.1** - Framework for managing pre-commit hooks -- **shellcheck 0.11.0** - Shell script static analysis tool -- **shfmt 3.12.0** - Shell script formatter (formats with `-sr -i 2 -w -ci` flags) - -### Step 3: Install Node.js and npm (if needed) - -If you don't have Node.js and npm, install via Homebrew: +**Linux** (Ubuntu/Debian): ```bash -brew install node +sudo apt-get update +sudo apt-get install docker.io docker-compose +sudo usermod -aG docker $USER +newgrp docker ``` -Alternatively, use a Node.js version manager: - -```bash -# Using nvm -nvm install --lts +**Windows**: -# Using fnm (Fast Node Manager) -fnm install --lts -``` +Download and install [Docker Desktop for Windows](https://www.docker.com/products/docker-desktop) Verify installation: ```bash -node --version -npm --version +docker --version ``` -### Step 4: Install markdownlint-cli2 +## Quick Start -Install the markdown linter globally via npm: +All linting commands are available via the Makefile: ```bash -npm install -g markdownlint-cli2 -``` - -This installs **markdownlint-cli2 v0.20.0** - Markdown file linter. - -### Step 5: Enable Pre-commit Hooks - -Navigate to the repository and install the hooks: - -```bash -cd /path/to/docker-node-minimal -pre-commit install -``` +# Run all linters +make lint -You should see: - -```bash -pre-commit installed at .git/hooks/pre-commit -``` - -### Step 6: Verify Installation - -Test that all hooks work correctly: - -```bash -pre-commit run --all-files -``` +# Run individual linters +make shellcheck # Check shell scripts +make shfmt # Check shell formatting +make markdown-lint # Check markdown files -You should see output like: +# Auto-fix formatting issues +make format # Auto-fixes shell scripts via shfmt +make shfmt-fix # Explicit shfmt fix command -```bash -shellcheck...Passed -shfmt........Passed -markdownlint-cli2...Passed +# See all available commands +make help ``` -All three should pass without errors. - -## Usage +## Development Workflow -### Running Hooks Automatically +### Before Committing -Hooks run automatically when you commit: +Run all checks to ensure code quality: ```bash -git commit -m "Your commit message" +make lint ``` -If any hook fails, the commit is blocked. Fix the errors and commit again. +This runs: -### Running Hooks Manually +1. **shellcheck** - Validates shell script syntax and best practices +2. **shfmt** - Checks shell script formatting +3. **markdownlint-cli2** - Validates markdown files -Run all hooks on all files: +Fix any issues, then commit. -```bash -pre-commit run --all-files -``` +### Using Pre-commit Hooks (Optional) -Run a specific hook: +Pre-commit hooks automatically run checks before each commit. This requires the pre-commit framework: ```bash -pre-commit run shellcheck --all-files -pre-commit run shfmt --all-files -pre-commit run markdownlint-cli2 --all-files +pip install pre-commit ``` -Run hooks only on changed files (default behavior at commit time): +Install the hooks in your repository: ```bash -pre-commit run +pre-commit install ``` -### Updating Hook Versions +Now, when you commit, hooks automatically run checks via Docker containers. If any check fails, the commit is blocked. Fix the issues and try again. -Update hooks to their latest compatible versions: +Run hooks manually on all files: ```bash -pre-commit autoupdate +pre-commit run --all-files ``` -### Temporarily Skipping Hooks - -For emergency commits (not recommended), bypass hooks: +Or use the Makefile: ```bash -git commit --no-verify +make lint ``` -## Hook Configuration +## How It Works -Hooks are defined in `.pre-commit-config.yaml`. Here's what each hook does: +### Official Docker Images -### shellcheck +The Makefile uses official Docker images from tool maintainers: -- **Purpose**: Validates shell script syntax and style -- **Files checked**: `*.sh` and `*.bats` -- **Configuration**: Default shellcheck rules +- **mvdan/shfmt:v3** - Shell script formatter +- **koalaman/shellcheck:stable** - Shell script linter +- **node:lts-alpine** - Node.js LTS (for markdownlint-cli2) -Detects: +Each tool runs in a temporary container with volume mounts for the project directory. -- Syntax errors -- Non-portable code -- Unsafe variable usage -- Unused variables +### Makefile -### shfmt +Convenient targets wrap Docker commands with proper volume mounts and working directories: -- **Purpose**: Auto-formats shell scripts -- **Files checked**: `*.sh` and `*.bats` -- **Flags**: `-sr -i 2 -w -ci` - - `-sr`: Simplify and space-align words - - `-i 2`: Indent with 2 spaces - - `-w`: Write changes back to files - - `-ci`: Indent switch cases - -Matches the formatting used in CI (GitHub Actions checkshell.yml). - -### markdownlint-cli2 +```bash +# This command: +make lint -- **Purpose**: Enforces markdown style guidelines -- **Files checked**: `*.md` -- **Configuration**: Respects `.markdownlint.yaml` in repository root +# Runs in Docker: +docker run --rm -v $(pwd):/work -w /work mvdan/shfmt:v3 -sr -i 2 -l -ci *.sh +docker run --rm -v /mnt koalaman/shellcheck:stable *.sh +docker run --rm -v $(pwd):/work -w /work node:lts-alpine npx markdownlint-cli2 "*.md" +``` -Current settings: +### Pre-commit Hooks with Docker -- MD013 (line length) is disabled to allow longer documentation lines +The `.pre-commit-config.yaml` configures hooks to run checks inside Docker containers. When you run `git commit`, pre-commit executes the tools via Docker for consistency. ## Troubleshooting -### "pre-commit: command not found" +### Docker Image Pull Fails -The `pre-commit` command is not in your PATH. +**Error**: `failed to pull image` -**Solution**: +**Solution**: Ensure Docker daemon is running and has internet access: -1. Verify installation: `brew list pre-commit` -2. If not installed: `brew install pre-commit` -3. If installed, add to PATH or reinstall: +```bash +docker run hello-world +``` + +On macOS, you may need to start Docker Desktop. On Linux, restart the daemon: ```bash -brew uninstall pre-commit -brew install pre-commit +sudo systemctl restart docker ``` -### "shellcheck: command not found" +### "make: command not found" -**Solution**: Install via Homebrew: +**Solution**: Install make: ```bash -brew install shellcheck +# macOS +brew install make + +# Linux (Ubuntu/Debian) +sudo apt-get install make + +# Linux (Fedora/RHEL) +sudo dnf install make ``` -### "shfmt: command not found" +### Permission Denied Errors + +**Error**: `permission denied while trying to connect to Docker daemon` -**Solution**: Install via Homebrew: +**Solution**: Add your user to the docker group (Linux): ```bash -brew install shfmt +sudo usermod -aG docker $USER +newgrp docker ``` -### "markdownlint-cli2: command not found" - -**Solution**: Install via npm: +Then log out and back in, or run: ```bash -npm install -g markdownlint-cli2 +docker ps ``` -Make sure Node.js and npm are installed first. +### Pre-commit Hooks Not Running -### Hooks not running after `pre-commit install` +**Error**: Hooks don't execute on commit -**Solution**: Verify installation and reinstall: +**Solution**: Verify installation: ```bash # Check if installed ls -la .git/hooks/pre-commit -# Reinstall +# Reinstall hooks pre-commit install -``` -### Permission denied errors - -**Solution**: Check file permissions: - -```bash -# Make hooks executable -chmod +x .git/hooks/pre-commit +# Run manually to debug +pre-commit run --all-files ``` -### Hook modifications not taking effect +### "markdownlint: command not found" in Hooks -**Solution**: Hooks are cached. Clear the cache: +Pre-commit may cache failures. Clear and retry: ```bash pre-commit clean pre-commit run --all-files ``` -## CI/CD Integration +## Why Docker? -These same checks run in the GitHub Actions CI pipeline (`.github/workflows/checkshell.yml`): +Using Docker for development tools provides: -- **shfmt** job: Validates formatting matches the configured rules -- **shellcheck** job: Validates shell scripts +- **Consistency**: Same tool versions across developers and CI/CD +- **Isolation**: Tools don't interfere with system or other projects +- **Zero Installation**: Only Docker required; no brew, npm, or system package managers +- **Official Images**: Uses well-maintained images from tool authors +- **Easy Maintenance**: Update by changing version tags, not build scripts -Using pre-commit hooks locally ensures your changes pass CI checks before pushing. +## For AI Agents -## More Information +AI agents can use the Makefile targets for automated checks: + +```bash +# Run all linters +make lint + +# Fix formatting issues +make format +``` + +Or call Docker commands directly: + +```bash +docker run --rm -v "$(pwd)":/work -w /work mvdan/shfmt:v3 -sr -i 2 -l -ci *.sh +docker run --rm -v "$(pwd)":/mnt koalaman/shellcheck:stable *.sh +docker run --rm -v "$(pwd)":/work -w /work node:lts-alpine npx markdownlint-cli2 "*.md" +``` -For more details on pre-commit framework, see the [official documentation](https://pre-commit.com/). +This approach requires only Docker to be installed in the agent's environment. -For specific tool documentation: +## For More Information +- [Docker Documentation](https://docs.docker.com/) +- [Makefile Documentation](https://www.gnu.org/software/make/manual/) +- [Pre-commit Framework](https://pre-commit.com/) - [shellcheck](https://www.shellcheck.net/) - [shfmt](https://github.com/mvdan/sh) - [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2)