A practical, step-by-step guide to testing and deploying this Jekyll website.
⚠️ IMPORTANT: All testing happens LOCALLY. GitHub Actions only builds and deploys!
Your local machine is the ONLY quality gate.
┌─────────────────────────────────────────────────────────┐
│ LOCAL MACHINE (You) │
├─────────────────────────────────────────────────────────┤
│ 1. Make changes │
│ 2. Run tests locally (via Lefthook hooks) │
│ 3. Fix any errors │
│ 4. Tests pass → commit and push │
└────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ GITHUB ACTIONS (Automated) │
├─────────────────────────────────────────────────────────┤
│ 1. Receives your push │
│ 2. Builds Jekyll site │
│ 3. Deploys to GitHub Pages │
│ NO TESTING - Deploys immediately │
└─────────────────────────────────────────────────────────┘
Benefits:
Your safety net:
Automatically enforced by Lefthook:
Optional (run manually with –full flag):
Run these commands once when setting up the project:
# Install Ruby dependencies (Jekyll, html-proofer)
bundle install
# Install Node.js dependencies (Lighthouse CI, Lefthook)
npm install
# Install Lefthook git hooks
npx lefthook install
# Install yamllint (Python tool)
pip install yamllint
# or on some systems:
pip3 install yamllint
Verify installation:
yamllint --version # Should show version number
bundle exec jekyll --version
npx lefthook --version
npx lhci --version
Check hooks are installed:
ls -la .git/hooks/
# Should see: pre-commit, pre-push (symlinks or files)
⭐ RECOMMENDED FOR MOST USERS
Just work normally - Lefthook will automatically run tests when you commit and push.
You do NOT need to run ./test-before-push.sh manually - the pre-push hook runs it automatically for you!
# 1. Make your changes
vim _portfolio/31-new-work.md
# 2. Start local server (optional, to preview)
bundle exec jekyll serve
# View at http://localhost:4000
# 3. Commit your changes
git add .
git commit -m "Add new portfolio work"
# → Lefthook pre-commit hook runs YAML validation
# → If YAML fails, commit is blocked
# 4. Push to GitHub
git push origin main
# → Lefthook pre-push hook runs ALL tests automatically
# → If tests pass: push succeeds → GitHub deploys
# → If tests fail: push is blocked → fix errors and try again
That’s it! No need to remember to run tests manually.
When you run git commit:
→ Running pre-commit hook...
→ Validating YAML in staged files (quick check)...
✓ YAML validation passed!
[main abc123] Add new portfolio work
When you run git push:
The pre-push hook automatically runs ./test-before-push.sh - the COMPLETE test suite:
→ Running pre-push hook...
→ Running: ./test-before-push.sh
═══════════════════════════════════════════════════════════
Pre-Push Testing - Local Validation
═══════════════════════════════════════════════════════════
⚠️ IMPORTANT: This is your ONLY test gate!
GitHub Actions does NOT run tests - it only builds and deploys.
→ Step 1/5: YAML Linting
✓ YAML linting passed!
→ Step 2/5: Building Jekyll Site
✓ Jekyll build completed successfully!
→ Step 3/5: HTML Validation & Link Checking
✓ HTML validation passed!
→ Step 4/5: Print Testing
✓ Print tests passed!
→ Step 5/5: Lighthouse CI (Skipped)
═══════════════════════════════════════════════════════════
Test Results Summary
═══════════════════════════════════════════════════════════
✓ All tests passed! ✨
Counting objects: 5, done.
[... git push output ...]
Example: YAML error on commit
git commit -m "Add work"
→ Running pre-commit hook...
→ Validating YAML in staged files...
_portfolio/31-work.md
42:81 warning line too long (151 > 150 characters)
❌ YAML validation failed. Fix the errors above before committing.
# Commit blocked! Fix the error and try again.
Example: HTML error on push
git push origin main
→ Running pre-push hook...
→ Running: ./test-before-push.sh
[... tests running ...]
→ Step 3/5: HTML Validation & Link Checking
✗ HTML validation failed!
- _site/works/new-work/index.html
* internally linking to /assets/missing.jpg, which does not exist
❌ Tests failed! Push blocked.
Fix the errors above, then run again:
./test-before-push.sh
# Push blocked! Fix the error and try again.
Only skip hooks if:
./test-before-push.sh manually and all tests passed# Skip hooks for this push only
LEFTHOOK=0 git push
# or
git push --no-verify
# Skip hooks for this commit only
LEFTHOOK=0 git commit -m "message"
# or
git commit --no-verify -m "message"
⚠️ WARNING: Skipping hooks = deploying untested code = potential site breakage!
If you want to test before committing, or run specific tests, use these commands:
# Run all tests (fast - no Lighthouse)
./test-before-push.sh
# Run all tests including Lighthouse (slower, ~2 minutes)
./test-before-push.sh --full
# Quick YAML check only (fastest, <1 second)
./test-before-push.sh --quick
This is the same script that the pre-push hook runs automatically.
YAML validation (very fast):
yamllint .
Jekyll build:
bundle exec jekyll build
HTML validation:
bundle exec rake test
Print tests:
npm run test:print
# PDFs saved to ./print-test-results/
Lighthouse CI (optional):
npm run lighthouse
# Reports saved to .lighthouseci/
External links check (slow):
bundle exec rake test_external
# 1. Start development server
bundle exec jekyll serve
# Keep this running in one terminal
# 2. Make changes and preview at http://localhost:4000
# 3. Run quick tests while developing
yamllint . # Fast YAML check
./test-before-push.sh --quick # Or use the script
# 4. Before committing, run full tests
./test-before-push.sh
# 5. If tests pass, commit and push
git add .
git commit -m "message"
git push origin main
# Hooks will run tests again automatically
┌─────────────────────────────────────────────────────────┐
│ Step 1: Local Testing (You) │
├─────────────────────────────────────────────────────────┤
│ • Make changes │
│ • Lefthook runs tests on git push │
│ • Tests pass → push succeeds │
│ • Tests fail → push blocked │
└────────────────┬────────────────────────────────────────┘
│
│ git push origin main
▼
┌─────────────────────────────────────────────────────────┐
│ Step 2: GitHub Actions Build │
├─────────────────────────────────────────────────────────┤
│ • Checks out code │
│ • Sets up Ruby │
│ • Runs: bundle exec jekyll build │
│ • NO TESTING - Just builds │
└────────────────┬────────────────────────────────────────┘
│
│ Build artifact
▼
┌─────────────────────────────────────────────────────────┐
│ Step 3: GitHub Pages Deployment │
├─────────────────────────────────────────────────────────┤
│ • Deploys to www.j3zz.com │
│ • Site live in ~30-60 seconds │
└─────────────────────────────────────────────────────────┘
Local testing (Lefthook): ~30-60 seconds
GitHub Actions: ~1-2 minutes
Total time from push to live: ~2-3 minutes
Old system (with CI testing): ~5-10 minutes
View GitHub Actions progress:
Success indicators:
Rare, but possible if:
Check the logs:
Common fixes:
Gemfile.lock: bundle update github-pages_config.yml is validCheck if hooks are installed:
ls -la .git/hooks/
# Should see: pre-commit, pre-push
Reinstall hooks:
npx lefthook install
Check Lefthook config:
cat lefthook.yml
# Should have pre-commit and pre-push sections
You shouldn’t need to, but if you must:
LEFTHOOK=0 git push
Better approach:
# Run tests manually first
./test-before-push.sh
# If all pass, push normally (hooks will run again but pass quickly)
git push origin main
Adjust rules in .yamllint:
rules:
line-length:
max: 200 # Increase if needed
level: warning # Change to warning instead of error
Default tests (without –full) should be fast:
If slower:
bundle exec jekyll cleanLighthouse is intentionally optional (use –full flag only before releases)
Expected! Chrome may not be available in WSL.
The script handles this gracefully:
⚠ Print tests skipped - Chrome not available in this environment
This is expected in WSL/headless environments.
This is OK - print tests validate QR codes and layouts, not critical for every push.
To test print layouts:
Check the logs:
Common causes:
CNAME file_config.yml has production-only setting that breaks buildQuick fix:
# Test production build locally
JEKYLL_ENV=production bundle exec jekyll build
# If it fails locally, fix the issue
# If it builds locally but fails on GitHub, check GitHub status
Run full test suite including Lighthouse:
./test-before-push.sh --full
Review reports:
# Open Lighthouse reports
open .lighthouseci/*.html
# Check print PDFs
open print-test-results/*.pdf
# Development
bundle exec jekyll serve # Start local server
bundle exec jekyll build # Build site
# Testing (automatic via hooks)
git commit -m "message" # Triggers YAML validation
git push origin main # Triggers full test suite
# Testing (manual)
./test-before-push.sh # All tests (fast)
./test-before-push.sh --full # All tests + Lighthouse
./test-before-push.sh --quick # YAML only
# Individual tests
yamllint . # YAML validation
bundle exec rake test # HTML + links
npm run test:print # Print layouts
npm run lighthouse # Performance/a11y
# Hooks
npx lefthook install # Install hooks
npx lefthook run pre-commit # Test pre-commit hook
npx lefthook run pre-push # Test pre-push hook
LEFTHOOK=0 git push # Skip hooks (caution!)
Before pushing changes:
./test-before-push.sh)--full flag)Quick tests (default, via hooks):
Full tests (with --full flag):
.lighthouseci/ # Lighthouse HTML reports
print-test-results/ # Print test PDFs
_site/ # Built Jekyll site
.bundle/ # Ruby gems cache
node_modules/ # Node.js packages
vendor/ # Bundler packages
Test failures:
Deployment issues:
JEKYLL_ENV=production bundle exec jekyll buildHook issues:
ls -la .git/hooks/npx lefthook installcat lefthook.ymlGeneral questions: