{"id":18889052,"url":"https://github.com/naver/pr-stats","last_synced_at":"2025-04-04T14:05:43.802Z","repository":{"id":206390692,"uuid":"716001942","full_name":"naver/pr-stats","owner":"naver","description":"PR에 대한 유용한 통계를 산출하는 GitHub Actions","archived":false,"fork":false,"pushed_at":"2024-12-10T05:19:44.000Z","size":784,"stargazers_count":195,"open_issues_count":0,"forks_count":12,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-28T13:11:10.833Z","etag":null,"topics":["dev-culture","github-actions","pr-review","pr-stats","pull-request","statistics","stats"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/naver.png","metadata":{"files":{"readme":"README.en.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-08T09:19:51.000Z","updated_at":"2025-03-13T13:59:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"e7a24e5a-8389-496f-ae8c-6fa490659ddc","html_url":"https://github.com/naver/pr-stats","commit_stats":null,"previous_names":["naver/pr-stats"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naver%2Fpr-stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naver%2Fpr-stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naver%2Fpr-stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naver%2Fpr-stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/naver","download_url":"https://codeload.github.com/naver/pr-stats/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247190248,"owners_count":20898702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dev-culture","github-actions","pr-review","pr-stats","pull-request","statistics","stats"],"created_at":"2024-11-08T07:47:17.732Z","updated_at":"2025-04-04T14:05:43.780Z","avatar_url":"https://github.com/naver.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pr-stats\n\n🌏 [**한국어**](README.md) | English\n\nGitHub Actions to generate useful statistics for pull requests.\n\nIt calculates metrics such as the average time to merge per PR and reviewer response times. The statistics can be [customized](#Customize) as needed.\n\nFor ways to apply it in your tasks, see the [usage examples](#Usage-examples).\n\n## Usage\n\nCreate the following file in your GitHub repository:\n\n```yaml\n# .github/workflows/pr-stats.yml\nname: PR Stats\non:\n  workflow_dispatch: # Specify the event that triggers the action\n  # https://docs.github.com/ko/actions/using-workflows/events-that-trigger-workflows\njobs:\n  pr-stats:\n    runs-on: ubuntu-latest\n    steps:\n      - name: PR Stats\n        uses: \"naver/pr-stats@v1.0.0\" # Path to the action and the version to use\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          # Be sure to check the documentation for 'with'.\n```\n\n**Usage example) Generate results as a PR**\n\n```yaml\n# .github/workflows/pr-stats.yml\n    # ...\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: PR Stats\n        uses: \"naver/pr-stats@v1.0.0\"\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@v5\n```\n\nWith this setup, a PR will be created with `pr.csv`, `prList.csv`, and `user.csv` files under the `./stats/` directory.\n\n\n## Collected Data\n\n### PR\n\nStatistics for individual PRs. This data is saved as `./stats/pr.csv`.\n\n| Field                         | Description                       |\n|-------------------------------|-----------------------------------|\n| `number`                      | PR number                         |\n| `title`                       | PR title                          |\n| `createdAt`                   | Timestamp of PR creation          |\n| `mergedAt`                    | Timestamp of PR merged            |\n| `addedLineCount`              | Number of lines added             |\n| `removedLineCount`            | Number of lines removed           |\n| `changedLineCount`            | Number of lines changed           |\n| `fileCount`                   | Number of files                   |\n| `commitCount`                 | Number of commits                 |\n| `commentCount`                | Number of comments                |\n| `conversationCount`           | Number of conversations           |\n| `reviewerCount`               | Number of reviewers               |\n| `approvalCount`               | Number of approvals               |\n| `participationCount`          | Number of participations          |\n| `participationRate`           | Participation rate                |\n| `timeFromReviewToMerge`       | Time from review to merge (ms)    |\n| `averageResponseTime`         | Average response time (ms)        |\n| `averageTimeToApproval`       | Average time to approval (ms)     |\n| `averageLinesChangedPerCommit` | Average lines changed per commit  |\n\n### PR list\n\nStatistics calculated for all collected PRs. This data is saved as `./stats/prList.csv`.\n\n| Field                          | Description          |\n|--------------------------------|----------------------|\n| `averageAddedLineCount`      | Average number of added lines    |\n| `averageRemovedLineCount`    | Average number of removed lines  |\n| `averageChangedLineCount`    | Average number of changed lines  |\n| `averageFileCount`           | Average number of files          |\n| `averageCommitCount`         | Average number of commits        |\n| `averageCommentCount`        | Average number of comments       |\n| `averageConversationCount`   | Average number of conversations  |\n| `averageReviewerCount`       | Average number of reviewers      |\n| `averageApprovalCount`       | Average number of approvals      |\n| `averageParticipationCount`  | Average number of participations |\n| `averageTimeFromReviewToMerge` | Average time from review to merge (ms) |\n| `averageResponseTime`        | Average response time (ms)       |\n| `averageTimeToApproval`      | Average time to approval (ms)    |\n| `averageLinesChangedPerCommit` | Average lines changed per commit |\n| `participationRate`          | Participation rate               |\n\n### User\n\nStatistics calculated for each user from the collected data. This data is saved as `./stats/user.csv`.\n\n| Field                         | Description                        |\n|------------------------------|------------------------------------|\n| `id`                         | User ID                            |\n| `requestedCount`             | Number of requests received        |\n| `participationCount`         | Number of participations           |\n| `participationRate`          | Participation rate (xx.xx)         |\n| `averageCommentCount`        | Average number of comments         |\n| `averageResponseTime`        | Average response time (ms)         |\n| `averageTimeToApproval`      | Average time to approval (ms)      |\n| `averageLinesChangedPerCommit` | Average lines changed per commit   |\n\n## Customize\n\nBy adding a `stats.config.js` file to the root of your repository, you can modify the statistics to be output.\n\n\u003e The `stats.config.js` file is optional. If it's not created, the default behavior will be used.\n\n\n### Controlling statistics fields\n\nFor example, if you configure it like this, `pr` will output `number`, `title`, and `fileCount` fields, `prList` will not be output, and `user` will only output the `id`.\n\n```javascript\n// {targetRepo}/stats.config.js\nmodule.exports = {\n    pr: [\"number\", \"title\", \"fileCount\"],\n    prList: [],\n    user: [\"id\"],\n};\n```\n\n### Adding statistics fields\n\nThe default statistics configuration (`defaultStats`) is passed as an argument to the exported function. This allows you to maintain the default statistics settings while adding specific statistics.\n\nHere's an example of calculating the fastest response time(ms).\n\n```javascript\n// {targetRepo}/stats.config.js\nconst firstResponseTime = pr =\u003e {\n    const {timeline} = pr;\n    const firstResponse = timeline.comments.find(comment =\u003e timeline.firstRequestedAt \u003c comment.createdAt);\n    const value = Number(firstResponse.createdAt) - Number(timeline.firstRequestedAt);\n\n    return {value, message: `First Response Time: ${value}`};\n};\n\nmodule.exports = defaultStats =\u003e {\n    return {\n        ...defaultStats,\n        pr: [...defaultStats.pr, [\"firstResponseTime\", firstResponseTime]],\n    };\n};\n```\n\n## `with` parameters\n\n| Name            | Description                                                                                                                                             | Default value                 | Example usage                                                      |\n|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|--------------------------------------------------------------------|\n| `token`         | GitHub token                                                                                                                                            | `${{ secrets.GITHUB_TOKEN }}` | `token: \"xoxb-798572638592-435243279588-9aCaWNnzVYelK9NzMMqa1yxz\"` |\n| `repository`    | The repository where `pr-stats` will run. If not provided, it defaults to the repository where the `pr-stats.yml` file is located.                      | `${{ github.repository }}`    | `repository: \"organization/repository\"`                            |\n| `ignoreUsers`   | List of users to exclude from PR statistics. Multiple users can be added, separated by commas.                                                          | `\"\"` (empty string)           | `ignoreUsers: \"brown\"`\u003cbr\u003e`ignoreUsers: \"sonarqube[bot],lee-load\"` |\n| `configPath`    | The path to the statistics configuration file.                                                                                                          | `\"./stats.config.js\"`         | `configPath: \"./settings/stats.config.js\"`                         |\n| `period`        | Specifies the period for PR statistics. If not provided, `count` will be used.                                                                          | `\"\"` (empty string)           | `period: \"2023-09-01~2023-10-01\"`\u003cbr\u003e`period: \"2023-09-01~\"`       |\n| `count`         | Specifies the number of PRs to fetch. If not provided, `period` will be used.                                                                           | `100`                         | `count: 50`                                                        |\n| `baseBranch`    | Specifies the branch to target for statistics. It extracts statistics for PRs where this branch is the base. If not provided, all PRs will be targeted. | `\"\"` (empty string)           | `baseBranch: \"main\"`                                               |\n| `output`        | Specifies the data output format. Multiple formats can be used, separated by commas. (Valid formats: `console`, `csv`)                                  | `\"console,csv\"`               | `output: \"csv\"`                                                    |\n\n\u003e ⚠️ The `period` parameter takes precedence over `count`; if `period` is provided, `count` will be ignored.\n\n## Usage examples\nUsing this action, you can clearly understand your team's code review status and identify areas for improvement.\n\n### 1. Analysis through a correlation table\n\nFor example, using Python code or generative AI, you can create a correlation table like the one below based on PR statistics.\n\n\u003cimg src=\"https://github.com/user-attachments/assets/42774705-ae06-4bed-aff9-17e4c82034a1\" width=\"600\" height=\"600\" alt=\"correlation-heatmap\"\u003e\n\nIf you want to shorten the time it takes to merge, you could find metrics with a high correlation to `timeFromReviewToMerge` and focus on improving them.\n\n### 2. Analysis through scatter plots\n\nYou can assess how much progress has been made by analyzing numerical changes.\n\nFor example, to see how much the review response time and participation rate of team members have improved, you can use scatter plots and density charts like the ones below.\n\n\u003cimg width=\"700\" alt=\"before\" src=\"https://github.com/user-attachments/assets/1b6be920-45ae-4483-95fb-711fdc24c10f\"\u003e\n\nIn the scatter plot on the left, each point represents the average response time and participation rate of a reviewer. Points closer to the top-left indicate higher participation and shorter response times.\n\nIf the chart looks like the one below after improvement activities, it shows that the efforts were highly successful.\n\n\u003cimg width=\"700\" alt=\"after\" src=\"https://github.com/user-attachments/assets/30ac9605-aa41-4cfa-a46b-ac32396172a2\"\u003e\n\n\n## License\n\n```\nCopyright (c) 2023-present NAVER Corp.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaver%2Fpr-stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnaver%2Fpr-stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaver%2Fpr-stats/lists"}