diff --git a/.github/workflows/first_contribution_labeler.yml b/.github/workflows/pr_labeler.yml similarity index 62% rename from .github/workflows/first_contribution_labeler.yml rename to .github/workflows/pr_labeler.yml index 9831441f910be585f9a903b47addeff633827dce..2e3dbb36383e6c5a3cc9583defc7d7d3f1f400cb 100644 --- a/.github/workflows/first_contribution_labeler.yml +++ b/.github/workflows/pr_labeler.yml @@ -1,4 +1,6 @@ -name: First Contribution Labeler +# Labels pull requests by author: 'staff' for staff team members, +# 'first contribution' for first-time external contributors. +name: PR Labeler on: pull_request_target: @@ -8,7 +10,7 @@ permissions: contents: read jobs: - label_first_contribution: + check-authorship-and-label: if: github.repository == 'zed-industries/zed' runs-on: namespace-profile-2x4-ubuntu-2404 timeout-minutes: 5 @@ -20,58 +22,65 @@ jobs: private-key: ${{ secrets.ZED_COMMUNITY_BOT_PRIVATE_KEY }} owner: zed-industries - - id: check-and-label + - id: apply-authorship-label uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ steps.get-app-token.outputs.token }} script: | - const LABEL_NAME = 'first contribution'; + const STAFF_LABEL = 'staff'; + const FIRST_CONTRIBUTION_LABEL = 'first contribution'; + const STAFF_TEAM_SLUG = 'staff'; const pr = context.payload.pull_request; const author = pr.user.login; // Skip bots (they shouldn't have FIRST_TIME* association anyway, but just in case) if (author.endsWith('[bot]')) { - console.log(`Skipping bot: ${author}`); + console.log(`Skipping bot author: ${author}`); return; } - // Check if this is a first-time contributor. - // We use inverted logic here due to a suspected GitHub bug where first-time contributors - // get 'NONE' instead of 'FIRST_TIME_CONTRIBUTOR' or 'FIRST_TIMER'. - // https://github.com/orgs/community/discussions/78038 - // This will break if GitHub ever adds new associations. - const association = pr.author_association; - const knownAssociations = ['CONTRIBUTOR', 'COLLABORATOR', 'MEMBER', 'OWNER', 'MANNEQUIN']; - - if (knownAssociations.includes(association)) { - console.log(`Author ${author} has association '${association}', not a first-time contributor`); - return; - } - - // Skip staff members + let isStaff = false; try { const response = await github.rest.teams.getMembershipForUserInOrg({ org: 'zed-industries', - team_slug: 'staff', + team_slug: STAFF_TEAM_SLUG, username: author }); - if (response.data.state === 'active') { - console.log(`Skipping staff member: ${author}`); - return; - } + isStaff = response.data.state === 'active'; } catch (error) { if (error.status !== 404) { throw error; } - // 404 means user is not a staff member, continue + } + + if (isStaff) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: [STAFF_LABEL] + }); + console.log(`PR #${pr.number} by ${author}: labeled '${STAFF_LABEL}' (staff team member)`); + return; + } + + // We use inverted logic here due to a suspected GitHub bug where first-time contributors + // get 'NONE' instead of 'FIRST_TIME_CONTRIBUTOR' or 'FIRST_TIMER'. + // https://github.com/orgs/community/discussions/78038 + // This will break if GitHub ever adds new associations. + const association = pr.author_association; + const knownAssociations = ['CONTRIBUTOR', 'COLLABORATOR', 'MEMBER', 'OWNER', 'MANNEQUIN']; + + if (knownAssociations.includes(association)) { + console.log(`PR #${pr.number} by ${author}: not a first-time contributor (association: '${association}')`); + return; } await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, - labels: [LABEL_NAME] + labels: [FIRST_CONTRIBUTION_LABEL] }); - - console.log(`Applied '${LABEL_NAME}' label to PR #${pr.number} by ${author}`); + console.log(`PR #${pr.number} by ${author}: labeled '${FIRST_CONTRIBUTION_LABEL}' (association: '${association}')`);