Use when designing how tests run in CI on any platform (GitHub Actions, GitLab CI, Jenkins, CircleCI): how many shards, which failures are safe to retry, quarantine, artifact retention, per-PR vs nightly cadence, cancel-on-push, timeouts and secrets. CircleCI config patterns are in its references.
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
The canonical home for this skill is testland/ci-test-job-conventions
Per-CI platform skills (GitHub Actions / GitLab CI / Jenkins / CircleCI) cover how to express workflows. This skill covers what to express - the cross-platform conventions that apply regardless of CI tool.
.gitlab-ci.yml / Jenkinsfile change.Then re-check the workflow against the conventions below.
Sharding splits a test suite across N parallel jobs. Decision matrix:
| Suite total runtime | Sharding recommendation |
|---|---|
| < 2 min | None. Overhead exceeds benefit. |
| 2-10 min | Optional. Shard if PR feedback time matters. |
| 10-30 min | 2-4 shards. |
| > 30 min | 4-8 shards. Investigate the suite - may be too big. |
| > 60 min | 8+ shards + investigate suite refactoring (per e2e-suite-budget). |
Sharding cost-equivalent is N parallel × ~runtime/N - same total CPU-time, faster wall-clock.
Distinguish retry classes:
| Failure class | Retry? | Pattern |
|---|---|---|
| Runner died / system failure | Yes (1-2x) | CI platform's retry-on-runner-failure. |
| Network timeout to dependency | Yes (1x) | Test framework retry; flag for analysis. |
| Test flake (passed on retry) | No | Mark + quarantine via flaky-test-quarantine. |
| Test consistently fails | No | Real bug; investigate. |
Rule: Maximum 1 framework-level retry. More retries hide flake.
Failed-on-first-run-passed-on-retry tests are flake. Pattern:
@flaky tag.Per flaky-test-quarantine (in the qa-flake-triage plugin)
for the workflow.
# Recommended retention per artifact type
test-results: 14 days # short-term debugging
coverage-reports: 30 days # trend analysis
e2e-screenshots: 30 days # failure debugging
performance-traces: 90 days # historical analysis
deployment-logs: 90 days # audit / compliancePer-CI:
| CI | Retention default |
|---|---|
| GitHub Actions | 90 days; configurable per artifact via retention-days |
| GitLab CI | Per-job expire_in:; 30 days project default |
| Jenkins | Configured via buildDiscarder(logRotator(...)) |
| CircleCI | 30 days; non-configurable on free tier |
Don't retain forever - storage cost.
Per-PR (push to PR branch):
- Smoke tests.
- Lint + unit tests.
- Per-changed-files coverage gate.
Per-merge to main:
- Full unit + integration suite.
- Smoke E2E.
- Coverage trend tracking.
Per-deploy to staging:
- Smoke E2E against staging.
- Synthetic monitor smoke.
Nightly scheduled:
- Full E2E across browsers.
- Full security scans (axe, OWASP).
- Mutation testing (per `stryker-mutation`).
Pre-release tag:
- Cross-platform matrix (per `mobile-device-matrix-toolkit`).
- Cross-browser matrix (per `playwright-testing` references/browser-matrix.md).
- Manual UAT sign-off.
Manual / on-demand:
- Specific debug runs.
- Performance / load tests.Tier the cadence to balance feedback latency vs cost.
When PRs receive rapid pushes:
| CI | Pattern |
|---|---|
| GitHub Actions | concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true |
| GitLab CI | interruptible: true per job |
| Jenkins | disableConcurrentBuilds() in pipeline options |
| CircleCI | auto-cancel-redundant-workflows in project settings |
The pattern: cancel superseded runs. Saves CI cost on stale commits.
Never:
- Commit credentials to .yml / Jenkinsfile
- Use secrets in pull_request from forks
- Use `set -x` in scripts that handle secrets
Always:
- CI platform's secret store
- Mask in logs (`echo "::add-mask::$VALUE"` for GHA)
- Rotate on schedule
- Scope per-job (job-level env > workflow-level env > global)| Job type | Recommended timeout |
|---|---|
| Lint | 5 min |
| Unit tests | 10 min |
| Integration tests | 20 min |
| E2E (per-browser) | 30 min |
| E2E (full matrix) | 60 min |
| Deploy | 30 min |
| Performance / load | 60 min |
Hard timeouts prevent runaway jobs from consuming runners.
If the team needs CI portability (multiple CIs in use, or anticipates migration):
scripts/test.sh,
scripts/build.sh); CI calls the script.CI=true, CI_BRANCH,
CI_COMMIT_SHA); abstract per-CI vars.The goal: .github/workflows/test.yml, .gitlab-ci.yml, and
Jenkinsfile are thin wrappers calling the same scripts.
Walk the How-to-use steps for a suite that runs 25 minutes end-to-end.
@flaky and quarantine it (§3)
rather than retrying further.concurrency: group: ${{ github.workflow }}-${{ github.head_ref }}
with cancel-in-progress: true (§6) so a fresh push to the PR
cancels the superseded run.dorny/test-reporter
so results feed junit-xml-analysis
(references/junit-and-cache-lookups.md),
and upload failure screenshots with retention-days: 30 - the
e2e-screenshots band in §4.The per-CI reporting mechanism and the per-language reporter and dependency-cache lookups live in one companion reference so this file stays a decision surface:
.circleci/config.yml workflows, executors,
timing-based test splitting, orbs, insights, contexts:
references/circleci.md.github-actions-test-jobs,
gitlab-ci-test-jobs,
jenkinsfile-test-stages -
per-CI implementation skills.flaky-test-quarantine - flake handling.junit-xml-analysis - JUnit XML parser.e2e-suite-budget - when to refactor instead of shard more.testland/qa
aa16752
Canonical home
since Jul 23, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.