Skip to content
SDETRole
SDETRole

CI/CD interview question

Write a GitHub Actions workflow that runs tests in parallel shards and keeps the reports

intermediate 2–5 yrs #github-actions#sharding#artifacts

Short answer

Trigger on pull_request and push, use a matrix to split the suite into shards, cache dependencies through setup-node or setup-java, set fail-fast false so every shard reports, and upload reports and traces with actions/upload-artifact@v4 under if: always() and a unique name per shard.

Answer

A good test workflow answers three questions: when does it run, how is the work split, and where do I look when it fails. Here is the workflow I would write for a Node-based Playwright suite; the same shape applies to Java with actions/setup-java@v4.

The workflow

name: e2e

on:
  pull_request:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: e2e-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci
      - run: npx playwright install --with-deps chromium

      - name: Run shard
        run: npx playwright test --shard=${{ matrix.shard }}/4
        env:
          BASE_URL: ${{ vars.BASE_URL }}
          TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}

      - name: Upload report
        if: ${{ !cancelled() }}
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report-${{ matrix.shard }}
          path: |
            playwright-report/
            test-results/
          retention-days: 14

Why each piece is there

  • Triggers: pull_request for feedback before merge, push to main for post-merge confirmation, workflow_dispatch for manual reruns. A nightly full run would add schedule with a cron expression.
  • concurrency with cancel-in-progress: pushing a new commit to a PR cancels the outdated run instead of wasting runners.
  • permissions: contents: read: least privilege for the GITHUB_TOKEN.
  • matrix + fail-fast: false: by default a failing matrix job cancels its siblings. For tests you want every shard to finish so you see all failures.
  • Caching: setup-node with cache: npm caches the npm download cache keyed on the lockfile. npm ci gives a clean, lockfile-exact install.
  • Artifacts: if: ${{ !cancelled() }} (or always()) makes the upload run when tests fail, which is exactly when you need it. In upload-artifact@v4, artifact names must be unique within a run, so each shard includes its number; uploading to the same name from several jobs fails.
  • Secrets come from secrets, non-sensitive config from vars. Secrets are not passed to workflows triggered from forks by default, so plan for that if you accept external PRs.

Merging results

Four separate reports are awkward to read. Playwright supports a blob reporter per shard and a follow-up job (needs: test) that downloads all blobs with actions/download-artifact@v4 (using pattern and merge-multiple: true) and runs npx playwright merge-reports. For JUnit-based tools, a test reporting action can publish the XML as a check summary.

Common mistakes

  • Leaving fail-fast at its default and losing results from other shards.
  • Uploading artifacts only on success.
  • Using one artifact name across matrix jobs with v4.
  • Putting credentials directly in the YAML.

What interviewers look for

  • Correct, current syntax (@v4 actions, matrix, if conditions).
  • Thoughtful handling of failure: all shards report, artifacts always uploaded.
  • Security awareness: secrets context, minimal permissions.

A strong answer covers

  • Triggers on pull_request/push, plus schedule or workflow_dispatch
  • Matrix strategy for sharding with fail-fast disabled
  • Dependency caching to speed up runs
  • Upload reports as artifacts even on failure, with unique names
  • Secrets via secrets context, minimal permissions, concurrency or timeout
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →