/
githubmirror
/
novu
Обзор
Документация
Войти
/
githubmirror
/
novu
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
next
.github/workflows/conventional-commit.yml
220 строк
10 KB
Himanshu Garg
chore(root): changes for release and bumping up node to a security release (#12250)
07 авг 2026, 11:06
Не верифицирован
07 авг 2026, 11:06
db33feb
Код
Авторство
О чём код?
name: "Lint PR title" on: pull_request: types: - opened - edited - synchronize permissions: pull-requests: write jobs: main: name: Validate PR titles runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - name: Install pnpm uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 # pnpm v11 requires Node.js >= 22.13. The default runner image ships Node # 20, which causes `pnpm m ls` to crash with ERR_UNKNOWN_BUILTIN_MODULE # (node:sqlite) and leaves the SCOPES env empty, failing this lint. - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '22.23.0' - name: Generate scopes id: generate_scopes run: | scopes=$(pnpm m ls --json --depth=-1 | grep "name" | sed -e 's/.*\: \(.*\)/\1/' -e 's/@novu\///g' -e 's/[",]//g') # Mintlify docs site (docs/) is not a pnpm workspace package. scopes="$scopes"$'\n'"docs" echo 'SCOPES<<EOF' >> $GITHUB_ENV echo "$scopes" >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - name: Detect docs-only PR id: detect_docs env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} run: | # Documentation-only PRs (only touching the Mintlify docs/ site) are # exempt from the "fixes NV-XXX" Linear ticket requirement below. # `--paginate` walks every page so large PRs (>100 files) aren't # misclassified as docs-only. files=$(gh api --paginate "repos/${{ github.repository }}/pulls/$PR_NUMBER/files" --jq '.[].path') echo "Changed files:" echo "$files" non_docs=$(echo "$files" | grep -v '^docs/' || true) if [ -n "$files" ] && [ -z "$non_docs" ]; then echo "docs_only=true" >> "$GITHUB_OUTPUT" echo "docs-only PR — skipping Linear ticket enforcement." else echo "docs_only=false" >> "$GITHUB_OUTPUT" fi - name: Check if PR author is team member id: check_team_member run: | author="${{ github.event.pull_request.user.login }}" echo "Checking if $author is a team member..." # Trusted bot accounts are treated as team members trusted_bots=("cursor[bot]") for bot in "${trusted_bots[@]}"; do if [[ "$author" == "$bot" ]]; then echo "is_team_member=true" >> $GITHUB_OUTPUT echo "$author is a trusted bot, treating as team member" exit 0 fi done # Use GitHub API to check user permissions encoded_author=$(printf '%s' "$author" | jq -sRr @uri) response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/repos/${{ github.repository }}/collaborators/${encoded_author}/permission") permission=$(echo "$response" | jq -r '.permission // "none"') echo "Permission level: $permission" if [[ "$permission" == "admin" || "$permission" == "write" ]]; then echo "is_team_member=true" >> $GITHUB_OUTPUT echo "$author is a team member" else echo "is_team_member=false" >> $GITHUB_OUTPUT echo "$author is not a team member" fi - name: Extract Linear ticket from branch and auto-fix PR title id: auto_fix_linear_ticket if: steps.check_team_member.outputs.is_team_member == 'true' && steps.detect_docs.outputs.docs_only != 'true' env: PR_TITLE: ${{ github.event.pull_request.title }} BRANCH_NAME: ${{ github.event.pull_request.head.ref }} run: | branch_name="$BRANCH_NAME" pr_title="$PR_TITLE" echo "Branch name: $branch_name" echo "Current PR title: $pr_title" # Extract ticket ID from branch name (e.g., nv-6051 from nv-6051-bug-steps-liquidjs...) if [[ "$branch_name" =~ ^([a-zA-Z]+-[0-9]+) ]]; then ticket_id="${BASH_REMATCH[1]^^}" # Convert to uppercase echo "Found ticket ID in branch: $ticket_id" # Check if PR title already has the Linear ticket format if [[ "$pr_title" =~ fixes\ [A-Z]+-[0-9]+$ ]]; then echo "PR title already contains Linear ticket ID" echo "needs_update=false" >> $GITHUB_OUTPUT echo "linear_ticket_valid=true" >> $GITHUB_OUTPUT else # Auto-append the Linear ticket ID new_title="$pr_title fixes $ticket_id" echo "Auto-fixing PR title to: $new_title" # Update PR title using GitHub API curl -X PATCH \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" \ -d "$(jq -n --arg title "$new_title" '{title: $title}')" echo "needs_update=true" >> $GITHUB_OUTPUT echo "linear_ticket_valid=true" >> $GITHUB_OUTPUT echo "updated_title=$new_title" >> $GITHUB_OUTPUT fi else echo "No Linear ticket ID found in branch name" # Check if title has Linear ticket format manually added if [[ "$pr_title" =~ fixes\ [A-Z]+-[0-9]+$ ]]; then echo "linear_ticket_valid=true" >> $GITHUB_OUTPUT else echo "linear_ticket_valid=false" >> $GITHUB_OUTPUT echo "linear_error_message=PR title must end with 'fixes TICKET-ID' (e.g., 'fixes NOV-123') or include ticket ID in branch name" >> $GITHUB_OUTPUT fi echo "needs_update=false" >> $GITHUB_OUTPUT fi - name: Validate Linear ticket ID for team members (fallback) id: validate_linear_ticket if: steps.check_team_member.outputs.is_team_member == 'true' && steps.detect_docs.outputs.docs_only != 'true' && steps.auto_fix_linear_ticket.outputs.linear_ticket_valid != 'true' env: PR_TITLE: ${{ github.event.pull_request.title }} run: | pr_title="$PR_TITLE" echo "Validating Linear ticket ID in PR title: $pr_title" # Check if title ends with "fixes TICKET-ID" pattern if [[ "$pr_title" =~ fixes\ [A-Z]+-[0-9]+$ ]]; then echo "linear_ticket_valid=true" >> $GITHUB_OUTPUT echo "Linear ticket ID format is valid" else echo "linear_ticket_valid=false" >> $GITHUB_OUTPUT echo "Linear ticket ID format is invalid" echo "linear_error_message=PR title must end with 'fixes TICKET-ID' (e.g., 'fixes NOV-123') or include ticket ID in branch name" >> $GITHUB_OUTPUT fi - uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5 id: lint_pr_title env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: requireScope: true scopes: | ${{ env.SCOPES }} - uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 # Show success message when PR title was auto-fixed if: steps.auto_fix_linear_ticket.outputs.needs_update == 'true' with: header: pr-title-auto-fixed message: | ✅ **PR title automatically updated!** I found the Linear ticket ID `${{ steps.auto_fix_linear_ticket.outputs.updated_title }}` in your branch name and automatically added it to your PR title. **Updated title:** `${{ steps.auto_fix_linear_ticket.outputs.updated_title }}` - uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 # Show error if either conventional commit validation fails OR Linear ticket validation fails (for team members) if: always() && (steps.lint_pr_title.outputs.error_message != null || (steps.detect_docs.outputs.docs_only != 'true' && steps.check_team_member.outputs.is_team_member == 'true' && steps.auto_fix_linear_ticket.outputs.linear_ticket_valid != 'true' && steps.validate_linear_ticket.outputs.linear_ticket_valid != 'true')) with: header: pr-title-lint-error message: | Hey there and thank you for opening this pull request! 👋 We require pull request titles to follow specific formatting rules and it looks like your proposed title needs to be adjusted. Your PR title is: `${{ github.event.pull_request.title }}` **Requirements:** 1. Follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) 2. ${{ steps.check_team_member.outputs.is_team_member == 'true' && steps.detect_docs.outputs.docs_only != 'true' && 'As a team member, include Linear ticket ID at the end: `fixes TICKET-ID` or include it in your branch name' || '' }} **Expected format:** `feat(scope): Add fancy new feature${{ steps.check_team_member.outputs.is_team_member == 'true' && steps.detect_docs.outputs.docs_only != 'true' && ' fixes NOV-123' || '' }}` **Details:** ${{ steps.lint_pr_title.outputs.error_message != null && steps.lint_pr_title.outputs.error_message || '' }} ${{ steps.validate_linear_ticket.outputs.linear_error_message != null && steps.validate_linear_ticket.outputs.linear_error_message || '' }} # Delete previous comments when all issues have been resolved - if: ${{ steps.lint_pr_title.outputs.error_message == null && (steps.detect_docs.outputs.docs_only == 'true' || steps.check_team_member.outputs.is_team_member != 'true' || steps.auto_fix_linear_ticket.outputs.linear_ticket_valid == 'true' || steps.validate_linear_ticket.outputs.linear_ticket_valid == 'true') }} uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 with: header: pr-title-lint-error delete: true # Delete auto-fix comment after a while (on subsequent updates) - if: ${{ steps.auto_fix_linear_ticket.outputs.needs_update != 'true' }} uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 with: header: pr-title-auto-fixed delete: true