Skip to content

Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, dynamic czg scope config, and CI workflow#11

Merged
ais-one merged 13 commits intomainfrom
copilot/create-git-pre-commit-pre-push-hooks
Apr 5, 2026
Merged

Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, dynamic czg scope config, and CI workflow#11
ais-one merged 13 commits intomainfrom
copilot/create-git-pre-commit-pre-push-hooks

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 5, 2026

Replaces the placeholder git-hooks/pre-commit with a full .githooks/ setup covering pre-commit validation, commit message format enforcement, pre-push workspace-scoped test gates, and a security audit step. Supports npm only. Also adds a CI workflow that mirrors the hook checks, and a czg.config.js that dynamically discovers workspace scopes for interactive conventional commit prompts.

New files

  • .githooks/pre-commit — Runs on every commit:

    • Runs npx biome check <dir> for each directory that has staged changes (common/iso, common/node, common/vue, common/web, apps, webs, scripts)
    • Detects staged files under common/schemas and apps/*/schemas and runs npm run test:schemas -- <folder> for each affected schema directory
  • .githooks/commit-msg — Runs on every commit to validate the commit message:

    • Validates against the Conventional Commits spec: type(scope?)[!]: description
    • Valid types: feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert
    • Skips merge, revert, fixup, and squash commits automatically
    • On failure, prints the expected format and suggests using npx czg to generate a valid message interactively
  • .githooks/pre-push — Runs on every push:

    • Reads the push range from stdin, determines which apps/* and common/* workspaces have changed files, and runs npm run test --workspace=<ws> for each impacted workspace that has a test script
    • Discovers all existing schema directories (common/schemas, apps/*/schemas) and runs npm run test:schemas -- <folder> for each
    • Runs npm audit --audit-level=moderate; if vulnerabilities are found, prompts the user to continue or abort
    • All gates respect --no-verify
  • .githooks/setup.sh — One-time install: sets core.hooksPath, makes all hooks (pre-commit, commit-msg, pre-push) executable, reports czg availability

  • .githooks/_common.sh — Shared colour variables and print_info/print_success/print_warning/print_error helpers, sourced by all hook scripts to eliminate duplication

  • czg.config.js — Configures npx czg scope options for the interactive commit prompt by dynamically discovering workspace directories at load time:

    • Uses fs.readdirSync to enumerate apps/* and common/* directories at runtime — no manual updates needed when workspaces are added or removed
    • NA is always listed first for commits that don't target a specific workspace
    • All discovered workspace paths follow as selectable options
  • .github/workflows/hooks-ci.yml — CI workflow that mirrors the git hooks:

    • Triggers on push to main (when common/**, apps/**, webs/**, or scripts/** change) and on all pull requests to main
    • commit-lint job: checks every commit message in a PR against the Conventional Commits pattern; emits ::error:: annotations for violations
    • biome job: runs npx biome ci <dir> for each watched directory that exists
    • schema-tests job: runs npm run test:schemas -- <folder> for common/schemas and each existing apps/*/schemas directory

Updated files

  • package.jsonprepare script updated to core.hooksPath .githooks so npm install auto-configures hooks
  • .github/CONTRIBUTING.md — Added Git Hooks Setup section: manual install, czg conventional commit usage (npx czg / npx czg --ai), and bypass instructions

czg usage

npx czg          # interactive conventional commit prompt (scopes dynamically listed from apps/* and common/*)
npx czg --ai     # AI-generated commit message
git commit --no-verify  # bypass pre-commit and commit-msg hooks
git push --no-verify    # bypass pre-push (including security audit)
Original prompt

Create native Git pre-commit and pre-push hooks with the following features:

Pre-commit Hook Requirements

  • Formatting & Linting: Use Biome for code formatting and linting
  • Commit Message: Integrate czg for standardized commit message formatting with option for AI-generated messages
  • Code Quality Checks:
    • Ensure no debugger statements in code
    • Ensure no console statements in production files
    • Validate code against Biome rules
  • Schema Validation: Run tests to validate zop schemas located in a schema/ folder
  • Staged Files: Only run checks on staged files

Pre-push Hook Requirements

  • Unit Tests: Run unit tests before allowing push
  • Schema Tests: Run schema validation tests
  • Branch Protection: Ensure tests pass before push is allowed
  • Options: Allow bypassing with --no-verify flag

Implementation Details

  • Use native Git hooks (shell scripts)
  • Located in .githooks/ directory
  • Make hooks executable and properly documented
  • Include helpful error messages
  • Support for common environments (Node.js, pnpm)
  • Color-coded output for better UX
  • Options to skip certain checks if needed

Files to Create

  1. .githooks/pre-commit - Pre-commit validation script
  2. .githooks/pre-push - Pre-push validation script
  3. .githooks/setup.sh - Hook installation script
  4. Documentation explaining usage and setup

Integration

  • Document how to install hooks locally
  • Include instructions in README or CONTRIBUTING.md
  • Support different package managers (pnpm, npm, yarn)

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: would you recommend czg or commitizen?

Assistant: I can help you decide between czg and commitizen! Let me search for information about both tools to give you a comprehensive comparison.

Assistant: Both commitizen and czg are valid tools for standardized commit messages, but they serve different needs:

Commitizen

  • Maturity: Well-established (10+ years), widely adopted ecosystem
  • Language: JavaScript/TypeScript focused
  • Extensibility: Highly customizable through adapters (cz-conventional-changelog, cz-jira-smart-commit, etc.)
  • Setup: Requires configuration in package.json or .czrc
  • Use case: Best if you want a battle-tested, plugin-based solution with multiple commit conventions

czg (Commits Wizard)

  • Newer: Modern alternative built with better UX in mind
  • Performance: Lighter weight, written in Rust (faster execution)
  • Simplicity: Zero-config by default, works out of the box
  • Scope: Less customizable but covers conventional commits well
  • Use case: Best if you want a quick setup with modern tooling and don't need extensive customization

My Recommendation

Choose commitizen if:

  • Your team needs deep customization or multiple commit styles
  • You're already in a JavaScript/Node.js ecosystem
  • You want a mature, proven solution with community support

Choose czg if:

  • You want a modern, lightweight tool that works immediately
  • You prefer faster execution and simpler configuration
  • You're comfortable with conventional commits as the standard

For most projects, commitizen is the safer choice due to maturity and ecosystem support, but czg is an excellent alternative if you value simplicity and modern tooling. You could also try both in a test project to see which developer experience you prefer.

User: can you write a precommit hook, using native git hooks, for pre-commit and pre-push scripts, using biome for formatting and linting, and czg for commit message formatting, please include options for using AI to generate commit message, run unit test, no debugger statements, no console in production, run tests to test zop schemas in a schema folder.

Assistant: I'll create comprehensive pre-commit and pre-push hooks for you with all those features.

Assistant: I'm waiting for you to review and confirm the pull request that will be created with the Git hooks implementation.

User: @Copilot Accepted Confirmation: Confirm agent session

Assistant: I need the repository information to create the pull request. Could you provide:

  1. Repository owner (your GitHub username or organization)
  2. Repository name

Alternatively, you can provide the full GitHub URL to your repository (e.g., https://github.com/owner/repo).

Once you provide this, I'll create a comprehensive pull request with:

  • ✅ Pre-commit hook with Biome formatting/linting
  • ✅ Pre-push hook with unit test execution
  • ✅ czg integration for commit messages with AI option
  • ✅ Debugger statement detection
  • ✅ Console statement validation for production
  • ✅ Schema validation tests (zop schemas)
  • ✅ Setup script for easy installation
  • ✅ Full documentation

User: @es-labs/express-template

Assistant: Perfect! I've created a comprehensive pull request for the es-labs/express-template repository with Git hooks for pre-comm...

This pull request was created from Copilot chat.

Copilot AI and others added 2 commits April 5, 2026 11:44
…te package.json prepare script and CONTRIBUTING.md

Agent-Logs-Url: https://github.com/es-labs/express-template/sessions/55aee88f-343e-4ab6-befc-5314fa4a21a9

Co-authored-by: ais-one <4284574+ais-one@users.noreply.github.com>
…cks to use staged content per-file

Agent-Logs-Url: https://github.com/es-labs/express-template/sessions/55aee88f-343e-4ab6-befc-5314fa4a21a9

Co-authored-by: ais-one <4284574+ais-one@users.noreply.github.com>
Copilot AI changed the title [WIP] Add native Git pre-commit and pre-push hooks Add native Git hooks (.githooks/) with Biome, czg, and test gates Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 11:47
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. please rewrite to only support npm

  2. for .githooks/pre-commit, can we

  • assume biome is already installed and use npx to run the checks, try following
    • if common/iso contents touched, run npx biome check common/iso
    • if common/node contents touched, run npx biome check common/node
    • if common/vue contents touched, run npx biome check common/vue
    • if common/web contents touched, run npx biome check common/web
    • if apps contents touched, run npx biome check apps
    • if webs contents touched, run npx biome check webs
    • if scripts contents touched, run npx biome check scripts
  • remove checks for no console
  • remove checks for debugger statements

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

  1. please rewrite to only support npm

  2. for .githooks/pre-commit, can we...

Done in fff53de:

  • Removed pnpm/yarn support — all hooks use npm exclusively
  • pre-commit now runs npx biome check <dir> only for directories with staged changes (common/iso, common/node, common/vue, common/web, apps, webs, scripts)
  • Removed the debugger statement check
  • Removed the console.* statement check
  • Schema tests still run when schema/ or schemas/ files are staged
  • Updated setup.sh description and CONTRIBUTING.md to match

Copilot AI changed the title Add native Git hooks (.githooks/) with Biome, czg, and test gates Add native Git hooks (.githooks/) with Biome per-directory checks and test gates Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 12:36
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the schemas validation, the following are the folders to check
common/schema
common/schemas
/apps//schema
/apps/
/schemas

for the npm run test:schema command can an argument be passed in to specify the above schema folder to be tested

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

for the schemas validation, the following are the folders to check
common/schema
common/schemas...

Done in 21607ee.

pre-commit: schema tests now trigger only for the specific folders (common/schema, common/schemas, apps/*/schema, apps/*/schemas). Each affected folder is passed individually as npm run test:schemas -- <folder>.

pre-push: discovers all of those schema directories that actually exist on disk and runs npm run test:schemas -- <folder> for each one.

Copilot AI requested a review from ais-one April 5, 2026 13:28
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code below appears on all scripts...

# ── Colours ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Colour

print_info()    { printf "${BLUE}[pre-commit]${NC} %s\n" "$1"; }
print_success() { printf "${GREEN}[pre-commit]${NC} %s\n" "$1"; }
print_warning() { printf "${YELLOW}[pre-commit]${NC} %s\n" "$1"; }
print_error()   { printf "${RED}[pre-commit]${NC} %s\n" "$1"; }

is it possible to make it be imported? or possible to shorten?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

the code below appears on all scripts...

Done in 06ebc0d. The repeated block is now extracted into .githooks/_common.sh. Each script sets HOOK_NAME before sourcing it:

HOOK_NAME=pre-commit
. "$(dirname "$0")/_common.sh"

_common.sh defines the colour variables and the four print_* helpers using $HOOK_NAME as the tag, so each hook's output still shows its own label ([pre-commit], [pre-push], [setup]).

@ais-one ais-one marked this pull request as ready for review April 5, 2026 13:37
Copilot AI requested a review from ais-one April 5, 2026 13:37
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce the schema folders to the 2 below

  • common/schemas
  • apps/*/schemas

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

please add security audit code below to pre-push

Done in ffe6741. Added as step 3 in pre-push, adapted to POSIX sh (the hook uses #!/bin/sh) and integrated with the existing print_* helpers:

# ── 3. Security audit ────────────────────────────────────────────────────────
print_info "Running security audit…"
npm audit --audit-level=moderate
AUDIT_EXIT=$?
if [ $AUDIT_EXIT -ne 0 ]; then
  print_warning "Security vulnerabilities found."
  printf "Continue push anyway? (y/n) "
  read -r REPLY
  case "$REPLY" in
    [Yy]*) print_info "Continuing push despite vulnerabilities." ;;
    *)     print_error "Push aborted. Fix vulnerabilities or use 'git push --no-verify' to bypass."; exit 1 ;;
  esac
else
  print_success "No security vulnerabilities found."
fi

The read -p and [[...]] from the snippet were replaced with POSIX-compatible printf + read -r + case so it works under dash/sh as well as bash.

Copilot AI changed the title Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, test gates, and CI workflow Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, security audit, test gates, and CI workflow Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 14:15
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. the command to test should be npm run test --workspace=<workspace_name> for impacted workspaces.

  2. what is the list of additional packages required to be installed in the root package.json as devDependencies?

Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the command to test should be npm run test --workspace=<workspace_name> for impacted workspaces, see if there is any place needs to update this?

what is the list of additional packages required to be installed in the root package.json as devDependencies? can add the info to contribution.md?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

  1. the command to test should be npm run test --workspace=<workspace_name> for impacted workspaces.

  2. what is the list of additional packages required to be installed in the root package.json as d...

Done in 80f4509.

1. Workspace-scoped tests — The pre-push hook now reads the push range from stdin (remote_sha..local_sha, or from the empty tree for new branches), collects all changed files, and identifies which apps/* / common/* workspaces have changes. It then runs npm run test --workspace=<ws> for each impacted workspace that has a test script:

npm run test --workspace="apps/app-sample"

If no workspace files changed, the test step is skipped gracefully.

2. Required devDependencies — No additional packages need to be added. The hooks rely on:

  • @biomejs/biome — already in devDependencies
  • npm audit — built into npm, no package needed
  • npx czg — optional interactive helper; fetched on-demand via npx (no install required); add czg to devDependencies only if you want a pinned version available offline

the command to test should be npm run test --workspace=<workspace_name> for impacted workspaces, see if there is any place needs to update this?

what is the list of additional packages required to be...

Addressed in 80f4509 — see the reply above for full details. The hook now runs npm run test --workspace=<ws> for each impacted workspace detected from the push range.

Copilot AI changed the title Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, security audit, test gates, and CI workflow Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, and CI workflow Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 14:35
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the scope for commit message be added as options to choose by npx czg

the scopes are workspace like apps/app-sample, common/vue, there will also be one more options NA placed as the first option

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

can the scope for commit message be added as options to choose by npx czg

the scopes are workspace like apps/app-sample, common/vue, there will also be one more options NA placed as the first optio...

Done in 580d0ec. Added czg.config.js at the repo root with NA as the first scope option followed by all workspace paths:

export default {
  prompt: {
    scopes: [
      'NA',
      'apps/app-mcp',
      'apps/app-mcp2',
      'apps/app-sample',
      'common/iso',
      'common/node',
      'common/schemas',
      'common/vue',
      'common/web',
    ],
  },
}

npx czg automatically picks up this file and presents these as a selectable list in the scope step of the interactive prompt.

Copilot AI changed the title Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, and CI workflow Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, czg scope config, and CI workflow Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 14:49
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to list workspaces first using script and then inject them as scopes when running npx czg?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 5, 2026

is it possible to list workspaces first using script and then inject them as scopes when running npx czg?

Done in 118ff12. czg.config.js now uses fs.readdirSync to discover workspace directories at load time instead of a hardcoded list:

import { readdirSync, statSync } from 'node:fs'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'

const root = dirname(fileURLToPath(import.meta.url))

function listDirs(parent) {
  try {
    return readdirSync(join(root, parent))
      .filter((name) => statSync(join(root, parent, name)).isDirectory())
      .map((name) => `${parent}/${name}`)
  } catch {
    return []
  }
}

const workspaceScopes = [...listDirs('apps'), ...listDirs('common')]

export default {
  prompt: {
    scopes: ['NA', ...workspaceScopes],
  },
}

When npx czg is run it resolves to ['NA', 'apps/app-mcp', 'apps/app-mcp2', 'apps/app-sample', 'common/iso', ...] automatically — any new workspace added under apps/ or common/ will appear in the list without needing to edit the config.

Copilot AI changed the title Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, czg scope config, and CI workflow Add native Git hooks (.githooks/) with Biome per-directory checks, commit message validation, workspace-scoped test gates, security audit, dynamic czg scope config, and CI workflow Apr 5, 2026
Copilot AI requested a review from ais-one April 5, 2026 15:02
Copy link
Copy Markdown
Contributor

@ais-one ais-one left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ais-one ais-one merged commit ceb1b06 into main Apr 5, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants