On September 1, 2022, GitHub Learning Lab will shut down.
Read more on the GitHub blog and check out GitHub Skills for courses backed by GitHub Actions.

Building: The steps block

GitHub Learning Lab is no longer accepting new public courses from outside of GitHub.

GitHub Learning Lab's mascot A course on GitHub Learning Lab can guide you through this step.

Steps are the building blocks of your course, and they are defined in config.yml. Steps are triggered by events, and execute actions.

the course progress page with some completed steps

Options for steps

A step is composed of the following fields:

Field Required Description
title The title of the step. Appears in the the course page in Learning Lab, and is used for notifications on course progress.
description A longer description of the action expected in the step. Displayed below the step title, and used for notifications on course progress.
video A YouTube or Vimeo embed link, to include a video in the step. The video will appear in the progress tab after a user has registered for the course.
event An webhook event name from the GitHub API. Used to trigger the step.
link A link to a section in the repository, usually an issue or pull request. Used to help the learner locate where they're expected to interact for the existing step.
actions A list of actions that will execute when the step is triggered. The completion of all the actions in a step is required for the step to be marked complete.

Usage examples


  - title: Install your first GitHub Apps
    description: Learn what GitHub Apps are and how to install them
    event: issues.closed
    link: '{{ store.first_issue_url }}'
    - type: updateBranchProtection
    - type: createPullRequest
      title: Trigger the app
      head: add-to-list
      body: 02_trigger-wip.md
        first_pr_url: '{{ result.data.html_url }}'
    - type: respond
      with: 01_successful-close.md
        url: '{{ store.first_pr_url }}'

  - title: Trigger the WIP app
    description: Once installed, learn how to interact with the app
    event: "pull_request.edited"
    link: '{{ store.first_pr_url}}'
      - type: gate
        left: '{{ payload.pull_request.title }}'
        operator: search
        right: WIP
          - type: respond
            with: 02_WIP-error-message.md
      - type: mergeBranch
        head: finish-list
        base: add-to-list
      - type: respond
        with: 02_adding-smee.md
         repoUrl: '{{ store.first_pr_url }}'

Keeping data from actions persistent

In some cases, you might want to persist data across actions in a step, or even propagate data to responses. Consider the following scenario:

  1. Learner comments on issue #1, as instructed by Learning Lab.
  2. Learning Lab opens issue #2.
  3. Learning Lab closes issue #1.
  4. Learning Lab directs the user to issue #2 with a link.

To solve this problem, we'll use Learning Lab's course data store.

The following example shows how to get issue #2's URL to persist across the actions in this step, and to the response file, as follows:

title: Point users to a new issue and close this one
  - title: Comment on this issue
    event: issue_comment.created
      - type: createIssue
        title: New issue
        body: an-issue.md
        # Store the url for this new issue using the custom new_issue value
          new_issue_url: '{{ result.data.html_url }}'

        # Close the issue the user just commented on
      - type: closeIssue

        # Respond in the issue the user just commented on
      - type: respond
        with: a-response.md
        # Include a `data` object to provide some template variables
          # Reference the `new_issue` url value from the store
          nextIssueUrl: '{{ store.new_issue_url }}'

In this example, we store the html_url received in the API response from the createIssue action in the store:. We can replace new_issue_url with any identifier we desire. This allows us to later refer to that information by simply calling the value: '{{ store.new_issue_url }}'.

To pass it into the text of a response, we can include it in the data key as shown in the above example, and give it a variable name. We can then refer to it in a-response.md as follows:

Great! Move on to the next issue, which is found at: {{ nextIssueUrl }}

Sample configs

The best way to get familiar with YAML, actions, and payloads, is to start building your own course. If you'd like, you can explore more examples and use cases from our own courses like those above, and you can brush up on each action's documentation and syntax.