name: '🏷️ PR Contribution Guidelines Notifier'

on:
  pull_request:
    types:
      - 'opened'

jobs:
  notify-process-change:
    runs-on: 'ubuntu-latest'
    if: |-
      github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli'
    permissions:
      pull-requests: 'write'
    steps:
      - name: 'Generate GitHub App Token'
        id: 'generate_token'
        env:
          APP_ID: '${{ secrets.APP_ID }}'
        if: |-
          ${{ env.APP_ID != '' }}
        uses: 'actions/create-github-app-token@v2'
        with:
          app-id: '${{ secrets.APP_ID }}'
          private-key: '${{ secrets.PRIVATE_KEY }}'

      - name: 'Check membership and post comment'
        uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
        with:
          github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
          script: |-
            const org = context.repo.owner;
            const repo = context.repo.repo;
            const username = context.payload.pull_request.user.login;
            const pr_number = context.payload.pull_request.number;

            // 1. Check if the PR author is a maintainer
            // Check team membership (most reliable for private org members)
            let isTeamMember = false;
            const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
            for (const team_slug of teams) {
              try {
                const members = await github.paginate(github.rest.teams.listMembersInOrg, {
                  org: org,
                  team_slug: team_slug
                });
                if (members.some(m => m.login.toLowerCase() === username.toLowerCase())) {
                  isTeamMember = true;
                  core.info(`${username} is a member of ${team_slug}. No notification needed.`);
                  break;
                }
              } catch (e) {
                core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
              }
            }

            if (isTeamMember) return;

            // Check author_association from webhook payload
            const authorAssociation = context.payload.pull_request.author_association;
            const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation);

            if (isRepoMaintainer) {
              core.info(`${username} is a maintainer (author_association: ${authorAssociation}). No notification needed.`);
              return;
            }

            // Check if author is a Googler
            const isGoogler = async (login) => {
              try {
                const orgs = ['googlers', 'google'];
                for (const org of orgs) {
                  try {
                    await github.rest.orgs.checkMembershipForUser({
                      org: org,
                      username: login
                    });
                    return true;
                  } catch (e) {
                    if (e.status !== 404) throw e;
                  }
                }
              } catch (e) {
                core.warning(`Failed to check org membership for ${login}: ${e.message}`);
              }
              return false;
            };

            if (await isGoogler(username)) {
              core.info(`${username} is a Googler. No notification needed.`);
              return;
            }

            // 2. Check if the PR is already associated with an issue
            const query = `
              query($owner:String!, $repo:String!, $number:Int!) {
                repository(owner:$owner, name:$repo) {
                  pullRequest(number:$number) {
                    closingIssuesReferences(first: 1) {
                      totalCount
                    }
                  }
                }
              }
            `;
            const variables = { owner: org, repo: repo, number: pr_number };
            const result = await github.graphql(query, variables);
            const issueCount = result.repository.pullRequest.closingIssuesReferences.totalCount;

            if (issueCount > 0) {
              core.info(`PR #${pr_number} is already associated with an issue. No notification needed.`);
              return;
            }

            // 3. Post the notification comment
            core.info(`${username} is not a maintainer and PR #${pr_number} has no linked issue. Posting notification.`);

            const comment = `
            Hi @${username}, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

            We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: [Improving Our Contribution Process & Introducing New Guidelines](https://github.com/google-gemini/gemini-cli/discussions/16706).

            Key Update: Starting **January 26, 2026**, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

            Thank you for your understanding and for being a part of our community!
            `.trim().replace(/^[ ]+/gm, '');

            await github.rest.issues.createComment({
              owner: org,
              repo: repo,
              issue_number: pr_number,
              body: comment
            });
