name: "Pull Request Labeler"
on:
  pull_request_target:
    types: [opened, synchronize]
# Do not execute arbitrary code on this workflow.
# See warnings at https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  labeler:
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-24.04-arm
    steps:
    - name: Auto-label PR
      uses: actions/github-script@v9
      with:
        script: |
          const branch = context.payload.pull_request.head.ref;
          const title = context.payload.pull_request.title || '';
          const labels = new Set();

          // Match branch prefix (e.g. feat/..., fix/..., chore-something)
          // Also parse conventional-commit-style PR titles as a fallback
          const branchPrefix = branch.split(/[\/\-_]/)[0].toLowerCase();
          const titlePrefix = (title.match(/^(\w+)[\(:]/) || [])[1]?.toLowerCase();

          const prefix = branchPrefix || titlePrefix;

          // Map prefixes to changelog-aligned labels
          const prefixMap = {
            'feat':     'enhancement',
            'feature':  'enhancement',
            'fix':      'bugfix',
            'bug':      'bugfix',
            'bugfix':   'bugfix',
            'hotfix':   'bugfix',
            'refactor': 'refactor',
            'chore':    'chore',
            'build':    'build',
            'ci':       'ci',
            'test':     'testing',
            'tests':    'testing',
            'docs':     'documentation',
            'doc':      'documentation',
            'perf':     'enhancement',
            'style':    'refactor',
            'repo':     'repo',
            'release':  'release',
          };

          // Label from branch prefix
          if (prefixMap[branchPrefix]) labels.add(prefixMap[branchPrefix]);

          // Label from PR title prefix (if different from branch)
          if (titlePrefix && prefixMap[titlePrefix] && !labels.has(prefixMap[titlePrefix])) {
            labels.add(prefixMap[titlePrefix]);
          }

          // Also label 'repo' if .github/ or build-logic/ files were changed
          if (!labels.has('repo') && !labels.has('ci') && !labels.has('build')) {
            try {
              const files = await github.paginate(
                github.rest.pulls.listFiles,
                { owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, per_page: 100 },
                (res) => res.data.map(f => f.filename)
              );
              if (files.some(f => f.startsWith('.github/'))) labels.add('repo');
              if (files.some(f => f.startsWith('build-logic/'))) labels.add('build');
            } catch (e) {
              core.warning(`Could not list PR files (rate limited?): ${e.message}`);
            }
          }

          if (labels.size > 0) {
            const labelArray = [...labels];
            core.info(`Applying labels: ${labelArray.join(', ')}`);
            try {
              await github.rest.issues.addLabels({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.payload.pull_request.number,
                labels: labelArray,
              });
            } catch (e) {
              core.warning(`Could not apply labels (rate limited?): ${e.message}`);
            }
          } else {
            core.info('No labels matched for this PR.');
          }
