[Sandbox] CoHDI #143
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: Vote Monitor and Onboarding Automation | |
| on: | |
| issues: | |
| types: [labeled, unlabeled] | |
| workflow_dispatch: | |
| inputs: | |
| process_existing: | |
| description: 'Process existing issues with gitvote/passed label' | |
| required: false | |
| default: false | |
| type: boolean | |
| permissions: | |
| issues: write | |
| contents: read | |
| jobs: | |
| create-onboarding-issue: | |
| runs-on: ubuntu-latest | |
| if: | | |
| (github.event_name == 'issues' && (github.event.action == 'labeled' || github.event.action == 'unlabeled')) || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.process_existing == 'true') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Extract project name and create onboarding issue | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { createOnboardingIssue, commentAndClose } = require('./scripts/create-onboarding-issue.js'); | |
| if (context.eventName === 'workflow_dispatch') { | |
| // Manual trigger - process existing issues | |
| console.log('🔍 Processing existing issues with gitvote/passed label...'); | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'gitvote/passed' | |
| }); | |
| console.log(`Found ${issues.data.length} issues with gitvote/passed label`); | |
| for (const issue of issues.data) { | |
| const sandboxMatch = issue.title.match(/^\[Sandbox\]\s*(.+)$/); | |
| if (!sandboxMatch) { | |
| console.log(`⚠️ Skipping issue #${issue.number} - not a sandbox issue`); | |
| continue; | |
| } | |
| const projectName = sandboxMatch[1].trim(); | |
| console.log(`📝 Processing issue #${issue.number}: "${projectName}"`); | |
| const hasUnsignedCA = (issue.labels || []).some(l => (typeof l === 'string' ? l : l.name) === 'contribution-agreement/unsigned'); | |
| if (hasUnsignedCA) { | |
| console.log(`⏸️ Issue #${issue.number} has contribution-agreement/unsigned; posting CA reminder and skipping onboarding creation.`); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: `The TOC vote for ${projectName} has passed! 🎉 Next step: Please finalize the Contribution Agreement. This is required before official CNCF on-boarding can begin. Please reach out to CNCF Staff for assistance.` | |
| }); | |
| continue; | |
| } | |
| try { | |
| const result = await createOnboardingIssue(github, context, projectName, issue.number); | |
| if (result.alreadyExists) { | |
| console.log(`⏭️ Skipped creating onboarding issue for #${issue.number} - already exists: #${result.issueNumber} (${result.state})`); | |
| continue; | |
| } | |
| await commentAndClose(github, context, issue.number, result.issueNumber, projectName); | |
| console.log(`✅ Processed issue #${issue.number} -> created onboarding issue #${result.issueNumber}`); | |
| } catch (error) { | |
| console.error(`❌ Error processing issue #${issue.number}:`, error.message); | |
| } | |
| } | |
| } else { | |
| // Label add/remove trigger - process single issue based on current labels | |
| const issue = context.payload.issue; | |
| // Ensure we only proceed for Sandbox issues with a passed vote | |
| const labels = issue.labels || []; | |
| const labelNames = labels.map(l => (typeof l === 'string' ? l : l.name)); | |
| const hasVotePassed = labelNames.includes('gitvote/passed'); | |
| const hasUnsignedCA = labelNames.includes('contribution-agreement/unsigned'); | |
| if (!hasVotePassed) { | |
| console.log('ℹ️ Skipping: issue does not have gitvote/passed label.'); | |
| return; | |
| } | |
| // Extract project name from issue title | |
| const title = issue.title; | |
| const sandboxMatch = title.match(/^\[Sandbox\]\s*(.+)$/); | |
| if (!sandboxMatch) { | |
| console.log('ℹ️ Skipping: not a Sandbox application issue.'); | |
| return; | |
| } | |
| const projectName = sandboxMatch[1].trim(); | |
| if (hasUnsignedCA) { | |
| console.log('⏸️ CA unsigned label present; posting reminder and not creating onboarding.'); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: `The TOC vote for ${projectName} has passed! 🎉 Next step: Please finalize the Contribution Agreement. This is required before official CNCF on-boarding can begin. Please reach out to CNCF Staff for assistance.` | |
| }); | |
| return; | |
| } | |
| console.log('🎉 Vote passed and CA requirement satisfied. Creating onboarding issue...'); | |
| const result = await createOnboardingIssue(github, context, projectName, issue.number); | |
| if (result.alreadyExists) { | |
| console.log(`⏭️ Onboarding issue already exists for "${projectName}": #${result.issueNumber} (${result.state})`); | |
| return; | |
| } | |
| await commentAndClose(github, context, issue.number, result.issueNumber, projectName); | |
| console.log(`✅ Successfully created onboarding issue #${result.issueNumber} and closed issue #${issue.number}`); | |
| } |