Fix /run-skipped-ci command to only run minimum dependency tests #18
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: Run Full CI Suite | |
| on: | |
| issue_comment: | |
| types: [created] | |
| # Prevent concurrent runs per PR | |
| concurrency: | |
| group: full-ci-${{ github.event.issue.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| trigger-full-ci: | |
| # Only run on PR comments that match the command | |
| if: | | |
| github.event.issue.pull_request && | |
| ( | |
| startsWith(github.event.comment.body, '/run-skipped-ci') || | |
| contains(github.event.comment.body, '\n/run-skipped-ci') | |
| ) | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| actions: write | |
| steps: | |
| - name: Check if user has write access | |
| id: check_access | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| try { | |
| const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| username: context.actor | |
| }); | |
| const hasAccess = ['admin', 'write'].includes(permission.permission); | |
| console.log(`User ${context.actor} has permission: ${permission.permission}`); | |
| if (!hasAccess) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: `@${context.actor} Sorry, only repository collaborators with write access can trigger full CI runs. 🔒` | |
| }); | |
| } | |
| return hasAccess; | |
| } catch (error) { | |
| console.error('Error checking permissions:', error); | |
| return false; | |
| } | |
| - name: Exit if no access | |
| if: steps.check_access.outputs.result == 'false' | |
| run: | | |
| echo "User does not have permission to trigger full CI" | |
| exit 1 | |
| - name: Add reaction to comment | |
| uses: peter-evans/create-or-update-comment@v4 | |
| with: | |
| comment-id: ${{ github.event.comment.id }} | |
| reactions: 'rocket' | |
| - name: Get PR details | |
| id: pr | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const pr = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number | |
| }); | |
| return { | |
| ref: pr.data.head.ref, | |
| sha: pr.data.head.sha | |
| }; | |
| - name: Trigger all workflows and collect results | |
| id: trigger_workflows | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prData = ${{ steps.pr.outputs.result }}; | |
| const workflows = [ | |
| 'main.yml', | |
| 'examples.yml', | |
| 'pro-integration-tests.yml', | |
| 'pro-package-tests.yml' | |
| ]; | |
| const succeeded = []; | |
| const failed = []; | |
| // Trigger all workflows | |
| for (const workflowId of workflows) { | |
| try { | |
| await github.rest.actions.createWorkflowDispatch({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| workflow_id: workflowId, | |
| ref: prData.ref | |
| }); | |
| console.log(`✅ Triggered ${workflowId}`); | |
| succeeded.push(workflowId); | |
| } catch (error) { | |
| console.error(`❌ Failed to trigger ${workflowId}:`, error.message); | |
| failed.push({ workflow: workflowId, error: error.message }); | |
| } | |
| } | |
| // Wait a bit for workflows to queue | |
| if (succeeded.length > 0) { | |
| console.log('Waiting 5 seconds for workflows to queue...'); | |
| await new Promise(resolve => setTimeout(resolve, 5000)); | |
| } | |
| // Verify workflows are queued/running | |
| const verified = []; | |
| const notFound = []; | |
| if (succeeded.length > 0) { | |
| const runs = await github.rest.actions.listWorkflowRunsForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| per_page: 100, | |
| created: `>${new Date(Date.now() - 60000).toISOString()}` | |
| }); | |
| for (const workflowId of succeeded) { | |
| const found = runs.data.workflow_runs.some(run => | |
| run.path === `.github/workflows/${workflowId}` && | |
| run.head_sha === prData.sha && | |
| run.event === 'workflow_dispatch' | |
| ); | |
| if (found) { | |
| verified.push(workflowId); | |
| } else { | |
| notFound.push(workflowId); | |
| } | |
| } | |
| } | |
| // Build the comment body based on actual results | |
| let status = '✅ **Successfully triggered and verified all workflows**'; | |
| if (failed.length > 0 && notFound.length > 0) { | |
| status = '❌ **Failed to trigger or verify workflows**'; | |
| } else if (failed.length > 0) { | |
| status = '⚠️ **Some workflows failed to trigger**'; | |
| } else if (notFound.length > 0) { | |
| status = '⚠️ **Workflows triggered but not yet verified**'; | |
| } | |
| const verifiedList = verified.length > 0 ? verified.map(w => `- ✅ ${w}`).join('\n') : ''; | |
| const notFoundList = notFound.length > 0 ? `\n\n**Triggered but not yet queued (may still start):**\n${notFound.map(w => `- ⏳ ${w}`).join('\n')}` : ''; | |
| const failedList = failed.length > 0 ? `\n\n**Failed to trigger:**\n${failed.map(f => `- ❌ ${f.workflow}: ${f.error}`).join('\n')}` : ''; | |
| const body = `🚀 **Full CI Suite Results** | |
| ${status} | |
| ${verifiedList ? `**Verified workflows:**\n${verifiedList}` : ''}${notFoundList}${failedList} | |
| ${verified.length > 0 ? `\nThese will run all CI jobs including those normally skipped on PRs: | |
| - ✅ Minimum dependency versions (Ruby 3.2, Node 20) | |
| - ✅ All example app tests | |
| - ✅ Pro package integration tests | |
| - ✅ Pro package unit tests | |
| View progress in the [Actions tab](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions).` : ''}`; | |
| // Post the comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: body | |
| }); | |
| // Fail the job if any workflows failed to trigger | |
| if (failed.length > 0) { | |
| core.setFailed(`Failed to trigger ${failed.length} workflow(s): ${failed.map(f => f.workflow).join(', ')}`); | |
| } |