Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update course format for accessibility #29

Merged
merged 8 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions .github/script/update-step.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# chmod a+x .github/script/update-step.sh

echo "Check that we are on FROM_STEP"
if [ "$(cat .github/script/STEP)" != $FROM_STEP ]
if [ "$(cat .github/steps/-step.txt)" != $FROM_STEP ]
then
echo "Current step is not $FROM_STEP"
exit 0
Expand All @@ -12,23 +12,17 @@ fi
echo "Make sure we are on the main branch"
git checkout main

echo "Remove 'open' from any <details> tags"
sed -r 's/<details id=([0-9]+) open>/<details id=\1>/g' README.md > tmp
mv tmp README.md
echo "TODO NEEDS UPDATE"

echo "Add 'open' to step TO_STEP"
sed -r "s/<details id=$TO_STEP>/<details id=$TO_STEP open>/g" README.md > tmp
mv tmp README.md

echo "Update the STEP file to TO_STEP"
echo "$TO_STEP" > .github/script/STEP
echo "Update the step file to TO_STEP"
echo "$TO_STEP" > .github/steps/-step.txt

echo "Commit the files, and push to main"
git config user.name github-actions
git config user.email github-actions@github.com
git add README.md
git add .github/script/STEP
git commit --message="Update to $TO_STEP in STEP and README.md"
git add .github/steps/-step.txt
git commit --message="Update to $TO_STEPin step and README.md"
git push

echo "If BRANCH_NAME, update that branch as well"
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions .github/steps/0-welcome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- readme -->
85 changes: 85 additions & 0 deletions .github/steps/1-initialize-javascript-project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<!--
<<< Author notes: Step 1 >>>
Choose 3-5 steps for your course.
The first step is always the hardest, so pick something easy!
Link to docs.github.com for further explanations.
Encourage users to open new tabs for steps!
-->

## Step 1: Initialize a new JavaScript project

_Welcome to the course :tada:_

### Configuring a workflow

Actions are enabled on your repository by default, but we still have to tell our repository to use them. We do this by creating a workflow file in our repository.

A **workflow** file can be thought of as the recipe for automating a task. They house the start to finish instructions, in the form of `jobs` and `steps`, for what should happen based on specific triggers.

Your repository can contain multiple **workflow** files that carry out a wide variety of tasks. It is important to consider this when deciding on a name for your **workflow**. The name you choose should reflect the tasks being performed.

_In our case, we will use this one **workflow** file for many things, which leads us to break this convention for teaching purposes._

Read more about [workflows](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/configuring-a-workflow#choosing-the-type-of-actions-for-your-workflow)

## On to your development environment

Our JavaScript actions are going to leverage the [GitHub ToolKit](https://github.com/actions/toolkit) for developing GitHub Actions.

This is an external library that we will install using `npm` which means that you will need [Node.js](https://nodejs.org/) installed.

We find writing actions to be easier from a local environment vs trying to do everything right here in the repository. Doing these steps locally allows you to use the editor of your choice so that you have all the extensions and snippets you are used to when writing code.

If you do not have a preferred environment then we suggest following along exactly as you see on the screen, which means you'll need to install [Visual Studio Code](https://code.visualstudio.com/).

## Don't forget to set up your workstation

Most of your work going forward will take place away from your Skills repository, so before continuing with the course ensure you have the following installed on your **local machine**.

1. [ ] [Node.js](https://nodejs.org)
2. [ ] [Visual Studio Code](https://code.visualstudio.com/) or your editor of choice
3. [ ] [Git](https://git-scm.com/)

### :keyboard: Activity 1: Initialize a new JavaScript project

Once you have the necessary tools installed locally, follow these steps to begin creating your first action.

1. Open the **Terminal** (Mac and Linux) or **Command Prompt** (Windows) on your local machine
2. Clone your Skills repo to your local machine:
```shell
git clone <this repository URL>.git
```
3. Navigate to the folder you just cloned:
```shell
cd <local folder with cloned repo>
```
4. We are using branch called `main`.
```shell
git switch main
```
5. Create a new folder for our actions files:
```shell
mkdir -p .github/actions/joke-action
```
6. Navigate to the `joke-action` folder you just created:
```shell
cd .github/actions/joke-action
```
7. Initialize a new project:
```shell
npm init -y
```
8. Install the **request**, **request-promise** and **@actions/core** dependencies using `npm` from the [GitHub ToolKit] (https://github.com/actions/toolkit):
```shell
npm install --save request request-promise @actions/core
```
9. Commit those newly added files,we will remove the need to upload **node_modules** in a later step:
```shell
git add .
git commit -m 'add project dependencies'
```
10. Push your changes to your repository:
```shell
git push
```
11. Wait about 20 seconds then refresh this page (the one you're following instructions from). [GitHub Actions](https://docs.github.com/en/actions) will automatically update to the next step.
36 changes: 36 additions & 0 deletions .github/steps/2-configure-your-action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Step 2: Configure Your Action

_Let's keep going! :bike:_

### Excellent!

Now that we have the custom action pre-requisites, let us create **joke-action** action.

### :keyboard: Activity 1: Configure Your Action

All of the following steps take place inside of the `.github/actions/joke-action` directory.

We will start with using the parameters that are **required** and later implement some optional parameters as our action evolves.

1. Create a new file in: `.github/actions/joke-action/action.yml`
2. Add the following contents to the `.github/actions/joke-action/action.yml` file:

```yaml
name: "my joke action"

description: "use an external API to retrieve and display a joke"

runs:
using: "node16"
main: "main.js"
```

3. Save the `action.yml` file
4. Commit the changes and push them to the `main` branch:
```shell
git add action.yml
git commit -m 'create action.yml'
git pull
git push
```
5. Wait about 20 seconds then refresh this page (the one you're following instructions from). [GitHub Actions](https://docs.github.com/en/actions) will automatically update to the next step.
58 changes: 58 additions & 0 deletions .github/steps/3-create-metadata-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
## Step 3: Create the metadata file

_Nice work configuring your action :smile:_

## Action metadata

Every GitHub Action that we write needs to be accompanied by a metadata file. This file has a few rules to it, as are indicated below:

- Filename **must** be `action.yml`.
- Required for both Docker container and JavaScript actions.
- Written in YAML syntax.

This file defines the following information about your action:

| Parameter | Description | Required |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------: |
| Name | The name of your action. Helps visually identify the actions in a job. | :white_check_mark: |
| Description | A summary of what your action does. | :white_check_mark: |
| Inputs | Input parameters allow you to specify data that the action expects to use during runtime. These parameters become environment variables in the runner. | :x: |
| Outputs | Specifies the data that subsequent actions can use later in the workflow after the action that defines these outputs has run. | :x: |
| Runs | The command to run when the action executes. | :white_check_mark: |
| Branding | You can use a color and Feather icon to create a badge to personalize and distinguish your action in GitHub Marketplace. | :x: |

---

Read more about [Action metadata](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/metadata-syntax-for-github-actions)

### :keyboard: Activity 1: Create the metadata file

All of the following steps take place inside of the `.github/actions/joke-action` directory.

Our action does not require much metadata for it to run correctly. We will not be accepting any inputs, we will however be setting a single output this time.

1. Update the action metadata file `.github/actions/joke-action/action.yml` with the following content:

```yaml
name: "my joke action"

description: "use an external API to retrieve and display a joke"

outputs:
joke-output:
description: The resulting joke from the icanhazdadjokes API

runs:
using: "node16"
main: "main.js"
```

2. Save the `action.yml` file
3. Commit the changes and push them to GitHub:
```shell
git add action.yml
git commit -m 'add metadata for the joke action'
git pull
git push
```
4. Wait about 20 seconds then refresh this page (the one you're following instructions from). [GitHub Actions](https://docs.github.com/en/actions) will automatically update to the next step.
157 changes: 157 additions & 0 deletions .github/steps/4-create-javascript-files-for-action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
## Step 4: Create the JavaScript files for your action

_Good job adding the metadata file! :dancer:_

## Files

As you probably know, in JavaScript and other programming languages it is common to break your code into modules so that it is easier to read and maintain going forward. Since JavaScript actions are just programs written in JavaScript that run based on a specific trigger we are able to make our action code modular as well.

To do so we will create two files. One of them will contain the logic to reach out to an external API and retrieve a joke for us, the other will call that module and print the joke to the actions console for us. We will be extending this functionality in our third and final action.

### Fetching a joke

**Joke API**

The first file will be `joke.js` and it will fetch our joke for us. We will be using the [icanhazdadjoke API](https://icanhazdadjoke.com/api) for our action. This API does not require any authentication, but it does however that we set a few parameters in the [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). We need to point out what those are when we get to the code, however it is outside of the scope of this course to cover HTTP in any depth.

When we make our request to this API we will get back a JSON Object in the response. That Object looks like this:

```
{
id: '0LuXvkq4Muc',
joke: "I knew I shouldn't steal a mixer from work, but it was a whisk I was willing to take.",
status: 200
}
```

It contains 3 key/value pairs of data that we can use in our own program or service. In our case, we are only interested in the `joke` field.

**Joke Module**

We will create a file named `joke.js` and it will reside in the `.github/action/joke-action` directory.

The joke module will look like this:

```javascript
const request = require("request-promise");

const options = {
method: "GET",
uri: "https://icanhazdadjoke.com/",
headers: {
Accept: "application/json",
"User-Agent": "Writing JavaScript action GitHub Skills course.",
},
json: true,
};

async function getJoke() {
const res = await request(options);
return res.joke;
}

module.exports = getJoke;
```

Need an advanced description of the <code>joke.js</code> source code?

We first bring in the `request-promise` library that we installed earlier using `npm`.

Next we define a set of `options` that the `request-promise` library will use when it makes the request.

Read more about [request-promise](https://github.com/request/request-promise/)

Inside of the `options` block we add a key named `headers`. This defines the HTTP headers that the **icanhazdadjoke** API expects in each request that comes it's way.

**icanhazdadjoke** cares the most about the keys, **Accept** and **User-Agent**, so we need to make sure we fill them in.

Next we define an **asynchronous JavaScript function** to make the request for us, storing the JSON Object that is returned in a variable named `res`.

Lastly, we `return` the `res.joke` which is only the value associated with the `joke` key of the JSON Object. This value will be random every time our action runs because of how we are interacting with the **icanhazdadjoke** API.

This file finishes up by exporting the newly created function so that we can use it in our `main.js` file.

### Creating the main entry point for your action

**Main Module**

We will also create a file named `main.js` that resides inside of the `.github/actions/joke-action` directory.

That file will look like this:

```javascript
const getJoke = require("./joke");
const core = require("@actions/core");

async function run() {
const joke = await getJoke();
console.log(joke);
core.setOutput("joke-output", joke);
}

run();
```

Need an advanced description of the <code>main.js</code> source code?

Like we did in the `joke.js` file, we are first going to bring in our dependencies. Only this time, our dependencies include something we wrote! To do that we simply use `require()` to point to the location of the file we wish to bring in.

We also bring in `@actions/core` so that we can set the output of our action.

Next we write another **asynchronous JavaScript function** that stores the return value of `getJoke()` in a variable called **joke**.

Then we log the joke to the console.

Finally we finish the function with by setting the contents of the joke as the value of the `joke-output` output parameter. We will use this output later in the course.
_Don't forget to call the `run()` function._

### :keyboard: Activity 1: Creating the JavaScript files for your new action.

1. Create and add the following contents to the `.github/actions/joke-action/joke.js` file:

```javascript
const request = require("request-promise");

const options = {
method: "GET",
uri: "https://icanhazdadjoke.com/",
headers: {
Accept: "application/json",
"User-Agent": "Writing JavaScript action GitHub Skills course.",
},
json: true,
};

async function getJoke() {
const res = await request(options);
return res.joke;
}

module.exports = getJoke;
```

2. Save the `joke.js` file.
3. Create and add the following contents to the `.github/actions/joke-action/main.js` file:

```javascript
const getJoke = require("./joke");
const core = require("@actions/core");

async function run() {
const joke = await getJoke();
console.log(joke);
core.setOutput("joke-output", joke);
}

run();
```

4. Save the `main.js` file.
5. Commit the changes to this branch and push them to GitHub:
```shell
git add joke.js main.js
git commit -m 'creating joke.js and main.js'
git pull
git push
```
6. Wait about 20 seconds then refresh this page (the one you're following instructions from). [GitHub Actions](https://docs.github.com/en/actions) will automatically update to the next step.
Loading