Skip to content
Latchkey

How to Restrict Who Can Trigger workflow_dispatch in GitHub Actions

Anyone with write access can trigger a manual workflow; for sensitive ones you may want an even tighter check.

Add a guard step that queries the actor permission level and fails the run unless they are an admin or maintainer.

Steps

  • Keep the workflow on workflow_dispatch.
  • Add a first job that checks the actor permission via the GitHub API.
  • Fail the run if the level is below admin (or your threshold).
  • Gate the real jobs behind that check with needs:.

Workflow

.github/workflows/manual-deploy.yml
on: workflow_dispatch
jobs:
  authorize:
    runs-on: ubuntu-latest
    steps:
      - name: Check permission
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          LEVEL=$(gh api "repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission" --jq .permission)
          if [ "$LEVEL" != "admin" ]; then
            echo "::error::${{ github.actor }} is not an admin ($LEVEL)"
            exit 1
          fi
  deploy:
    needs: authorize
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

Gotchas

  • For broad org policy, a protected environment with required reviewers is sturdier than an inline check.
  • The default token can read collaborator permission without extra scopes.
  • Latchkey runs the gated jobs on cheaper, self-healing runners once the authorization check passes.

Verify it actually works

A workflow that runs is not a workflow that works. Confirm the behaviour on a real event rather than on a manual dispatch, because trigger conditions, permissions, and context values all differ between the two.

Terminal
# 1. validate the file before pushing
docker run --rm -v "$(pwd):/repo" --workdir /repo rhysd/actionlint:latest -color

# 2. trigger the real event, not workflow_dispatch
git commit --allow-empty -m "ci: verify trigger" && git push

# 3. watch it and read the conclusion, not just the colour
gh run watch
gh run view --log-failed

What usually goes wrong first

  • The workflow file must exist on the default branch before scheduled or dispatch triggers appear at all.
  • GITHUB_TOKEN permissions default to read-only in many organisations. Declare a permissions: block listing every scope the job needs.
  • Fork pull requests get a read-only token and no access to secrets, regardless of workflow configuration.
  • actions/checkout gives you depth 1 on a detached HEAD, so anything needing history or a branch name needs fetch-depth: 0.

Frequently asked questions

How do I restrict Who Can Trigger workflow_dispatch in GitHub Actions?
Add a guard step that queries the actor permission level and fails the run unless they are an admin or maintainer.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card