cpswan / writing-javascript-actions

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

Hello action #4

Closed github-learning-lab[bot] closed 3 years ago

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

Anatomy of an action

Earlier you learned how the different pieces of the GitHub Actions feature work together. Now you will learn about the components that make up an individual action.

Remember, and action is the unit of work that a workflow file executes when it reaches that task. They are called by referencing them as the value to the uses: key in a workflow step.

What makes up an action?

JavaScript actions are consist of two key components:

Component Description
JavaScript source code files These files contain the logic of your action. This includes any dependencies or custom modules that your main logic may need.
Action metadata file This file contains information that the actions source code can use. An example of this is allowing a developer to specify an API key as an input variable for your action to consume. This file MUST be named action.yml

Let's take a look at how those components fit in with the workflow file.

Screenshot depicting the interaction between the JavaScript files, action metadata file and workflow file.

Although the workflow file is used to allow us to set the inputs and outputs using the with: keyword it is not a required component of an individual action.

The failing workflow

Before we jump into the details of action metadata, it might be helpful to examine our workflow to understand the order that things happen. I have attached a screenshot below of the most recent workflow run, you can also follow along by clicking on the Actions tab for your repository.

This screenshot shows the results of a failing workflow run.  These result can be found by clicking the actions tab of this repository

Notice that our third workflow step, the one that is looking for our action is failing. We expect this, but the magic ✨is in the error message!

That step is looking for a file named action.yml.

Because action.yml is non-existent in the hello-world directory we see this error. So let's start by talking about, and creating, the missing action.yml file.

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

Action metadata

Every GitHub Action that we write needs to be accompanied by a metadata file. This file has a few rules to it, lets outline those now:

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.
Outputs Specifies the data that subsequent actions can use later in the workflow after the action that defines these outputs has run.
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.

📖Read more about Action metadata

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

Enough talk, lets do this!

Now that we know what action metadata is, let's create the metadata for our current hello-world action.

:keyboard: Activity: Create the metadata file

💡All of the following steps take place inside of the .github/actions/hello-world 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/hello-world/action.yml
  2. Add the following contents to the .github/actions/hello-world/action.yml file:

    name: "my hello action"
    
    description: "say hello with GitHub Actions"
    
    runs:
     using: "node12"
     main: "main.js"
  3. Save the action.yml file
  4. Commit the changes and push them to the hello-world branch:

    git add action.yml
    git commit -m 'create action.yml'
    git push

I'll respond here once I notice that you've pushed your changes.

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

Runs

As you have learned runs: defines the command necessary to execute your action.

In our current case runs: takes 2 arguments

These are specific to JavaScript actions. It is our way of telling the runner to run the main.js file using node12

This is no different than running a local JavaScript file using Node like you see below: node example

Which means that the value of main: would be different if your file was not named main.js.
different filename example In this scenario our metadata block would look like this:

runs:
  using: "node12"
  main: "bread.js"

From our workflows perspective

This execution is visible from within your workflow. To save time I have included a screenshot of what your workflow currently looks like. As always, you can follow along in the [Actions tab]().

A look into the failed run

Look 👀, now we have a new error! We are totally making progress here! What we can reason from this output is that our action.yml file was found and read. Since we defined the main: parameter to point to a file named main.js the workflow looked for that file in the root of the hello-world directory, but since it couldn't find it the workflow fails.

Let's fix this next!

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

Time to code 💻

You may have noticed that your workflow has been running every time a change has been made. This is expected since it's trigger is a push event.

Hopefully you have also noticed that it fails when it reaches the hello-action step.

As we can see from the screenshot, as well as the Actions tab, the failure occurs because the runner cannot find the action.

Lets fix that by creating the action it is looking for!

:keyboard: Activity: Hello World

💡All of the following steps take place inside of the .github/actions/hello-world directory.

The first iteration of our action will follow the traditional path of logging "Hello World" 👋to the console. We will expand on this as we move forward, for now it's a good test to make sure all of our files are set up correctly 😄

  1. Create and add the following contents to the .github/actions/hello-world/main.js file:

    console.log("Hello World");
  2. Save the main.js file

  3. Commit the changes and push them to the hello-world branch:

    git add main.js
    git commit -m 'create main.js'
    git push

I'll respond here once the workflow has completed running. Remember, you need to push your changes to trigger it!

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

Congratulations 🎉

Your very first JavaScript action has been written and executed within a workflow! You may be wondering how I know that and the truth is that GitHub Actions provide real-time logging of the events happening within the runner! Since our action prints to the console we can just expand that step in our workflow and look at the standard output that is on our screen.

You can do this in your own Actions tab or you can settle for examining the screenshot below to see our Hello World statement in place of where our previous errors existed.

hello world success

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

Using input parameters

Earlier I asked you to install the @actions/core package using npm. We did this so that we can expand our action to make it more flexible.

A "Hello World" message is great, but let's personalize it a little bit. We will do this by adding an input parameter to the action.yml and main.js files.

Although this example may seem a little lightweight input parameters have a very flexible use case. Consider a scenario where you need to access secret API key with your action, or when you need to specify the path to a given file. Inputs allows for these problems to be easily solved.

A quick example

To add inputs we need to add the inputs: parameter to the action.yml file. The inputs: parameter has a few parameters of its own.

Parameter Description Required
description: String describing the purpose of the input True
required: Boolean value indicating if the input parameter is required or not False (Default value is True)
default: String representing a default value for the input parameter False

Let's take a look at how this fits into an action.yml file.

action.yml

name: "my hello action"

description: "say hello with actions"

inputs:
  first-greeting:
    description: "who would you like to greet in the console"
    required: true
    default: "Hubot"

  second-greeting:
    description: "another person to greet"
    required: true
    default: "Mona the Octocat"

  third-greeting:
    description: "a third greeting"
    required: false

The placement of your inputs: is not strictly enforced, however it has become commonplace to ensure the runs: statement is defined after your inputs: and outputs: in your action.yml file.

So what is actually happening here?

Well, in the my-workflow.yml file we could specify values for inputs we just created:

Or we could leave them out and rely on their default values.

The example below demonstrates a mix of both:

my-workflow.yml

name: "JS Actions"

on: [push]

jobs:
  action:
    runs-on: "ubuntu-latest"
    steps:
      - uses: actions/checkout@v1

      - name: "hello-action"
        uses: ./.github/actions/hello-world
        with:
          first-greeting: "Learning Lab User"

Now that there are inputs in the action's metadata we can use the @actions/core package to handle them within our main.js file.

main.js

const core = require("@actions/core");

const firstGreeting = core.getInput("first-greeting");
const secondGreeting = core.getInput("second-greeting");
const thirdGreeting = core.getInput("third-greeting");

console.log(`Hello ${firstGreeting}`);
console.log(`Hello ${secondGreeting}`);
if (thirdGreeting) {
    console.log(`Hello ${thirdGreeting}`);
}

By using core.getInput() we can specify the string of any input parameter we have placed inside of the action.yml file.

The @actions/core package brings a few more methods along with it to help us interact with the GitHub Actions platform. If writing actions is something you plan to continue doing it's work reading the documentation about this package.


📖Read more about the input parameter

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

Your turn!

:keyboard: Activity: Add input parameters

That was a lot of information that you just learned. @cpswan it is time for you to put it in practice.

  1. Using your code editor change these files to reflect the code in the examples shown above:

    .github/actions/hello-world/main.js ```javascript const core = require("@actions/core"); const firstGreeting = core.getInput("first-greeting"); const secondGreeting = core.getInput("second-greeting"); const thirdGreeting = core.getInput("third-greeting"); console.log(`Hello ${firstGreeting}`); console.log(`Hello ${secondGreeting}`); if (thirdGreeting) { console.log(`Hello ${thirdGreeting}`); } ```
    .github/actions/hello-world/action.yml ```yaml name: "my hello action" description: "say hello with actions" inputs: first-greeting: description: "who would you like to greet in the console" required: true default: "Hubot" second-greeting: description: "another person to greet" required: true default: "Mona the Octocat" third-greeting: description: "a third greeting" required: false runs: using: "node12" main: "main.js" ```
    .github/workflows/my-workflow.yml ```yaml name: "JS Actions" on: [push] jobs: action: runs-on: "ubuntu-latest" steps: - uses: actions/checkout@v1 - name: "hello-action" uses: ./.github/actions/hello-world with: first-greeting: "Learning Lab User" ```
  2. Save the changes to each file

  3. Commit the changes to this branch and push them to GitHub:

    git add main.js action.yml workflow.yml
    git commit -m 'allow input in all action files'
    git push

I'll respond here when GitHub Actions reports it's finished.

Is your workflow failing? If you workflow is failing, please double check your: - JavaScript source code - action metadata - workflow file Look for linter errors or any errors reported on the Actions tab. I will respond when I receive another workflow run is completed.
github-learning-lab[bot] commented 3 years ago

Take a 👀 at what you made!

Great Job 👍 making those changes @cpswan. I will take just a moment to walk you through what happened.

If you look at the screenshot below you will see a very similar output to what your results should show. If you'd like you can open your own Actions tab to follow along.

results from using input

Your action now says hello to Learning Lab User which was the specified value for the first-greeting input parameter which was added to the my-workflow.yml file.

What's interesting though, is that we also see Mona the Octocat and if you recall that is the value of the second-greeting parameter in the action.yml file.

Why do we see the value of the second-greeting 🤔

If you remember, we made the second-greeting input parameter required. This means that even if it is not specified in my-workflow.yml it will be executed by the main.js code using whatever value was set as default. It cannot be ignored like our third-greeting was.

Circling back to the fist-greeting you may have noticed that you were able to overwrite the default value of Hubot by being explicit in the my-workflow.yml file.

Had you been explicit with third-greeting in the my-workflow.yml file then the if statement in the main.js file would have executed and you would have three inputs.

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

Time for you to explore

Take a few minutes to play with the current code you have. I don't suggest editing the main.js file, rather I think there is a lot to gain by changing the my-workflow.yml file to include or exclude certain input parameters.

:keyboard: Activity: Try these things

  1. Remove all the input parameters from the my-workflow.yml file. What happens when your action executes?
  2. Add all three input parameter and be explicit with their values in the my-workflow.yml file. What happens when your action executes?
  3. Specify only the third-greeting input parameter in the my-workflow.yml file. what happens when your action executes?

When you are finished experimenting and examining the results merge this pull request into the main branch.

Our next lesson will show you how to add external libraries to an action as well as interact with external APIs.


When I notice that you have merged this branch I will open a new issue in your repository to continue guiding you.

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

Congrats on your first Action 🎉

Congratulations cpswan you have officially written your first GitHub JavaScript action!!!

That's super exciting news, but this lesson has just start, so let's head over to the new issue I've opened to continue writing GitHub Actions.