Skip to content
Back to skills

Github Actions Test Jobs

ASecurity

Configures GitHub Actions test workflows - `.github/workflows/test.yml` with matrix builds (OS × runtime, with per-OS quirks - path separators, line endings, shells - and per-language runtime matrices in references/os-matrix.md), JUnit XML artifact upload, retry/sharding, services (PostgreSQL, Redis), per-trigger filtering (pull_request, push, schedule, workflow_dispatch). Use when the project hosts on GitHub and the team wants idiomatic GitHub Actions patterns for test workflows, or needs co...

  • 10 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 12, 2026
testingpythonjavashellsqlnodegitapidatabase

Works with

  • api

Security analysis

A100/100

Pro scans all 14 files and shows the line behind each finding

Scanned October 12, 2026

npx -y skills add testland/qa --skill github-actions-test-jobs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Github Actions Test Jobs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Github Actions Test Jobs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/testland-github-actions-test-jobs/badge)](https://www.skillsdirectory.com/skills/testland-github-actions-test-jobs)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: github-actions-test-jobs
description: "Configures GitHub Actions test workflows - `.github/workflows/test.yml` with matrix builds (OS × runtime, with per-OS quirks - path separators, line endings, shells - and per-language runtime matrices in references/os-matrix.md), JUnit XML artifact upload, retry/sharding, services (PostgreSQL, Redis), per-trigger filtering (pull_request, push, schedule, workflow_dispatch). Use when the project hosts on GitHub and the team wants idiomatic GitHub Actions patterns for test workflows, or needs continuous cross-platform OS / runtime coverage."
---

# github-actions-test-jobs

## Overview

Test workflows are YAML files in `.github/workflows/` that run jobs on
trigger events ([gha][gha]). This skill sets up the idiomatic patterns -
matrix builds, sharding, service containers, JUnit reporting, trigger
filtering, concurrency, and secrets. Start with the minimal pattern in
Step 1.

[gha]: https://docs.github.com/en/actions/using-workflows/about-workflows

## When to use

- Project on GitHub.
- Need to set up test CI for a new repo.
- Existing GitHub Actions workflows need standardization.

## How to use

1. Add `.github/workflows/test.yml` triggered on `pull_request`
   and push to `main`; check out the repo and set up the runtime
   (Step 1).
2. Install dependencies and run the suite (`npm ci` then
   `npm test`).
3. Add a build matrix over OS and runtime versions with
   `fail-fast: false` for multi-target signal (Step 2), and shard
   large suites across parallel jobs (Step 3).
4. Wire any service containers the tests need and emit JUnit XML,
   uploading it with `if: always()` -
   [references/services-and-reporting.md](references/services-and-reporting.md).
5. Filter triggers by path and add `schedule` / `workflow_dispatch`
   (Step 7); add a `concurrency` group so superseded pushes cancel
   (Step 8).
6. Move tokens into `secrets.*` and reference them from step `env`
   (Step 9).
7. Verify the workflow runs (see Verify below), then review the
   anti-patterns table before merging.

## Step 1 - Basic test workflow

```yaml
# .github/workflows/test.yml
name: test

on:
  pull_request:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: npm ci
      - run: npm test
```

The minimal pattern: trigger on PR + push-to-main, install deps,
run tests.

## Step 2 - Matrix builds

```yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node: [20, 22]
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
        with: { node-version: ${{ matrix.node }} }
      - run: npm ci
      - run: npm test
```

`fail-fast: false` ensures one matrix failure doesn't cancel
others. Matrix size is OS × Node = 3 × 2 = 6 jobs.

Runner pinning, per-language runtime matrices (Node / Python / Java /
.NET), OS-specific quirks (path separators, line endings, case
sensitivity, shells), per-OS conditional steps and tests, and the
tiered cost-management cadence are in
[references/os-matrix.md](references/os-matrix.md).

## Step 3 - Sharding for parallel execution

For large suites:

```yaml
jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: npx jest --shard=${{ matrix.shard }}/4
```

4 parallel jobs, each running 1/4 of the test suite. Faster than
serial execution; cost-equivalent (same total CPU-time).

## Service containers and reporting

Wiring the service containers the tests depend on (PostgreSQL,
Redis) and publishing JUnit XML as artifacts plus PR-check
summaries are in
[references/services-and-reporting.md](references/services-and-reporting.md).

## Step 6 - Retry policy

GitHub Actions doesn't ship native test-retry; use the framework's
retry mechanism (e.g., Playwright's `retries` config) or a wrapper
action:

```yaml
- uses: nick-fields/retry@v3
  with:
    timeout_minutes: 10
    max_attempts: 2
    command: npm test
```

Use sparingly - retries hide flake. Prefer
`flaky-test-quarantine` (in the qa-flake-triage plugin).

## Step 7 - Per-trigger filtering

```yaml
on:
  pull_request:
    paths:
      - 'src/**'
      - 'tests/**'
      - 'package.json'

  push:
    branches: [main]
    paths-ignore:
      - 'docs/**'
      - '*.md'

  schedule:
    - cron: '0 4 * * *'   # daily 4am UTC

  workflow_dispatch:        # manual trigger
    inputs:
      target_browser:
        description: 'Browser to test'
        type: choice
        options: [chrome, firefox, safari]
        default: chrome
```

Path filters skip workflows when only docs change - saves CI
budget.

## Step 8 - Concurrency control

```yaml
concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: true
```

When a PR receives multiple pushes, the older runs cancel -
saves CI cost on superseded commits.

## Step 9 - Secrets + env

```yaml
env:
  CI: true

steps:
  - run: npm test
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
```

Secrets configured in repo settings; never committed.

## Verify before merge

Run the workflow once before merging - push the branch or trigger it
manually via `workflow_dispatch` (or dry-run locally with `act`).

Verify: the matrix expands into the expected job count (e.g. OS × Node =
3 × 2 = 6 jobs) and each job uploads its JUnit artifact. If a job fails on
a missing secret, confirm `NPM_TOKEN` / `TEST_DATABASE_URL` exist under
repo **Settings -> Secrets and variables -> Actions**, add any that are
missing, and re-run the job.

## Worked example

A Node service needs PR tests on Linux + macOS, plus a nightly
full run against PostgreSQL.

1. `test.yml` triggers on `pull_request` and `push` to `main`,
   with `schedule: cron '0 4 * * *'` for the nightly run.
2. The `test` job runs a matrix of `os: [ubuntu-latest,
   macos-latest]` × `node: [20, 22]` with `fail-fast: false` - 4
   jobs, and no target cancels another.
3. A separate `integration` job (Linux only) declares a
   `postgres:15` service with a `pg_isready` healthcheck and
   passes `DATABASE_URL` into `npm test`.
4. Tests emit `test-results/junit.xml`; `actions/upload-artifact@v4`
   with `if: always()` keeps the report even when tests fail, and
   `dorny/test-reporter@v1` renders it in the PR check summary.
5. A `concurrency` group keyed on the ref cancels superseded runs,
   so rapid pushes don't pile up billable minutes.

Result: PR authors get fast cross-platform signal, the nightly
catches DB-integration regressions, and failed runs still surface
their JUnit report.

## Anti-patterns

| Anti-pattern                                                          | Why it fails                                                              | Fix |
|-----------------------------------------------------------------------|---------------------------------------------------------------------------|-----|
| `fail-fast: true` on matrix                                            | First failure cancels all; lose multi-target signal.                    | `fail-fast: false` (Step 2). |
| No `concurrency` group                                                 | PRs with rapid pushes pile CI runs.                                       | Add concurrency cancel (Step 8). |
| `if: always()` everywhere                                              | Some steps shouldn't run on failure (deploy).                            | Selective `if: always()` for upload steps only ([services-and-reporting](references/services-and-reporting.md)). |
| Hardcoded secrets in YAML                                              | Secret leak; revocation needed.                                           | `secrets.X` references (Step 9). |
| Massive single workflow file                                            | Hard to navigate; merge conflicts.                                        | Split per concern (test.yml, deploy.yml, lint.yml). |
| Missing `actions/checkout` step                                         | Job can't access repo files.                                              | First step always (Step 1). |

## Limitations

- **Runner cost.** macOS / Windows runners 5x-10x more expensive
  than Linux (after free quota). Budget accordingly.
- **Per-job 6h timeout.** Long jobs need splitting.
- **Service containers Linux-only.** macOS / Windows runners don't
  support `services:` block.
- **JUnit reporting requires a third-party action.** No native.

## References

- [gha][gha] - GitHub Actions workflow basics: events + jobs +
  steps; YAML in `.github/workflows/`.
- [references/os-matrix.md](references/os-matrix.md) - OS / runtime matrix depth + per-OS quirks.
- [references/services-and-reporting.md](references/services-and-reporting.md) - service container + JUnit reporting recipes.
- `gitlab-ci-test-jobs`,
  `jenkinsfile-test-stages` -
  per-platform alternatives.
- `ci-test-job-conventions` - cross-CI conventions; CircleCI patterns
  live in its references/circleci.md.
- `junit-xml-analysis` - downstream JUnit XML parser.
- `flaky-test-quarantine` - preferred over retries.

Files in this skill

  • .tessl-plugin/plugin.json689 B
  • SKILL.md9.2 KB
  • evals/finance-flagged-the-ci-bill-after-we-went-cross-platform/criteria.json8.6 KB
  • evals/finance-flagged-the-ci-bill-after-we-went-cross-platform/task.md7.7 KB
  • evals/security-review-flagged-the-tokens-pasted-into-our-workflow/criteria.json8.1 KB
  • evals/security-review-flagged-the-tokens-pasted-into-our-workflow/task.md9 KB
  • evals/summary-job-cannot-see-the-files-the-shards-just-wrote/criteria.json6.1 KB
  • evals/summary-job-cannot-see-the-files-the-shards-just-wrote/task.md8 KB
  • evals/test-artifacts-vanish-exactly-when-the-run-is-red/criteria.json5.8 KB
  • evals/test-artifacts-vanish-exactly-when-the-run-is-red/task.md9.6 KB
  • evals/windows-crash-that-ci-has-never-once-reproduced/criteria.json7.9 KB
  • evals/windows-crash-that-ci-has-never-once-reproduced/task.md9.2 KB
  • references/os-matrix.md6.9 KB
  • references/services-and-reporting.md1.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.