From d3087e6d96e2cc8337680c66e10d021c6058997a Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Mon, 3 Nov 2025 11:34:52 +0000
Subject: [PATCH 01/15] Update workflows
---
.github/dependabot.yml | 6 -
...ialize-javascript-project.md => 1-step.md} | 0
.../{2-configure-your-action.md => 2-step.md} | 0
.../{3-create-metadata-file.md => 3-step.md} | 0
...vascript-files-for-action.md => 4-step.md} | 0
...d-action-to-workflow-file.md => 5-step.md} | 0
.../steps/{6-trigger-action.md => 6-step.md} | 0
.github/steps/{X-finish.md => x-review.md} | 0
.github/workflows/0-start-exercise.yml | 67 ++++++++
.github/workflows/0-welcome.yml | 97 ------------
.../1-initialize-javascript-project.yml | 76 ---------
.github/workflows/1-step.yml | 136 ++++++++++++++++
.github/workflows/2-configure-your-action.yml | 76 ---------
.github/workflows/2-step.yml | 136 ++++++++++++++++
.github/workflows/3-create-metadata-file.yml | 78 ----------
.github/workflows/3-step.yml | 137 ++++++++++++++++
.../4-create-javascript-files-for-action.yml | 75 ---------
.github/workflows/4-step.yml | 146 ++++++++++++++++++
.../5-add-action-to-workflow-file.yml | 78 ----------
.github/workflows/5-step.yml | 137 ++++++++++++++++
.github/workflows/6-step.yml | 137 ++++++++++++++++
.github/workflows/6-trigger-action.yml | 71 ---------
.github/workflows/my-workflow.yml | 2 +-
23 files changed, 897 insertions(+), 558 deletions(-)
delete mode 100644 .github/dependabot.yml
rename .github/steps/{1-initialize-javascript-project.md => 1-step.md} (100%)
rename .github/steps/{2-configure-your-action.md => 2-step.md} (100%)
rename .github/steps/{3-create-metadata-file.md => 3-step.md} (100%)
rename .github/steps/{4-create-javascript-files-for-action.md => 4-step.md} (100%)
rename .github/steps/{5-add-action-to-workflow-file.md => 5-step.md} (100%)
rename .github/steps/{6-trigger-action.md => 6-step.md} (100%)
rename .github/steps/{X-finish.md => x-review.md} (100%)
create mode 100644 .github/workflows/0-start-exercise.yml
delete mode 100644 .github/workflows/0-welcome.yml
delete mode 100644 .github/workflows/1-initialize-javascript-project.yml
create mode 100644 .github/workflows/1-step.yml
delete mode 100644 .github/workflows/2-configure-your-action.yml
create mode 100644 .github/workflows/2-step.yml
delete mode 100644 .github/workflows/3-create-metadata-file.yml
create mode 100644 .github/workflows/3-step.yml
delete mode 100644 .github/workflows/4-create-javascript-files-for-action.yml
create mode 100644 .github/workflows/4-step.yml
delete mode 100644 .github/workflows/5-add-action-to-workflow-file.yml
create mode 100644 .github/workflows/5-step.yml
create mode 100644 .github/workflows/6-step.yml
delete mode 100644 .github/workflows/6-trigger-action.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 8ac6b8c..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-version: 2
-updates:
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "monthly"
diff --git a/.github/steps/1-initialize-javascript-project.md b/.github/steps/1-step.md
similarity index 100%
rename from .github/steps/1-initialize-javascript-project.md
rename to .github/steps/1-step.md
diff --git a/.github/steps/2-configure-your-action.md b/.github/steps/2-step.md
similarity index 100%
rename from .github/steps/2-configure-your-action.md
rename to .github/steps/2-step.md
diff --git a/.github/steps/3-create-metadata-file.md b/.github/steps/3-step.md
similarity index 100%
rename from .github/steps/3-create-metadata-file.md
rename to .github/steps/3-step.md
diff --git a/.github/steps/4-create-javascript-files-for-action.md b/.github/steps/4-step.md
similarity index 100%
rename from .github/steps/4-create-javascript-files-for-action.md
rename to .github/steps/4-step.md
diff --git a/.github/steps/5-add-action-to-workflow-file.md b/.github/steps/5-step.md
similarity index 100%
rename from .github/steps/5-add-action-to-workflow-file.md
rename to .github/steps/5-step.md
diff --git a/.github/steps/6-trigger-action.md b/.github/steps/6-step.md
similarity index 100%
rename from .github/steps/6-trigger-action.md
rename to .github/steps/6-step.md
diff --git a/.github/steps/X-finish.md b/.github/steps/x-review.md
similarity index 100%
rename from .github/steps/X-finish.md
rename to .github/steps/x-review.md
diff --git a/.github/workflows/0-start-exercise.yml b/.github/workflows/0-start-exercise.yml
new file mode 100644
index 0000000..aca3b65
--- /dev/null
+++ b/.github/workflows/0-start-exercise.yml
@@ -0,0 +1,67 @@
+name: Step 0 # Start Exercise
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: write
+ actions: write
+ issues: write
+
+env:
+ STEP_1_FILE: ".github/steps/1-step.md"
+
+jobs:
+ start_exercise:
+ if: |
+ !github.event.repository.is_template
+ name: Start Exercise
+ uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.7.0
+ with:
+ exercise-title: "Write JavaScript Actions"
+ intro-message: "Learn to create and use custom JavaScript actions in your GitHub workflows"
+
+ post_next_step_content:
+ name: Post next step content
+ runs-on: ubuntu-latest
+ needs: [start_exercise]
+ env:
+ ISSUE_NUMBER: ${{ needs.start_exercise.outputs.issue-number }}
+ ISSUE_REPOSITORY: ${{ github.repository }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_1_FILE }}
+ vars: |
+ login: ${{ github.actor }}
+ full_repo_name: ${{ github.repository }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Enable next step workflow
+ run: |
+ gh workflow enable "Step 1"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/0-welcome.yml b/.github/workflows/0-welcome.yml
deleted file mode 100644
index 81d1011..0000000
--- a/.github/workflows/0-welcome.yml
+++ /dev/null
@@ -1,97 +0,0 @@
-name: Step 0, Welcome
-
-# This step triggers after the learner creates a new repository from the template.
-# This workflow updates from step 0 to step 1.
-
-# When creating a repository from a template, there is variability in the
-# order and timing of events that fire and when workflow triggers are registered.
-# Given that, these triggers are purposely broad to ensure this workflow is always triggered.
-# The conditions within the on_start job are to ensure it is only fully executed once.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- push:
- branches:
- - main
- workflow_dispatch:
-
-permissions:
- contents: write
- pull-requests: write
- issues: write
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_start:
- name: On start
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 0.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 0 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- # This is required to establish labels.
- # after being created from the template repository.
- - name: Prepare labels
- run: |
- echo "Make sure we are on step 0"
- if [ "$(cat .github/steps/-step.txt)" != 0 ]
- then
- echo "Current step is not 0"
- exit 0
- fi
- echo "Create label 1"
- gh label create "first joke" -d "first joke for lab" -f
- echo "Create label 2"
- gh label create "second joke" -d "second joke for lab" -f
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # This is required to create issues.
- # after being created from the template repository.
- - name: Prepare issues
- run: |
- echo "Make sure we are on step 0"
- if [ "$(cat .github/steps/-step.txt)" != 0 ]
- then
- echo "Current step is not 0"
- exit 0
- fi
- echo "Create issue #1 from file"
- gh issue create --title "Create Custom Action" --body "Implement custom action using JavaScript"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # Update README from step 0 to step 1.
- - name: Update to step 1
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 0
- to_step: 1
diff --git a/.github/workflows/1-initialize-javascript-project.yml b/.github/workflows/1-initialize-javascript-project.yml
deleted file mode 100644
index b10da80..0000000
--- a/.github/workflows/1-initialize-javascript-project.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-name: Step 1, Initialize JavaScript Project
-
-# This step listens for the learner pushing a commit to `main`.
-# This workflow updates from step 1 to step 2.
-
-# This will run every time we push a commit to `main`.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-
-on:
- workflow_dispatch:
- push:
- branches:
- - main
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_commit_contains_required_dependendencies:
- name: Check if main branch has the required action dependencies
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 1.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 1 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Check if NPM package.json exists in the expected location.
- - name: Check file existence
- id: check_files
- uses: andstor/file-existence-action@v3
- with:
- files: ".github/actions/joke-action/package.json"
-
- # Update README from step 1 to step 2.
- - name: Update to step 2
- if: steps.check_files.outputs.files_exists == 'true'
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 1
- to_step: 2
diff --git a/.github/workflows/1-step.yml b/.github/workflows/1-step.yml
new file mode 100644
index 0000000..50ef810
--- /dev/null
+++ b/.github/workflows/1-step.yml
@@ -0,0 +1,136 @@
+name: Step 1
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - ".github/actions/**"
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ STEP_2_FILE: ".github/steps/2-step.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if package.json file exists
+ id: check-package-json
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: .github/actions/joke-action/package.json
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 1
+ results_table:
+ - description: "Created package.json in .github/actions/joke-action/"
+ passed: ${{ steps.check-package-json.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ post_next_step_content:
+ name: Post next step content
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: 2
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_2_FILE }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Disable current workflow and enable next one
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ gh workflow enable "Step 2"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/2-configure-your-action.yml b/.github/workflows/2-configure-your-action.yml
deleted file mode 100644
index 64e192b..0000000
--- a/.github/workflows/2-configure-your-action.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-name: Step 2, Configure Your Action
-
-# This step listens for the learner pushing a commit to `main`.
-# This workflow updates from step 2 to step 3.
-
-# This will run every time we push a commit to `main`.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- workflow_dispatch:
- push:
- branches:
- - main
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_check_action_file_added:
- name: Check if the action.yml file was added
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 2.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 2 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Check if NPM package.json exists in the expected location.
- - name: Check file existence
- id: check_files
- uses: andstor/file-existence-action@v3
- with:
- files: ".github/actions/joke-action/action.yml"
-
- # Update README from step 2 to step 3.
- - name: Update to step 3
- if: steps.check_files.outputs.files_exists == 'true'
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 2
- to_step: 3
diff --git a/.github/workflows/2-step.yml b/.github/workflows/2-step.yml
new file mode 100644
index 0000000..4b2585e
--- /dev/null
+++ b/.github/workflows/2-step.yml
@@ -0,0 +1,136 @@
+name: Step 2
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - ".github/actions/**"
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ STEP_3_FILE: ".github/steps/3-step.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if action.yml file exists
+ id: check-action-yml
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: .github/actions/joke-action/action.yml
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 2
+ results_table:
+ - description: "Created action.yml metadata file in .github/actions/joke-action/"
+ passed: ${{ steps.check-action-yml.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ post_next_step_content:
+ name: Post next step content
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: 3
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_3_FILE }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Disable current workflow and enable next one
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ gh workflow enable "Step 3"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/3-create-metadata-file.yml b/.github/workflows/3-create-metadata-file.yml
deleted file mode 100644
index 538efae..0000000
--- a/.github/workflows/3-create-metadata-file.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: Step 3, Create Metadata File
-
-# This step listens for the learner pushing a commit to `main`.
-# This workflow updates from step 3 to step 4.
-
-# This will run every time we push a commit to `main`.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- workflow_dispatch:
- push:
- branches: [main]
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-env:
- EXPECTED_METADATA: outputs
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_action_file_contains_expected_metadata:
- name: Check if the action.yml file contains the expected metadata
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 3.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 3 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Check if action.yml file contains metadata.
- - name: Read action file contents
- id: read_action_yml_file
- uses: andstor/file-reader-action@v1
- with:
- path: ".github/actions/joke-action/action.yml"
-
- # Update README to from step 3 to step 4.
- - name: Update to step 4
- if: (contains(steps.read_action_yml_file.outputs.contents, ${{ env.EXPECTED_METADATA }})
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 3
- to_step: 4
diff --git a/.github/workflows/3-step.yml b/.github/workflows/3-step.yml
new file mode 100644
index 0000000..12796d7
--- /dev/null
+++ b/.github/workflows/3-step.yml
@@ -0,0 +1,137 @@
+name: Step 3
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - ".github/actions/**"
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ STEP_4_FILE: ".github/steps/4-step.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if action.yml contains metadata outputs
+ id: check-outputs-metadata
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: .github/actions/joke-action/action.yml
+ keyphrase: outputs
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 3
+ results_table:
+ - description: "Added outputs metadata to action.yml"
+ passed: ${{ steps.check-outputs-metadata.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ post_next_step_content:
+ name: Post next step content
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: 4
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_4_FILE }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Disable current workflow and enable next one
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ gh workflow enable "Step 4"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/4-create-javascript-files-for-action.yml b/.github/workflows/4-create-javascript-files-for-action.yml
deleted file mode 100644
index 25c2880..0000000
--- a/.github/workflows/4-create-javascript-files-for-action.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-name: Step 4, Create JavaScript Files For Action
-
-# This step listens for the learner pushing a commit to `main`.
-# This workflow updates from step 4 to step 5.
-
-# This will run every time we push a commit to `main`
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- workflow_dispatch:
- push:
- branches: [main]
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_javascript_files_added:
- name: Check if JavaScript files were added
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 4.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 4 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Check if action JavaScript exists in the expected location.
- - name: Check file existence
- id: check_files
- uses: andstor/file-existence-action@v3
- with:
- files: ".github/actions/joke-action/joke.js, .github/actions/joke-action/main.js"
-
- # Update README from step 4 to step 5.
- - name: Update to step 5
- if: steps.check_files.outputs.files_exists == 'true'
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 4
- to_step: 5
diff --git a/.github/workflows/4-step.yml b/.github/workflows/4-step.yml
new file mode 100644
index 0000000..911c093
--- /dev/null
+++ b/.github/workflows/4-step.yml
@@ -0,0 +1,146 @@
+name: Step 4
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - ".github/actions/**"
+
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ STEP_5_FILE: ".github/steps/5-step.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if joke.js file exists
+ id: check-joke-js
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: .github/actions/joke-action/joke.js
+
+ - name: Check if main.js file exists
+ id: check-main-js
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: .github/actions/joke-action/main.js
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 4
+ results_table:
+ - description: "Created joke.js in .github/actions/joke-action/"
+ passed: ${{ steps.check-joke-js.outcome == 'success' }}
+ - description: "Created main.js in .github/actions/joke-action/"
+ passed: ${{ steps.check-main-js.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ post_next_step_content:
+ name: Post next step content
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: 5
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_5_FILE }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Disable current workflow and enable next one
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ gh workflow enable "Step 5"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/5-add-action-to-workflow-file.yml b/.github/workflows/5-add-action-to-workflow-file.yml
deleted file mode 100644
index 3728511..0000000
--- a/.github/workflows/5-add-action-to-workflow-file.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: Step 5, Add Action To Workflow File
-
-# This step listens for the learner pushing a commit to `main`
-# This workflow updates from step 5 to step 6.
-
-# This will run every time we push a commit to `main`.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- workflow_dispatch:
- push:
- branches: [main]
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-env:
- EXPECTED_METADATA: ha-ha
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_workflow_added_with_custom_action:
- name: Check if workflow is referencing the custom action
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 5.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 5 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Check if action.yml file contains metadata.
- - name: Read action file contents
- id: read_action_yml_file
- uses: andstor/file-reader-action@v1
- with:
- path: ".github/workflows/my-workflow.yml"
-
- # Update README from step 5 to step 6.
- - name: Update to step 6
- if: (contains(steps.read_action_yml_file.outputs.contents, ${{ env.EXPECTED_METADATA }})
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 5
- to_step: 6
diff --git a/.github/workflows/5-step.yml b/.github/workflows/5-step.yml
new file mode 100644
index 0000000..7ec4825
--- /dev/null
+++ b/.github/workflows/5-step.yml
@@ -0,0 +1,137 @@
+name: Step 5
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - ".github/workflows/my-workflow.yml"
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ STEP_6_FILE: ".github/steps/6-step.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if my-workflow.yml contains the custom action
+ id: check-workflow-action
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: .github/workflows/my-workflow.yml
+ keyphrase: ha-ha
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 5
+ results_table:
+ - description: "Added custom action to workflow file that outputs 'ha-ha'"
+ passed: ${{ steps.check-workflow-action.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ post_next_step_content:
+ name: Post next step content
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: 6
+
+ - name: Create comment - add step content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.STEP_6_FILE }}
+
+ - name: Create comment - watching for progress
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
+
+ - name: Disable current workflow and enable next one
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ gh workflow enable "Step 6"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/6-step.yml b/.github/workflows/6-step.yml
new file mode 100644
index 0000000..54efea5
--- /dev/null
+++ b/.github/workflows/6-step.yml
@@ -0,0 +1,137 @@
+name: Step 6
+
+on:
+ workflow_dispatch:
+ issues:
+ types: [labeled]
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+
+env:
+ REVIEW_FILE: ".github/steps/x-review.md"
+
+jobs:
+ find_exercise:
+ name: Find Exercise Issue
+ uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
+
+ check_step_work:
+ name: Check step work
+ runs-on: ubuntu-latest
+ needs: [find_exercise]
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Find last comment
+ id: find-last-comment
+ uses: peter-evans/find-comment@v3
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ direction: last
+
+ - name: Update comment - checking work
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
+ edit-mode: replace
+
+ # START: Check practical exercise
+
+ - name: Check if "second joke" label was applied
+ id: check-label-applied
+ continue-on-error: true
+ run: |
+ if [[ "${{ github.event.label.name }}" == "second joke" ]]; then
+ echo "Label 'second joke' was applied successfully"
+ exit 0
+ else
+ echo "Expected label 'second joke' but got '${{ github.event.label.name }}'"
+ exit 1
+ fi
+
+ - name: Update comment - step results
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
+ edit-mode: replace
+ file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
+ vars: |
+ step_number: 6
+ results_table:
+ - description: "Applied 'second joke' label to trigger the action"
+ passed: ${{ steps.check-label-applied.outcome == 'success' }}
+
+ # END: Check practical exercise
+
+ - name: Fail job if not all checks passed
+ if: contains(steps.*.outcome, 'failure')
+ run: exit 1
+
+ finish_exercise:
+ name: Finish exercise
+ needs: [find_exercise, check_step_work]
+ runs-on: ubuntu-latest
+ env:
+ ISSUE_REPOSITORY: ${{ github.repository }}
+ ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Get response templates
+ uses: actions/checkout@v5
+ with:
+ repository: skills/exercise-toolkit
+ path: exercise-toolkit
+ ref: v0.7.0
+
+ - name: Create comment - step finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
+ vars: |
+ next_step_number: finish
+
+ - name: Create comment - add review content
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: ${{ env.REVIEW_FILE }}
+
+ - name: Create comment - exercise finished
+ uses: GrantBirki/comment@v2.1.1
+ with:
+ repository: ${{ env.ISSUE_REPOSITORY }}
+ issue-number: ${{ env.ISSUE_NUMBER }}
+ file: exercise-toolkit/markdown-templates/step-feedback/exercise-finished.md
+
+ - name: Disable current workflow
+ run: |
+ gh workflow disable "${{github.workflow}}"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/6-trigger-action.yml b/.github/workflows/6-trigger-action.yml
deleted file mode 100644
index 55ee27a..0000000
--- a/.github/workflows/6-trigger-action.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-name: Step 6, Trigger Your Action
-
-# This step listens for the learner applying a label to an issue.
-# This workflow updates from step 6 to step X.
-
-# This will run every time we apply a label to an issue.
-# Reference: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
-on:
- workflow_dispatch:
- issues:
- types: [labeled]
-
-permissions:
- # Need `contents: read` to checkout the repository.
- # Need `contents: write` to update the step metadata.
- contents: write
-
-env:
- EXPECTED_METADATA: "second joke"
-
-jobs:
- # Get the current step to only run the main job when the learner is on the same step.
- get_current_step:
- name: Check current step number
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - id: get_step
- run: |
- echo "current_step=$(cat ./.github/steps/-step.txt)" >> $GITHUB_OUTPUT
- outputs:
- current_step: ${{ steps.get_step.outputs.current_step }}
-
- on_my_workflow_run:
- name: Check if my_workflow has run
- needs: get_current_step
-
- # We will only run this action when:
- # 1. This repository isn't the template repository.
- # 2. The step is currently 6.
- # Reference: https://docs.github.com/en/actions/learn-github-actions/contexts
- # Reference: https://docs.github.com/en/actions/learn-github-actions/expressions
- if: >-
- ${{ !github.event.repository.is_template
- && needs.get_current_step.outputs.current_step == 6 }}
-
- # We'll run Ubuntu for performance instead of Mac or Windows.
- runs-on: ubuntu-latest
-
- steps:
- # We'll need to check out the repository so that we can edit the README.
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Let's get all the branches.
-
- - name: Dump GitHub comment context
- id: github_comment_step
- env:
- COMMENT_CONTEXT: ${{ toJson(github.event) }}
- run: echo "$COMMENT_CONTEXT"
-
- # Update README from step 6 to step X.
- - name: Update to step X
- if: contains(github.event, ${{ env.EXPECTED_METADATA }})
- uses: skills/action-update-step@v2
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- from_step: 6
- to_step: X
diff --git a/.github/workflows/my-workflow.yml b/.github/workflows/my-workflow.yml
index afe29e8..40575c6 100644
--- a/.github/workflows/my-workflow.yml
+++ b/.github/workflows/my-workflow.yml
@@ -10,4 +10,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
From b7674265b4af69695a3970f2229134bbd54a19b5 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Mon, 3 Nov 2025 13:00:58 +0000
Subject: [PATCH 02/15] Update readme
---
README.md | 70 +++++++++++++++++++------------------------------------
1 file changed, 24 insertions(+), 46 deletions(-)
diff --git a/README.md b/README.md
index 1f915f2..2b296fe 100644
--- a/README.md
+++ b/README.md
@@ -1,35 +1,18 @@
-
-
-
-
# Write JavaScript Actions
_Write your own GitHub JavaScript Action and automate customized tasks unique to your workflow._
-
-
-
-
## Welcome
-Write your own GitHub JavaScript Action and automate customized tasks unique to your workflow.
-
- **Who is this for**: Developers, GitHub users, users new to Git, students, managers, and for teams.
- **What you'll learn**: How to consume actions within a workflow file, create custom JavaScript based actions and publish your newly created action to the marketplace.
-- **Prerequisites**: Before you start, you should be familiar with GitHub, GitHub Actions, and Continuous Integration with GitHub Actions.
-- **How long**: This course takes about 1 to 2 hours to be completed.
+- **What you'll build**: A custom JavaScript-based GitHub Action that can be published to the marketplace.
+- **Prerequisites**:
+ - You should be familiar with GitHub and GitHub Actions. We recommend taking the [Hello GitHub Actions](https://github.com/skills-dev/hello-github-actions) exercise first.
+
+- **How long**: This exercise takes about 1 hour to complete.
-In this course, you will:
+In this exercise, you will:
1. Initialize a JavaScript project
2. Configure an action
@@ -38,34 +21,29 @@ In this course, you will:
5. Add actions to workflow file
6. Trigger action
-### How to start this course
+### How to start this exercise
-
+Simply copy the exercise to your account, then give your favorite Octocat (Mona) **about 20 seconds** to prepare the first lesson, then **refresh the page**.
-[](https://github.com/new?template_owner=skills&template_name=write-javascript-actions&owner=%40me&name=skills-write-javascript-actions&description=My+clone+repository&visibility=public)
+[](https://github.com/new?template_owner=FidelusAleksander&template_name=write-javascript-actions&owner=%40me&name=skills-write-javascript-actions&description=Exercise:+Write+JavaScript+Actions&visibility=public)
-1. Right-click **Start course** and open the link in a new tab.
-2. In the new tab, most of the prompts will automatically fill in for you.
- - For owner, choose your personal account or an organization to host the repository.
- - We recommend creating a public repository, as private repositories will [use Actions minutes](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions).
- - Scroll down and click the **Create repository** button at the bottom of the form.
-3. After your new repository is created, wait about 20 seconds, then refresh the page. Follow the step-by-step instructions in the new repository's README.
+
+Having trouble? 🤷
-
+
+---
-
+© 2025 GitHub • [Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md) • [MIT License](https://gh.io/mit)
From 37779be38aa0b5288dcc3d81ca6d0f7101425ddd Mon Sep 17 00:00:00 2001
From: FidelusAleksander
Date: Thu, 6 Nov 2025 12:50:03 +0100
Subject: [PATCH 03/15] Add node_modules to gitignore
---
.gitignore | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.gitignore b/.gitignore
index 773bfd6..81d726e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,7 @@
.Trashes
ehthumbs.db
Thumbs.db
+
+# Node modules #
+################
+node_modules/
\ No newline at end of file
From a0259ea317cd11048bca499e5f0afa1795f9acba Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 6 Nov 2025 19:08:20 +0100
Subject: [PATCH 04/15] feat: initial rewrite of the exercise (#1)
---
.github/steps/-step.txt | 1 -
.github/steps/0-welcome.md | 1 -
.github/steps/1-step.md | 120 +++++++++--------
.github/steps/2-step.md | 122 ++++++++++++++----
.github/steps/3-step.md | 70 +++-------
.github/steps/4-step.md | 170 +++----------------------
.github/steps/5-step.md | 77 +++++------
.github/steps/6-step.md | 20 +--
.github/workflows/0-start-exercise.yml | 2 +-
.github/workflows/1-step.yml | 66 +++++++++-
.github/workflows/2-step.yml | 22 +++-
.github/workflows/3-step.yml | 24 +++-
.github/workflows/4-step.yml | 36 ++++--
.github/workflows/5-step.yml | 33 ++++-
.github/workflows/6-step.yml | 21 +--
.github/workflows/my-workflow.yml | 13 --
16 files changed, 387 insertions(+), 411 deletions(-)
delete mode 100644 .github/steps/-step.txt
delete mode 100644 .github/steps/0-welcome.md
delete mode 100644 .github/workflows/my-workflow.yml
diff --git a/.github/steps/-step.txt b/.github/steps/-step.txt
deleted file mode 100644
index 573541a..0000000
--- a/.github/steps/-step.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/.github/steps/0-welcome.md b/.github/steps/0-welcome.md
deleted file mode 100644
index 9ff13a5..0000000
--- a/.github/steps/0-welcome.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/.github/steps/1-step.md b/.github/steps/1-step.md
index 0394b22..518b06c 100644
--- a/.github/steps/1-step.md
+++ b/.github/steps/1-step.md
@@ -1,85 +1,81 @@
-
+## Step 1: Initializing the Dad Jokes GitHub Action
-## Step 1: Initialize a new JavaScript project
+Imagine you have a repetitive task that you want to automate. You've searched through the [**GitHub Marketplace**](https://github.com/marketplace?type=actions) to see if there are any existing actions that suit your needs, but found nothing - because your task is very specific: **generating DAD JOKES**! 🎭
-_Welcome to the course :tada:_
+Since no pre-built action exists for your quirky automation needs, it's time to roll up your sleeves and create your own
-### Configuring a workflow
+### ⌨️ Activity: Set up your development environment
-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.
+Let's use **GitHub Codespaces** to set up a cloud-based development environment and work in it for the remainder of the exercise!
-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.
+1. Right-click the below button to open the **Create Codespace** page in a new tab. Use the default configuration.
-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.
+ [](https://codespaces.new/{{full_repo_name}}?quickstart=1)
-_In our case, we will use this one **workflow** file for many things, which leads us to break this convention for teaching purposes._
+1. Confirm the **Repository** field is your copy of the exercise, not the original, then click the green **Create Codespace** button.
-Read more about [workflows](https://docs.github.com/en/actions/writing-workflows/about-workflows)
+ - ✅ Your copy: `/{{full_repo_name}}`
+ - ❌ Original: `/skills-dev/write-javascript-actions`
-## On to your development environment
+1. Wait a moment for Visual Studio Code to load in your browser.
-Our JavaScript actions are going to leverage the [GitHub ToolKit](https://github.com/actions/toolkit) for developing GitHub Actions.
+1. Verify that **Node.js** is available by opening a terminal and running:
-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.
+ ```sh
+ node --version
+ npm --version
+ ```
-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/).
+
+ Having trouble? 🤷
-## Don't forget to set up your workstation
+ - 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.
-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/)
+### ⌨️ Activity: Initialize Project
-### :keyboard: Activity 1: Initialize a new JavaScript 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.
-Once you have the necessary tools installed locally, follow these steps to begin creating your first action.
+1. Within your GitHub Codespace terminal window initialize a new project:
-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 .git
- ```
-3. Navigate to the folder you just cloned:
- ```shell
- cd
- ```
-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
+ ```sh
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
+
+1. Install the required dependencies:
+
+ ```sh
+ npm install request request-promise @actions/core @vercel/ncc
+ ```
+
+1. Review `package.json` to confirm dependencies are listed in the `dependencies` section.
+
+1. Open the `.gitignore` file and add an entry to exclude the `node_modules` directory from being tracked by git:
+
+ ```text
+ node_modules/
```
-9. Commit those newly added files,we will remove the need to upload **node_modules** in a later step:
- ```shell
+
+ 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.
+
+1. Commit and push your changes:
+
+ ```sh
+ git status
git add .
- git commit -m 'add project dependencies'
+ git commit -m "Initialize project"
+ git push
```
-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.
+
+
+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`.
+
+
diff --git a/.github/steps/2-step.md b/.github/steps/2-step.md
index 9c4fd27..912172c 100644
--- a/.github/steps/2-step.md
+++ b/.github/steps/2-step.md
@@ -1,42 +1,110 @@
-
+## Step 2: Create Source Files & Run Locally
-## Step 2: Configure Your Action
+### 📖 Theory
-_Let's keep going! :bike:_
+Author the action’s core logic and verify it runs locally before bundling.
-### Excellent!
+### ⌨️ Activity: Implement the Dad Jokes Action
-Now that we have the custom action pre-requisites, let us create **joke-action** action.
+Now that your project is initialized and dependencies are installed, it's time to create the source files for your Dad Jokes GitHub Action.
-### :keyboard: Activity 1: Configure Your Action
-All of the following steps take place inside of the `.github/actions/joke-action` directory.
+1. Create `src/` directory to hold your GitHub Action JavaScript files:
-We will start with using the parameters that are **required** and later implement some optional parameters as our action evolves.
+ ```sh
+ mkdir src
+ ```
+
+1. Create `src/joke.js` file to hold the logic for fetching a joke from the `icanhazdadjoke.com` API:
-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:
+ ```js
+ const request = require("request-promise");
- ```yaml
- name: "my joke action"
+ const options = {
+ method: "GET",
+ uri: "https://icanhazdadjoke.com/",
+ headers: {
+ Accept: "application/json",
+ "User-Agent": "Writing JavaScript action GitHub Skills exercise.",
+ },
+ json: true,
+ };
- description: "use an external API to retrieve and display a joke"
+ async function getJoke() {
+ const res = await request(options);
+ return res.joke;
+ }
- runs:
- using: "node16"
- main: "main.js"
+ module.exports = getJoke;
```
-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
+1. Create `src/main.js` that will be the main entry point for your action:
+
+ ```js
+ 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();
+ ```
+
+1. Run the action locally to verify it works:
+
+ ```sh
+ node src/main.js
+ ```
+
+
+
+1. Commit and push:
+
+ ```sh
+ git add src/
+ git commit -m "Add Dad Joke action source files"
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.
+
+### 🛠 Activity (Optional): Debug your action
+
+>[!NOTE]
+> This activity is optional and not required to complete the exercise.
+>
+> Learning how to debug your action code can be very helpful!
+
+
+Show steps
+
+1. Install dev dependency:
+
+ ```sh
+ npm install -D @github/local-action
+ ```
+
+1. Create `.vscode/launch.json`:
+
+ ```json
+ {
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug Action",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npx",
+ "cwd": "${workspaceRoot}",
+ "args": ["@github/local-action", ".", "src/main.js"],
+ "console": "integratedTerminal",
+ "skipFiles": ["/**", "node_modules/**"]
+ }
+ ]
+ }
+ ```
+
+1. Set breakpoints in `src/main.js` and start the "Debug Action" configuration.
+
+
diff --git a/.github/steps/3-step.md b/.github/steps/3-step.md
index ce26a39..1f07648 100644
--- a/.github/steps/3-step.md
+++ b/.github/steps/3-step.md
@@ -1,64 +1,30 @@
-
+## Step 3: Bundle the Action
-## Step 3: Create the metadata file
+### 📖 Theory: Bundling the action
-_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:
+### ⌨️ Activity: Build Setup & Bundle
-- Filename **must** be `action.yml`.
-- Required for both Docker container and JavaScript actions.
-- Written in YAML syntax.
+1. Add a build script to `package.json` (inside the existing scripts block or create one):
-This file defines the following information about your action:
+ ```json
+ "scripts": {
+ "build": "ncc build src/main.js -o dist"
+ }
+
+ ```
-| 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: |
+1. Run the build command. This should create a `dist/` directory with a bundled `index.js` file:
----
+ ```sh
+ npm run build
+ ```
-Read more about [Action metadata](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/metadata-syntax-for-github-actions)
+1. Commit and push the changes to the `main` branch:
-### :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 pull
- git commit -m 'add metadata for the joke action'
+ ```sh
+ git add .
+ git commit -m "Add ncc build script and bundled dist/index.js"
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.
diff --git a/.github/steps/4-step.md b/.github/steps/4-step.md
index 2039bd3..5f5920e 100644
--- a/.github/steps/4-step.md
+++ b/.github/steps/4-step.md
@@ -1,163 +1,31 @@
-
+## Step 4: Add Action Metadata
-## Step 4: Create the JavaScript files for your action
+### 📖 Theory
-_Good job adding the metadata file! :dancer:_
+Define the action’s interface (name, description, outputs, runtime, main entry) via `action.yml` pointing to the bundled file.
-## Files
+### ⌨️ Activity: Create Metadata File
-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.
+1. Create `action.yml` at the repository root (same level as `package.json`).
-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.
+ ```yaml
+ name: "Joke Action"
+ description: "Fetches a random joke and exposes it as an output"
-### Fetching a joke
+ outputs:
+ joke:
+ description: "The fetched joke text"
-**Joke API**
+ runs:
+ using: node24
+ main: dist/index.js
+ ```
-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:
+1. Commit and push:
-```
-{
- 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/actions/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 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 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 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 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
+ ```sh
+ git add action.yml
+ git commit -m "Add action metadata referencing dist/index.js"
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.
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index f556695..d1df15c 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -1,42 +1,35 @@
-
-
-## Step 5: Add your action to the workflow file
-
-_Great job! :tada:_
-
-All of the following steps will add the action to the workflow file that’s already in the repo [`my-workflow.yml` file](/.github/workflows/my-workflow.yml)
-
-### :keyboard: Activity 1: Edit the custom action at the bottom of the workflow file.
-
-```yaml
-- name: ha-ha
- uses: ./.github/actions/joke-action
-```
-
-Here is what the full file should look like (we’re using issues instead of the pull request event and removing the reference to the hello world action.)
-
-```yaml
-name: JS Actions
-
-on:
- issues:
- types: [labeled]
-
-jobs:
- action:
- if: ${{ !github.event.repository.is_template }}
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- - name: ha-ha
- uses: ./.github/actions/joke-action
-```
-
-You can make these changes in your repository by opening [`my-workflow.yml`](/.github/workflows/my-workflow.yml) in another browser tab and [editing the file directly](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files). Make sure to select the `Commit directly to the main branch` option.
-
-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.
+## Step 5: Create Workflow & Consume Output
+
+### 📖 Theory
+
+Use a workflow triggered by `issue_comment` to run the local action and then post the retrieved joke as a comment.
+
+### ⌨️ Activity: Author Workflow
+
+1. Create `.github/workflows/joke-action.yml`.
+
+ ```yaml
+ name: Joke Action
+ on:
+ issue_comment:
+ types: [created]
+ 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 }}
+
+ ```
+
+ The workflow will run on every issue comment created event. If the comment starts with `/joke`, it will execute the Dad Jokes action and post the joke as a comment in the same issue.
+
+1. Commit and push the workflow file to the `main`:
diff --git a/.github/steps/6-step.md b/.github/steps/6-step.md
index c5898b9..e786dbd 100644
--- a/.github/steps/6-step.md
+++ b/.github/steps/6-step.md
@@ -1,19 +1,9 @@
-
+## Step 6: Trigger & Validate
-## Step 6: Trigger the joke action
-_Great job! :heart:_
-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 the easiest way to follow along would be to use suggested labels.
+### ⌨️ Activity: Try out your action!
-### Trigger a joke
-
-1. Open issue #1 in the "Issues tab"
-2. Apply the `first-joke` label to the issue
-3. Wait a few seconds and then apply the `second-joke` label to the issue
-4. Check the `JS Actions` workflow results on the "Actions tab"
-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.
+1. Create a comment in this issue (or create a new one) with the text `/joke`
+1. Monitor the `actions` tab for the "Joke Action" workflow run to complete.
+1. After it completes you should see a new comment posted by the bot with the dad joke!
diff --git a/.github/workflows/0-start-exercise.yml b/.github/workflows/0-start-exercise.yml
index aca3b65..ed2372f 100644
--- a/.github/workflows/0-start-exercise.yml
+++ b/.github/workflows/0-start-exercise.yml
@@ -19,7 +19,7 @@ jobs:
if: |
!github.event.repository.is_template
name: Start Exercise
- uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.7.0
+ uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.7.3
with:
exercise-title: "Write JavaScript Actions"
intro-message: "Learn to create and use custom JavaScript actions in your GitHub workflows"
diff --git a/.github/workflows/1-step.yml b/.github/workflows/1-step.yml
index 50ef810..76c0a14 100644
--- a/.github/workflows/1-step.yml
+++ b/.github/workflows/1-step.yml
@@ -1,12 +1,12 @@
name: Step 1
on:
- workflow_dispatch:
push:
branches:
- main
paths:
- - ".github/actions/**"
+ - "package.json"
+ - ".gitignore"
permissions:
contents: read
@@ -18,6 +18,7 @@ env:
jobs:
find_exercise:
+ if: github.run_number != 1
name: Find Exercise Issue
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
@@ -64,7 +65,54 @@ jobs:
continue-on-error: true
uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
with:
- file: .github/actions/joke-action/package.json
+ file: package.json
+
+ - name: Check for @actions/core dependency
+ id: check-core-dep
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: package.json
+ keyphrase: "@actions/core"
+
+ - name: Check for @actions/github dependency
+ id: check-github-dep
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: package.json
+ keyphrase: "@actions/github"
+
+ - name: Check for @vercel/ncc dependency
+ id: check-ncc-dep
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: package.json
+ keyphrase: "@vercel/ncc"
+
+ - name: Check .gitignore excludes node_modules
+ id: check-gitignore
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: .gitignore
+ keyphrase: "node_modules/"
+
+ - name: Check node_modules is not committed
+ id: check-node-modules-not-committed
+ continue-on-error: true
+ run: |
+ if [ -d "node_modules" ] || find . -name "node_modules" -type d | grep -q .; then
+ found_dirs=$(find . -name "node_modules" -type d)
+ echo "❌ Found node_modules directory in repository"
+ echo "$found_dirs"
+ echo "STEP_MESSAGE=Found node_modules committed to repository. Remove it from the repository." >> $GITHUB_OUTPUT
+ exit 1
+ else
+ echo "✅ No node_modules directory found in repository"
+ echo "STEP_MESSAGE=node_modules properly excluded from repository" >> $GITHUB_OUTPUT
+ fi
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -77,8 +125,18 @@ jobs:
vars: |
step_number: 1
results_table:
- - description: "Created package.json in .github/actions/joke-action/"
+ - description: "package.json file exists"
passed: ${{ steps.check-package-json.outcome == 'success' }}
+ - description: "@actions/core dependency present"
+ passed: ${{ steps.check-core-dep.outcome == 'success' }}
+ - description: "@actions/github dependency present"
+ passed: ${{ steps.check-github-dep.outcome == 'success' }}
+ - description: "@vercel/ncc dependency present"
+ passed: ${{ steps.check-ncc-dep.outcome == 'success' }}
+ - description: ".gitignore excludes node_modules/"
+ passed: ${{ steps.check-gitignore.outcome == 'success' }}
+ - description: "${{ steps.check-node-modules-not-committed.outputs.STEP_MESSAGE }}"
+ passed: ${{ steps.check-node-modules-not-committed.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/2-step.yml b/.github/workflows/2-step.yml
index 4b2585e..bd0237d 100644
--- a/.github/workflows/2-step.yml
+++ b/.github/workflows/2-step.yml
@@ -6,7 +6,8 @@ on:
branches:
- main
paths:
- - ".github/actions/**"
+ - "src/main.js"
+ - "src/joke.js"
permissions:
contents: read
@@ -59,12 +60,19 @@ jobs:
# START: Check practical exercise
- - name: Check if action.yml file exists
- id: check-action-yml
+ - name: Check if src/main.js exists
+ id: check-main-js
continue-on-error: true
uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
with:
- file: .github/actions/joke-action/action.yml
+ file: src/main.js
+
+ - name: Check if src/joke.js exists
+ id: check-joke-js
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: src/joke.js
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -77,8 +85,10 @@ jobs:
vars: |
step_number: 2
results_table:
- - description: "Created action.yml metadata file in .github/actions/joke-action/"
- passed: ${{ steps.check-action-yml.outcome == 'success' }}
+ - description: "src/main.js exists"
+ passed: ${{ steps.check-main-js.outcome == 'success' }}
+ - description: "src/joke.js exists"
+ passed: ${{ steps.check-joke-js.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/3-step.yml b/.github/workflows/3-step.yml
index 12796d7..a6e954d 100644
--- a/.github/workflows/3-step.yml
+++ b/.github/workflows/3-step.yml
@@ -6,7 +6,8 @@ on:
branches:
- main
paths:
- - ".github/actions/**"
+ - "package.json"
+ - "dist/index.js"
permissions:
contents: read
@@ -59,13 +60,20 @@ jobs:
# START: Check practical exercise
- - name: Check if action.yml contains metadata outputs
- id: check-outputs-metadata
+ - name: Check for build script in package.json
+ id: check-build-script
continue-on-error: true
uses: skills/action-keyphrase-checker@v1
with:
- text-file: .github/actions/joke-action/action.yml
- keyphrase: outputs
+ text-file: package.json
+ keyphrase: "ncc build src/main.js -o dist"
+
+ - name: Check if dist/index.js exists
+ id: check-dist-index
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: dist/index.js
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -78,8 +86,10 @@ jobs:
vars: |
step_number: 3
results_table:
- - description: "Added outputs metadata to action.yml"
- passed: ${{ steps.check-outputs-metadata.outcome == 'success' }}
+ - description: "Build script present in package.json"
+ passed: ${{ steps.check-build-script.outcome == 'success' }}
+ - description: "dist/index.js generated"
+ passed: ${{ steps.check-dist-index.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/4-step.yml b/.github/workflows/4-step.yml
index 911c093..1376933 100644
--- a/.github/workflows/4-step.yml
+++ b/.github/workflows/4-step.yml
@@ -6,8 +6,7 @@ on:
branches:
- main
paths:
- - ".github/actions/**"
-
+ - "action.yml"
permissions:
contents: read
@@ -60,19 +59,28 @@ jobs:
# START: Check practical exercise
- - name: Check if joke.js file exists
- id: check-joke-js
+ - name: Check if action.yml exists
+ id: check-action-yml
continue-on-error: true
uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
with:
- file: .github/actions/joke-action/joke.js
+ file: action.yml
- - name: Check if main.js file exists
- id: check-main-js
+ - name: Check action.yml references dist/index.js
+ id: check-action-main
continue-on-error: true
- uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: action.yml
+ keyphrase: "dist/index.js"
+
+ - name: Check action.yml declares joke output
+ id: check-action-output
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
with:
- file: .github/actions/joke-action/main.js
+ text-file: action.yml
+ keyphrase: "joke:"
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -85,10 +93,12 @@ jobs:
vars: |
step_number: 4
results_table:
- - description: "Created joke.js in .github/actions/joke-action/"
- passed: ${{ steps.check-joke-js.outcome == 'success' }}
- - description: "Created main.js in .github/actions/joke-action/"
- passed: ${{ steps.check-main-js.outcome == 'success' }}
+ - description: "action.yml exists"
+ passed: ${{ steps.check-action-yml.outcome == 'success' }}
+ - description: "action.yml references dist/index.js"
+ passed: ${{ steps.check-action-main.outcome == 'success' }}
+ - description: "action.yml declares joke output"
+ passed: ${{ steps.check-action-output.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/5-step.yml b/.github/workflows/5-step.yml
index 7ec4825..d945f67 100644
--- a/.github/workflows/5-step.yml
+++ b/.github/workflows/5-step.yml
@@ -6,7 +6,7 @@ on:
branches:
- main
paths:
- - ".github/workflows/my-workflow.yml"
+ - ".github/workflows/joke-action.yml"
permissions:
contents: read
@@ -59,13 +59,28 @@ jobs:
# START: Check practical exercise
- - name: Check if my-workflow.yml contains the custom action
- id: check-workflow-action
+ - name: Check if joke-action workflow exists
+ id: check-joke-workflow
+ continue-on-error: true
+ uses: skills/exercise-toolkit/actions/file-exists@v0.7.0
+ with:
+ file: .github/workflows/joke-action.yml
+
+ - name: Check workflow has issue_comment trigger
+ id: check-issue-comment-trigger
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: .github/workflows/joke-action.yml
+ keyphrase: issue_comment
+
+ - name: Check workflow references steps.get_joke.outputs.joke
+ id: check-output-reference
continue-on-error: true
uses: skills/action-keyphrase-checker@v1
with:
- text-file: .github/workflows/my-workflow.yml
- keyphrase: ha-ha
+ text-file: .github/workflows/joke-action.yml
+ keyphrase: steps.get_joke.outputs.joke
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -78,8 +93,12 @@ jobs:
vars: |
step_number: 5
results_table:
- - description: "Added custom action to workflow file that outputs 'ha-ha'"
- passed: ${{ steps.check-workflow-action.outcome == 'success' }}
+ - description: "joke-action workflow file exists"
+ passed: ${{ steps.check-joke-workflow.outcome == 'success' }}
+ - description: "issue_comment trigger present"
+ passed: ${{ steps.check-issue-comment-trigger.outcome == 'success' }}
+ - description: "Output reference steps.get_joke.outputs.joke present"
+ passed: ${{ steps.check-output-reference.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/6-step.yml b/.github/workflows/6-step.yml
index 54efea5..e2c3303 100644
--- a/.github/workflows/6-step.yml
+++ b/.github/workflows/6-step.yml
@@ -2,8 +2,11 @@ name: Step 6
on:
workflow_dispatch:
- issues:
- types: [labeled]
+ workflow_run:
+ workflows:
+ - Joke Action
+ types:
+ - completed
permissions:
contents: read
@@ -56,15 +59,15 @@ jobs:
# START: Check practical exercise
- - name: Check if "second joke" label was applied
- id: check-label-applied
+ - name: Check Joke Action workflow run success
+ id: check-joke-run
continue-on-error: true
run: |
- if [[ "${{ github.event.label.name }}" == "second joke" ]]; then
- echo "Label 'second joke' was applied successfully"
+ if [ "${{ github.event.workflow_run.conclusion }}" = "success" ]; then
+ echo "Joke Action workflow run was successful"
exit 0
else
- echo "Expected label 'second joke' but got '${{ github.event.label.name }}'"
+ echo "Joke Action workflow run conclusion: ${{ github.event.workflow_run.conclusion }}"
exit 1
fi
@@ -79,8 +82,8 @@ jobs:
vars: |
step_number: 6
results_table:
- - description: "Applied 'second joke' label to trigger the action"
- passed: ${{ steps.check-label-applied.outcome == 'success' }}
+ - description: "Joke Action workflow run concluded successfully"
+ passed: ${{ steps.check-joke-run.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/my-workflow.yml b/.github/workflows/my-workflow.yml
deleted file mode 100644
index 40575c6..0000000
--- a/.github/workflows/my-workflow.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: JS Actions
-
-on:
- issues:
- types: [labeled]
-
-jobs:
- action:
- if: ${{ !github.event.repository.is_template }}
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v5
From 16c67a44682af8bebc94d92b3685872e1c3caa41 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 6 Nov 2025 20:05:36 +0000
Subject: [PATCH 05/15] Test run updates
---
.devcontainer/devcontainer.json | 6 ++
.github/steps/5-step.md | 18 +++--
.github/workflows/0-start-exercise.yml | 1 -
.github/workflows/1-step.yml | 20 ++++--
.github/workflows/2-step.yml | 4 +-
.github/workflows/5-step.yml | 10 +--
.github/workflows/6-step.yml | 99 ++++----------------------
.gitignore | 5 +-
8 files changed, 58 insertions(+), 105 deletions(-)
create mode 100644 .devcontainer/devcontainer.json
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..0464eb0
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,6 @@
+{
+ "image": "mcr.microsoft.com/devcontainers/universal:2",
+ "features": {
+ "ghcr.io/devcontainers/features/node:1": {}
+ }
+}
\ No newline at end of file
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index d1df15c..9f56e25 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -6,13 +6,24 @@ Use a workflow triggered by `issue_comment` to run the local action and then pos
### ⌨️ Activity: Author Workflow
-1. Create `.github/workflows/joke-action.yml`.
+1. Create a new GitHub Actions workflow file with the following name
+
+ ```txt
+ .github/workflows/joke-action.yml
+ ```
+
+1. Add the following contents to the workflow file:
```yaml
name: Joke Action
on:
issue_comment:
types: [created]
+
+ permissions:
+ issues: write
+ contents: read
+
jobs:
joke:
if: startsWith(github.event.comment.body, '/joke')
@@ -25,9 +36,8 @@ Use a workflow triggered by `issue_comment` to run the local action and then pos
- name: Create comment
uses: peter-evans/create-or-update-comment@v5
with:
- issue-number: ${{ github.event.issue.number }}
- body: ${{ steps.get-joke.outputs.joke }}
-
+ issue-number: {% raw %}${{ github.event.issue.number }}{% endraw %}
+ body: {% raw %}${{ steps.get-joke.outputs.joke }}{% endraw %}
```
The workflow will run on every issue comment created event. If the comment starts with `/joke`, it will execute the Dad Jokes action and post the joke as a comment in the same issue.
diff --git a/.github/workflows/0-start-exercise.yml b/.github/workflows/0-start-exercise.yml
index ed2372f..9344d46 100644
--- a/.github/workflows/0-start-exercise.yml
+++ b/.github/workflows/0-start-exercise.yml
@@ -50,7 +50,6 @@ jobs:
issue-number: ${{ env.ISSUE_NUMBER }}
file: ${{ env.STEP_1_FILE }}
vars: |
- login: ${{ github.actor }}
full_repo_name: ${{ github.repository }}
- name: Create comment - watching for progress
diff --git a/.github/workflows/1-step.yml b/.github/workflows/1-step.yml
index 76c0a14..f87d53f 100644
--- a/.github/workflows/1-step.yml
+++ b/.github/workflows/1-step.yml
@@ -75,13 +75,21 @@ jobs:
text-file: package.json
keyphrase: "@actions/core"
- - name: Check for @actions/github dependency
- id: check-github-dep
+ - name: Check for request dependency
+ id: check-request-dep
continue-on-error: true
uses: skills/action-keyphrase-checker@v1
with:
text-file: package.json
- keyphrase: "@actions/github"
+ keyphrase: "request"
+
+ - name: Check for request-promise dependency
+ id: check-request-promise-dep
+ continue-on-error: true
+ uses: skills/action-keyphrase-checker@v1
+ with:
+ text-file: package.json
+ keyphrase: "request-promise"
- name: Check for @vercel/ncc dependency
id: check-ncc-dep
@@ -129,8 +137,10 @@ jobs:
passed: ${{ steps.check-package-json.outcome == 'success' }}
- description: "@actions/core dependency present"
passed: ${{ steps.check-core-dep.outcome == 'success' }}
- - description: "@actions/github dependency present"
- passed: ${{ steps.check-github-dep.outcome == 'success' }}
+ - description: "request dependency present"
+ passed: ${{ steps.check-request-dep.outcome == 'success' }}
+ - description: "request-promise dependency present"
+ passed: ${{ steps.check-request-promise-dep.outcome == 'success' }}
- description: "@vercel/ncc dependency present"
passed: ${{ steps.check-ncc-dep.outcome == 'success' }}
- description: ".gitignore excludes node_modules/"
diff --git a/.github/workflows/2-step.yml b/.github/workflows/2-step.yml
index bd0237d..07b3f93 100644
--- a/.github/workflows/2-step.yml
+++ b/.github/workflows/2-step.yml
@@ -85,9 +85,9 @@ jobs:
vars: |
step_number: 2
results_table:
- - description: "src/main.js exists"
+ - description: "Checked for src/main.js file"
passed: ${{ steps.check-main-js.outcome == 'success' }}
- - description: "src/joke.js exists"
+ - description: "Checked for src/joke.js file"
passed: ${{ steps.check-joke-js.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/5-step.yml b/.github/workflows/5-step.yml
index d945f67..90622f9 100644
--- a/.github/workflows/5-step.yml
+++ b/.github/workflows/5-step.yml
@@ -74,13 +74,13 @@ jobs:
text-file: .github/workflows/joke-action.yml
keyphrase: issue_comment
- - name: Check workflow references steps.get_joke.outputs.joke
- id: check-output-reference
+ - name: Check workflow has "Joke Action" name
+ id: check-joke-action-name
continue-on-error: true
uses: skills/action-keyphrase-checker@v1
with:
text-file: .github/workflows/joke-action.yml
- keyphrase: steps.get_joke.outputs.joke
+ keyphrase: "Joke Action"
- name: Update comment - step results
uses: GrantBirki/comment@v2.1.1
@@ -97,8 +97,8 @@ jobs:
passed: ${{ steps.check-joke-workflow.outcome == 'success' }}
- description: "issue_comment trigger present"
passed: ${{ steps.check-issue-comment-trigger.outcome == 'success' }}
- - description: "Output reference steps.get_joke.outputs.joke present"
- passed: ${{ steps.check-output-reference.outcome == 'success' }}
+ - description: "workflow name should be 'Joke Action'"
+ passed: ${{ steps.check-joke-action-name.outcome == 'success' }}
# END: Check practical exercise
diff --git a/.github/workflows/6-step.yml b/.github/workflows/6-step.yml
index e2c3303..94592af 100644
--- a/.github/workflows/6-step.yml
+++ b/.github/workflows/6-step.yml
@@ -18,82 +18,13 @@ env:
jobs:
find_exercise:
+ if: github.event.workflow_run.conclusion == 'success'
name: Find Exercise Issue
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
- check_step_work:
- name: Check step work
- runs-on: ubuntu-latest
+ post_review_content:
+ name: Post review content
needs: [find_exercise]
- env:
- ISSUE_REPOSITORY: ${{ github.repository }}
- ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
-
- steps:
- - name: Checkout
- uses: actions/checkout@v5
-
- - name: Get response templates
- uses: actions/checkout@v5
- with:
- repository: skills/exercise-toolkit
- path: exercise-toolkit
- ref: v0.7.0
-
- - name: Find last comment
- id: find-last-comment
- uses: peter-evans/find-comment@v3
- with:
- repository: ${{ env.ISSUE_REPOSITORY }}
- issue-number: ${{ env.ISSUE_NUMBER }}
- direction: last
-
- - name: Update comment - checking work
- uses: GrantBirki/comment@v2.1.1
- with:
- repository: ${{ env.ISSUE_REPOSITORY }}
- issue-number: ${{ env.ISSUE_NUMBER }}
- comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
- file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
- edit-mode: replace
-
- # START: Check practical exercise
-
- - name: Check Joke Action workflow run success
- id: check-joke-run
- continue-on-error: true
- run: |
- if [ "${{ github.event.workflow_run.conclusion }}" = "success" ]; then
- echo "Joke Action workflow run was successful"
- exit 0
- else
- echo "Joke Action workflow run conclusion: ${{ github.event.workflow_run.conclusion }}"
- exit 1
- fi
-
- - name: Update comment - step results
- uses: GrantBirki/comment@v2.1.1
- with:
- repository: ${{ env.ISSUE_REPOSITORY }}
- issue-number: ${{ env.ISSUE_NUMBER }}
- comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
- edit-mode: replace
- file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
- vars: |
- step_number: 6
- results_table:
- - description: "Joke Action workflow run concluded successfully"
- passed: ${{ steps.check-joke-run.outcome == 'success' }}
-
- # END: Check practical exercise
-
- - name: Fail job if not all checks passed
- if: contains(steps.*.outcome, 'failure')
- run: exit 1
-
- finish_exercise:
- name: Finish exercise
- needs: [find_exercise, check_step_work]
runs-on: ubuntu-latest
env:
ISSUE_REPOSITORY: ${{ github.repository }}
@@ -110,14 +41,12 @@ jobs:
path: exercise-toolkit
ref: v0.7.0
- - name: Create comment - step finished
+ - name: Create comment - step finished - final review next
uses: GrantBirki/comment@v2.1.1
with:
repository: ${{ env.ISSUE_REPOSITORY }}
issue-number: ${{ env.ISSUE_NUMBER }}
- file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
- vars: |
- next_step_number: finish
+ file: exercise-toolkit/markdown-templates/step-feedback/lesson-review.md
- name: Create comment - add review content
uses: GrantBirki/comment@v2.1.1
@@ -126,15 +55,15 @@ jobs:
issue-number: ${{ env.ISSUE_NUMBER }}
file: ${{ env.REVIEW_FILE }}
- - name: Create comment - exercise finished
- uses: GrantBirki/comment@v2.1.1
- with:
- repository: ${{ env.ISSUE_REPOSITORY }}
- issue-number: ${{ env.ISSUE_NUMBER }}
- file: exercise-toolkit/markdown-templates/step-feedback/exercise-finished.md
-
- name: Disable current workflow
- run: |
- gh workflow disable "${{github.workflow}}"
+ run: gh workflow disable "${{github.workflow}}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ finish_exercise:
+ name: Finish Exercise
+ needs: [find_exercise]
+ uses: skills/exercise-toolkit/.github/workflows/finish-exercise.yml@v0.7.0
+ with:
+ issue-url: ${{ needs.find_exercise.outputs.issue-url }}
+ exercise-title: "Write JavaScript Actions"
diff --git a/.gitignore b/.gitignore
index 81d726e..f966d66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,5 @@
ehthumbs.db
Thumbs.db
-# Node modules #
-################
-node_modules/
\ No newline at end of file
+# Add Node modules below #
+################
\ No newline at end of file
From 5210d7499cf1f0e9b15e676545235d9da2a3aa7c Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Wed, 12 Nov 2025 11:01:04 +0100
Subject: [PATCH 06/15] Theory updates (#2)
---
.github/steps/1-step.md | 12 ++++--
.github/steps/2-step.md | 81 +++++++++++++--------------------------
.github/steps/3-step.md | 32 +++++++++++-----
.github/steps/4-step.md | 61 ++++++++++++++++++++++-------
.github/steps/5-step.md | 22 +++++++----
.github/steps/6-step.md | 29 ++++++++++++--
.github/steps/x-review.md | 43 ++++++++-------------
README.md | 15 ++++----
8 files changed, 170 insertions(+), 125 deletions(-)
diff --git a/.github/steps/1-step.md b/.github/steps/1-step.md
index 518b06c..204e367 100644
--- a/.github/steps/1-step.md
+++ b/.github/steps/1-step.md
@@ -1,8 +1,14 @@
-## Step 1: Initializing the Dad Jokes GitHub Action
+## Step 1: Setting up the project
-Imagine you have a repetitive task that you want to automate. You've searched through the [**GitHub Marketplace**](https://github.com/marketplace?type=actions) to see if there are any existing actions that suit your needs, but found nothing - because your task is very specific: **generating DAD JOKES**! 🎭
+Imagine you’ve got a repetitive task you’d love to automate. You've searched through the [**GitHub Marketplace**](https://github.com/marketplace?type=actions) for existing actions that might help, you come up empty-handed…
-Since no pre-built action exists for your quirky automation needs, it's time to roll up your sleeves and create your own
+Maybe that’s because your task is a bit _too_ unique 😆
+
+**GENERATING DAD JOKES**! 🎭
+
+
+
+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
diff --git a/.github/steps/2-step.md b/.github/steps/2-step.md
index 912172c..b66a16b 100644
--- a/.github/steps/2-step.md
+++ b/.github/steps/2-step.md
@@ -1,14 +1,21 @@
## Step 2: Create Source Files & Run Locally
-### 📖 Theory
+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](https://github.com/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](https://github.com/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](https://github.com/actions/toolkit) repository for more.
-Author the action’s core logic and verify it runs locally before bundling.
### ⌨️ Activity: Implement the Dad Jokes Action
Now that your project is initialized and dependencies are installed, it's time to create the source files for your Dad Jokes GitHub Action.
-
1. Create `src/` directory to hold your GitHub Action JavaScript files:
```sh
@@ -38,20 +45,26 @@ Now that your project is initialized and dependencies are installed, it's time t
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.
+
1. Create `src/main.js` that will be the main entry point for your action:
- ```js
- const getJoke = require("./joke");
- const core = require("@actions/core");
+ ```js
+ const getJoke = require("./joke");
+ const core = require("@actions/core");
- async function run() {
- const joke = await getJoke();
- console.log(joke);
- core.setOutput("joke-output", joke);
- }
+ async function run() {
+ const joke = await getJoke();
+ console.log(joke);
+ core.setOutput("joke", joke);
+ }
- run();
- ```
+ run();
+ ```
+
+ We call the `getJoke` function and call the `core.setOutput()` method to set the `joke` output of your GitHub Action.
1. Run the action locally to verify it works:
@@ -59,7 +72,7 @@ Now that your project is initialized and dependencies are installed, it's time t
node src/main.js
```
-
+
1. Commit and push:
@@ -68,43 +81,3 @@ Now that your project is initialized and dependencies are installed, it's time t
git commit -m "Add Dad Joke action source files"
git push
```
-
-### 🛠 Activity (Optional): Debug your action
-
->[!NOTE]
-> This activity is optional and not required to complete the exercise.
->
-> Learning how to debug your action code can be very helpful!
-
-
-Show steps
-
-1. Install dev dependency:
-
- ```sh
- npm install -D @github/local-action
- ```
-
-1. Create `.vscode/launch.json`:
-
- ```json
- {
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Debug Action",
- "type": "node",
- "request": "launch",
- "runtimeExecutable": "npx",
- "cwd": "${workspaceRoot}",
- "args": ["@github/local-action", ".", "src/main.js"],
- "console": "integratedTerminal",
- "skipFiles": ["/**", "node_modules/**"]
- }
- ]
- }
- ```
-
-1. Set breakpoints in `src/main.js` and start the "Debug Action" configuration.
-
-
diff --git a/.github/steps/3-step.md b/.github/steps/3-step.md
index 1f07648..89918a9 100644
--- a/.github/steps/3-step.md
+++ b/.github/steps/3-step.md
@@ -1,25 +1,37 @@
## Step 3: Bundle the Action
-### 📖 Theory: Bundling the action
+Good job! :tada:
+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 build script to `package.json` (inside the existing scripts block or create one):
- ```json
- "scripts": {
- "build": "ncc build src/main.js -o dist"
- }
-
- ```
+ ```json
+ "scripts": {
+ "build": "ncc build src/main.js -o dist"
+ }
+ ```
1. Run the build command. This should create a `dist/` directory with a bundled `index.js` file:
- ```sh
- npm run build
- ```
+ ```sh
+ npm run build
+ ```
+
+1. (optional) Run the bundled action to verify it works:
+
+ ```sh
+ node dist/index.js
+ ```
1. Commit and push the changes to the `main` branch:
diff --git a/.github/steps/4-step.md b/.github/steps/4-step.md
index 5f5920e..d740e05 100644
--- a/.github/steps/4-step.md
+++ b/.github/steps/4-step.md
@@ -1,26 +1,61 @@
## Step 4: Add Action Metadata
-### 📖 Theory
+Great work! :tada: You've successfully bundled your Dad Jokes GitHub Action into a single file.
-Define the action’s interface (name, description, outputs, runtime, main entry) via `action.yml` pointing to the bundled 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:
+
+- **Filename**: Must be `action.yml`
+- **Required for**: All actions types - JavaScript, Docker container, and composite actions
+- **Format**: Written in YAML syntax
+
+#### 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 other actions can use after this action runs. | ❌ |
+| **`runs`** | Tells GitHub how to execute your action. | ✅ |
+| **`branding`** | Optional 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](https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax).
+
+---
### ⌨️ Activity: Create Metadata File
1. Create `action.yml` at the repository root (same level as `package.json`).
- ```yaml
- name: "Joke Action"
- description: "Fetches a random joke and exposes it as an output"
-
- outputs:
- joke:
- description: "The fetched joke text"
+ ```yaml
+ name: "Joke Action"
+ description: "Fetches a random joke and exposes it as an output"
- runs:
- using: node24
- main: dist/index.js
- ```
+ outputs:
+ joke:
+ description: "The fetched joke text"
+ runs:
+ using: node24
+ main: dist/index.js
+ ```
1. Commit and push:
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index 9f56e25..56163a4 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -1,11 +1,13 @@
## Step 5: Create Workflow & Consume Output
-### 📖 Theory
+Well done! :clap: You've created the Dad Jokes GitHub Action and defined its metadata.
-Use a workflow triggered by `issue_comment` to run the local action and then post the retrieved joke as a comment.
+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
```txt
@@ -17,10 +19,10 @@ Use a workflow triggered by `issue_comment` to run the local action and then pos
```yaml
name: Joke Action
on:
- issue_comment:
- types: [created]
+ issue_comment:
+ types: [created]
- permissions:
+ permissions:
issues: write
contents: read
@@ -40,6 +42,12 @@ Use a workflow triggered by `issue_comment` to run the local action and then pos
body: {% raw %}${{ steps.get-joke.outputs.joke }}{% endraw %}
```
- The workflow will run on every issue comment created event. If the comment starts with `/joke`, it will execute the Dad Jokes action and post the joke as a comment in the same issue.
+ This workflow triggers when someone comments `/joke` on an issue and responds with a joke!
+
+1. Commit and push the workflow file to the `main` branch:
-1. Commit and push the workflow file to the `main`:
+ ```sh
+ git add .github/workflows/joke-action.yml
+ git commit -m "Add workflow to test joke action"
+ git push
+ ```
diff --git a/.github/steps/6-step.md b/.github/steps/6-step.md
index e786dbd..631542f 100644
--- a/.github/steps/6-step.md
+++ b/.github/steps/6-step.md
@@ -1,9 +1,30 @@
## Step 6: Trigger & Validate
+Awesome! :rocket: 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!
+### ⌨️ Activity: Try out your action
-1. Create a comment in this issue (or create a new one) with the text `/joke`
-1. Monitor the `actions` tab for the "Joke Action" workflow run to complete.
-1. After it completes you should see a new comment posted by the bot with the dad joke!
+1. Create a comment in this issue (or create a new one) with the text `/joke`
+
+1. Monitor the **Actions** tab for the "Joke Action" workflow run to complete:
+ - Click on the **Actions** tab in your repository
+ - Look for a new workflow run titled "Joke Action"
+ - The run should show a green checkmark when completed successfully
+
+1. Return to the issue and you should see a new comment posted by `github-actions[bot]` containing a random dad joke!
+
+1. Mona will post the review of the exercise once the 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
+
+
diff --git a/.github/steps/x-review.md b/.github/steps/x-review.md
index 58521c1..427aa01 100644
--- a/.github/steps/x-review.md
+++ b/.github/steps/x-review.md
@@ -1,34 +1,23 @@
-
+## Review
-## Finish
+_Congratulations, you've completed this exercise and learned how to write JavaScript GitHub Actions!_
-
+
-### Congratulations, you've completed this course!
+Here's a recap of your accomplishments:
-In this course, you've learned a lot about developing custom actions using JavaScript and Actions Toolkit.
-
-## Publishing your actions
-
-Publishing your actions is a great way to help others in your team and across the GitHub community. Although actions do not need to be published to be consumed, by adding them to the marketplace you make them easier to find.
-
-Some notable actions you will find on the marketplace are:
-
-- [Actions for Discord](https://github.com/marketplace/actions/actions-for-discord)
-- [GitHub Action for Slack](https://github.com/marketplace/actions/github-action-for-slack)
-- [Jekyll action](https://github.com/marketplace/actions/jekyll-action)
-- [Run Jest](https://github.com/marketplace/actions/run-jest)
-
-And that just scratches the surface of the 1600+ and counting actions you will find on the marketplace
-
-Follow [this guide](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/publishing-actions-in-github-marketplace#publishing-an-action) to learn how to publish your actions to the GitHub Marketplace
+- **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?
-- [Take another GitHub Skills course](https://github.com/skills).
-- We'd love to hear what you thought of this course in our [discussion board](https://github.com/orgs/skills/discussions/categories/write-javascript-actions).
-- [Read the GitHub Getting Started docs](https://docs.github.com/en/get-started).
-- To find projects to contribute to, check out [GitHub Explore](https://github.com/explore).
+- Check out the other [GitHub Skills exercises](https://learn.github.com/skills).
+- Try using your Dad Jokes action in your other repositories to add some humor to your workflows!
+
+- **Create your next action** using GitHub's template repositories with best practices like tests and linting already built-in:
+ - [actions/javascript-action](https://github.com/actions/javascript-action) template repository
+ - [actions/typescript-action](https://github.com/actions/typescript-action) template repository
\ No newline at end of file
diff --git a/README.md b/README.md
index 2b296fe..35c4ecd 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,10 @@ _Write your own GitHub JavaScript Action and automate customized tasks unique to
## Welcome
- **Who is this for**: Developers, GitHub users, users new to Git, students, managers, and for teams.
-- **What you'll learn**: How to consume actions within a workflow file, create custom JavaScript based actions and publish your newly created action to the marketplace.
-- **What you'll build**: A custom JavaScript-based GitHub Action that can be published to the marketplace.
+- **What you'll learn**: How to create custom JavaScript-based GitHub Actions, bundle them for distribution, and use them in workflows.
+- **What you'll build**: A Dad Jokes GitHub Action that fetches random jokes and responds to issue comments.
- **Prerequisites**:
+
- You should be familiar with GitHub and GitHub Actions. We recommend taking the [Hello GitHub Actions](https://github.com/skills-dev/hello-github-actions) exercise first.
- **How long**: This exercise takes about 1 hour to complete.
@@ -15,11 +16,11 @@ _Write your own GitHub JavaScript Action and automate customized tasks unique to
In this exercise, you will:
1. Initialize a JavaScript project
-2. Configure an action
-3. Create a metadata file
-4. Create JavaScript files
-5. Add actions to workflow file
-6. Trigger action
+2. Create JavaScript source files for a Dad Jokes action
+3. Bundle your action into a distributable file
+4. Create action metadata with `action.yml`
+5. Author a workflow that uses your custom action
+6. Test your action by triggering it with issue comments
### How to start this exercise
From b740fde44f1b1a721fe6b51909cdd714fd92eeea Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Wed, 12 Nov 2025 10:34:21 +0000
Subject: [PATCH 07/15] Test run updates
---
.github/steps/2-step.md | 12 +++---------
.github/steps/3-step.md | 1 -
.github/steps/5-step.md | 4 +++-
.github/steps/6-step.md | 2 +-
.github/workflows/6-step.yml | 2 +-
5 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/.github/steps/2-step.md b/.github/steps/2-step.md
index b66a16b..77933da 100644
--- a/.github/steps/2-step.md
+++ b/.github/steps/2-step.md
@@ -14,13 +14,9 @@ The `@actions/core` library is the main library from the [GitHub Actions Toolkit
### ⌨️ Activity: Implement the Dad Jokes Action
-Now that your project is initialized and dependencies are installed, it's time to create the source files for your Dad Jokes GitHub Action.
+Let's create the source files and implement the logic for your action.
-1. Create `src/` directory to hold your GitHub Action JavaScript files:
-
- ```sh
- mkdir src
- ```
+1. Create `src/` directory to hold your JavaScript files:
1. Create `src/joke.js` file to hold the logic for fetching a joke from the `icanhazdadjoke.com` API:
@@ -64,7 +60,7 @@ Now that your project is initialized and dependencies are installed, it's time t
run();
```
- We call the `getJoke` function and call the `core.setOutput()` method to set the `joke` output of your GitHub Action.
+ We call the `getJoke` function and follow up with `core.setOutput()` to set the `joke` output of your GitHub Action.
1. Run the action locally to verify it works:
@@ -72,8 +68,6 @@ Now that your project is initialized and dependencies are installed, it's time t
node src/main.js
```
-
-
1. Commit and push:
```sh
diff --git a/.github/steps/3-step.md b/.github/steps/3-step.md
index 89918a9..41a1cf9 100644
--- a/.github/steps/3-step.md
+++ b/.github/steps/3-step.md
@@ -10,7 +10,6 @@ When someone uses your action in their workflow, GitHub downloads and executes i
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 build script to `package.json` (inside the existing scripts block or create one):
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index 56163a4..1f931fb 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -42,7 +42,9 @@ Let's see your Dad Jokes action in action by creating a GitHub Actions workflow
body: {% raw %}${{ steps.get-joke.outputs.joke }}{% endraw %}
```
- This workflow triggers when someone comments `/joke` on an issue and responds with a 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`.
1. Commit and push the workflow file to the `main` branch:
diff --git a/.github/steps/6-step.md b/.github/steps/6-step.md
index 631542f..d960831 100644
--- a/.github/steps/6-step.md
+++ b/.github/steps/6-step.md
@@ -6,7 +6,7 @@ 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 one) with the text `/joke`
+1. Create a comment in this issue (or create a new issue) with the text `/joke`
1. Monitor the **Actions** tab for the "Joke Action" workflow run to complete:
- Click on the **Actions** tab in your repository
diff --git a/.github/workflows/6-step.yml b/.github/workflows/6-step.yml
index 94592af..aa87f26 100644
--- a/.github/workflows/6-step.yml
+++ b/.github/workflows/6-step.yml
@@ -9,7 +9,7 @@ on:
- completed
permissions:
- contents: read
+ contents: write
actions: write
issues: write
From d93092e9066caff88b0f9d11be2a425e1949521f Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Wed, 12 Nov 2025 15:33:57 +0100
Subject: [PATCH 08/15] Revise README for clarity and time estimate
Updated the project description and estimated completion time.
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 35c4ecd..77be2f2 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,12 @@ _Write your own GitHub JavaScript Action and automate customized tasks unique to
- **Who is this for**: Developers, GitHub users, users new to Git, students, managers, and for teams.
- **What you'll learn**: How to create custom JavaScript-based GitHub Actions, bundle them for distribution, and use them in workflows.
-- **What you'll build**: A Dad Jokes GitHub Action that fetches random jokes and responds to issue comments.
+- **What you'll build**: A Javascript based GitHub Action that fetches random dad jokes and exposes them as an output.
- **Prerequisites**:
- You should be familiar with GitHub and GitHub Actions. We recommend taking the [Hello GitHub Actions](https://github.com/skills-dev/hello-github-actions) exercise first.
-- **How long**: This exercise takes about 1 hour to complete.
+- **How long**: This exercise takes less than 1 hour to complete.
In this exercise, you will:
From 053165177902d0cf76d20c2c05bf66d18d6f3e2e Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 10:02:41 +0000
Subject: [PATCH 09/15] Step 1-3 review updates
---
.github/steps/1-step.md | 6 +++++-
.github/steps/2-step.md | 2 ++
.github/steps/3-step.md | 4 +++-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/.github/steps/1-step.md b/.github/steps/1-step.md
index 204e367..d1b67bf 100644
--- a/.github/steps/1-step.md
+++ b/.github/steps/1-step.md
@@ -57,9 +57,11 @@ Now that your Codespace is ready, let's initialize a new Node.js project and ins
npm install request request-promise @actions/core @vercel/ncc
```
+ > 🪧 **Note:** You will learn each library purpose in the next steps
+
1. Review `package.json` to confirm dependencies are listed in the `dependencies` section.
-1. Open the `.gitignore` file and add an entry to exclude the `node_modules` directory from being tracked by git:
+1. Open the `.gitignore` file and add an entry to exclude the `node_modules` directory from being tracked by Git:
```text
node_modules/
@@ -78,6 +80,8 @@ Now that your Codespace is ready, let's initialize a new Node.js project and ins
git push
```
+1. With the changes pushed to GitHub, Mona will check your work and share the next steps.
+
Having trouble? 🤷
diff --git a/.github/steps/2-step.md b/.github/steps/2-step.md
index 77933da..03038db 100644
--- a/.github/steps/2-step.md
+++ b/.github/steps/2-step.md
@@ -75,3 +75,5 @@ Let's create the source files and implement the logic for your action.
git commit -m "Add Dad Joke action source files"
git push
```
+
+1. With the changes pushed to GitHub, Mona will check your work and share the next steps.
diff --git a/.github/steps/3-step.md b/.github/steps/3-step.md
index 41a1cf9..f36c790 100644
--- a/.github/steps/3-step.md
+++ b/.github/steps/3-step.md
@@ -12,10 +12,11 @@ Rather than committing your `node_modules` directory (which causes problems with
### ⌨️ Activity: Build Setup & Bundle
-1. Add a build script to `package.json` (inside the existing scripts block or create one):
+1. Add a new `build` script to `package.json` (inside the existing `scripts` object):
```json
"scripts": {
+ // Existing scripts...
"build": "ncc build src/main.js -o dist"
}
```
@@ -39,3 +40,4 @@ Rather than committing your `node_modules` directory (which causes problems with
git commit -m "Add ncc build script and bundled dist/index.js"
git push
```
+1. With the changes pushed to GitHub, Mona will check your work and share the next steps.
\ No newline at end of file
From b41d11fc6c4d9c96da779b6c11a8f412321c62be Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 11:03:01 +0100
Subject: [PATCH 10/15] Apply suggestion from @chriswblake
Co-authored-by: Christopher W. Blake
---
.github/steps/4-step.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/steps/4-step.md b/.github/steps/4-step.md
index d740e05..d4963c2 100644
--- a/.github/steps/4-step.md
+++ b/.github/steps/4-step.md
@@ -13,7 +13,7 @@ Every GitHub Action requires a metadata file that defines how the action should
The metadata file has specific requirements:
- **Filename**: Must be `action.yml`
-- **Required for**: All actions types - JavaScript, Docker container, and composite actions
+- **Required for**: All actions types - JavaScript, [Docker container](https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action), and [composite action](https://docs.github.com/en/actions/tutorials/create-actions/create-a-composite-action)
- **Format**: Written in YAML syntax
#### Core Metadata Parameters
From a142a8e606d6fa80f7b69aecb4e1bea0f278dff1 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 10:39:13 +0000
Subject: [PATCH 11/15] fix: update action metadata requirements and workflow
example
---
.github/steps/4-step.md | 8 ++++----
.github/steps/5-step.md | 2 ++
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/.github/steps/4-step.md b/.github/steps/4-step.md
index d4963c2..2c2adcb 100644
--- a/.github/steps/4-step.md
+++ b/.github/steps/4-step.md
@@ -22,11 +22,11 @@ The metadata file has specific requirements:
| ----------------- | -------------------------------------------------------------- | :------: |
| **`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 other actions can use after this action runs. | ❌ |
+| **`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`** | Optional color and icon for your action in GitHub Marketplace. | ❌ |
+| **`branding`** | Color and icon for your action in GitHub Marketplace. | ○ |
#### JavaScript Action `runs` Configuration
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index 1f931fb..719ac0b 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -18,6 +18,8 @@ Let's see your Dad Jokes action in action by creating a GitHub Actions workflow
```yaml
name: Joke Action
+ run-name: {% raw %}Dad Joke for issue ${{ github.event.issue.number }} by ${{ github.event.comment.user.login }}{% endraw %}
+
on:
issue_comment:
types: [created]
From 27666af09d569d51a5a8bf7296f123d63f327a71 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 11:39:49 +0100
Subject: [PATCH 12/15] Apply suggestion from @chriswblake
Co-authored-by: Christopher W. Blake
---
.github/steps/6-step.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/steps/6-step.md b/.github/steps/6-step.md
index d960831..c1b30a2 100644
--- a/.github/steps/6-step.md
+++ b/.github/steps/6-step.md
@@ -15,7 +15,7 @@ The only thing left to do is test it out!
1. Return to the issue and you should see a new comment posted by `github-actions[bot]` containing a random dad joke!
-1. Mona will post the review of the exercise once the workflow completes **successfully**!
+1. Mona will post the exercise review once your new Dad Joke workflow completes **successfully**!
Having trouble? 🤷
From 8e6d2ad79550cdad5530ae1cd3bcf62bedef3fc4 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 11:43:36 +0100
Subject: [PATCH 13/15] Revise monitoring steps for Joke Action workflow
Updated instructions for monitoring the Joke Action workflow.
---
.github/steps/6-step.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/steps/6-step.md b/.github/steps/6-step.md
index c1b30a2..9e67037 100644
--- a/.github/steps/6-step.md
+++ b/.github/steps/6-step.md
@@ -8,10 +8,10 @@ The only thing left to do is test it out!
1. Create a comment in this issue (or create a new issue) with the text `/joke`
-1. Monitor the **Actions** tab for the "Joke Action" workflow run to complete:
- - Click on the **Actions** tab in your repository
- - Look for a new workflow run titled "Joke Action"
- - The run should show a green checkmark when completed successfully
+1. Monitor the **Actions** tab for the `Joke Action` workflow to complete:
+
+
+
1. Return to the issue and you should see a new comment posted by `github-actions[bot]` containing a random dad joke!
From 42805bbcf1fd6482d20971c6c087ff4c5e626984 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 11:44:44 +0100
Subject: [PATCH 14/15] Update exercise copy link in README
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 77be2f2..73f7aca 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ In this exercise, you will:
Simply copy the exercise to your account, then give your favorite Octocat (Mona) **about 20 seconds** to prepare the first lesson, then **refresh the page**.
-[](https://github.com/new?template_owner=FidelusAleksander&template_name=write-javascript-actions&owner=%40me&name=skills-write-javascript-actions&description=Exercise:+Write+JavaScript+Actions&visibility=public)
+[](https://github.com/new?template_owner=skills-dev&template_name=write-javascript-actions&owner=%40me&name=skills-write-javascript-actions&description=Exercise:+Write+JavaScript+Actions&visibility=public)
Having trouble? 🤷
From f7c937da9aec896aa44b8d236ee33671e544adb7 Mon Sep 17 00:00:00 2001
From: Aleksander Fidelus <63016446+FidelusAleksander@users.noreply.github.com>
Date: Thu, 13 Nov 2025 10:48:59 +0000
Subject: [PATCH 15/15] Add mona comments for next steps
---
.github/steps/3-step.md | 1 +
.github/steps/4-step.md | 6 ++++--
.github/steps/5-step.md | 3 +++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/.github/steps/3-step.md b/.github/steps/3-step.md
index f36c790..f7f360b 100644
--- a/.github/steps/3-step.md
+++ b/.github/steps/3-step.md
@@ -40,4 +40,5 @@ Rather than committing your `node_modules` directory (which causes problems with
git commit -m "Add ncc build script and bundled dist/index.js"
git push
```
+
1. With the changes pushed to GitHub, Mona will check your work and share the next steps.
\ No newline at end of file
diff --git a/.github/steps/4-step.md b/.github/steps/4-step.md
index 2c2adcb..3f454d4 100644
--- a/.github/steps/4-step.md
+++ b/.github/steps/4-step.md
@@ -57,10 +57,12 @@ For JavaScript actions, the `runs` section needs:
main: dist/index.js
```
-1. Commit and push:
+1. Commit and push the action metadata file to the `main` branch:
```sh
git add action.yml
- git commit -m "Add action metadata referencing dist/index.js"
+ git commit -m "Add action metadata file"
git push
```
+
+1. With the changes pushed to GitHub, Mona will check your work and share the next steps.
\ No newline at end of file
diff --git a/.github/steps/5-step.md b/.github/steps/5-step.md
index 719ac0b..a0e7775 100644
--- a/.github/steps/5-step.md
+++ b/.github/steps/5-step.md
@@ -55,3 +55,6 @@ Let's see your Dad Jokes action in action by creating a GitHub Actions workflow
git commit -m "Add workflow to test joke action"
git push
```
+
+
+1. With the workflow pushed to GitHub, Mona will check your work and share the next steps.
\ No newline at end of file