28 min read5 domains coveredFree practice, no sign-up
The GitHub Actions certification (GH-200) tests one habit above feature recall: choosing the workflow structure, trigger, context, runner, secret scope, or security control that best fits a stated automation need. GitHub hands you a short CI/CD situation with a constraint - run something nightly with no commit, return a value from a reusable workflow to its caller, give the automatic token only the access it needs, cache dependencies so a small lockfile change does not redownload everything - and asks which configuration meets it. The hard part is rarely knowing that the "schedule" event or a reusable workflow exists. It is knowing which one wins when two or three options could plausibly work and only one matches what the scenario actually asked for at the least operational overhead, lowest cost, or least privilege.
It suits practitioners who already build and operate automation on "GitHub Actions": developers, DevOps engineers, and platform teams who write workflows, author actions, and manage Actions at organisation scale. The exam reweighted significantly in January 2026: objectives were added, removed, moved and reworded, so older study notes mislead. It now draws across five domains, with authoring and managing workflows carrying the most marks, followed closely by managing Actions for the enterprise, then consuming and troubleshooting workflows, authoring and maintaining actions, and securing and optimising automation. There is no enforced prerequisite, but the questions assume real exposure to workflow YAML, contexts and expressions, the action types, runners, and the secrets and permissions model.
The exam rewards decision rules, not memorised syntax. Most questions are short scenarios where two or three answers are technically plausible and only one is the best fit once you weigh the named constraint: a single central definition so a fix reaches every consumer, a value that survives between steps, a token that carries no more than the job needs. Running through the security objectives is one thread the exam never drops: a design that works can still be the wrong answer when it grants broad permissions, trusts unsanitised input in a run step, stores a long-lived cloud secret, or pins a third-party action to a mutable tag instead of a full commit SHA.
GH-200 is a pick-the-right-mechanism exam: almost every question is a CI/CD scenario with a stated need, and the right answer is the trigger, workflow structure, context, runner, secret scope, caching or artifact mechanism, action type, or security control built for it - and an insecure design can be wrong even when it works.
Difficulty
Intermediate
Best for
Working GitHub Actions practitioners: developers, DevOps and platform engineers who author workflows and custom actions, operate GitHub-hosted and self-hosted runners, and manage Actions across an organisation, and who need to prove they can choose secure, correctly scoped, cost-aware automation under real constraints.
Prerequisites
None enforced. Genuine hands-on experience writing workflow YAML, using contexts and expressions, authoring composite, JavaScript and Docker actions, and working with runners, secrets, variables and the GITHUB_TOKEN permissions model is what actually carries you through the scenarios. Comfort reading a workflow file and predicting what it does is the baseline.
About 60 to 65 questions
Questions
100 min
Time allowed
700 / 1000
Pass mark
$99
Exam cost (USD)
267
Practice questions
How this exam thinks
One habit decides this exam: read the scenario for its constraint, then pick the GitHub Actions mechanism built for it. Almost every question is a short automation situation with a stated need - fire on a recurring timetable with no human, share one definition so a fix reaches every repository, hand a value from one step or job to the next, scope the automatic token to least privilege, warm a near-miss cache - and several options will sound capable. Only one matches what the scenario actually asked for, and the wrong answers are usually plausible misdescriptions of real features.
The structural splits are the spine. For triggers, "schedule" with a cron expression runs on a timetable with no commit and no actor; "workflow_dispatch" is a manual button with typed inputs; "repository_dispatch" fires on an external API call; push and pull_request fire on repository events. For reuse, a reusable workflow is referenced with uses at job level and stays a single central definition so a fix propagates to every caller, a composite action bundles shell run steps into one unit referenced as a step, and a starter workflow seeds a copy into each repository. For passing data, GITHUB_ENV sets an environment variable for later steps in the same job, GITHUB_OUTPUT registers a step output read through the steps context, artifacts move files between jobs, and a reusable workflow only returns a value mapped through on.workflow_call.outputs. Pick by what the scenario needs done, not by which feature is newest.
The security and cost questions reward least privilege and the lever built for the pattern, and they treat a working-but-insecure design as wrong. A top-level permissions block sets every unlisted GITHUB_TOKEN scope to none for all jobs, so it is the reliable way to restrict the token. OpenID Connect federation removes long-lived cloud secrets by exchanging a short-lived token a cloud trust policy validates. Third-party actions are pinned to a full commit SHA, not a mutable tag, because a tag can be moved under you. restore-keys warms a cache on an exact-key miss; retention-days caps an artifact's lifetime at upload and is clamped down by an organisation maximum. When two answers both work, the one with least operational overhead, least privilege, and correct scope wins - and the option that quietly grants more than the job needs is the trap, not the convenience.
What each domain tests and how to study it
The GH-200 blueprint is split across 5 domains. Weights are the official share of the exam; see the official exam guide for the authoritative breakdown.
What you must be able to do. Given a workflow requirement, choose the trigger, job and step structure, matrix strategy, context or expression, and data-passing mechanism that produces the intended runs and moves values between steps, jobs and reusable workflows correctly and securely.
In one sentenceThe biggest domain: picking the right event trigger, structuring jobs and steps with needs and if, and moving data between steps and jobs with the correct command file or output mapping.
Recall check: answer these from memory first
A workflow must run nightly at 02:00 UTC with no commit and no person starting it. Which trigger fires it, and why do workflow_dispatch, repository_dispatch and push not?
A step computes a version string that every later step in the same job must read as an environment variable. Which command file do you append to, and how does that differ from GITHUB_OUTPUT?
A reusable workflow sets a job output but the caller cannot read it. What must the reusable file declare so the caller reads needs.call-build.outputs.build_id, and why is the job output alone not enough?
A caller passes a secret named DEPLOY_KEY to a reusable workflow and the run fails saying the secret is not valid. What must change in the reusable workflow, and what does secrets: inherit do instead?
What it tests. Authoring workflows end to end. Configuring triggers for scheduled, manual, webhook and repository events with the right scope and permissions; defining and validating workflow_dispatch inputs and passing inputs and secrets to reusable workflows through workflow_call; structuring jobs and steps with needs for dependencies and if for conditional execution; using workflow commands, environment variables and service containers for dependent services; generating job variations with strategy and matrix using include, exclude, fail-fast and max-parallel to control coverage and cost; reading metadata through contexts and evaluating expressions while distinguishing parse-time from runtime evaluation and preventing secret leakage; managing caching and artifacts and passing data with GITHUB_ENV, GITHUB_OUTPUT, artifacts and reusable workflow outputs; and producing job summaries with GITHUB_STEP_SUMMARY, status badges, environment protections, and reusing YAML with anchors and aliases.
How to study it. Build a trigger decision tree and drill it from the constraint: recurring with no commit and no actor is "schedule" with cron in UTC, a manual button with typed inputs is "workflow_dispatch", an external system firing the run is "repository_dispatch", and a code event is push or pull_request. Then fix the data-passing split until it is automatic: GITHUB_ENV sets an environment variable for every later step in the same job, GITHUB_OUTPUT registers a step output read as steps.<id>.outputs.<name>, artifacts carry files across jobs, and a reusable workflow returns a value only when a job output is mapped through on.workflow_call.outputs and the caller reads it via needs. Learn the workflow_call contract: a caller may pass a secret only if the reusable file declares it under on.workflow_call.secrets, or uses secrets: inherit. Practise matrix expansion by hand with include and exclude, and set fail-fast: false and max-parallel when the scenario wants full coverage or cost control. Read contexts as parse-time versus runtime and never interpolate an untrusted value straight into a run step.
Easy to confuse
GITHUB_ENV versus GITHUB_OUTPUT. Appending NAME=value to the file named by GITHUB_ENV sets an environment variable injected into every later step in the same job; appending name=value to the file named by GITHUB_OUTPUT registers a step output read as steps.<step_id>.outputs.<name>. Use GITHUB_ENV for an env var all following steps read implicitly, GITHUB_OUTPUT when a specific step output must be referenced through the steps context.
schedule versus workflow_dispatch versus repository_dispatch. schedule fires on a cron timetable in UTC with no commit and no actor; workflow_dispatch is a manual Run workflow button that records the operator and accepts typed inputs; repository_dispatch fires on an external REST API call carrying a custom payload. A run with no commit, no actor and no recorded API call is schedule, not a manual or external trigger.
reusable workflow output versus passing data through an artifact or GITHUB_ENV. A reusable workflow returns a value to its caller only when a job output is mapped through an on.workflow_call.outputs entry and the caller reads it via the needs context; artifacts move files between jobs and GITHUB_ENV sets env vars within a job, but neither bridges a value to the caller as an output. The on.workflow_call.outputs mapping is the only path that reaches the caller.
Worked example from the GH-200 bank
lock_openFree sampleAuthor and manage workflowsmedium
A reusable workflow called through workflow_call computes a build identifier and must return it to the caller so the caller can reference it as needs.call-build.outputs.build_id. The reusable file already sets a job output. What else must the reusable workflow declare for the value to reach the caller?
on:
workflow_call:
outputs:
build_id:
value: ${{ jobs.compute.outputs.build_id }}
ADeclare an output under on.workflow_call.outputs whose value maps to the job output, because a reusable workflow only returns values that are mapped through its workflow_call outputs block.check_circle Correct
BNothing further, because once a job inside the reusable workflow sets a job output, the caller can read it directly as needs.call-build.outputs.build_id without any on.workflow_call declaration.
CUpload the build identifier as an artifact in the reusable workflow, because the caller automatically downloads artifacts produced by a called workflow and reads them as job outputs.
DWrite the build identifier to the GITHUB_ENV file in the reusable workflow, because env values set there are inherited by the calling workflow and exposed under the called job's outputs.
Return data from a reusable workflow by mapping a job output through an on.workflow_call.outputs entry so the caller reads it via needs. A reusable workflow does not expose its internal job outputs automatically. It must declare each return value under on.workflow_call.outputs, setting that output's value to the relevant job output expression such as jobs.compute.outputs.build_id. Only then does the calling workflow read the value through the needs context of the job that called it. Artifacts and GITHUB_ENV do not bridge to the caller as outputs.
Why A is correct: A reusable workflow returns data only through an on.workflow_call.outputs entry whose value references the producing job output, so mapping build_id there lets the caller read needs.call-build.outputs.build_id.
Why B is wrong: Tempting because the job output exists, but a reusable workflow only exposes values the caller can read when they are declared under on.workflow_call.outputs, so the caller would otherwise see nothing.
Why C is wrong: Tempting because artifacts share data, but they are downloaded explicitly and are not surfaced as outputs, so an artifact cannot populate needs.call-build.outputs.build_id for the caller.
Why D is wrong: Tempting because GITHUB_ENV sets values, but those stay inside the job that wrote them and are never inherited by the caller, so they cannot become a reusable workflow output.
What you must be able to do. Given a run history, log line, or workflow file, infer which trigger and configuration produced a run, diagnose a failure from logs and annotations, interpret matrix expansions and merged YAML, manage logs and artifacts through the UI and REST API, and consume organisation-shared reusable and starter workflows correctly.
In one sentenceThe diagnosis domain: reading a run's history and logs to find why it ran and why it failed, interpreting matrices and anchors, and consuming shared reusable and starter workflows without re-authoring them.
Recall check: answer these from memory first
A run shows no commit, no named actor and no recorded API dispatch. Which trigger most likely produced it, and why do push, workflow_dispatch and repository_dispatch each leave a different fingerprint?
A failed step ends with a non-zero exit-code line and no other error text. What does that line tell you about where the failure originated, and where do you look next?
An artifact uploaded with no retention value disappears after about ninety days. How do you cap it at fourteen days for one workflow, and why does changing the repository default not fix the existing artifacts?
What is the difference between disabling a workflow and deleting it, and when would you disable rather than delete?
What it tests. Operating and debugging workflows you did not necessarily write. Identifying which trigger and configuration produced a run and predicting its effects from the workflow file and run history; diagnosing failed runs by reading step logs, run history and annotations to locate the cause; interpreting matrix expansions and merged YAML anchors and aliases when analysing a workflow, and selectively re-running individual matrix jobs; locating, downloading and managing workflow logs and artifacts through the user interface and the REST API; consuming organisation-level reusable workflows and starter workflows, including non-public templates, and customising them for a repository; and distinguishing starter workflows, reusable workflows and composite actions, and contrasting disabling a workflow with deleting it.
How to study it. Practise inference from run-history evidence: no commit plus no actor plus no recorded API call points to a scheduled run, a head commit points to push, and a named operator points to workflow_dispatch. Read a failed step's final exit-code line as the result of a non-zero command return and trace the cause in the preceding output, rather than blaming the runner or a timeout unless the log says so. Drill artifact retention as a runtime concern: retention-days on the actions/upload-artifact with block overrides the inherited default for one artifact, a configured organisation maximum clamps any larger request down, the default setting is not applied retroactively, and an artifact can be deleted early through the UI or REST. Learn to expand a matrix on paper and to re-run a single failed matrix job. Finally, fix the reuse contrast: a reusable workflow is one central definition consumers reference, a starter workflow is a copied template, and disabling a workflow stops it running while keeping the file, whereas deleting removes it.
Easy to confuse
disabling a workflow versus deleting a workflow. Disabling a workflow stops it from being triggered while leaving the file in the repository, so it can be re-enabled later with its history intact; deleting removes the workflow file entirely. Disable to pause a noisy or broken workflow you intend to restore, delete only when the automation is permanently gone.
starter workflow versus reusable workflow when consuming shared automation. A starter workflow seeds a copy of the YAML into each repository, so later fixes to the template never reach the existing copies; a reusable workflow stays one central definition referenced with uses, so a fix there applies to every caller on its next run. Consume a starter workflow to bootstrap a one-off file, a reusable workflow when the logic must stay centrally governed.
step exit-code line versus runner crash or timeout. A non-zero exit-code summary line means a command inside the step returned non-zero, so the real cause is in the earlier step output; a runner crash or a timeout-minutes breach is recorded with its own distinct message. Read the exit code as a command failure unless the log explicitly names infrastructure failure or a timeout.
Worked example from the GH-200 bank
lock_openFree sampleConsume and troubleshoot workflowsmedium
A team manages how long their workflow artifacts are stored to keep storage costs down. Their organisation has set a maximum artifact retention limit of thirty days, and individual workflows set retention-days on their actions/upload-artifact steps. The team needs an accurate understanding of how these settings interact before they tune them further. Which TWO statements about managing artifact retention are accurate? Select TWO.
AA retention-days value above the configured maximum is clamped down to that maximum, so the snippet's request for forty-five days is reduced to the organisation's thirty-day ceiling.check_circle Correct
BAn uploaded artifact can be deleted from its run before its retention period elapses, through the web interface or the REST API, which frees the storage it occupied immediately.check_circle Correct
CThe retention-days input on the upload step also governs how long the run's logs are kept, so setting it shortens the log archive retention by the same number of days as the artifact.
DLowering the organisation's default retention shortens artifacts that were already uploaded, so existing build outputs are re-expired to match the newly reduced default value retroactively.
Understand that a configured maximum clamps any larger retention-days request and that artifacts can be deleted early, while retention is set at upload time and does not cover logs. Retention-days expresses a desired lifetime but the repository, organisation or enterprise maximum is a hard ceiling, so a forty-five-day request is clamped to the thirty-day limit. Because retention is a maximum rather than a floor, an artifact can also be deleted early through the UI or REST to free storage at once. Retention-days governs only the artifact, not the separately handled run logs, and the value is fixed when the artifact is created so a lowered default is not applied retroactively.
Why A is correct: GitHub enforces the repository, organisation or enterprise maximum as a hard ceiling, so a larger retention-days request is silently clamped down to that configured limit.
Why B is correct: Retention sets a maximum lifetime rather than a guaranteed one, so an artifact can be manually deleted early through the UI or REST to reclaim its storage at once.
Why C is wrong: Tempting because logs and artifacts both relate to a run, but retention-days applies only to the uploaded artifact and never alters how long the run's logs are kept.
Why D is wrong: Tempting because the default does change future behaviour, but retention is fixed when an artifact is created, so the new default never re-expires artifacts that already exist.
What you must be able to do. Given a custom-action requirement, choose between JavaScript, Docker container and composite action types, define the action.yml metadata and directory structure, set outputs and emit log messages with workflow commands, choose a distribution model, and apply a sound versioning strategy.
In one sentenceThe action-authoring domain: picking the right action type for the task, writing correct action.yml metadata, setting outputs with GITHUB_OUTPUT, and versioning and distributing the action sensibly.
Recall check: answer these from memory first
A team wants to package three existing shell run steps into one unit callable with a single uses reference, without rewriting in another language or building an image. Which action type fits, and what does its runs block declare?
Name two accurate properties of a JavaScript action: what does its runs block declare and on which hosted platforms does it run?
Inside a composite or JavaScript action, which file do you append name=value to so a later step reads it as steps.compute.outputs.tag, and why not GITHUB_ENV?
An action.yml input named log-level has a default of info and the caller omits it under with. What value does the action read at runtime, and why?
What it tests. Building and maintaining custom actions. Selecting and implementing the appropriate action type among JavaScript, Docker container and composite actions, accounting for immutable action behaviour; troubleshooting custom action execution and runtime errors during a run; defining the required files, directory structure and action.yml metadata including inputs, outputs and branding; implementing workflow commands inside an action to set outputs, write environment files and emit log messages; selecting a distribution model among public, private and Marketplace and publishing to the GitHub Marketplace; and applying versioning and release strategies using tags, release branches and semantic version references.
How to study it. Fix the action-type decision tree from the task: a composite action bundles existing shell run steps into one unit referenced with uses and using: composite; a JavaScript action declares using: node20 with runs.main pointing at a committed entry file and runs cross-platform on the runner's bundled Node.js; a Docker container action ships an image, runs on Linux only and pulls before each invocation; and a reusable workflow is not an action at all because it is invoked at job level through workflow_call. Drill the metadata details: an input default declared in action.yml is substituted automatically when the caller omits it under with, and a step output is registered by appending name=value to the file named by GITHUB_OUTPUT, read as steps.<id>.outputs.<name>. Learn the versioning strategy: publish a semantic version tag, move a major-version tag so consumers can track it, and remember consumers should pin third-party actions to a full commit SHA for security.
Easy to confuse
composite action versus reusable workflow. A composite action bundles shell run steps under runs.using: composite and is referenced as a step with uses inside a job; a reusable workflow is a file under .github/workflows invoked at job level through workflow_call. Use a composite action to package step-level logic reusable inside any job, a reusable workflow to share an entire job-and-trigger definition centrally.
JavaScript action versus Docker container action. A JavaScript action declares using: node20 with runs.main and runs directly on the runner's bundled Node.js across Linux, Windows and macOS hosted runners; a Docker container action ships an image, runs on Linux only and pulls the image before each invocation. Choose JavaScript for cross-platform speed, Docker only when a specific image or non-Node toolchain is required.
action input default versus a required input. An input with a declared default is substituted automatically when the caller omits it under with, so the action reads the default rather than failing; a required input with no default causes the run to fail when omitted. A default makes an input optional, it does not make the input required.
Worked example from the GH-200 bank
lock_openFree sampleAuthor and maintain actionsmedium
An author is deciding when a JavaScript action is the right type for a new custom action. Which two characteristics are accurate properties of a JavaScript action authored for GitHub Actions? Select TWO.
runs:
using: "node20"
main: "dist/index.js"
AIt runs directly on the runner with the bundled Node.js runtime, so it executes on Linux, Windows, and macOS hosted runners alike.check_circle Correct
BIt must be packaged into a container image first, so the runner pulls that image before each invocation regardless of the host operating system.
CIt declares using: node20 in the runs block and points main at a committed JavaScript entry point that the runner invokes when the step starts.check_circle Correct
DIt groups several existing shell run steps under using: composite so the steps execute in sequence without any JavaScript entry point.
Recognise that a JavaScript action runs on the runner's Node.js across all hosted platforms via runs.using and runs.main. A JavaScript action is defined by runs.using set to a Node version and runs.main pointing at a committed JavaScript entry file, which the runner executes directly on its bundled Node.js runtime. Because that runtime exists on Ubuntu, Windows, and macOS hosted runners, the action runs cross-platform without any image, unlike a Docker container action that ships an image or a composite action that lists shell steps.
Why A is correct: JavaScript actions run on the runner's own Node.js runtime, which ships on every GitHub-hosted operating system, so the same action works cross-platform without an image.
Why B is wrong: Tempting because images feel portable, but image packaging describes a Docker container action, not a JavaScript action, which runs from committed JavaScript on the host.
Why C is correct: A JavaScript action sets runs.using to a Node version and runs.main at the JavaScript entry file, which is exactly how the runner locates and executes the code.
Why D is wrong: Tempting since both reuse logic, but using: composite with run steps describes a composite action, whereas a JavaScript action needs a Node entry point declared by main.
What you must be able to do. Given an organisation-scale requirement, choose the shared component, access and usage policy, runner configuration, runner group scoping, and secret or variable scope that standardises automation centrally while granting the least access and the least ongoing maintenance.
In one sentenceThe enterprise domain: governing Actions at scale with reusable components and policies, configuring GitHub-hosted and self-hosted runners and runner groups, and scoping secrets and variables at the right level.
Recall check: answer these from memory first
A platform team wants every repository to run the same security-scanning logic from one central definition so a bug fix updates all consumers. Which component do they author, and why not a starter workflow or composite action?
A job must run on self-hosted runners that carry a custom gpu label. How do you target them with runs-on, and why does the label alone or a separate group key not do it?
One deployment secret must be available to three specific repositories without copying it or exposing it to the rest of the organisation. Which secret scope and visibility meets this with least maintenance?
What is the documented maximum depth of a nested reusable workflow chain, and what is counted in that depth?
What it tests. Managing GitHub Actions across an organisation. Defining and managing reusable components and workflow templates so teams share standardised automation; controlling access to actions and workflows and configuring organisation use policies that restrict which actions may run; configuring GitHub-hosted runners and identifying preinstalled software, installing additional tools at runtime when required; configuring self-hosted runners and runner groups and scoping their access to organisations and repositories; applying IP allow lists and networking settings to runners and troubleshooting runner connectivity and capacity; defining and scoping encrypted secrets and configuration variables at organisation, repository and environment levels; and accessing secrets and variables in workflows and actions and managing them through the REST API.
How to study it. Anchor on choosing the central component: when shared logic must stay a single definition so a fix propagates everywhere, the answer is a reusable workflow referenced with uses at job level, not a starter workflow that copies itself or a composite action that only groups steps inside a job. Learn the runner targeting rule: runs-on given an array of labels dispatches only to a runner carrying all of them, so [self-hosted, gpu] targets a self-hosted machine that also advertises gpu, and there is no separate group key that filters by capability label. Fix the secret-scoping ladder: an organisation secret with selected-repositories visibility shares one centrally rotated value with named repositories without duplication, an environment secret gates a deployment behind environment protections, and a repository secret is local. Drill scope levels for variables the same way, and recall hard limits the exam asks about, such as the four-level maximum depth for nested reusable workflow chains including the top caller.
Easy to confuse
reusable workflow versus starter workflow for organisation-wide standardisation. A reusable workflow stays one central definition that consumers reference with uses, so a fix made there reaches every caller on the next run; a starter workflow copies itself into each repository, so later fixes never reach existing copies. Use a reusable workflow when the logic must stay centrally governed, a starter workflow only to bootstrap an editable starting file.
organisation secret with selected-repositories visibility versus a repository secret duplicated per repo. An organisation secret with selected-repositories visibility stores one value rotated in a single place and grants it to named repositories; duplicating a repository secret across repos stores the same value many times and must be rotated in every one. Choose the organisation secret with selected visibility for least ongoing maintenance and exclusion of the other repositories.
GitHub-hosted runner versus self-hosted runner. A GitHub-hosted runner is a fresh managed machine with preinstalled software that GitHub maintains and bills per minute; a self-hosted runner is hardware you provide, register and maintain, suited to custom hardware such as GPUs, private network access or specific tooling, and targeted by the self-hosted label plus your custom labels. Pick hosted for zero maintenance, self-hosted when hardware, network or tooling demands it.
Worked example from the GH-200 bank
lock_openFree sampleManage GitHub Actions for the enterprisemedium
A platform team must make one shared deployment secret available to three specific repositories in an organisation, without copying the secret into each repository and without exposing it to every other repository in the organisation. Which approach meets this requirement with the least ongoing maintenance?
ACreate an organisation secret with its visibility set to selected repositories and add the three repositories to its selected list, so all three read one centrally managed value.check_circle Correct
BCreate the same repository secret separately in each of the three repositories, so the value is scoped per repository while staying identical across the three.
CCreate an organisation secret with its visibility set to all repositories, then rely on branch protection in the other repositories to block them from reading it.
DCreate an environment secret in one repository and let the other two repositories reference that environment through a shared deployment configuration setting.
Use an organisation secret with selected-repositories visibility to share one managed value across specific repositories without duplication. Organisation secrets store a value once and support a visibility of all, private or selected repositories. Setting selected repositories and listing the three target repositories gives those repositories access to a single centrally rotated secret, while every other repository is excluded, which duplicated repository secrets and all-repositories visibility cannot achieve.
Why A is correct: An organisation secret stores the value once, and a selected-repositories visibility restricts access to exactly the listed repositories, so the three share one managed secret without exposing it organisation-wide.
Why B is wrong: This is tempting because repository secrets do scope per repository, but it duplicates the value three times, so every rotation must be applied in three places. That is exactly the maintenance the requirement avoids.
Why C is wrong: This is tempting because it centralises the value, but all-repositories visibility exposes the secret to every repository in the organisation. Branch protection governs merges, not secret access, so it cannot restrict scope.
Why D is wrong: This is tempting because environment secrets scope tightly, but an environment and its secrets belong to a single repository. Other repositories cannot reference another repository's environment, so the value is not shared.
What you must be able to do. Given a security or cost constraint, choose the environment protection, input-sanitising and least-privilege approach, GITHUB_TOKEN scoping, OpenID Connect federation, action-pinning policy, and caching, retention or concurrency setting that secures and speeds the automation without granting more than the job needs.
In one sentenceThe security and cost domain: locking down the automatic token, removing long-lived cloud secrets with OpenID Connect, pinning actions to a commit SHA, and tuning caching, retention and concurrency for speed and spend.
Recall check: answer these from memory first
A job needs only contents read and checks write and nothing else writable, for every job now and later. Which permissions block placement and contents apply that least-privilege posture most reliably, and why does a job-level block fall short?
A deployment needs cloud credentials but the team wants no long-lived secret stored in GitHub. Which mechanism solves this, and what two claims can the team customise on the issued token?
An exact cache key misses after a small lockfile change and the whole dependency set redownloads. Which single addition restores the newest near-miss cache as a warm start, and why not fail-fast or lookup-only?
Why is pinning a third-party action to v3 weaker than pinning to a full commit SHA, and what attack does the SHA prevent?
What it tests. Securing and optimising automation. Using environment protections and approval gates and selecting trustworthy actions from the GitHub Marketplace; mitigating script injection by sanitising untrusted input, applying least-privilege permissions and avoiding untrusted data in run steps; configuring granular GITHUB_TOKEN permissions and using OpenID Connect token federation to remove long-lived cloud secrets; pinning third-party actions to full commit SHAs, enforcing action usage policies and verifying artifact attestations and provenance; and optimising workflow performance and cost using caching, artifact retention, concurrency and scaling strategies.
How to study it. Make least privilege your reflex: a top-level permissions block sets every unlisted GITHUB_TOKEN scope to none for all jobs, so listing only contents: read and checks: write yields exactly those grants and nothing else, where a job-level block would leave other jobs on the default. Learn OpenID Connect as the answer whenever a workflow needs cloud credentials without a stored secret: the workflow requests a short-lived token whose subject and audience a cloud trust policy validates, the subject template is customisable through the Actions OIDC REST API, and the audience defaults to the owner URL but is overridable per request. Treat any third-party action pinned to a mutable tag as a wrong answer and pin to a full commit SHA instead. For optimisation, drill the cache: actions/cache tries the exact key first and only on a miss walks restore-keys to restore the newest prefix-matching cache as a warm start, and use concurrency to cancel superseded runs. Remember a working-but-insecure option is still wrong.
Easy to confuse
top-level permissions block versus job-level permissions block. A top-level permissions block applies to all jobs and sets every unlisted scope to none regardless of the repository default; a job-level block restricts only that job and leaves other jobs, including ones added later, on the default. Use the top-level block to enforce least privilege across the whole workflow reliably.
OpenID Connect federation versus a stored long-lived cloud secret. OpenID Connect exchanges a short-lived token the cloud validates against a trust policy keyed on the token's subject and audience, so no static credential lives in GitHub; a stored cloud secret is a long-lived key that must be rotated and can leak. Choose OpenID Connect to remove the long-lived secret entirely, not merely to hide it.
pinning an action to a tag versus a full commit SHA. A tag such as v3 is mutable and can be repointed to malicious code under you; a full commit SHA is immutable and always resolves to the exact reviewed code. Pin third-party actions to a full commit SHA so a moved tag cannot silently change what runs.
restore-keys cache fallback versus fail-fast or lookup-only. restore-keys lists key prefixes so an exact-key miss restores the newest prefix-matching cache as a warm start; fail-fast governs matrix job cancellation and lookup-only only checks for a cache without restoring it. Add restore-keys when a near miss should reuse most dependencies instead of starting empty.
Worked example from the GH-200 bank
lock_openFree sampleSecure and optimize automationhard
A workflow only needs to clone the repository and post a status check, but its automatic GITHUB_TOKEN currently has broad write access because the repository default grants read and write to all scopes. The maintainer wants the token to carry only contents read and checks write for every job, with no other scope writable. Which change to the workflow file applies that least-privilege posture most reliably?
name: ci
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
AAdd a job-level permissions block to the build job granting contents: read and checks: write, and trust that listing two scopes leaves the repository default untouched for any other job added later.
BAdd a top-level permissions block with contents: read and checks: write, because declaring any permissions key resets every unlisted scope to none for all jobs unless a job overrides it.check_circle Correct
CAdd a top-level permissions block listing contents: read and checks: write, expecting the remaining scopes to keep the repository default of write so existing steps that push tags continue to function.
DChange the repository Settings to read-only token permissions and add no permissions key, because the read-only default alone supplies contents read and checks write while denying every other write scope.
Use a top-level permissions block to restrict GITHUB_TOKEN, knowing any declared scope sets all unlisted scopes to none for every job. When a workflow declares a permissions key at the top level, GitHub applies it to all jobs and sets every scope that is not listed to none, regardless of the repository default. Listing contents: read and checks: write therefore yields exactly those grants and nothing else across the whole workflow. A job-level block would leave future jobs on the default, the read-only default cannot grant checks write, and unlisted scopes are not preserved at their default once any permission is declared.
Why A is wrong: Tempting because a job-level block does scope that job correctly, but it governs only the build job, so any future job without its own block still inherits the broad repository default rather than the restricted set.
Why B is correct: A top-level permissions block applies to every job, and once any scope is declared GitHub sets all unlisted scopes to none, so the token carries only contents read and checks write across the whole workflow.
Why C is wrong: Tempting because it fears breaking other steps, but declaring permissions sets unlisted scopes to none rather than preserving the default, so this misreads the behaviour and would not deliver least privilege.
Why D is wrong: Tempting because the read-only default is restrictive, but it grants read everywhere and write nowhere, so checks write would be missing and the workflow could not post its status check.
A study plan that works
Map the reweighted blueprint and book a date
Day 1
Read the current GH-200 objectives, noting the January 2026 reweighting so older notes do not mislead you. Author and manage workflows and Manage GitHub Actions for the enterprise are the two heaviest domains and account for roughly half the marks between them, so plan the deepest study there. Book a provisional date now: a fixed date turns open-ended study into a plan and is the strongest predictor of actually sitting.
Build the core decision trees
Week 1
Before drilling any domain, build the splits the whole exam rests on: the trigger tree (schedule, workflow_dispatch, repository_dispatch, push, pull_request), the data-passing split (GITHUB_ENV, GITHUB_OUTPUT, artifacts, on.workflow_call.outputs), the reuse split (reusable workflow, composite action, starter workflow), and the action-type tree (composite, JavaScript, Docker). Use the recall prompts in this guide: cover the answer, choose the mechanism from the constraint, then reveal. If you cannot pick from the requirement alone, you do not own it yet.
Go deep on authoring and enterprise management (Domains 1 and 4)
Weeks 1 to 3
These two carry the most marks, so they get the most time. Drill workflow structure with needs and if, matrix expansion with include and exclude and fail-fast, and the workflow_call contract for inputs, secrets and outputs. For enterprise, fix the runner targeting array rule, the secret-scoping ladder, runner groups, and limits such as the four-level reusable workflow nesting depth. Practise on scenario questions and read the worked explanation on every one, including the ones you got right, watching for the named constraint that picks the answer.
Drill consuming, troubleshooting and action authoring (Domains 2 and 3)
Weeks 3 to 4
Practise inferring a trigger from run-history evidence and reading a failed step's exit-code line to trace the real cause. Fix artifact retention behaviour, the disable-versus-delete contrast, and matrix re-runs. For action authoring, lock the action-type decision tree, action.yml inputs, outputs and defaults, GITHUB_OUTPUT for step outputs, and tag-based versioning. Do the composite-versus-reusable-workflow and JavaScript-versus-Docker calls by hand until the constraint alone decides them.
Cover security and optimisation and its traps (Domain 5)
Week 4
This domain is smaller but its thread runs through every other domain. Drill the top-level permissions block and least-privilege GITHUB_TOKEN scoping, OpenID Connect federation to remove long-lived cloud secrets, pinning third-party actions to a full commit SHA, and environment protections including the wait timer and required reviewers. For cost, fix restore-keys cache warming, retention-days clamping, and concurrency. Practise rejecting the option that works but grants too much access.
Drill weak domains, then space the review
Week 5
Use your per-domain accuracy to attack the two domains dragging you down, not to re-read what you already know. Then space it: revisit each domain's recall prompts after a few days and again a week later. Spacing roughly doubles what sticks compared with cramming, and it is the cheapest gain available before the exam.
Sit a timed mock and calibrate
Weeks 5 to 6
Take at least one full timed mock under exam conditions to rehearse pacing and the flag-and-return habit across the whole question set in the time allowed. Treat the score as a per-domain readiness signal, not a single number, and review every missed question, naming the constraint you misread and re-reading the relevant YAML key, before you book or sit.
Know when you're ready
Readiness for the GitHub Actions certification is a measured score on scenario questions you have not seen before, not a feeling that the syntax is familiar. Those are different things, and the gap between them is where people fail. Re-reading the documentation builds fluency, and fluency feels like knowledge, so confidence rises while real recall does not. The fix is to test yourself: if you can read a fresh scenario, name the constraint, and pick the right trigger, structure, scope or control while explaining why each other option is wrong, you know it; if you can only nod along to an explanation, you do not yet.
Be especially wary of early confidence on the feature list. Knowing what schedule, a reusable workflow, GITHUB_OUTPUT and the GITHUB_TOKEN each do is the easy half; choosing between two plausible mechanisms under a constraint of least overhead, correct scope or least privilege is the half the exam actually tests. Trust your measured per-domain accuracy over your gut, and set the bar at clearing every domain comfortably on unseen questions across more than one session, not scraping a single pass.
This guide gives you the map. The practice bank is where you find out whether you can navigate it, with a worked explanation and a reason every distractor is wrong on every question. Readiness scoring tells you when you are there. Not before.
Ready to put this into practice?
Free GH-200 questions with worked explanations. No sign-up.
Read the scenario for its constraint first. The need named in the question - recurring with no commit, one central definition, a value that survives between steps, a token scoped to least privilege - is what picks the answer, so find it before you judge the options.
Treat broad GITHUB_TOKEN permissions as a wrong answer. When a job needs only a scope or two, a top-level permissions block that sets every unlisted scope to none is almost always the fit; an option leaving the default read-write or scoping only one job is the trap.
Reach for OpenID Connect whenever cloud credentials are needed without a stored secret. If an option proposes a long-lived cloud key in a GitHub secret and another proposes OIDC federation, the federation answer is the secure one the exam wants.
Pin third-party actions to a full commit SHA, not a tag. Any option pinning to a mutable tag like v3 for a third-party action is the weaker, exploitable choice even though it works.
Let the data-passing requirement pick the mechanism. Same-job environment variable means GITHUB_ENV, a named step output means GITHUB_OUTPUT, files across jobs means artifacts, and a value back to a reusable workflow's caller means on.workflow_call.outputs read via needs.
Distinguish reusable workflow from starter workflow whenever sharing is involved. One central definition that a fix propagates from is a reusable workflow; a copied editable template is a starter workflow. The word centrally or the phrase fix reaches every consumer points to reusable.
Flag and move on. Cover every question once before you spend time on a hard one; collecting the clear marks first protects the ones you actually know within the time limit.
Frequently asked questions
Is the GitHub Actions certification (GH-200) hard?
It is an associate-level exam, and the difficulty is judgement rather than recall. Most questions are scenarios where several GitHub Actions mechanisms could work and only one fits the stated constraint of least overhead, correct scope or least privilege. Scenario practice with worked explanations matters far more than memorising every YAML key, though you must read workflow files fluently.
How long should I study for GH-200?
Most candidates with genuine hands-on GitHub Actions experience are ready in five to six weeks of steady study. Less day-to-day exposure means more time on the two heavy domains, authoring and managing workflows and managing Actions for the enterprise, and on the trigger, reuse and data-passing decisions the whole exam rests on.
Did the January 2026 update change what I should study?
Yes. The objectives were added, removed, moved and reworded and the domains were reweighted, so study notes written before 2026 can point you at the wrong emphasis. Work from the current objectives: authoring and managing workflows is the largest domain, with managing Actions for the enterprise close behind.
Do I need to write code or author actions for this exam?
You need to read and reason about workflow YAML, contexts and expressions, and the structure of composite, JavaScript and Docker actions, but the exam is about choosing and configuring the right mechanism, not writing production code. Comfort with the action types, the action.yml metadata, and the secrets and permissions model is what carries you.
Which domains should I focus on?
Author and manage workflows is the heaviest domain and managing GitHub Actions for the enterprise is close behind, so together they deserve the most time. Consuming and troubleshooting workflows and authoring and maintaining actions are mid-weight, and securing and optimising automation is smaller but its security thread runs through every other domain, so do not skip it.
How should I think about the GITHUB_TOKEN and OpenID Connect questions?
Default to least privilege. When a job needs only a scope or two, a top-level permissions block that sets every unlisted scope to none is the reliable answer. When the job needs cloud credentials, OpenID Connect federation that exchanges a short-lived token a cloud trust policy validates removes the long-lived secret entirely, and any option storing a long-lived cloud key is the trap.
What is the difference between a reusable workflow, a composite action and a starter workflow?
A reusable workflow is one central definition referenced with uses at job level, so a fix there reaches every caller; a composite action bundles shell run steps into one unit referenced as a step inside a job; a starter workflow seeds a copy of YAML into each repository, so later template fixes never reach existing copies. Choose reusable for central governance, composite for step-level packaging, and starter only to bootstrap an editable file.
How many practice questions should I do before booking?
Enough that every domain clears comfortably on questions you have not seen, and a full timed mock feels comfortable on pacing. Quality of review beats raw volume: on every question, read the explanation and name the constraint that picked the answer, including on the ones you got right.
Is the GitHub Actions certification (GH-200) worth it for DevOps and platform engineers?
It is a practical credential for engineers who already build and operate CI/CD automation on GitHub and want to demonstrate they can make the right architectural choices, not just write YAML that runs. The exam rewards judgement over syntax recall, so the preparation tends to sharpen how practitioners reason about triggers, reuse patterns, and the security posture of their workflows rather than just confirming what they already do. A natural complement is the GH-500 GitHub Advanced Security certification, which covers the security layer that sits above a well-structured Actions setup.
Examworthy is not affiliated with or endorsed by GitHub. This guide is original study material based on the public exam blueprint. We never reproduce live exam items. GH-200 and related marks belong to their respective owners.