Workflow foundations
Choose triggers carefully
Limit branches, paths, activities, schedules, and manual inputs to the events that should spend authority and compute.
The on: block decides when your workflow runs. It also decides which code gets access to secrets and write tokens.
A trigger that is too broad wastes minutes and opens security holes. A trigger that is too narrow lets broken code slip through.
Match the event to the work
Not every push needs a full build.
Documentation-only changes can skip heavy jobs with path filters. Deployment should run only from the protected default branch, not from every feature branch push.
on:
push:
branches: [main]
paths:
- 'src/**'
- 'package.json'
- 'package-lock.json'
pull_request:
paths:
- 'src/**'
- 'package.json'
- 'package-lock.json'
This workflow ignores README edits. That saves time on a busy repo.
Do not filter in shell what you can filter in YAML
A common mistake: trigger on every pull_request, then add if: github.ref == 'refs/heads/main' inside a deploy step.
The workflow still started. Fork pull requests still reached your runners. You just hid the deploy step.
The stronger move is to put the boundary in on: and in job-level if: conditions where needed.
jobs:
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment: production
runs-on: ubuntu-latest
steps:
- run: echo "deploy"
Notice the deploy job does not even start on pull requests.
Test the cases that matter
Build a trigger table for your repo:
| Event | Branch | Paths changed | Should CI run? | Should deploy run? |
|---|---|---|---|---|
| push | main | src/ | yes | yes |
| push | feature/x | src/ | yes | no |
| pull_request | any | docs/ only | no | no |
Then create one test commit for each row and check the Actions tab.
Also test fork pull requests, tag pushes, and workflow_dispatch if you use manual runs. The failure you see tells you where the boundary actually is.
Try this on your own project: add one path filter, push a docs-only commit, and confirm the workflow stays idle.
Lesson completed