feat: add end-to-end tests and fix benchmark framework targets #160
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto-Fix Commit Messages | ||
| on: | ||
| workflow_run: | ||
| workflows: ["Commit Message Lint"] | ||
| types: [completed] | ||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }} | ||
| cancel-in-progress: true | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| jobs: | ||
| auto-fix-commits: | ||
| name: Squash and Fix Commit Messages | ||
| if: | | ||
| github.event.workflow_run.conclusion == 'failure' && | ||
| github.event.workflow_run.event == 'pull_request' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Get PR information | ||
| id: get-pr | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| // Get PR associated with the head branch | ||
| const headBranch = '${{ github.event.workflow_run.head_branch }}'; | ||
| const headSha = '${{ github.event.workflow_run.head_sha }}'; | ||
| core.info(`Looking for PR with head branch: ${headBranch}, sha: ${headSha}`); | ||
| const prs = await github.rest.pulls.list({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| head: `${context.repo.owner}:${headBranch}`, | ||
| state: 'open' | ||
| }); | ||
| if (prs.data.length === 0) { | ||
| core.setFailed('No open PR found for this branch. This may occur if the workflow triggered before the PR was opened, or if the branch name does not match any open PR. Please verify that the PR exists and the branch name is correct.'); | ||
| return; | ||
| } | ||
| const pr = prs.data[0]; | ||
| core.info(`Found PR #${pr.number}: ${pr.title}`); | ||
| // Verify PR title follows conventional commits (should be auto-fixed already) | ||
| const pattern = /^(feat|fix|docs|refactor|perf|test|chore|ci|style)(\(.+\))?!?: .+/; | ||
| if (!pattern.test(pr.title)) { | ||
| core.setFailed(`PR title does not follow conventional commits: ${pr.title}`); | ||
| return; | ||
| } | ||
| // Don't modify PRs from forks (security) | ||
| if (pr.head.repo.full_name !== pr.base.repo.full_name) { | ||
| core.setFailed('Cannot auto-fix commits from forked repositories'); | ||
| return; | ||
| } | ||
| core.setOutput('pr_number', pr.number); | ||
| core.setOutput('pr_title', pr.title); | ||
| core.setOutput('head_branch', pr.head.ref); | ||
| core.setOutput('base_branch', pr.base.ref); | ||
| core.setOutput('head_sha', pr.head.sha); | ||
| - name: Checkout PR branch | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ steps.get-pr.outputs.head_branch }} | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Configure Git | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| - name: Count commits ahead of base | ||
| id: count-commits | ||
| run: | | ||
| BASE_BRANCH="${{ steps.get-pr.outputs.base_branch }}" | ||
| git fetch origin "$BASE_BRANCH" | ||
| COMMIT_COUNT=$(git rev-list --count "origin/$BASE_BRANCH..HEAD") | ||
| echo "commit_count=$COMMIT_COUNT" >> $GITHUB_OUTPUT | ||
| echo "Found $COMMIT_COUNT commits ahead of $BASE_BRANCH" | ||
| - name: Squash commits | ||
| id: squash-commits | ||
| if: steps.count-commits.outputs.commit_count > 1 | ||
| run: | | ||
| BASE_BRANCH="${{ steps.get-pr.outputs.base_branch }}" | ||
| PR_TITLE="${{ steps.get-pr.outputs.pr_title }}" | ||
| COMMIT_COUNT="${{ steps.count-commits.outputs.commit_count }}" | ||
| echo "Squashing $COMMIT_COUNT commits into one..." | ||
| # Reset to base branch keeping all changes staged | ||
| git reset --soft "origin/$BASE_BRANCH" | ||
| # Create the squashed commit with the PR title | ||
| git commit -m "$PR_TITLE | ||
| Squashed $COMMIT_COUNT commits automatically by GitHub Actions. | ||
| This ensures the commit message follows conventional commits format. | ||
| Co-Authored-By: github-actions[bot] <github-actions[bot]@users.noreply.github.com>" | ||
| echo "Squash complete!" | ||
| echo "changes_made=true" >> $GITHUB_OUTPUT | ||
| - name: Fix single commit message | ||
| id: fix-single-commit | ||
| if: steps.count-commits.outputs.commit_count == 1 | ||
| run: | | ||
| PR_TITLE="${{ steps.get-pr.outputs.pr_title }}" | ||
| CURRENT_MSG=$(git log -1 --format=%B) | ||
| # Check if commit message already matches PR title | ||
| FIRST_LINE=$(echo "$CURRENT_MSG" | head -1) | ||
| if [ "$FIRST_LINE" = "$PR_TITLE" ]; then | ||
| echo "Commit message already matches PR title, no fix needed" | ||
| echo "changes_made=false" >> $GITHUB_OUTPUT | ||
| exit 0 | ||
| fi | ||
| echo "Amending commit message to match PR title..." | ||
| # Preserve the body if it exists (skip subject and blank line, then trim whitespace) | ||
| BODY=$(echo "$CURRENT_MSG" | tail -n +3 | awk '{$1=$1};1') | ||
| if [ -n "$BODY" ]; then | ||
| git commit --amend -m "$PR_TITLE | ||
| $BODY" | ||
| else | ||
| git commit --amend -m "$PR_TITLE | ||
| Commit message auto-fixed by GitHub Actions. | ||
| Co-Authored-By: github-actions[bot] <github-actions[bot]@users.noreply.github.com>" | ||
| fi | ||
| echo "changes_made=true" >> $GITHUB_OUTPUT | ||
| - name: Force push fixed commits | ||
| if: steps.squash-commits.outputs.changes_made == 'true' || steps.fix-single-commit.outputs.changes_made == 'true' | ||
| run: | | ||
| HEAD_BRANCH="${{ steps.get-pr.outputs.head_branch }}" | ||
| HEAD_SHA="${{ steps.get-pr.outputs.head_sha }}" | ||
| echo "Force pushing to $HEAD_BRANCH..." | ||
| git push origin "$HEAD_BRANCH" --force-with-lease="$HEAD_BRANCH:$HEAD_SHA" | ||
| - name: Comment on PR | ||
| if: steps.squash-commits.outputs.changes_made == 'true' || steps.fix-single-commit.outputs.changes_made == 'true' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const prNumber = ${{ steps.get-pr.outputs.pr_number }}; | ||
| const commitCount = ${{ steps.count-commits.outputs.commit_count }}; | ||
| const prTitle = `${{ steps.get-pr.outputs.pr_title }}`; | ||
| let message; | ||
| if (commitCount > 1) { | ||
| message = `### Commit Messages Auto-Fixed | ||
| The commitlint check failed because one or more commit messages didn't follow [Conventional Commits](https://www.conventionalcommits.org/) format. | ||
| **Action taken** — Squashed ${commitCount} commits into a single commit using the PR title as the commit message. | ||
| **New commit message** | ||
| \`\`\` | ||
| ${prTitle} | ||
| \`\`\` | ||
| The PR branch has been force-pushed with the fixed commit. If you had local changes, you may need to \`git pull --rebase\`.`; | ||
| } else { | ||
| message = `### Commit Message Auto-Fixed | ||
| The commitlint check failed because the commit message didn't follow [Conventional Commits](https://www.conventionalcommits.org/) format. | ||
| **Action taken** — Amended the commit message to use the PR title. | ||
| **New commit message** | ||
| \`\`\` | ||
| ${prTitle} | ||
| \`\`\` | ||
| The PR branch has been force-pushed with the fixed commit. If you had local changes, you may need to \`git pull --rebase\`.`; | ||
| } | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| body: message | ||
| }); | ||