nanodock 0.1.0

Zero-dependency-light Docker/Podman daemon client for container detection, port mapping, and lifecycle control
Documentation
#!/bin/sh

# nanodock - Commit message validation hook

# Enforces Conventional Commits format: https://www.conventionalcommits.org

#

# Format: <type>(<optional-scope>): <description>

#

# Allowed types:

#   feat      — New feature or capability

#   fix       — Bug fix

#   docs      — Documentation only changes

#   style     — Formatting, whitespace, no code change

#   refactor  — Code change that neither fixes a bug nor adds a feature

#   perf      — Performance improvement

#   test      — Adding or updating tests

#   build     — Build system or external dependency changes

#   ci        — CI/CD configuration changes

#   chore     — Maintenance tasks, tooling, config

#   revert    — Reverts a previous commit

#   enforce   — Adding or updating enforcement rules/quality gates

#

# Rules:

#   - Type is required and must be one of the above

#   - Scope is optional, wrapped in parentheses: feat(api): ...

#   - Colon + space after type/scope is required

#   - Description must start with lowercase letter

#   - Description must be 5-200 characters

#   - No period at the end of the subject line

#

# Examples:

#   feat(api): parse container labels from daemon response

#   fix(ipc): handle named pipe timeout on Windows

#   docs: update README with usage examples


# Read the commit message (first line only for subject validation)

commit_msg_file="$1"
subject=$(head -1 "$commit_msg_file")

# Skip merge commits

if echo "$subject" | grep -qE '^Merge '; then
    exit 0

fi


# Skip revert commits generated by git

if echo "$subject" | grep -qE '^Revert "'; then
    exit 0

fi


# Allowed types

types="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert|enforce"

# Pattern: type(optional-scope): lowercase description

# - Type must be one of the allowed list

# - Optional scope in parentheses (alphanumeric + hyphens)

# - Colon and space required

# - Description starts with lowercase letter

pattern="^($types)(\([a-z0-9-]+\))?: [a-z]"

if ! echo "$subject" | grep -qE "$pattern"; then
    echo ""

    echo "✗ COMMIT MESSAGE REJECTED"

    echo ""

    echo "  Your message:  \"$subject\""

    echo ""

    echo "  Expected format: <type>(<scope>): <description>"

    echo ""

    echo "  Allowed types:"

    echo "    feat, fix, docs, style, refactor, perf,"

    echo "    test, build, ci, chore, revert, enforce"

    echo ""

    echo "  Rules:"

    echo "    - Description must start with a lowercase letter"

    echo "    - No period at the end"

    echo "    - Scope is optional: feat(api): ..."

    echo ""

    echo "  Examples:"

    echo "    feat(api): parse container labels from daemon response"

    echo "    fix(ipc): handle named pipe timeout on Windows"

    echo "    docs: update README with usage examples"

    echo ""

    exit 1

fi


# Check subject length (description part, after "type: " or "type(scope): ")

desc=$(echo "$subject" | sed -E "s/^($types)(\([a-z0-9-]+\))?: //")
desc_len=${#desc}

if [ "$desc_len" -lt 5 ]; then
    echo ""

    echo "✗ COMMIT MESSAGE TOO SHORT"

    echo "  Description must be at least 5 characters."

    echo "  Got: \"$desc\" ($desc_len chars)"

    echo ""

    exit 1

fi


if [ "$desc_len" -gt 200 ]; then
    echo ""

    echo "✗ COMMIT MESSAGE TOO LONG"

    echo "  Subject line description must be ≤200 characters."

    echo "  Got: \"$desc\" ($desc_len chars)"

    echo ""

    exit 1

fi


# No period at the end

if echo "$subject" | grep -qE '\.$'; then
    echo ""

    echo "✗ COMMIT MESSAGE ENDS WITH PERIOD"

    echo "  Do not end the subject line with a period."

    echo "  Got: \"$subject\""

    echo ""

    exit 1

fi