From 99033df963409f9ffccc46d30cc68709f7e968f0 Mon Sep 17 00:00:00 2001 From: MihirKohli Date: Fri, 22 Sep 2023 13:14:36 +0530 Subject: [PATCH 01/10] merge && cherry-pick Co-authored-by: MihirKohli --- .gitignore | 1 + .idea/.gitignore | 8 + .idea/inspectionProfiles/Project_Default.xml | 18 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/issue-metrics.iml | 12 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + README.md | 448 +----------------- assign-team-instead-of-individual.md | 60 +++ example-using-json-instead-markdown-output.md | 33 ++ example-workflows.md | 136 ++++++ local-usage-without-docker.md | 8 + measure-time.md | 105 ++++ search-query.md | 75 +++ 15 files changed, 505 insertions(+), 423 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/issue-metrics.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 assign-team-instead-of-individual.md create mode 100644 example-using-json-instead-markdown-output.md create mode 100644 example-workflows.md create mode 100644 local-usage-without-docker.md create mode 100644 measure-time.md create mode 100644 search-query.md diff --git a/.gitignore b/.gitignore index de4c02c..4f03760 100644 --- a/.gitignore +++ b/.gitignore @@ -143,3 +143,4 @@ cython_debug/ # Mac .DS_Store +**/.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..f9f69bd --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/issue-metrics.iml b/.idea/issue-metrics.iml new file mode 100644 index 0000000..8a05c6e --- /dev/null +++ b/.idea/issue-metrics.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..141de14 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..cba9a62 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 5e51536..26332a4 100644 --- a/README.md +++ b/README.md @@ -21,30 +21,35 @@ [![CodeQL](https://github.com/github/issue-metrics/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/codeql-analysis.yml) [![Docker Image CI](https://github.com/github/issue-metrics/actions/workflows/docker-image.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/docker-image.yml) [![Python package](https://github.com/github/issue-metrics/actions/workflows/python-package.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/python-package.yml) -This is a GitHub Action that searches for pull requests/issues/discussions in a repository and measures and reports on -several metrics. The issues/pull requests/discussions to search for can be filtered by using a search query. +This is a GitHub Action that searches for pull requests/issues/discussions in a repository +and measures and reports on several metrics. The issues/pull requests/discussions to +search for can be filtered by using a search query. -The metrics that are measured are: | Metric | Description | |--------|-------------| -| Time to first response | The time between when an issue/pull request/discussion is created and when the first comment or review is made.* | -| Time to close | The time between when an issue/pull request/discussion is created and when it is closed.* | -| Time to answer | (Discussions only) The time between when a discussion is created and when it is answered. | -| Time in label | The time between when a label has a specific label applied to an issue/pull request/discussion and when it is removed. This requires the LABELS_TO_MEASURE env variable to be set. | +|Time to First Response | The duration from creation to the initial comment or review.| +|Time to Close | The period from creation to closure.| +|Time to Answer (Discussions Only) | The time from creation to an answer.| +|Time in Label | The duration from label application to removal, requires LABELS_TO_MEASURE env variable.| *For pull requests, these metrics exclude the time the PR was in draft mode. *For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded. -This action was developed by the GitHub OSPO for our own use and developed in a way that we could open source it that it might be useful to you as well! If you want to know more about how we use it, reach out in an issue in this repository. +This action, developed by GitHub OSPO for our internal use, is open-sourced for your potential benefit. +Feel free to inquire about its usage by creating an issue in this repository. -To find syntax for search queries, check out the [documentation on searching issues and pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) or the [documentation on searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions). +To find syntax for search queries, check out the [documentation on searching issues and pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) +or the [documentation on searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions). ## Example use cases -- As a maintainer, I want to see metrics for issues and pull requests on the repository I maintain in order to ensure I am giving them the proper amount of attention. -- As a first responder on a repository, I want to ensure that users are getting contact from me in a reasonable amount of time. -- As an OSPO, I want to see how many open source repository requests are open/closed, and metrics for how long it takes to get through the open source process. -- As a product development team, I want to see metrics around how long pull request reviews are taking, so that we can reflect on that data during retrospectives. +| Metric | Description | +|--------|-------------| +|Maintainer Metrics| Monitor issue and pull request metrics for effective attention.| +|Timely Response| Ensure prompt user contact as a first responder.| +|OSPO Insights| Track open source request status and processing times.| +|Review Efficiency| Analyze PR review durations for retrospectives.| + ## Support @@ -61,6 +66,7 @@ If you need support using this project or have questions about it, please [open 1. Commit the workflow file to the default branch (often `master` or `main`) 1. Wait for the action to trigger based on the `schedule` entry or manually trigger the workflow as shown in the [documentation](https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow). + ### Configuration Below are the allowed configuration options: @@ -77,423 +83,19 @@ Below are the allowed configuration options: | `HIDE_LABEL_METRICS` | False | | If set to any value, the time in label metrics will not be displayed in the generated markdown file. | | `IGNORE_USERS` | False | | A comma separated list of users to ignore when calculating metrics. (ie. `IGNORE_USERS: 'user1,user2'`). To ignore bots, append `[bot]` to the user (ie. `IGNORE_USERS: 'github-actions[bot]'`) | -### Example workflows - -#### Calculated Time Example -This workflow searches for the issues created last month, and generates an issue with metrics. - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - schedule: - - cron: '3 2 1 * *' - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - - name: Get dates for last month - shell: bash - run: | - # Calculate the first day of the previous month - first_day=$(date -d "last month" +%Y-%m-01) - - # Calculate the last day of the previous month - last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) - - #Set an environment variable with the date range - echo "$first_day..$last_day" - echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" - - - name: Run issue-metrics tool - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' - - - name: Create issue - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: - -``` - -#### Fixed Time Example -This workflow searches for the issues created between 2023-05-01..2023-05-31, and generates an issue with metrics. - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - - name: Run issue-metrics tool - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' - - - name: Create issue - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: - -``` - -#### Multiple Repositories Example - -This workflow searches for the issues created last month, and generates an issue with metrics. It also searches for issues in a second repository and includes those metrics in the same issue. - -```yaml -name: Monthly issue metrics (Multi Repo) -on: - workflow_dispatch: - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - name: Get dates for last month - shell: bash - run: | - # Calculate the first day of the previous month - first_day=$(date -d "last month" +%Y-%m-01) - - # Calculate the last day of the previous month - last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) - - #Set an environment variable with the date range - echo "$first_day..$last_day" - echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" - - - name: Get issue metrics - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo1 repo:owner/repo2 is:issue created:${{ env.last_month }} -reason:"not planned"' - - - name: Create issue - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report (dev) - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: -``` - -## SEARCH_QUERY -Issues or Pull Requests? Open or closed? -This action can be configured to run metrics on discussions, pull requests and/or issues. It is also configurable by whether they were open or closed in the specified time window. Further query options are listed in the [documentation on searching issues and pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) or the [documentation on searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions). Search results are limited to 1000 results by the GitHub API. Here are some search query examples: - -Issues opened in May 2023: -- `repo:owner/repo is:issue created:2023-05-01..2023-05-31` - -Issues closed in May 2023 (may have been open in May or earlier): -- `repo:owner/repo is:issue closed:2023-05-01..2023-05-31` - -Pull requests opened in May 2023: -- `repo:owner/repo is:pr created:2023-05-01..2023-05-31` - -Pull requests closed in May 2023 (may have been open in May or earlier): -- `repo:owner/repo is:pr closed:2023-05-01..2023-05-31` - -Discussions opened in May 2023: -- `repo:owner/repo type:discussions created:2023-05-01..2023-05-31` - -Discussions opened in May 2023 with category of engineering and label of question: -- `repo:owner/repo type:discussions created:2023-05-01..2023-05-31 category:engineering label:"question"` - -Both issues and pull requests opened in May 2023: -- `repo:owner/repo created:2023-05-01..2023-05-31` - -Both issues and pull requests closed in May 2023 (may have been open in May or earlier): -- `repo:owner/repo closed:2023-05-01..2023-05-31` - -OK, but what if I want both open or closed issues and pull requests? Due to limitations in issue search (no ability for OR logic), you will need to run the action twice, once for opened and once for closed. Here is an example workflow that does this: - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - schedule: - - cron: '3 2 1 * *' - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - - name: Run issue-metrics tool for issues and prs opened in May 2023 - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo created:2023-05-01..2023-05-31 -reason:"not planned"' - - - name: Create issue for opened issues and prs - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report for opened issues and prs - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: - - - name: Run issue-metrics tool for issues and prs closed in May 2023 - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo closed:2023-05-01..2023-05-31 -reason:"not planned"' - - - name: Create issue for closed issues and prs - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report for closed issues and prs - content-filepath: ./issue_metrics.md - assignees: -``` - -## Measuring time spent in labels - -**Note**: The discussions API currently doesn't support the `LabeledEvent` so this action cannot measure the time spent in a label for discussions. - -Sometimes it is helpful to know how long an issue or pull request spent in a particular label. This action can be configured to measure the time spent in a label. This is different from only wanting to measure issues with a specific label. If that is what you want, see the section on [configuring your search query](https://github.com/github/issue-metrics/blob/main/README.md#search_query-issues-or-pull-requests-open-or-closed). - -Here is an example workflow that does this: - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - - name: Run issue-metrics tool - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - LABELS_TO_MEASURE: 'waiting-for-manager-approval,waiting-for-security-review' - SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' - - - name: Create issue - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: - -``` - -then the report will look like this: - -```markdown -# Issue Metrics - -| Metric | Value | -| --- | ---: | -| Average time to first response | 0:50:44.666667 | -| Average time to close | 6 days, 7:08:52 | -| Average time to answer | 1 day | -| Average time spent in waiting-for-manager-approval | 0:00:41 | -| Average time spent in waiting-for-security-review | 2 days, 4:25:03 | -| Number of items that remain open | 2 | -| Number of items closed | 1 | -| Total number of items created | 3 | - -| Title | URL | Author | Time to first response | Time to close | Time to answer | Time spent in waiting-for-manager-approval | Time spent in waiting-for-security-review | -| --- | --- | --- | --- | --- | --- | --- | --- | -| Pull Request Title 1 | https://github.com/user/repo/pulls/1 | alice | 0:05:26 | None | None | None | None | -| Issue Title 2 | https://github.com/user/repo/issues/2 | bob | 2:26:07 | None | None | 0:00:41 | 2 days, 4:25:03 | - -``` - -## Example issue_metrics.md output - -Here is the output with no hidden columns: -```markdown -# Issue Metrics - -| Metric | Value | -| --- | ---: | -| Average time to first response | 0:50:44.666667 | -| Average time to close | 6 days, 7:08:52 | -| Average time to answer | 1 day | -| Number of items that remain open | 2 | -| Number of items closed | 1 | -| Total number of items created | 3 | - -| Title | URL | Author | Time to first response | Time to close | Time to answer | -| --- | --- | --- | --- | --- | --- | -| Discussion Title 1 | https://github.com/user/repo/discussions/1 | None | 0:00:41 | 6 days, 7:08:52 | 1 day | -| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | bob | 0:05:26 | None | None | -| Issue Title 3 | https://github.com/user/repo/issues/3 | carol | 2:26:07 | None | None | - -``` - -Here is the output with all hidable columns hidden: -```markdown -# Issue Metrics - -| Metric | Value | -| --- | ---: | -| Number of items that remain open | 2 | -| Number of items closed | 1 | -| Total number of items created | 3 | - -| Title | URL | Author | -| --- | --- | --- | -| Discussion Title 1 | https://github.com/user/repo/discussions/1 | None | -| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | bob | -| Issue Title 3 | https://github.com/user/repo/issues/3 | carol | - -``` - -## Example using the JSON output instead of the markdown output - -There is JSON output available as well. You could use it for any number of possibilities, but here is one example that demonstrates retreiving the JSON output and then printing it out. - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - schedule: - - cron: '3 2 1 * *' - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - name: Run issue-metrics tool - id: issue-metrics - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' - - - name: Print output of issue metrics tool - run: echo "${{ steps.issue-metrics.outputs.metrics }}" - -``` - -## Assigning teams instead of individuals - -The assignee part of this workflow action comes from [a different GitHub action](https://github.com/peter-evans/create-issue-from-file) and currently GitHub issues don't support assigning groups. - -By way of work around, you could use the [GitHub API to retrieve the members of the team](https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#list-team-members) and then put them in a comma separated string that you provide as the assignee. This requires setting up a new GitHub API token (referred to below as `CUSTOM_TOKEN`) which has `read:org` permissions assigned and single sign on authorization as needed. To do this, create a [GitHub API token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with permissions to read the org (`read:org`). Then take the value of the API token you just created, and [create a repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) where the name of the secret is `CUSTOM_TOKEN` and the value of the secret the API token. - -That might look something like the workflow below where `ORG` is your organization name and `TEAM_SLUG` is the name of the team: - -```yaml -name: Monthly issue metrics -on: - workflow_dispatch: - schedule: - - cron: '3 2 1 * *' - -permissions: - issues: write - pull-requests: read - -jobs: - build: - name: issue metrics - runs-on: ubuntu-latest - - steps: - - - name: Get dates for last month - shell: bash - run: | - # Calculate the first day of the previous month - first_day=$(date -d "last month" +%Y-%m-01) - # Calculate the last day of the previous month - last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) +[Example workflows](example-workflows.md) - #Set an environment variable with the date range - echo "$first_day..$last_day" - echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" +[Search Query](search-query.md) - - name: Run issue-metrics tool - uses: github/issue-metrics@v2 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' +[Measuring Time Spent](measure-time.md) - - name: Get user names from team - run: | - teamMembers="$(gh api /orgs/ORG/teams/TEAM_SLUG/members | jq -r '.[].login' | paste -sd, -)" - echo 'TEAM_MEMBERS='$teamMembers >> $GITHUB_ENV - env: - GITHUB_TOKEN: ${{ secrets.CUSTOM_TOKEN }} +[Example Using Json Instead Markdown Output](example-using-json-instead-markdown-output.md) - - name: Create issue - uses: peter-evans/create-issue-from-file@v4 - with: - title: Monthly issue metrics report - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./issue_metrics.md - assignees: ${{ env.TEAM_MEMBERS }} -``` +[Assigning Teams Instead Of Individual](assign-team-instead-of-individual.md) -## Local usage without Docker +[Local Usage Without Docker](local-usage-without-docker.md) -1. Make sure you have at least Python3.11 installed -1. Copy `.env-example` to `.env` -1. Fill out the `.env` file with a _token_ from a user that has access to the organization to scan (listed below). Tokens should have admin:org or read:org access. -1. Fill out the `.env` file with the _search_query_ to filter issues by -1. `pip3 install -r requirements.txt` -1. Run `python3 ./issue_metrics.py`, which will output issue metrics data ## License diff --git a/assign-team-instead-of-individual.md b/assign-team-instead-of-individual.md new file mode 100644 index 0000000..3ded090 --- /dev/null +++ b/assign-team-instead-of-individual.md @@ -0,0 +1,60 @@ +## Assigning teams instead of individuals + +The assignee part of this workflow action comes from [a different GitHub action](https://github.com/peter-evans/create-issue-from-file) and currently GitHub issues don't support assigning groups. + +By way of work around, you could use the [GitHub API to retrieve the members of the team](https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#list-team-members) and then put them in a comma separated string that you provide as the assignee. This requires setting up a new GitHub API token (referred to below as `CUSTOM_TOKEN`) which has `read:org` permissions assigned and single sign on authorization as needed. To do this, create a [GitHub API token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with permissions to read the org (`read:org`). Then take the value of the API token you just created, and [create a repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) where the name of the secret is `CUSTOM_TOKEN` and the value of the secret the API token. + +That might look something like the workflow below where `ORG` is your organization name and `TEAM_SLUG` is the name of the team: + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + - cron: '3 2 1 * *' + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + first_day=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "$first_day..$last_day" + echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" + + - name: Run issue-metrics tool + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' + + - name: Get user names from team + run: | + teamMembers="$(gh api /orgs/ORG/teams/TEAM_SLUG/members | jq -r '.[].login' | paste -sd, -)" + echo 'TEAM_MEMBERS='$teamMembers >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.CUSTOM_TOKEN }} + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: ${{ env.TEAM_MEMBERS }} +``` diff --git a/example-using-json-instead-markdown-output.md b/example-using-json-instead-markdown-output.md new file mode 100644 index 0000000..33388af --- /dev/null +++ b/example-using-json-instead-markdown-output.md @@ -0,0 +1,33 @@ + +## Example using the JSON output instead of the markdown output + +There is JSON output available as well. You could use it for any number of possibilities, but here is one example that demonstrates retreiving the JSON output and then printing it out. + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + - cron: '3 2 1 * *' + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + - name: Run issue-metrics tool + id: issue-metrics + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' + + - name: Print output of issue metrics tool + run: echo "${{ steps.issue-metrics.outputs.metrics }}" + +``` \ No newline at end of file diff --git a/example-workflows.md b/example-workflows.md new file mode 100644 index 0000000..7962f50 --- /dev/null +++ b/example-workflows.md @@ -0,0 +1,136 @@ + +### Example workflows + +#### Calculated Time Example +This workflow searches for the issues created last month, and generates an issue with metrics. + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + - cron: '3 2 1 * *' + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + first_day=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "$first_day..$last_day" + echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" + + - name: Run issue-metrics tool + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: + +``` + +#### Fixed Time Example +This workflow searches for the issues created between 2023-05-01..2023-05-31, and generates an issue with metrics. + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + + - name: Run issue-metrics tool + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: + +``` + + +#### Multiple Repositories Example + +This workflow searches for the issues created last month, and generates an issue with metrics. It also searches for issues in a second repository and includes those metrics in the same issue. + +```yaml +name: Monthly issue metrics (Multi Repo) +on: + workflow_dispatch: + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + first_day=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "$first_day..$last_day" + echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" + + - name: Get issue metrics + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo1 repo:owner/repo2 is:issue created:${{ env.last_month }} -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report (dev) + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: +``` + diff --git a/local-usage-without-docker.md b/local-usage-without-docker.md new file mode 100644 index 0000000..80ec365 --- /dev/null +++ b/local-usage-without-docker.md @@ -0,0 +1,8 @@ +## Local usage without Docker + +1. Make sure you have at least Python3.11 installed +1. Copy `.env-example` to `.env` +1. Fill out the `.env` file with a _token_ from a user that has access to the organization to scan (listed below). Tokens should have admin:org or read:org access. +1. Fill out the `.env` file with the _search_query_ to filter issues by +1. `pip3 install -r requirements.txt` +1. Run `python3 ./issue_metrics.py`, which will output issue metrics data diff --git a/measure-time.md b/measure-time.md new file mode 100644 index 0000000..06baab8 --- /dev/null +++ b/measure-time.md @@ -0,0 +1,105 @@ +## Measuring time spent in labels + +**Note**: The discussions API currently doesn't support the `LabeledEvent` so this action cannot measure the time spent in a label for discussions. + +Sometimes it is helpful to know how long an issue or pull request spent in a particular label. This action can be configured to measure the time spent in a label. This is different from only wanting to measure issues with a specific label. If that is what you want, see the section on [configuring your search query](https://github.com/github/issue-metrics/blob/main/README.md#search_query-issues-or-pull-requests-open-or-closed). + +Here is an example workflow that does this: + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + + - name: Run issue-metrics tool + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + LABELS_TO_MEASURE: 'waiting-for-manager-approval,waiting-for-security-review' + SEARCH_QUERY: 'repo:owner/repo is:issue created:2023-05-01..2023-05-31 -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: + +``` + +then the report will look like this: + +```markdown +# Issue Metrics + +| Metric | Value | +| --- | ---: | +| Average time to first response | 0:50:44.666667 | +| Average time to close | 6 days, 7:08:52 | +| Average time to answer | 1 day | +| Average time spent in waiting-for-manager-approval | 0:00:41 | +| Average time spent in waiting-for-security-review | 2 days, 4:25:03 | +| Number of items that remain open | 2 | +| Number of items closed | 1 | +| Total number of items created | 3 | + +| Title | URL | Time to first response | Time to close | Time to answer | Time spent in waiting-for-manager-approval | Time spent in waiting-for-security-review | +| --- | --- | --- | --- | --- | --- | --- | +| Pull Request Title 1 | https://github.com/user/repo/pulls/1 | 0:05:26 | None | None | None | None | +| Issue Title 2 | https://github.com/user/repo/issues/2 | 2:26:07 | None | None | 0:00:41 | 2 days, 4:25:03 | + +``` + +## Example issue_metrics.md output + +Here is the output with no hidden columns: +```markdown +# Issue Metrics + +| Metric | Value | +| --- | ---: | +| Average time to first response | 0:50:44.666667 | +| Average time to close | 6 days, 7:08:52 | +| Average time to answer | 1 day | +| Number of items that remain open | 2 | +| Number of items closed | 1 | +| Total number of items created | 3 | + +| Title | URL | Time to first response | Time to close | Time to answer | +| --- | --- | --- | --- | --- | +| Discussion Title 1 | https://github.com/user/repo/discussions/1 | 0:00:41 | 6 days, 7:08:52 | 1 day | +| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | 0:05:26 | None | None | +| Issue Title 3 | https://github.com/user/repo/issues/3 | 2:26:07 | None | None | + +``` + +Here is the output with all hidable columns hidden: +```markdown +# Issue Metrics + +| Metric | Value | +| --- | ---: | +| Number of items that remain open | 2 | +| Number of items closed | 1 | +| Total number of items created | 3 | + +| Title | URL | +| --- | --- | +| Discussion Title 1 | https://github.com/user/repo/discussions/1 | +| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | +| Issue Title 3 | https://github.com/user/repo/issues/3 | + +``` + diff --git a/search-query.md b/search-query.md new file mode 100644 index 0000000..d8390b6 --- /dev/null +++ b/search-query.md @@ -0,0 +1,75 @@ +## SEARCH_QUERY +Issues or Pull Requests? Open or closed? +This action can be configured to run metrics on discussions, pull requests and/or issues. It is also configurable by whether they were open or closed in the specified time window. Further query options are listed in the [documentation on searching issues and pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) or the [documentation on searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions). Search results are limited to 1000 results by the GitHub API. Here are some search query examples: + +Issues opened in May 2023: +- `repo:owner/repo is:issue created:2023-05-01..2023-05-31` + +Issues closed in May 2023 (may have been open in May or earlier): +- `repo:owner/repo is:issue closed:2023-05-01..2023-05-31` + +Pull requests opened in May 2023: +- `repo:owner/repo is:pr created:2023-05-01..2023-05-31` + +Pull requests closed in May 2023 (may have been open in May or earlier): +- `repo:owner/repo is:pr closed:2023-05-01..2023-05-31` + +Discussions opened in May 2023: +- `repo:owner/repo type:discussions created:2023-05-01..2023-05-31` + +Discussions opened in May 2023 with category of engineering and label of question: +- `repo:owner/repo type:discussions created:2023-05-01..2023-05-31 category:engineering label:"question"` + +Both issues and pull requests opened in May 2023: +- `repo:owner/repo created:2023-05-01..2023-05-31` + +Both issues and pull requests closed in May 2023 (may have been open in May or earlier): +- `repo:owner/repo closed:2023-05-01..2023-05-31` + +OK, but what if I want both open or closed issues and pull requests? Due to limitations in issue search (no ability for OR logic), you will need to run the action twice, once for opened and once for closed. Here is an example workflow that does this: + +```yaml +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + - cron: '3 2 1 * *' + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + + - name: Run issue-metrics tool for issues and prs opened in May 2023 + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo created:2023-05-01..2023-05-31 -reason:"not planned"' + + - name: Create issue for opened issues and prs + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report for opened issues and prs + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: + + - name: Run issue-metrics tool for issues and prs closed in May 2023 + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:owner/repo closed:2023-05-01..2023-05-31 -reason:"not planned"' + + - name: Create issue for closed issues and prs + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report for closed issues and prs + content-filepath: ./issue_metrics.md + assignees: +``` \ No newline at end of file From 601a774e2c5f522b4ed08a26489a3af3be20133b Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 16:30:32 +0900 Subject: [PATCH 02/10] del: .idea --- .idea/.gitignore | 8 -------- .idea/inspectionProfiles/Project_Default.xml | 18 ------------------ .idea/inspectionProfiles/profiles_settings.xml | 6 ------ .idea/issue-metrics.iml | 12 ------------ .idea/misc.xml | 4 ---- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 7 files changed, 62 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/issue-metrics.iml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index f9f69bd..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/issue-metrics.iml b/.idea/issue-metrics.iml deleted file mode 100644 index 8a05c6e..0000000 --- a/.idea/issue-metrics.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 141de14..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index cba9a62..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From fdc61eac77839c0024534d8e5f4a4d5d9f0d868f Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 16:30:59 +0900 Subject: [PATCH 03/10] fix: gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4f03760..0f01f75 100644 --- a/.gitignore +++ b/.gitignore @@ -143,4 +143,7 @@ cython_debug/ # Mac .DS_Store -**/.DS_Store \ No newline at end of file +**/.DS_Store + +# PyCharm +.idea/ From ef303e56d7b211cd11b7f1d6d0882496ddd25753 Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 17:27:10 +0900 Subject: [PATCH 04/10] fix: mkdir docs && mv *.md docs/*.md --- CONTRIBUTING.md => docs/CONTRIBUTING.md | 0 .../assign-team-instead-of-individual.md | 0 .../example-using-json-instead-markdown-output.md | 0 example-workflows.md => docs/example-workflows.md | 0 .../local-usage-without-docker.md | 0 measure-time.md => docs/measure-time.md | 0 search-query.md => docs/search-query.md | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING.md => docs/CONTRIBUTING.md (100%) rename assign-team-instead-of-individual.md => docs/assign-team-instead-of-individual.md (100%) rename example-using-json-instead-markdown-output.md => docs/example-using-json-instead-markdown-output.md (100%) rename example-workflows.md => docs/example-workflows.md (100%) rename local-usage-without-docker.md => docs/local-usage-without-docker.md (100%) rename measure-time.md => docs/measure-time.md (100%) rename search-query.md => docs/search-query.md (100%) diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to docs/CONTRIBUTING.md diff --git a/assign-team-instead-of-individual.md b/docs/assign-team-instead-of-individual.md similarity index 100% rename from assign-team-instead-of-individual.md rename to docs/assign-team-instead-of-individual.md diff --git a/example-using-json-instead-markdown-output.md b/docs/example-using-json-instead-markdown-output.md similarity index 100% rename from example-using-json-instead-markdown-output.md rename to docs/example-using-json-instead-markdown-output.md diff --git a/example-workflows.md b/docs/example-workflows.md similarity index 100% rename from example-workflows.md rename to docs/example-workflows.md diff --git a/local-usage-without-docker.md b/docs/local-usage-without-docker.md similarity index 100% rename from local-usage-without-docker.md rename to docs/local-usage-without-docker.md diff --git a/measure-time.md b/docs/measure-time.md similarity index 100% rename from measure-time.md rename to docs/measure-time.md diff --git a/search-query.md b/docs/search-query.md similarity index 100% rename from search-query.md rename to docs/search-query.md From f8ed1f1691d92091a34ecf1acc8fc374c9ce3e8b Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 17:31:53 +0900 Subject: [PATCH 05/10] fix: mv docs/CONTRIBUTING.md CONTRIBUTING.md --- docs/CONTRIBUTING.md => CONTRIBUTING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/CONTRIBUTING.md => CONTRIBUTING.md (100%) diff --git a/docs/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 100% rename from docs/CONTRIBUTING.md rename to CONTRIBUTING.md From 4bd452d24694fcb7590709c1eab422f04fe9aa6c Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 17:32:08 +0900 Subject: [PATCH 06/10] fix: linter error --- README.md | 58 +++++++++++-------------------------------------------- 1 file changed, 11 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 26332a4..9ad63c6 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,9 @@ -# Table of Contents -- [Issue Metrics Action](#issue-metrics-action) - - [Example use cases](#example-use-cases) - - [Support](#support) - - [Use as a GitHub Action](#use-as-a-github-action) - - [Configuration](#configuration) - - [Example workflows](#example-workflows) - - [Calculated Time Example](#calculated-time-example) - - [Fixed Time Example](#fixed-time-example) - - [Multiple Repositories Example](#multiple-repositories-example) - - [SEARCH_QUERY](#search_query) - - [Measuring time spent in labels](#measuring-time-spent-in-labels) - - [Example issue_metrics.md output](#example-issue_metricsmd-output) - - [Example using the JSON output instead of the markdown output](#example-using-the-json-output-instead-of-the-markdown-output) - - [Assigning teams instead of individuals](#assigning-teams-instead-of-individuals) - - [Local usage without Docker](#local-usage-without-docker) - - [License](#license) - - # Issue Metrics Action [![CodeQL](https://github.com/github/issue-metrics/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/codeql-analysis.yml) [![Docker Image CI](https://github.com/github/issue-metrics/actions/workflows/docker-image.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/docker-image.yml) [![Python package](https://github.com/github/issue-metrics/actions/workflows/python-package.yml/badge.svg)](https://github.com/github/issue-metrics/actions/workflows/python-package.yml) -This is a GitHub Action that searches for pull requests/issues/discussions in a repository -and measures and reports on several metrics. The issues/pull requests/discussions to -search for can be filtered by using a search query. +This is a GitHub Action that searches for issues/pull requests/discussions in a repository and measures and reports on several metrics. +The issues/pull requests/discussions to search for can be filtered by using a search query. | Metric | Description | |--------|-------------| @@ -32,8 +12,8 @@ search for can be filtered by using a search query. |Time to Answer (Discussions Only) | The time from creation to an answer.| |Time in Label | The duration from label application to removal, requires LABELS_TO_MEASURE env variable.| -*For pull requests, these metrics exclude the time the PR was in draft mode. -*For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded. +* For pull requests, these metrics exclude the time the PR was in draft mode. +* For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded. This action, developed by GitHub OSPO for our internal use, is open-sourced for your potential benefit. Feel free to inquire about its usage by creating an issue in this repository. @@ -50,7 +30,6 @@ or the [documentation on searching discussions](https://docs.github.com/en/searc |OSPO Insights| Track open source request status and processing times.| |Review Efficiency| Analyze PR review durations for retrospectives.| - ## Support If you need support using this project or have questions about it, please [open up an issue in this repository](https://github.com/github/issue-metrics/issues). Requests made directly to GitHub staff or support team will be redirected here to open an issue. GitHub SLA's and support/services contracts do not apply to this repository. @@ -58,14 +37,13 @@ If you need support using this project or have questions about it, please [open ## Use as a GitHub Action 1. Create a repository to host this GitHub Action or select an existing repository. This is easiest if it is the same repository as the one you want to measure metrics on. -1. Select a best fit workflow file from the [examples below](#example-workflows). -1. Copy that example into your repository (from step 1) and into the proper directory for GitHub Actions: `.github/workflows/` directory with the file extension `.yml` (ie. `.github/workflows/issue-metrics.yml`) -1. Edit the values (`SEARCH_QUERY`, `assignees`) from the sample workflow with your information. See the [SEARCH_QUERY](#search_query) section for more details on options. -1. If you are running metrics on a repository other than the one where the workflow file is going to be, then update the value of `GH_TOKEN`. Do this by creating a [GitHub API token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with permissions to read the repo and write issues. Then take the value of the API token you just created, and [create a repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) where the name of the secret is `GH_TOKEN` and the value of the secret the API token. Then finally update the workflow file to use that repository secret by changing `GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` to `GH_TOKEN: ${{ secrets.GH_TOKEN }}`. The name of the secret can really be anything. It just needs to match between when you create the secret name and when you refer to it in the workflow file. -1. If you want the resulting issue with the metrics in it to appear in a different repository other than the one the workflow file runs in, update the line `token: ${{ secrets.GITHUB_TOKEN }}` with your own GitHub API token stored as a repository secret. This process is the same as described in the step above. More info on creating secrets can be found [here](https://docs.github.com/en/actions/security-guides/encrypted-secrets). -1. Commit the workflow file to the default branch (often `master` or `main`) -1. Wait for the action to trigger based on the `schedule` entry or manually trigger the workflow as shown in the [documentation](https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow). - +2. Select a best fit workflow file from the [examples directory](./docs/example-workflows.md) for your use case. +3. Copy that example into your repository (from step 1) and into the proper directory for GitHub Actions: `.github/workflows/` directory with the file extension `.yml` (ie. `.github/workflows/issue-metrics.yml`) +4. Edit the values (`SEARCH_QUERY`, `assignees`) from the sample workflow with your information. See the [SEARCH_QUERY](./docs/search-query.md) section for more information on how to configure the search query. +5. If you are running metrics on a repository other than the one where the workflow file is going to be, then update the value of `GH_TOKEN`. Do this by creating a [GitHub API token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) with permissions to read the repo and write issues. Then take the value of the API token you just created, and [create a repository secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) where the name of the secret is `GH_TOKEN` and the value of the secret the API token. Then finally update the workflow file to use that repository secret by changing `GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` to `GH_TOKEN: ${{ secrets.GH_TOKEN }}`. The name of the secret can really be anything. It just needs to match between when you create the secret name and when you refer to it in the workflow file. +6. If you want the resulting issue with the metrics in it to appear in a different repository other than the one the workflow file runs in, update the line `token: ${{ secrets.GITHUB_TOKEN }}` with your own GitHub API token stored as a repository secret. This process is the same as described in the step above. More info on creating secrets can be found [here](https://docs.github.com/en/actions/security-guides/encrypted-secrets). +7. Commit the workflow file to the default branch (often `master` or `main`) +8. Wait for the action to trigger based on the `schedule` entry or manually trigger the workflow as shown in the [documentation](https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow). ### Configuration @@ -83,20 +61,6 @@ Below are the allowed configuration options: | `HIDE_LABEL_METRICS` | False | | If set to any value, the time in label metrics will not be displayed in the generated markdown file. | | `IGNORE_USERS` | False | | A comma separated list of users to ignore when calculating metrics. (ie. `IGNORE_USERS: 'user1,user2'`). To ignore bots, append `[bot]` to the user (ie. `IGNORE_USERS: 'github-actions[bot]'`) | - -[Example workflows](example-workflows.md) - -[Search Query](search-query.md) - -[Measuring Time Spent](measure-time.md) - -[Example Using Json Instead Markdown Output](example-using-json-instead-markdown-output.md) - -[Assigning Teams Instead Of Individual](assign-team-instead-of-individual.md) - -[Local Usage Without Docker](local-usage-without-docker.md) - - ## License [MIT](LICENSE) From f404fc3b47749734efa64b832a9b972ec87193da Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Wed, 11 Oct 2023 17:36:50 +0900 Subject: [PATCH 07/10] fix: linter error (docs/*.md) --- docs/assign-team-instead-of-individual.md | 2 +- docs/example-using-json-instead-markdown-output.md | 5 ++--- docs/example-workflows.md | 11 +++++------ docs/local-usage-without-docker.md | 2 +- docs/measure-time.md | 5 +++-- docs/search-query.md | 13 +++++++++++-- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/docs/assign-team-instead-of-individual.md b/docs/assign-team-instead-of-individual.md index 3ded090..6b2b6e6 100644 --- a/docs/assign-team-instead-of-individual.md +++ b/docs/assign-team-instead-of-individual.md @@ -1,4 +1,4 @@ -## Assigning teams instead of individuals +# Assigning teams instead of individuals The assignee part of this workflow action comes from [a different GitHub action](https://github.com/peter-evans/create-issue-from-file) and currently GitHub issues don't support assigning groups. diff --git a/docs/example-using-json-instead-markdown-output.md b/docs/example-using-json-instead-markdown-output.md index 33388af..0396b54 100644 --- a/docs/example-using-json-instead-markdown-output.md +++ b/docs/example-using-json-instead-markdown-output.md @@ -1,5 +1,4 @@ - -## Example using the JSON output instead of the markdown output +# Example using the JSON output instead of the markdown output There is JSON output available as well. You could use it for any number of possibilities, but here is one example that demonstrates retreiving the JSON output and then printing it out. @@ -30,4 +29,4 @@ jobs: - name: Print output of issue metrics tool run: echo "${{ steps.issue-metrics.outputs.metrics }}" -``` \ No newline at end of file +``` diff --git a/docs/example-workflows.md b/docs/example-workflows.md index 7962f50..b4fc8ff 100644 --- a/docs/example-workflows.md +++ b/docs/example-workflows.md @@ -1,7 +1,7 @@ +# Example workflows -### Example workflows +## Calculated Time Example -#### Calculated Time Example This workflow searches for the issues created last month, and generates an issue with metrics. ```yaml @@ -51,7 +51,8 @@ jobs: ``` -#### Fixed Time Example +## Fixed Time Example + This workflow searches for the issues created between 2023-05-01..2023-05-31, and generates an issue with metrics. ```yaml @@ -86,8 +87,7 @@ jobs: ``` - -#### Multiple Repositories Example +## Multiple Repositories Example This workflow searches for the issues created last month, and generates an issue with metrics. It also searches for issues in a second repository and includes those metrics in the same issue. @@ -133,4 +133,3 @@ jobs: content-filepath: ./issue_metrics.md assignees: ``` - diff --git a/docs/local-usage-without-docker.md b/docs/local-usage-without-docker.md index 80ec365..2273d86 100644 --- a/docs/local-usage-without-docker.md +++ b/docs/local-usage-without-docker.md @@ -1,4 +1,4 @@ -## Local usage without Docker +# Local usage without Docker 1. Make sure you have at least Python3.11 installed 1. Copy `.env-example` to `.env` diff --git a/docs/measure-time.md b/docs/measure-time.md index 06baab8..3547100 100644 --- a/docs/measure-time.md +++ b/docs/measure-time.md @@ -1,4 +1,4 @@ -## Measuring time spent in labels +# Measuring time spent in labels **Note**: The discussions API currently doesn't support the `LabeledEvent` so this action cannot measure the time spent in a label for discussions. @@ -65,6 +65,7 @@ then the report will look like this: ## Example issue_metrics.md output Here is the output with no hidden columns: + ```markdown # Issue Metrics @@ -86,6 +87,7 @@ Here is the output with no hidden columns: ``` Here is the output with all hidable columns hidden: + ```markdown # Issue Metrics @@ -102,4 +104,3 @@ Here is the output with all hidable columns hidden: | Issue Title 3 | https://github.com/user/repo/issues/3 | ``` - diff --git a/docs/search-query.md b/docs/search-query.md index d8390b6..9996483 100644 --- a/docs/search-query.md +++ b/docs/search-query.md @@ -1,29 +1,38 @@ -## SEARCH_QUERY +# SEARCH_QUERY + Issues or Pull Requests? Open or closed? This action can be configured to run metrics on discussions, pull requests and/or issues. It is also configurable by whether they were open or closed in the specified time window. Further query options are listed in the [documentation on searching issues and pull requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests) or the [documentation on searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions). Search results are limited to 1000 results by the GitHub API. Here are some search query examples: Issues opened in May 2023: + - `repo:owner/repo is:issue created:2023-05-01..2023-05-31` Issues closed in May 2023 (may have been open in May or earlier): + - `repo:owner/repo is:issue closed:2023-05-01..2023-05-31` Pull requests opened in May 2023: + - `repo:owner/repo is:pr created:2023-05-01..2023-05-31` Pull requests closed in May 2023 (may have been open in May or earlier): + - `repo:owner/repo is:pr closed:2023-05-01..2023-05-31` Discussions opened in May 2023: + - `repo:owner/repo type:discussions created:2023-05-01..2023-05-31` Discussions opened in May 2023 with category of engineering and label of question: + - `repo:owner/repo type:discussions created:2023-05-01..2023-05-31 category:engineering label:"question"` Both issues and pull requests opened in May 2023: + - `repo:owner/repo created:2023-05-01..2023-05-31` Both issues and pull requests closed in May 2023 (may have been open in May or earlier): + - `repo:owner/repo closed:2023-05-01..2023-05-31` OK, but what if I want both open or closed issues and pull requests? Due to limitations in issue search (no ability for OR logic), you will need to run the action twice, once for opened and once for closed. Here is an example workflow that does this: @@ -72,4 +81,4 @@ jobs: title: Monthly issue metrics report for closed issues and prs content-filepath: ./issue_metrics.md assignees: -``` \ No newline at end of file +``` From 659c287446fda32d1d830c23deaf678353c93533 Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Thu, 12 Oct 2023 17:21:13 +0900 Subject: [PATCH 08/10] fix: footnotes --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6c89860..f1f8d1b 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,8 @@ The issues/pull requests/discussions to search for can be filtered by using a se |Time to Answer (Discussions Only) | The time from creation to an answer.| |Time in Label | The duration from label application to removal, requires LABELS_TO_MEASURE env variable.| - -* For pull requests, these metrics exclude the time the PR was in draft mode. -* For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded. +*For pull requests, these metrics exclude the time the PR was in draft mode. +*For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded. This action, developed by GitHub OSPO for our internal use, is open-sourced for your potential benefit. Feel free to inquire about its usage by creating an issue in this repository. From 1b6d343111bc79863010ae787e429f9f23d62163 Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Thu, 12 Oct 2023 17:24:49 +0900 Subject: [PATCH 09/10] reverted the changes to "Example use cases" --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f1f8d1b..046bc3d 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,10 @@ or the [documentation on searching discussions](https://docs.github.com/en/searc ## Example use cases -| Metric | Description | -|--------|-------------| -|Maintainer Metrics| Monitor issue and pull request metrics for effective attention.| -|Timely Response| Ensure prompt user contact as a first responder.| -|OSPO Insights| Track open source request status and processing times.| -|Review Efficiency| Analyze PR review durations for retrospectives.| +- As a maintainer, I want to see metrics for issues and pull requests on the repository I maintain in order to ensure I am giving them the proper amount of attention. +- As a first responder on a repository, I want to ensure that users are getting contact from me in a reasonable amount of time. +- As an OSPO, I want to see how many open source repository requests are open/closed, and metrics for how long it takes to get through the open source process. +- As a product development team, I want to see metrics around how long pull request reviews are taking, so that we can reflect on that data during retrospectives. ## Support From 48e73e00f645f3f355b19195558cf7299a66c428 Mon Sep 17 00:00:00 2001 From: Junya Okabe Date: Thu, 12 Oct 2023 17:29:49 +0900 Subject: [PATCH 10/10] add: links sections --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 046bc3d..8bc26cf 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,15 @@ Below are the allowed configuration options: | `HIDE_LABEL_METRICS` | False | | If set to any value, the time in label metrics will not be displayed in the generated markdown file. | | `IGNORE_USERS` | False | | A comma separated list of users to ignore when calculating metrics. (ie. `IGNORE_USERS: 'user1,user2'`). To ignore bots, append `[bot]` to the user (ie. `IGNORE_USERS: 'github-actions[bot]'`) | +## Links + +- [Assigning teams instead of individuals](./docs/assign-team-instead-of-individual.md) +- [Example using the JSON output instead of the markdown output](./docs/example-using-json-instead-markdown-output.md) +- [Example workflows](./docs/example-workflows.md) +- [Local usage without Docker](./docs/local-usage-without-docker.md) +- [Measuring time spent in labels](./docs/measure-time.md) +- [SEARCH_QUERY](./docs/search-query.md) + ## License [MIT](LICENSE)