name: validate-milestone

permissions:
  contents: read
  pull-requests: read

on:
  pull_request:
    types: [opened, synchronize, milestoned, demilestoned, edited]

jobs:
  validate-milestone:
    runs-on: ubuntu-24.04
    timeout-minutes: 5
    steps:
      - name: Validate milestone matches docker next version
        uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
        env:
          MILESTONE: ${{ github.event.pull_request.milestone.title }}
        with:
          script: |
            const files = await github.paginate(github.rest.pulls.listFiles, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
            });
            core.info(`Modified files: ${files.map(f => f.filename).join(', ')}`);

            const touchesVersions = files.some(f => f.filename === 'releases/versions.yaml');
            core.info(`Touches version: ${touchesVersions}`);

            // Use the PR's version when it bumps the file, base branch otherwise.
            // It's fine to trust the author in this case, it's not meant to be
            // a security gate, just a helpful check for maintainers.
            const ref = touchesVersions
              ? context.payload.pull_request.head.sha
              : context.payload.pull_request.base.ref;

            core.info(`Base ref: ${ref}`);

            const resp = await github.rest.repos.getContent({
              owner: context.repo.owner,
              repo: context.repo.repo,
              path: 'releases/versions.yaml',
              ref,
            });
            const content = Buffer.from(resp.data.content, resp.data.encoding).toString('utf8');
            const line = content.split('\n').find(l => l.includes('next:'));
            if (!line) {
              core.setFailed('Could not find docker.next in releases/versions.yaml');
              return;
            }
            const expected = line.trim().replace('next: ', '').replaceAll('"', '');
            const milestone = process.env.MILESTONE;

            if (!milestone) {
              core.setFailed(`PR must have a milestone set (expected: ${expected})`);
              return;
            }
            if (milestone !== expected) {
              core.setFailed(`Milestone '${milestone}' does not match docker next version '${expected}'`);
              return;
            }
            core.info(`Milestone: ${milestone} ✓`);