├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── general.yml │ ├── question.yml │ ├── feature-request.yml │ ├── bug-report.yml │ └── support-request.yml ├── FUNDING.yml ├── workflows │ ├── renovate-config-validator.yaml │ ├── actionlint.yaml │ ├── watch-star.yaml │ ├── test.yaml │ ├── check-commit-signing.yaml │ ├── typos.yaml │ ├── autofix.yaml │ ├── workflow_call_test.yaml │ └── test-action.yaml └── pull_request_template.md ├── _typos.toml ├── aqua ├── imports │ ├── typos.yaml │ ├── nllint.yaml │ └── pinact.yaml ├── aqua.yaml └── aqua-checksums.json ├── CONTRIBUTING.md ├── renovate.json5 ├── LICENSE ├── action.yaml ├── server └── action.yaml └── README.md /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | repositorys = "repositorys" 3 | -------------------------------------------------------------------------------- /aqua/imports/typos.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - name: crate-ci/typos@v1.40.0 3 | -------------------------------------------------------------------------------- /aqua/imports/nllint.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - name: suzuki-shunsuke/nllint@v1.0.0 3 | -------------------------------------------------------------------------------- /aqua/imports/pinact.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - name: suzuki-shunsuke/pinact@v3.6.0 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please read the following document. 4 | 5 | - https://github.com/suzuki-shunsuke/oss-contribution-guide 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository 2 | github: 3 | - suzuki-shunsuke 4 | -------------------------------------------------------------------------------- /renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | extends: [ 3 | "github>suzuki-shunsuke/renovate-config#3.3.1", 4 | "github>suzuki-shunsuke/renovate-config:nolimit#3.3.1", 5 | "github>aquaproj/aqua-renovate-config#2.9.0", 6 | "github>aquaproj/aqua-renovate-config:file#2.9.0(aqua/imports/.*\\.yaml)", 7 | ], 8 | } 9 | -------------------------------------------------------------------------------- /.github/workflows/renovate-config-validator.yaml: -------------------------------------------------------------------------------- 1 | name: renovate-config-validator 2 | permissions: {} 3 | on: workflow_call 4 | jobs: 5 | renovate-config-validator: 6 | uses: suzuki-shunsuke/renovate-config-validator-workflow/.github/workflows/validate.yaml@dcf025732ed76061838048f7f8b0099ae0e89876 # v0.2.5 7 | permissions: 8 | contents: read 9 | -------------------------------------------------------------------------------- /.github/workflows/actionlint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: actionlint 3 | on: pull_request 4 | jobs: 5 | actionlint: 6 | runs-on: ubuntu-24.04 7 | timeout-minutes: 10 8 | permissions: 9 | contents: read 10 | pull-requests: write 11 | steps: 12 | - uses: suzuki-shunsuke/actionlint-action@29e0b7cda52e51a495d15f22759745ef6e19583a # v0.1.1 13 | -------------------------------------------------------------------------------- /aqua/aqua.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # yaml-language-server: $schema=https://raw.githubusercontent.com/aquaproj/aqua/main/json-schema/aqua-yaml.json 3 | # aqua - Declarative CLI Version Manager 4 | # https://aquaproj.github.io/ 5 | checksum: 6 | enabled: true 7 | require_checksum: true 8 | registries: 9 | - type: standard 10 | ref: v4.447.1 # renovate: depName=aquaproj/aqua-registry 11 | import_dir: imports 12 | -------------------------------------------------------------------------------- /.github/workflows/watch-star.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: watch-star 3 | on: 4 | watch: 5 | types: 6 | - started 7 | jobs: 8 | watch-star: 9 | timeout-minutes: 10 10 | runs-on: ubuntu-24.04 11 | permissions: 12 | issues: write 13 | steps: 14 | - uses: suzuki-shunsuke/watch-star-action@2b3d259ce2ea06d53270dfe33a66d5642c8010ca # v0.1.1 15 | with: 16 | number: 2 17 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | permissions: {} 3 | on: pull_request 4 | jobs: 5 | status-check: 6 | runs-on: ubuntu-24.04 7 | if: always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) 8 | timeout-minutes: 10 9 | permissions: {} 10 | needs: 11 | - test 12 | steps: 13 | - run: exit 1 14 | test: 15 | uses: ./.github/workflows/workflow_call_test.yaml 16 | permissions: 17 | contents: read 18 | -------------------------------------------------------------------------------- /.github/workflows/check-commit-signing.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Check if all commits are signed 3 | on: 4 | pull_request_target: 5 | branches: [main] 6 | concurrency: 7 | group: ${{ github.workflow }}--${{ github.head_ref }} # github.ref is unavailable in case of pull_request_target 8 | cancel-in-progress: true 9 | jobs: 10 | check-commit-signing: 11 | uses: suzuki-shunsuke/check-commit-signing-workflow/.github/workflows/check.yaml@547eee345f56310a656f271ec5eaa900af46b0fb # v0.1.0 12 | permissions: 13 | contents: read 14 | pull-requests: write 15 | -------------------------------------------------------------------------------- /.github/workflows/typos.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: typos 3 | on: workflow_call 4 | env: 5 | AQUA_LOG_COLOR: always 6 | jobs: 7 | typos: 8 | timeout-minutes: 15 9 | runs-on: ubuntu-latest 10 | permissions: {} 11 | steps: 12 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 13 | with: 14 | persist-credentials: false 15 | - uses: aquaproj/aqua-installer@11dd79b4e498d471a9385aa9fb7f62bb5f52a73c # v4.0.4 16 | with: 17 | aqua_version: v2.56.0 18 | env: 19 | AQUA_GITHUB_TOKEN: ${{github.token}} 20 | - run: typos 21 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Check List 2 | 3 | 4 | 5 | - [ ] Read [CONTRIBUTING.md](https://github.com/csm-actions/approve-pr-action/blob/main/CONTRIBUTING.md) 6 | - [ ] [Write a GitHub Issue before creating a Pull Request](https://github.com/suzuki-shunsuke/oss-contribution-guide/blob/main/README.md#create-an-issue-before-creating-a-pull-request) 7 | - Link to the issue: 8 | - [Avoid force push](https://github.com/suzuki-shunsuke/oss-contribution-guide?tab=readme-ov-file#dont-do-force-pushes-after-opening-pull-requests) 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general.yml: -------------------------------------------------------------------------------- 1 | name: General 2 | description: Please use this template only when other templates don't meet your requirement 3 | labels: 4 | - general 5 | body: 6 | - type: textarea 7 | id: what 8 | attributes: 9 | label: What 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: why 14 | attributes: 15 | label: Why 16 | description: Please explain the background and the reason of this issue 17 | validations: 18 | required: false 19 | - type: textarea 20 | id: note 21 | attributes: 22 | label: Note 23 | description: Please write any additional information 24 | validations: 25 | required: false 26 | -------------------------------------------------------------------------------- /.github/workflows/autofix.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: autofix.ci 3 | on: pull_request 4 | permissions: {} 5 | jobs: 6 | autofix: 7 | runs-on: ubuntu-24.04 8 | permissions: {} 9 | timeout-minutes: 15 10 | steps: 11 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 12 | with: 13 | persist-credentials: false 14 | - uses: aquaproj/aqua-installer@11dd79b4e498d471a9385aa9fb7f62bb5f52a73c # v4.0.4 15 | with: 16 | aqua_version: v2.56.0 17 | env: 18 | GITHUB_TOKEN: ${{github.token}} 19 | - run: aqua upc -prune 20 | - run: git ls-files | xargs nllint -f -s 21 | - run: | 22 | git ls-files | grep -E '\.md$' | xargs pinact run -u 23 | pinact run 24 | - uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 # v1.3.2 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: Question 2 | description: | 3 | Please use this template when you have any questions. 4 | Please don't hesitate to ask any questions via Issues. 5 | labels: 6 | - question 7 | body: 8 | - type: textarea 9 | id: question 10 | attributes: 11 | label: Question 12 | description: | 13 | Please explain your question in details. 14 | If example code is useful to explain your question, please write it. 15 | validations: 16 | required: true 17 | - type: textarea 18 | id: background 19 | attributes: 20 | label: Background 21 | description: Please explain the background and why you have the question 22 | validations: 23 | required: false 24 | - type: textarea 25 | id: note 26 | attributes: 27 | label: Note 28 | description: Please write any additional information 29 | validations: 30 | required: false 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: If you want to add a feature. 3 | labels: 4 | - enhancement 5 | body: 6 | - type: textarea 7 | id: feature-overview 8 | attributes: 9 | label: Feature Overview 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: why 14 | attributes: 15 | label: Why is the feature needed? 16 | description: Please explain the problem you want to solve. 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: example-code 21 | attributes: 22 | label: Example Code 23 | description: | 24 | Please explain the feature with code. For example, if you want a new input, please explain the usage of it. 25 | value: | 26 | Workflow: 27 | 28 | ```yaml 29 | 30 | ``` 31 | validations: 32 | required: false 33 | - type: textarea 34 | id: note 35 | attributes: 36 | label: Note 37 | validations: 38 | required: false 39 | -------------------------------------------------------------------------------- /.github/workflows/workflow_call_test.yaml: -------------------------------------------------------------------------------- 1 | name: test (workflow_call) 2 | permissions: {} 3 | on: workflow_call 4 | jobs: 5 | path-filter: 6 | timeout-minutes: 10 7 | outputs: 8 | renovate-config-validator: ${{steps.changes.outputs.renovate-config-validator}} 9 | runs-on: ubuntu-24.04 10 | permissions: {} 11 | steps: 12 | - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 13 | id: changes 14 | with: 15 | filters: | 16 | renovate-config-validator: 17 | - renovate.json5 18 | - .github/workflows/workflow_call_test.yaml 19 | - .github/workflows/renovate-config-vdalidator.yaml 20 | 21 | renovate-config-validator: 22 | uses: ./.github/workflows/renovate-config-validator.yaml 23 | needs: path-filter 24 | if: needs.path-filter.outputs.renovate-config-validator == 'true' 25 | permissions: 26 | contents: read 27 | 28 | typos: 29 | uses: ./.github/workflows/typos.yaml 30 | permissions: {} 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 csm-actions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/test-action.yaml: -------------------------------------------------------------------------------- 1 | # This is a dummy workflow file to test actions using actionlint. 2 | # This workflow is never run. 3 | name: test action (actionlint) 4 | on: workflow_call 5 | jobs: 6 | actionlint-action: 7 | timeout-minutes: 10 8 | runs-on: ubuntu-24.04 9 | permissions: {} 10 | steps: 11 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 12 | with: 13 | persist-credentials: false 14 | 15 | - uses: ./ 16 | with: 17 | app_id: dummy 18 | app_private_key: dummy 19 | server_repository_name: demo-server 20 | pull_request_number: 1 21 | 22 | - uses: ./parse-label 23 | id: pr 24 | - uses: ./validate 25 | id: validate 26 | with: 27 | github_token: xxx 28 | pull_request_number: ${{ steps.pr.outputs.pull_request_number }} 29 | repository_owner: ${{ steps.pr.outputs.repository_owner }} 30 | repository_name: ${{ steps.pr.outputs.repository_name }} 31 | - uses: ./approve 32 | if: steps.validate.outputs.approved == 'true' 33 | with: 34 | github_token: xxx 35 | pull_request_number: ${{ steps.pr.outputs.pull_request_number }} 36 | repository_owner: ${{ steps.pr.outputs.repository_owner }} 37 | repository_name: ${{ steps.pr.outputs.repository_name }} 38 | sha: ${{ steps.validate.outputs.approved_sha }} 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: | 3 | Please report the bug of Server Action. 4 | If you're not sure if it's a bug or not, please use the template `Support Request` instead. 5 | labels: 6 | - bug 7 | body: 8 | - type: textarea 9 | id: version 10 | attributes: 11 | label: version 12 | value: | 13 | Versions that the issue occurs: 14 | 15 | (Opitonal) Versions that the issue doesn't occur: 16 | 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: overview 21 | attributes: 22 | label: Overview 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: how-to-reproduce 27 | attributes: 28 | label: How to reproduce 29 | description: | 30 | Please see [the guide](https://github.com/suzuki-shunsuke/oss-contribution-guide#write-good-how-to-reproduce) too. 31 | workflow should be not partial but complete configuration. 32 | Please remove unnecessary code to reproduce the issue. 33 | value: | 34 | Workflow: 35 | 36 | ```yaml 37 | 38 | ``` 39 | validations: 40 | required: true 41 | - type: textarea 42 | id: expected-behaviour 43 | attributes: 44 | label: Expected behaviour 45 | validations: 46 | required: true 47 | - type: textarea 48 | id: actual-behaviour 49 | attributes: 50 | label: Actual behaviour 51 | validations: 52 | required: true 53 | - type: textarea 54 | id: note 55 | attributes: 56 | label: Note 57 | validations: 58 | required: false 59 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support-request.yml: -------------------------------------------------------------------------------- 1 | name: Support Request 2 | description: | 3 | Please use this template when you face any problem (not bug) and need our help. 4 | If you're not sure if it's a bug or not, please use this template. 5 | labels: 6 | - support-request 7 | body: 8 | - type: textarea 9 | id: version 10 | attributes: 11 | label: version 12 | value: | 13 | Versions that the issue occurs: 14 | 15 | (Opitonal) Versions that the issue doesn't occur: 16 | 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: overview 21 | attributes: 22 | label: Overview 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: how-to-reproduce 27 | attributes: 28 | label: How to reproduce 29 | description: | 30 | Please see [the guide](https://github.com/suzuki-shunsuke/oss-contribution-guide#write-good-how-to-reproduce) too. 31 | workflow should be not partial but complete configuration. 32 | Please remove unnecessary code to reproduce the issue. 33 | value: | 34 | Workflow: 35 | 36 | ```yaml 37 | 38 | ``` 39 | validations: 40 | required: true 41 | - type: textarea 42 | id: expected-behaviour 43 | attributes: 44 | label: Expected behaviour 45 | validations: 46 | required: true 47 | - type: textarea 48 | id: actual-behaviour 49 | attributes: 50 | label: Actual behaviour 51 | validations: 52 | required: true 53 | - type: textarea 54 | id: note 55 | attributes: 56 | label: Note 57 | validations: 58 | required: false 59 | -------------------------------------------------------------------------------- /action.yaml: -------------------------------------------------------------------------------- 1 | name: Approve pull requests securely 2 | description: Approve pull requests securely 3 | author: Shunsuke Suzuki 4 | branding: 5 | icon: git-commit 6 | color: green 7 | inputs: 8 | app_id: 9 | description: | 10 | GitHub App ID 11 | required: true 12 | app_private_key: 13 | description: | 14 | GitHub App Private Key 15 | required: true 16 | server_repository_name: 17 | description: | 18 | Server repository name 19 | required: true 20 | pull_request_number: 21 | description: | 22 | The pull request number of the updated pull request 23 | required: true 24 | 25 | github_token: 26 | description: | 27 | GitHub token to read the pull request. 28 | `contents: read` and `pull_requests:read` permissions are required. 29 | required: false 30 | default: ${{ github.token }} 31 | repository_name: 32 | description: | 33 | The repository name of the updated pull request 34 | required: false 35 | default: ${{ github.event.repository.name }} 36 | repository_owner: 37 | description: | 38 | The repository owner of the updated pull request 39 | required: false 40 | default: ${{ github.repository_owner }} 41 | server_repository_owner: 42 | description: | 43 | A server repository owner. 44 | required: false 45 | default: ${{ github.repository_owner }} 46 | allowed_committers: 47 | description: | 48 | A list of allowed committers. 49 | required: false 50 | default: | 51 | renovate[bot] 52 | dependabot[bot] 53 | runs: 54 | using: composite 55 | steps: 56 | - uses: csm-actions/core-approve-pr-action/validate@2bfb2a4f082938741ac6b722e3d2e6e9436c2803 # v0.0.2 57 | id: validate 58 | with: 59 | github_token: ${{ inputs.github_token }} 60 | pull_request_number: ${{ inputs.pull_request_number }} 61 | repository_owner: ${{ inputs.repository_owner }} 62 | repository_name: ${{ inputs.repository_name }} 63 | allowed_committers: ${{ inputs.allowed_committers }} 64 | 65 | # Create a GitHub App token to create and delete a label 66 | - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 67 | if: steps.validate.outputs.approved == 'true' 68 | id: token 69 | with: 70 | app-id: ${{inputs.app_id}} 71 | private-key: ${{inputs.app_private_key}} 72 | permission-issues: write 73 | owner: ${{ github.server_repository_owner }} 74 | repositories: | 75 | ${{inputs.server_repository_name}} 76 | 77 | - uses: csm-actions/label-action@e882c05058dd13a9072a60980f490728cea7de1c # v0.1.0 78 | if: steps.validate.outputs.approved == 'true' 79 | with: 80 | prefix: approve-pr- 81 | description: ${{inputs.repository_owner}}/${{inputs.repository_name}}/${{inputs.pull_request_number}} 82 | repository_owner: ${{inputs.server_repository_owner}} 83 | repository_name: ${{inputs.server_repository_name}} 84 | github_token: ${{steps.token.outputs.token}} 85 | -------------------------------------------------------------------------------- /server/action.yaml: -------------------------------------------------------------------------------- 1 | name: Approve Pull Requests 2 | description: Approve Pull Requests 3 | inputs: 4 | github_token: 5 | description: | 6 | GitHub Access token to approve pull requests. 7 | `pull_requests:write` permission is required. 8 | required: true 9 | app_id: 10 | description: | 11 | GitHub App ID. 12 | Permissions `pull_requests:read` and `contents:read` are required to validate pull requests. 13 | required: true 14 | app_private_key: 15 | description: | 16 | GitHub App Private Key 17 | required: true 18 | runs: 19 | using: composite 20 | steps: 21 | - id: pr 22 | shell: bash 23 | env: 24 | # ${repo}/${pull_request_number} 25 | LABEL_DESCRIPTION: ${{ github.event.label.description }} 26 | run: | 27 | repo_full_name=${LABEL_DESCRIPTION%/*} 28 | { 29 | echo "repository_owner=${repo_full_name%/*}" 30 | echo "repository_name=${repo_full_name#*/}" 31 | echo "pull_request_number=${LABEL_DESCRIPTION##*/}" 32 | } >> "$GITHUB_OUTPUT" 33 | 34 | - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 35 | id: token 36 | with: 37 | app-id: ${{inputs.app_id}} 38 | private-key: ${{inputs.app_private_key}} 39 | permission-pull-requests: read 40 | permission-contents: read 41 | owner: ${{ steps.pr.outputs.repository_owner }} 42 | repositories: | 43 | ${{steps.pr.outputs.repository_name}} 44 | 45 | - uses: csm-actions/core-approve-pr-action/validate@2bfb2a4f082938741ac6b722e3d2e6e9436c2803 # v0.0.2 46 | id: validate 47 | with: 48 | github_token: ${{ steps.token.outputs.token }} 49 | pull_request_number: ${{ steps.pr.outputs.pull_request_number }} 50 | repository_owner: ${{ steps.pr.outputs.repository_owner }} 51 | repository_name: ${{ steps.pr.outputs.repository_name }} 52 | 53 | - if: steps.validate.outputs.approved == 'true' 54 | shell: bash 55 | env: 56 | GH_TOKEN: ${{ inputs.github_token }} 57 | REPO: ${{ steps.pr.outputs.repository_owner }}/${{ steps.pr.outputs.repository_name }} 58 | NUMBER: ${{ steps.pr.outputs.pull_request_number }} 59 | SHA: ${{ steps.validate.outputs.approved_sha }} 60 | run: | 61 | gh api \ 62 | --method POST \ 63 | -H "Accept: application/vnd.github+json" \ 64 | -H "X-GitHub-Api-Version: 2022-11-28" \ 65 | "/repos/$REPO/pulls/$NUMBER/reviews" \ 66 | -f "commit_id=$SHA" \ 67 | -f "event=APPROVE" 68 | 69 | # Create a pull request comment to report an error 70 | - if: failure() 71 | shell: bash 72 | env: 73 | GH_TOKEN: ${{ inputs.github_token }} 74 | REPO: ${{ steps.pr.outputs.repository_owner }}/${{ steps.pr.outputs.repository_name }} 75 | NUMBER: ${{ steps.pr.outputs.pull_request_number }} 76 | COMMENT: | 77 | ## :x: Failed to approve this pull request 78 | 79 | [Workflow](${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}) 80 | run: | 81 | gh pr comment \ 82 | -R "$REPO" \ 83 | -b "${COMMENT}" \ 84 | "$NUMBER" 85 | -------------------------------------------------------------------------------- /aqua/aqua-checksums.json: -------------------------------------------------------------------------------- 1 | { 2 | "checksums": [ 3 | { 4 | "id": "github_release/github.com/crate-ci/typos/v1.40.0/typos-v1.40.0-aarch64-apple-darwin.tar.gz", 5 | "checksum": "1EA9ED6520B94D0E1148942E3EF80A997FF8DB856E1389EDAA9A5BDAFF658FA4", 6 | "algorithm": "sha256" 7 | }, 8 | { 9 | "id": "github_release/github.com/crate-ci/typos/v1.40.0/typos-v1.40.0-aarch64-unknown-linux-musl.tar.gz", 10 | "checksum": "349B2C3F7C7FBA125E978DF232FAA9C5A57C33AA144F88CBC250C8C6D3E8E054", 11 | "algorithm": "sha256" 12 | }, 13 | { 14 | "id": "github_release/github.com/crate-ci/typos/v1.40.0/typos-v1.40.0-x86_64-apple-darwin.tar.gz", 15 | "checksum": "51368551A37E15464438EA5C95AD29CB7239BFDEFD69EE9A9BE5FF3D45FC4D19", 16 | "algorithm": "sha256" 17 | }, 18 | { 19 | "id": "github_release/github.com/crate-ci/typos/v1.40.0/typos-v1.40.0-x86_64-pc-windows-msvc.zip", 20 | "checksum": "F13426420749FAE31136E15A245C8EB144D6D3D681B3300D54D1A129999A140D", 21 | "algorithm": "sha256" 22 | }, 23 | { 24 | "id": "github_release/github.com/crate-ci/typos/v1.40.0/typos-v1.40.0-x86_64-unknown-linux-musl.tar.gz", 25 | "checksum": "485405D0A92871F45EAD0703D23C04AE6969AD4A6E5799794F55EB04B9F07801", 26 | "algorithm": "sha256" 27 | }, 28 | { 29 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_darwin_amd64.tar.gz", 30 | "checksum": "5733518D44F7EAE2B4B16B0EA6617597C89B2EB084A4E6101A1DC03716266B6C", 31 | "algorithm": "sha256" 32 | }, 33 | { 34 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_darwin_arm64.tar.gz", 35 | "checksum": "E854EE0AA0DD83273D3B68E335BC025FDA721A32A3373091DFDEC3A582D1EC41", 36 | "algorithm": "sha256" 37 | }, 38 | { 39 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_linux_amd64.tar.gz", 40 | "checksum": "F54EC24CE1C344B611F6D80155396101D38E72B7F88E2CA8B9BFADC16307AE35", 41 | "algorithm": "sha256" 42 | }, 43 | { 44 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_linux_arm64.tar.gz", 45 | "checksum": "EC8D94494C70F4285A39375F385A4E52F945C597A3A5361ADF3DD9F1C8263CE4", 46 | "algorithm": "sha256" 47 | }, 48 | { 49 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_windows_amd64.zip", 50 | "checksum": "4ABEBC98AF160C06C988F1421F0CF991FBDBFB6789CC1681C5C8E33C48A70160", 51 | "algorithm": "sha256" 52 | }, 53 | { 54 | "id": "github_release/github.com/suzuki-shunsuke/nllint/v1.0.0/nllint_windows_arm64.zip", 55 | "checksum": "7493FF32F027507BDA9E9308E4AA25D640AA16B0287F7656A7C0A61AF907D270", 56 | "algorithm": "sha256" 57 | }, 58 | { 59 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_darwin_amd64.tar.gz", 60 | "checksum": "49D10A46D9E1C87541BFE8551964868F3F62CF33BF6A80A9C68F7D3696651420", 61 | "algorithm": "sha256" 62 | }, 63 | { 64 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_darwin_arm64.tar.gz", 65 | "checksum": "B5B8229A2F00B209D7168E41A335E612BD2CCF6E0E41DD830A7CFC65A06532BF", 66 | "algorithm": "sha256" 67 | }, 68 | { 69 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_linux_amd64.tar.gz", 70 | "checksum": "BAAD9DCFC298B1281BDA3E29A977C4B2F6979DFD80718ABD8CCB23D170005D5E", 71 | "algorithm": "sha256" 72 | }, 73 | { 74 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_linux_arm64.tar.gz", 75 | "checksum": "971CDF464BE2AC09E2600307571AD5FBE78E1AA1F978F4CAD3B1C56EFA4A39E4", 76 | "algorithm": "sha256" 77 | }, 78 | { 79 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_windows_amd64.zip", 80 | "checksum": "B510414A442473AC96F4F5D20C57AC1F5E8BA502C9DCAB985AB0A9FBFCD40826", 81 | "algorithm": "sha256" 82 | }, 83 | { 84 | "id": "github_release/github.com/suzuki-shunsuke/pinact/v3.6.0/pinact_windows_arm64.zip", 85 | "checksum": "083510E344D403E98AFF942A619FA7A96B35E42F36B24B901FA3D6AA217E1B2A", 86 | "algorithm": "sha256" 87 | }, 88 | { 89 | "id": "registries/github_content/github.com/aquaproj/aqua-registry/v4.447.1/registry.yaml", 90 | "checksum": "324ED65ED60627EBE90CFD5A63985ECFDA545954EFC0B9208A9B054FAD86ED4226AAD93D7314666F170A53DF89EE90769FF74D8A71AE90B47C5D2F00F3C01CF5", 91 | "algorithm": "sha512" 92 | } 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Approve PR Action 2 | 3 | [![DeepWiki](https://img.shields.io/badge/DeepWiki-csm--actions%2Fapprove--pr--action-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==)](https://deepwiki.com/csm-actions/approve-pr-action) [![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/csm-actions/approve-pr-action/main/LICENSE) | [Versioning Policy](https://github.com/suzuki-shunsuke/versioning-policy/blob/main/POLICY.md) 4 | 5 | `Approve PR Action` is a set of GitHub Actions to approve pull requests securely by [the Client/Server Model](https://github.com/csm-actions/docs). 6 | 7 | Approve PR Action allows you to approve pull requests by Machine Users securely without sharing Machine Users' Personal Access Tokens (PAT) across GitHub Actions workflows. 8 | It elevates the security of your workflows to the next level. 9 | 10 | ## Features 11 | 12 | - 💪 Approve pull requests to merge pull requests automatically 13 | - 🛡 Secure 14 | - You don't need to pass PAT of machine users to GitHub Actions workflows on the client side 15 | - 😊 Easy to use 16 | - You don't need to host a server application 17 | - 😉 [OSS (MIT License)](LICENSE) 18 | 19 | ## Overview 20 | 21 | It would be convenient to automatically merge pull requests created by apps like Renovate. 22 | Manually reviewing and merging all of them can be time-consuming and labor-intensive. 23 | Tedious reviews can sometimes become mere formalities. 24 | This can lead to delayed updates and potentially troublesome issues. 25 | 26 | Of course, automatic merging comes with its own risks, but if the benefits of automation outweigh those risks, it’s a good idea to automatically merge at least some updates—excluding major updates, for example. 27 | 28 | But if approvals from codeowners are required by Branch Rulesets, you need to approve pull requests automatically. 29 | GitHub Apps can't be codeowners, so you need to approve pull requests using machine user's PAT. 30 | But if the PAT is abused, people can approve any pull requests using it and merge them without pull request reviews. 31 | It's so dangerous. 32 | So you must protect machine user's PAT securely. 33 | You shouldn't pass it to workflows widely. 34 | 35 | This action allows you to protect PAT by [the Client/Server Model](https://github.com/csm-actions/docs). 36 | 37 | This action intends to approve only pull requests created by reliable Apps automatically. 38 | This action doesn't approve pull requests unless they don't meet the following conditions: 39 | 40 | 1. All commits are linked to GitHub Users 41 | 1. All commits are signed 42 | 1. All committers or authors are allowed in the input `allowed_committers` (By default, `allowed_committers` are `renovate[bot]` and `dependabot[bot]`) 43 | 44 | ## How To Set Up 45 | 46 | - Create a server repository 47 | - Create a server GitHub App: 48 | - Required Permissions: `pull_requests:read` and `contents:read` To validate pull requests 49 | - Installed Repositories: client and server repositories 50 | - Create a fine-grained PAT of a machine user 51 | - Required Permissions: 52 | - `pull_requests:write`: To approve pull requests 53 | - Repositories: client repositories 54 | - [Allow the server workflow to access the PAT securely](https://github.com/csm-actions/docs?tab=readme-ov-file#secret-management) 55 | - Create the server workflow: [Example](https://github.com/csm-actions/demo-server/blob/main/.github/workflows/approve.yaml) 56 | - Create a client GitHub App: 57 | - Required Permissions: `issues:write` To create GitHub Issue labels 58 | - Installed Repositories: client and server repositories 59 | - Run the client action in client workflows: [Example](https://github.com/csm-actions/demo-client/blob/c46ce73ffdaa83af182d733a382d5dc051d3b994/.github/workflows/approve.yaml#L11-L20) 60 | 61 | ## Actions 62 | 63 | Approve PR Action composes of following actions: 64 | 65 | - [csm-actions/approve-pr-action](action.yaml): Client action 66 | - [csm-actions/approve-pr-action/server](server/action.yaml): Server action 67 | --------------------------------------------------------------------------------