Skip to content

Exercise: Write JavaScript ActionsΒ #1

Closed

Description

@github-actions

Write JavaScript Actions

original github octocat

πŸ‘‹ Hey there @marnheus! Welcome to your Skills exercise!

Learn to create and use custom JavaScript actions in your GitHub workflows


✨ This is an interactive, hands-on GitHub Skills exercise!

As you complete each step, I’ll leave updates in the comments:

  • βœ… Check your work and guide you forward
  • πŸ’‘ Share helpful tips and resources
  • πŸš€ Celebrate your progress and completion

Let’s get started - good luck and have fun!

β€” Mona

If you encounter any issues along the way please report them here.

Activity

  1. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 1: Setting up the project

    Imagine you’ve got a repetitive task you’d love to automate. You've searched through the GitHub Marketplace for existing actions that might help, you come up empty-handed…

    Maybe that’s because your task is a bit too unique πŸ˜†

    GENERATING DAD JOKES! 🎭

    dadjoke-mona

    Since no pre-built action exists for your quirky automation needs, it's time to roll up your sleeves and create your own!

    ⌨️ Activity: Set up your development environment

    Let's use GitHub Codespaces to set up a cloud-based development environment and work in it for the remainder of the exercise!

    1. Right-click the below button to open the Create Codespace page in a new tab. Use the default configuration.

      Open in GitHub Codespaces

    2. Confirm the Repository field is your copy of the exercise, not the original, then click the green Create Codespace button.

      • βœ… Your copy: /marnheus/skills-write-javascript-actions
      • ❌ Original: /skills/write-javascript-actions
    3. Wait a moment for Visual Studio Code to load in your browser.

    4. Verify that Node.js is available by opening a terminal and running:

      node --version
      npm --version
      Having trouble? 🀷
      • Make sure you selected your personal copy of the repository, not the original template.
      • If the Codespace fails to start, try refreshing the page and creating a new one.
      • Node.js and npm should be pre-installed in the development environment.

    ⌨️ Activity: Initialize Project

    Now that your Codespace is ready, let's initialize a new Node.js project and install the dependencies needed for your Dad Jokes action.

    1. Within your GitHub Codespace terminal window initialize a new project:

      npm init -y
    2. Install the required dependencies:

      npm install request request-promise @actions/core @vercel/ncc

      πŸͺ§ Note: You will learn each library purpose in the next steps

    3. Review package.json to confirm dependencies are listed in the dependencies section.

    4. Open the .gitignore file and add an entry to exclude the node_modules directory from being tracked by Git:

      node_modules/
      

      We don't want to commit node_modules because it contains thousands of files that would bloat the repository.

      πŸͺ§ Note: Instead, later in the exercise you will bundle your action into a single JavaScript file with all dependencies included.

    5. Commit and push your changes:

      git status
      git add .
      git commit -m "Initialize project"
      git push
    6. With the changes pushed to GitHub, Mona will check your work and share the next steps.

    Having trouble? 🀷
    • Ensure you are at the repository root before running npm init -y.
    • Do not commit node_modules/ to the repository; ensure it's listed in .gitignore.
  2. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 1 - Passed βœ…

    Inflatocat image indicating the step passed

    Status Description
    βœ… - Pass package.json file exists
    βœ… - Pass @actions/core dependency present
    βœ… - Pass request dependency present
    βœ… - Pass request-promise dependency present
    βœ… - Pass @vercel/ncc dependency present
    βœ… - Pass .gitignore excludes node_modules/
    βœ… - Pass node_modules properly excluded from repository
  3. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 2! One moment... πŸ€“

  4. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 2: Create Source Files & Run Locally

    Nice! Now that we have the project initialized and dependencies installed, it's time to create the source files for your Dad Jokes GitHub Action.

    πŸ“– Theory: The GitHub Actions Toolkit

    The @actions/core library is the main library from the GitHub Actions Toolkit, a collection of packages for building JavaScript GitHub Actions. It provides essential methods to interact with the GitHub Actions runtime environment, accept action inputs, and produce outputs for other workflow steps.

    Tip

    The GitHub Actions Toolkit includes other useful libraries like @actions/github for interacting with the GitHub API and @actions/artifact for uploading and downloading artifacts.

    Visit the actions/toolkit repository for more.

    ⌨️ Activity: Implement the Dad Jokes Action

    Let's create the source files and implement the logic for your action.

    1. Create src/ directory to hold your JavaScript files:

    2. Create src/joke.js file to hold the logic for fetching a joke from the icanhazdadjoke.com API:

      const request = require("request-promise");
      
      const options = {
        method: "GET",
        uri: "https://icanhazdadjoke.com/",
        headers: {
          Accept: "application/json",
          "User-Agent": "Writing JavaScript action GitHub Skills exercise.",
        },
        json: true,
      };
      
      async function getJoke() {
        const res = await request(options);
        return res.joke;
      }
      
      module.exports = getJoke;

      The getJoke function makes an HTTP GET request to the icanhazdadjoke.com API and returns a random dad joke.

      We export the getJoke function so it can be used in other files.

    3. Create src/main.js that will be the main entry point for your action:

      const getJoke = require("./joke");
      const core = require("@actions/core");
      
      async function run() {
        const joke = await getJoke();
        console.log(joke);
        core.setOutput("joke", joke);
      }
      
      run();

      We call the getJoke function and follow up with core.setOutput() to set the joke output of your GitHub Action.

    4. Run the action locally to verify it works:

      node src/main.js
    5. Commit and push:

      git add src/
      git commit -m "Add Dad Joke action source files"
      git push
    6. With the changes pushed to GitHub, Mona will check your work and share the next steps.

  5. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 2 - Passed βœ…

    Inflatocat image indicating the step passed

    Status Description
    βœ… - Pass Checked for src/main.js file
    βœ… - Pass Checked for src/joke.js file
  6. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 3! One moment... πŸ€“

  7. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 3: Bundle the Action

    Good job! πŸŽ‰

    Now that you've created the source files for your Dad Jokes GitHub Action and tested it locally, it's time to bundle the action so it can be used in GitHub workflows.

    πŸ“– Theory: Bundling Your Action

    When someone uses your action in their workflow, GitHub downloads and executes it as a complete package of code. This means you must include any package dependencies required to run the JavaScript code, such as the @actions/core and request-promise packages your action uses.

    Rather than committing your node_modules directory (which causes problems with repository size and performance), you can use bundling tools like @vercel/ncc to combine your code and dependencies into a single dist/index.js file for distribution.

    ⌨️ Activity: Build Setup & Bundle

    1. Add a new build script to package.json (inside the existing scripts object):

      "scripts": {
         // Existing scripts...
        "build": "ncc build src/main.js -o dist"
      }
    2. Run the build command. This should create a dist/ directory with a bundled index.js file:

      npm run build
    3. (optional) Run the bundled action to verify it works:

      node dist/index.js
    4. Commit and push the changes to the main branch:

      git add .
      git commit -m "Add ncc build script and bundled dist/index.js"
      git push
    5. With the changes pushed to GitHub, Mona will check your work and share the next steps.

  8. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 3 - Fail ❌

    Spidertocat image indicating the step failed

    Some checks failed. Please review the results below and try again.

    Time to find the bug! πŸ€”

    Status Description
    βœ… - Pass Build script present in package.json
    ❌ - Fail dist/index.js generated
  9. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 2! One moment... πŸ€“

  10. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 2: Create Source Files & Run Locally

    Nice! Now that we have the project initialized and dependencies installed, it's time to create the source files for your Dad Jokes GitHub Action.

    πŸ“– Theory: The GitHub Actions Toolkit

    The @actions/core library is the main library from the GitHub Actions Toolkit, a collection of packages for building JavaScript GitHub Actions. It provides essential methods to interact with the GitHub Actions runtime environment, accept action inputs, and produce outputs for other workflow steps.

    Tip

    The GitHub Actions Toolkit includes other useful libraries like @actions/github for interacting with the GitHub API and @actions/artifact for uploading and downloading artifacts.

    Visit the actions/toolkit repository for more.

    ⌨️ Activity: Implement the Dad Jokes Action

    Let's create the source files and implement the logic for your action.

    1. Create src/ directory to hold your JavaScript files:

    2. Create src/joke.js file to hold the logic for fetching a joke from the icanhazdadjoke.com API:

      const request = require("request-promise");
      
      const options = {
        method: "GET",
        uri: "https://icanhazdadjoke.com/",
        headers: {
          Accept: "application/json",
          "User-Agent": "Writing JavaScript action GitHub Skills exercise.",
        },
        json: true,
      };
      
      async function getJoke() {
        const res = await request(options);
        return res.joke;
      }
      
      module.exports = getJoke;

      The getJoke function makes an HTTP GET request to the icanhazdadjoke.com API and returns a random dad joke.

      We export the getJoke function so it can be used in other files.

    3. Create src/main.js that will be the main entry point for your action:

      const getJoke = require("./joke");
      const core = require("@actions/core");
      
      async function run() {
        const joke = await getJoke();
        console.log(joke);
        core.setOutput("joke", joke);
      }
      
      run();

      We call the getJoke function and follow up with core.setOutput() to set the joke output of your GitHub Action.

    4. Run the action locally to verify it works:

      node src/main.js
    5. Commit and push:

      git add src/
      git commit -m "Add Dad Joke action source files"
      git push
    6. With the changes pushed to GitHub, Mona will check your work and share the next steps.

  11. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 3 - Passed βœ…

    Inflatocat image indicating the step passed

    Status Description
    βœ… - Pass Build script present in package.json
    βœ… - Pass dist/index.js generated
  12. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 4! One moment... πŸ€“

  13. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 4: Add Action Metadata

    Great work! πŸŽ‰ You've successfully bundled your Dad Jokes GitHub Action into a single file.

    Now it's time to create the action metadata file - this special file tells GitHub exactly how to use your action when someone includes it in their workflow!

    πŸ“– Theory: Action Metadata

    Every GitHub Action requires a metadata file that defines how the action should be executed and what parameters it accepts.

    Metadata File Requirements

    The metadata file has specific requirements:

    Core Metadata Parameters

    Parameter Description Required
    name The name of your action. βœ…
    description A short description of what your action does. βœ…
    author The name of the action's author. β—‹
    inputs Data that the action expects to receive. β—‹
    outputs Data that downstream steps in the workflow can use β—‹
    runs Tells GitHub how to execute your action. βœ…
    branding Color and icon for your action in GitHub Marketplace. β—‹

    JavaScript Action runs Configuration

    For JavaScript actions, the runs section needs:

    • using: Which Node.js version to use
    • main: The main JavaScript file to run

    Tip

    For complete details on all available metadata parameters, optional fields, and advanced configurations, see the official GitHub Actions metadata syntax documentation.


    ⌨️ Activity: Create Metadata File

    1. Create action.yml at the repository root (same level as package.json).

      name: "Joke Action"
      description: "Fetches a random joke and exposes it as an output"
      
      outputs:
        joke:
          description: "The fetched joke text"
      
      runs:
        using: node24
        main: dist/index.js
    2. Commit and push the action metadata file to the main branch:

      git add action.yml
      git commit -m "Add action metadata file"
      git push
    3. With the changes pushed to GitHub, Mona will check your work and share the next steps.

  14. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 4 - Passed βœ…

    Inflatocat image indicating the step passed

    Status Description
    βœ… - Pass action.yml exists
    βœ… - Pass action.yml references dist/index.js
    βœ… - Pass action.yml declares joke output
  15. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 5! One moment... πŸ€“

  16. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 5: Create Workflow & Consume Output

    Well done! πŸ‘ You've created the Dad Jokes GitHub Action and defined its metadata.

    Your action should be ready to use in any GitHub repository now!

    ⌨️ Activity: Author Workflow

    Let's see your Dad Jokes action in action by creating a GitHub Actions workflow that uses it!

    1. Create a new GitHub Actions workflow file with the following name

      .github/workflows/joke-action.yml
    2. Add the following contents to the workflow file:

      name: Joke Action
      run-name: Dad Joke for issue ${{ github.event.issue.number }} by ${{ github.event.comment.user.login }}
      
      on:
       issue_comment:
         types: [created]
      
      permissions:
       issues: write
       contents: read
      
      jobs:
        joke:
          if: startsWith(github.event.comment.body, '/joke')
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v5
            - name: Get Joke
              id: get-joke
              uses: ./
            - name: Create comment
              uses: peter-evans/create-or-update-comment@v5
              with:
               issue-number: ${{ github.event.issue.number }}
               body: ${{ steps.get-joke.outputs.joke }}

      This workflow triggers for all new issue comments in the repository.

      Because of the if conditional, the joke job only runs if the comment starts with /joke.

    3. Commit and push the workflow file to the main branch:

      git add .github/workflows/joke-action.yml
      git commit -m "Add workflow to test joke action"
      git push
    4. With the workflow pushed to GitHub, Mona will check your work and share the next steps.

  17. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 5 - Passed βœ…

    Inflatocat image indicating the step passed

    Status Description
    βœ… - Pass joke-action workflow file exists
    βœ… - Pass issue_comment trigger present
    βœ… - Pass workflow name should be 'Joke Action'
  18. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Preparing content for step 6! One moment... πŸ€“

  19. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Step 6: Trigger & Validate

    Awesome! πŸš€ You've created the Dad Jokes GitHub Action, defined its metadata, and authored a workflow to use it.

    The only thing left to do is test it out!

    ⌨️ Activity: Try out your action

    1. Create a comment in this issue (or create a new issue) with the text /joke

    2. Monitor the Actions tab for the Joke Action workflow to complete:

      SCR-20251113-kntg
    3. Return to the issue and you should see a new comment posted by github-actions[bot] containing a random dad joke!

    4. Mona will post the exercise review once your new Dad Joke workflow completes successfully!

      Having trouble? 🀷

      If the workflow doesn't trigger or fails:

      • Make sure your comment starts exactly with /joke
      • Check the Actions tab for error messages
      • Verify that your dist/index.js file exists and was committed
      • If you did any updates to your source code, ensure you re-bundled with npm run build and pushed the changes
      • Ensure your action.yml file is correctly formatted
  20. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Please, follow the steps above.
    I'll watch your progress in the background to provide feedback. 🧐

  21. marnheus commented on Feb 4, 2026

    @marnheus
    Owner

    /joke

  22. marnheus commented on Feb 4, 2026

    @marnheus
    Owner

    /joke

  23. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Me and my mates are in a band called Duvet. We're a cover band.

  24. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    πŸŽ‰πŸŽ‰πŸŽ‰ Nice work! Everything is perfect! πŸŽ‰πŸŽ‰πŸŽ‰
    Now, let's do a quick review!

  25. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Review

    Congratulations, you've completed this exercise and learned how to write JavaScript GitHub Actions!

    celebrate

    Here's a recap of your accomplishments:

    • Initialized a Node.js project with proper dependencies and excluded node_modules with a .gitignore configuration
    • Created JavaScript source files implementing a Dad Jokes action and leveraged the @actions/core library to handle action outputs
    • Bundled your action into a single distributable dist/index.js file
    • Created action metadata (action.yml) defining name, description, outputs, and execution parameters
    • Authored a GitHub Actions workflow that uses your custom action
    • Tested your action by triggering it with issue comments and validating the output

    What's next?

    Actions running pricing

    Actions runner pricing

  26. github-actions commented on Feb 4, 2026

    @github-actions
    ContributorAuthor

    Congratulations @marnheus! You finished the exercise! πŸŽ‰πŸŽ‰πŸŽ‰

    We've updated the repository with a couple changes to highlight your success!

    Return to the repository home page to see your progress!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions