Most workflow steps are someone else's action; knowing how to choose and pin them keeps builds stable and safe.
An action is a reusable step published in a repository. You reference it as owner/repo@ref, for example actions/checkout@v7, and GitHub downloads it at the start of the job. The ref can be:
- a major version tag like
v5(gets compatible updates automatically), - an exact tag like
v5.0.0, - a full commit SHA, the only reference that cannot be moved by the action's owner.
Inputs go under with:; each action documents its inputs in its action.yml and README. Some actions also set outputs that later steps can read. A local action in your own repository is referenced by path: uses: ./.github/actions/setup.
actions/checkout deserves special attention. By default it fetches only the triggering commit (fetch-depth: 1), which is fast but means git describe or history-based tools see no history; set fetch-depth: 0 for full history. It also persists the job's token so later steps can run authenticated git commands such as git push; set persist-credentials: false if they don't need to.
The actions/ organization is maintained by GitHub. For third-party actions, check the source, the maintainer and how widely it is used: an action runs with access to your workspace and whatever secrets you pass it.
Example
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # full history for git describe
persist-credentials: false
- run: git describe --tags --always # e.g. v1.4.2-3-g1a2b3c4
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# third-party action pinned to a full commit SHA (comment records the tag)
- uses: owner/some-action@0123456789abcdef0123456789abcdef01234567 # v2.1.0Remember
- uses: owner/repo@ref runs an action; with: passes inputs
- Major tags auto-update; a full SHA pins exactly
- checkout fetches one commit unless fetch-depth: 0
Watch out for
- Quoting versions is needed for YAML: python-version: 3.10 becomes the number 3.1.