Deployment
Git Hooks & Code Quality

Git Hooks & Code Quality

Complete guide to git hooks, code quality enforcement, and pre-commit checks in the MyNATCA platform.

Overview

The MyNATCA platform uses git hooks to:

  • Enforce branch protection - Prevent direct commits to main/staging
  • Maintain code quality - Run basic checks on every commit
  • Synchronize migrations - Update symlinks automatically
  • Ensure consistency - Trim whitespace, validate syntax

Git Hooks Installation

One-Time Setup

Install git hooks in each repository you work on:

# Platform repository (required)
cd ~/dev/mynatca/platform
./scripts/setup-git-hooks.sh
 
# Pay repository (if working on PayChecker)
cd ~/dev/mynatca/pay
./scripts/setup-git-hooks.sh
 
# Discord repository (if working on Discord bot)
cd ~/dev/mynatca/discord
./scripts/setup-git-hooks.sh

What Gets Installed

Platform repository:

  • pre-commit - Branch protection + quality checks
  • post-checkout - Update migration symlinks
  • post-merge - Update migration symlinks after pulls

Subproject repositories (Pay, Discord):

  • pre-commit - Branch protection + quality checks
  • post-checkout - Trigger platform symlink update
  • post-merge - Trigger platform symlink update

Verification

# Check hooks are installed
ls -la .git/hooks/
 
# Should see:
# pre-commit (executable)
# post-checkout (executable)
# post-merge (executable)
 
# Test pre-commit hook
git checkout main
git commit --allow-empty -m "test"
# Should be blocked with error message

Pre-Commit Hooks

Branch Protection

Prevents direct commits to protected branches:

  • main - Production branch
  • staging - Pre-production branch

Error message:

❌ Direct commits to main/staging are not allowed!

Please use the Pull Request workflow:

1. Create a feature branch:
   git checkout -b feature/my-feature

2. Make your changes and commit:
   git add .
   git commit -m "Your changes"

3. Push and create a Pull Request:
   git push origin feature/my-feature

To bypass this check (not recommended):
   git commit --no-verify

Override (emergency only):

git commit --no-verify -m "Emergency hotfix"

Quality Checks

Automatically run on every commit:

  1. Trailing whitespace - Remove trailing spaces
  2. End of file - Ensure files end with newline
  3. YAML validation - Check YAML syntax
  4. JSON validation - Check JSON syntax
  5. Merge conflict markers - Detect unresolved conflicts

Implementation: Uses pre-commit framework (opens in a new tab) with configuration in .pre-commit-config.yaml.

Configuration

.pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: branch-protection
        name: Branch Protection
        entry: scripts/hooks/check-branch.sh
        language: script
        stages: [commit]
        always_run: true
 
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
        name: Trim trailing whitespace
      - id: end-of-file-fixer
        name: Fix end of files
      - id: check-yaml
        name: Validate YAML
      - id: check-json
        name: Validate JSON
      - id: check-merge-conflict
        name: Check for merge conflicts

Post-Checkout Hooks

Purpose

Automatically update migration symlinks when switching branches.

Behavior

When you run:

git checkout feature/my-branch

Hook automatically runs:

./scripts/link-migrations.sh

Result:

  • Symlinks in platform/supabase/migrations/ updated
  • Point to correct branch versions of pay/discord migrations
  • No manual intervention needed

Example

# Start on main branch
git checkout main
# Hook runs: symlinks point to pay main, discord main
 
# Switch to feature branch
git checkout feature/new-feature
# Hook runs: symlinks point to pay feature, discord main (whatever branches they're on)
 
# Symlinks always reflect current branch state

Post-Merge Hooks

Purpose

Automatically update migration symlinks after pulling changes.

Behavior

When you run:

git pull origin main

Hook automatically runs:

./scripts/link-migrations.sh

Result:

  • Symlinks updated to reflect merged changes
  • New migrations from pay/discord are automatically linked
  • Database stays synchronized

Code Quality Tools

Prettier (Code Formatter)

Purpose: Enforce consistent code formatting

Configuration: .prettierrc.json

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "endOfLine": "lf"
}

Ignored files: .prettierignore

node_modules/
.next/
dist/
build/
coverage/
supabase/functions

Manual usage:

# Check formatting
npx prettier --check "**/*.{js,mjs,json,md,yaml,yml}"
 
# Fix formatting
npx prettier --write "**/*.{js,mjs,json,md,yaml,yml}"

Automatic usage: Runs automatically when you use npm run bump:* commands.

ESLint (Code Linter)

Purpose: Enforce code quality and catch errors

Configuration: .eslintrc.json

{
  "extends": ["eslint:recommended", "next"],
  "env": {
    "node": true,
    "es6": true
  },
  "parserOptions": {
    "ecmaVersion": 2022,
    "sourceType": "module"
  },
  "rules": {
    "no-console": "warn",
    "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
    "prefer-const": "error"
  }
}

Manual usage:

# Check for issues
npx eslint "**/*.{js,mjs}"
 
# Fix auto-fixable issues
npx eslint --fix "**/*.{js,mjs}"

Automatic usage: Runs automatically when you use npm run bump:* commands.

TypeScript Check

Purpose: Validate TypeScript types (if using TypeScript)

Configuration: tsconfig.json

Manual usage:

# Check types
npm run type-check
 
# Or directly
npx tsc --noEmit

Automatic usage: Runs automatically when you use npm run bump:* commands (if tsconfig.json exists).

Deployment Preparation Workflow

Full Quality Check + Version Bump

# Run all quality checks + bump version
npm run bump:patch   # or minor/major

What runs:

Step 1: Prettier

  • Auto-formats all code
  • Fixes formatting issues
  • Updates .js, .mjs, .json, .md, .yaml, .yml files

Step 2: ESLint

  • Lints code
  • Auto-fixes fixable issues
  • Reports unfixable issues (fails if any)

Step 3: TypeScript

  • Checks types (if TypeScript project)
  • Reports type errors (fails if any)

Step 4: Version Bump

  • Updates VERSION file
  • Updates package.json
  • Shows next steps

If any step fails: Process stops, version is not bumped

Why Quality Checks Don't Run on Every Commit

Design decision:

  • Pre-commit hooks run basic checks (whitespace, syntax)
  • Full quality checks (Prettier, ESLint, TypeScript) run during deployment prep
  • Faster commits during development
  • Comprehensive checks before PR/deployment

Rationale:

  • Developers iterate quickly during feature development
  • Full quality checks can be slow
  • Quality enforced at deployment time (when it matters)
  • Can always run manually: npx prettier --write .

Bypassing Hooks

When to Bypass

Legitimate use cases:

  • Emergency hotfixes to production
  • Automated commits (CI/CD)
  • Revert commits
  • Temporary WIP commits (that will be squashed)

NOT legitimate:

  • Avoiding fixing quality issues
  • Skipping branch protection for convenience
  • Committing to main/staging to "save time"

How to Bypass

# Skip all git hooks
git commit --no-verify -m "Emergency fix"
 
# Or set environment variable
SKIP=1 git commit -m "Emergency fix"
 
# Only for pre-commit framework checks
SKIP=trailing-whitespace,check-yaml git commit -m "WIP"

Warning: Use sparingly and only when necessary.

Hook Maintenance

Updating Hooks

# Re-run setup script
cd ~/dev/mynatca/platform
./scripts/setup-git-hooks.sh
 
# Updates all hooks to latest version

Disabling Hooks

Temporarily:

# Bypass for single commit
git commit --no-verify
 
# Disable pre-commit framework
rm .git/hooks/pre-commit
 
# Re-enable
./scripts/setup-git-hooks.sh

Permanently (not recommended):

# Remove all hooks
rm .git/hooks/*

Custom Hooks

Add custom hook:

  1. Edit .pre-commit-config.yaml
  2. Add new hook configuration
  3. Update hooks: pre-commit install

Example: Add custom script

  - repo: local
    hooks:
      - id: my-custom-check
        name: My Custom Check
        entry: scripts/hooks/my-check.sh
        language: script
        stages: [commit]

Troubleshooting

Hooks Not Running

Issue: Git hooks don't execute

Solution:

# Reinstall hooks
./scripts/setup-git-hooks.sh
 
# Check hooks are executable
ls -la .git/hooks/
 
# If not executable
chmod +x .git/hooks/pre-commit
chmod +x .git/hooks/post-checkout
chmod +x .git/hooks/post-merge

Pre-Commit Framework Not Found

Issue: pre-commit: command not found

Solution:

# Install pre-commit framework
pip install pre-commit
 
# Or via Homebrew
brew install pre-commit
 
# Install hooks
pre-commit install

Hook Fails with Error

Issue: Hook script has syntax error or fails

Solution:

# Check hook script
cat .git/hooks/pre-commit
 
# Test hook manually
.git/hooks/pre-commit
 
# See detailed error
bash -x .git/hooks/pre-commit

Can't Commit on Main/Staging

Issue: Legitimate need to commit to main/staging

Solution:

# Option 1: Use feature branch (recommended)
git checkout -b feature/my-fix
git commit -m "My fix"
# Then create PR
 
# Option 2: Bypass hook (emergency only)
git commit --no-verify -m "Emergency hotfix"

Symlinks Not Updating

Issue: Migration symlinks don't update after checkout

Solution:

# Manually run link script
./scripts/link-migrations.sh
 
# Verify post-checkout hook exists
ls -la .git/hooks/post-checkout
 
# Reinstall hooks
./scripts/setup-git-hooks.sh

Quality Checks Fail

Issue: npm run bump fails with lint errors

Solution:

# Fix Prettier issues
npx prettier --write "**/*.{js,mjs,json,md,yaml,yml}"
 
# Fix ESLint issues
npx eslint --fix "**/*.{js,mjs}"
 
# Fix remaining ESLint issues manually
npx eslint "**/*.{js,mjs}"
# Edit files to fix reported issues
 
# Fix TypeScript issues
npm run type-check
# Edit files to fix type errors
 
# Try bump again
npm run bump:patch

Best Practices

DO ✅

  • Install git hooks in all repos you work on
  • Run npm run bump:* before creating PRs
  • Fix quality issues promptly
  • Use feature branches for all work
  • Test hooks after installation
  • Update hooks when scripts change
  • Follow branch protection rules
  • Keep hooks executable

DON'T ❌

  • Skip hook installation
  • Regularly bypass hooks with --no-verify
  • Commit directly to main/staging
  • Ignore quality check failures
  • Modify .git/hooks/ files directly (use setup script)
  • Disable hooks permanently
  • Commit without testing
  • Force push to protected branches

Quick Reference

Commands

# Installation
./scripts/setup-git-hooks.sh              # Install all hooks
 
# Quality checks (manual)
npx prettier --write "**/*.{js,mjs,json,md,yaml,yml}"
npx eslint --fix "**/*.{js,mjs}"
npm run type-check
 
# Quality checks (automatic)
npm run bump:patch                        # All checks + version bump
npm run bump:minor
npm run bump:major
 
# Bypass hooks
git commit --no-verify                    # Skip all hooks
SKIP=1 git commit -m "message"            # Skip pre-commit framework
 
# Hook management
ls -la .git/hooks/                        # List installed hooks
chmod +x .git/hooks/*                     # Make hooks executable
rm .git/hooks/hook-name                   # Remove specific hook

Files

Configuration:

  • .pre-commit-config.yaml - Pre-commit framework configuration
  • .prettierrc.json - Prettier configuration
  • .prettierignore - Prettier ignore patterns
  • .eslintrc.json - ESLint configuration
  • tsconfig.json - TypeScript configuration

Scripts:

  • scripts/setup-git-hooks.sh - Hook installation script
  • scripts/hooks/check-branch.sh - Branch protection script
  • scripts/link-migrations.sh - Migration symlink script
  • scripts/prepare-deployment.sh - Full deployment prep
  • scripts/bump-version.js - Version bump script

Hooks:

  • .git/hooks/pre-commit - Before commit
  • .git/hooks/post-checkout - After checkout
  • .git/hooks/post-merge - After merge/pull

Related Documentation