feat(ci): add doc review pipeline with auto-labeling and Copilot review #29
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 PRs | |
| on: | |
| pull_request: | |
| types: [opened, synchronize] | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to label' | |
| required: true | |
| type: number | |
| permissions: {} | |
| concurrency: | |
| group: auto-label-${{ github.event.number || inputs.pr_number }} | |
| cancel-in-progress: true | |
| jobs: | |
| auto-label: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| # Skip draft PRs and fork PRs (workflow_dispatch always runs) | |
| if: | | |
| github.event_name == 'workflow_dispatch' || | |
| (!github.event.pull_request.draft && | |
| github.event.pull_request.head.repo.full_name == github.repository) | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| sparse-checkout: | | |
| content | |
| data/products.yml | |
| scripts/lib/content-utils.js | |
| .github/scripts/workflow-utils.js | |
| package.json | |
| sparse-checkout-cone-mode: false | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: 22 | |
| - name: Install js-yaml | |
| run: npm install --no-save --ignore-scripts --no-package-lock --legacy-peer-deps js-yaml | |
| - name: Apply product labels | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const { | |
| getProductLabelMap, | |
| matchFilesToLabels, | |
| } = await import( | |
| `${process.cwd()}/.github/scripts/workflow-utils.js` | |
| ); | |
| const prNumber = | |
| context.issue.number || | |
| Number('${{ inputs.pr_number }}'); | |
| if (!prNumber) { | |
| core.setFailed('No PR number available'); | |
| return; | |
| } | |
| // --- Build path-to-label mapping from products.yml --- | |
| const pathToLabel = await getProductLabelMap(); | |
| core.info( | |
| `Loaded ${pathToLabel.size} path-to-label mappings from products.yml` | |
| ); | |
| // --- Get changed files from the PR (paginated) --- | |
| const files = await github.paginate( | |
| github.rest.pulls.listFiles, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber, | |
| per_page: 100, | |
| } | |
| ); | |
| const changedFiles = files.map(f => f.filename); | |
| core.info(`PR has ${changedFiles.length} changed files`); | |
| // --- Match files to product labels --- | |
| const labelsToAdd = matchFilesToLabels(changedFiles, pathToLabel); | |
| if (labelsToAdd.size === 0) { | |
| core.info('No product labels to add'); | |
| return; | |
| } | |
| // --- Get existing PR labels to avoid duplicates --- | |
| const { data: prData } = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const existingLabels = new Set(prData.labels.map(l => l.name)); | |
| const newLabels = [...labelsToAdd].filter( | |
| l => !existingLabels.has(l) | |
| ); | |
| if (newLabels.length === 0) { | |
| core.info('All matching labels already present'); | |
| return; | |
| } | |
| // --- Apply labels --- | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| labels: newLabels, | |
| }); | |
| core.info(`Added labels: ${newLabels.join(', ')}`); |