@@ -30,98 +30,93 @@ jobs:
3030 permission-members : read
3131
3232 - name : Label external contributions
33+ uses : actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
3334 env :
34- API_URL : ${{ github.api_url }}
35- GH_TOKEN : ${{ github.token }}
3635 MEMBERS_TOKEN : ${{ steps.membership-token.outputs.token }}
37- ORG : ${{ github.repository_owner }}
38- REPO : ${{ github.repository }}
39- run : |
40- set -euo pipefail
36+ with :
37+ github-token : ${{ github.token }}
38+ retries : 3
39+ script : |
40+ const label = "external-contribution";
41+ const { owner, repo } = context.repo;
42+ const fullRepo = `${owner}/${repo}`;
43+ const since = new Date(Date.now() - 60 * 60 * 1000).toISOString();
44+ const membershipGithub = getOctokit(process.env.MEMBERS_TOKEN);
45+ let membershipCheckFailed = false;
4146
42- label="external-contribution"
43- membership_check_failed=false
44- updated_cutoff=$(date -u -d "1 hour ago" "+%Y-%m-%dT%H:%M:%SZ")
47+ const issues = await github.paginate("GET /repos/{owner}/{repo}/issues", {
48+ owner,
49+ repo,
50+ state: "open",
51+ since,
52+ sort: "updated",
53+ direction: "desc",
54+ per_page: 100,
55+ });
4556
46- while IFS= read -r pr_number; do
47- if [[ ! "$pr_number" =~ ^[1-9][0-9]*$ ]]; then
48- echo "Skipping malformed pull request number."
49- continue
50- fi
57+ for (const issue of issues) {
58+ if (!issue.pull_request) {
59+ continue;
60+ }
5161
52- pr_json=$(gh api "repos/$REPO/pulls/$pr_number")
53- if ! jq -e \
54- --arg repo "$REPO" \
55- --arg label "$label" \
56- '.state == "open" and
57- .draft == false and
58- .base.repo.full_name == $repo and
59- (.head.repo.full_name | type == "string") and
60- .head.repo.full_name != $repo and
61- .user.type == "User" and
62- (.user.login | type == "string" and length > 0) and
63- (any(.labels[]?; .name == $label) | not)' \
64- >/dev/null <<<"$pr_json"; then
65- continue
66- fi
62+ const { data: pull } = await github.request(
63+ "GET /repos/{owner}/{repo}/pulls/{pull_number}",
64+ { owner, repo, pull_number: issue.number },
65+ );
6766
68- author=$(jq -r '.user.login' <<<"$pr_json")
69- events=$(gh api --paginate \
70- "repos/$REPO/issues/$pr_number/events?per_page=100" |
71- jq -cs 'add')
67+ if (
68+ pull.state !== "open" ||
69+ pull.draft ||
70+ pull.base.repo.full_name !== fullRepo ||
71+ !pull.head.repo?.full_name ||
72+ pull.head.repo.full_name === fullRepo ||
73+ pull.user?.type !== "User" ||
74+ !pull.user.login ||
75+ pull.labels.some(({ name }) => name === label)
76+ ) {
77+ continue;
78+ }
7279
73- if jq -e --arg label "$label" \
74- 'any(.[]; .event == "labeled" and .label.name == $label)' \
75- >/dev/null <<<"$events"; then
76- continue
77- fi
80+ const events = await github.paginate(
81+ "GET /repos/{owner}/{repo}/issues/{issue_number}/events",
82+ { owner, repo, issue_number: issue.number, per_page: 100 },
83+ );
7884
79- if ! membership_status=$(curl \
80- --silent \
81- --show-error \
82- --output /dev/null \
83- --write-out '%{http_code}' \
84- --connect-timeout 10 \
85- --max-time 30 \
86- --header "Accept: application/vnd.github+json" \
87- --header "Authorization: Bearer $MEMBERS_TOKEN" \
88- --header "X-GitHub-Api-Version: 2022-11-28" \
89- "$API_URL/orgs/$ORG/members/$author"); then
90- echo "::error::Membership check failed for pull request #$pr_number; skipping."
91- membership_check_failed=true
92- continue
93- fi
85+ if (
86+ events.some(
87+ (event) =>
88+ event.event === "labeled" && event.label?.name === label,
89+ )
90+ ) {
91+ continue;
92+ }
9493
95- case "$membership_status" in
96- 204)
97- echo "Pull request #$pr_number was opened by an organization member; skipping."
98- continue
99- ;;
100- 404)
101- ;;
102- *)
103- echo "::error::Membership check for pull request #$pr_number returned HTTP $membership_status; skipping."
104- membership_check_failed=true
105- continue
106- ;;
107- esac
94+ try {
95+ await membershipGithub.request(
96+ "GET /orgs/{org}/members/{username}",
97+ { org: owner, username: pull.user.login },
98+ );
99+ core.info(
100+ `Pull request #${issue.number} was opened by an organization member; skipping.`,
101+ );
102+ continue;
103+ } catch (error) {
104+ if (error.status !== 404) {
105+ core.error(
106+ `Membership check failed for pull request #${issue.number}: ${error.message}`,
107+ );
108+ membershipCheckFailed = true;
109+ continue;
110+ }
111+ }
108112
109- jq -n --arg label "$label" '{labels: [$label]}' |
110- gh api --method POST \
111- "repos/$REPO/issues/$pr_number/labels" \
112- --input - \
113- >/dev/null
114- echo "Labelled pull request #$pr_number."
115- done < <(
116- gh api --method GET --paginate "repos/$REPO/issues" \
117- -f state=open \
118- -f since="$updated_cutoff" \
119- -f sort=updated \
120- -f direction=desc \
121- -f per_page=100 |
122- jq -r '.[] | select(.pull_request != null) | .number'
123- )
113+ await github.request(
114+ "POST /repos/{owner}/{repo}/issues/{issue_number}/labels",
115+ { owner, repo, issue_number: issue.number, labels: [label] },
116+ );
117+ core.info(`Labelled pull request #${issue.number}.`);
118+ }
124119
125- if [ "$membership_check_failed" = true ]; then
126- exit 1
127- fi
120+ if (membershipCheckFailed) {
121+ core.setFailed("One or more organization membership checks failed.");
122+ }
0 commit comments