Skip to content

GH-200 · Domain 3: Author and maintain actions · 19% of the exam

Task 3.1: Create and troubleshoot custom actions

JavaScript, Docker container and composite actions, which runners each supports, and diagnosing actions that fail to load, start or report their results.

Study it

Sample questions

Try each one before opening the answer. Every option is explained, with the GitHub documentation page that proves it.

Question 1 · choose 1

A team is building an action that calls the GitHub API and parses JSON. Its users run jobs on Linux, Windows and macOS GitHub-hosted runners. The action must start quickly and must not depend on command-line tools that differ between runner images. Which kind of action should the team build?

  1. AA Docker container action with the tools baked into its image
  2. BA composite action that chains bash, jq and curl steps
  3. CA JavaScript action written in pure JavaScript
  4. DA reusable workflow with one job for each operating system the users run
Show the answer and why
  • AA Docker container action with the tools baked into its image

    Incorrect

    The image would fix the tools, but this type of action can't run on every runner operating system the users have.

  • BA composite action that chains bash, jq and curl steps

    Incorrect

    Those steps depend on tools and shells that vary between runner images.

  • CA JavaScript action written in pure JavaScript

    Correct

    Pure JavaScript runs on all GitHub-hosted runners, starts faster than a container and needs no extra binaries.

  • DA reusable workflow with one job for each operating system the users run

    Incorrect

    A reusable workflow isn't an action that users add as a step.

JavaScript actions run directly on the runner. To stay compatible with the Ubuntu, Windows and macOS GitHub-hosted runners, the packaged code should be pure JavaScript that doesn't rely on other binaries. A container action can't serve every operating system, and composite actions run whatever tools their steps call.

Question 2 · choose 1

A new Docker container action fails at start with "exec: "/entrypoint.sh": permission denied". The Dockerfile copies entrypoint.sh and uses it as ENTRYPOINT. The author works on Windows. What should the author do?

  1. AChange the base image to alpine
  2. BRename the file to entrypoint.bash
  3. CMove entrypoint.sh under /github/workspace
  4. DMark the file executable in Git with git update-index --chmod=+x entrypoint.sh
Show the answer and why
  • AChange the base image to alpine

    Incorrect

    The base image doesn't make a copied file executable; the file's mode does.

  • BRename the file to entrypoint.bash

    Incorrect

    The name doesn't make a file executable.

  • CMove entrypoint.sh under /github/workspace

    Incorrect

    The workspace is mounted over that path, and the mode would still be wrong.

  • DMark the file executable in Git with git update-index --chmod=+x entrypoint.sh

    Correct

    The script must be executable, and setting the mode in Git keeps it on every clone.

The code a Docker action's ENTRYPOINT runs must be executable; otherwise the container fails with a permission denied error. GitHub's tutorial sets the mode in Git with git update-index --chmod=+x so it isn't reset on clone.

Question 3 · choose 1

A JavaScript action starts a local proxy in main and stops it in a post script. When a job fails, the team wants the proxy left running so that a debugging step can inspect it, but after a successful job it must be stopped. What should action.yml set?

  1. ANothing; post scripts already run only after successful jobs
  2. Bpost-if: success() next to post
  3. Cpre-if: failure() so that the proxy starts only when needed
  4. Dpost-if: failure() next to post
Show the answer and why
  • ANothing; post scripts already run only after successful jobs

    Incorrect

    post runs by default whatever the outcome, since post-if defaults to always().

  • Bpost-if: success() next to post

    Correct

    Status functions in post-if check the job's status, so cleanup runs only after a successful job.

  • Cpre-if: failure() so that the proxy starts only when needed

    Incorrect

    pre-if controls the pre script, not the cleanup.

  • Dpost-if: failure() next to post

    Incorrect

    That would stop the proxy after failures only, the opposite of what's wanted.

JavaScript actions can declare pre and post scripts. post runs at the end of the job by default, because post-if defaults to always(). In post-if, status check functions evaluate the job's status, not the action's own status, so post-if: success() limits cleanup to successful jobs.

Question 4 · choose 2

A team maintains a JavaScript action and a composite action that both take an input named region. Which two statements about reading that input are true? (Choose TWO.)

  1. AThe JavaScript action can read it with core.getInput('region')
  2. BThe composite action's steps get INPUT_REGION set automatically
  3. CThe composite action's steps can read it as ${{ inputs.region }}
  4. DInput names are case-sensitive: Region and region become separate environment variables
  5. EThe JavaScript action must declare the input under runs
Show the answer and why
  • AThe JavaScript action can read it with core.getInput('region')

    Correct

    The toolkit reads the INPUT_REGION variable that GitHub creates.

  • BThe composite action's steps get INPUT_REGION set automatically

    Incorrect

    Composite actions don't automatically get INPUT_ variables.

  • CThe composite action's steps can read it as ${{ inputs.region }}

    Correct

    Composite actions access their inputs through the inputs context.

  • DInput names are case-sensitive: Region and region become separate environment variables

    Incorrect

    The variable name is converted to uppercase, so both map to INPUT_REGION.

  • EThe JavaScript action must declare the input under runs

    Incorrect

    Inputs are declared under inputs at the top of the metadata file.

For JavaScript and Docker container actions, GitHub creates an INPUT_<NAME> environment variable for each input, with the name uppercased; the toolkit's getInput reads it. Composite actions don't get these variables automatically and read inputs through the inputs context.

Question 5 · choose 1

Where does GitHub publish the Node.js packages, such as @actions/core, for building JavaScript actions?

  1. AThe actions/runner repository
  2. BThe actions/starter-workflows repository
  3. CThe actions/toolkit repository
  4. DThe actions/runner-images repository
Show the answer and why
  • AThe actions/runner repository

    Incorrect

    That repository holds the runner application.

  • BThe actions/starter-workflows repository

    Incorrect

    That repository holds GitHub's workflow templates.

  • CThe actions/toolkit repository

    Correct

    The actions toolkit is a set of Node.js packages for building actions.

  • DThe actions/runner-images repository

    Incorrect

    That repository holds the GitHub-hosted runner images.

The GitHub Actions Toolkit provides Node.js packages that speed up building JavaScript actions; its source and documentation are in the actions/toolkit repository.

Question 6 · choose 1

A developer writing a JavaScript action wants functions to read inputs, set outputs, log debug messages and set a failing exit status. Which package provides them?

  1. A@actions/cache
  2. B@actions/core
  3. C@actions/artifact
  4. D@actions/glob
Show the answer and why
  • A@actions/cache

    Incorrect

    That package saves and restores caches.

  • B@actions/core

    Correct

    It wraps workflow commands, inputs, outputs, exit status and debug messages.

  • C@actions/artifact

    Incorrect

    That package uploads and downloads artifacts.

  • D@actions/glob

    Incorrect

    That package matches file patterns.

The actions toolkit's @actions/core package provides an interface to the workflow commands, input and output variables, exit statuses and debug messages. @actions/github returns an authenticated Octokit client and the workflow contexts.

Question 7 · choose 1

A Docker container action builds a project inside its container. The next workflow step must upload the build output as an artifact. Where should the action write the output?

  1. ATo /tmp inside the container
  2. BTo /github/workspace inside the container
  3. CTo the container's home directory
  4. DTo a Docker volume that the action creates itself
Show the answer and why
  • ATo /tmp inside the container

    Incorrect

    That directory disappears with the container.

  • BTo /github/workspace inside the container

    Correct

    That path is mapped to the runner's workspace, so later steps can use the files.

  • CTo the container's home directory

    Incorrect

    Later steps don't see the container's own file system.

  • DTo a Docker volume that the action creates itself

    Incorrect

    Later steps don't mount volumes the action creates.

When a container action runs, GitHub maps the runner's default working directory, GITHUB_WORKSPACE, to /github/workspace in the container. Files added there are available to subsequent steps in the same job, such as an artifact upload.

Question 8 · choose 1

A Docker container action's Dockerfile starts with FROM node:latest. A reviewer asks the author to follow GitHub's Dockerfile guidance for actions. Which first line should the Dockerfile have?

  1. AFROM node:22, an official image with a major version tag
  2. BFROM node:latest, kept so that the action always gets the newest Node.js
  3. CNo FROM line, with the base image named in action.yml instead
  4. DFROM node:22-alpine, because Alpine-based images are recommended for actions
Show the answer and why
  • AFROM node:22, an official image with a major version tag

    Correct

    GitHub recommends official images and a version tag, preferably a major version, instead of latest.

  • BFROM node:latest, kept so that the action always gets the newest Node.js

    Incorrect

    GitHub's guidance is to use a version tag, for example node:10 instead of node:latest.

  • CNo FROM line, with the base image named in action.yml instead

    Incorrect

    The first instruction in the Dockerfile must be FROM, which selects the base image.

  • DFROM node:22-alpine, because Alpine-based images are recommended for actions

    Incorrect

    GitHub recommends Docker images based on the Debian operating system.

The first instruction in a Docker container action's Dockerfile must be FROM. GitHub's best practices for it are to use official Docker images, such as python or ruby, to use a version tag if one exists, preferably with a major version (node:10 rather than node:latest), and to use images based on the Debian operating system.

Practice domain 3 →Practice all domains →