Skip to content
CodeKruPro

CI/CD and tools

GitHub Actions

Workflows, jobs, triggers, secrets and artifacts.

Learn: GitHub Actions for test automation: workflows, triggers, secrets and artifacts8 minute read

GitHub Actions is the CI service built into GitHub (CI means a server runs your build and tests automatically): YAML files in the repository (YAML is a simple text format that uses indentation) describe which jobs run when something happens, such as a push or a pull request. Many teams have moved their test pipelines there from Jenkins, so interviewers ask you to read or write a workflow file (the YAML file that describes the automation) and explain triggers, jobs, secrets and reports. This article walks through a real workflow that passes actionlint, a checker for workflow files.

Where workflows live and how they are built

Each workflow is a YAML file in .github/workflows/. Its main keys:

  • on lists the events (triggers) that start it: push, pull_request, schedule, workflow_dispatch (manual) and many more.
  • jobs holds one or more jobs. Each runs on a fresh runner, a new temporary computer chosen with runs-on (for example ubuntu-latest). Jobs run in parallel unless needs orders them.
  • steps run in order on that job's runner. A step either uses a ready-made action (a reusable step written by someone else) or runs shell commands.

A Python UI test workflow

name: ui-tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11", "3.12"]
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install -r requirements.txt
      - run: pytest -n 4 --junitxml=report.xml
        env:
          TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: report-${{ matrix.python-version }}
          path: report.xml

What happens on a push to main:

  • The matrix (a list of values to try) creates two jobs, one per Python version, running in parallel. By default fail-fast is true: if one matrix job fails, GitHub cancels the others still running. Set fail-fast: false to see every result.
  • actions/checkout fetches the code and actions/setup-python installs Python. A fresh runner has none of your packages, so pip install must come first.
  • The test step gets the password from a secret, as an environment variable. Secrets are stored encrypted, masked in logs and never in the repository.
  • Steps after a failed step are normally skipped. if: always() makes the upload run anyway, so the report exists exactly when tests fail. An artifact is a file that a run saves so you can download it later. Artifact names must be unique within a run, which is why the name includes the Python version.

For Java, actions/setup-java with distribution: temurin, java-version: "21" and cache: maven prepares the JDK and caches dependencies, and the test step runs mvn -B test.

Schedules and manual runs

on:
  schedule:
    - cron: "30 1 * * *"
  workflow_dispatch:
    inputs:
      groups:
        description: TestNG groups to run
        type: choice
        options: [smoke, regression]
        default: smoke

A schedule uses cron, a standard way to write times (the five fields are minute, hour, day of month, month and day of week; the Jenkins topic explains them). Scheduled workflows run on the latest commit of the default branch (usually main) and use UTC, the world time standard, by default, so 30 1 * * * is 07:00 in India. Runs can start late when GitHub Actions is busy, and the shortest interval is every five minutes. workflow_dispatch adds a "Run workflow" button with inputs, GitHub's version of Jenkins parameters, read as ${{ inputs.groups }}. On other events the input is empty, so a fallback such as ${{ inputs.groups || 'smoke' }} keeps the command valid.

Ordering jobs with needs

A common shape is a build job, then api-tests and ui-tests in parallel (both needs: build), then a report job with needs: [api-tests, ui-tests] and if: always(). If a job fails, the jobs that need it are skipped unless they have such a condition.

The build job runs first; api-tests and ui-tests both need build and run in parallel; report needs both and runs even after a failure because of if: always().
needs orders jobs; jobs without a link between them run in parallel.

Secrets and other settings

Secrets cannot be used directly in if: conditions, so put them in an environment variable and test that. Workflows started by pull requests from forks (copies of the repository made by other people) do not receive repository secrets (only a read-only GITHUB_TOKEN, a temporary key that GitHub creates for each run), so tests that need secrets fail there by design. Environments such as staging can hold their own secrets and require approval. timeout-minutes on a job stops runs that never end (the default is 360 minutes), and jobs that must reach internal systems can run on self-hosted runners, which are your own machines inside your network instead of GitHub's.

How to answer in an interview

Read a workflow aloud from the top: the triggers, the jobs and their runners, each step, where secrets come from, and what happens to the report when tests fail. When asked about moving from Jenkins, map the parts: webhooks to on: push and pull_request, cron to schedule (in UTC), parameters to workflow_dispatch inputs, credentials to secrets, and junit plus archiveArtifacts to artifact uploads.

Common mistakes

  • Uploading reports without if: always(), so they vanish when tests fail.
  • Forgetting that schedules use UTC.
  • Expecting jobs to share files; use artifacts to pass them.
  • Writing a password in the YAML instead of a secret.

Recap

A workflow lists triggers in on, jobs that run on fresh runners, and steps that use actions or run commands. A matrix multiplies jobs, needs orders them, secrets arrive as environment variables, and if: always() keeps reports when tests fail.

11 questions0/11 solved

Not startedNot startedIn progressIn progressSolvedSolvedPro+Pro+

The first 2 questions of each topic are free. Pro+ opens every question.

Back to the plan