├── .github ├── steps │ ├── 1-step.md │ ├── 2-step.md │ ├── 3-step.md │ └── x-review.md └── workflows │ ├── 0-start-exercise.yml │ ├── 1-step.yml │ └── 2-step.yml ├── .gitignore ├── LICENSE └── README.md /.github/steps/1-step.md: -------------------------------------------------------------------------------- 1 | ## Step 1: (replace-me: STEP-NAME) 2 | 3 | (replace-me: OPTIONAL Brief story or scenario to introduce the step) 4 | 5 | ### 📖 Theory: (replace-me: Theory title) 6 | 7 | 8 | 12 | 13 | (replace-me: Optional theory or background information relevant to this step) 14 | 15 | ### ⌨️ Activity: (replace-me: Activity title) 16 | 17 | 1. (replace-me: First instruction) 18 | 1. (replace-me: Second instruction) 19 | 1. (replace-me: Additional instructions as needed) 20 | 21 |
22 | Having trouble? 🤷
23 | 24 | - (replace-me: Troubleshooting tip or hint) 25 | - (replace-me: Additional troubleshooting tips as needed) 26 | 27 |
28 | -------------------------------------------------------------------------------- /.github/steps/2-step.md: -------------------------------------------------------------------------------- 1 | ## Step 2: (replace-me: STEP-NAME) 2 | 3 | (replace-me: OPTIONAL Brief story or scenario to introduce the step) 4 | 5 | ### 📖 Theory: (replace-me: Theory title) 6 | 7 | 8 | 12 | 13 | (replace-me: Optional theory or background information relevant to this step) 14 | 15 | ### ⌨️ Activity: (replace-me: Activity title) 16 | 17 | 1. (replace-me: First instruction) 18 | 1. (replace-me: Second instruction) 19 | 1. (replace-me: Additional instructions as needed) 20 | 21 |
22 | Having trouble? 🤷
23 | 24 | - (replace-me: Troubleshooting tip or hint) 25 | - (replace-me: Additional troubleshooting tips as needed) 26 | 27 |
28 | -------------------------------------------------------------------------------- /.github/steps/3-step.md: -------------------------------------------------------------------------------- 1 | ## Step 3: (replace-me: STEP-NAME) 2 | 3 | (replace-me: OPTIONAL Brief story or scenario to introduce the step) 4 | 5 | ### 📖 Theory: (replace-me: Theory title) 6 | 7 | 8 | 12 | 13 | (replace-me: Optional theory or background information relevant to this step) 14 | 15 | ### ⌨️ Activity: (replace-me: Activity title) 16 | 17 | 1. (replace-me: First instruction) 18 | 1. (replace-me: Second instruction) 19 | 1. (replace-me: Additional instructions as needed) 20 | 21 |
22 | Having trouble? 🤷
23 | 24 | - (replace-me: Troubleshooting tip or hint) 25 | - (replace-me: Additional troubleshooting tips as needed) 26 | 27 |
28 | -------------------------------------------------------------------------------- /.github/steps/x-review.md: -------------------------------------------------------------------------------- 1 | ## Review 2 | 3 | _Congratulations, you've completed this exercise and learned a lot about (replace-me: feature/product that was taught in this exercise) 4 | 5 | celebrate 6 | 7 | Here's a recap of your accomplishments: 8 | 9 | - (replace-me: Accomplishment #1) 10 | - (replace-me: Accomplishment #N) 11 | 12 | ### What's next? 13 | 14 | - (replace-me: Natural follow up Skills exercise - if there is one) 15 | - (replace-me: Documentation link to learn more about the feature) 16 | - (replace-me: Other resources or calls to action) 17 | -------------------------------------------------------------------------------- /.github/workflows/0-start-exercise.yml: -------------------------------------------------------------------------------- 1 | name: Step 0 # Start Exercise 2 | 3 | on: 4 | workflow_dispatch: 5 | # NOTE: Make sure the repository is a template before enabling this trigger. 6 | # push: 7 | # branches: 8 | # - main 9 | 10 | permissions: 11 | contents: write 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | STEP_1_FILE: ".github/steps/1-step.md" 17 | 18 | jobs: 19 | start_exercise: 20 | if: | 21 | !github.event.repository.is_template 22 | name: Start Exercise 23 | uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.5.0 24 | with: 25 | exercise-title: "(replace-me: Exercise title)" 26 | intro-message: "(replace-me: Brief one line introduction message for the exercise)" 27 | 28 | post_next_step_content: 29 | name: Post next step content 30 | runs-on: ubuntu-latest 31 | needs: [start_exercise] 32 | env: 33 | ISSUE_URL: ${{ needs.start_exercise.outputs.issue-url }} 34 | 35 | steps: 36 | - name: Checkout 37 | uses: actions/checkout@v4 38 | 39 | - name: Get response templates 40 | uses: actions/checkout@v4 41 | with: 42 | repository: skills/exercise-toolkit 43 | path: exercise-toolkit 44 | ref: v0.5.0 45 | 46 | - name: Build comment - add step content 47 | id: build-comment 48 | uses: skills/action-text-variables@v2 49 | with: 50 | template-file: ${{ env.STEP_1_FILE }} 51 | template-vars: | 52 | login: ${{ github.actor }} 53 | full_repo_name: ${{ github.repository }} 54 | 55 | - name: Create comment - add step content 56 | run: | 57 | gh issue comment "$ISSUE_URL" \ 58 | --body "$ISSUE_BODY" 59 | env: 60 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | ISSUE_BODY: ${{ steps.build-comment.outputs.updated-text }} 62 | 63 | - name: Create comment - watching for progress 64 | run: | 65 | gh issue comment "$ISSUE_URL" \ 66 | --body-file "exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md" 67 | env: 68 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | 70 | - name: Enable next step workflow 71 | run: | 72 | gh workflow disable "${{github.workflow}}" 73 | env: 74 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 75 | -------------------------------------------------------------------------------- /.github/workflows/1-step.yml: -------------------------------------------------------------------------------- 1 | name: Step 1 2 | 3 | 4 | 5 | on: 6 | workflow_dispatch: 7 | # Common event triggers: pull_request, push, issues, issue_comment (feel free to experiment) 8 | # Docs: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows 9 | # Example: 10 | # pull_request: 11 | # branches: 12 | # - main 13 | 14 | permissions: 15 | contents: read 16 | actions: write 17 | issues: write 18 | 19 | env: 20 | STEP_2_FILE: ".github/steps/2-step.md" 21 | 22 | jobs: 23 | find_exercise: 24 | name: Find Exercise Issue 25 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.5.0 26 | 27 | post_next_step_content: 28 | name: Post next step content 29 | needs: [find_exercise] 30 | runs-on: ubuntu-latest 31 | env: 32 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 33 | 34 | steps: 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | 38 | - name: Get response templates 39 | uses: actions/checkout@v4 40 | with: 41 | repository: skills/exercise-toolkit 42 | path: exercise-toolkit 43 | ref: v0.5.0 44 | 45 | - name: Create comment - add step content 46 | run: | 47 | gh issue comment "$ISSUE_URL" \ 48 | --body-file "$STEP_2_FILE" 49 | env: 50 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | - name: Create comment - watching for progress 53 | run: | 54 | gh issue comment "$ISSUE_URL" \ 55 | --body-file exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md 56 | env: 57 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | 59 | - name: Disable current workflow and enable next one 60 | run: | 61 | gh workflow disable "${{github.workflow}}" 62 | gh workflow enable "Step 2" 63 | env: 64 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 65 | -------------------------------------------------------------------------------- /.github/workflows/2-step.yml: -------------------------------------------------------------------------------- 1 | name: Step 2 2 | 3 | 4 | on: 5 | workflow_dispatch: 6 | # Common event triggers: pull_request, push, issues, issue_comment (feel free to experiment) 7 | # Docs: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows 8 | # Example: 9 | # pull_request: 10 | # branches: 11 | # - main 12 | # types: 13 | # - closed 14 | 15 | permissions: 16 | contents: write 17 | actions: write 18 | issues: write 19 | 20 | env: 21 | REVIEW_FILE: ".github/steps/x-review.md" 22 | 23 | jobs: 24 | find_exercise: 25 | name: Find Exercise Issue 26 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.5.0 27 | 28 | # This job is optional. We often call it a "grading job". If the step is not graded, remove it. 29 | check_step_work: 30 | name: Check step work 31 | runs-on: ubuntu-latest 32 | needs: [find_exercise] 33 | env: 34 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 35 | 36 | steps: 37 | - name: Checkout 38 | uses: actions/checkout@v4 39 | 40 | - name: Get response templates 41 | uses: actions/checkout@v4 42 | with: 43 | repository: skills/exercise-toolkit 44 | path: exercise-toolkit 45 | ref: v0.5.0 46 | 47 | - name: Update comment - checking work 48 | run: | 49 | gh issue comment "$ISSUE_URL" \ 50 | --body-file exercise-toolkit/markdown-templates/step-feedback/checking-work.md \ 51 | --edit-last 52 | env: 53 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | 55 | # replace-me: Example of a grading check. You can add more checks as needed. 56 | - name: Check if README file exists 57 | id: check-file-exists 58 | continue-on-error: true 59 | uses: skills/exercise-toolkit/actions/file-exists@v0.5.0 60 | with: 61 | file: README.md 62 | 63 | # replace-me: Example of a grading check. You can add more checks as needed. 64 | - name: Check for keyphrase in README.md 65 | id: check-for-keyphrase 66 | continue-on-error: true 67 | uses: skills/action-keyphrase-checker@v1 68 | with: 69 | text-file: README.md 70 | keyphrase: Installation guide 71 | 72 | - name: Build message - step results 73 | id: build-message-step-results 74 | uses: skills/action-text-variables@v2 75 | with: 76 | template-file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md 77 | template-vars: | 78 | step_number: 1 79 | passed: ${{ !contains(steps.*.outcome, 'failure') }} 80 | results_table: 81 | - description: "Checked if README.md file exists" 82 | passed: ${{ steps.check-file-exists.outcome == 'success' }} 83 | - description: "Checked for Installation guide in README.md" 84 | passed: ${{ steps.check-for-keyphrase.outcome == 'success' }} 85 | 86 | 87 | - name: Create comment - step results 88 | run: | 89 | gh issue comment "$ISSUE_URL" \ 90 | --body "$COMMENT_BODY" \ 91 | --edit-last 92 | env: 93 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 94 | COMMENT_BODY: ${{ steps.build-message-step-results.outputs.updated-text }} 95 | 96 | - name: Fail job if not all checks passed 97 | if: contains(steps.*.outcome, 'failure') 98 | run: exit 1 99 | 100 | - name: Build message - step finished 101 | id: build-message-step-finish 102 | uses: skills/action-text-variables@v2 103 | with: 104 | template-file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md 105 | template-vars: | 106 | next_step_number: 2 107 | 108 | - name: Update comment - step finished 109 | run: | 110 | gh issue comment "$ISSUE_URL" \ 111 | --body "$ISSUE_BODY" 112 | env: 113 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 114 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 115 | 116 | post_review_content: 117 | name: Post review content 118 | needs: [find_exercise, check_step_work] 119 | runs-on: ubuntu-latest 120 | env: 121 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 122 | 123 | steps: 124 | - name: Checkout 125 | uses: actions/checkout@v4 126 | 127 | - name: Create comment - add step content 128 | run: | 129 | gh issue comment "$ISSUE_URL" \ 130 | --body-file "$REVIEW_FILE" 131 | env: 132 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 133 | 134 | # The last workflow in the chain of steps should also finish the exercise. 135 | finish_exercise: 136 | name: Finish Exercise 137 | needs: [find_exercise, post_review_content] 138 | uses: skills/exercise-toolkit/.github/workflows/finish-exercise.yml@v0.5.0 139 | with: 140 | issue-url: ${{ needs.find_exercise.outputs.issue-url }} 141 | 142 | disable_workflow: 143 | name: Disable this workflow 144 | needs: [find_exercise, post_review_content] 145 | runs-on: ubuntu-latest 146 | 147 | steps: 148 | - name: Checkout 149 | uses: actions/checkout@v4 150 | 151 | - name: Disable current workflow 152 | run: gh workflow disable "${{github.workflow}}" 153 | env: 154 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 155 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) GitHub, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # (replace-me: Exercise title) 2 | 3 | _(replace-me: One-line description of the exercise)_ 4 | 5 | ## Welcome 6 | 7 | - **Who is this for**: (replace-me: Target audience description) 8 | - **What you'll learn**: (replace-me: Learning objectives) 9 | - **What you'll build**: (replace-me: Description of what the learner will create) 10 | - **Prerequisites**: 11 | - (replace-me: Prerequisite skill/exercise) 12 | - (replace-me: Other prerequisites) 13 | 14 | - **How long**: This exercise takes less than (replace-me: estimated time) to complete. 15 | 16 | In this exercise, you will: 17 | 18 | 1. (replace-me: Learning objective step #1) 19 | 1. (replace-me: Learning objective step #2) 20 | 1. (replace-me: Learning objective step #N) 21 | 22 | 23 | ### How to start this exercise 24 | 25 | 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**. 26 | 27 | 28 | [![](https://img.shields.io/badge/Copy%20Exercise-%E2%86%92-1f883d?style=for-the-badge&logo=github&labelColor=197935)](https://github.com/new?template_owner=skills&template_name=exercise-template&owner=%40me&name=skills-&description=Exercise:+Replace+me&visibility=public) 29 | 30 |
31 | Having trouble? 🤷
32 | 33 | When copying the exercise, we recommend the following settings: 34 | 35 | - For owner, choose your personal account or an organization to host the repository. 36 | 37 | - We recommend creating a public repository, since private repositories will use Actions minutes. 38 | 39 | If the exercise isn't ready in 20 seconds, please check the [Actions](../../actions) tab. 40 | 41 | - Check to see if a job is running. Sometimes it simply takes a bit longer. 42 | 43 | - If the page shows a failed job, please submit an issue. Nice, you found a bug! 🐛 44 | 45 |
46 | 47 | --- 48 | 49 | © 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) 50 | --------------------------------------------------------------------------------