Copyright (c) 2026 MindMesh Academy. All rights reserved. This content is proprietary and may not be reproduced or distributed without permission.

2.1.4. Choosing Scope, Permissions, and Event Filters

💡 First Principle: A trigger decision is incomplete until you've also decided how much authority the resulting run gets and how many runs are allowed to pile up — event, permissions:, and concurrency: are three dials on the same control panel.

Scope down first with filters, because runs you never start cost nothing and can't misbehave. paths:/paths-ignore: limit a build to the code it actually cares about (note you cannot use both a paths and paths-ignore filter for the same event — likewise for branches/branches-ignore). Filter patterns support *, **, +, ?, !, and character ranges; ** is the one that crosses directory separators.

Then scope authority with permissions:, which sets the GITHUB_TOKEN's access at the workflow or job level. Declaring permissions: at all switches the token from the repository default to only what you list, so the idiomatic secure pattern is a restrictive workflow-level block with narrow per-job widening:

permissions:
  contents: read                  # applies to all jobs

jobs:
  release:
    permissions:
      contents: write             # this job only
      id-token: write             # OIDC, see 6.1.3

Finally, control pile-up with concurrency:. A group key plus cancel-in-progress: true is the standard "only the newest commit on a PR matters" pattern, and the standard answer to "how do we stop redundant runs from burning minutes":

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

For deployments you usually want the inverse — a concurrency group without cancellation, so production deploys queue rather than trample each other.

⚠️ Exam Trap: Adding a permissions: block to grant one scope silently revokes every scope you didn't list. If a scenario shows a job that could push commits before someone added permissions: {id-token: write} and now fails on git push, the fix is adding contents: write back — not a PAT.

Reflection Question: For a PR-validation workflow, cancel-in-progress: true is almost always right; for a production deploy workflow it's almost always wrong. What property of the two workloads flips the answer?

See how it connects
Alvin Varughese
Written byAlvin Varughese
Founder18 professional certifications