├── images └── title.png ├── README.md └── .github └── workflows ├── create_issue_on_label.yml ├── create_issue.yml └── comment_issue.yml /images/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codacy/tools-for-code-review-engineers/HEAD/images/title.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # List of tools for code review engineers 2 | 3 | ![List of tools for code review engineers](images/title.png) 4 | 5 | If you perform code reviews at your company we hope that this list of tools adds value to your GitHub workflow. 6 | We created this list recently and we'll periodically keep adding more tools. 7 | Feel free to contribute your suggestions. 8 | 9 | | Tool | Description | 10 | | ---- | ----------- | 11 | | [Gitpod](https://gitpod.io/) | Always ready to code - spin up fresh, automated dev environments for each task, in the cloud, in seconds. 12 | Gitpod is an open-source developer platform automating the provisioning of ready-to-code developer environments. | 13 | | [Pull Reminders](https://pullreminders.com/) (from Pull Panda) | Review and merge pull requests faster with Slack reminders and notifications. | 14 | | [Pull Assigner](https://pullpanda.com/assigner) (from Pull Panda) | Pull Assigner assigns code reviews to make your process more balanced and efficient: 1) Organize reviewers into groups using GitHub Teams 2) Assign pull requests to teams or automate it with CODEOWNERS 3) Pull Assigner auto-assigns one or more members of the team as reviewers. | 15 | | [Gitify](https://www.gitify.io/) | Gitify is all about making your life easier. Sitting on your menu bar, it informs you of any GitHub notifications without being annoying and of course without adverts. It just gets the job done. Works with GitHub and GitHub Enterprise. You can even connect multiple accounts. | 16 | | [Quests](https://steamclock.com/quests/) | Quests is similar to Gitify but with one important difference: Quest also supports GitLab. | 17 | | [DevHub](https://devhubapp.com/) | Create columns for the repositories and people that matter to you; Receive Desktop Push Notifications; Manage Notifications, Issues, Pull Requests & Activities; Bookmark things for later. | 18 | | [Bolt](https://www.whitesourcesoftware.com/free-developer-tools/bolt) | Designed to close the gap between code development and security, Bolt helps GitHub developers create more secure products. It detects and alerts you of vulnerable open source components in your repository. | 19 | | [Imgbot](https://imgbot.net/) | Imgbot is a friendly robot that optimizes your images and saves you time by leveraging the power of pull requests. | 20 | | [Codelantis](https://www.codelantis.com/) | Designed specifically for doing code reviews, Codelantis makes it a breeze to review GitLab merge requests (or GitHub pull requests). | 21 | | [Reviewpad](https://reviewpad.com) | Reviewpad is a code review tool for GitHub, GitLab and Bitbucket that simplifies the review process by allowing developers to navigate through changes and comments easily, mitigate git conflicts and access comments from previous code reviews. It supports the ability to review code without pull requests and provides an automated kanban of pull requests to easily identify bottlenecks in the review process. | 22 | -------------------------------------------------------------------------------- /.github/workflows/create_issue_on_label.yml: -------------------------------------------------------------------------------- 1 | name: Create issue on Jira when labeled with JIRA_ISSUE_LABEL 2 | 3 | on: 4 | issues: 5 | types: [labeled] 6 | 7 | jobs: 8 | jira: 9 | env: 10 | JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Start workflow if GitHub issue is tagged with JIRA_ISSUE_LABEL 15 | if: github.event.label.name == env.JIRA_ISSUE_LABEL 16 | run: echo "Starting workflow" 17 | 18 | - name: Jira Login 19 | if: github.event.label.name == env.JIRA_ISSUE_LABEL 20 | id: login 21 | uses: atlassian/gajira-login@v2.0.0 22 | env: 23 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 24 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 25 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 26 | 27 | - name: Jira Create issue 28 | if: github.event.label.name == env.JIRA_ISSUE_LABEL 29 | id: create_jira_issue 30 | uses: atlassian/gajira-create@v2.0.1 31 | with: 32 | project: ${{ secrets.JIRA_PROJECT }} 33 | issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} 34 | summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}" 35 | description: | 36 | ${{ github.event.issue.body }} 37 | ---- 38 | {panel} 39 | _[Github permalink |${{ github.event.issue.html_url }}]_ 40 | {panel} 41 | 42 | - name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined 43 | if: github.event.label.name == env.JIRA_ISSUE_LABEL && env.JIRA_UPDATE_ISSUE_BODY != '' 44 | env: 45 | JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }} 46 | run: > 47 | curl 48 | -u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }} 49 | -X PUT 50 | -H 'Content-Type: application/json' 51 | -d '${{ env.JIRA_UPDATE_ISSUE_BODY }}' 52 | ${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }} 53 | 54 | - name: Change Title 55 | if: github.event.label.name == env.JIRA_ISSUE_LABEL 56 | uses: actions/github-script@v2.0.0 57 | env: 58 | JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }} 59 | GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }} 60 | with: 61 | github-token: ${{secrets.GITHUB_TOKEN}} 62 | script: | 63 | const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}` 64 | github.issues.update({ 65 | issue_number: context.issue.number, 66 | owner: context.repo.owner, 67 | repo: context.repo.repo, 68 | title: newTitle 69 | }) 70 | 71 | - name: Add comment after sync 72 | if: github.event.label.name == env.JIRA_ISSUE_LABEL 73 | uses: actions/github-script@v2.0.0 74 | with: 75 | github-token: ${{secrets.GITHUB_TOKEN}} 76 | script: | 77 | github.issues.createComment({ 78 | issue_number: context.issue.number, 79 | owner: context.repo.owner, 80 | repo: context.repo.repo, 81 | body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})' 82 | }) 83 | -------------------------------------------------------------------------------- /.github/workflows/create_issue.yml: -------------------------------------------------------------------------------- 1 | name: Create issue on Jira 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | jobs: 8 | jira: 9 | env: 10 | JIRA_CREATE_ISSUE_AUTO: ${{ secrets.JIRA_CREATE_ISSUE_AUTO }} 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Start workflow if JIRA_CREATE_ISSUE_AUTO is enabled 15 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' 16 | run: echo "Starting workflow" 17 | 18 | - name: Jira Login 19 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' 20 | id: login 21 | uses: atlassian/gajira-login@v2.0.0 22 | env: 23 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 24 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 25 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 26 | 27 | - name: Jira Create issue 28 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' 29 | id: create_jira_issue 30 | uses: atlassian/gajira-create@v2.0.1 31 | with: 32 | project: ${{ secrets.JIRA_PROJECT }} 33 | issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} 34 | summary: "[GH#${{ github.event.issue.number }}] ${{ github.event.issue.title }}" 35 | description: | 36 | ${{ github.event.issue.body }} 37 | ---- 38 | {panel} 39 | _[Github permalink |${{ github.event.issue.html_url }}]_ 40 | {panel} 41 | 42 | - name: Update Jira issue if JIRA_UPDATE_ISSUE_BODY is defined 43 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' && env.JIRA_UPDATE_ISSUE_BODY != '' 44 | env: 45 | JIRA_UPDATE_ISSUE_BODY: ${{ secrets.JIRA_UPDATE_ISSUE_BODY }} 46 | run: > 47 | curl 48 | -u ${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }} 49 | -X PUT 50 | -H 'Content-Type: application/json' 51 | -d '${{ env.JIRA_UPDATE_ISSUE_BODY }}' 52 | ${{ secrets.JIRA_BASE_URL }}/rest/api/2/issue/${{ steps.create_jira_issue.outputs.issue }} 53 | 54 | - name: Update GitHub issue 55 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' 56 | uses: actions/github-script@v2.0.0 57 | env: 58 | JIRA_ISSUE_NUMBER: ${{ steps.create_jira_issue.outputs.issue }} 59 | GITHUB_ORIGINAL_TITLE: ${{ github.event.issue.title }} 60 | JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} 61 | with: 62 | github-token: ${{secrets.GITHUB_TOKEN}} 63 | script: | 64 | const newTitle = `[${process.env.JIRA_ISSUE_NUMBER}] ${process.env.GITHUB_ORIGINAL_TITLE}` 65 | github.issues.update({ 66 | issue_number: context.issue.number, 67 | owner: context.repo.owner, 68 | repo: context.repo.repo, 69 | title: newTitle 70 | }) 71 | github.issues.addLabels({ 72 | issue_number: context.issue.number, 73 | owner: context.repo.owner, 74 | repo: context.repo.repo, 75 | labels: [process.env.JIRA_ISSUE_LABEL] 76 | }) 77 | 78 | 79 | - name: Add comment after sync 80 | if: env.JIRA_CREATE_ISSUE_AUTO == 'true' 81 | uses: actions/github-script@v2.0.0 82 | with: 83 | github-token: ${{secrets.GITHUB_TOKEN}} 84 | script: | 85 | github.issues.createComment({ 86 | issue_number: context.issue.number, 87 | owner: context.repo.owner, 88 | repo: context.repo.repo, 89 | body: 'Internal ticket created : [${{ steps.create_jira_issue.outputs.issue }}](${{ secrets.JIRA_BASE_URL }}/browse/${{ steps.create_jira_issue.outputs.issue }})' 90 | }) 91 | -------------------------------------------------------------------------------- /.github/workflows/comment_issue.yml: -------------------------------------------------------------------------------- 1 | name: Comment issue on Jira 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | jobs: 8 | jira: 9 | env: 10 | JIRA_CREATE_COMMENT_AUTO: ${{ secrets.JIRA_CREATE_COMMENT_AUTO }} 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Start workflow if JIRA_CREATE_COMMENT_AUTO is enabled 15 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' 16 | run: echo "Starting workflow" 17 | 18 | - name: Check GitHub Issue type 19 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' 20 | id: github_issue_type 21 | uses: actions/github-script@v2.0.0 22 | with: 23 | result-encoding: string 24 | script: | 25 | // An Issue can be a pull request, you can identify pull requests by the pull_request key 26 | const pullRequest = ${{ toJson(github.event.issue.pull_request) }} 27 | if(pullRequest) { 28 | return "pull-request" 29 | } else { 30 | return "issue" 31 | } 32 | 33 | - name: Check if GitHub Issue has JIRA_ISSUE_LABEL 34 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' 35 | id: github_issue_has_jira_issue_label 36 | uses: actions/github-script@v2.0.0 37 | env: 38 | JIRA_ISSUE_LABEL: ${{ secrets.JIRA_ISSUE_LABEL }} 39 | with: 40 | result-encoding: string 41 | script: | 42 | const labels = ${{ toJson(github.event.issue.labels) }} 43 | if(labels.find(label => label.name == process.env.JIRA_ISSUE_LABEL)) { 44 | return "true" 45 | } else { 46 | return "false" 47 | } 48 | 49 | - name: Continue workflow only for Issues (not Pull Requests) tagged with JIRA_ISSUE_LABEL 50 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' 51 | env: 52 | GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} 53 | GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} 54 | run: echo "GitHub Issue is tracked on Jira, eligilbe to be commented" 55 | 56 | - name: Jira Login 57 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' 58 | id: login 59 | uses: atlassian/gajira-login@v2.0.0 60 | env: 61 | GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} 62 | GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} 63 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 64 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 65 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 66 | 67 | - name: Extract Jira number 68 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' 69 | id: extract_jira_number 70 | uses: actions/github-script@v2.0.0 71 | env: 72 | GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} 73 | GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} 74 | JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }} 75 | GITHUB_TITLE: ${{ github.event.issue.title }} 76 | with: 77 | script: | 78 | const jiraTaskRegex = new RegExp(`\\\[(${process.env.JIRA_PROJECT}-[0-9]+?)\\\]`) 79 | return process.env.GITHUB_TITLE.match(jiraTaskRegex)[1] 80 | result-encoding: string 81 | 82 | - name: Jira Add comment on issue 83 | if: env.JIRA_CREATE_COMMENT_AUTO == 'true' && env.GITHUB_ISSUE_TYPE == 'issue' && env.GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL == 'true' 84 | id: add_comment_jira_issue 85 | uses: atlassian/gajira-comment@v2.0.2 86 | env: 87 | GITHUB_ISSUE_TYPE: ${{ steps.github_issue_type.outputs.result }} 88 | GITHUB_ISSUE_HAS_JIRA_ISSUE_LABEL: ${{ steps.github_issue_has_jira_issue_label.outputs.result }} 89 | with: 90 | issue: ${{ steps.extract_jira_number.outputs.result }} 91 | comment: | 92 | GitHub Comment : ${{ github.event.comment.user.login }} 93 | {quote}${{ github.event.comment.body }}{quote} 94 | ---- 95 | {panel} 96 | _[Github permalink |${{ github.event.comment.html_url }}]_ 97 | {panel} 98 | --------------------------------------------------------------------------------