GitHub Actions (GH-200) · 25% practice allocation

GitHub GH-200: Author and Manage Workflows Practice Questions

5 free sample questions from the Author and Manage Workflows domain, with answers and explanations. The full GH-200 bank has 133 questions across 5 domains. Questions are scenario-based and written from the official GitHub exam guide.

1.

A developer wants a workflow job to continue running its remaining steps even if one particular step fails, but the overall job should still be marked as failed at the end. Which configuration achieves this on the individual step?

  • A. Set continue-on-error: true on the job
  • B. Set if: always() on each subsequent step in the job
  • C. Set continue-on-error: true on the step✓ Correct
  • D. Wrap the step command in || true in the shell script
Explanation

continue-on-error: true on a step allows subsequent steps to run if that step fails, while the job itself is still ultimately marked failed — exactly the described behavior. B is wrong because setting continue-on-error: true on the job level causes the entire job (and dependent jobs using needs) to be treated as successful even when steps fail, which is too broad. C is wrong because || true makes the shell command exit with code 0, meaning GitHub Actions never sees a failure at all — the step is marked as passed, not just continued past. D is wrong because if: always() on subsequent steps would make them run regardless, but the failing step itself would still halt execution of later steps by default unless combined with another mechanism; it also doesn't control the job's final status in the desired way.

2.

A workflow needs to read a non-sensitive configuration value (e.g., a deployment region like us-east-1) that is shared across multiple repositories in an organization. The value should be easily updatable without modifying workflow YAML files. Which approach is MOST appropriate?

  • A. Store the value in a .env file committed to the repository and source it in a shell step
  • B. Hardcode the value directly in the workflow YAML under the env: key at the workflow level
  • C. Store the value as an organization-level variable and reference it with ${{ vars.DEPLOY_REGION }}✓ Correct
  • D. Store the value as an organization-level secret and reference it with ${{ secrets.DEPLOY_REGION }}
Explanation

Organization-level variables (the vars context) are designed exactly for non-sensitive, reusable configuration values that can be shared across repos and updated centrally without touching YAML files. A is wrong because secrets are encrypted and intended for sensitive data; using them for non-sensitive config is a misuse and makes values harder to audit. C is wrong because hardcoding means every repo/workflow file must be updated manually when the value changes, defeating the goal. D is wrong because a committed .env file stores values in source control and requires a shell step to source it, which is fragile and not a GitHub-native configuration mechanism.

3.

A workflow has the following concurrency configuration at the workflow level:

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: false

Three workflow runs for the same branch are queued in quick succession. What is the resulting behavior?

  • A. All three runs execute in parallel because cancel-in-progress is false
  • B. All runs after the first are immediately cancelled because they share the same concurrency group
  • C. The first run executes; the second and third are queued and will run sequentially after the first completes✓ Correct
  • D. The first run executes; the second run is queued; when the third arrives, it replaces the second in the queue, and only two total runs execute
Explanation

With cancel-in-progress: false, GitHub Actions does not cancel in-progress or queued runs. Instead, new runs wait until the current run in the same concurrency group finishes. Only one run executes at a time, and the others are queued. All three runs will eventually execute in order. A is wrong — the concurrency group still serializes runs; cancel-in-progress: false does not mean parallel execution. C describes the behavior when cancel-in-progress: true, where a newly queued run replaces a previously pending (queued) run — but that is not the case here. D is wrong — cancellation only happens when cancel-in-progress: true.

4.

A team authors a reusable workflow at .github/workflows/publish.yml with the following input definition:

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
      notify:
        required: false
        type: boolean
        default: true

A caller workflow invokes it but omits the notify input. What value does ${{ inputs.notify }} resolve to inside the reusable workflow?

  • A. false, because boolean inputs default to false when not provided by the caller.
  • B. An empty string, because the caller did not supply the value.
  • C. The workflow run fails with a validation error because notify was not passed by the caller.
  • D. true, because the reusable workflow declares default: true for the notify input.✓ Correct
Explanation

Option D is correct: when a workflow_call input has a default value defined, that default is used whenever the caller omits the input. Here default: true means ${{ inputs.notify }} evaluates to true. Option A is wrong: GitHub Actions does not implicitly default boolean inputs to false; it uses the declared default value. Option B is wrong: omitting an optional input with a declared default does not produce an empty string — the default is applied. Option C is wrong: only required: true inputs cause a validation error when omitted; notify is required: false and has a default, so omitting it is perfectly valid.

5.

A workflow defines job outputs that are consumed by a downstream job. Review this configuration:

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.tag.outputs.version }}
    steps:
      - id: tag
        run: echo "version=1.4.2" >> $GITHUB_OUTPUT
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying ${{ needs.build.outputs.version }}"

Assuming the workflow runs successfully, what does the deploy job print?

  • A. Deploying undefined because the version key must be declared under jobs.build.steps not jobs.build.outputs
  • B. Deploying 1.4.2✓ Correct
  • C. Deploying ${{ needs.build.outputs.version }} (literal string, because expressions are not evaluated in run blocks)
  • D. Deploying (empty string, because job outputs are not accessible via needs context without additional configuration)
Explanation

Option B is correct: the workflow is configured exactly as documented. The build job declares a job-level outputs block mapping version to ${{ steps.tag.outputs.version }}. The step with id: tag writes version=1.4.2 to $GITHUB_OUTPUT. The deploy job lists needs: build, which makes the needs.build.outputs context available. The expression ${{ needs.build.outputs.version }} resolves to 1.4.2, so the printed message is Deploying 1.4.2. Option D is wrong: the needs context is exactly how downstream jobs access upstream job outputs; the configuration is complete and correct. Option C is wrong: expressions in run: blocks ARE evaluated by GitHub Actions before the shell executes the script. Option A is wrong: jobs.<job_id>.outputs is the correct location to declare job-level outputs; the step output is correctly referenced via the steps context within that expression.

Test yourself across every GH-200 domain

The free GH-200 practice test mixes about 20 questions weighted like the exam. The full 133-question bank adds instant grading, flashcards and a timed mock exam.

Study this domain

Author and Manage Workflows study guide (GH-200) →

Other GH-200 domains

← All GitHub Actions study resources