esmailbenmoussa / writing-javascript-actions

https://lab.github.com/githubtraining/github-actions:-writing-javascript-actions
MIT License
0 stars 0 forks source link

External APIs #6

Closed esmailbenmoussa closed 3 years ago

github-learning-lab[bot] commented 3 years ago

esmailbenmoussa you're doing great 👍

Just like the first action you wrote, you are going to need to setup a few directories and files.

:keyboard: Activity: Configure your second action

Now that you have all the necessary tools installed locally, follow these steps to ensure your environment is configured and ready for actions.

  1. Open the Terminal (Mac and Linux) or Command Prompt (Windows) on your local machine
  2. Navigate to the .github/ directory.
  3. Checkout the main branch
    git checkout main
  4. Update the contents of your Learning Lab repo to your local machine:
    git pull
  5. Checkout the action-two branch you created for this pull request.
    git checkout action-two
  6. Create a new folder for our actions files. The full path should be .github/actions/joke-action.
    mkdir actions/joke-action
  7. Navigate to the joke-action folder you just created:
    cd actions/joke-action
  8. Initialize a new project:
    npm init -y
  9. Install the request, request-promise and @actions/core dependencies using npm:
    npm install --save request request-promise @actions/core
  10. Commit those newly added files. We will remove the need to upload node_modules in a later step. Push your changes to GitHub:
    git add .
    git commit -m 'add joke action dependencies'
    git push

I will respond once you push a new commit to the action-two branch.

github-learning-lab[bot] commented 3 years ago

:keyboard: Activity: 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.

We will not use the joke-output in in this portion of the course. There will be a later step that will rely on this actions output.

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

    name: "external API 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: "node12"
     main: "main.js"
  2. Save the action.yml file
  3. Commit the changes and push them to GitHub:
    git add action.yml
    git commit -m 'add metadata for the joke action'
    git push

I'll respond when you push to this branch.

github-learning-lab[bot] commented 3 years ago

Files? 🤔

Yes... files... plural. 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 for our action. This API does not require any authentication, but it does however that we set a few parameters in the HTTP headers. I'll 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:

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

const options = {
  method: "GET",
  uri: "https://icanhazdadjoke.com/",
  headers: {
    Accept: "application/json",
    "User-Agent":
      "Writing JavaScript action GitHub Learning Lab course.  Visit lab.github.com or to contact us."
  },
  json: true
};

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

module.exports = getJoke;
Need an advanced description of the joke.js 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 second 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:

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 main.js 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: Creating the JavaScript files for your new action.

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

    const request = require("request-promise");
    
    const options = {
     method: "GET",
     uri: "https://icanhazdadjoke.com/",
     headers: {
       Accept: "application/json",
       "User-Agent":
         "Writing JavaScript action GitHub Learning Lab course.  Visit lab.github.com or to contact us."
     },
     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:

    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:

    git add joke.js main.js
    git commit -m 'creating joke.js and main.js'
    git push

I'll respond in this pull request when you have pushed to this branch.

github-learning-lab[bot] commented 3 years ago

Using your new action

At this point we can't expect much from our workflow, if you remember all of its contents are commented out. Let's go ahead and fix that now so that we can see our action fetch us a joke.

We are going to add a new trigger to our workflow to make it easier for us to trigger it without the need to push changes to the repository. Remember that every time our workflow runs this action we should see a new joke which means we need a good way to make it run a few times. If you recall there are many events that trigger a workflow run.

We will use the pull_request event and specify the activity type to be when an issue get's labeled. This will allow us to trigger our workflow by simply placing a label on this pull request.

:keyboard: Activity: Restore the workflow file

Let's change the tigger and add the joke action

  1. Edit your current workflow file to contain the following:

    name: JS Actions
    
    on:
      pull_request:
        types: [labeled]
    
    jobs:
      action:
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v1
    
          - name: hello-action
            uses: ./.github/actions/hello-world
    
          - name: ha-ha
            uses: ./.github/actions/joke-action
  2. Commit the changes to the action-two branch

I'll respond once you commit your changes

github-learning-lab[bot] commented 3 years ago

esmailbenmoussa get ready to laugh

Great job! Everything is all set up and now we are ready to start laughing 🤣. You will find you have some joke related labels available to you in this repository. You don't have to use them, any label will trigger our workflow, but it might be easier to follow along with me if you use the labels I suggest.

:keyboard: Trigger a joke

  1. Apply the first-joke label to this pull request
  2. Wait a few seconds and then apply the second-joke label to this pull request
  3. Check the workflow results on the Actions tab

Feel free to continue adding labels to this pull request if you want to see more jokes.

When you are ready to move forward in the lesson merge this pull request into the main branch.

github-learning-lab[bot] commented 3 years ago

Congrats on your second action 🎉

Congratulations esmailbenmoussa you have officially written two GitHub JavaScript actions!!!

Next, you'll write your final action of this course, so let's head over to the new issue I've opened to continue.