Skip to content

ci: add conventional commit and PR base checks #5

ci: add conventional commit and PR base checks

ci: add conventional commit and PR base checks #5

Workflow file for this run

name: Lint PR
on:
pull_request:
types:
- opened
- edited
- synchronize
- reopened
- labeled
- unlabeled
jobs:
validate-pr-title:
name: Validate PR title (Conventional Commits)
runs-on: ubuntu-latest
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-conventional-commit-check') }}
steps:
- name: Check Conventional Commits format
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
# Conventional Commits: <type>(<optional-scope>)(!): <subject>
# Allowed types match the project's release-please changelog sections.
PATTERN='^(feat|fix|docs|style|refactor|test|chore|ci|build|perf|revert)(\([^)]+\))?!?: .+'
if printf '%s' "$PR_TITLE" | grep -qE "$PATTERN"; then
echo "PR title is a valid Conventional Commit: $PR_TITLE"
exit 0
fi
{
echo "::error title=Invalid PR title::PR title must follow Conventional Commits format."
echo " Got: $PR_TITLE"
echo " Expected: <type>(<optional-scope>)(!): <subject>"
echo " Types: feat, fix, docs, style, refactor, test, chore, ci, build, perf, revert"
echo ""
echo " Examples:"
echo " feat: add new endpoint"
echo " fix(client): handle empty response"
echo " chore!: drop python 3.11 support"
echo ""
echo " Add the 'skip-conventional-commit-check' label to bypass this check."
} >&2
exit 1
validate-pr-base:
name: Validate PR base branch
runs-on: ubuntu-latest
if: github.event.pull_request.base.ref == 'main'
permissions:
pull-requests: read
steps:
- name: Check base branch
env:
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
HAS_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'target-main') }}
run: |
# Exempt automated PRs (Stainless codegen, release-please, dependabot, etc.)
case "$PR_AUTHOR" in
stainless-app|stainless-app\[bot\]|release-please\[bot\]|github-actions\[bot\]|dependabot\[bot\])
echo "PR is from automation ($PR_AUTHOR); allowing PR targeting main."
exit 0
;;
esac
if [ "$HAS_LABEL" = "true" ]; then
echo "Found 'target-main' label; allowing PR targeting main."
exit 0
fi
echo "::error title=PR should target 'next'::PRs should target the 'next' branch by default. The 'main' branch is reserved for release-please and Stainless automation. If this PR is an intentional hotfix or automation exception, add the 'target-main' label to bypass this check, or re-target the PR base to 'next'."
exit 1