v1.1.0

Build Summary: Implementing Husky for Production Tag Enforcement

Date: October 8, 2025

Project: acorninteractive.ca

Version: v1.0.4 → v1.1.0

What We Built

Today we implemented Git hooks using Husky to enforce annotated tags on our production branch, ensuring all production releases are properly versioned and documented.

Implementation Steps

Researched Project Context

  • Cross-referenced existing notes about production branch setup
  • Identified multi-environment configuration (Meteor 2.7.2 on prod/staging, Meteor 3.3 on QA)
  • Confirmed Node version differences (Node 18 vs Node 20.12.2)

Installed Husky

  • Added Husky v9 as a dev dependency via npm install --save-dev husky
  • Ran npx husky install to initialize the .husky directory
  • Created the _/husky.sh support file

Created Pre-Push Hook

  • Built custom shell script in .husky/pre-push
  • Implemented branch detection (only triggers on production branch)
  • Added annotated tag validation logic
  • Verified tags have messages (not just lightweight tags)
  • Included helpful error messages with exact commands to fix issues

Updated package.json

  • Added "prepare": "husky install" script
  • Ensures Husky sets up automatically on npm install

Made Hooks Executable

  • Ran chmod +x .husky/pre-push to set execution permissions
  • Verified permissions with ls -la .husky/pre-push

Tested the Hook

  • Ran .husky/pre-push directly to test functionality
  • Attempted git push without a tag (correctly blocked)
  • Verified existing annotated tag (v1.0.4) was properly detected
  • Confirmed hook allows push when requirements are met

Updated Documentation

  • Added comprehensive Husky section to README.md
  • Included environment-specific setup instructions
  • Documented workflow for creating annotated tags
  • Added tag naming conventions (v1.0.x for production)
  • Provided troubleshooting steps

Committed Changes

  • Staged .husky/, package.json, package-lock.json, and README.md
  • Created detailed commit message explaining the changes
  • Tagged as v1.0.5: "Add Husky pre-push hooks for production tag enforcement"
  • Successfully pushed to production with --follow-tags

Technical Details

Hook Behavior:

  • Only enforces on production branch (other branches unaffected)
  • Checks if latest commit has an annotated tag
  • Validates tag includes a message (not lightweight)
  • Provides clear error messages with remediation steps
  • Displays success confirmation when requirements met

Files Changed:

  • 3 files modified
  • 152 insertions (+)
  • 5 deletions (-)
  • Created .husky/pre-push (mode 100755)

Benefits

  1. Enforces Release Documentation - Every production release now has a version tag and description
  2. Prevents Unversioned Releases - Impossible to push to production without proper tagging
  3. Team Consistency - All developers follow the same release process
  4. Audit Trail - Git tags provide clear history of production releases
  5. Automatic Setup - New team members get hooks automatically via npm install

Environments:

  • ✅ Works on Production/Staging (Meteor 2.7.2 + Node 18)
  • ✅ Works on QA (Meteor 3.3 + Node 20.12.2)
  • ✅ Cross-platform compatible (Linux, macOS, Windows)

Next Steps

  • Team members should pull latest changes and run npm install
  • Update any CI/CD pipelines to include HUSKY=0 flag if needed
  • Consider adding additional hooks (pre-commit for linting, commit-msg for conventional commits)
  • Monitor adoption and gather team feedback

Lessons Learned

  • Husky v9 uses install command instead of init
  • Hook files must be executable (chmod +x) to function
  • The || true in prepare script prevents failures in CI environments
  • Clear error messages significantly improve developer experience
  • Testing hooks directly (.husky/pre-push) speeds up validation
  • The tag enforcement test validated Husky works correctly - This proves our hook infrastructure is functional and ready for other pre-push tasks

Future Refactoring: Move Tagging to CI/CD Pipeline

While the current implementation enforces tags at pre-push, a more robust approach would move tag creation to the pipeline stage sequence - only creating tags after successful deployment validation.

This would:

  • Ensure tags only exist for successfully deployed code
  • Eliminate the possibility of tagged but undeployed commits
  • Enable automatic version incrementing without manual developer intervention
  • Provide a single source of truth for release versioning

Proposed workflow:

  • Developer pushes to production branch (no tag required)
  • CI/CD runs build and deployment
  • After successful deployment, pipeline automatically creates and pushes annotated tag
  • Tag version is auto-incremented based on previous tags

Tools that support automatic version incrementing:

semantic-release - Fully automated version management and package publishing

  • Analyzes commit messages to determine version bump (major/minor/patch)
  • Creates tags and release notes automatically
  • Works with conventional commits

standard-version - Automated versioning and CHANGELOG generation

  • Bumps version in package.json
  • Creates annotated Git tags
  • Generates CHANGELOG from commit history

Bitbucket Pipelines variables - $BITBUCKET_BUILD_NUMBER or custom scripting

  • Can use build numbers for auto-incrementing
  • Combine with git tag parsing to determine next version

GitVersion - Semantic versioning based on Git history

  • Calculates versions from branch and tag patterns
  • Works well with GitFlow workflows

bump2version / bumpversion - Simple version incrementing tool

  • Updates version strings in multiple files
  • Creates Git tags automatically

npm version - Built-in Node.js versioning

  • npm version patch/minor/major auto-increments and tags
  • Simple integration with existing workflows

More research needed:

  • Integration with Bitbucket Pipelines YML
  • Handling failed deployments and rollback scenarios
  • Version numbering strategy for hotfixes vs regular releases
  • Coordination between QA (v3.x) and Production (v1.x) version schemes

Repurposing Pre-Push Hook

Keep the pre-push hook in place but repurpose it for unit test execution instead of tag enforcement:

# .husky/pre-push - Run tests before pushing

$ npm run test

This provides:

  • Fast feedback on test failures before code reaches CI/CD
  • Reduced CI/CD pipeline execution time (failing fast locally)
  • Developer confidence before pushing to remote
  • No impact on other branches (tests run everywhere, which is good)

The tag enforcement test we implemented today successfully validated that Husky infrastructure works correctly, proving we can rely on pre-push hooks for other quality gates like unit tests.