Try each one before opening the answer. Every option is explained, with the GitHub documentation page that proves it.
Question 1 · choose 1
A step base64-encodes the SIGNING_KEY secret to pass it to a tool. A reviewer finds the encoded value in plain text in the run log, while the original secret shows as asterisks. The encoded value must be hidden in every later step too. What should the step do?
AWrite the encoded value to GITHUB_ENV, whose values are redacted in logs
BRegister the encoded value with ::add-mask:: before using it
CStore the encoded form as a second repository secret in advance
DTurn off step debug logging for the repository
Show the answer and why
AWrite the encoded value to GITHUB_ENV, whose values are redacted in logs
Incorrect
Environment file values aren't redacted; the encoded string would still appear wherever it is printed.
BRegister the encoded value with ::add-mask:: before using it
Correct
Masking the transformed value makes the runner redact it in the rest of the job's log output.
CStore the encoded form as a second repository secret in advance
Incorrect
A secret is redacted only when the job uses it, and this job never references the second secret.
DTurn off step debug logging for the repository
Incorrect
The value is printed in the normal log, so debug logging isn't the cause.
Redaction relies largely on finding an exact match for a secret's value, so a transformed secret, such as a Base64 or URL-encoded copy, isn't redacted automatically. GitHub's guidance is to register any value generated from a secret, including encodings, with the add-mask workflow command.
A team copies a working Ubuntu job that uses a redis service container to a new job with runs-on: windows-latest, to test the Windows build against redis. The Windows job fails while setting up the service. What is the cause?
AThe redis image needs credentials to be pulled on Windows
BWindows jobs must map service ports with the udp suffix
CService containers need a Linux runner
DThe service label must match the image name on Windows runners
Show the answer and why
AThe redis image needs credentials to be pulled on Windows
Incorrect
Credentials depend on the registry, not the runner's operating system.
BWindows jobs must map service ports with the udp suffix
Incorrect
The protocol suffix is optional and isn't tied to the operating system.
CService containers need a Linux runner
Correct
GitHub-hosted service containers and container jobs require a Linux runner with Docker.
DThe service label must match the image name on Windows runners
Incorrect
The label is any name you choose, on any runner.
Service containers and container jobs require a Linux environment: on GitHub-hosted runners that means an Ubuntu runner, and on self-hosted runners a Linux machine with Docker installed. A Windows test can reach a service that runs elsewhere, but not a service container in the job.
In a monorepo, a detect job writes the changed package names to its output packages as a JSON array, such as ["api","web"]. A test job must run once per changed package, and the list differs on every push. How should the test job define its matrix?
Apackage: ${{ needs.detect.outputs.packages }}
Bpackage: ${{ steps.detect.outputs.packages }}, reading the step that wrote the list
fromJSON turns the job output into an array, so one job runs for each package.
Dpackage: ${{ env.PACKAGES }}, after detect writes the list to GITHUB_ENV
Incorrect
Environment file values stay in the job that wrote them, and env isn't available in strategy.
A matrix can be built at run time from a previous job's output. Job outputs are strings, so the value is passed through fromJSON to become an array or object. The strategy key can use only the github, needs, vars and inputs contexts, which is why the list has to come through needs.
A compatibility workflow builds a matrix of 3 operating systems, 10 runtime versions and 9 regions, 270 combinations in one job. What happens when it runs?
AThe matrix exceeds the limit of 256 jobs per workflow run
BAll 270 jobs run, but only 20 at a time on a Free plan
CThe matrix runs if max-parallel is set below 256
DThe jobs run on self-hosted runners, where the limit doesn't apply
Show the answer and why
AThe matrix exceeds the limit of 256 jobs per workflow run
Correct
A job matrix can generate at most 256 jobs per run, on any kind of runner.
BAll 270 jobs run, but only 20 at a time on a Free plan
Incorrect
Concurrency limits queue jobs, but this matrix is larger than any run may generate.
CThe matrix runs if max-parallel is set below 256
Incorrect
max-parallel limits how many jobs run at once, not how many the matrix generates.
DThe jobs run on self-hosted runners, where the limit doesn't apply
Incorrect
The matrix limit applies to both GitHub-hosted and self-hosted runners.
A job matrix can generate a maximum of 256 jobs per workflow run, and the limit applies to GitHub-hosted and self-hosted runners alike. Larger test sets must be split, for example into several matrix jobs or workflows.
Platform engineers want to move every job of a workflow to a different runner label without editing the file, by changing one value in the repository settings. A first attempt, runs-on: ${{ env.RUNNER_LABEL }} with RUNNER_LABEL in the workflow's env, fails validation. What should runs-on use?
A${{ vars.RUNNER_LABEL }}, a repository configuration variable
B${{ secrets.RUNNER_LABEL }}, a repository secret
C${{ env.RUNNER_LABEL }} with the variable set in the job's env instead
D${{ steps.pick.outputs.label }} from a first step that reads the settings
Show the answer and why
A${{ vars.RUNNER_LABEL }}, a repository configuration variable
Correct
runs-on can use the vars context, and the value is changed in the repository settings.
B${{ secrets.RUNNER_LABEL }}, a repository secret
Incorrect
The secrets context isn't available in runs-on.
C${{ env.RUNNER_LABEL }} with the variable set in the job's env instead
Incorrect
The env context isn't available in runs-on at any level.
D${{ steps.pick.outputs.label }} from a first step that reads the settings
Incorrect
Steps run after the runner is chosen, and the steps context isn't available in runs-on.
jobs.<job_id>.runs-on can use the github, needs, strategy, matrix, vars and inputs contexts. Configuration variables are read through vars, so changing the repository variable in settings moves the jobs without editing the workflow.
Every run step in a job starts with cd frontend. How can the job set that directory once for all of its run steps?
Aenv: { PWD: frontend } on the job
Bdefaults: run: working-directory: frontend on the job
CA first step that runs cd frontend
DA with: working-directory input on actions/checkout for each job
Show the answer and why
Aenv: { PWD: frontend } on the job
Incorrect
Setting a PWD variable doesn't change the directory a shell starts in.
Bdefaults: run: working-directory: frontend on the job
Correct
Job-level defaults apply the working directory to every run step in the job.
CA first step that runs cd frontend
Incorrect
Each run step starts a new shell, so a cd doesn't carry over.
DA with: working-directory input on actions/checkout for each job
Incorrect
That input doesn't exist on checkout, and it wouldn't affect run steps.
defaults.run sets the default shell and working-directory for all run steps, at the workflow level or for a single job. Each run step starts its own shell, so changing directory in one step doesn't affect the next.
A build script prints hundreds of dependency lines that clutter the run log. The team wants them folded under one expandable heading. Which workflow commands should the script print around them?
A::stop-commands:: with a token before the lines
B::notice:: on each line
C::group::Dependencies and ::endgroup::
D::add-mask:: on each line
Show the answer and why
A::stop-commands:: with a token before the lines
Incorrect
That stops processing of workflow commands; it doesn't fold lines.
B::notice:: on each line
Incorrect
Every line would become an annotation, adding clutter.
C::group::Dependencies and ::endgroup::
Correct
Lines between these commands fold into one expandable group in the log.
D::add-mask:: on each line
Incorrect
Masking hides values as asterisks; the lines would still fill the log.
The group and endgroup workflow commands create an expandable group in the log. stop-commands pauses command processing, notice creates annotations, and add-mask redacts values.
A step installs a CLI into $HOME/tools/bin. Later steps in the job must be able to call it by name. What should the installing step do?
Aexport PATH="$HOME/tools/bin:$PATH"
BWrite PATH_EXTRA=$HOME/tools/bin to GITHUB_OUTPUT
CAppend $HOME/tools/bin to the GITHUB_PATH file
DSet PATH in the workflow's top-level env
Show the answer and why
Aexport PATH="$HOME/tools/bin:$PATH"
Incorrect
An export lasts only for that step's shell.
BWrite PATH_EXTRA=$HOME/tools/bin to GITHUB_OUTPUT
Incorrect
An output is read through the steps context; it doesn't change PATH.
CAppend $HOME/tools/bin to the GITHUB_PATH file
Correct
Paths added there are prepended to PATH for all later steps in the job.
DSet PATH in the workflow's top-level env
Incorrect
A fixed value there would replace the runner's PATH instead of adding to it.
Writing a directory to the GITHUB_PATH environment file prepends it to the system PATH for all subsequent steps and actions in the current job; the step that writes it doesn't see the change.
startsWith works on strings, not on an array of label objects.
Dgithub.event.label.name == 'deploy-preview' on every pull request event
Incorrect
That property is set only for labeled events and names the one label just added.
The * object filter selects a property from each item in a collection, so labels.*.name returns an array of label names. contains() returns true if an array includes the item. The label property of the payload exists only for labeled and unlabeled activity.