Use github-script to safely label PRs from forks (#9256)
parent
485b72cd0d
commit
ff2d9ad67d
|
@ -1,27 +1,75 @@
|
|||
name: "Apply issue labels to PR"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
|
||||
|
||||
jobs:
|
||||
label_on_pr:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
permissions:
|
||||
contents: none
|
||||
issues: read
|
||||
pull-requests: write
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Apply labels from linked issue to PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_DATA: ${{ toJson(github.event.pull_request) }}
|
||||
run: node ./.github/workflows/scripts/apply-issue-labels-to-pr.ts
|
||||
uses: actions/github-script@v5
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
async function getLinkedIssues(owner, repo, prNumber) {
|
||||
const query = `query GetLinkedIssues($owner: String!, $repo: String!, $prNumber: Int!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
pullRequest(number: $prNumber) {
|
||||
closingIssuesReferences(first: 10) {
|
||||
nodes {
|
||||
number
|
||||
labels(first: 10) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
const variables = {
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
prNumber: prNumber,
|
||||
};
|
||||
|
||||
const result = await github.graphql(query, variables);
|
||||
return result.repository.pullRequest.closingIssuesReferences.nodes;
|
||||
}
|
||||
|
||||
const pr = context.payload.pull_request;
|
||||
const linkedIssues = await getLinkedIssues(
|
||||
context.repo.owner,
|
||||
context.repo.repo,
|
||||
pr.number
|
||||
);
|
||||
|
||||
const labelsToAdd = new Set();
|
||||
for (const issue of linkedIssues) {
|
||||
if (issue.labels && issue.labels.nodes) {
|
||||
for (const label of issue.labels.nodes) {
|
||||
labelsToAdd.add(label.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (labelsToAdd.size) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: Array.from(labelsToAdd),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
const https = require("https");
|
||||
|
||||
async function applyLabelFromLinkedIssueToPR(pr, token) {
|
||||
// Get the labels from issues linked to the PR
|
||||
const query = `
|
||||
query GetLinkedIssues($owner: String!, $repo: String!, $prNumber: Int!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
pullRequest(number: $prNumber) {
|
||||
closingIssuesReferences(first: 10) {
|
||||
nodes {
|
||||
number
|
||||
labels(first: 10) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const graphqlData = JSON.stringify({
|
||||
query,
|
||||
variables: {
|
||||
owner: pr.base.repo.owner.login,
|
||||
repo: pr.base.repo.name,
|
||||
prNumber: pr.number,
|
||||
},
|
||||
});
|
||||
|
||||
const requestOptions = {
|
||||
hostname: "api.github.com",
|
||||
path: "/graphql",
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Length": graphqlData.length,
|
||||
Authorization: "Bearer " + token,
|
||||
"User-Agent": "Node.js",
|
||||
},
|
||||
};
|
||||
|
||||
// Use the native Node.js request library to make the request
|
||||
let linkedIssues;
|
||||
linkedIssues = await new Promise((resolve, reject) => {
|
||||
const request = https.request(requestOptions, (response) => {
|
||||
let responseBody = "";
|
||||
response.on("data", (chunk) => {
|
||||
responseBody += chunk;
|
||||
});
|
||||
response.on("end", () => {
|
||||
resolve(JSON.parse(responseBody)?.data?.repository?.pullRequest?.closingIssuesReferences?.nodes);
|
||||
});
|
||||
});
|
||||
|
||||
request.on("error", (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
request.write(graphqlData);
|
||||
request.end();
|
||||
});
|
||||
|
||||
if (!linkedIssues || linkedIssues.length === 0) {
|
||||
console.log("No issue linked.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate over linked issues and apply labels to PR
|
||||
for (const issue of linkedIssues) {
|
||||
const labels = issue?.labels?.nodes?.map((label) => label.name);
|
||||
|
||||
if (!labels || labels.length === 0) {
|
||||
console.log(`No labels found on the linked issue #${issue.number}.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const labelsData = JSON.stringify({
|
||||
labels: labels,
|
||||
});
|
||||
|
||||
const requestOptions = {
|
||||
hostname: "api.github.com",
|
||||
path: `/repos/${pr.base.repo.owner.login}/${pr.base.repo.name}/issues/${pr.number}/labels`,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Length": labelsData.length,
|
||||
Authorization: "Bearer " + token,
|
||||
"User-Agent": "Node.js",
|
||||
},
|
||||
};
|
||||
|
||||
let labelResult;
|
||||
labelResult = await new Promise((resolve, reject) => {
|
||||
const request = https.request(requestOptions, (response) => {
|
||||
let responseBody = "";
|
||||
response.on("data", (chunk) => {
|
||||
responseBody += chunk;
|
||||
});
|
||||
response.on("data", () => {});
|
||||
response.on("end", () => {
|
||||
resolve(JSON.parse(responseBody));
|
||||
});
|
||||
});
|
||||
|
||||
request.on("error", (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
request.write(labelsData);
|
||||
request.end();
|
||||
});
|
||||
|
||||
if (labelResult.message) {
|
||||
console.log(`Error labelling PR: ${labelResult.message}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Applied labels: ${labels.join(", ")} to PR #${pr.number} from linked issue #${issue.number}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the PR data and GitHub token to the script
|
||||
(async () => {
|
||||
if (!process.env.PR_DATA) {
|
||||
console.log("No PR data found.");
|
||||
return;
|
||||
}
|
||||
|
||||
const prData = JSON.parse(process.env.PR_DATA);
|
||||
const token = process.env.GITHUB_TOKEN;
|
||||
|
||||
await applyLabelFromLinkedIssueToPR(prData, token);
|
||||
})();
|
Loading…
Reference in New Issue