From fa6fca5dbb94ed0f2ea56e128fa483e79571712b Mon Sep 17 00:00:00 2001 From: ImpactMojo Standards Bot Date: Mon, 16 Mar 2026 14:42:46 +0000 Subject: [PATCH] Chore: add git best-practice standards --- .editorconfig | 33 ++++++++++++++++++++++ .gitattributes | 51 +++++++++++++++++++++++++++++++++ .githooks/commit-msg | 42 +++++++++++++++++++++++++++ .githooks/pre-commit | 65 ++++++++++++++++++++++++++++++++++++++++++ .gitignore | 67 ++++++++++++++++++++++++++++++++++++++++++++ .gitmessage | 19 +++++++++++++ 6 files changed, 277 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100755 .githooks/commit-msg create mode 100755 .githooks/pre-commit create mode 100644 .gitignore create mode 100644 .gitmessage diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..501b6a3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,33 @@ +# EditorConfig — consistent formatting across editors and contributors +# https://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{html,css}] +indent_size = 2 + +[*.js] +indent_size = 2 + +[*.{json,yml,yaml}] +indent_size = 2 + +[*.py] +indent_size = 4 + +[*.{r,R}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..437ca70 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,51 @@ +# Auto-detect text files and normalise line endings to LF +* text=auto eol=lf + +# Explicitly declare text files +*.html text eol=lf +*.css text eol=lf +*.js text eol=lf +*.ts text eol=lf +*.json text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.toml text eol=lf +*.xml text eol=lf +*.svg text eol=lf +*.txt text eol=lf +*.sh text eol=lf +*.py text eol=lf +*.r text eol=lf +*.R text eol=lf + +# Windows-specific files keep CRLF +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +# Binary files — no diff, no merge, no line-ending conversion +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.webp binary +*.avif binary +*.woff binary +*.woff2 binary +*.ttf binary +*.eot binary +*.otf binary +*.pdf binary +*.zip binary +*.gz binary +*.tar binary +*.mp4 binary +*.webm binary +*.mp3 binary +*.ogg binary + +# Lock files — exact merge to prevent conflicts +package-lock.json merge=ours +yarn.lock merge=ours diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 0000000..c57d3f7 --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Commit message hook: enforce prefix convention from CONTRIBUTING.md +set -euo pipefail + +MSG_FILE="$1" +MSG=$(head -1 "$MSG_FILE") + +RED='\033[0;31m' +NC='\033[0m' + +# Skip merge commits and fixup/squash commits +if echo "$MSG" | grep -qE '^(Merge|Revert|fixup!|squash!)'; then + exit 0 +fi + +# Allowed prefixes (from CONTRIBUTING.md) +PREFIXES="Add|Fix|Update|Translate|Docs|Refactor|Test|CI|Chore|Merge" + +if ! echo "$MSG" | grep -qE "^(${PREFIXES}):"; then + echo -e "${RED}Invalid commit message format.${NC}" + echo "" + echo "Commit message must start with one of these prefixes:" + echo " Add: — New feature, course, or tool" + echo " Fix: — Bug fix or broken link" + echo " Update: — Improvement to existing content or code" + echo " Translate: — Translation work" + echo " Docs: — Documentation changes" + echo " Refactor: — Code restructuring (no behaviour change)" + echo " Test: — Adding or updating tests" + echo " CI: — CI/CD pipeline changes" + echo " Chore: — Maintenance (deps, configs, tooling)" + echo "" + echo "Example: Add: interactive Theory of Change lab" + echo "" + echo "Your message was: $MSG" + exit 1 +fi + +# Warn if subject line is too long +if [ ${#MSG} -gt 72 ]; then + echo -e "\033[0;33mWARNING:\033[0m Commit subject is ${#MSG} chars (recommended max: 72)" +fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..b7bb6a2 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# Pre-commit hook: catch common mistakes before they're committed +set -euo pipefail + +RED='\033[0;31m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +echo "Running pre-commit checks..." + +# 1. Block commits of sensitive files +SENSITIVE_PATTERNS=('.env' '.env.local' '.env.production' 'credentials.json' '*.pem' '*.key') +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM) + +for pattern in "${SENSITIVE_PATTERNS[@]}"; do + while IFS= read -r file; do + if [[ -n "$file" ]]; then + echo -e "${RED}BLOCKED:${NC} Refusing to commit sensitive file: $file" + echo "If this is intentional, use: git commit --no-verify" + exit 1 + fi + done < <(echo "$STAGED_FILES" | grep -E "^${pattern//\*/.*}$" 2>/dev/null || true) +done + +# 2. Check for debug/console statements in staged JS/TS/Python files +CODE_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|ts|py)$' || true) +if [ -n "$CODE_FILES" ]; then + ISSUES=0 + while IFS= read -r file; do + if git diff --cached "$file" | grep -E '^\+.*console\.(log|debug|warn)\(' | grep -v '// keep' > /dev/null 2>&1; then + echo -e "${YELLOW}WARNING:${NC} console.log/debug/warn found in $file" + ISSUES=$((ISSUES + 1)) + fi + if git diff --cached "$file" | grep -E '^\+.*(debugger|breakpoint\(\))' > /dev/null 2>&1; then + echo -e "${RED}BLOCKED:${NC} debugger statement found in $file" + exit 1 + fi + done <<< "$CODE_FILES" + if [ $ISSUES -gt 0 ]; then + echo -e "${YELLOW}Found $ISSUES file(s) with console statements. Consider removing them.${NC}" + fi +fi + +# 3. Check for merge conflict markers +if [ -n "$STAGED_FILES" ]; then + while IFS= read -r file; do + if [ -f "$file" ] && grep -rn '<<<<<<<\|=======\|>>>>>>>' "$file" > /dev/null 2>&1; then + echo -e "${RED}BLOCKED:${NC} Merge conflict markers found in $file" + exit 1 + fi + done <<< "$STAGED_FILES" +fi + +# 4. Warn on large files (> 500KB) +while IFS= read -r file; do + if [ -f "$file" ]; then + SIZE=$(wc -c < "$file") + if [ "$SIZE" -gt 512000 ]; then + SIZE_KB=$((SIZE / 1024)) + echo -e "${YELLOW}WARNING:${NC} Large file (${SIZE_KB}KB): $file" + fi + fi +done <<< "$STAGED_FILES" + +echo "Pre-commit checks passed." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74c48a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# Environment files (contain secrets) +.env +.env.* +!.env.example + +# Dependencies +node_modules/ +jspm_packages/ +bower_components/ + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ +.eggs/ +venv/ +.venv/ +env/ + +# Build output +build/ +dist/ +out/ +coverage/ +*.lcov +.nyc_output/ + +# OS files +.DS_Store +Thumbs.db +Desktop.ini + +# Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ +*.sublime-project +*.sublime-workspace + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +*.pid +*.pid.lock +*.seed + +# Package caches +.npm +.eslintcache +.stylelintcache +*.tsbuildinfo +*.tgz + +# Misc +.cache/ +.parcel-cache/ +.next/ +.nuxt/ +.serverless/ +.firebase/ diff --git a/.gitmessage b/.gitmessage new file mode 100644 index 0000000..3ff9114 --- /dev/null +++ b/.gitmessage @@ -0,0 +1,19 @@ +# : +# +# Prefixes: +# Add: — New feature, course, or tool +# Fix: — Bug fix or broken link +# Update: — Improvement to existing content or code +# Translate: — Translation work +# Docs: — Documentation changes +# Refactor: — Code restructuring (no behaviour change) +# Test: — Adding or updating tests +# CI: — CI/CD pipeline changes +# Chore: — Maintenance (deps, configs, tooling) +# +# Example: +# Add: interactive Theory of Change lab +# Fix: broken nav dropdown on mobile Safari +# +# Body (optional): explain *why*, not *what* — the diff shows what changed. +# Wrap at 72 characters.