Skip to content

Commit

Permalink
Automate triaging to content review board on adding waiting for revie…
Browse files Browse the repository at this point in the history
…w label (github#21825)

* os-ready-for-review

* include grapqhl issue

* populate size, feature, first-time contributor (github#21810)

* turnaround -> 3 & 2

* Update .github/workflows/os-ready-for-review.yml

Co-authored-by: Sarah Edwards <[email protected]>

* Update .github/workflows/os-ready-for-review.yml

Co-authored-by: Sarah Edwards <[email protected]>

* Update .github/workflows/os-ready-for-review.yml

Co-authored-by: Sarah Edwards <[email protected]>

* Update .github/workflows/os-ready-for-review.yml

Co-authored-by: Sarah Edwards <[email protected]>

* Update .github/workflows/os-ready-for-review.yml

Co-authored-by: Sarah Edwards <[email protected]>

* prettier

Co-authored-by: skedwards88 <[email protected]>
  • Loading branch information
Ramya Parimi and skedwards88 authored Oct 1, 2021
1 parent 18f9d9a commit e12d988
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .github/actions-scripts/fr-add-docs-reviewers-requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ async function run() {
const statusID = findFieldID('Status', data)
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)

// Get the ID of the single select values that we want to set
Expand Down Expand Up @@ -169,6 +170,8 @@ async function run() {
reviewDueDateID: reviewDueDateID,
contributorTypeID: contributorTypeID,
contributorType: contributorType,
sizeTypeID: sizeTypeID,
sizeType: '', // Although we aren't populating size, we are passing the variable so that we can use the shared mutation function
featureID: featureID,
authorID: authorID,
headers: {
Expand Down
7 changes: 7 additions & 0 deletions .github/actions-scripts/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ export function generateUpdateProjectNextItemFieldMutation({
$reviewDueDateID: ID!
$contributorTypeID: ID!
$contributorType: String!
$sizeTypeID: ID!
$sizeType: String!
$featureID: ID!
$authorID: ID!
) {
Expand All @@ -211,6 +213,11 @@ export function generateUpdateProjectNextItemFieldMutation({
fieldID: '$contributorTypeID',
value: '$contributorType',
})}
${generateMutationToUpdateField({
item: item,
fieldID: '$sizeTypeID',
value: '$sizeType',
})}
${generateMutationToUpdateField({
item: item,
fieldID: '$featureID',
Expand Down
119 changes: 114 additions & 5 deletions .github/actions-scripts/ready-for-docs-review.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function run() {
// Get info about the docs-content review board project
const data = await graphql(
`
query ($organization: String!, $projectNumber: Int!) {
query ($organization: String!, $projectNumber: Int!, $id: ID!) {
organization(login: $organization) {
projectNext(number: $projectNumber) {
id
Expand All @@ -25,9 +25,22 @@ async function run() {
}
}
}
item: node(id: $id) {
__typename
... on PullRequest {
files(first: 100) {
nodes {
additions
deletions
path
}
}
}
}
}
`,
{
id: process.env.ITEM_NODE_ID,
organization: process.env.ORGANIZATION,
projectNumber: parseInt(process.env.PROJECT_NUMBER),
headers: {
Expand All @@ -46,29 +59,123 @@ async function run() {
const statusID = findFieldID('Status', data)
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)

// Get the ID of the single select values that we want to set
const readyForReviewID = findSingleSelectID('Ready for review', 'Status', data)
const hubberTypeID = findSingleSelectID('Hubber or partner', 'Contributor type', data)
const docsMemberTypeID = findSingleSelectID('Docs team', 'Contributor type', data)
const osContributorTypeID = findSingleSelectID('OS contributor', 'Contributor type', data)
const sizeXS = findSingleSelectID('XS', 'Size', data)
const sizeS = findSingleSelectID('S', 'Size', data)
const sizeM = findSingleSelectID('M', 'Size', data)
const sizeL = findSingleSelectID('L', 'Size', data)

// Add the PR to the project
const newItemID = await addItemToProject(process.env.PR_NODE_ID, projectID)
const newItemID = await addItemToProject(process.env.ITEM_NODE_ID, projectID)

// If the item is a PR, determine the feature and size
let feature = ''
let sizeType = '' // You don't need to use a field ID if you want the value to be empty
if (data.item.__typename === 'PullRequest') {
// Get the
// - number of files changed
// - total number of additions/deletions
// - affected docs sets (not considering changes to data/assets)
let numFiles = 0
let numChanges = 0
let features = new Set([])
const files = data.item.files.nodes.forEach((node) => {
numFiles += 1
numChanges += node.additions
numChanges += node.deletions
// To determine the feature, we are only looking at `content/*` paths
// and then pulling out the second part of the path, which corresponds to the docs set
const pathComponents = node.path.split('/')
if (pathComponents[0] === 'content') {
features.add(pathComponents[1])
}
})

// Determine the size
if (numFiles < 5 && numChanges < 25) {
sizeType = sizeXS
} else if (numFiles < 5 && numChanges < 25) {
sizeType = sizeS
} else if (numFiles < 5 && numChanges < 25) {
sizeType = sizeM
} else {
sizeType = sizeL
}

// Set the feature
feature = Array.from(features).join()
}

// If this is the OS repo, determine if this is a first time contributor
// If yes, set the author to 'first time contributor' instead of to the author login
let firstTimeContributor
if (process.env.REPO === 'github/docs') {
const contributorData = await graphql(
`
query ($author: String!) {
user(login: $author) {
contributionsCollection {
pullRequestContributionsByRepository {
contributions {
totalCount
}
repository {
nameWithOwner
}
}
issueContributionsByRepository {
contributions {
totalCount
}
repository {
nameWithOwner
}
}
}
}
}
`,
{
author: process.env.AUTHOR_LOGIN,
headers: {
authorization: `token ${process.env.TOKEN}`,
},
}
)
const prCount =
contributorData.user.contributionsCollection.pullRequestContributionsByRepository.filter(
(item) => item.repository.nameWithOwner === 'github/docs'
)[0].contributions.totalCount
const issueCount =
contributorData.user.contributionsCollection.issueContributionsByRepository.filter(
(item) => item.repository.nameWithOwner === 'github/docs'
)[0].contributions.totalCount

if (prCount + issueCount <= 1) {
firstTimeContributor = true
}
}
const turnaround = process.env.REPO === 'github/docs' ? 3 : 2
// Generate a mutation to populate fields for the new project item
const updateProjectNextItemMutation = generateUpdateProjectNextItemFieldMutation({
item: newItemID,
author: process.env.AUTHOR_LOGIN,
turnaround: 2,
author: firstTimeContributor ? 'first time contributor' : process.env.AUTHOR_LOGIN,
turnaround: turnaround,
feature: feature,
})

// Determine which variable to use for the contributor type
let contributorType
if (await isDocsTeamMember(process.env.AUTHOR_LOGIN)) {
contributorType = docsMemberTypeID
} else if (process.env.PR_REPO === 'github/docs') {
} else if (process.env.REPO === 'github/docs') {
contributorType = osContributorTypeID
} else {
contributorType = hubberTypeID
Expand All @@ -84,6 +191,8 @@ async function run() {
reviewDueDateID: reviewDueDateID,
contributorTypeID: contributorTypeID,
contributorType: contributorType,
sizeTypeID: sizeTypeID,
sizeType: sizeType,
featureID: featureID,
authorID: authorID,
headers: {
Expand Down
68 changes: 68 additions & 0 deletions .github/workflows/os-ready-for-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: OS Ready for review

# **What it does**: Adds pull requests and issues in the docs repository to the docs-content review board when the "waiting for review" label is added
# **Why we have it**: So that contributors in the OS repo can easily get reviews from the docs-content team, and so that writers can see when a PR is ready for review
# **Who does it impact**: Writers working in the docs repository
permissions:
contents: read

on:
pull_request:
types: [labeled]
issues:
types: [labeled]

jobs:
request_doc_review:
name: Request a review from the docs-content team
if: github.event.label.name == 'waiting for review' && github.repository == 'github/docs'
runs-on: ubuntu-latest
steps:
- name: Exit if not triggered by a docs team member
env:
GITHUB_TOKEN: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }}
run: |
members="$( gh api graphql -f query='
query {
organization(login: "github") {
team(slug: "docs") {
members {
nodes {
login
}
}
}
}
}
' --jq '.data.organization.team.members.nodes | [(.[].login)]')"
isMember=$(echo ${members[@]} | grep -ow $GITHUB_ACTOR | wc -w)
if [ $isMember -eq 0 ]
then
echo "$GITHUB_ACTOR is not a docs team member. exiting..."
exit 1
fi
- name: Check out repo content
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f

- name: Setup Node
uses: actions/setup-node@38d90ce44d5275ad62cc48384b3d8a58c500bb5f
with:
node-version: 16.x
cache: npm

- name: Install dependencies
run: npm install @octokit/graphql

- name: Run script
run: |
node .github/actions-scripts/ready-for-docs-review.js
env:
TOKEN: ${{ secrets.DOCS_BOT_FR }}
PROJECT_NUMBER: 2936
ORGANIZATION: 'github'
ITEM_NODE_ID: ${{ github.event.pull_request.node_id || github.event.issue.node_id }}
AUTHOR_LOGIN: ${{ github.event.pull_request.user.login || github.event.issue.user.login }}
REPO: ${{ github.repository }}
4 changes: 2 additions & 2 deletions .github/workflows/ready-for-doc-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ jobs:
TOKEN: ${{ secrets.DOCS_BOT_FR }}
PROJECT_NUMBER: 2936
ORGANIZATION: 'github'
PR_NODE_ID: ${{ github.event.pull_request.node_id }}
ITEM_NODE_ID: ${{ github.event.pull_request.node_id }}
AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
PR_REPO: ${{ github.event.pull_request.base.repo.full_name }}
REPO: ${{ github.event.pull_request.base.repo.full_name }}

# Since the projects API is still in beta, use the old workflow if something fails
# so that we don't miss these PRs
Expand Down

0 comments on commit e12d988

Please sign in to comment.