[mcp3204] differential mode support #2432
Workflow file for this run
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 Label PR | |
| on: | |
| # Runs only on pull_request_target due to having access to a App token. | |
| # This means PRs from forks will not be able to alter this workflow to get the tokens | |
| pull_request_target: | |
| types: [opened, reopened, synchronize, edited] | |
| # Allow manual triggering for recheck functionality | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'Pull Request number to process' | |
| required: true | |
| type: number | |
| permissions: | |
| pull-requests: write | |
| contents: read | |
| env: | |
| BOT_NAME: "esphome[bot]" | |
| jobs: | |
| label: | |
| runs-on: ubuntu-latest | |
| if: github.event.action != 'labeled' || github.event.sender.type != 'Bot' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| - name: Generate a token | |
| id: generate-token | |
| uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 | |
| with: | |
| app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }} | |
| private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} | |
| - name: Auto Label PR | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| env: | |
| PR_NUMBER: ${{ github.event.inputs.pr_number || github.event.number }} | |
| with: | |
| github-token: ${{ steps.generate-token.outputs.token }} | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const pr_number = parseInt(process.env.PR_NUMBER); | |
| console.log('Processing PR #' + pr_number); | |
| // Get current labels | |
| const { data: currentLabelsData } = await github.rest.issues.listLabelsOnIssue({ | |
| owner, | |
| repo, | |
| issue_number: pr_number | |
| }); | |
| const currentLabels = currentLabelsData.map(label => label.name); | |
| // Define managed labels that this workflow controls | |
| const managedLabels = currentLabels.filter(label => | |
| [ | |
| 'current', | |
| 'next', | |
| 'has-parent', | |
| 'wrong-base-branch', | |
| 'labeller-recheck' | |
| ].includes(label) || | |
| label.startsWith('component: ') | |
| ); | |
| console.log('Current labels:', currentLabels.join(', ')); | |
| console.log('Managed labels:', managedLabels.join(', ')); | |
| const labels = new Set(); | |
| // Strategy: Branch-based labeling | |
| let baseRef, prBody; | |
| if (context.eventName === 'workflow_dispatch') { | |
| // Get PR details when called via workflow_dispatch | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner, | |
| repo, | |
| pull_number: pr_number | |
| }); | |
| baseRef = pr.base.ref; | |
| prBody = pr.body || ''; | |
| } else { | |
| // Use context when called via pull_request_target | |
| baseRef = context.payload.pull_request.base.ref; | |
| prBody = context.payload.pull_request.body || ''; | |
| } | |
| console.log('Target branch:', baseRef); | |
| if (baseRef === 'current') { | |
| labels.add('current'); | |
| } else if (baseRef === 'next') { | |
| labels.add('next'); | |
| } | |
| // Strategy: Parent PR detection | |
| // prBody is already set above based on event type | |
| // Look for ESPHome PR links in PR body | |
| // Patterns to match: | |
| // - https://github.com/esphome/esphome/pull/1234 | |
| // - esphome/esphome#1234 | |
| const esphomePrPatterns = [ | |
| /https:\/\/github\.com\/esphome\/esphome\/pull\/(\d+)/, | |
| /esphome\/esphome#(\d+)/ | |
| ]; | |
| const hasEsphomeLink = esphomePrPatterns.some(pattern => | |
| pattern.test(prBody) | |
| ); | |
| console.log('PR Body contains ESPHome link:', hasEsphomeLink); | |
| if (hasEsphomeLink) { | |
| labels.add('has-parent'); | |
| // Extract parent PR number and fetch its labels | |
| for (const pattern of esphomePrPatterns) { | |
| const match = prBody.match(pattern); | |
| if (!match) continue; // Skip to next pattern if no match | |
| try { | |
| // Extract PR number from the capture group | |
| const parentPrNumber = match[1]; | |
| console.log('Found parent PR number:', parentPrNumber); | |
| // Fetch labels from the parent PR in esphome/esphome repository | |
| const { data: parentLabels } = await github.rest.issues.listLabelsOnIssue({ | |
| owner: 'esphome', | |
| repo: 'esphome', | |
| issue_number: parseInt(parentPrNumber) | |
| }); | |
| console.log('Parent PR labels:', parentLabels.map(l => l.name).join(', ')); | |
| // Add all "component: " labels from parent PR | |
| parentLabels.forEach(label => { | |
| if (label.name.startsWith('component: ')) { | |
| labels.add(label.name); | |
| console.log('Added component label from parent:', label.name); | |
| } | |
| }); | |
| break; // Only process the first match | |
| } catch (error) { | |
| console.log('Failed to fetch parent PR labels:', error.message); | |
| } | |
| } | |
| } | |
| // Convert Set to Array | |
| const finalLabels = Array.from(labels); | |
| // Strategy: Wrong base branch detection | |
| const hasParent = finalLabels.includes('has-parent'); | |
| const isCurrent = finalLabels.includes('current'); | |
| if (hasParent && isCurrent) { | |
| finalLabels.push('wrong-base-branch'); | |
| console.log('Added wrong-base-branch label: has-parent targeting current branch'); | |
| } | |
| console.log('Computed labels:', finalLabels.join(', ')); | |
| // Add new labels | |
| if (finalLabels.length > 0) { | |
| console.log(`Adding labels: ${finalLabels.join(', ')}`); | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number: pr_number, | |
| labels: finalLabels | |
| }); | |
| } | |
| // Request changes if wrong base branch is detected | |
| if (hasParent && isCurrent) { | |
| console.log('Requesting changes due to wrong base branch'); | |
| await github.rest.pulls.createReview({ | |
| owner, | |
| repo, | |
| pull_number: pr_number, | |
| event: 'REQUEST_CHANGES', | |
| body: 'As this is a feature matched with a PR in https://github.com/esphome/esphome, please target your PR to the `next` branch and rebase.' | |
| }); | |
| } else { | |
| // Check if we should dismiss any existing review from this bot | |
| const { data: reviews } = await github.rest.pulls.listReviews({ | |
| owner, | |
| repo, | |
| pull_number: pr_number | |
| }); | |
| // Find the most recent review from this bot that requested changes for wrong base branch | |
| const botReview = reviews | |
| .filter(review => | |
| review.user.login === process.env.BOT_NAME && | |
| review.state === 'CHANGES_REQUESTED' && | |
| review.body && review.body.includes('target your PR to the `next` branch') | |
| ) | |
| .sort((a, b) => new Date(b.submitted_at) - new Date(a.submitted_at))[0]; | |
| if (botReview) { | |
| console.log('Dismissing previous bot review as labels are now correct'); | |
| await github.rest.pulls.dismissReview({ | |
| owner, | |
| repo, | |
| pull_number: pr_number, | |
| review_id: botReview.id, | |
| message: 'Base branch has been corrected - dismissing previous review.' | |
| }); | |
| } | |
| } | |
| // Remove old managed labels that are no longer needed | |
| const labelsToRemove = managedLabels.filter(label => | |
| !finalLabels.includes(label) | |
| ); | |
| for (const label of labelsToRemove) { | |
| console.log(`Removing label: ${label}`); | |
| try { | |
| await github.rest.issues.removeLabel({ | |
| owner, | |
| repo, | |
| issue_number: pr_number, | |
| name: label | |
| }); | |
| } catch (error) { | |
| console.log(`Failed to remove label ${label}:`, error.message); | |
| } | |
| } |