├── .devcontainer ├── devcontainer.json ├── post_create.sh ├── post_start.sh └── welcome-message.txt ├── .github ├── steps │ ├── 1-preparing.md │ ├── 2-application-initial-setup.md │ ├── 3-database-django-project-setup.md │ ├── 4-setup-django-rest-framework.md │ ├── 5-setup-frontend-react-framework.md │ ├── 6-copilot-on-github.md │ └── x-review.md └── workflows │ ├── 0-start-exercise.yml │ ├── 1-preparing.yml │ ├── 2-application-initial-setup.yml │ ├── 3-database-django-project-setup.yml │ ├── 4-setup-django-rest-framework.yml │ ├── 5-setup-frontend-react-framework.yml │ ├── 6-copilot-on-github.yml │ └── 6b-copilot-on-github.yml ├── .gitignore ├── .vscode └── launch.json ├── LICENSE ├── README.md └── docs ├── mona-high-school-fitness-tracker.md ├── octofit_story.md └── octofitapp-small.png /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/devcontainers/universal:2-linux", 3 | "hostRequirements": { 4 | "cpus": 4 5 | }, 6 | "name": "OctoFit App codespace", 7 | "postCreateCommand": "sudo chmod +x ./.devcontainer/post_create.sh && ./.devcontainer/post_create.sh", 8 | "postStartCommand": "sudo chmod +x ./.devcontainer/post_start.sh && ./.devcontainer/post_start.sh", 9 | "customizations": { 10 | "vscode": { 11 | "extensions": [ 12 | "github.copilot@insiders", // GitHub Copilot + Copilot Chat insiders 13 | "markdown-lint.markdownlinter", 14 | "ms-python.python", // Python extension 15 | "ms-python.vscode-pylance" // Pylance extension for Python 16 | ], 17 | "settings": { 18 | "chat.agent.enabled": true, 19 | } 20 | } 21 | }, 22 | "forwardPorts": [ 23 | 3000, // React default port 24 | 8000, // Django default port 25 | 27017 // MongoDB default port 26 | ], 27 | "portAttributes": { 28 | "3000": { // React port attributes 29 | "label": "octofit-tracker", 30 | "requireLocalPort": true, 31 | "visibility": "public" 32 | }, 33 | "8000": { // Django port attributes 34 | "label": "octofit-api", 35 | "requireLocalPort": true, 36 | "visibility": "public" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.devcontainer/post_create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is run after the container is created. 3 | # It is used to install any additional dependencies or perform any setup tasks. 4 | 5 | sudo cp --force ./.devcontainer/welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt -------------------------------------------------------------------------------- /.devcontainer/post_start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script is run after the container is startup. 3 | 4 | # open ports for Python Django server and React app 5 | gh cs ports visibility 8000:public -c $CODESPACE_NAME 6 | gh cs ports visibility 3000:public -c $CODESPACE_NAME -------------------------------------------------------------------------------- /.devcontainer/welcome-message.txt: -------------------------------------------------------------------------------- 1 | 👋 Welcome to building a full stack fitness application with GitHub Copilot agent mode! 2 | We are thrilled that you are here and we hope you are excited to explore the capabilities of Copilot! 3 | 🏋🏽🔥💪🏼🎧 As the gym teacher of Mergington High School you have been tasked with building a fitness app for your students. 4 | 📃 GitHub Copilot documentation: https://docs.github.com/en/copilot 5 | -------------------------------------------------------------------------------- /.github/steps/1-preparing.md: -------------------------------------------------------------------------------- 1 | ## Step 1: Hello GitHub Copilot agent mode 2 | 3 | Welcome to your **"Build applications with GitHub Copilot agent mode"** exercise! :robot: 4 | 5 | In this exercise, you will be using GitHub Copilot agent mode to build an application that tracks your fitness goals and progress. 🏋️♂️🏃♀️💪 6 | 7 | ### What is GitHub Copilot agent mode? 8 | 9 | Copilot agent mode can create apps from scratch, refactor across multiple files, write and run tests, and migrate legacy code to modern frameworks. It can automatically generate documentation, integrate new libraries, or help answer questions about a complex codebase. Copilot agent mode helps you be super-productive by having an AI collaborator that understands the workspace. It can orchestrate your inner development flow while keeping you in control. 10 | 11 | Copilot agent mode operates in a more autonomous and dynamic manner to achieve the desired outcome. To process a request, Copilot loops over the following steps and iterates multiple times as needed: 12 | 13 | Determines the relevant context and files to edit autonomously. 14 | Offers both code changes and terminal commands to complete the task. For example, Copilot might compile code, install packages, run tests, and more. 15 | Monitors the correctness of code edits and terminal command output and iterates to remediate issues. 16 | 17 | > 💡 **Tip:** You can learn more about GitHub Copilot agent mode in the [Use agent mode documentation](https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode). 18 | 19 | ### :keyboard: Activity: Getting to know your GitHub Copilot agent mode development environment 20 | 21 | 1. Right-click the below button to open the **Create Codespace** page in a new tab. 22 | 23 | [](https://codespaces.new/{{full_repo_name}}?quickstart=1) 24 | 25 | - The free tier of Codespaces that comes with all GitHub accounts is fine, assuming you still have minutes available. 26 | - The default Codespace settings are fine. 27 | 28 | 1. Confirm the **Repository** field is your copy of the exercise, not the original, then click the green **Create Codespace** button. 29 | 30 | - ✅ Your copy: `/{{{full_repo_name}}}` 31 | - ❌ Original: `/skills/build-applications-w-copilot-agent-mode` 32 | 33 | 1. Wait a moment for Visual Studio Code to load. 34 | 1. You may need to switch to VS Code insiders edition in the codespace since agent mode was released on 4/4 as a phased rollout to users. 35 | 36 | 37 | 1. Before we continue let's take a moment to familiarize ourselves with the project folder. 38 | 39 | - The left navigation bar is where you can access the file explorer, debugger, and search. 40 | - The lower panel (Ctrl+J) shows the debugger output, allows running terminal commands, and allows configuring the web service ports. 41 | - Our docs folder contains the another sample application repository that will give Copilot agent mode context to build your application. More on that in the next steps! 42 | 43 | 1. At the top of VS Code, locate and click the Copilot icon to open a Copilot Chat panel. 44 | 45 | 46 | 47 | 1. If this is your first, time using GitHub Copilot, you will have to accept the usage terms to continue. 48 | - Click the **Accept** button to continue. 49 | - If you are using Copilot Chat for the first time, you will also have to accept the usage terms to continue. 50 | - Click the **Accept** button to continue. 51 | 52 | ### :keyboard: Activity: Use Copilot agent mode to create a branch and publish it. 🙋 53 | 54 | Great work! Now that we are familiar with the app and we know it works, let's ask copilot for help starting a branch so we can do some customizing. 55 | 56 | 1. If not already there, return to VS Code. 57 | 58 | 1. Open the GitHub Copilot Chat window if not already open. 59 | 2. Copy and paste the following prompt in the GitHub Copilot Chat and select the **Agent** instead of **Ask** or **Edit** from the drop down where you are inserting the prompt. 60 | 61 | 62 | 63 | 64 | > 🪧 **Note:** 65 | - Do not change the model from GPT-4o this will be an optional activity at the end of the course. 66 | - Keep in mind that the Copilot agent mode is conversational so it may ask you questions and you can ask it questions too. 67 | - Wait a moment for the Copilot to respond and press the continue button to execute commands presented by Copilot agent mode. 68 | 69 | 1. Let's ask Copilot agent mode to help us remember the command and create the branch `build-octofit-app` and publishing it 70 | 71 | >  72 | > 73 | > ```prompt 74 | > Hey copilot, how can I create and publish a new Git branch called build-octofit-app? 75 | > ``` 76 | 77 | 78 | Copilot agent mode will respond and ask if you want agent mode to run the command. Respond with **Yes**. 79 | 80 | 81 | 82 | 83 | 1. Now that we are happy with the command, press the `Continue` button to let Copilot agent mode run it for us. No need to copy and paste! 84 | 85 | 1. After a moment, look in the VS Code lower status bar, on the left, to see the active branch. It should now say `build-octofit-app`. If so, you are all done with this step! 86 | 87 | 1. Now that your branch is pushed to GitHub, Mona should already be busy checking your work. Give her a moment and keep watch in the comments. You will see her respond with progress info and the next lesson. 88 | 89 | 90 | Having trouble? 🤷 91 | 92 | If you don't get feedback, here are some things to check: 93 | 94 | - Make sure your created the branch with the exact name `build-octofit-app`. No prefixes or suffixes. 95 | - Make sure the branch was indeed published to your repository. 96 | 97 | 98 | -------------------------------------------------------------------------------- /.github/steps/2-application-initial-setup.md: -------------------------------------------------------------------------------- 1 | ## Step 2: The initial application setup: Directory structure, Python requirements, and MongoDB 2 | 3 | In this step, we will accomplish the following: 4 | 5 | - Create the octofit-tracker application directory structure. 6 | - Create the octofit-tracker/backend and octofit-tracker/frontend directories. 7 | - Create the octofit-tracker/backend/requirements.txt file. 8 | 9 | 1. Open all files in the `docs` folder and keep this file open in the editor throughout this exercise. 10 | 1. Agent mode uses `mona-high-school-fitness-tracker.md` and `octofit_story.md` as a reference to create the application 11 | 2. Copy and paste the following prompt(s) in the GitHub Copilot Chat and select the "Agent" instead of "Ask" or "Edit" from the drop down where you are inserting the prompt. 12 | 13 | 14 | 15 | > 🪧 **Note:** 16 | - Do not change the model from GPT-4o this will be an optional activity at the end of the course. 17 | - Keep in mind that the Copilot agent mode is conversational so it may ask you questions and you can ask it questions too. 18 | - Wait a moment for the Copilot to respond and press the `Continue` button to execute commands presented by Copilot agent mode. 19 | - Keep files created and updated by Copilot agent mode until it is finished. 20 | - Agent mode has the ability to evaluate your code base and execute commands and add/refactor/delete parts of your code base and automatically self heal if it or you makes a mistake in the process. 21 | 22 | ### :keyboard: Activity: Prompt for GitHub Copilot in agent mode to start the creation of our application 23 | 24 | >  25 | > 26 | > ```prompt 27 | > Let's take the following step by step and generate instructions in this order and execute the commands. 28 | > Use docs/mona-high-school-fitness-tracker.md as a guide for the project structure and requirements. 29 | > 30 | > 1. Understand the story of creating the fitness application from the docs/octofit_story.md file. 31 | > 2. Create the initial directory structure for the octofit-tracker application octofit-tracker/backend, octofit-tracker/frontend. 32 | > 3. Setup the backend python virtual environment, octofit-tracker/backend/requirements.txt based on docs/mona-high-school-fitness-tracker.md, and install required packages. 33 | > 34 | > Don't proceed with the next activity until all of these steps are completed. 35 | >``` 36 | > 37 | 38 | > ❕ **Important:** Once the above activity installs all the required packages, proceed to the next activity. 39 | 40 | ### :keyboard: Activity: Let's install MongoDB 41 | 42 | >  43 | > 44 | > ```prompt 45 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. > Let's install MongoDB. 46 | > 47 | > 1. Install MongoDB and make sure the command is complete. 48 | > 49 | > Don't proceed with the next activity until all of these steps are completed. 50 | >``` 51 | 52 | > ❕ **Important:** 53 | - If the command completes in the terminal but agent mode shows it is still running click stop. 54 | - You may need to paste the prompt again in agent mode. 55 | 56 | ### :keyboard: Activity: Let's start and verify MongoDB is running 57 | 58 | >  59 | > 60 | > ```prompt 61 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. > Let's start and verify MongoDB is running. 62 | > 63 | > 1. Start the MongoDB service. 64 | > 2. Verify the MongoDB service running. 65 | > 66 | > Don't proceed with the next activity until all of these steps are completed. 67 | >``` 68 | 69 | > ❕ **Important:** 70 | - If the command completes in the terminal but agent mode shows it is still running click stop. 71 | - You may need to paste the prompt again in agent mode. 72 | 73 | 1. Now that we have created the app directory structure, setup a Python virtual environment, and Copilot agent mode helped write a `requirements.txt` to install all project dependencies, let's check our changes in to our `build-octofit-app` branch. 74 | 75 | 1. With our new changes complete, please **commit** and **push** the changes to GitHub. 76 | 77 | 1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson so we can keep working! 78 | 79 | 80 | Having trouble? 🤷 81 | 82 | If you don't get feedback, here are some things to check: 83 | 84 | - Make sure your commit changes were made for the following file to the branch `build-octofit-app` and pushed/synchronized to GitHub: 85 | - `octofit-tracker/backend/requirements.txt` and it contains the package `Django==4.1` 86 | - If Mona found a mistake, simply make a correction and push your changes again. Mona will check your work as many times as needed. 87 | 88 | 89 | -------------------------------------------------------------------------------- /.github/steps/3-database-django-project-setup.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Initialize and create the octofit_db MongoDB database, Django project/app, update Django project/app files, and populate the MongoDB database 2 | 3 | In this step, we will accomplish the following: 4 | 5 | - Set up the octofit_db MongoDB database structure. 6 | - Update the octofit-tracker/backend/octofit_tracker app files: 7 | - settings, models, serializers, urls, views, tests, and admin files. 8 | - Populate the octofit_db database with test data. 9 | - Verify the test data is populated in the octofit_db database. 10 | 11 | 1. Open all files in the `docs` folder and keep this file open in the editor throughout this exercise. 12 | 1. agent mode uses `mona-high-school-fitness-tracker.md` and `octofit_story.md` as a reference to create the application 13 | 2. Copy and paste the following prompt(s) in the GitHub Copilot Chat and select the "Agent" instead of "Ask" or "Edit" from the drop down where you are inserting the prompt. 14 | 15 | > 🪧 **Note:** 16 | - Do not change the model from GPT-4o this will be an optional activity at the end of the course. 17 | - Keep in mind that the Copilot agent mode is conversational so it may ask you questions and you can ask it questions too. 18 | - Wait a moment for the Copilot to respond and press the `Continue` button to execute commands presented by Copilot agent mode. 19 | - Keep files created and updated by Copilot agent mode until it is finished. 20 | - Agent mode has the ability to evaluate your code base and execute commands and add/refactor/delete parts of your code base and automatically self heal if it or you makes a mistake in the process. 21 | 22 | ### :keyboard: Activity: Setup the Python Django project/app 23 | 24 | >  25 | > 26 | > ```prompt 27 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app, > let's setup the Python Django project/app and run the server. 28 | > 29 | > 1. The octofit-tracker/backend directory will store the django project and app with the name octofit-tracker. 30 | > 2. Setup the additional configuration for the django project/app with the name octofit-tracker. 31 | > 32 | > Don't proceed with the next activity until all of these steps are completed. 33 | >``` 34 | 35 | > 🪧 **Note:** 36 | - Wait a moment for the Copilot to respond and press the `Continue` button to execute each command presented by Copilot agent mode. 37 | - Keep files created and updated until the Copilot agent mode has finished. 38 | 39 | > ❕ **Important:** 40 | - Don't start the Python Django app in the way that GitHub Copilot agent mode suggests hit **cancel**. 41 | 42 | ### :keyboard: Activity: Initialize and create the octofit_db MongoDB database 43 | 44 | >  45 | > 46 | > ```prompt 47 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for Merington's high school's app. Let's initialize the octofit_db database. 48 | > 49 | > 1. Initialize the mongo octofit_db database. 50 | > 2. Create a correct table structure for users, teams, activity, leaderboard, and workouts collections. 51 | > 3. Make sure there is a unique ID for the primary key for the user collection. 52 | > ex. db.users.createIndex({ "email": 1 }, { unique: true }) 53 | > 4. Execute the command for me to create the database. 54 | > 5. List the collections in the octofit_db database. 55 | > 56 | > Don't proceed with the next activity until all of these steps are completed. 57 | > ``` 58 | 59 | > ❕ **Important:** 60 | - If there is no `Continue` button, just pull the left side of the GitHub Copilot Chat panel over to the left, and it should appear. 61 | - If this doesn't work, you may need to copy and paste the response in the terminal if there is no `Continue` button. 62 | 63 | ### :keyboard: Activity: Update the Python Django project/app files 64 | 65 | >  66 | > 67 | > ```prompt 68 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for Merington's high school's app. Let's update the octofit-tracker/backend/octofit_tracker app files. 69 | > 70 | > 1. Update the octofit-tracker/backend/octofit_tracker/settings.py file to include the MongoDB database connection. 71 | > 2. Update the octofit-tracker/backend/octofit_tracker/models.py file to include the models for users, teams, activity, leaderboard, and workouts collections. 72 | > 3. Update the octofit-tracker/backend/octofit_tracker/serializers.py file to include the serializers for users, teams, activity, leaderboard, and workouts collections. 73 | > 4. Update the octofit-tracker/backend/octofit_tracker/urls.py file to include the URLs for users, teams, activity, leaderboard, and workouts collections. 74 | > 5. Update the octofit-tracker/backend/octofit_tracker/views.py file to include the views for users, teams, activity, leaderboard, and workouts collections. 75 | > 6. Update the octofit-tracker/backend/octofit_tracker/tests.py file to include the tests for users, teams, activity, leaderboard, and workouts collections. 76 | > 7. Update the octofit-tracker/backend/octofit_tracker/admin.py file to include the admin for users, teams, activity, leaderboard, and workouts collections. 77 | > 8. Make sure api_root is in octofit-tracker/backend/octofit_tracker/urls.py 78 | > 9. Enable CORS in the octofit-tracker/backend/octofit_tracker/settings.py file to allow cross-origin requests from the frontend React app and allow all origins, methods, and headers. 79 | > 10. Allow all hosts in the settings.py file. 80 | > 11. Install CORS middleware components. 81 | > 82 | > Don't proceed with the next activity until all of these steps are completed. 83 | > ``` 84 | 85 | > ❕ **Important:** Don't start the Python Django app in the way that GitHub Copilot agent mode suggests hit **cancel**. 86 | 87 | ### :keyboard: Activity: Populate the octofit_db database with test data from Django project/app files 88 | 89 | >  90 | > 91 | > ```prompt 92 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for Merington's high school's app. Let's populate the octofit_db database with test data. Use the same data from docs/mona-high-school-fitness-tracker.md file. 93 | > 94 | > 1. Create a test data file in the octofit-tracker/backend/octofit_tracker directory. 95 | > 2. Run makemigrations and migrate the database in a Python virtual environment. 96 | > 3. Populate the octofit_db database with test data for users, teams, activities, leaderboard, and workouts collections based on test data in docs/mona-high-school-fitness-tracker.md octofit-tracker/backend/octofit_tracker/management/commands/populate_db.py. 97 | > 4. Verify the test data is populated in the octofit_db database. 98 | > 99 | > Don't proceed with the next activity until all of these steps are completed. 100 | > ``` 101 | 102 | > ❕ **Important:** 103 | - Don't start the Python Django app in the way that GitHub Copilot agent mode suggests hit **cancel**. 104 | - If there is no `Continue` button, just pull the left side of the GitHub Copilot Chat panel over to the left, and it should appear. 105 | - If this doesn't work, you may need to copy and paste the response in the terminal if there is no `Continue` button. 106 | 107 | 1. Now that we have created the database structure, updated our Django project files, and populated the database, let's check our changes into our `build-octofit-app` branch. 108 | 109 | 1. With our new changes complete, please **commit** and **push** the changes to GitHub. 110 | 111 | 1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson so we can keep working! 112 | 113 | 114 | Having trouble? 🤷 115 | 116 | If you don't get feedback, here are some things to check: 117 | 118 | - Make sure your commit changes were made for the following files to the branch `build-octofit-app` and pushed/synchronized to GitHub: 119 | - `octofit-tracker/backend/octofit_tracker/settings.py` 120 | - `octofit-tracker/backend/octofit_tracker/management/commands/populate_db.py` 121 | - If Mona found a mistake, simply make a correction and push your changes again. Mona will check your work as many times as needed. 122 | 123 | 124 | -------------------------------------------------------------------------------- /.github/steps/4-setup-django-rest-framework.md: -------------------------------------------------------------------------------- 1 | ## Step 4: Setup Django REST Framework, start the server, and test the API 2 | 3 | In this step, we will accomplish the following: 4 | 5 | - Setup the Django REST Framework. 6 | - Start the server. 7 | - Test the API using curl. 8 | 9 | 1. Open all files in the `docs` folder and keep this file open in the editor throughout this exercise. 10 | 1. agent mode uses `mona-high-school-fitness-tracker.md` and `octofit_story.md` as a reference to create the application 11 | 2. Copy and paste the following prompt(s) in the GitHub Copilot Chat and select the "Agent" instead of "Ask" or "Edit" from the drop down where you are inserting the prompt. 12 | 13 | > 🪧 **Note:** 14 | - Do not change the model from GPT-4o this will be an optional activity at the end of the course. 15 | - Keep in mind that the Copilot agent mode is conversational so it may ask you questions and you can ask it questions too. 16 | - Wait a moment for the Copilot to respond and press the continue button to execute commands presented by Copilot agent mode. 17 | - Keep files created and updated by Copilot agent mode until it is finished. 18 | - Agent mode has the ability to evaluate your code base and execute commands and add/refactor/delete parts of your code base and automatically self heal if it or you makes a mistake in the process. 19 | 20 | ### :keyboard: Activity: Setup Django REST Framework, restart the server, and test the API 21 | 22 | > 🪧 **Note:** 23 | - Make sure to replace [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME] with your codespace name. 24 | - ex. redesigned-spork-g6pj46rr9hpp6x 25 | - You can get the codespace name by running the following command in the terminal: `echo $CODESPACE_NAME`. 26 | 27 | >  28 | > 29 | > ```prompt 30 | >Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for Mergington's high school's app. Let's setup codespace for the URL, start the server via VS Code launch.json, and test the API. 31 | > 32 | > 1. Activate the Python virtual environment. 33 | > 2. Update #file:octofit-tracker/backend/octofit_tracker/views.py to replace the return for the REST API URL endpoints with the codespace URL https://[REPLACE-THIS-WITH-YOUR-CODESPACE-NAME]-8000.app.github.dev for Django and avoid certificate HTTPS issues. 34 | > 3. Make sure the Django backend works on [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME]-8000.app.github.dev and localhost:8000. 35 | > 4. Test the API endpoints using curl command. 36 | > 5. Allow host access to codespace URL and localhost:8000. 37 | > 38 | > Don't proceed with the next activity until all of these steps are completed. 39 | >``` 40 | 41 | > ❕ **Important:** Don't start the Python Django app in the way that GitHub Copilot agent mode suggests hit **cancel**. Follow the next activity instead. 42 | 43 | ### :keyboard: Activity: Start the Python Django app and check the output 44 | 45 | Now, let's actually try running the Django application! In the left sidebar, select the `Run and Debug` tab and then press the **Start Debugging** icon. 46 | 47 | 48 | 49 | > ❕ **Important:** 50 | - Make sure to replace [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME] with your codespace name. 51 | - ex. redesigned-spork-g6pj46rr9hpp6x 52 | - You can get the codespace name by running the following command in the terminal: `echo $CODESPACE_NAME`. 53 | 54 | 1. Now that we have updated our Django product to include our codespace name for the URL endpoint, 55 | let's check our changes in to our `build-octofit-app` branch. 56 | 57 | 1. With our new changes complete, please **commit** and **push** the changes to GitHub. 58 | 59 | 1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson so we can keep working! 60 | 61 | 62 | Having trouble? 🤷 63 | 64 | If you don't get feedback, here are some things to check: 65 | 66 | - Make sure your commit changes were made for the following files to the branch `build-octofit-app` and pushed/synchronized to GitHub: 67 | - `octofit-tracker/backend/octofit_tracker/settings.py` 68 | - `octofit-tracker/backend/octofit_tracker/views.py` 69 | - If Mona found a mistake, simply make a correction and push your changes again. Mona will check your work as many times as needed. 70 | 71 | 72 | -------------------------------------------------------------------------------- /.github/steps/5-setup-frontend-react-framework.md: -------------------------------------------------------------------------------- 1 | ## Step 5: Setup the frontend React framework, update the components, and start OctoFit Tracker app 2 | 3 | In this step, we will accomplish the following: 4 | 5 | - Setup the octofit-tracker frontend React framework. 6 | - Update the following components to include the React framework: 7 | - src/App.js 8 | - src/index.js 9 | - src/components/Activities.js 10 | - src/components/Leaderboard.js 11 | - src/components/Teams.js 12 | - src/components/Users.js 13 | - src/components/Workouts.js 14 | - Start the React app and check the output. 15 | 16 | 1. Open all files in the `docs` folder and keep this file open in the editor throughout this exercise. 17 | 1. agent mode uses `mona-high-school-fitness-tracker.md` and `octofit_story.md` as a reference to create the application 18 | 2. Copy and paste the following prompt(s) in the GitHub Copilot Chat and select the "Agent" instead of "Ask" or "Edit" from the drop down where you are inserting the prompt. 19 | 20 | > 🪧 **Note:** 21 | - Do not change the model from GPT-4o this will be an optional activity at the end of the course. 22 | - Keep in mind that the Copilot agent mode is conversational so it may ask you questions and you can ask it questions too. 23 | - Wait a moment for the Copilot to respond and press the continue button to execute commands presented by Copilot agent mode. 24 | - Keep files created and updated by Copilot agent mode until it is finished. 25 | - Agent mode has the ability to evaluate your code base and execute commands and add/refactor/delete parts of your code base and automatically self heal if it or you makes a mistake in the process. 26 | 27 | ### :keyboard: Activity: Install the octofit-tracker frontend React framework 28 | 29 | >  30 | > 31 | > ```prompt 32 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. Let's setup codespace for the octofit-tracker frontend React framework. 33 | > 34 | > 1. Make the octofit-tracker/frontend directory. 35 | > 2. Create the react app in the octofit-tracker/frontend directory. 36 | > 3. Install stable versions of React framework and modules based on docs/mona-high-school-fitness-tracker.md. 37 | > 4. Install stable bootstrap in the octofit-tracker/frontend directory. 38 | > 5. Import bootstrap css in the src/index.js file. 39 | > 6. Install the stable react-router-dom in the octofit-tracker/frontend directory. 40 | > 7. Don't change .gitignore file 41 | > 42 | > Don't proceed with the next activity until all of these steps are completed. 43 | >``` 44 | 45 | ### :keyboard: Activity: Update the octofit-tracker frontend React components 46 | 47 | > 🪧 **Note:** 48 | - Make sure to replace [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME] with your codespace name. 49 | - ex. redesigned-spork-g6pj46rr9hpp6x 50 | - You can get the codespace name by running the following command in the terminal: `echo $CODESPACE_NAME`. 51 | 52 | >  53 | > 54 | > ```prompt 55 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. Let's update the octofit-tracker frontend React components. 56 | > 57 | > - Update the following components to include the React framework to point to the backend API: 58 | > - src/App.js 59 | > - src/index.js 60 | > - src/components/Activities.js 61 | > - src/components/Leaderboard.js 62 | > - src/components/Teams.js 63 | > - src/components/Users.js 64 | > - src/components/Workouts.js 65 | > - In each component replace the fetch url with the codespace url https://[REPLACE-THIS-WITH-YOUR-CODESPACE-NAME]-8000.app.github.dev/api/ for the Django rest framework backend. 66 | > - Make sure to use the correct port and protocol http or https. 67 | > - Update src/App.js to include the main navigation for all components. 68 | > - Make sure react-router-dom is used for the navigation menu. 69 | > - The react app should show the navigation menu and the components. 70 | > 71 | > Don't proceed with the next activity until all of these steps are completed. 72 | > ``` 73 | 74 | > ❕ **Important:** 75 | - Make sure to replace [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME] with your codespace name. 76 | - ex. redesigned-spork-g6pj46rr9hpp6x 77 | - You can get the codespace name by running the following command in the terminal: `echo $CODESPACE_NAME`. 78 | 79 | ### :keyboard: Activity: Start the react app and check the output 80 | 81 | Now, let's actually try running the react application! In the left sidebar, select the `Run and Debug` tab and then press the **Start Debugging** icon. 82 | 83 | 84 | 85 | ### :keyboard: Activity: Let's add some formatting, structuring, and styling to the octofit tracker app 86 | 87 | >  88 | > 89 | > ```prompt 90 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. Let's style this like App.css and make it look nice. 91 | > 92 | > - Let's make the App.js and all components javascript files in the app are consistent with the following: 93 | > - Use bootstrap tables for the data in all javascript components. 94 | > - Use bootstrap buttons for the buttons. 95 | > - Use bootstrap headings for the headings. 96 | > - Use bootstrap links for the links. 97 | > - Use bootstrap navigation for the navigation menu. 98 | > - Use bootstrap forms for the forms. 99 | > - Use bootstrap cards for the cards. 100 | > - Use bootstrap modals for the modals. 101 | > 102 | > Don't proceed with the next activity until all of these steps are completed. 103 | >``` 104 | 105 | ### :keyboard: Optional Activity: Let's make the octofit tracker app look nice, pretty, and add some color 106 | 107 | >  108 | > 109 | > ```prompt 110 | > Based on the example monafit tracker app in the docs/mona-high-school-fitness-tracker.md file and use octofit as the name for mergington's high schools app. Let's style this like App.css and make it look nice. 111 | > 112 | > - Edit the App.css file to do the following: 113 | > - Add some color to the background. 114 | > - Add some color to the text. 115 | > - Add some color to the tables. 116 | > - Add some color to the buttons. 117 | > - Add some color to the headings. 118 | > - Add some color to the links. 119 | > - Add some color to the navigation menu. 120 | > - Add the octofitapp-small logo justified to the left to the app and make it look nice. 121 | > - Add a favicon to the app and make it look nice. 122 | > 123 | >Don't proceed with the next activity until all of these steps are completed. 124 | >``` 125 | 126 | ### :keyboard: Optional Activity: Iterate on the appearance and try different models 127 | 128 | > 🧪 **Try this:** 129 | - Try creating your own prompts to change the application appearance, add features, and try different models. 130 | - Once you are happy with the application you can commit the changes and push them to your branch `build-octofit-app`. 131 | 132 | 1. Now that we have created the React frontend for all application components, let's check our changes in to our `build-octofit-app` branch. 133 | 134 | 1. With our new changes complete, please **commit** and **push** the changes to GitHub. 135 | 136 | 1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson so we can keep working! 137 | 138 | 139 | Having trouble? 🤷 140 | 141 | If you don't get feedback, here are some things to check: 142 | 143 | - Make sure your commit changes were made for the following files to the branch `build-octofit-app` and pushed/synchronized to GitHub: 144 | - `octofit-tracker/frontend/src/components/Activities.js` and it contains `-8000.app.github.dev/api/activities/` 145 | - `octofit-tracker/frontend/src/components/Leaderboard.js` and it contains `-8000.app.github.dev/api/leaderboard/` 146 | - `octofit-tracker/frontend/src/components/Teams.js` and it contains `-8000.app.github.dev/api/teams/` 147 | - `octofit-tracker/frontend/src/components/Users.js` and it contains `-8000.app.github.dev/api/users/` 148 | - `octofit-tracker/frontend/src/components/Workouts.js` and it contains `-8000.app.github.dev/api/workouts/` 149 | - If Mona found a mistake, simply make a correction and push your changes again. Mona will check your work as many times as needed. 150 | 151 | 152 | -------------------------------------------------------------------------------- /.github/steps/6-copilot-on-github.md: -------------------------------------------------------------------------------- 1 | ## Step 6: Using GitHub Copilot within a pull request 2 | 3 | Congratulations! You are finished with coding for this exercise (and VS Code). Now it's time to merge our work. :tada: To wrap up, let's learn about two limited-access Copilot features that can speed up our pull requests! 4 | 5 | #### Copilot Pull Request Summaries 6 | 7 | Typically, you would review your notes and commit messages then summarize them for your pull request description. This may take some time, especially if commit messages are inconsistent or code is not documented well. Fortunately, Copilot can consider all changes in the pull request and provide the important highlights, and with references too! 8 | 9 | > [!NOTE] 10 | > This is unavailable with the **Copilot Free** tier. [[docs]](https://docs.github.com/en/enterprise-cloud@latest/copilot/using-github-copilot/using-github-copilot-for-pull-requests/creating-a-pull-request-summary-with-github-copilot) 11 | 12 | #### Copilot Review 13 | 14 | More eyes on our work is always useful so let's ask Copilot to do a first pass before we do a normal peer review process. Copilot is great at catching common mistakes that can be fixed by simple adjustment, but please remember to use it responsibly. 15 | 16 | > [!NOTE] 17 | > This is in **Public Preview** for organizations. [[docs]](https://docs.github.com/en/copilot/using-github-copilot/code-review/using-copilot-code-review) 18 | 19 | ### :keyboard: Activity: Summarize and review a PR with Copilot 20 | 21 | Both **pull request summaries** and **Copilot review** have limited access, so this activity is mostly optional. If you have access, Mona will gladly check your work though! If not, you can skip the optional steps. 22 | 23 | 1. In a web browser, open another tab and navigate to your exercise repository. 24 | 25 | 1. You might notice a **notification banner** suggesting to create a new pull request. Click that or use the **Pull Requests** tab at the top to create a new pull request. Please use the following details: 26 | 27 | - **base:** `main` 28 | - **compare:** `build-octofit-app` 29 | - **title:** `Add registration validation and more activities` 30 | 31 | 1. (Optional) In the **Add a description** area, enter edit mode if needed, then click the **Copilot actions** icon and **Summary** action. After a moment, Copilot will add a description. :memo: 32 | 33 | 34 | 35 | 1. (Optional) In the right side information panel at the top, locate the **Reviewers** section and click the **Request** button next to a **Copilot icon**. Wait a moment for Copilot to add a review comment to your pull request! 36 | 37 | 38 | 39 | > **Tip:** Notice a log entry that Copilot was requested for a review. 40 | 41 | 1. At the bottom, press the **Merge pull request** button. Nice work! You are all done! :tada: 42 | 43 | 1. Wait a moment for Mona to check your work, provide feedback, and post a final review of this lesson! 44 | -------------------------------------------------------------------------------- /.github/steps/x-review.md: -------------------------------------------------------------------------------- 1 | ## Review 2 | 3 | _Congratulations, you've completed this exercise and learned a lot about GitHub Copilot agent mode!_ 4 | 5 | 6 | 7 | Here's a recap of your accomplishments: 8 | 9 | - Set up your GitHub Codespace and environment. 10 | - Learned how to use Copilot inline suggestions, Chat, and Edits. 11 | - Used Copilot to generate commit messages and pull request summaries. 12 | - Learned how to request Copilot to review your code. 13 | 14 | ### What's next? 15 | 16 | - Continue working on the project 17 | - Use Copilot to add an ability for login and authentication. 18 | - Keep evolving the look of the application through app.css. 19 | - Use Copilot to fix issues found during a pull request review. 20 | - Use Copilot to generate tests and documentation. 21 | - Use Copilot with different models. 22 | - Check out the other [GitHub Skills exercises](https://skills.github.com). 23 | - Try building your first [GitHub Copilot Extension](https://github.com/skills/your-first-extension-for-github-copilot) 24 | 25 | Check out these resources to learn more about GitHub Copilot: 26 | 27 | - Take a look at this blog on GitHub Copilot agent mode [Mastering GitHub Copilot: When to use AI agent mode](https://github.blog/ai-and-ml/github-copilot/mastering-github-copilot-when-to-use-ai-agent-mode/) 28 | - Are you not getting the responses you want from Copilot? [Learn prompt engineering](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/prompt-engineering-for-copilot-chat) 29 | - Explore GitHub Copilot [Slash Commands](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/github-copilot-chat-cheat-sheet?tool=vscode). 30 | - See what other features are available [GitHub Copilot Features](https://docs.github.com/en/copilot/about-github-copilot/github-copilot-features). 31 | - Take a look at the [GitHub Copilot Documentation](https://docs.github.com/en/copilot). -------------------------------------------------------------------------------- /.github/workflows/0-start-exercise.yml: -------------------------------------------------------------------------------- 1 | name: Step 0 # Start Exercise 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: write 10 | actions: write 11 | issues: write 12 | 13 | env: 14 | EXERCISE_NAME: "Build Applications with GitHub Copilot Agent Mode" 15 | INTRO_MESSAGE: "Welcome to the exciting world of GitHub Copilot agent mode! 🚀 In this exercise, you'll unlock the potential of this AI-powered coding assistant to accelerate your development process. Let's dive in and have some fun exploring the future of coding together! 💻✨" 16 | STEP_1_FILE: ".github/steps/1-preparing.md" 17 | 18 | jobs: 19 | disable_workflows: 20 | name: Disable workflows 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | 27 | - name: Disable all workflows 28 | run: | 29 | workflows=$(git ls-files | grep -E '\.yml$|\.yaml$') 30 | for workflow in $workflows; do 31 | workflow_name=$(basename $workflow) 32 | gh workflow disable "$workflow_name" || true 33 | done 34 | env: 35 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | 37 | start_exercise: 38 | if: | 39 | !github.event.repository.is_template 40 | name: Start Exercise 41 | runs-on: ubuntu-latest 42 | 43 | steps: 44 | - name: Checkout 45 | uses: actions/checkout@v4 46 | 47 | - name: Configure Git user 48 | run: | 49 | git config user.name github-actions[bot] 50 | git config user.email github-actions[bot]@users.noreply.github.com 51 | 52 | - name: Deactivate 'Start Exercise' button 53 | run: | 54 | # Remove href from 'Start Exercise' button 55 | target='id="copy-exercise"[^>]*href="[^"]*"' 56 | replacement='id="copy-exercise"' 57 | sed -i "s|$target|$replacement|g" README.md 58 | 59 | # Change color from green to gray 60 | target=Copy_Exercise-008000 61 | replacement=Copy_Exercise-AAA 62 | sed -i "s|$target|$replacement|g" README.md 63 | 64 | - name: Activate 'Start Exercise' button 65 | run: | 66 | # Add link to issue 67 | target='id="start-exercise"' 68 | replacement='id="start-exercise" href="../../issues/1"' 69 | sed -i "s|$target|$replacement|g" README.md 70 | 71 | # Change color from gray to green 72 | target=Start_Exercise-AAA 73 | replacement=Start_Exercise-008000 74 | sed -i "s|$target|$replacement|g" README.md 75 | 76 | - name: Replace relative links in readme 77 | run: | 78 | target=../../ 79 | replacement=https://github.com/${{ github.repository }}/ 80 | sed -i "s|$target|$replacement|g" README.md 81 | 82 | - name: Push README changes 83 | run: | 84 | git add README.md 85 | git commit --message="Start exercise" 86 | git push 87 | env: 88 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 89 | 90 | create_exercise: 91 | if: | 92 | !github.event.repository.is_template 93 | name: Create exercise issue 94 | runs-on: ubuntu-latest 95 | 96 | outputs: 97 | issue-url: ${{ steps.create-issue.outputs.ISSUE_URL }} 98 | 99 | steps: 100 | - name: Checkout 101 | uses: actions/checkout@v4 102 | 103 | - name: Get response templates 104 | uses: actions/checkout@v4 105 | with: 106 | repository: skills/response-templates 107 | path: skills-response-templates 108 | 109 | - name: Configure Git user 110 | run: | 111 | git config user.name github-actions[bot] 112 | git config user.email github-actions[bot]@users.noreply.github.com 113 | 114 | - name: Build welcome message from template 115 | id: build-issue-description 116 | uses: skills/action-text-variables@v1 117 | with: 118 | template-file: skills-response-templates/step-feedback/welcome.md 119 | template-vars: | 120 | title=${{ env.EXERCISE_NAME }} 121 | login=${{ github.actor }} 122 | intro_message=${{ env.INTRO_MESSAGE }} 123 | 124 | - name: Create issue - add welcome message 125 | id: create-issue 126 | run: | 127 | issue_url=$(gh issue create \ 128 | --title "Exercise: $EXERCISE_NAME" \ 129 | --body "$ISSUE_BODY") 130 | echo "ISSUE_URL=$issue_url" >> "$GITHUB_OUTPUT" 131 | env: 132 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 133 | ISSUE_BODY: ${{ steps.build-issue-description.outputs.updated-text }} 134 | 135 | post_next_step_content: 136 | name: Post next step content 137 | runs-on: ubuntu-latest 138 | needs: [create_exercise] 139 | env: 140 | ISSUE_URL: ${{ needs.create_exercise.outputs.issue-url }} 141 | 142 | steps: 143 | - name: Checkout 144 | uses: actions/checkout@v4 145 | 146 | - name: Get response templates 147 | uses: actions/checkout@v4 148 | with: 149 | repository: skills/response-templates 150 | path: skills-response-templates 151 | 152 | - name: Configure Git user 153 | run: | 154 | git config user.name github-actions[bot] 155 | git config user.email github-actions[bot]@users.noreply.github.com 156 | 157 | - name: Build comment - add step content 158 | id: build-comment 159 | uses: skills/action-text-variables@v1 160 | with: 161 | template-file: ${{ env.STEP_1_FILE }} 162 | template-vars: | 163 | login=${{ github.actor }} 164 | full_repo_name=${{ github.repository }} 165 | 166 | - name: Create comment - add step content 167 | run: | 168 | gh issue comment "$ISSUE_URL" \ 169 | --body "$ISSUE_BODY" 170 | env: 171 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 172 | ISSUE_BODY: ${{ steps.build-comment.outputs.updated-text }} 173 | 174 | - name: Create comment - watching for progress 175 | run: | 176 | gh issue comment "$ISSUE_URL" \ 177 | --body-file "skills-response-templates/step-feedback/watching-for-progress.md" 178 | env: 179 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 180 | 181 | - name: Disable current workflow and enable next one 182 | run: | 183 | # gh workflow enable "Step 0" # Already disabled 184 | gh workflow enable "Step 1" 185 | env: 186 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 187 | -------------------------------------------------------------------------------- /.github/workflows/1-preparing.yml: -------------------------------------------------------------------------------- 1 | name: Step 1 # Preparing to make your extension 2 | 3 | on: 4 | push: 5 | branches: 6 | - "build-octofit-app" 7 | 8 | permissions: 9 | contents: read 10 | actions: write 11 | issues: write 12 | 13 | env: 14 | STEP_2_FILE: ".github/steps/2-application-initial-setup.md" 15 | 16 | jobs: 17 | find_exercise: 18 | name: Find Exercise Issue 19 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 20 | 21 | check_step_work: 22 | name: Check step work 23 | runs-on: ubuntu-latest 24 | needs: [find_exercise] 25 | env: 26 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | 32 | - name: Get response templates 33 | uses: actions/checkout@v4 34 | with: 35 | repository: skills/response-templates 36 | path: skills-response-templates 37 | 38 | - name: Update comment - checking work 39 | run: | 40 | gh issue comment "$ISSUE_URL" \ 41 | --body-file skills-response-templates/step-feedback/checking-work.md \ 42 | --edit-last 43 | env: 44 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | # START: Check practical exercise 47 | 48 | # Nothing to verify. Creating the branch is enough for now. 49 | # In a future update, we will check that the codepsace is running and that the website is visible. 50 | 51 | # END: Check practical exercise 52 | 53 | - name: Build message - step finished 54 | id: build-message-step-finish 55 | uses: skills/action-text-variables@v1 56 | with: 57 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 58 | template-vars: | 59 | next_step_number=2 60 | 61 | - name: Update comment - step finished 62 | run: | 63 | gh issue comment "$ISSUE_URL" \ 64 | --body "$ISSUE_BODY" \ 65 | --edit-last 66 | env: 67 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 68 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 69 | 70 | post_next_step_content: 71 | name: Post next step content 72 | needs: [find_exercise, check_step_work] 73 | runs-on: ubuntu-latest 74 | env: 75 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 76 | 77 | steps: 78 | - name: Checkout 79 | uses: actions/checkout@v4 80 | 81 | - name: Get response templates 82 | uses: actions/checkout@v4 83 | with: 84 | repository: skills/response-templates 85 | path: skills-response-templates 86 | 87 | - name: Create comment - add step content 88 | run: | 89 | gh issue comment "$ISSUE_URL" \ 90 | --body-file "$STEP_2_FILE" 91 | env: 92 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 93 | 94 | - name: Create comment - watching for progress 95 | run: | 96 | gh issue comment "$ISSUE_URL" \ 97 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 98 | env: 99 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 100 | 101 | - name: Disable current workflow and enable next one 102 | run: | 103 | gh workflow disable "Step 1" 104 | gh workflow enable "Step 2" 105 | env: 106 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/2-application-initial-setup.yml: -------------------------------------------------------------------------------- 1 | name: Step 2 # octofit-tracker application initial setup 2 | 3 | on: 4 | push: 5 | branches: 6 | - "build-octofit-app" 7 | paths: 8 | - "octofit-tracker/backend/requirements.txt" 9 | 10 | permissions: 11 | contents: read 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | STEP_3_FILE: ".github/steps/3-database-django-project-setup.md" 17 | 18 | jobs: 19 | find_exercise: 20 | name: Find Exercise Issue 21 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 22 | 23 | check_step_work: 24 | name: Check step work 25 | runs-on: ubuntu-latest 26 | needs: [find_exercise] 27 | env: 28 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Get response templates 35 | uses: actions/checkout@v4 36 | with: 37 | repository: skills/response-templates 38 | path: skills-response-templates 39 | 40 | - name: Update comment - checking work 41 | run: | 42 | gh issue comment "$ISSUE_URL" \ 43 | --body-file skills-response-templates/step-feedback/checking-work.md \ 44 | --edit-last 45 | env: 46 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | # START: Check practical exercise 49 | 50 | # Search for the comment about registration validation 51 | - name: Check file and contents of 'octofit-tracker/backend/requirements.txt' 52 | run: | 53 | # File and expected Python requirement 54 | file="octofit-tracker/backend/requirements.txt" 55 | keyphrase="Django==4.1" 56 | 57 | # Fail the workflow if the file content is missing 58 | if ! grep -q "$keyphrase" "$file"; then 59 | message="It seems you didn't check in your octofit-tracker/backend/requirements.txt with the Python Django requirement. Please try again." 60 | gh issue comment "$ISSUE_URL" \ 61 | --body "$message" \ 62 | --edit-last 63 | exit 1 64 | fi 65 | env: 66 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 67 | 68 | # END: Check practical exercise 69 | 70 | - name: Build message - step finished 71 | id: build-message-step-finish 72 | uses: skills/action-text-variables@v1 73 | with: 74 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 75 | template-vars: | 76 | next_step_number=3 77 | 78 | - name: Update comment - step finished 79 | run: | 80 | gh issue comment "$ISSUE_URL" \ 81 | --body "$ISSUE_BODY" \ 82 | --edit-last 83 | env: 84 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 85 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 86 | 87 | post_next_step_content: 88 | name: Post next step content 89 | needs: [find_exercise, check_step_work] 90 | runs-on: ubuntu-latest 91 | env: 92 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 93 | 94 | steps: 95 | - name: Checkout 96 | uses: actions/checkout@v4 97 | 98 | - name: Get response templates 99 | uses: actions/checkout@v4 100 | with: 101 | repository: skills/response-templates 102 | path: skills-response-templates 103 | 104 | - name: Create comment - add step content 105 | run: | 106 | gh issue comment "$ISSUE_URL" \ 107 | --body-file "$STEP_3_FILE" 108 | env: 109 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 110 | 111 | - name: Create comment - watching for progress 112 | run: | 113 | gh issue comment "$ISSUE_URL" \ 114 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 115 | env: 116 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 117 | 118 | - name: Disable current workflow and enable next one 119 | run: | 120 | gh workflow disable "Step 2" 121 | gh workflow enable "Step 3" 122 | env: 123 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 124 | -------------------------------------------------------------------------------- /.github/workflows/3-database-django-project-setup.yml: -------------------------------------------------------------------------------- 1 | name: Step 3 # Django project setup and database test data population 2 | 3 | on: 4 | push: 5 | branches: 6 | - "build-octofit-app" 7 | paths: 8 | - "octofit-tracker/backend/octofit_tracker/**" 9 | 10 | permissions: 11 | contents: read 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | STEP_4_FILE: ".github/steps/4-setup-django-rest-framework.md" 17 | 18 | jobs: 19 | find_exercise: 20 | name: Find Exercise Issue 21 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 22 | 23 | check_step_work: 24 | name: Check step work 25 | runs-on: ubuntu-latest 26 | needs: [find_exercise] 27 | env: 28 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Get response templates 35 | uses: actions/checkout@v4 36 | with: 37 | repository: skills/response-templates 38 | path: skills-response-templates 39 | 40 | - name: Update comment - checking work 41 | run: | 42 | gh issue comment "$ISSUE_URL" \ 43 | --body-file skills-response-templates/step-feedback/checking-work.md \ 44 | --edit-last 45 | env: 46 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | # START: Check practical exercise 49 | 50 | - name: Check octofit_db and djongo has been added to settings.py and populate_db.py has been created 51 | id: check-user-work 52 | run: | 53 | # Checks to perform 54 | checks='{ 55 | "settings_py": { 56 | "name": "settings.py", 57 | "passed": true, 58 | "message": "" 59 | }, 60 | "populate_db": { 61 | "name": "populate_db.py", 62 | "passed": true, 63 | "message": "" 64 | } 65 | }' 66 | 67 | # Check for octofit_db info in settings.py 68 | file="octofit-tracker/backend/octofit_tracker/settings.py" 69 | keyphrase='octofit_db' 70 | minimum_occurences=1 71 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 72 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 73 | checks=$(echo $checks | jq '.settings_py.passed = false') 74 | checks=$(echo $checks | jq '.settings_py.message = "Please use Copilot agent mode to add the name of the database octofit_db to settings.py."') 75 | fi 76 | 77 | # Check for djongo info in settings.py 78 | file="octofit-tracker/backend/octofit_tracker/settings.py" 79 | keyphrase='djongo' 80 | minimum_occurences=2 81 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 82 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 83 | checks=$(echo $checks | jq '.settings_py.passed = false') 84 | checks=$(echo $checks | jq '.settings_py.message = "Please use Copilot agent mode to add the database engine djongo to settings.py."') 85 | fi 86 | 87 | # Check for 'test data' in populate_db.py 88 | file="octofit-tracker/backend/octofit_tracker/management/commands/populate_db.py" 89 | keyphrase='test data for' 90 | minimum_occurences=1 91 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 92 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 93 | checks=$(echo $checks | jq '.populate_db.passed = false') 94 | checks=$(echo $checks | jq '.populate_db.message = "Please use Copilot agent mode to add test data with the file populate_db.py."') 95 | fi 96 | 97 | # Verify all checks passed 98 | passed=$(echo $checks | jq '. | all(.passed?)') 99 | 100 | # Flatten to an array for returning. Allows iteration during rendering. 101 | results=$(echo $checks | jq 'to_entries | map({name: .key} + .value)') 102 | 103 | # Save pass status to output 104 | echo "passed=$passed" >> $GITHUB_OUTPUT 105 | 106 | # Save results to output 107 | echo 'results<> $GITHUB_OUTPUT 108 | echo $results >> $GITHUB_OUTPUT 109 | echo 'EOF' >> $GITHUB_OUTPUT 110 | env: 111 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 112 | 113 | - name: Build message - step results 114 | id: build-message-step-results 115 | uses: skills/action-text-variables@v1 116 | with: 117 | template-file: skills-response-templates/step-feedback/step-results.md 118 | template-vars: '{ 119 | "step_number": 3, 120 | "passed": ${{ steps.check-user-work.outputs.passed }}, 121 | "results_table": ${{ steps.check-user-work.outputs.results }}, 122 | "tips": [ 123 | "Copilot agent mode is becoming more capable everyday. Make sure to always be experimenting!", 124 | "Try different prompts and models." 125 | ] 126 | }' 127 | 128 | - name: Create comment - step results 129 | run: | 130 | gh issue comment "$ISSUE_URL" \ 131 | --body "$COMMENT_BODY" \ 132 | --edit-last 133 | env: 134 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 135 | COMMENT_BODY: ${{ steps.build-message-step-results.outputs.updated-text }} 136 | 137 | - name: Fail job if not all checks passed 138 | if: steps.check-user-work.outputs.passed == 'false' 139 | run: exit 1 140 | 141 | # END: Check practical exercise 142 | 143 | - name: Build message - step finished 144 | id: build-message-step-finish 145 | uses: skills/action-text-variables@v1 146 | with: 147 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 148 | template-vars: | 149 | next_step_number=4 150 | 151 | - name: Update comment - step finished 152 | run: | 153 | gh issue comment "$ISSUE_URL" \ 154 | --body "$ISSUE_BODY" 155 | env: 156 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 157 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 158 | 159 | post_next_step_content: 160 | name: Post next step content 161 | needs: [find_exercise, check_step_work] 162 | runs-on: ubuntu-latest 163 | env: 164 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 165 | 166 | steps: 167 | - name: Checkout 168 | uses: actions/checkout@v4 169 | 170 | - name: Get response templates 171 | uses: actions/checkout@v4 172 | with: 173 | repository: skills/response-templates 174 | path: skills-response-templates 175 | 176 | - name: Create comment - add step content 177 | run: | 178 | gh issue comment "$ISSUE_URL" \ 179 | --body-file "$STEP_4_FILE" 180 | env: 181 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 182 | 183 | - name: Create comment - watching for progress 184 | run: | 185 | gh issue comment "$ISSUE_URL" \ 186 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 187 | env: 188 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 189 | 190 | - name: Disable current workflow and enable next one 191 | run: | 192 | gh workflow disable "Step 3" 193 | gh workflow enable "Step 4" 194 | env: 195 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 196 | -------------------------------------------------------------------------------- /.github/workflows/4-setup-django-rest-framework.yml: -------------------------------------------------------------------------------- 1 | name: Step 4 # Setup the Django REST API framework 2 | 3 | on: 4 | push: 5 | branches: 6 | - "build-octofit-app" 7 | paths: 8 | - "octofit-tracker/backend/octofit_tracker/**" 9 | 10 | permissions: 11 | contents: read 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | STEP_5_FILE: ".github/steps/5-setup-frontend-react-framework.md" 17 | 18 | jobs: 19 | find_exercise: 20 | name: Find Exercise Issue 21 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 22 | 23 | check_step_work: 24 | name: Check step work 25 | runs-on: ubuntu-latest 26 | needs: [find_exercise] 27 | env: 28 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Get response templates 35 | uses: actions/checkout@v4 36 | with: 37 | repository: skills/response-templates 38 | path: skills-response-templates 39 | 40 | - name: Update comment - checking work 41 | run: | 42 | gh issue comment "$ISSUE_URL" \ 43 | --body-file skills-response-templates/step-feedback/checking-work.md \ 44 | --edit-last 45 | env: 46 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | # START: Check practical exercise 49 | 50 | - name: Check codespace url has been added to settings.py and views.py 51 | id: check-user-work 52 | run: | 53 | # Checks to perform 54 | checks='{ 55 | "settings_py": { 56 | "name": "settings.py", 57 | "passed": true, 58 | "message": "" 59 | }, 60 | "views_py": { 61 | "name": "views.py", 62 | "passed": true, 63 | "message": "" 64 | } 65 | }' 66 | 67 | # Check for codespace Django REST API endpoint suffix in settings.py 68 | file="octofit-tracker/backend/octofit_tracker/settings.py" 69 | keyphrase='\-8000.app.github.dev' 70 | minimum_occurences=1 71 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 72 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 73 | checks=$(echo $checks | jq '.settings_py.passed = false') 74 | checks=$(echo $checks | jq '.settings_py.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to settings.py."') 75 | fi 76 | 77 | # Check for codespace Django REST API endpoint suffix in views.py 78 | file="octofit-tracker/backend/octofit_tracker/views.py" 79 | keyphrase='\-8000.app.github.dev' 80 | minimum_occurences=1 81 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 82 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 83 | checks=$(echo $checks | jq '.views_py.passed = false') 84 | checks=$(echo $checks | jq '.views_py.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to views.py."') 85 | fi 86 | 87 | # Verify all checks passed 88 | passed=$(echo $checks | jq '. | all(.passed?)') 89 | 90 | # Flatten to an array for returning. Allows iteration during rendering. 91 | results=$(echo $checks | jq 'to_entries | map({name: .key} + .value)') 92 | 93 | # Save pass status to output 94 | echo "passed=$passed" >> $GITHUB_OUTPUT 95 | 96 | # Save results to output 97 | echo 'results<> $GITHUB_OUTPUT 98 | echo $results >> $GITHUB_OUTPUT 99 | echo 'EOF' >> $GITHUB_OUTPUT 100 | env: 101 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 102 | 103 | - name: Build message - step results 104 | id: build-message-step-results 105 | uses: skills/action-text-variables@v1 106 | with: 107 | template-file: skills-response-templates/step-feedback/step-results.md 108 | template-vars: '{ 109 | "step_number": 4, 110 | "passed": ${{ steps.check-user-work.outputs.passed }}, 111 | "results_table": ${{ steps.check-user-work.outputs.results }}, 112 | "tips": [ 113 | "Copilot agent mode is becoming more capable everyday. Make sure to always be experimenting!", 114 | "Try different prompts and models." 115 | ] 116 | }' 117 | 118 | - name: Create comment - step results 119 | run: | 120 | gh issue comment "$ISSUE_URL" \ 121 | --body "$COMMENT_BODY" \ 122 | --edit-last 123 | env: 124 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 125 | COMMENT_BODY: ${{ steps.build-message-step-results.outputs.updated-text }} 126 | 127 | - name: Fail job if not all checks passed 128 | if: steps.check-user-work.outputs.passed == 'false' 129 | run: exit 1 130 | 131 | # END: Check practical exercise 132 | 133 | - name: Build message - step finished 134 | id: build-message-step-finish 135 | uses: skills/action-text-variables@v1 136 | with: 137 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 138 | template-vars: | 139 | next_step_number=5 140 | 141 | - name: Update comment - step finished 142 | run: | 143 | gh issue comment "$ISSUE_URL" \ 144 | --body "$ISSUE_BODY" 145 | env: 146 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 147 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 148 | 149 | post_next_step_content: 150 | name: Post next step content 151 | needs: [find_exercise, check_step_work] 152 | runs-on: ubuntu-latest 153 | env: 154 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 155 | 156 | steps: 157 | - name: Checkout 158 | uses: actions/checkout@v4 159 | 160 | - name: Get response templates 161 | uses: actions/checkout@v4 162 | with: 163 | repository: skills/response-templates 164 | path: skills-response-templates 165 | 166 | - name: Create comment - add step content 167 | run: | 168 | gh issue comment "$ISSUE_URL" \ 169 | --body-file "$STEP_5_FILE" 170 | env: 171 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 172 | 173 | - name: Create comment - watching for progress 174 | run: | 175 | gh issue comment "$ISSUE_URL" \ 176 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 177 | env: 178 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 179 | 180 | - name: Disable current workflow and enable next one 181 | run: | 182 | gh workflow disable "Step 4" 183 | gh workflow enable "Step 5" 184 | env: 185 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 186 | -------------------------------------------------------------------------------- /.github/workflows/5-setup-frontend-react-framework.yml: -------------------------------------------------------------------------------- 1 | name: Step 5 # Setup the REACT framework frontend 2 | 3 | on: 4 | push: 5 | branches: 6 | - "build-octofit-app" 7 | paths: 8 | - "octofit-tracker/frontend/**" 9 | 10 | permissions: 11 | contents: read 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | STEP_6_FILE: ".github/steps/6-copilot-on-github.md" 17 | 18 | jobs: 19 | find_exercise: 20 | name: Find Exercise Issue 21 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 22 | 23 | check_step_work: 24 | name: Check step work 25 | runs-on: ubuntu-latest 26 | needs: [find_exercise] 27 | env: 28 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Get response templates 35 | uses: actions/checkout@v4 36 | with: 37 | repository: skills/response-templates 38 | path: skills-response-templates 39 | 40 | - name: Update comment - checking work 41 | run: | 42 | gh issue comment "$ISSUE_URL" \ 43 | --body-file skills-response-templates/step-feedback/checking-work.md \ 44 | --edit-last 45 | env: 46 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | # START: Check practical exercise 49 | 50 | - name: Check for codespace Django REST API endpoint suffix in all components 51 | id: check-user-work 52 | run: | 53 | # Checks to perform 54 | checks='{ 55 | "activities_js": { 56 | "name": "Activities.js", 57 | "passed": true, 58 | "message": "" 59 | }, 60 | "leaderboard_js": { 61 | "name": "Leaderboard.js", 62 | "passed": true, 63 | "message": "" 64 | }, 65 | "teams_js": { 66 | "name": "Teams.js", 67 | "passed": true, 68 | "message": "" 69 | }, 70 | "users_js": { 71 | "name": "Users.js", 72 | "passed": true, 73 | "message": "" 74 | }, 75 | "workouts_js": { 76 | "name": "Workouts.js", 77 | "passed": true, 78 | "message": "" 79 | } 80 | }' 81 | 82 | # Check for codespace Django REST API endpoint suffix in Activities.js 83 | file="octofit-tracker/frontend/src/components/Activities.js" 84 | keyphrase='\-8000.app.github.dev\/api\/activities' 85 | minimum_occurences=1 86 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 87 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 88 | checks=$(echo $checks | jq '.activities_js.passed = false') 89 | checks=$(echo $checks | jq '.activities_js.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to Activities.js."') 90 | fi 91 | 92 | # Check for codespace Django REST API endpoint suffix in Leaderboard.js 93 | file="octofit-tracker/frontend/src/components/Leaderboard.js" 94 | keyphrase='\-8000.app.github.dev\/api\/leaderboard' 95 | minimum_occurences=1 96 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 97 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 98 | checks=$(echo $checks | jq '.leaderboard_js.passed = false') 99 | checks=$(echo $checks | jq '.leaderboard_js.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to Leaderboard.js."') 100 | fi 101 | 102 | # Check for codespace Django REST API endpoint suffix in Teams.js 103 | file="octofit-tracker/frontend/src/components/Teams.js" 104 | keyphrase='\-8000.app.github.dev\/api\/teams' 105 | minimum_occurences=1 106 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 107 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 108 | checks=$(echo $checks | jq '.teams_js.passed = false') 109 | checks=$(echo $checks | jq '.teams_js.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to Teams.js."') 110 | fi 111 | 112 | # Check for codespace Django REST API endpoint suffix in Users.js 113 | file="octofit-tracker/frontend/src/components/Users.js" 114 | keyphrase='\-8000.app.github.dev\/api\/users' 115 | minimum_occurences=1 116 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 117 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 118 | checks=$(echo $checks | jq '.users_js.passed = false') 119 | checks=$(echo $checks | jq '.users_js.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to Users.js."') 120 | fi 121 | 122 | # Check for codespace Django REST API endpoint suffix in Workouts.js 123 | file="octofit-tracker/frontend/src/components/Workouts.js" 124 | keyphrase='\-8000.app.github.dev\/api\/workouts' 125 | minimum_occurences=1 126 | found_occurences=$(grep -o "$keyphrase" "$file" | wc -l) 127 | if [ "$found_occurences" -lt "$minimum_occurences" ]; then 128 | checks=$(echo $checks | jq '.workouts_js.passed = false') 129 | checks=$(echo $checks | jq '.workouts_js.message = "Please use Copilot agent mode to add the codespace Django REST API endpoint suffix to Workouts.js."') 130 | fi 131 | 132 | # Verify all checks passed 133 | passed=$(echo $checks | jq '. | all(.passed?)') 134 | 135 | # Flatten to an array for returning. Allows iteration during rendering. 136 | results=$(echo $checks | jq 'to_entries | map({name: .key} + .value)') 137 | 138 | # Save pass status to output 139 | echo "passed=$passed" >> $GITHUB_OUTPUT 140 | 141 | # Save results to output 142 | echo 'results<> $GITHUB_OUTPUT 143 | echo $results >> $GITHUB_OUTPUT 144 | echo 'EOF' >> $GITHUB_OUTPUT 145 | env: 146 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 147 | 148 | - name: Build message - step results 149 | id: build-message-step-results 150 | uses: skills/action-text-variables@v1 151 | with: 152 | template-file: skills-response-templates/step-feedback/step-results.md 153 | template-vars: '{ 154 | "step_number": 4, 155 | "passed": ${{ steps.check-user-work.outputs.passed }}, 156 | "results_table": ${{ steps.check-user-work.outputs.results }}, 157 | "tips": [ 158 | "Copilot agent mode is becoming more capable everyday. Make sure to always be experimenting!", 159 | "Try different prompts and models." 160 | ] 161 | }' 162 | 163 | - name: Create comment - step results 164 | run: | 165 | gh issue comment "$ISSUE_URL" \ 166 | --body "$COMMENT_BODY" \ 167 | --edit-last 168 | env: 169 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 170 | COMMENT_BODY: ${{ steps.build-message-step-results.outputs.updated-text }} 171 | 172 | - name: Fail job if not all checks passed 173 | if: steps.check-user-work.outputs.passed == 'false' 174 | run: exit 1 175 | 176 | # END: Check practical exercise 177 | 178 | - name: Build message - step finished 179 | id: build-message-step-finish 180 | uses: skills/action-text-variables@v1 181 | with: 182 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 183 | template-vars: | 184 | next_step_number=6 185 | 186 | - name: Update comment - step finished 187 | run: | 188 | gh issue comment "$ISSUE_URL" \ 189 | --body "$ISSUE_BODY" 190 | env: 191 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 192 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 193 | 194 | post_next_step_content: 195 | name: Post next step content 196 | needs: [find_exercise, check_step_work] 197 | runs-on: ubuntu-latest 198 | env: 199 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 200 | 201 | steps: 202 | - name: Checkout 203 | uses: actions/checkout@v4 204 | 205 | - name: Get response templates 206 | uses: actions/checkout@v4 207 | with: 208 | repository: skills/response-templates 209 | path: skills-response-templates 210 | 211 | - name: Create comment - add step content 212 | run: | 213 | gh issue comment "$ISSUE_URL" \ 214 | --body-file "$STEP_6_FILE" 215 | env: 216 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 217 | 218 | - name: Create comment - watching for progress 219 | run: | 220 | gh issue comment "$ISSUE_URL" \ 221 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 222 | env: 223 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 224 | 225 | - name: Disable current workflow and enable next one 226 | run: | 227 | gh workflow disable "Step 5" 228 | gh workflow enable "Step 6" 229 | env: 230 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 231 | -------------------------------------------------------------------------------- /.github/workflows/6-copilot-on-github.yml: -------------------------------------------------------------------------------- 1 | name: Step 6 # Copilot on GitHub 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | types: 8 | - closed 9 | 10 | permissions: 11 | contents: write 12 | actions: write 13 | issues: write 14 | 15 | env: 16 | REVIEW_FILE: ".github/steps/x-review.md" 17 | 18 | jobs: 19 | find_exercise: 20 | name: Find Exercise Issue 21 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 22 | 23 | check_step_work: 24 | name: Check step work 25 | runs-on: ubuntu-latest 26 | needs: [find_exercise] 27 | env: 28 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Get response templates 35 | uses: actions/checkout@v4 36 | with: 37 | repository: skills/response-templates 38 | path: skills-response-templates 39 | 40 | # START: Check practical exercise 41 | 42 | # Nothing to check. Merging the pull request is enough. 43 | 44 | # END: Check practical exercise 45 | 46 | - name: Create comment - step finished - final review next 47 | run: | 48 | gh issue comment "$ISSUE_URL" \ 49 | --body-file skills-response-templates/step-feedback/lesson-review.md 50 | env: 51 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | 53 | post_review_content: 54 | name: Post review content 55 | needs: [find_exercise, check_step_work] 56 | runs-on: ubuntu-latest 57 | env: 58 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 59 | 60 | steps: 61 | - name: Checkout 62 | uses: actions/checkout@v4 63 | 64 | - name: Get response templates 65 | uses: actions/checkout@v4 66 | with: 67 | repository: skills/response-templates 68 | path: skills-response-templates 69 | 70 | - name: Create comment - add step content 71 | run: | 72 | gh issue comment "$ISSUE_URL" \ 73 | --body-file "$REVIEW_FILE" 74 | env: 75 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 76 | 77 | finish_exercise: 78 | name: Finish exercise 79 | needs: [find_exercise, post_review_content] 80 | runs-on: ubuntu-latest 81 | env: 82 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 83 | 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | with: 88 | ref: main 89 | 90 | - name: Get response templates 91 | uses: actions/checkout@v4 92 | with: 93 | repository: skills/response-templates 94 | path: skills-response-templates 95 | 96 | - name: Configure Git user 97 | run: | 98 | git config user.name github-actions[bot] 99 | git config user.email github-actions[bot]@users.noreply.github.com 100 | 101 | - name: Build message - congratulations 102 | id: build-message-congratulations 103 | uses: skills/action-text-variables@v1 104 | with: 105 | template-file: skills-response-templates/readme/congratulations.md 106 | template-vars: | 107 | login=${{ github.actor }} 108 | 109 | - name: Update README - congratulations 110 | run: | 111 | # Add "Congratulations" to the start of the README 112 | orig_readme=$(cat README.md) 113 | new_readme="${{ steps.build-message-congratulations.outputs.updated-text }} $orig_readme" 114 | 115 | # Update file and push 116 | echo "$new_readme" > README.md 117 | git add README.md 118 | git commit --message="Congratulations!🎉" 119 | git push 120 | env: 121 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 122 | 123 | - name: Build message - exercise finished 124 | id: build-finish-message 125 | uses: skills/action-text-variables@v1 126 | with: 127 | template-file: skills-response-templates/step-feedback/lesson-finished.md 128 | template-vars: | 129 | login=${{ github.actor }} 130 | repo_full_name=${{ github.repository }} 131 | 132 | - name: Create comment - exercise finished 133 | run: | 134 | gh issue comment "$ISSUE_URL" \ 135 | --body "$ISSUE_BODY" 136 | env: 137 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 138 | ISSUE_BODY: ${{ steps.build-finish-message.outputs.updated-text }} 139 | 140 | - name: Close issue 141 | run: gh issue close "$ISSUE_URL" 142 | env: 143 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 144 | 145 | - name: Disable current workflow 146 | run: | 147 | gh workflow disable "Step 6" 148 | # gh workflow disable "Step 6b" 149 | env: 150 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 151 | -------------------------------------------------------------------------------- /.github/workflows/6b-copilot-on-github.yml: -------------------------------------------------------------------------------- 1 | name: Step 6b # Copilot on GitHub 2 | 3 | on: 4 | # Trigger if Copilot adds a review comment 5 | pull_request_review: 6 | 7 | permissions: 8 | contents: write 9 | actions: write 10 | issues: write 11 | pull-requests: read 12 | repository-projects: read 13 | 14 | jobs: 15 | find_exercise: 16 | name: Find Exercise Issue 17 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.1.0 18 | 19 | check_step_work: 20 | name: Check step work 21 | runs-on: ubuntu-latest 22 | needs: [find_exercise] 23 | env: 24 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | 30 | - name: Get response templates 31 | uses: actions/checkout@v4 32 | with: 33 | repository: skills/response-templates 34 | path: skills-response-templates 35 | 36 | # START: Check practical exercise 37 | 38 | - name: Check for pr description and copilot review 39 | id: check-user-work 40 | run: | 41 | # Checks to perform 42 | checks='{ 43 | "pr_description": { 44 | "name": "PR Description", 45 | "passed": true, 46 | "message": "" 47 | }, 48 | "copilot_review": { 49 | "name": "Copilot Review", 50 | "passed": true, 51 | "message": "" 52 | } 53 | }' 54 | 55 | # Check if PR has a description and minimum length 56 | min_length=15 57 | body_length=$(echo "$PR_Body" | wc -c) 58 | echo "PR description length: $body_length" 59 | if [ "$body_length" -lt $min_length ]; then 60 | checks=$(echo $checks | jq '.pr_description.passed = false') 61 | checks=$(echo $checks | jq '.pr_description.message = "Please use Copilot to generate a pull request description."') 62 | fi 63 | 64 | # Check for a PR Review from Copilot 65 | reviews=$(gh pr view --repo $REPO $PR_NUMBER --json reviews) 66 | authors=$(echo "$reviews" | jq '.reviews[].author.login') 67 | if echo "$authors" | grep -q "copilot-pull-request-reviewer"; then 68 | echo "Copilot has reviewed this PR." 69 | else 70 | echo "Copilot has NOT reviewed this PR." 71 | checks=$(echo $checks | jq '.copilot_review.passed = false') 72 | checks=$(echo $checks | jq '.copilot_review.message = "Please request a review from Copilot."') 73 | fi 74 | 75 | # Verify all checks passed 76 | passed=$(echo $checks | jq '. | all(.passed?)') 77 | 78 | # Flatten to an array for returning. Allows iteration during rendering. 79 | results=$(echo $checks | jq 'to_entries | map({name: .key} + .value)') 80 | 81 | # Save pass status to output 82 | echo "passed=$passed" >> $GITHUB_OUTPUT 83 | 84 | # Save results to output 85 | echo 'results<> $GITHUB_OUTPUT 86 | echo $results >> $GITHUB_OUTPUT 87 | echo 'EOF' >> $GITHUB_OUTPUT 88 | env: 89 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 90 | PR_Body: ${{ github.event.pull_request.body }} 91 | REPO: ${{ github.repository }} 92 | PR_NUMBER: ${{ github.event.pull_request.number }} 93 | 94 | - name: Build message - step results 95 | id: build-message-step-results 96 | uses: skills/action-text-variables@v1 97 | with: 98 | template-file: skills-response-templates/step-feedback/step-results.md 99 | template-vars: '{ 100 | "step_number": 6, 101 | "passed": ${{ steps.check-user-work.outputs.passed }}, 102 | "results_table": ${{ steps.check-user-work.outputs.results }}, 103 | "tips": [ 104 | "Copilot review will also suggest changes for common mistakes and typos.", 105 | "You can use repository rulesets to automatically require a review from Copilot." 106 | ] 107 | }' 108 | 109 | - name: Create comment - step results 110 | run: | 111 | gh issue comment "$ISSUE_URL" \ 112 | --body "$COMMENT_BODY" 113 | env: 114 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 115 | COMMENT_BODY: ${{ steps.build-message-step-results.outputs.updated-text }} 116 | 117 | - name: Fail job if not all checks passed 118 | if: steps.check-user-work.outputs.passed == 'false' 119 | run: exit 1 120 | 121 | # END: Check practical exercise 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Virtual Environment 4 | venv 5 | 6 | # octofit tracker app 7 | # octfit-tracker 8 | 9 | # React node_modules 10 | node_modules 11 | /.pnp 12 | .pnp.js 13 | 14 | # testing 15 | /coverage 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | .env.local 23 | .env.development.local 24 | .env.test.local 25 | .env.production.local 26 | 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | 31 | # Python files 32 | *.pyc 33 | __pycache__/ 34 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Django Backend", 6 | "type": "python", 7 | "request": "launch", 8 | "program": "${workspaceFolder}/octofit-tracker/backend/manage.py", 9 | "args": ["runserver", "0.0.0.0:8000"], 10 | "django": true, 11 | "justMyCode": true, 12 | "python": "${workspaceFolder}/octofit-tracker/backend/venv/bin/python", 13 | "env": { 14 | "PYTHONPATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin/python", 15 | "VIRTUAL_ENV": "${workspaceFolder}/octofit-tracker/backend/venv", 16 | "PATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin:${env:PATH}" 17 | } 18 | }, 19 | { 20 | "name": "Launch React Frontend", 21 | "type": "node", 22 | "request": "launch", 23 | "program": "${workspaceFolder}/octofit-tracker/frontend/node_modules/react-scripts/scripts/start.js", 24 | "cwd": "${workspaceFolder}/octofit-tracker/frontend", 25 | "runtimeExecutable": "npm", 26 | "runtimeArgs": ["start"], 27 | "port": 3000 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 GitHub Skills 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build applications with GitHub Copilot agent mode 2 | 3 | 4 | 5 | 6 | _Build an application with GitHub Copilot agent mode in less than an hour._ 7 | 8 | ## Welcome 9 | 10 | People love how GitHub Copilot helps them write code faster and with fewer errors. 11 | But what if GitHub could create a full stack application for your job role based on requirements 12 | written in natural language? 13 | In this exercise, we will prompt GitHub Copilot agent mode to create us a complete application. 14 | 15 | - **Who is this for**: Intermediate developers familiar with GitHub Copilot, basic GitHub, and basic web development 16 | - **What you'll learn**: We'll introduce GitHub Copilot agent mode and how to use it for application development. 17 | - **What you'll build**: You'll use GitHub Copilot agent mode to create a fitness application as the gym teacher of a high school. 18 | - **Prerequisites**: Skills Exercise: Getting Started with GitHub Copilot. 19 | - **How long**: This course takes less than one hour to complete. 20 | 21 | In this exercise, you will: 22 | 23 | 1. Start up a preconfigured development environment for making a full stack application. 24 | 2. Prompt in GitHub Copilot Chat and select the edit tab and select agent mode from the edit/agent drop-down. 25 | 3. Try creating the application with GPT-4o. 26 | 4. Try other LLM models to see other output. 27 | 28 | ### How to start this exercise 29 | 30 | 1. Right-click **Copy Exercise** and open the link in a new tab. 31 | 32 | 33 | 34 | 35 | 36 | 2. In the new tab, most of the fields will automatically fill in for you. 37 | 38 | - For owner, choose your personal account or an organization to host the repository. 39 | - 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). 40 | - Scroll down and click the **Create repository** button at the bottom of the form. 41 | 42 | 3. After your new repository is created, wait about 20 seconds for the course to be prepared. 43 | 44 | - The **Copy Exercise** button will deactivate, changing to gray. 45 | - The **Start Exercise** button will activate, changing to green. 46 | 47 | 4. Click **Start Exercise**. Follow the step-by-step instructions and feedback will be provided as you progress. 48 | 49 | 50 | 51 | 52 | 53 | 54 | > ❕ **Important:** The **Start Exercise** button will activate after copying the repository. You will probably need to refresh the page. 55 | 56 | --- 57 | 58 | Get help: [Post in our discussion board](https://github.com/orgs/skills/discussions/categories/introduction-to-github) • [Review the GitHub status page](https://www.githubstatus.com/) 59 | 60 | © 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) 61 | -------------------------------------------------------------------------------- /docs/mona-high-school-fitness-tracker.md: -------------------------------------------------------------------------------- 1 | # Getting started - app frontend and backend creation 2 | 3 | ## Explain to GitHub Copilot the goals and steps 4 | 5 | ```text 6 | I want to build an monafit Tracker app that will include the following: 7 | 8 | * User authentication and profiles 9 | * Activity logging and tracking 10 | * Team creation and management 11 | * Competitive leader board 12 | * Personalized workout suggestions 13 | 14 | It should be in one app 15 | 16 | generate instructions in this order 17 | 18 | 1. Create the frontend and backend in the monafit-tracker directory structure of this repository in one command 19 | 2. Setup backend python venv and create a monafit-tracker/backend/requirements.txt file 20 | 3. The monafit-tracker/backend directory will store the django project and app with the name monafit-tracker 21 | 4. The Django project monafit-tracker directory will have all the backend components for the app 22 | 5. Create the django app directly in the directory monafit_tracker/backend 23 | 6. Setup the monafit-tracker/frontend directory will store the react app with no subdirectories 24 | 7. Install react framework 25 | 8. Install bootstrap and import it 26 | 9. Commands to install mongodb via 'apt-get' 27 | 10. Commands start mongodb with the 'sudo service mongodb start' and 'sudo service mongodb status' 28 | 29 | The directory tree for the monafit Tracker App 30 | monafit-tracker/ 31 | ├── backend/ 32 | │ ├── venv/ 33 | │ ├── monafit_tracker/ 34 | │ │ ├── __init__.py 35 | │ │ ├── models.py 36 | │ │ ├── serializers.py 37 | │ │ ├── settings.py 38 | │ │ ├── views.py 39 | │ │ ├── urls.py 40 | │ │ ├── wsgi.py 41 | │ │ └── asgi.py 42 | └── frontend/ 43 | ├── node_modules/ 44 | ├── public/ 45 | ├── src/ 46 | ├── package.json 47 | └── README.md 48 | 49 | Create a requirements.txt with the following Python required packages 50 | 51 | Django==4.1 52 | djangorestframework==3.14.0 53 | django-allauth==0.51.0 54 | django-cors-headers==4.5.0 55 | dj-rest-auth 56 | djongo==1.3.6 57 | pymongo==3.12 58 | sqlparse==0.2.4 59 | stack-data==0.6.3 60 | sympy==1.12 61 | tenacity==9.0.0 62 | terminado==0.18.1 63 | threadpoolctl==3.5.0 64 | tinycss2==1.3.0 65 | tornado==6.4.1 66 | traitlets==5.14.3 67 | types-python-dateutil==2.9.0.20240906 68 | typing_extensions==4.9.0 69 | tzdata==2024.2 70 | uri-template==1.3.0 71 | urllib3==2.2.3 72 | wcwidth==0.2.13 73 | webcolors==24.8.0 74 | webencodings==0.5.1 75 | websocket-client==1.8.0 76 | 77 | All of the backend django app will be in monafit_tracker and do NOT create another app of any kind 78 | 79 | Use a Python virtual environment and install all python dependencies from file monafit-tracker/backend/requirements.txt in this workspace 80 | 81 | The monafit-tracker/backend/requirements.txt already contains all Django requirements. Django, djongo, sqlparse 82 | 83 | Layout the directory structure with no redundant backend and frontend subdirectories 84 | 85 | Use bootstrap for the frontend 86 | 87 | Let's think about this step by step 88 | ``` 89 | 90 | ### Commands to use to create the monafit Tracker structure 91 | 92 | ```bash 93 | mkdir -p monafit-tracker/{backend,frontend} 94 | 95 | python3 -m venv monafit-tracker/backend/venv 96 | source monafit-tracker/backend/venv/bin/activate 97 | pip install -r monafit-tracker/backend/requirements.txt 98 | 99 | django-admin startproject monafit_tracker monafit-tracker/backend 100 | 101 | npx create-react-app monafit-tracker/frontend 102 | 103 | npm install bootstrap monafit-tracker/frontend 104 | 105 | echo "import 'bootstrap/dist/css/bootstrap.min.css';" >> src/index.js 106 | 107 | sudo apt-get update && sudo apt-get install -y mongodb 108 | sudo service mongodb start && sudo service mongodb status 109 | ``` 110 | 111 | ## Initialize the database, setup database and install apps in settings.py, models, serializers, urls, and views 112 | 113 | Type the following prompt in GitHub Copilot Chat: 114 | 115 | ```text 116 | In our next steps lets think step by step and setup the following in this order 117 | 118 | 1. Initialize the mongo monafit_db database and create a correct table structure for users, teams, activities, leaderboard, and workouts collections 119 | 2. Make sure there is a unique id for primary key for the user collection 120 | ex. db.users.createIndex({ "email": 1 }, { unique: true }) 121 | 3. settings.py in our django project for mongodb monafit_db database including localhost and the port 122 | 4. settings.py in our django project setup for all installed apps. ex djongo, monafit_tracker, rest_framework 123 | 5. In monafit_tracker project setup and use command touch models.py, serializers.py, urls.py, and views.py for users, teams, activity, leaderboard, and workouts 124 | 6. Generate code for models.py, serializers.py, and views.py and 125 | 7. make sure urls.py has a root, admin, and api endpoints 126 | urlpatterns = [ 127 | path('', api_root, name='api-root'), # Root endpoint 128 | path('admin/', admin.site.urls), # Admin endpoint 129 | path('api/', include(router.urls)), # API endpoint 130 | ] 131 | ``` 132 | 133 | ### MongoDB commands to initialize and setup `monafit_db` 134 | 135 | ```bash 136 | mongo --eval "db = db.getSiblingDB('monafit_db'); db.createCollection('users'); db.createCollection('teams'); db.createCollection('activity'); db.createCollection('leaderboard'); db.createCollection('workouts'); db.users.createIndex({ email: 1 }, { unique: true }); db.teams.createIndex({ name: 1 }, { unique: true }); db.activity.createIndex({ activity_id: 1 }, { unique: true }); db.leaderboard.createIndex({ leaderboard_id: 1 }, { unique: true }); db.workouts.createIndex({ workout_id: 1 }, { unique: true });" 137 | ``` 138 | 139 | ### Check the database collections 140 | 141 | ```bash 142 | mongo --eval "db = db.getSiblingDB('monafit_db'); printjson(db.getCollectionNames());" 143 | ``` 144 | 145 | ### Sample settings.py 146 | 147 | ```json 148 | # FILE: monafit_tracker/settings.py 149 | 150 | """ 151 | Django settings for monafit_tracker project. 152 | 153 | Generated by 'django-admin startproject' using Django 4.1. 154 | 155 | For more information on this file, see 156 | https://docs.djangoproject.com/en/4.1/topics/settings/ 157 | 158 | For the full list of settings and their values, see 159 | https://docs.djangoproject.com/en/4.1/ref/settings/ 160 | """ 161 | 162 | from pathlib import Path 163 | 164 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 165 | BASE_DIR = Path(__file__).resolve().parent.parent 166 | 167 | 168 | # Quick-start development settings - unsuitable for production 169 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 170 | 171 | # SECURITY WARNING: keep the secret key used in production secret! 172 | SECRET_KEY = "django-insecure-25rsll_s*6ml5lv4l$51z6x!y5u_k!11f!hf^1&%q!$syk=ja3" 173 | 174 | # SECURITY WARNING: don't run with debug turned on in production! 175 | DEBUG = True 176 | 177 | ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'congenial-robot-pwrx4jxpp9c6vjv-8000.app.github.dev'] 178 | 179 | 180 | # Application definition 181 | 182 | INSTALLED_APPS = [ 183 | "django.contrib.admin", 184 | "django.contrib.auth", 185 | "django.contrib.contenttypes", 186 | "django.contrib.sessions", 187 | "django.contrib.messages", 188 | "django.contrib.staticfiles", 189 | 'rest_framework', 190 | 'djongo', 191 | 'corsheaders', 192 | 'monafit_tracker', 193 | ] 194 | 195 | MIDDLEWARE = [ 196 | "django.middleware.security.SecurityMiddleware", 197 | "django.contrib.sessions.middleware.SessionMiddleware", 198 | "django.middleware.common.CommonMiddleware", 199 | "django.middleware.csrf.CsrfViewMiddleware", 200 | "django.contrib.auth.middleware.AuthenticationMiddleware", 201 | "django.contrib.messages.middleware.MessageMiddleware", 202 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 203 | 'corsheaders.middleware.CorsMiddleware', 204 | ] 205 | 206 | ROOT_URLCONF = "monafit_tracker.urls" 207 | 208 | TEMPLATES = [ 209 | { 210 | "BACKEND": "django.template.backends.django.DjangoTemplates", 211 | "DIRS": [], 212 | "APP_DIRS": True, 213 | "OPTIONS": { 214 | "context_processors": [ 215 | "django.template.context_processors.debug", 216 | "django.template.context_processors.request", 217 | "django.contrib.auth.context_processors.auth", 218 | "django.contrib.messages.context_processors.messages", 219 | ], 220 | }, 221 | }, 222 | ] 223 | 224 | WSGI_APPLICATION = "monafit_tracker.wsgi.application" 225 | 226 | 227 | # Database 228 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 229 | 230 | DATABASES = { 231 | 'default': { 232 | 'ENGINE': 'djongo', 233 | 'NAME': 'monafit_db', 234 | 'HOST': 'localhost', 235 | 'PORT': 27017, 236 | } 237 | } 238 | 239 | 240 | # Password validation 241 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 242 | 243 | AUTH_PASSWORD_VALIDATORS = [ 244 | { 245 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 246 | }, 247 | { 248 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 249 | }, 250 | { 251 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 252 | }, 253 | { 254 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 255 | }, 256 | ] 257 | 258 | 259 | # Internationalization 260 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 261 | 262 | LANGUAGE_CODE = "en-us" 263 | 264 | TIME_ZONE = "UTC" 265 | 266 | USE_I18N = True 267 | 268 | USE_TZ = True 269 | 270 | 271 | # Static files (CSS, JavaScript, Images) 272 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 273 | 274 | STATIC_URL = "static/" 275 | 276 | # Default primary key field type 277 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 278 | 279 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 280 | 281 | CORS_ALLOW_ALL_ORIGINS = True 282 | ``` 283 | 284 | ### Sample code for models.py, serializers.py, views.py, and urls.py 285 | 286 | #### models.py 287 | 288 | ```python 289 | # FILE: monafit-tracker/backend/monafit_tracker/models.py 290 | 291 | from djongo import models 292 | 293 | class User(models.Model): 294 | _id = models.ObjectIdField() 295 | username = models.CharField(max_length=100) 296 | email = models.EmailField(unique=True) 297 | password = models.CharField(max_length=100) 298 | 299 | class Team(models.Model): 300 | _id = models.ObjectIdField() 301 | name = models.CharField(max_length=100) 302 | members = models.ArrayReferenceField(to=User, on_delete=models.CASCADE) 303 | 304 | class Activity(models.Model): 305 | _id = models.ObjectIdField() 306 | user = models.ForeignKey(User, on_delete=models.CASCADE) 307 | activity_type = models.CharField(max_length=100) 308 | duration = models.DurationField() 309 | 310 | class Leaderboard(models.Model): 311 | _id = models.ObjectIdField() 312 | user = models.ForeignKey(User, on_delete=models.CASCADE) 313 | score = models.IntegerField() 314 | 315 | class Workout(models.Model): 316 | _id = models.ObjectIdField() 317 | name = models.CharField(max_length=100) 318 | description = models.TextField() 319 | ``` 320 | 321 | #### serializers.py 322 | 323 | ```python 324 | from rest_framework import serializers 325 | from .models import User, Team, Activity, Leaderboard, Workout 326 | from bson import ObjectId 327 | 328 | class ObjectIdField(serializers.Field): 329 | def to_representation(self, value): 330 | return str(value) 331 | 332 | def to_internal_value(self, data): 333 | return ObjectId(data) 334 | 335 | class UserSerializer(serializers.ModelSerializer): 336 | _id = ObjectIdField() 337 | 338 | class Meta: 339 | model = User 340 | fields = '__all__' 341 | 342 | class TeamSerializer(serializers.ModelSerializer): 343 | _id = ObjectIdField() 344 | members = UserSerializer(many=True) 345 | 346 | class Meta: 347 | model = Team 348 | fields = '__all__' 349 | 350 | class ActivitySerializer(serializers.ModelSerializer): 351 | _id = ObjectIdField() 352 | user = ObjectIdField() 353 | 354 | class Meta: 355 | model = Activity 356 | fields = '__all__' 357 | 358 | class LeaderboardSerializer(serializers.ModelSerializer): 359 | _id = ObjectIdField() 360 | user = UserSerializer() # Expand the user object 361 | 362 | class Meta: 363 | model = Leaderboard 364 | fields = '__all__' 365 | 366 | class WorkoutSerializer(serializers.ModelSerializer): 367 | _id = ObjectIdField() 368 | 369 | class Meta: 370 | model = Workout 371 | fields = '__all__' 372 | ``` 373 | 374 | #### views.py 375 | 376 | ```python 377 | # FILE: monafit-tracker/backend/monafit_tracker/views.py 378 | 379 | from rest_framework import viewsets, status 380 | from rest_framework.decorators import api_view 381 | from rest_framework.response import Response 382 | from rest_framework.reverse import reverse 383 | from .serializers import UserSerializer, TeamSerializer, ActivitySerializer, LeaderboardSerializer, WorkoutSerializer 384 | from .models import User, Team, Activity, Leaderboard, Workout 385 | 386 | @api_view(['GET', 'POST']) 387 | def api_root(request, format=None): 388 | if request.method == 'POST': 389 | return Response({"message": "POST request received"}, status=status.HTTP_201_CREATED) 390 | 391 | base_url = '[USE CODESPACE URL]' 392 | return Response({ 393 | 'users': base_url + 'api/users/?format=api', 394 | 'teams': base_url + 'api/teams/?format=api', 395 | 'activities': base_url + 'api/activities/?format=api', 396 | 'leaderboard': base_url + 'api/leaderboard/?format=api', 397 | 'workouts': base_url + 'api/workouts/?format=api' 398 | }) 399 | 400 | class UserViewSet(viewsets.ModelViewSet): 401 | queryset = User.objects.all() 402 | serializer_class = UserSerializer 403 | 404 | class TeamViewSet(viewsets.ModelViewSet): 405 | queryset = Team.objects.all() 406 | serializer_class = TeamSerializer 407 | 408 | class ActivityViewSet(viewsets.ModelViewSet): 409 | queryset = Activity.objects.all() 410 | serializer_class = ActivitySerializer 411 | 412 | class LeaderboardViewSet(viewsets.ModelViewSet): 413 | queryset = Leaderboard.objects.all() 414 | serializer_class = LeaderboardSerializer 415 | 416 | class WorkoutViewSet(viewsets.ModelViewSet): 417 | queryset = Workout.objects.all() 418 | serializer_class = WorkoutSerializer 419 | ``` 420 | 421 | #### urls.py 422 | 423 | ```python 424 | # FILE: monafit-tracker/backend/monafit_tracker/urls.py 425 | 426 | from django.contrib import admin 427 | from django.urls import path, include 428 | from rest_framework.routers import DefaultRouter 429 | from .views import UserViewSet, TeamViewSet, ActivityViewSet, LeaderboardViewSet, WorkoutViewSet, api_root 430 | 431 | router = DefaultRouter() 432 | router.register(r'users', UserViewSet) 433 | router.register(r'teams', TeamViewSet) 434 | router.register(r'activities', ActivityViewSet) 435 | router.register(r'leaderboard', LeaderboardViewSet) 436 | router.register(r'workouts', WorkoutViewSet) 437 | 438 | urlpatterns = [ 439 | path('', api_root, name='api-root'), # Root endpoint 440 | path('admin/', admin.site.urls), # Admin endpoint 441 | path('api/', include(router.urls)), # API endpoint 442 | ] 443 | ``` 444 | 445 | ## Populate the databse with sample data 446 | 447 | ```text 448 | Let's use manage.py to get the database setup and populated based on fields in models.py 449 | 450 | - Create populate_db.py as a manage.py command so it initializes and deletes previous data and recreates it 451 | - populate_db.py creates users, teams, activity, leaderboard, and workouts 452 | - users will be super hero users 453 | - Include steps to migrate in the monafit_tracker project 454 | ``` 455 | 456 | ### Commands to create the directory structure for populate_db.py 457 | 458 | ```bash 459 | mkdir -p monafit-tracker/backend/monafit_tracker/management/commands 460 | touch monafit-tracker/backend/monafit_tracker/management/__init__.py 461 | touch monafit-tracker/backend/monafit_tracker/management/commands/__init__.py 462 | touch monafit-tracker/backend/monafit_tracker/management/commands/populate_db.py 463 | ``` 464 | 465 | ### Sample code for populate_db.py to populate the database 466 | 467 | Mergington Physical Education sample data use for populate_db.py 468 | Should reside under monafit-tracker/backend/monafit_tracker/management/commands/populate_db.py 469 | 470 | ```python 471 | # FILE: monafit-tracker/backend/monafit_tracker/management/commands/populate_db.py 472 | 473 | from django.core.management.base import BaseCommand 474 | from monafit_tracker.models import User, Team, Activity, Leaderboard, Workout 475 | from django.conf import settings 476 | from pymongo import MongoClient 477 | from datetime import timedelta 478 | from bson import ObjectId 479 | 480 | class Command(BaseCommand): 481 | help = 'Populate the database with test data for users, teams, activity, leaderboard, and workouts' 482 | 483 | def handle(self, *args, **kwargs): 484 | # Connect to MongoDB 485 | client = MongoClient(settings.DATABASES['default']['HOST'], settings.DATABASES['default']['PORT']) 486 | db = client[settings.DATABASES['default']['NAME']] 487 | 488 | # Drop existing collections 489 | db.users.drop() 490 | db.teams.drop() 491 | db.activity.drop() 492 | db.leaderboard.drop() 493 | db.workouts.drop() 494 | 495 | # Create users 496 | users = [ 497 | User(_id=ObjectId(), username='thundergod', email='thundergod@mhigh.edu', password='thundergodpassword'), 498 | User(_id=ObjectId(), username='metalgeek', email='metalgeek@mhigh.edu', password='metalgeekpassword'), 499 | User(_id=ObjectId(), username='zerocool', email='zerocool@mhigh.edu', password='zerocoolpassword'), 500 | User(_id=ObjectId(), username='crashoverride', email='crashoverride@hmhigh.edu', password='crashoverridepassword'), 501 | User(_id=ObjectId(), username='sleeptoken', email='sleeptoken@mhigh.edu', password='sleeptokenpassword'), 502 | ] 503 | User.objects.bulk_create(users) 504 | 505 | # Create teams 506 | team = Team(_id=ObjectId(), name='Blue Team') 507 | team = Team(_id=ObjectId(), name='Gold Team') 508 | team.save() 509 | for user in users: 510 | team.members.add(user) 511 | 512 | # Create activities 513 | activities = [ 514 | Activity(_id=ObjectId(), user=users[0], activity_type='Cycling', duration=timedelta(hours=1)), 515 | Activity(_id=ObjectId(), user=users[1], activity_type='Crossfit', duration=timedelta(hours=2)), 516 | Activity(_id=ObjectId(), user=users[2], activity_type='Running', duration=timedelta(hours=1, minutes=30)), 517 | Activity(_id=ObjectId(), user=users[3], activity_type='Strength', duration=timedelta(minutes=30)), 518 | Activity(_id=ObjectId(), user=users[4], activity_type='Swimming', duration=timedelta(hours=1, minutes=15)), 519 | ] 520 | Activity.objects.bulk_create(activities) 521 | 522 | # Create leaderboard entries 523 | leaderboard_entries = [ 524 | Leaderboard(_id=ObjectId(), user=users[0], score=100), 525 | Leaderboard(_id=ObjectId(), user=users[1], score=90), 526 | Leaderboard(_id=ObjectId(), user=users[2], score=95), 527 | Leaderboard(_id=ObjectId(), user=users[3], score=85), 528 | Leaderboard(_id=ObjectId(), user=users[4], score=80), 529 | ] 530 | Leaderboard.objects.bulk_create(leaderboard_entries) 531 | 532 | # Create workouts 533 | workouts = [ 534 | Workout(_id=ObjectId(), name='Cycling Training', description='Training for a road cycling event') 535 | Workout(_id=ObjectId(), name='Crossfit', description='Training for a crossfit competition'), 536 | Workout(_id=ObjectId(), name='Running Training', description='Training for a marathon'), 537 | Workout(_id=ObjectId(), name='Strength Training', description='Training for strength'), 538 | Workout(_id=ObjectId(), name='Swimming Training', description='Training for a swimming competition'), 539 | ] 540 | Workout.objects.bulk_create(workouts) 541 | 542 | self.stdout.write(self.style.SUCCESS('Successfully populated the database with test data.')) 543 | ``` 544 | 545 | ### Run the following commands to migrate the database and populate it with data 546 | 547 | ```bash 548 | python monafit-tracker/backend/manage.py monafit-tracker/backend/makemigrations 549 | python monafit-tracker/backend/manage.py monafit-tracker/backend/migrate 550 | python monafit-tracker/backendmanage.py monafit-tracker/backend/populate_db 551 | ``` 552 | 553 | ## Using the Codespace endpoint to access the Django REST API endpoints 554 | 555 | ```text 556 | Let's do the following step by step 557 | 558 | - Update #file:monafit-tracker/backend/monafit_tracker/views.py to replace the return for the rest api url endpiints with the codespace url http://[REPLACE-THIS-WITH-YOUR-CODESPACE-NAME]-8000.app.github.dev for django 559 | - Replace with [REPLACE-THIS-WITH-YOUR-CODESPACE-NAME] 560 | - Run the Django server 561 | 562 | HTTP 200 OK 563 | Allow: GET, HEAD, OPTIONS 564 | Content-Type: application/json 565 | Vary: Accept 566 | 567 | { 568 | "users": "http://localhost:8000/api/users/?format=api", 569 | "teams": "http://localhost:8000/api/teams/?format=api", 570 | "activities": "http://localhost:8000/api/activities/?format=api", 571 | "leaderboard": "http://localhost:8000/api/leaderboard/?format=api", 572 | "workouts": "http://localhost:8000/api/workouts/?format=api" 573 | } 574 | 575 | becomes 576 | 577 | HTTP 200 OK Allow: GET, HEAD, OPTIONS Content-Type: application/json Vary: Accept 578 | 579 | { 580 | "users": "http://-8000.app.github.dev/api/users/?format=api", 581 | "teams": "http://-8000.app.github.dev/api/teams/?format=api", 582 | "activities": "http://-8000.app.github.dev/api/activities/?format=api", 583 | "leaderboard": "http://-8000.app.github.dev/api/leaderboard/?format=api", 584 | "workouts": "http://-8000.app.github.dev/api/workouts/?format=api" 585 | } 586 | ``` 587 | 588 | ## Update to views.py 589 | 590 | ```python 591 | # FILE: monafit-tracker/backend/monafit_tracker/views.py 592 | 593 | from rest_framework import viewsets 594 | from rest_framework.decorators import api_view 595 | from rest_framework.response import Response 596 | from rest_framework.reverse import reverse 597 | from .serializers import UserSerializer, TeamSerializer, ActivitySerializer, LeaderboardSerializer, WorkoutSerializer 598 | from .models import User, Team, Activity, Leaderboard, Workout 599 | 600 | @api_view(['GET']) 601 | def api_root(request, format=None): 602 | base_url = 'http://[REPLACE-THIS-WITH-YOUR-CODESPACE-NAME]-8000.app.github.dev/' 603 | return Response({ 604 | 'users': base_url + 'api/users/?format=api', 605 | 'teams': base_url + 'api/teams/?format=api', 606 | 'activities': base_url + 'api/activities/?format=api', 607 | 'leaderboard': base_url + 'api/leaderboard/?format=api', 608 | 'workouts': base_url + 'api/workouts/?format=api' 609 | }) 610 | 611 | class UserViewSet(viewsets.ModelViewSet): 612 | queryset = User.objects.all() 613 | serializer_class = UserSerializer 614 | 615 | class TeamViewSet(viewsets.ModelViewSet): 616 | queryset = Team.objects.all() 617 | serializer_class = TeamSerializer 618 | 619 | class ActivityViewSet(viewsets.ModelViewSet): 620 | queryset = Activity.objects.all() 621 | serializer_class = ActivitySerializer 622 | 623 | class LeaderboardViewSet(viewsets.ModelViewSet): 624 | queryset = Leaderboard.objects.all() 625 | serializer_class = LeaderboardSerializer 626 | 627 | class WorkoutViewSet(viewsets.ModelViewSet): 628 | queryset = Workout.objects.all() 629 | serializer_class = WorkoutSerializer 630 | ``` 631 | 632 | ## Run the server via manage.py 633 | 634 | ```bash 635 | python manage.py runserver 636 | ``` 637 | 638 | ## Setup the frontend React app use the below package.json 639 | 640 | ```bash 641 | mkdir -p monafit-tracker/frontend 642 | 643 | npx create-react-app monafit-tracker/frontend 644 | 645 | npm install bootstrap --prefix monafit-tracker/frontend 646 | 647 | echo "import 'bootstrap/dist/css/bootstrap.min.css';" >> src/index.js 648 | 649 | npm install react-router-dom --prefix monafit-tracker/frontend 650 | ``` 651 | 652 | ### package.json 653 | 654 | ```json 655 | { 656 | "name": "octofit-tracker", 657 | "version": "0.1.0", 658 | "private": true, 659 | "dependencies": { 660 | "@testing-library/dom": "^9.3.1", 661 | "@testing-library/jest-dom": "^6.1.5", 662 | "@testing-library/react": "^14.1.2", 663 | "@testing-library/user-event": "^14.5.1", 664 | "bootstrap": "^5.3.2", 665 | "react": "^18.2.0", 666 | "react-dom": "^18.2.0", 667 | "react-router-dom": "^6.21.0", 668 | "react-scripts": "5.0.1", 669 | "web-vitals": "^2.1.4" 670 | }, 671 | "scripts": { 672 | "start": "react-scripts start", 673 | "build": "react-scripts build", 674 | "test": "react-scripts test", 675 | "eject": "react-scripts eject" 676 | }, 677 | "eslintConfig": { 678 | "extends": [ 679 | "react-app", 680 | "react-app/jest" 681 | ] 682 | }, 683 | "browserslist": { 684 | "production": [ 685 | ">0.2%", 686 | "not dead", 687 | "not op_mini all" 688 | ], 689 | "development": [ 690 | "last 1 chrome version", 691 | "last 1 firefox version", 692 | "last 1 safari version" 693 | ] 694 | } 695 | } 696 | ``` 697 | 698 | ## monafit App components 699 | 700 | Create the following components 701 | 702 | - Users 703 | - Ativities 704 | - Teams 705 | - Leaderboard 706 | - Workouts 707 | - Login 708 | - Register 709 | - Profile 710 | - Dashboard 711 | - Settings 712 | - Home 713 | 714 | Basic username password authentication is fine 715 | 716 | ### App.js 717 | 718 | ```javascript 719 | import React from 'react'; 720 | import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom'; 721 | import Activities from './components/Activities'; 722 | import Leaderboard from './components/Leaderboard'; 723 | import Teams from './components/Teams'; 724 | import Users from './components/Users'; 725 | import Workouts from './components/Workouts'; 726 | import './App.css'; 727 | 728 | function App() { 729 | return ( 730 | 731 | 732 | 733 | 734 | OctoFit Tracker 735 | 736 | 737 | 738 | 739 | 740 | 741 | Activities 742 | 743 | 744 | Leaderboard 745 | 746 | 747 | Teams 748 | 749 | 750 | Users 751 | 752 | 753 | Workouts 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | } /> 762 | } /> 763 | } /> 764 | } /> 765 | } /> 766 | Welcome to OctoFit Tracker} /> 767 | 768 | 769 | 770 | 771 | ); 772 | } 773 | 774 | export default App; 775 | ``` 776 | 777 | ### index.js potential React version issues 778 | 779 | The error indicates that the ReactDOM.render function is not available in the version of React you are using. This is because React 18 introduced a new root API for rendering. 780 | 781 | To fix this issue, update your src/index.js file to use the new createRoot API provided by React 18. Here's the updated code: 782 | 783 | ```javascript 784 | import React from 'react'; 785 | import ReactDOM from 'react-dom/client'; // Use the new root API 786 | import './index.css'; 787 | import App from './App'; 788 | import 'bootstrap/dist/css/bootstrap.min.css'; 789 | 790 | const root = ReactDOM.createRoot(document.getElementById('root')); // Create a root 791 | root.render( 792 | 793 | 794 | 795 | ); 796 | ``` 797 | 798 | ### Example leaderboard component 799 | 800 | Always use the Codespace URL for the API endpoint 801 | 802 | ```javascript 803 | import React, { useEffect, useState } from 'react'; 804 | 805 | function Leaderboard() { 806 | const [leaderboard, setLeaderboard] = useState([]); 807 | 808 | useEffect(() => { 809 | fetch('https://congenial-robot-pwrx4jxpp9c6vjv-8000.app.github.dev/api/leaderboard/') 810 | .then(response => response.json()) 811 | .then(data => setLeaderboard(data)) 812 | .catch(error => console.error('Error fetching leaderboard:', error)); 813 | }, []); 814 | 815 | return ( 816 | 817 | Leaderboard 818 | 819 | 820 | 821 | Username 822 | Score 823 | 824 | 825 | 826 | {leaderboard.map(entry => ( 827 | 828 | {entry.user.username} 829 | {entry.score} 830 | 831 | ))} 832 | 833 | 834 | 835 | ); 836 | } 837 | 838 | export default Leaderboard; 839 | ``` 840 | 841 | ## App.css example 842 | 843 | ```css 844 | /* General styles */ 845 | body { 846 | font-family: 'Roboto', sans-serif; 847 | background-color: #f0f8ff; /* Light blue background */ 848 | margin: 0; 849 | padding: 0; 850 | } 851 | 852 | .App { 853 | text-align: center; 854 | } 855 | 856 | /* Navigation styles */ 857 | nav { 858 | background-color: #4682b4; /* Steel blue */ 859 | padding: 1rem; 860 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 861 | } 862 | 863 | nav ul { 864 | list-style: none; 865 | padding: 0; 866 | margin: 0; 867 | display: flex; 868 | justify-content: center; 869 | } 870 | 871 | nav ul li { 872 | margin: 0 1rem; 873 | } 874 | 875 | nav ul li a { 876 | color: #0f0be4; /* White text for visibility */ 877 | text-decoration: none; 878 | font-weight: bold; 879 | font-size: 1.2rem; 880 | transition: color 0.3s; 881 | } 882 | 883 | nav ul li a:hover { 884 | color: #f0f8ff; /* Light blue */ 885 | text-decoration: underline; 886 | } 887 | 888 | /* Component styles */ 889 | h1 { 890 | color: #00008b; /* Dark blue header name */ 891 | font-size: 2.5rem; 892 | margin-bottom: 1rem; 893 | } 894 | 895 | /* Table styles */ 896 | table { 897 | width: 90%; 898 | margin: 1rem auto; 899 | border-collapse: collapse; 900 | background-color: #ffffff; /* White background */ 901 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 902 | border-radius: 8px; 903 | overflow: hidden; 904 | } 905 | 906 | table th, table td { 907 | border: 1px solid #ddd; 908 | padding: 1rem; 909 | text-align: left; 910 | font-size: 1rem; 911 | } 912 | 913 | table th { 914 | background-color: #4682b4; /* Steel blue */ 915 | color: white; 916 | font-size: 1.2rem; 917 | } 918 | 919 | table tr:nth-child(even) { 920 | background-color: #f0f8ff; /* Light blue */ 921 | } 922 | 923 | table tr:hover { 924 | background-color: #e0ffff; /* Light cyan */ 925 | } 926 | 927 | ul { 928 | list-style: none; 929 | padding: 0; 930 | } 931 | 932 | ul li { 933 | color: #4682b4; /* Steel blue text */ 934 | background-color: #fff; 935 | margin: 0.5rem 0; 936 | padding: 1rem; 937 | border-radius: 8px; 938 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); 939 | font-size: 1.1rem; 940 | } 941 | 942 | /* Text styles */ 943 | .component-text { 944 | color: #00008b; /* Dark blue center title */ 945 | font-size: 1.8rem; 946 | margin-bottom: 1rem; 947 | } 948 | 949 | /* Button styles */ 950 | button { 951 | background-color: #4682b4; /* Steel blue */ 952 | color: white; 953 | border: none; 954 | padding: 0.75rem 1.5rem; 955 | border-radius: 8px; 956 | font-size: 1rem; 957 | cursor: pointer; 958 | transition: background-color 0.3s; 959 | } 960 | 961 | button:hover { 962 | background-color: #5a9bd4; /* Lighter steel blue */ 963 | } 964 | 965 | .App-logo { 966 | height: 40vmin; 967 | pointer-events: none; 968 | } 969 | 970 | @media (prefers-reduced-motion: no-preference) { 971 | .App-logo { 972 | animation: App-logo-spin infinite 20s linear; 973 | } 974 | } 975 | 976 | .App-header { 977 | background-color: #2b2834; 978 | min-height: 100vh; 979 | display: flex; 980 | flex-direction: column; 981 | align-items: center; 982 | justify-content: center; 983 | font-size: calc(10px + 2vmin); 984 | color: white; 985 | } 986 | 987 | .App-link { 988 | color: #61dafb; 989 | } 990 | 991 | @keyframes App-logo-spin { 992 | from { 993 | transform: rotate(0deg); 994 | } 995 | to { 996 | transform: rotate(360deg); 997 | } 998 | } 999 | ``` 1000 | -------------------------------------------------------------------------------- /docs/octofit_story.md: -------------------------------------------------------------------------------- 1 | # Building a Fitness App with GitHub Copilot agent mode for Mergington High School 2 | 3 | ## OctoFit Tracker application story for Mergington High School 4 | 5 | Paul Octo has been a physical education teacher at Mergington High School for over 8 years. Despite his enthusiasm and creative approach to gym class, he's been increasingly concerned about students' physical activity declining once they leave school grounds. Many students admitted they rarely exercised outside of the required PE classes. 6 | After attending a professional development conference on "Technology Integration in Physical Education," Paul became inspired to create a solution. He wanted something that would: 7 | 8 | 1. Make fitness tracking fun and engaging 9 | 2. Create positive peer pressure through friendly competition 10 | 3. Allow him to monitor student progress remotely 11 | 4. Provide personalized guidance based on individual fitness levels 12 | 13 | ## The Birth of OctoFit Tracker 14 | 15 | Paul initially sketched his idea on a notepad during lunch breaks. He envisioned an app where students could log workouts, earn achievement badges, and compete in monthly fitness challenges. However, as a PE teacher with only basic coding knowledge, the technical aspects seemed daunting. 16 | That's when he approached Jessica Cat, the head of Mergington High's IT department. Jessica recommended basing the app on the Monafit Tracker developed by Mona High School, which was documented in `docs/mona-high-school-fitness-tracker.md`. She saw potential in adapting the Monafit Tracker's structure and features to meet Mergington High School's needs. 17 | 18 | ### Technical Planning Phase 19 | 20 | Before starting development, Paul and Jessica carefully reviewed the Monafit Tracker's repository and documentation. This provided a solid foundation for OctoFit Tracker, ensuring compliance with technical standards and leveraging proven design patterns. 21 | Together, Paul and the IT team identified key requirements for OctoFit Tracker: 22 | 23 | ### User Experience Goals 24 | 25 | - Simple, intuitive interface designed specifically for teenagers 26 | - Quick activity logging to minimize friction 27 | - Social features that respect student privacy 28 | - Gamification elements to maintain engagement 29 | 30 | ### Technical Specifications 31 | 32 | - Mobile-responsive web application (accessible on school Chromebooks and personal devices) 33 | - Secure authentication based on Monafit Tracker's implementation 34 | - Activity verification system to prevent cheating 35 | 36 | ## Current Development Status 37 | 38 | Paul and Jessica have set up a GitHub Codespace environment and are making remarkable progress with GitHub Copilot agent mode. By adapting the Monafit Tracker's structure, the OctoFit Tracker prototype already includes: 39 | 40 | - A functional user registration system 41 | - Basic activity logging for running, walking, and strength training 42 | - The beginning framework for team competitions 43 | - A simple dashboard showing student progress 44 | 45 | ## Next Steps for Paul 46 | 47 | With the basic infrastructure in place, Paul is now focused on: 48 | 49 | 1. Developing an engaging point system that fairly compares different types of activities 50 | 2. Creating motivational challenges that appeal to different student interests 51 | 3. Building a notification system that encourages consistency without being intrusive 52 | 4. Designing reports that help him identify students who might need additional support or motivation 53 | 54 | The IT department has been impressed with how GitHub Copilot agent mode has accelerated development, allowing Paul to focus on the educational aspects while the AI handles much of the technical implementation. Jessica Cat has been particularly pleased with how OctoFit Tracker leverages the Monafit Tracker's foundation to meet Mergington High School's unique requirements. 55 | 56 | ### Workshop Overview 57 | 58 | In this workshop, you'll: 59 | 60 | 1. Set up a development environment using **GitHub Codespaces** 61 | 2. Use **GitHub Copilot** to accelerate development across multiple technologies 62 | 3. Build key components of the **OctoFit Tracker** app with the help of Copilot agent mode 63 | 4. Learn best practices and prompting techniques for working with **GitHub Copilot agent mode** 64 | 65 | ### Application Features 66 | 67 | **OctoFit Tracker** will include: 68 | 69 | - User profiles 70 | - Activity logging and tracking 71 | - Team creation and management 72 | - A competitive leaderboard 73 | - Personalized workout suggestions 74 | 75 | ### GitHub Copilot Chat 76 | 77 | These are the current models supported for GitHub Copilot Chat: 78 | 79 | - Claude Sonnet 3.5 (Preview) 80 | - Claude Sonnet 3.7 (Preview) 81 | - Claude Sonnet 3.7 Thinking (Preview) 82 | - Gemini 2.0 Flash (Preview) 83 | - GPT-4o 84 | - o1 (Preview) 85 | - o3-mini (Preview) 86 | 87 | #### [LLM models explained](https://docs.github.com/en/copilot/using-github-copilot/ai-models/changing-the-ai-model-for-copilot-chat#ai-models-for-copilot-chat-1) 88 | 89 |  90 | 91 | #### Prompt engineering 92 | 93 | - [GitHub documentation prompt engineering](https://docs.github.com/en/copilot/using-github-copilot/prompt-engineering-for-github-copilot) 94 | - [How to use GitHub Copilot: Prompts, tips, and use cases](https://github.blog/2023-06-20-how-to-write-better-prompts-for-github-copilot/) 95 | - [Using GitHub Copilot in your IDE: Tips, tricks, and best practices](https://github.blog/2024-03-25-how-to-use-github-copilot-in-your-ide-tips-tricks-and-best-practices/) 96 | - [A developer's guide to prompt engineering and LLMs](https://docs.github.com/en/copilot/using-github-copilot/prompt-engineering-for-github-copilot#:~:text=A%20developer%E2%80%99s%20guide%20to%20prompt%20engineering%20and%20LLMs) 97 | - [GitHub Copilot: The Agent Awakens](https://github.blog/news-insights/product-news/github-copilot-the-agent-awakens/#agent-mode-available-in-preview-%f0%9f%a4%96) 98 | 99 | ### OctoFit tracker fitness application technology stack 100 | 101 | We'll be using a modern web application stack: 102 | 103 | - **Frontend**: React.js 104 | - **Backend**: Python with Django REST Framework 105 | - **Database**: MongoDB 106 | - **Development Environment**: GitHub Codespaces 107 | 108 | ### Workshop Structure 109 | 110 | 1. **Introduction** 111 | - Overview of OctoFit Tracker app concept 112 | - GitHub Copilot Chat models 113 | 114 | 2. **Setup of Prerequisites** 115 | - Setting up GitHub Codespaces 116 | - Ensure GitHub Copilot and Copilot Chat extensions are up to date 117 | 118 | 3. **Rapid Prototyping with GitHub Copilot agent mode** 119 | - Creating project structure 120 | - Generating boilerplate code 121 | - Implementing basic models, serializers, urls, and views 122 | 123 | 4. **Building Core Features** 124 | - Activity logging API 125 | - Team management 126 | - Leaderboard functionality 127 | 128 | 5. **Frontend and Backend Development** 129 | - Setting up React components 130 | - Implementing responsive UI 131 | - Connecting to backend APIs 132 | - Python Django business logic 133 | - MongoDB data layer 134 | -------------------------------------------------------------------------------- /docs/octofitapp-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skills/build-applications-w-copilot-agent-mode/a022cc39074b266da58c93a3971e8244564d65c1/docs/octofitapp-small.png --------------------------------------------------------------------------------