Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into marktnoonan/16098
- Loading branch information
Showing
105 changed files
with
1,709 additions
and
539 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
.github/workflows/add_to_triage_project.yml → .github/workflows/triage_add_to_project.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: 'Triage: route to team project board' | ||
on: | ||
issues: | ||
types: | ||
- labeled | ||
jobs: | ||
route-to-e2e: | ||
if: github.event.label.name == 'routed-to-e2e' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Get project data | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }} | ||
ORGANIZATION: 'cypress-io' | ||
PROJECT_NUMBER: 10 | ||
run: | | ||
gh api graphql -f query=' | ||
query($org: String!, $number: Int!) { | ||
organization(login: $org){ | ||
projectV2(number: $number) { | ||
id | ||
} | ||
} | ||
}' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json | ||
echo 'PROJECT_ID='$(jq -r '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV | ||
- name: add issue to e2e project | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }} | ||
ISSUE_ID: ${{ github.event.issue.node_id }} | ||
run: | | ||
gh api graphql -f query=' | ||
mutation($project:ID!, $issue:ID!) { | ||
addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) { | ||
item { | ||
id | ||
} | ||
} | ||
}' -f project=$PROJECT_ID -f issue=$ISSUE_ID |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
name: 'Triage: closed issue comment' | ||
on: | ||
issue_comment: | ||
types: | ||
- created | ||
jobs: | ||
move-to-new-issue-status: | ||
if: | | ||
!github.event.issue.pull_request && | ||
github.event.issue.state == 'closed' && | ||
github.event.comment.created_at != github.event.issue.closed_at && | ||
github.event.sender.login != 'cypress-bot' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Get project data | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }} | ||
ORGANIZATION: 'cypress-io' | ||
REPOSITORY: 'cypress' | ||
PROJECT_NUMBER: 9 | ||
ISSUE_NUMBER: ${{ github.event.issue.number }} | ||
run: | | ||
gh api graphql -f query=' | ||
query($org: String!, $repo: String!, $project: Int!, $issue: Int!) { | ||
organization(login: $org) { | ||
repository(name: $repo) { | ||
issue(number: $issue) { | ||
projectItems(first: 10, includeArchived: false) { | ||
nodes { | ||
id | ||
fieldValueByName(name: "Status") { | ||
... on ProjectV2ItemFieldSingleSelectValue { | ||
name | ||
field { | ||
... on ProjectV2SingleSelectField { | ||
project { | ||
... on ProjectV2 { | ||
id | ||
number | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
projectV2(number: $project) { | ||
field(name: "Status") { | ||
... on ProjectV2SingleSelectField { | ||
id | ||
options { | ||
id | ||
name | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}' -f org=$ORGANIZATION -f repo=$REPOSITORY -F issue=$ISSUE_NUMBER -F project=$PROJECT_NUMBER > project_data.json | ||
echo 'PROJECT_ID='$(jq -r '.data.organization.repository.issue.projectItems.nodes[].fieldValueByName.field.project | select(.number == ${{ env.PROJECT_NUMBER }}) | .id' project_data.json) >> $GITHUB_ENV | ||
echo 'PROJECT_ITEM_ID='$(jq -r '.data.organization.repository.issue.projectItems.nodes[] | select(.fieldValueByName.field.project.number == ${{ env.PROJECT_NUMBER }}) | .id' project_data.json) >> $GITHUB_ENV | ||
echo 'STATUS_FIELD_ID='$(jq -r '.data.organization.projectV2.field | .id' project_data.json) >> $GITHUB_ENV | ||
echo 'STATUS='$(jq -r '.data.organization.repository.issue.projectItems.nodes[].fieldValueByName | select(.field.project.number == ${{ env.PROJECT_NUMBER }}) | .name' project_data.json) >> $GITHUB_ENV | ||
echo 'NEW_ISSUE_OPTION_ID='$(jq -r '.data.organization.projectV2.field.options[] | select(.name== "New Issue") | .id' project_data.json) >> $GITHUB_ENV | ||
- name: Move issue to New Issue status | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_TOKEN }} | ||
if: env.STATUS == 'Closed' | ||
run: | | ||
gh api graphql -f query=' | ||
mutation ( | ||
$project: ID! | ||
$item: ID! | ||
$status_field: ID! | ||
$status_value: String! | ||
) { | ||
updateProjectV2ItemFieldValue(input: { | ||
projectId: $project | ||
itemId: $item | ||
fieldId: $status_field | ||
value: { | ||
singleSelectOptionId: $status_value | ||
} | ||
}) { | ||
projectV2Item { | ||
id | ||
} | ||
} | ||
}' -f project=$PROJECT_ID -f item=$PROJECT_ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=$NEW_ISSUE_OPTION_ID |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
name: 'Triage: issue metrics' | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
startDate: | ||
description: 'Start date (YYYY-MM-DD)' | ||
type: date | ||
endDate: | ||
description: 'End date (YYYY-MM-DD)' | ||
type: date | ||
jobs: | ||
seven-day-close: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/github-script@v6 | ||
env: | ||
ORGANIZATION: 'cypress-io' | ||
REPOSITORY: 'cypress' | ||
PROJECT_NUMBER: 9 | ||
with: | ||
github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }} | ||
script: | | ||
const ROUTED_TO_LABELS = ['routed-to-e2e', 'routed-to-ct'] | ||
const MS_PER_DAY = 1000 * 60 * 60 * 24 | ||
const { REPOSITORY, ORGANIZATION, PROJECT_NUMBER } = process.env | ||
const issues = [] | ||
const determineDateRange = () => { | ||
const inputStartDate = '${{ inputs.startDate }}' | ||
const inputEndDate = '${{ inputs.endDate }}' | ||
if (inputStartDate && inputEndDate) { | ||
return { startDate: inputStartDate, endDate: inputEndDate } | ||
} | ||
if (inputStartDate || inputEndDate) { | ||
core.setFailed('Both startDate and endDate are required if one is provided.') | ||
} | ||
const startDate = new Date() | ||
startDate.setDate(startDate.getDate() - 6) | ||
return { startDate: startDate.toISOString().split('T')[0], endDate: (new Date()).toISOString().split('T')[0] } | ||
} | ||
const dateRange = determineDateRange() | ||
const query = `is:issue+repo:${ORGANIZATION}/${REPOSITORY}+project:${ORGANIZATION}/${PROJECT_NUMBER}+created:${dateRange.startDate}..${dateRange.endDate}` | ||
const findLabelDateTime = async (issueNumber) => { | ||
const iterator = github.paginate.iterator(github.rest.issues.listEventsForTimeline, { | ||
owner: ORGANIZATION, | ||
repo: REPOSITORY, | ||
issue_number: issueNumber, | ||
}) | ||
for await (const { data: timelineData } of iterator) { | ||
for (const timelineItem of timelineData) { | ||
if (timelineItem.event === 'labeled' && ROUTED_TO_LABELS.includes(timelineItem.label.name)) { | ||
return timelineItem.created_at | ||
} | ||
} | ||
} | ||
} | ||
const calculateElapsedDays = (createdAt, routedOrClosedAt) => { | ||
return Math.round((new Date(routedOrClosedAt) - new Date(createdAt)) / MS_PER_DAY, 0) | ||
} | ||
const iterator = github.paginate.iterator(github.rest.search.issuesAndPullRequests, { | ||
q: query, | ||
per_page: 100, | ||
}) | ||
for await (const { data } of iterator) { | ||
for (const issue of data) { | ||
let routedOrClosedAt | ||
if (!issue.pull_request) { | ||
const routedLabel = issue.labels.find((label) => ROUTED_TO_LABELS.includes(label.name)) | ||
if (routedLabel) { | ||
routedOrClosedAt = await findLabelDateTime(issue.number) | ||
} else if (issue.state === 'closed') { | ||
routedOrClosedAt = issue.closed_at | ||
} | ||
let elapsedDays | ||
if (routedOrClosedAt) { | ||
elapsedDays = calculateElapsedDays(issue.created_at, routedOrClosedAt) | ||
} | ||
issues.push({ | ||
number: issue.number, | ||
title: issue.title, | ||
state: issue.state, | ||
url: issue.html_url, | ||
createdAt: issue.created_at, | ||
routedOrClosedAt, | ||
elapsedDays, | ||
}) | ||
} | ||
} | ||
} | ||
const issuesRoutedOrClosedIn7Days = issues.filter((issue) => issue.elapsedDays <= 7).length | ||
const percentage = Number(issues.length > 0 ? issuesRoutedOrClosedIn7Days / issues.length : 0).toLocaleString(undefined, { style: 'percent', minimumFractionDigits: 2 }) | ||
console.log(`Triage Metrics (${dateRange.startDate} - ${dateRange.endDate})`) | ||
console.log('Total issues:', issues.length) | ||
console.log(`Issues routed/closed within 7 days: ${issuesRoutedOrClosedIn7Days} (${percentage})`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
1ce850c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Circle has built the
linux x64
version of the Test Runner.Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.
Run this command to install the pre-release locally: