Add go-subtree source code #5
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
| # ------------------------------------------------------------------------------------ | |
| # Pull Request Management Workflow | |
| # | |
| # Purpose: Automatically applies labels to pull requests based on branch name prefix, | |
| # assigns a default user if none is assigned, and welcomes new contributors | |
| # (excluding known bots/authors) with a friendly comment on PR creation. | |
| # The workflow is hardened to gracefully handle forked PRs where the | |
| # default `GITHUB_TOKEN` has limited permissions (no write access to the | |
| # upstream repository’s issues or PRs). In those cases, the workflow | |
| # skips assigning or commenting and only emits warnings. | |
| # | |
| # Triggers: On PR open, synchronize, reopen, or ready for review. | |
| # | |
| # Maintainer: @icellan | |
| # | |
| # Default Assignee: Set below in the 'DEFAULT_ASSIGNEE' variable. | |
| # | |
| # Known Bots/Authors: The list of known bots/authors to exclude from welcome comments | |
| # is set in the 'knownBots' array in the script section below. | |
| # ------------------------------------------------------------------------------------ | |
| name: pull-request-management | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| # Cancel older runs of the same PR if a new commit is pushed | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| # Minimal read permissions; write permissions are elevated only where needed | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| apply-changes: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Manage PR (labels, assignee, welcome) | |
| uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| /* eslint-disable no-undef */ | |
| const DEFAULT_ASSIGNEE = 'icellan'; // <-- change if needed | |
| // Helpers ------------------------------------------------------- | |
| const pr = context.payload.pull_request; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = pr.number; | |
| const isFromFork = pr.head.repo.owner.login !== owner; | |
| const isIntegrationError = (err) => | |
| err.message && err.message.includes('Resource not accessible by integration'); | |
| // ────────────────────────────────────────────────────────────── | |
| // 1. Label PRs by branch prefix | |
| // ────────────────────────────────────────────────────────────── | |
| try { | |
| const branch = pr.head.ref; | |
| const labelsToApply = []; | |
| const labelMap = [ | |
| { regex: /^feat\//i, label: 'feature' }, | |
| { regex: /^(bug)?fix\//i, label: 'bug-P3' }, | |
| { regex: /^docs\//i, label: 'documentation' }, | |
| { regex: /^chore\//i, label: 'update' }, | |
| { regex: /^test\//i, label: 'test' }, | |
| { regex: /^refactor\//i, label: 'refactor' }, | |
| { regex: /^hotfix\//i, label: 'hot-fix' }, | |
| { regex: /^proto(type)?\//i, label: 'prototype' }, | |
| { regex: /^idea\//i, label: 'idea' }, | |
| { regex: /^question\//i, label: 'question' }, | |
| ]; | |
| for (const { regex, label } of labelMap) { | |
| if (regex.test(branch)) { | |
| labelsToApply.push(label); | |
| } | |
| } | |
| if (labelsToApply.length) { | |
| const { data: existing } = await github.rest.issues.listLabelsOnIssue({ | |
| owner, | |
| repo, | |
| issue_number, | |
| }); | |
| const have = existing.map((l) => l.name); | |
| const toAdd = labelsToApply.filter((l) => !have.includes(l)); | |
| if (toAdd.length) { | |
| await github.rest.issues.addLabels({ owner, repo, issue_number, labels: toAdd }); | |
| console.log(`Added labels: ${toAdd.join(', ')}`); | |
| } | |
| } | |
| } catch (error) { | |
| core.warning(`Label application failed: ${error.message}`); | |
| } | |
| // ────────────────────────────────────────────────────────────── | |
| // 2. Assign PR to default assignee if none is assigned | |
| // ────────────────────────────────────────────────────────────── | |
| try { | |
| if (!pr.assignees || pr.assignees.length === 0) { | |
| if (isFromFork) { | |
| console.warn(`Skipping assignee because PR is from fork and token lacks permission (actor: ${context.actor})`); | |
| } else { | |
| await github.rest.issues.addAssignees({ | |
| owner, | |
| repo, | |
| issue_number, | |
| assignees: [DEFAULT_ASSIGNEE], | |
| }); | |
| console.log(`Assigned PR to ${DEFAULT_ASSIGNEE}`); | |
| } | |
| } | |
| } catch (error) { | |
| if (isIntegrationError(error) && isFromFork) { | |
| console.warn('Skipping assignee due to integration permission limits on fork PR.'); | |
| } else { | |
| core.setFailed(`Assigning PR failed: ${error.message}`); | |
| } | |
| } | |
| // ────────────────────────────────────────────────────────────── | |
| // 3. Welcome new contributors with a friendly comment | |
| // ────────────────────────────────────────────────────────────── | |
| try { | |
| const author = pr.user.login; | |
| const knownBots = ['dependabot[bot]', 'mergify[bot]', 'copilot[bot]', 'Copilot', DEFAULT_ASSIGNEE]; | |
| const shouldWelcome = !knownBots.includes(author) && context.payload.action === 'opened'; | |
| if (shouldWelcome) { | |
| if (isFromFork) { | |
| console.warn('Skipping welcome comment: PR is from fork and token lacks permission to comment.'); | |
| } else { | |
| const welcomeBody = `\n👋 **Welcome, @${author}!**\n\nThanks for opening your first pull request in **${owner}/${repo}**. \nA maintainer will review your contribution shortly.\n\n_If you have any questions feel free to reach out!_`; | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number, | |
| body: welcomeBody, | |
| }); | |
| console.log('Posted welcome comment.'); | |
| } | |
| } | |
| } catch (error) { | |
| if (isIntegrationError(error) && isFromFork) { | |
| console.warn('Skipping welcome comment due to integration permission limits on fork PR.'); | |
| } else { | |
| core.setFailed(`Posting welcome comment failed: ${error.message}`); | |
| } | |
| } |