Merge pull request #12425 from backstage/jhaals/cleanup-review
workflow: delete old review workflows
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
# on a review from someone in the reviewers group, remove the awaiting-review label and add the awaiting-author label
|
||||
name: Automate review labels - scheduled
|
||||
on:
|
||||
schedule:
|
||||
- cron: '* * * * *'
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Token
|
||||
id: get_workflow_token
|
||||
uses: peter-murray/workflow-application-token-action@v1
|
||||
with:
|
||||
application_id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }}
|
||||
application_private_key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }}
|
||||
organization: backstage
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
- run: npm install codeowners
|
||||
|
||||
- uses: actions/github-script@v6
|
||||
id: fix-labels
|
||||
with:
|
||||
github-token: ${{ steps.get_workflow_token.outputs.token }}
|
||||
script: |
|
||||
const script = require('./scripts/goalie-labels.js')
|
||||
await script({github, context, core})
|
||||
@@ -1,84 +0,0 @@
|
||||
# When the target of the PR changes, open, re-open or sync, then re-add the label.
|
||||
|
||||
name: Automate review labels
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- closed
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# THESE SCRIPTS SHOULD BE INLINED AND NOT IN REPO
|
||||
# DUE TO THE TOKEN PERMISSIONS THAT ARE GIVEN
|
||||
# TO THE WORKFLOW. THIS SCRIPT WILL AND SHOULD
|
||||
# RUN FROM THE BASE REPO ALL TIMES.
|
||||
- uses: actions/github-script@v6
|
||||
id: fix-labels
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
if (['opened', 'synchronize'].includes('${{ github.event.action }}')) {
|
||||
// if it's the author, always add awaiting-review label
|
||||
const isAuthor = context.payload.pull_request.user.login === context.actor
|
||||
if (isAuthor) {
|
||||
await github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['awaiting-review']
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ('${{ github.event.action}}' === 'closed') {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: 'awaiting-review'
|
||||
}).catch((e) => {
|
||||
console.log(e)
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add PRs to review board
|
||||
uses: actions/github-script@v6
|
||||
if: github.event.action == 'opened' || github.event.action == 'reopened'
|
||||
env:
|
||||
PROJECT_ID: PN_kwDOBFKqdc02LQ
|
||||
with:
|
||||
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
|
||||
script: |
|
||||
const prLookup = await github.graphql(`
|
||||
query($owner: String!, $repo: String!, $number: Int!){
|
||||
repository(owner: $owner, name: $repo) {
|
||||
pullRequest(number: $number) {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`, context.issue);
|
||||
|
||||
await github.graphql(`
|
||||
mutation($projectId: ID!, $contentId: ID!) {
|
||||
addProjectNextItem(input: {
|
||||
projectId: $projectId,
|
||||
contentId: $contentId,
|
||||
}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`, {
|
||||
projectId: process.env.PROJECT_ID,
|
||||
contentId: prLookup.repository.pullRequest.id
|
||||
})
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const Codeowners = require('codeowners');
|
||||
|
||||
const getRepoEvents = async ({ github, context, pull_number }) => {
|
||||
const commits = await github.paginate(github.rest.pulls.listCommits, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number,
|
||||
});
|
||||
|
||||
const reviews = await github.paginate(github.rest.pulls.listReviews, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number,
|
||||
});
|
||||
|
||||
const pullComments = await github.paginate(
|
||||
'GET /repos/{owner}/{repo}/pulls/{pull_number}/comments',
|
||||
{
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number,
|
||||
},
|
||||
);
|
||||
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pull_number,
|
||||
});
|
||||
|
||||
const events = [
|
||||
...reviews.map(({ user, submitted_at }) => ({
|
||||
user,
|
||||
updated_at: submitted_at,
|
||||
type: 'review',
|
||||
})),
|
||||
...commits.map(({ commit, author, committer }) => ({
|
||||
user: author || committer,
|
||||
updated_at: commit.author.date || commit.committer.date,
|
||||
type: 'commit',
|
||||
})),
|
||||
...pullComments.map(({ user, updated_at }) => ({
|
||||
user,
|
||||
updated_at,
|
||||
type: 'pr_comment',
|
||||
})),
|
||||
...comments.map(({ user, updated_at }) => ({
|
||||
user,
|
||||
updated_at,
|
||||
type: 'pr_comment',
|
||||
})),
|
||||
];
|
||||
|
||||
return events
|
||||
.sort((a, b) => new Date(a.updated_at) - new Date(b.updated_at))
|
||||
.filter(({ user }) => (user ? !user.login.includes('[bot]') : false));
|
||||
};
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
// first get all open pull requests
|
||||
const allPullRequests = await github.paginate(github.rest.pulls.list, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
});
|
||||
|
||||
const { data: teams } = await github.request('GET /orgs/{org}/teams', {
|
||||
org: context.repo.owner,
|
||||
});
|
||||
|
||||
const groupMembers = await Promise.all(
|
||||
teams.map(async team => {
|
||||
const { data } = await github.rest.teams.listMembersInOrg({
|
||||
org: context.repo.owner,
|
||||
team_slug: team.slug,
|
||||
});
|
||||
|
||||
return { team: `@backstage/${team.slug}`, data };
|
||||
}),
|
||||
);
|
||||
|
||||
const codeowners = new Codeowners();
|
||||
|
||||
for (const pullRequest of allPullRequests) {
|
||||
// Go through each file changed and get the codeowners for that file.
|
||||
// Find the group in the group list that matches the codeowner.
|
||||
// If it does match push the owner to a list of reviewers
|
||||
// check to see the reviews and if there is at least one matching reviewer from those group
|
||||
|
||||
const changedFiles = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pullRequest.number,
|
||||
});
|
||||
|
||||
const allReviews = await github.paginate(github.rest.pulls.listReviews, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pullRequest.number,
|
||||
});
|
||||
|
||||
const expectedReviewers = new Set();
|
||||
|
||||
for (const file of changedFiles) {
|
||||
expectedReviewers.add(...codeowners.getOwner(file.filename));
|
||||
}
|
||||
|
||||
const hasReviewed = new Set();
|
||||
|
||||
// For each reviewer in the group, check to see if they have a review set
|
||||
for (const reviewer of expectedReviewers) {
|
||||
const members = groupMembers.find(member => member.team === reviewer);
|
||||
if (members) {
|
||||
// then we are dealing with a group
|
||||
const hasMemberReview = allReviews.some(review =>
|
||||
members.data.some(member => member.login === review.user.login),
|
||||
);
|
||||
if (hasMemberReview) {
|
||||
hasReviewed.add(reviewer);
|
||||
}
|
||||
} else {
|
||||
// reviewer is a person
|
||||
const hasReview = allReviews.some(
|
||||
review => reviewer === `@${review.user.login}`,
|
||||
);
|
||||
if (hasReview) {
|
||||
hasReviewed.add(reviewer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if all required reviewers have reviewed
|
||||
if (hasReviewed.size === expectedReviewers.size) {
|
||||
const repoEvents = await getRepoEvents({
|
||||
github,
|
||||
context,
|
||||
pull_number: pullRequest.number,
|
||||
});
|
||||
// if the last event for the issue is not by the author, remove the label
|
||||
if (
|
||||
repoEvents[repoEvents.length - 1].user.login !== pullRequest.user.login
|
||||
) {
|
||||
await github.rest.issues
|
||||
.removeLabel({
|
||||
issue_number: pullRequest.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'awaiting-review',
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
// add the awaiting-review label to tell us that the PR is waiting on reviews
|
||||
} else {
|
||||
await github.rest.issues
|
||||
.addLabels({
|
||||
issue_number: pullRequest.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['awaiting-review'],
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user