CI/CD Integration
GitLint can be integrated into continuous integration workflows to ensure that all commits in your repository adhere to your team's commit message standards. This guide covers how to integrate GitLint with popular CI/CD platforms.
Why Integrate with CI/CD?
While local Git hooks help developers maintain commit message quality during development, CI/CD integration offers additional benefits:
- Catch errors early: Validate commit messages before code is merged
- Enforce standards: Ensure all team members follow commit conventions
- Centralized validation: Apply consistent rules across all branches
- PR validation: Check commit messages in pull requests
- Branch protection: Require commit message validation for protected branches
GitHub Actions
You can easily add GitLint validation to your GitHub Actions workflow:
# .github/workflows/gitlint.yml
name: Validate Commit Messages
on:
push:
branches: [main, dev]
pull_request:
branches: [main]
jobs:
gitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all branches and tags
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: npm
- name: Install dependencies
run: npm install
- name: Validate latest commit message
run: npx gitlint
if: github.event_name == 'push'
- name: Validate PR commit messages
run: git log --pretty=%B ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} | npx gitlint
if: github.event_name == 'pull_request'
GitLab CI
For GitLab CI, add a job to your .gitlab-ci.yml
file:
# .gitlab-ci.yml
stages:
- validate
- build
- test
gitlint:
stage: validate
image: node:18-alpine
script:
- npm install gitlint
- |
if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
# For merge requests, check all commits in the MR
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
git log --pretty=%B FETCH_HEAD..$CI_COMMIT_SHA | npx gitlint
else
# For direct commits, check the latest commit
git log --pretty=%B -n 1 | npx gitlint
fi
CircleCI
Add GitLint validation to your CircleCI configuration:
# .circleci/config.yml
version: 2.1
jobs:
validate-commits:
docker:
- image: cimg/node:18.12
steps:
- checkout
- run:
name: Install dependencies
command: npm install gitlint
- run:
name: Validate commit messages
command: |
if [[ -n "$CIRCLE_PULL_REQUEST" ]]; then
# For pull requests
PR_NUMBER=${CIRCLE_PULL_REQUEST##*/}
git fetch origin +refs/pull/$PR_NUMBER/merge
git log --pretty=%B HEAD^..HEAD | npx gitlint
else
# For direct commits
git log --pretty=%B -n 1 | npx gitlint
fi
workflows:
version: 2
build-test-deploy:
jobs:
- validate-commits
# Other jobs...
Azure DevOps Pipelines
For Azure DevOps, add a validation task to your pipeline:
# azure-pipelines.yml
trigger:
- main
- dev
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: 18.x
displayName: Install Node.js
- script: npm install gitlint
displayName: Install dependencies
- script: |
if [ -n "$(System.PullRequest.SourceBranch)" ]; then
# For pull requests
git fetch origin $(System.PullRequest.TargetBranch)
git log --pretty=%B origin/$(System.PullRequest.TargetBranch)..HEAD | npx gitlint
else
# For direct commits
git log --pretty=%B -n 1 | npx gitlint
fi
displayName: Validate commit messages
Customizing CI Validation
For more advanced CI validation scenarios, you can create a custom script:
// scripts/validate-commits.js
const { execSync } = require('node:child_process')
const { lintCommitMessage } = require('gitlint')
// Determine which commits to check based on CI environment
function getCommitsToCheck() {
if (process.env.GITHUB_EVENT_NAME === 'pull_request') {
const base = process.env.GITHUB_BASE_REF
const head = process.env.GITHUB_HEAD_REF
return execSync(`git log --pretty=%B origin/${base}..origin/${head}`).toString()
}
else {
// Default to checking the latest commit
return execSync('git log --pretty=%B -n 1').toString()
}
}
// Get and validate commits
const commits = getCommitsToCheck().split('\n\ncommit ').filter(Boolean)
let hasErrors = false
commits.forEach((commit) => {
const result = lintCommitMessage(commit)
if (!result.valid) {
console.error(`❌ Invalid commit message:`)
console.error(commit.split('\n')[0])
result.errors.forEach(error => console.error(` - ${error}`))
hasErrors = true
}
})
if (hasErrors) {
process.exit(1)
}
else {
console.log('✅ All commit messages are valid')
}
Best Practices for CI Integration
- Fast feedback: Configure validation as an early step in your CI pipeline
- Clear error reporting: Ensure validation failures provide actionable feedback
- Skip certain commits: Configure rules to ignore merge commits or automated commits
- Documentation: Document the commit message requirements in your repository
- Block merges: Consider making commit message validation a required check for protected branches
Troubleshooting
Common Issues
Issue: CI validation passes locally but fails in CI Solution: Ensure your local and CI GitLint configurations match. Check for environment-specific settings.
Issue: Merge commits failing validation Solution: Add merge commit patterns to your ignores list in GitLint configuration.
Issue: Performance issues with large PRs Solution: Consider validating only the latest N commits or sampling commits.