This chapter follows Git workflows for teams.
GitHub Actions is GitHub’s built-in automation: run scripts when repository events fire. It complements Git itself—commits still land via git push; Actions reacts afterward for CI, deploys, labeling, and releases. Other hosts offer the same idea under different names, such as GitLab CI/CD with its .gitlab-ci.yml.
Core concepts
| Term | Meaning |
|---|---|
| Workflow | YAML file under .github/workflows/ |
| Event | Trigger: push, pull_request, schedule, workflow_dispatch, … |
| Job | Parallelizable unit; runs on one runner VM |
| Step | Shell command or action inside a job |
| Runner | Machine executing jobs (GitHub-hosted or self-hosted) |
| Action | Reusable step (marketplace or repo-local) |
Workflows live in the repository, versioned like application code. Pull requests can change CI in the same PR that changes product code—review those diffs carefully.
Minimal workflow
name: CI
on: push: branches: [main] pull_request: branches: [main]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: echo "Build and test here"actions/checkout clones the ref that triggered the workflow (PR merge ref for pull_request events).
A complete Node.js pipeline
Example matching a typical JavaScript repo in this knowledgebase:
name: CI
on: push: branches: [main] pull_request:
concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true
jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [20, 22] steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: npm
- name: Install run: npm ci
- name: Lint run: npm run lint --if-present
- name: Test run: npm test
- name: Build run: npm run build --if-presentnpm ci assumes a lockfile. --if-present skips scripts your package.json does not define. concurrency cancels outdated runs on the same branch when new commits arrive.
Secrets and environments
Store tokens in Settings → Secrets and variables → Actions. Reference them as ${{ secrets.MY_TOKEN }}—GitHub masks values in logs. Never commit secrets into workflow YAML.
Environments (for example production) add approval gates and environment-scoped secrets for deploy jobs:
jobs: deploy: needs: build runs-on: ubuntu-latest environment: production steps: - run: ./deploy.sh env: DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}Caching dependencies
actions/setup-node with cache: npm (or pnpm, yarn) speeds installs. For custom paths use actions/cache:
- uses: actions/cache@v4 with: path: ~/.npm key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}Reusable workflows and composite actions
Split org-wide CI into callable workflows:
on: workflow_call: inputs: node-version: required: true type: stringjobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ inputs.node-version }} - run: npm ci && npm testCaller:
jobs: call: uses: ./.github/workflows/reusable-test.yml with: node-version: "22"Status checks and branch protection
Job names appear as status checks on pull requests. Tie branch protection to required checks so main cannot merge until CI passes.
Self-hosted runners
Self-hosted runners execute on your hardware—useful for private networks, larger machines, or specialized hardware. You register the runner with the repo or org and label jobs with runs-on: [self-hosted, linux]. Patch and isolate runners; they execute arbitrary workflow code.
Where Actions fits in the series
Git records history; Actions validates and ships it. Combine protected main, PR review, and a workflow like the Node example above for a baseline pipeline many teams use before adding deploy stages.
This is the last chapter in Git and GitHub. Reference pages: Git cheat sheet and Git glossary.
Check your understanding
Question 1 of 8
0 of 8 checked