Computers & Electronics
169,522 views
25 min · 2 min read
7 steps
Advanced

How to set up GitHub Actions to automate builds and tests for a personal project

Automating builds and tests with GitHub Actions saves time and ensures your project stays healthy after every change. This guide walks you through setting up a simple workflow that runs on pushes and pull requests so you get fast feedback without manual steps.

Verified by pleasexplain editors
  1. Step 1: Create a .github/workflows folder

    In your repository root, create a .github/workflows directory to store workflow files. Keeping workflows in this exact path lets GitHub detect and run your automation automatically when events occur.

    [Illustration: folder view showing .github and workflows subfolder with a new file icon]

  2. Step 2: Choose a trigger event

    Decide when the workflow should run, such as on push and pull_request to main or develop branches. Using both push and pull_request catches commits and branch-based review events, providing feedback within 1–2 minutes after commits in typical repos.

    [Illustration: diagram of git branch with push and pull_request arrows pointing to a small clock]

  3. Step 3: Add a workflow YAML file

    Create a YAML file like ci.yml inside .github/workflows and define name, on (events), and jobs. A single file with clear job names makes it easier to expand later and keeps CI organized for collaborators.

    [Illustration: text editor window showing a new ci.yml file with YAML structure]

  4. Step 4: Define job runs-on and matrix

    Specify jobs.<run-on> such as ubuntu-latest and add a matrix for versions (for example node: [14,16] or python: [3.8,3.10]). A matrix runs parallel jobs for each version, giving coverage across 2–3 runtimes with minimal config change.

    [Illustration: table showing matrix axes like node versions and OS rows running in parallel]

  5. Step 5: Install dependencies and cache

    Add steps to install dependencies (npm ci, pip install -r requirements.txt) and use caching actions to speed runs, e.g., cache node_modules or pip wheelhouse. Caching typically reduces install time from minutes to 20–40 seconds after the first run.

    [Illustration: pipeline steps listing Install dependencies then Cache with a speed gauge]

  6. Step 6: Run build and test commands

    Include commands such as npm run build and npm test or pytest -q to compile and run tests. Fail the job on nonzero exit codes so Pull Requests get a red X quickly; aim for tests to finish within 1–5 minutes for fast feedback loops.

    [Illustration: terminal showing build output then test suite passing with green indicators]

  7. Step 7: Add status checks and notifications

    Configure branch protection rules in GitHub to require the workflow as a status check and enable workflow email or Slack notifications via a small action. Requiring checks prevents merging broken code and notifications inform you within seconds of failures.

    [Illustration: GitHub PR page showing required checks and a notification popup]


  • Start with one workflow file and expand later to avoid overwhelming complexity.
  • Limit matrix to 2–3 versions to control CI minutes and cost; add more only when necessary.
  • Use incremental caching keys (like hash of package-lock.json) to keep caches valid and small.
  • Run only unit tests in CI by default; run long integration tests on a scheduled workflow (e.g., weekly) to save time.
  • Keep build and test commands deterministic by pinning dependency versions and using lockfiles.
  • Include a quick lint step (30–60 seconds) to catch style issues before tests run.

  • Do not commit secrets into repository files; use GitHub Secrets for tokens and credentials.
  • Be mindful of GitHub Actions usage limits; avoid very large matrices or frequent workflows on free plans to prevent quota exhaustion.
  • Avoid running destructive commands on shared runners; tests that modify databases or external services should use isolated test doubles or ephemeral resources.
  • Don’t expose sensitive logs in workflow output; redact secrets and use masked values for inputs.

Was this guide helpful?