From 0345bc35836ebc302a06bf46f6ced4c52f14d2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1igo=20Imaz?= Date: Fri, 10 Jul 2026 13:15:39 +0200 Subject: [PATCH 1/4] feat: check job permissions and warn if not enough --- _check-github-permissions/action.yml | 126 +++++++++++++++++++++++++++ doc-deploy-dev/action.yml | 7 ++ 2 files changed, 133 insertions(+) create mode 100644 _check-github-permissions/action.yml diff --git a/_check-github-permissions/action.yml b/_check-github-permissions/action.yml new file mode 100644 index 000000000..98ff8850a --- /dev/null +++ b/_check-github-permissions/action.yml @@ -0,0 +1,126 @@ +# Copyright (C) 2022 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +name: | + Check GitHub permissions action + +description: | + Verifies that the ``GITHUB_TOKEN`` has the required permissions to run an + action. Emits a ``::warning::`` for each missing permission without stopping + the job. + + Supported permission scopes: ``contents``, ``pull-requests``, ``issues``, + ``actions``, ``packages``, ``pages``, ``id-token``, and ``attestations``. + + .. note:: + + Write-level permissions (e.g. ``contents: write``) are verified with a + read probe. If the probe succeeds, read access is confirmed but write + access cannot be guaranteed without a side-effecting call. + + .. important:: + + The ``id-token`` and ``attestations`` scopes are verified by checking for + the ``ACTIONS_ID_TOKEN_REQUEST_URL`` environment variable rather than an + API call. + +inputs: + + # Required inputs + + permissions: + description: | + Comma-separated list of required GitHub token permissions in + ``scope: level`` format. For example: + ``"contents: read, pull-requests: write"``. + required: true + type: string + + # Optional inputs + + token: + description: | + GitHub token to use for permission verification. + required: false + default: ${{ github.token }} + type: string + +runs: + using: "composite" + steps: + + - name: "Check GitHub permissions" + shell: bash + env: + GH_TOKEN: ${{ inputs.token }} + PERMISSIONS: ${{ inputs.permissions }} + REPO: ${{ github.repository }} + run: | + probe() { + local endpoint="$1" + local err + if ! err=$(gh api "${endpoint}" 2>&1 >/dev/null); then + echo "${err}" | grep -qiE "HTTP 403|403|forbidden|not accessible by integration|insufficient permission" && return 1 + fi + return 0 + } + + IFS=',' read -ra PERMS <<< "${PERMISSIONS}" + for perm in "${PERMS[@]}"; do + perm=$(echo "${perm}" | xargs) + scope=$(echo "${perm}" | cut -d: -f1 | xargs) + + case "${scope}" in + contents) + probe "repos/${REPO}/git/commits?per_page=1" || \ + echo "::warning::Missing permission '${perm}'. Add 'contents: read' (or higher) to your workflow's permissions block." + ;; + pull-requests) + probe "repos/${REPO}/pulls?per_page=1" || \ + echo "::warning::Missing permission '${perm}'. Add 'pull-requests: read' (or higher) to your workflow's permissions block." + ;; + issues) + probe "repos/${REPO}/issues?per_page=1" || \ + echo "::warning::Missing permission '${perm}'. Add 'issues: read' (or higher) to your workflow's permissions block." + ;; + actions) + probe "repos/${REPO}/actions/runs?per_page=1" || \ + echo "::warning::Missing permission '${perm}'. Add 'actions: read' (or higher) to your workflow's permissions block." + ;; + packages) + probe "repos/${REPO}/packages?package_type=container" || \ + echo "::warning::Missing permission '${perm}'. Add 'packages: read' (or higher) to your workflow's permissions block." + ;; + pages) + probe "repos/${REPO}/pages" || \ + echo "::warning::Missing permission '${perm}'. Add 'pages: read' (or higher) to your workflow's permissions block." + ;; + id-token | attestations) + if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then + echo "::warning::Missing permission '${perm}'. Add 'id-token: write' to your workflow's permissions block." + fi + ;; + *) + echo "::notice::Unknown permission scope '${scope}' — skipping verification." + ;; + esac + done diff --git a/doc-deploy-dev/action.yml b/doc-deploy-dev/action.yml index e65a94e26..89f6947e5 100644 --- a/doc-deploy-dev/action.yml +++ b/doc-deploy-dev/action.yml @@ -137,6 +137,12 @@ runs: using: "composite" steps: + - name: "Check GitHub permissions" + uses: ansys/actions/_check-github-permissions@main + with: + permissions: "contents: write, pull-requests: write" + token: ${{ inputs.token }} + - uses: ansys/actions/_logging@main with: level: "INFO" @@ -162,6 +168,7 @@ runs: repository: ${{ steps.get-repository-name.outputs.REPOSITORY }} token: ${{ inputs.token }} # zizmor: ignore[artipacked] , credentials need to be persisted in this case + - name: "Ensure that the desired branch exists" shell: bash env: From 9e80c8a481c88d787d42c4bcdee3ac07095936fa Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:24:47 +0000 Subject: [PATCH 2/4] chore: adding changelog file 1410.added.md [dependabot-skip] --- doc/source/changelog/1410.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/source/changelog/1410.added.md diff --git a/doc/source/changelog/1410.added.md b/doc/source/changelog/1410.added.md new file mode 100644 index 000000000..dcb98343c --- /dev/null +++ b/doc/source/changelog/1410.added.md @@ -0,0 +1 @@ +Check job permissions and warn if not enough From c3086da70a3f4c89eab8732be0cd3a88ac726aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1igo=20Imaz?= Date: Fri, 10 Jul 2026 15:35:43 +0200 Subject: [PATCH 3/4] fix: content check instead of commits --- _check-github-permissions/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_check-github-permissions/action.yml b/_check-github-permissions/action.yml index 98ff8850a..e1e625dde 100644 --- a/_check-github-permissions/action.yml +++ b/_check-github-permissions/action.yml @@ -91,7 +91,7 @@ runs: case "${scope}" in contents) - probe "repos/${REPO}/git/commits?per_page=1" || \ + probe "repos/${REPO}/contents/" || \ echo "::warning::Missing permission '${perm}'. Add 'contents: read' (or higher) to your workflow's permissions block." ;; pull-requests) From 2f4d5bda4acea05928fee6a792bd154e5ec796cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1igo=20Imaz?= Date: Fri, 10 Jul 2026 15:47:35 +0200 Subject: [PATCH 4/4] fix: split attestations : write from id-token: write --- _check-github-permissions/action.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/_check-github-permissions/action.yml b/_check-github-permissions/action.yml index e1e625dde..aa2093351 100644 --- a/_check-github-permissions/action.yml +++ b/_check-github-permissions/action.yml @@ -114,11 +114,16 @@ runs: probe "repos/${REPO}/pages" || \ echo "::warning::Missing permission '${perm}'. Add 'pages: read' (or higher) to your workflow's permissions block." ;; - id-token | attestations) + id-token) if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then echo "::warning::Missing permission '${perm}'. Add 'id-token: write' to your workflow's permissions block." fi ;; + attestations) + if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then + echo "::warning::Missing permission '${perm}'. Add 'attestations: write' and 'id-token: write' to your workflow's permissions block." + fi + ;; *) echo "::notice::Unknown permission scope '${scope}' — skipping verification." ;;