mirror of
https://github.com/jlengrand/getting-started-with-github-copilot.git
synced 2026-03-10 00:11:20 +00:00
Initial commit
This commit is contained in:
15
.devcontainer/devcontainer.json
Normal file
15
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Python 3",
|
||||
"image": "mcr.microsoft.com/vscode/devcontainers/python:3.13",
|
||||
"forwardPorts": [8000],
|
||||
"postCreateCommand": "pip install -r requirements.txt",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"GitHub.copilot",
|
||||
"ms-python.python",
|
||||
"ms-python.debugpy"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
127
.github/steps/1-preparing.md
vendored
Normal file
127
.github/steps/1-preparing.md
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
## Step 1: Hello Copilot
|
||||
|
||||
Welcome to your **"Getting Started with GitHub Copilot"** exercise! :robot:
|
||||
|
||||
In this exercise, you will be using different GitHub Copilot features to work on a website that allows students of Mergington High School to sign up for extracurricular activities. 🎻 ⚽️ ♟️
|
||||
|
||||
<img width="600" alt="screenshot of Mergington High School WebApp" src="https://github.com/user-attachments/assets/472398fd-1aa1-4084-b443-4e242deb30d9" />
|
||||
|
||||
### 📖 Theory: Getting to know GitHub Copilot
|
||||
|
||||
<img width="150" align="right" alt="copilot logo" src="https://github.com/user-attachments/assets/4d22496d-850b-4785-aafe-11cba03cd5f2" />
|
||||
|
||||
GitHub Copilot is an AI coding assistant that helps you write code faster and with less effort, allowing you to focus more energy on problem solving and collaboration.
|
||||
|
||||
GitHub Copilot has been proven to increase developer productivity and accelerate the pace of software development. For more information, see [Research: quantifying GitHub Copilot’s impact on developer productivity and happiness in the GitHub blog.](https://github.blog/news-insights/research/research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/)
|
||||
|
||||
As you work in your IDE, you'll most often interact with GitHub Copilot in the following ways:
|
||||
|
||||
| Interaction Mode | 📝 Description | 🎯 Best For |
|
||||
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| **⚡ Inline suggestions** | AI-powered code suggestions that appear as you type, offering context-aware completions from single lines to entire functions. | Completion of the current line, sometimes a whole new block of code |
|
||||
| **💬 Ask Mode** | Optimized for answering questions about your codebase, coding, and general technology concepts. | Understanding how code works, brainstorming ideas, asking questions |
|
||||
| **✏️ Edit Mode** | Optimized for making code edits across multiple files in your project. VS Code directly applies the code changes in the editor for in-place review. | Coding tasks when you have a good understanding of the changes you want to make and which files you want to edit |
|
||||
| **🤖 Agent Mode** | Optimized for making autonomous edits across multiple files in your project. | Coding tasks when you have a less well-defined task that might also require running terminal commands and tools |
|
||||
| **💭 Inline Chat** | Interactive chat scoped to your current file or selection. Ask questions about specific code blocks. | Code explanations, debugging specific functions, targeted improvements |
|
||||
|
||||
As you work, you'll find GitHub Copilot can help out in several places across the `github.com` website and in your favorite coding environments such as VS Code, Jet Brains, and Xcode!
|
||||
|
||||
For today's coding though, we will practice with VS Code in a pre-configured development environment known as a [GitHub Codespace](https://github.com/features/codespaces).
|
||||
|
||||
> [!TIP]
|
||||
> You can learn more about current and upcoming features in the [GitHub Copilot Features](https://docs.github.com/en/copilot/about-github-copilot/github-copilot-features) documentation.
|
||||
|
||||
### :keyboard: Activity: Get a project intro from Copilot Chat
|
||||
|
||||
Let's start up our development environment, use copilot to learn a bit about the project, and then give it a test run.
|
||||
|
||||
1. Use the below button to open the **Create Codespace** page in a new tab. Use the default configuration.
|
||||
|
||||
[](https://codespaces.new/{{full_repo_name}}?quickstart=1)
|
||||
|
||||
1. Confirm the **Repository** field is your copy of the exercise, not the original, then click the green **Create Codespace** button.
|
||||
|
||||
- ✅ Your copy: `/{{full_repo_name}}`
|
||||
- ❌ Original: `/skills/getting-started-with-github-copilot`
|
||||
|
||||
1. Wait a moment for Visual Studio Code to load in your browser.
|
||||
|
||||
1. In the left sidebar, click the extensions tab and verify that the `GitHub Copilot` and `Python` extensions are installed and enabled.
|
||||
|
||||
<img width="350" alt="copilot extension for VS Code" src="https://github.com/user-attachments/assets/ef1ef984-17fc-4b20-a9a6-65a866def468" />
|
||||
|
||||
<img width="350" alt="python extension for VS Code" src="https://github.com/user-attachments/assets/3040c0f5-1658-47e2-a439-20504a384f77" />
|
||||
|
||||
1. At the top of VS Code, locate and click the **Toggle Chat icon** to open a Copilot Chat side panel.
|
||||
|
||||
<img width="150" alt="image" src="https://github.com/user-attachments/assets/abf584e9-ef68-4725-8b22-4803805e6d55" />
|
||||
|
||||
> 🪧 **Note:** If this is your first time using GitHub Copilot, you will need to accept the usage terms to continue.
|
||||
|
||||
1. Make sure you are in **Ask Mode** for our first interaction
|
||||
|
||||
|
||||
<img width="350" alt="screenshot showing Ask Mode selection in Copilot Chat" src="https://github.com/user-attachments/assets/fb1d7cac-2d39-4199-b5d9-0f3dfcfb3bcd" />
|
||||
1. Enter the below prompt to ask Copilot to introduce you to the project.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> @workspace Please briefly explain the structure of this project.
|
||||
> What should I do to run it?
|
||||
> ```
|
||||
|
||||
> 🪧 **Note:** It is not necessary to follow Copilot's recommended instructions. We have already prepared the environment for you.
|
||||
|
||||
<details>
|
||||
<summary>What is @workspace?</summary>
|
||||
|
||||
Great question! This is a specialized [chat participant](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/github-copilot-chat-cheat-sheet?tool=vscode#chat-participants) that will explore the project repository and try to include relevant additional context.
|
||||
|
||||
</details>
|
||||
|
||||
1. Now that we know a bit more about the project, let's actually try running it! In the left sidebar, select the `Run and Debug` tab and then press the **Start Debugging** icon.
|
||||
|
||||
<img width="300" alt="image" src="https://github.com/user-attachments/assets/50b27f2a-5eab-4827-9343-ab5bce62357e" />
|
||||
|
||||
1. We want to see our webpage running in a browser, so let's find the url and port. If it isn't visible, expand the lower panel and select the **Ports** tab.
|
||||
|
||||
1. In the list, find port `8000` and the related link. Hover over the link and select the **Open in browser** icon.
|
||||
|
||||

|
||||
|
||||
### :keyboard: Activity: Use Copilot to help remember a terminal command 🙋
|
||||
|
||||
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.
|
||||
|
||||
1. In VS Code's bottom panel, select the **Terminal** tab and on the right side click the plus `+` sign to create a new terminal window.
|
||||
|
||||
> 🪧 **Note:** This will avoid stopping the existing debug session that is hosting our web application service.
|
||||
|
||||
1. Within the new terminal window use the keyboard shortcut `Ctrl + I` (windows) or `Cmd + I` (mac) to bring up **Copilot's Terminal Inline Chat**.
|
||||
|
||||
1. Let's ask Copilot to help us remember a command we have forgotten: creating a branch and publishing it.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> Hey copilot, how can I create and publish a new Git branch called "accelerate-with-copilot"?
|
||||
> ```
|
||||
|
||||
> 💡 **Tip:** If Copilot doesn't give you quite what you want, you can always continue explaining what you need. Copilot will remember the conversation history for follow-up responses.
|
||||
|
||||
1. Press the `Run` button to let Copilot insert the terminal command for us. No need to copy and paste!
|
||||
|
||||
1. After a moment, look in the VS Code lower status bar, on the left, to see the active branch. It should now say `accelerate-with-copilot`. If so, you are all done with this step!
|
||||
|
||||
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.
|
||||
|
||||
<details>
|
||||
<summary>Having trouble? 🤷</summary><br/>
|
||||
|
||||
If you don't get feedback, here are some things to check:
|
||||
|
||||
- Make sure your created the branch with the exact name `accelerate-with-copilot`. No prefixes or suffixes.
|
||||
- Make sure the branch was indeed published to your repository.
|
||||
|
||||
</details>
|
||||
198
.github/steps/2-first-introduction.md
vendored
Normal file
198
.github/steps/2-first-introduction.md
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
## Step 2: Getting work done with Copilot
|
||||
|
||||
In the previous step, GitHub Copilot was able to help us onboard to the project. That alone is a huge time saver, but now let's get some work done!
|
||||
|
||||
:bug: **THERE IS A BUG ON THE WEBSITE** :bug:
|
||||
|
||||
We’ve discovered that something’s off in the signup flow.
|
||||
Students can currently register for the same activity **more than once**! Let’s see how far Copilot can take us in uncovering the cause and shaping a clean fix.
|
||||
|
||||
Before we dive in, a quick primer on how Copilot works. 🧑🚀
|
||||
|
||||
### 📖 Theory: How Copilot works
|
||||
|
||||
In short, you can think of Copilot like a very specialized coworker. To be effective with them, you need to provide them background (context) and clear direction (prompts). Additionally, different people are better at different things because of their unique experiences (models).
|
||||
|
||||
- **How do we provide context?:** In our coding environment, Copilot will automatically consider nearby code and open tabs. If you are using chat, you can also explicitly refer to files.
|
||||
|
||||
- **What model should we pick?:** For our exercise, it shouldn't matter too much. Experimenting with different models is part of the fun! That's another lesson! 🤖
|
||||
|
||||
- **How do I make prompts?:** Being explicit and clear helps Copilot do the best job. But unlike some traditional systems, you can always clarify your direction with followup prompts.
|
||||
|
||||
> [!TIP]
|
||||
> There several other ways to supplement Copilot's knowledge and capabilities like [chat participants](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/github-copilot-chat-cheat-sheet?tool=vscode#chat-participants), [chat variables](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/github-copilot-chat-cheat-sheet?tool=vscode#chat-variables), [slash commands](https://docs.github.com/en/copilot/using-github-copilot/copilot-chat/github-copilot-chat-cheat-sheet?tool=vscode#slash-commands-1), and [MCP tools](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).
|
||||
|
||||
### :keyboard: Activity: Use Copilot to fix our registration bug :bug:
|
||||
|
||||
1. Let's ask Copilot to suggest where our bug might be coming from. Open the **Copilot Chat** panel in **Ask mode** and ask the following.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> @workspace Students are able to register twice for an activity.
|
||||
> Where could this bug be coming from?
|
||||
> ```
|
||||
|
||||
1. Now that we know the issue is in the `src/app.py` file and the `signup_for_activity` method, let's follow Copilot's recommendation and go fix it (semi-manually). We'll start with a comment and let Copilot finish the correction.
|
||||
|
||||
1. In VS Code, select the file **Explorer tab** to show the project files and open the `src/app.py` file.
|
||||
|
||||
1. Scroll near the bottom of the file and find the `signup_for_activity` method.
|
||||
|
||||
1. Find the comment line that describes adding a student. Above this is where it seems logical to do our registration check.
|
||||
|
||||
1. Enter the below comment and press enter to go to the next line. After a moment, temporary shadow text will appear with a suggestion from Copilot! Nice! :tada:
|
||||
|
||||
```python
|
||||
# Validate student is not already signed up
|
||||
```
|
||||
|
||||
1. Press `Tab` to accept Copilot's suggestion and convert the shadow text to code.
|
||||
|
||||
<details>
|
||||
<summary>Example Results</summary><br/>
|
||||
|
||||
Copilot is growing every day and may not always produce the same results. If you are unhappy with the suggestions, here is an example of a valid suggestion result we produced during the making of this exercise. You can use it to continue forward.
|
||||
|
||||
```python
|
||||
@app.post("/activities/{activity_name}/signup")
|
||||
def signup_for_activity(activity_name: str, email: str):
|
||||
"""Sign up a student for an activity"""
|
||||
# Validate activity exists
|
||||
if activity_name not in activities:
|
||||
raise HTTPException(status_code=404, detail="Activity not found")
|
||||
|
||||
# Get the activity
|
||||
activity = activities[activity_name]
|
||||
|
||||
# Validate student is not already signed up
|
||||
if email in activity["participants"]:
|
||||
raise HTTPException(status_code=400, detail="Student is already signed up")
|
||||
|
||||
# Add student
|
||||
activity["participants"].append(email)
|
||||
return {"message": f"Signed up {email} for {activity_name}"}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### :keyboard: Activity: Let Copilot generate sample data 📋
|
||||
|
||||
In new project developments, it's often helpful to have some realistic looking fake data for testing. Copilot is excellent at this task, so let's add some more sample activities and introduce another way to interact with Copilot using **Inline Chat**
|
||||
|
||||
**Inline Chat** and the **Copilot Chat** panel are similar, but differ in scope: Copilot Chat handles broader, multi-file or exploratory questions; Inline Chat is faster when you want targeted help on the exact line or block in front of you.
|
||||
|
||||
1. Near the top of the `src/app.py` file (about line 23), find the `activities` variable, where our example extracurricular activities are configured.
|
||||
|
||||
1. Click on any of the related lines and bring up Copilot inline chat by using the keyboard command `Ctrl + I` (windows) or `Cmd + I` (mac).
|
||||
|
||||
> 💡 **Tip:** Another way to bring up Copilot inline chat is: `right click` on any of the selected lines -> `Copilot` -> `Editor Inline Chat`.
|
||||
|
||||
1. Enter the following prompt text and press enter or the **Send and Dispatch** button.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> Add 2 more sports related activities, 2 more artistic
|
||||
> activities, and 2 more intellectual activities.
|
||||
> ```
|
||||
|
||||
1. After a moment, Copilot will directly start making changes to the code. The changes will be stylized differently to make any additions and removals easy to identify. Take a moment to inspect and then press the **Accept** button.
|
||||
|
||||
<details>
|
||||
<summary>Example Results</summary><br/>
|
||||
|
||||
Copilot is growing every day and may not always produce the same results. If you are unhappy with the suggestions, here is an example result we produced during the making of this exercise. You can use it to continue forward, if having trouble.
|
||||
|
||||
```python
|
||||
# In-memory activity database
|
||||
activities = {
|
||||
"Chess Club": {
|
||||
"description": "Learn strategies and compete in chess tournaments",
|
||||
"schedule": "Fridays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 12,
|
||||
"participants": ["michael@mergington.edu", "daniel@mergington.edu"]
|
||||
},
|
||||
"Programming Class": {
|
||||
"description": "Learn programming fundamentals and build software projects",
|
||||
"schedule": "Tuesdays and Thursdays, 3:30 PM - 4:30 PM",
|
||||
"max_participants": 20,
|
||||
"participants": ["emma@mergington.edu", "sophia@mergington.edu"]
|
||||
},
|
||||
"Gym Class": {
|
||||
"description": "Physical education and sports activities",
|
||||
"schedule": "Mondays, Wednesdays, Fridays, 2:00 PM - 3:00 PM",
|
||||
"max_participants": 30,
|
||||
"participants": ["john@mergington.edu", "olivia@mergington.edu"]
|
||||
},
|
||||
"Basketball Team": {
|
||||
"description": "Competitive basketball training and games",
|
||||
"schedule": "Tuesdays and Thursdays, 4:00 PM - 6:00 PM",
|
||||
"max_participants": 15,
|
||||
"participants": []
|
||||
},
|
||||
"Swimming Club": {
|
||||
"description": "Swimming training and water sports",
|
||||
"schedule": "Mondays and Wednesdays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 20,
|
||||
"participants": []
|
||||
},
|
||||
"Art Studio": {
|
||||
"description": "Express creativity through painting and drawing",
|
||||
"schedule": "Wednesdays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 15,
|
||||
"participants": []
|
||||
},
|
||||
"Drama Club": {
|
||||
"description": "Theater arts and performance training",
|
||||
"schedule": "Tuesdays, 4:00 PM - 6:00 PM",
|
||||
"max_participants": 25,
|
||||
"participants": []
|
||||
},
|
||||
"Debate Team": {
|
||||
"description": "Learn public speaking and argumentation skills",
|
||||
"schedule": "Thursdays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 16,
|
||||
"participants": []
|
||||
},
|
||||
"Science Club": {
|
||||
"description": "Hands-on experiments and scientific exploration",
|
||||
"schedule": "Fridays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 20,
|
||||
"participants": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### :keyboard: Activity: Use Copilot to describe our work 💬
|
||||
|
||||
Nice work fixing that bug and expanding the example activities! Now let's get our work committed and pushed to GitHub, again with the help of Copilot!
|
||||
|
||||
1. In the left sidebar, select the `Source Control` tab.
|
||||
|
||||
> 💡 **Tip:** Opening a file from the source control area will show the differences to the original rather than simply opening it.
|
||||
|
||||
1. Find the `app.py` file and press the `+` sign to collect your changes together in the staging area.
|
||||
|
||||

|
||||
|
||||
1. Above the list of staged changes, find the **Message** text box, but **don't enter anything** for now.
|
||||
|
||||
- Typically, you would write a short description of the changes here, but now we have Copilot to help out!
|
||||
|
||||
1. To the right of the **Message** text box, find and click the **Generate Commit Message** button (sparkles icon).
|
||||
|
||||
1. Press the **Commit** button and **Sync Changes** button to push your changes to GitHub.
|
||||
|
||||
1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson.
|
||||
|
||||
<details>
|
||||
<summary>Having trouble? 🤷</summary><br/>
|
||||
|
||||
If you don't get feedback, here are some things to check:
|
||||
|
||||
- Make sure your pushed the `src/app.py` file changes to the branch `accelerate-with-copilot`.
|
||||
|
||||
</details>
|
||||
103
.github/steps/3-copilot-edits.md
vendored
Normal file
103
.github/steps/3-copilot-edits.md
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
## Step 3: Getting work done even _faster_ with Copilot Edit Mode
|
||||
|
||||
In our previous steps, we used features of Copilot that require more hands-on guidance and they produced mostly localized results. Now, we will explore Copilot **Edit Mode**, a feature that allows working more holistically on our repo.
|
||||
|
||||
### 📖 Theory: Copilot Edit Mode
|
||||
|
||||
Copilot **Edit Mode** and **Agent Mode** both let you apply **natural‑language** driven changes across **multiple files**, however there are some differences between them.
|
||||
|
||||
In this step we will focus on **Edit Mode** and explore **Agent Mode** in the next step.
|
||||
|
||||
Edit Mode is best used for **well defined** tasks where you **know the scope** of the needed changes.
|
||||
|
||||
#### How Edit Mode works
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Select Context Files] --> B[Prompt Copilot]
|
||||
B --> C[Proposed Changes]
|
||||
C --> D{Review Change}
|
||||
D --> E[Accept]
|
||||
D --> F[Discard]
|
||||
D -->|Refine Prompt| B
|
||||
|
||||
```
|
||||
|
||||
1. **Set Context**: Select files that Copilot should consider in it's changes
|
||||
1. **Prompt Copilot**: Use natural language to describe the required changes.
|
||||
1. **Review Changes**: See proposed changes in-place in your code.
|
||||
1. **Accept or Discard**: Review each suggested edit and choose which to keep.
|
||||
1. **Iterate**: If needed, provide follow-up instructions to refine the changes.
|
||||
|
||||
### :keyboard: Activity: Use Copilot to add a new feature! :rocket:
|
||||
|
||||
Our website lists activities, but it's keeping the guest list secret 🤫
|
||||
|
||||
Let's use Copilot to change the website to display signed up students under each activity!
|
||||
|
||||
1. At the bottom of Copilot Chat window, use the dropdown to switch to **Edit** mode.
|
||||
|
||||
<img width="350" alt="image" src="https://github.com/user-attachments/assets/646fc94a-7d60-4821-b9cf-9ec6f4fd03d7" />
|
||||
|
||||
1. Open the files related to our webpage then drag each editor window (or file) to the chat panel, informing Copilot to use them as context.
|
||||
|
||||
- `src/static/app.js`
|
||||
- `src/static/index.html`
|
||||
- `src/static/styles.css`
|
||||
|
||||
<img width="400" alt="image showing files added to context" src="https://github.com/user-attachments/assets/8026a86b-b350-4b98-bf4f-764b61d157e7" />
|
||||
|
||||
> 💡 **Tip:** You can also use the **Add Context...** button to provide other sources of context items, like a GitHub issue, the entire codebase, or the results of a terminal window.
|
||||
|
||||
1. Ask Copilot to update our project to display the current participants of activities. Wait a moment for the edit suggestions to arrive and be applied.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> Hey Copilot, can you please edit the activity cards to add a participants section.
|
||||
> It will show what participants that are already signed up for that activity as a bulleted list.
|
||||
> Remember to make it pretty!
|
||||
> ```
|
||||
|
||||
- An extra icon has appeared next to the file names and open editor windows indicating they have suggested edits.
|
||||
- A suggested edits panel has appeared in the bottom right of the editor window providing controls to jump to the recommended changes.
|
||||
|
||||
<img width="200" alt="files with icons indicating they have been edited" src="https://github.com/user-attachments/assets/9c7c2e10-cd18-43c5-9947-cffd6dde0473" />
|
||||
|
||||
<img width="250" alt="edit navigation panel" src="https://github.com/user-attachments/assets/a84965a5-2f43-4c93-a814-0fdeb3a06494" />
|
||||
|
||||
|
||||
1. Before we simply accept the changes, please check our website again and verify everything is updated as expected. Here is an example of an updated activity card. You may need to restart the app or refresh the page.
|
||||
|
||||
<img width="350" alt="Activity card with participant info" src="https://github.com/user-attachments/assets/c4d56187-4791-4c8e-87d7-d5ce7cdc0bee" />
|
||||
|
||||
> 🪧 **Note:** Your activity card may look different. Copilot won't always produce the same results.
|
||||
|
||||
<details>
|
||||
<summary>Need help? 🤷</summary><br/>
|
||||
If the website is not loading, here are some things to check.
|
||||
|
||||
- Restart the VS Code Debugger to make sure the latest version of the website is served.
|
||||
- If you forgot the url, or closed the window, please review step 1.
|
||||
- Try hard refreshing the webpage or opening in a private window so it downloads a fresh copy.
|
||||
|
||||
</details>
|
||||
|
||||
1. Now that we have confirmed our changes are good, use the panel to cycle through each suggested edit and press **Keep** to apply the change.
|
||||
|
||||
> 💡 **Tip:** You can accept the changes directly, modify them, or provide additional instruction to refine them using the chat interface.
|
||||
|
||||
1. With our new feature complete, please **commit** and **push** the changes to GitHub.
|
||||
|
||||
1. Wait a moment for Mona to check your work, provide feedback, and share the next lesson.
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Having trouble? 🤷</summary><br/>
|
||||
|
||||
If you don't get feedback, here are some things to check:
|
||||
|
||||
- Make sure your commit the changes in the `src/static/` directory to the branch `accelerate-with-copilot` and pushed/synchronized to GitHub.
|
||||
- If Mona found a mistake, simply make a correction and push your changes again. Mona will check your work as many times as needed.
|
||||
|
||||
</details>
|
||||
95
.github/steps/4-copilot-agent-mode.md
vendored
Normal file
95
.github/steps/4-copilot-agent-mode.md
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
## Step 4: Engage Hyperdrive - Copilot Agent Mode 🚀
|
||||
|
||||
### 📖 Theory: What is Copilot Agent Mode?
|
||||
|
||||
Copilot [agent mode](https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode) is the next evolution in AI-assisted coding. Acting as an autonomous peer programmer, it performs multi-step coding tasks at your command.
|
||||
|
||||
Copilot Agent Mode responds to compile and lint errors, monitors terminal and test output, and auto-corrects in a loop until the task is completed.
|
||||
|
||||
#### Edit Mode vs Agent Mode (at a glance)
|
||||
|
||||
| Aspect | ✏️ Edit Mode | 👩🚀 Agent Mode |
|
||||
| -------------- | --------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| Context scope | Only the files you explicitly add | May read/add additional files & surfaces as needed |
|
||||
| Self‑review | Minimal (you drive iteration) | Built‑in feedback & retry loop on errors/failures |
|
||||
| Change scope | Highly scoped & surgical | Broader; may touch related layers for consistency |
|
||||
| When to choose | You know exactly what to change | Goal is broader or uncertain; requires exploration |
|
||||
| Tool calling | None (you run commands manually) | Can invoke tools (read/edit files, run commands, inspect terminal & test output) |
|
||||
|
||||
#### 🧰 Agent Mode Tools
|
||||
|
||||
Agent mode uses tools to accomplish specialized tasks while processing a user request. Examples of such tasks are:
|
||||
|
||||
- Finding relevant files to complete your prompt
|
||||
- Fetching contents of a webpage
|
||||
- Running tests or terminal commands
|
||||
|
||||
> [!TIP]
|
||||
> While VS Code provides many built‑in tools, you can also provide Agent Mode more domain‑specific powers through **MCP tools**.
|
||||
>
|
||||
> Read more on [MCP servers](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) and [GitHub MCP Server](https://github.com/github/github-mcp-server)
|
||||
|
||||
Now, let's give **Agent Mode** a try! 👩🚀
|
||||
|
||||
### :keyboard: Activity: Use Agent mode to add functional "unregister" buttons
|
||||
|
||||
Let's experiment with some more open-ended requests that will add more functionality to our web application.
|
||||
|
||||
If you don't get the desired results, you can try other models or provided followup feedback to refine the results.
|
||||
|
||||
1. Open the **Copilot** chat panel and use the dropdown menu to switch to **Agent** mode.
|
||||
|
||||
<img width="250" alt="agent mode" src="https://github.com/user-attachments/assets/9bb85530-77a1-4d47-86b2-99769ce197db" />
|
||||
|
||||
1. Click on the **Tools** icon and explore all Tools currently available to Copilot Agent Mode.
|
||||
|
||||
<img width="250" alt="tools icon" src="https://github.com/user-attachments/assets/8f73400a-2647-4b28-b52b-721b8cf348d8" />
|
||||
|
||||
|
||||
1. Time for our test! Let's ask Copilot to add functionality for removing participants.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> #codebase Please add a delete icon next to each participant and hide the bullet points.
|
||||
> When clicked, it will unregister that participant from the activity.
|
||||
> ```
|
||||
|
||||
The `#codebase` tool is used by Copilot to find relevant files, code chunks that are relevant to the task at hand.
|
||||
|
||||
> 🪧 **Note:** In this lab we explicitly include the `#codebase` tool to get the most repeatable results.
|
||||
> Feel free to try the prompt **without** `#codebase` and observe whether Agent Mode decides to gather broader project context on its own.
|
||||
|
||||
1. When Copilot is finished, restart the debugger and inspect the results. If you like the results, press the **Keep** button. If not, try providing Copilot some feedback to refined the results.
|
||||
|
||||
1. Ask Copilot to fix a registration bug.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> I've noticed there seems to be a bug.
|
||||
> When a participant is registered, the page must be refreshed to see the change on the activity.
|
||||
> ```
|
||||
|
||||
1. When Copilot is finished, inspect the results. If you like the results, press the **Keep** button. If not, try providing Copilot some feedback.
|
||||
|
||||
### :keyboard: Activity: Use Agent mode to get test coverage 🧑🚀
|
||||
|
||||
Your backend is now feature‑rich—but still has zero test coverage. Use Copilot **Agent Mode** to add test dependencies, scaffold starter tests and run them.
|
||||
|
||||
1. Ask Copilot in **Agent mode** to set up and run tests for your backend.
|
||||
|
||||
> 
|
||||
>
|
||||
> ```prompt
|
||||
> Add fastapi tests using pytest in a new tests directory and run them.
|
||||
> Make sure to add any new dependencies to requirements.txt
|
||||
> ```
|
||||
|
||||
1. As Copilot works on your prompt, different tools might need your approval.
|
||||
|
||||
**🎯 Goal: Get all tests passing (green) — aim for a clean run! ✅**
|
||||
|
||||
> 🪧 **Note:** Copilot may one-shot this with the initial prompt or need more guidance from you.
|
||||
|
||||
1. Once the tests are passing - **commit** and **push** all changes to your `accelerate-with-copilot` branch to progress to the last step! Almost done!
|
||||
42
.github/steps/5-copilot-on-github.md
vendored
Normal file
42
.github/steps/5-copilot-on-github.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
## Step 5: Using GitHub Copilot within a pull request
|
||||
|
||||
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!
|
||||
|
||||
### 📖 Theory: GitHub Copilot for pull requests
|
||||
|
||||
#### Copilot pull request summaries
|
||||
|
||||
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!
|
||||
|
||||
#### Copilot code review
|
||||
|
||||
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 are fixed by simple adjustments, but please remember to use it responsibly.
|
||||
|
||||
> [!NOTE]
|
||||
> These features are only available on paid plans of **GitHub Copilot**. [[docs]](https://docs.github.com/en/copilot/get-started/plans)
|
||||
|
||||
### :keyboard: Activity: Summarize and review a PR with Copilot
|
||||
|
||||
Both **Copilot pull request summaries** and **Copilot code review** have limited access, so this activity is mostly optional. If you don't have access, skip the optional steps of this activity.
|
||||
|
||||
1. In a web browser, open another tab and navigate to your exercise repository.
|
||||
|
||||
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:
|
||||
|
||||
- **base:** `main`
|
||||
- **compare:** `accelerate-with-copilot`
|
||||
- **title:** `Improve student activity registration system`
|
||||
|
||||
1. (Optional) In the PR description toolbar click the **Copilot** icon and **Summary** action. After a moment, Copilot will add a description based on your changes. :memo:
|
||||
|
||||
<img alt="Copilot summarize button " width="450px" src="https://github.com/user-attachments/assets/7a712d8b-484d-41df-9353-bc2b397fc1e0">
|
||||
|
||||
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!
|
||||
|
||||
<img alt="Copilot review button" width="300px" src="https://github.com/user-attachments/assets/39b15002-a235-4c25-b09d-6a8097e27b62">
|
||||
|
||||
> 💡 **Tip:** Notice a log entry that Copilot was requested for a review.
|
||||
|
||||
1. At the bottom, press the **Merge pull request** button. Nice work! You are all done! :tada:
|
||||
|
||||
1. Wait a moment for Mona to check your work, provide feedback, and post a final review of this exercise!
|
||||
22
.github/steps/x-review.md
vendored
Normal file
22
.github/steps/x-review.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
## Review
|
||||
|
||||
_Congratulations, you've completed this exercise and learned a lot about GitHub Copilot!_
|
||||
|
||||
<img src="https://octodex.github.com/images/jetpacktocat.png" alt=celebrate width=200 align=right>
|
||||
|
||||
Here's a recap of the GitHub Copilot features you learned:
|
||||
|
||||
- **Ask Mode**: Used @workspace to explore and understand your codebase
|
||||
- **Inline suggestions**: Completed code with Tab acceptance
|
||||
- **Inline Chat**: Generated code and data with Ctrl/Cmd + I
|
||||
- **Edit Mode**: Made multi-file changes with targeted prompts
|
||||
- **Agent Mode**: Built features and tests autonomously
|
||||
- **GitHub integration**: Generated commit messages, PR summaries, and code reviews
|
||||
|
||||
### What's next?
|
||||
|
||||
- Check out the other [GitHub Skills exercises](https://learn.github.com/skills).
|
||||
- Learn how to [Integrate MCP with Copilot](https://github.com/skills/integrate-mcp-with-copilot) to give Copilot extra capabilities!
|
||||
- Tailor Copilot to your project needs in [Customize your GitHub Copilot Experience](https://github.com/skills/customize-your-github-copilot-experience)
|
||||
- Tackle legacy COBOL code in [Modernize Your Legacy Code with GitHub Copilot](https://github.com/skills/modernize-your-legacy-code-with-github-copilot) exercise
|
||||
- Try GitHub Copilot Coding Agent in the [Expand your team with Copilot](https://github.com/skills/expand-your-team-with-copilot) exercise
|
||||
66
.github/workflows/0-start-exercise.yml
vendored
Normal file
66
.github/workflows/0-start-exercise.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
name: Step 0 # Start Exercise
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
STEP_1_FILE: ".github/steps/1-preparing.md"
|
||||
|
||||
jobs:
|
||||
start_exercise:
|
||||
if: |
|
||||
!github.event.repository.is_template
|
||||
name: Start Exercise
|
||||
uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.7.0
|
||||
with:
|
||||
exercise-title: "Getting Started with GitHub Copilot"
|
||||
intro-message: "Welcome to the exciting world of GitHub Copilot! 🚀 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! 💻✨"
|
||||
|
||||
post_next_step_content:
|
||||
name: Post next step content
|
||||
runs-on: ubuntu-latest
|
||||
needs: [start_exercise]
|
||||
env:
|
||||
ISSUE_NUMBER: ${{ needs.start_exercise.outputs.issue-number }}
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - add step content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.STEP_1_FILE }}
|
||||
vars: |
|
||||
login: ${{ github.actor }}
|
||||
full_repo_name: ${{ github.repository }}
|
||||
|
||||
- name: Create comment - watching for progress
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
|
||||
|
||||
- name: Enable next step workflow
|
||||
run: |
|
||||
gh workflow enable "Step 1"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
139
.github/workflows/1-preparing.yml
vendored
Normal file
139
.github/workflows/1-preparing.yml
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
name: Step 1
|
||||
|
||||
on:
|
||||
push:
|
||||
# Trigger on pushes to any branch except the protected `main` branch
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
STEP_2_FILE: ".github/steps/2-first-introduction.md"
|
||||
|
||||
jobs:
|
||||
find_exercise:
|
||||
name: Find Exercise Issue
|
||||
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
|
||||
|
||||
check_step_work:
|
||||
name: Check step work
|
||||
runs-on: ubuntu-latest
|
||||
needs: [find_exercise]
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Find last comment
|
||||
id: find-last-comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
direction: last
|
||||
|
||||
- name: Update comment - checking work
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
|
||||
edit-mode: replace
|
||||
|
||||
# START: Check practical exercise
|
||||
|
||||
- name: Check branch name is correct
|
||||
id: check-branch
|
||||
continue-on-error: true
|
||||
uses: skills/action-keyphrase-checker@v1
|
||||
with:
|
||||
# Check the branch ref directly
|
||||
text: ${{ github.ref }}
|
||||
keyphrase: accelerate-with-copilot
|
||||
case-sensitive: true
|
||||
minimum-occurrences: 1
|
||||
maximum-occurrences: 1
|
||||
|
||||
- name: Update comment - step results
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
|
||||
vars: |
|
||||
step_number: 1
|
||||
results_table:
|
||||
- description: "Checked that branch name is accelerate-with-copilot"
|
||||
passed: ${{ steps.check-branch.outcome == 'success' }}
|
||||
|
||||
# END: Check practical exercise
|
||||
|
||||
- name: Fail job if check failed
|
||||
if: ${{ steps.check-branch.outcome != 'success' }}
|
||||
run: exit 1
|
||||
|
||||
post_next_step_content:
|
||||
name: Post next step content
|
||||
needs: [find_exercise, check_step_work]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - step finished
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
|
||||
vars: |
|
||||
next_step_number: 2
|
||||
|
||||
- name: Create comment - add step content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.STEP_2_FILE }}
|
||||
|
||||
- name: Create comment - watching for progress
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
|
||||
|
||||
- name: Disable current workflow and enable next one
|
||||
run: |
|
||||
gh workflow disable "${{github.workflow}}"
|
||||
gh workflow enable "Step 2"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
136
.github/workflows/2-first-introduction.yml
vendored
Normal file
136
.github/workflows/2-first-introduction.yml
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
name: Step 2
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "accelerate-with-copilot"
|
||||
paths:
|
||||
- "src/app.py"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
STEP_3_FILE: ".github/steps/3-copilot-edits.md"
|
||||
|
||||
jobs:
|
||||
find_exercise:
|
||||
name: Find Exercise Issue
|
||||
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
|
||||
|
||||
check_step_work:
|
||||
name: Check step work
|
||||
runs-on: ubuntu-latest
|
||||
needs: [find_exercise]
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Find last comment
|
||||
id: find-last-comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
direction: last
|
||||
|
||||
- name: Update comment - checking work
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
|
||||
edit-mode: replace
|
||||
|
||||
# START: Check practical exercise
|
||||
|
||||
- name: Check for additional student activities
|
||||
id: check-additional-activities
|
||||
continue-on-error: true
|
||||
uses: skills/action-keyphrase-checker@v1
|
||||
with:
|
||||
text-file: src/app.py
|
||||
keyphrase: '"description"'
|
||||
minimum-occurrences: 4
|
||||
case-sensitive: false
|
||||
|
||||
- name: Update comment - step results
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
|
||||
vars: |
|
||||
step_number: 2
|
||||
results_table:
|
||||
- description: "New activities added to src/app.py. We found ${{ steps.check-additional-activities.outputs.occurrences }} activities (minimum 4 required)"
|
||||
passed: ${{ steps.check-additional-activities.outcome == 'success' }}
|
||||
|
||||
- name: Fail job if not all checks passed
|
||||
if: contains(steps.*.outcome, 'failure')
|
||||
run: exit 1
|
||||
|
||||
post_next_step_content:
|
||||
name: Post next step content
|
||||
needs: [find_exercise, check_step_work]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - step finished
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
|
||||
vars: |
|
||||
next_step_number: 3
|
||||
|
||||
- name: Create comment - add step content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.STEP_3_FILE }}
|
||||
|
||||
- name: Create comment - watching for progress
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
|
||||
|
||||
- name: Disable current workflow and enable next one
|
||||
run: |
|
||||
gh workflow disable "${{github.workflow}}"
|
||||
gh workflow enable "Step 3"
|
||||
gh workflow enable "Step 3b"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
146
.github/workflows/3-copilot-edits.yml
vendored
Normal file
146
.github/workflows/3-copilot-edits.yml
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
name: Step 3
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "accelerate-with-copilot"
|
||||
paths:
|
||||
- "src/static/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
STEP_4_FILE: ".github/steps/4-copilot-agent-mode.md"
|
||||
|
||||
jobs:
|
||||
find_exercise:
|
||||
name: Find Exercise Issue
|
||||
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
|
||||
|
||||
check_step_work:
|
||||
name: Check step work
|
||||
runs-on: ubuntu-latest
|
||||
needs: [find_exercise]
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Find last comment
|
||||
id: find-last-comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
direction: last
|
||||
|
||||
- name: Update comment - checking work
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
|
||||
edit-mode: replace
|
||||
|
||||
- name: Check for participant info in app.js
|
||||
id: check-app-js
|
||||
continue-on-error: true
|
||||
uses: skills/action-keyphrase-checker@v1
|
||||
with:
|
||||
text-file: src/static/app.js
|
||||
keyphrase: participant
|
||||
minimum-occurrences: 3
|
||||
case-sensitive: false
|
||||
|
||||
- name: Check for participant info in styles.css
|
||||
id: check-styles-css
|
||||
continue-on-error: true
|
||||
uses: skills/action-keyphrase-checker@v1
|
||||
with:
|
||||
text-file: src/static/styles.css
|
||||
keyphrase: participant
|
||||
minimum-occurrences: 1
|
||||
case-sensitive: false
|
||||
|
||||
- name: Update comment - step results
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
|
||||
vars: |
|
||||
step_number: 3
|
||||
results_table:
|
||||
- description: "Check app.js for participant info"
|
||||
passed: ${{ steps.check-app-js.outcome == 'success' }}
|
||||
- description: "Check styles.css for participant info"
|
||||
passed: ${{ steps.check-styles-css.outcome == 'success' }}
|
||||
|
||||
- name: Fail job if not all checks passed
|
||||
if: contains(steps.*.outcome, 'failure')
|
||||
run: exit 1
|
||||
|
||||
post_next_step_content:
|
||||
name: Post next step content
|
||||
needs: [find_exercise, check_step_work]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - step finished
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
|
||||
vars: |
|
||||
next_step_number: 4
|
||||
|
||||
- name: Create comment - add step content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.STEP_4_FILE }}
|
||||
|
||||
- name: Create comment - watching for progress
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
|
||||
|
||||
- name: Disable current workflow and enable next one
|
||||
run: |
|
||||
gh workflow disable "${{github.workflow}}"
|
||||
gh workflow enable "Step 4"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
148
.github/workflows/4-copilot-agent-mode.yml
vendored
Normal file
148
.github/workflows/4-copilot-agent-mode.yml
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
name: Step 4
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "accelerate-with-copilot"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
STEP_5_FILE: ".github/steps/5-copilot-on-github.md"
|
||||
|
||||
jobs:
|
||||
find_exercise:
|
||||
name: Find Exercise Issue
|
||||
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
|
||||
|
||||
check_step_work:
|
||||
name: Check step work
|
||||
runs-on: ubuntu-latest
|
||||
needs: [find_exercise]
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Find last comment
|
||||
id: find-last-comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
direction: last
|
||||
|
||||
- name: Update comment - checking work
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/checking-work.md
|
||||
edit-mode: replace
|
||||
|
||||
# START: Check practical exercise
|
||||
|
||||
- name: Check for pytest keyphrase in requirements.txt
|
||||
id: check-for-pytest
|
||||
continue-on-error: true
|
||||
uses: skills/action-keyphrase-checker@v1
|
||||
with:
|
||||
text-file: requirements.txt
|
||||
keyphrase: pytest
|
||||
|
||||
- name: Check if tests directory exists
|
||||
id: check-tests-dir
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if find . -name "tests" -type d | grep -q .; then
|
||||
echo "Tests directory found"
|
||||
exit 0
|
||||
else
|
||||
echo "Tests directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Update comment - step results
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
comment-id: ${{ steps.find-last-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
|
||||
vars: |
|
||||
step_number: 4
|
||||
results_table:
|
||||
- description: "Checked for pytest in requirements.txt"
|
||||
passed: ${{ steps.check-for-pytest.outcome == 'success' }}
|
||||
- description: "Checked if tests are added in a separate directory"
|
||||
passed: ${{ steps.check-tests-dir.outcome == 'success' }}
|
||||
|
||||
# END: Check practical exercise
|
||||
|
||||
- name: Fail job if not all checks passed
|
||||
if: contains(steps.*.outcome, 'failure')
|
||||
run: exit 1
|
||||
|
||||
post_next_step_content:
|
||||
name: Post next step content
|
||||
needs: [find_exercise, check_step_work]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - step finished
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/step-finished-prepare-next-step.md
|
||||
vars: |
|
||||
next_step_number: 5
|
||||
|
||||
- name: Create comment - add step content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.STEP_5_FILE }}
|
||||
|
||||
- name: Create comment - watching for progress
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/watching-for-progress.md
|
||||
|
||||
- name: Disable current workflow and enable next one
|
||||
run: |
|
||||
gh workflow disable "${{github.workflow}}"
|
||||
gh workflow enable "Step 5"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
67
.github/workflows/5-copilot-on-github.yml
vendored
Normal file
67
.github/workflows/5-copilot-on-github.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: Step 5
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types:
|
||||
- closed
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
REVIEW_FILE: ".github/steps/x-review.md"
|
||||
|
||||
jobs:
|
||||
find_exercise:
|
||||
name: Find Exercise Issue
|
||||
uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.7.0
|
||||
|
||||
post_review_content:
|
||||
name: Post review content
|
||||
needs: [find_exercise]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ISSUE_REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ needs.find_exercise.outputs.issue-number }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Get response templates
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: skills/exercise-toolkit
|
||||
path: exercise-toolkit
|
||||
ref: v0.7.0
|
||||
|
||||
- name: Create comment - step finished - final review next
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: exercise-toolkit/markdown-templates/step-feedback/lesson-review.md
|
||||
|
||||
- name: Create comment - add review content
|
||||
uses: GrantBirki/comment@v2.1.1
|
||||
with:
|
||||
repository: ${{ env.ISSUE_REPOSITORY }}
|
||||
issue-number: ${{ env.ISSUE_NUMBER }}
|
||||
file: ${{ env.REVIEW_FILE }}
|
||||
|
||||
- name: Disable current workflow
|
||||
run: gh workflow disable "${{github.workflow}}"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
finish_exercise:
|
||||
name: Finish Exercise
|
||||
needs: [find_exercise, post_review_content]
|
||||
uses: skills/exercise-toolkit/.github/workflows/finish-exercise.yml@v0.7.1
|
||||
with:
|
||||
issue-url: ${{ needs.find_exercise.outputs.issue-url }}
|
||||
exercise-title: "Getting Started with GitHub Copilot"
|
||||
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
*.temp*
|
||||
|
||||
# Compiled source #
|
||||
###################
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.so
|
||||
|
||||
# Packages #
|
||||
############
|
||||
# it's better to unpack these files and commit the raw source
|
||||
# git has its own built in compression methods
|
||||
*.7z
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
|
||||
# Logs and databases #
|
||||
######################
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.actrc*
|
||||
|
||||
__pycache__/
|
||||
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Mergington WebApp",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"module": "uvicorn",
|
||||
"args": [
|
||||
"src.app:app",
|
||||
"--reload"
|
||||
],
|
||||
"jinja": true
|
||||
}
|
||||
]
|
||||
}
|
||||
20
LICENSE
Normal file
20
LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) GitHub and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Getting Started with GitHub Copilot
|
||||
|
||||
_Get started using GitHub Copilot in less than an hour._
|
||||
|
||||
## Welcome
|
||||
|
||||
- **Who is this for**: Developers at any experience level looking to accelerate their code workflow.
|
||||
- **What you'll learn**: The different ways to interact with Copilot to explain, write, debug, and develop code.
|
||||
- **What you'll build**: You will guide Copilot to update Mergington High School's extracurricular activities website.
|
||||
- **Prerequisites**:
|
||||
- Skills exercise: [Introduction to GitHub](https://github.com/skills/introduction-to-github)
|
||||
- Familiarity with [VS Code](https://code.visualstudio.com/)
|
||||
- Basic coding principles
|
||||
- **How long**: This exercise takes less than one hour to complete.
|
||||
|
||||
In this exercise, you will:
|
||||
|
||||
1. Use a preconfigured Codespace to run VS Code in your browser.
|
||||
1. Learn different interaction options to develop with GitHub Copilot.
|
||||
1. Use Copilot to summarize and review your pull request.
|
||||
|
||||
### How to start this exercise
|
||||
|
||||
Simply copy the exercise to your account, then give your favorite Octocat (Mona) **about 20 seconds** to prepare the first lesson, then **refresh the page**.
|
||||
|
||||
[](https://github.com/new?template_owner=skills&template_name=getting-started-with-github-copilot&owner=%40me&name=skills-getting-started-with-github-copilot&description=Exercise:+Get+started+using+GitHub+Copilot&visibility=public)
|
||||
|
||||
<details>
|
||||
<summary>Having trouble? 🤷</summary><br/>
|
||||
|
||||
When copying the exercise, we recommend the following settings:
|
||||
|
||||
- For owner, choose your personal account or an organization to host the repository.
|
||||
|
||||
- We recommend creating a public repository, since private repositories will use Actions minutes.
|
||||
|
||||
If the exercise isn't ready in 20 seconds, please check the [Actions](../../actions) tab.
|
||||
|
||||
- Check to see if a job is running. Sometimes it simply takes a bit longer.
|
||||
|
||||
- If the page shows a failed job, please submit an issue. Nice, you found a bug! 🐛
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
© 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)
|
||||
2
pytest.ini
Normal file
2
pytest.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[pytest]
|
||||
pythonpath = .
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
fastapi
|
||||
uvicorn
|
||||
50
src/README.md
Normal file
50
src/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Mergington High School Activities API
|
||||
|
||||
A super simple FastAPI application that allows students to view and sign up for extracurricular activities.
|
||||
|
||||
## Features
|
||||
|
||||
- View all available extracurricular activities
|
||||
- Sign up for activities
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Install the dependencies:
|
||||
|
||||
```
|
||||
pip install fastapi uvicorn
|
||||
```
|
||||
|
||||
2. Run the application:
|
||||
|
||||
```
|
||||
python app.py
|
||||
```
|
||||
|
||||
3. Open your browser and go to:
|
||||
- API documentation: http://localhost:8000/docs
|
||||
- Alternative documentation: http://localhost:8000/redoc
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| ------ | ----------------------------------------------------------------- | ------------------------------------------------------------------- |
|
||||
| GET | `/activities` | Get all activities with their details and current participant count |
|
||||
| POST | `/activities/{activity_name}/signup?email=student@mergington.edu` | Sign up for an activity |
|
||||
|
||||
## Data Model
|
||||
|
||||
The application uses a simple data model with meaningful identifiers:
|
||||
|
||||
1. **Activities** - Uses activity name as identifier:
|
||||
|
||||
- Description
|
||||
- Schedule
|
||||
- Maximum number of participants allowed
|
||||
- List of student emails who are signed up
|
||||
|
||||
2. **Students** - Uses email as identifier:
|
||||
- Name
|
||||
- Grade level
|
||||
|
||||
All data is stored in memory, which means data will be reset when the server restarts.
|
||||
67
src/app.py
Normal file
67
src/app.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""
|
||||
High School Management System API
|
||||
|
||||
A super simple FastAPI application that allows students to view and sign up
|
||||
for extracurricular activities at Mergington High School.
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import RedirectResponse
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
app = FastAPI(title="Mergington High School API",
|
||||
description="API for viewing and signing up for extracurricular activities")
|
||||
|
||||
# Mount the static files directory
|
||||
current_dir = Path(__file__).parent
|
||||
app.mount("/static", StaticFiles(directory=os.path.join(Path(__file__).parent,
|
||||
"static")), name="static")
|
||||
|
||||
# In-memory activity database
|
||||
activities = {
|
||||
"Chess Club": {
|
||||
"description": "Learn strategies and compete in chess tournaments",
|
||||
"schedule": "Fridays, 3:30 PM - 5:00 PM",
|
||||
"max_participants": 12,
|
||||
"participants": ["michael@mergington.edu", "daniel@mergington.edu"]
|
||||
},
|
||||
"Programming Class": {
|
||||
"description": "Learn programming fundamentals and build software projects",
|
||||
"schedule": "Tuesdays and Thursdays, 3:30 PM - 4:30 PM",
|
||||
"max_participants": 20,
|
||||
"participants": ["emma@mergington.edu", "sophia@mergington.edu"]
|
||||
},
|
||||
"Gym Class": {
|
||||
"description": "Physical education and sports activities",
|
||||
"schedule": "Mondays, Wednesdays, Fridays, 2:00 PM - 3:00 PM",
|
||||
"max_participants": 30,
|
||||
"participants": ["john@mergington.edu", "olivia@mergington.edu"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def root():
|
||||
return RedirectResponse(url="/static/index.html")
|
||||
|
||||
|
||||
@app.get("/activities")
|
||||
def get_activities():
|
||||
return activities
|
||||
|
||||
|
||||
@app.post("/activities/{activity_name}/signup")
|
||||
def signup_for_activity(activity_name: str, email: str):
|
||||
"""Sign up a student for an activity"""
|
||||
# Validate activity exists
|
||||
if activity_name not in activities:
|
||||
raise HTTPException(status_code=404, detail="Activity not found")
|
||||
|
||||
# Get the specific activity
|
||||
activity = activities[activity_name]
|
||||
|
||||
# Add student
|
||||
activity["participants"].append(email)
|
||||
return {"message": f"Signed up {email} for {activity_name}"}
|
||||
86
src/static/app.js
Normal file
86
src/static/app.js
Normal file
@@ -0,0 +1,86 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const activitiesList = document.getElementById("activities-list");
|
||||
const activitySelect = document.getElementById("activity");
|
||||
const signupForm = document.getElementById("signup-form");
|
||||
const messageDiv = document.getElementById("message");
|
||||
|
||||
// Function to fetch activities from API
|
||||
async function fetchActivities() {
|
||||
try {
|
||||
const response = await fetch("/activities");
|
||||
const activities = await response.json();
|
||||
|
||||
// Clear loading message
|
||||
activitiesList.innerHTML = "";
|
||||
|
||||
// Populate activities list
|
||||
Object.entries(activities).forEach(([name, details]) => {
|
||||
const activityCard = document.createElement("div");
|
||||
activityCard.className = "activity-card";
|
||||
|
||||
const spotsLeft = details.max_participants - details.participants.length;
|
||||
|
||||
activityCard.innerHTML = `
|
||||
<h4>${name}</h4>
|
||||
<p>${details.description}</p>
|
||||
<p><strong>Schedule:</strong> ${details.schedule}</p>
|
||||
<p><strong>Availability:</strong> ${spotsLeft} spots left</p>
|
||||
`;
|
||||
|
||||
activitiesList.appendChild(activityCard);
|
||||
|
||||
// Add option to select dropdown
|
||||
const option = document.createElement("option");
|
||||
option.value = name;
|
||||
option.textContent = name;
|
||||
activitySelect.appendChild(option);
|
||||
});
|
||||
} catch (error) {
|
||||
activitiesList.innerHTML = "<p>Failed to load activities. Please try again later.</p>";
|
||||
console.error("Error fetching activities:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle form submission
|
||||
signupForm.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const email = document.getElementById("email").value;
|
||||
const activity = document.getElementById("activity").value;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/activities/${encodeURIComponent(activity)}/signup?email=${encodeURIComponent(email)}`,
|
||||
{
|
||||
method: "POST",
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
messageDiv.textContent = result.message;
|
||||
messageDiv.className = "success";
|
||||
signupForm.reset();
|
||||
} else {
|
||||
messageDiv.textContent = result.detail || "An error occurred";
|
||||
messageDiv.className = "error";
|
||||
}
|
||||
|
||||
messageDiv.classList.remove("hidden");
|
||||
|
||||
// Hide message after 5 seconds
|
||||
setTimeout(() => {
|
||||
messageDiv.classList.add("hidden");
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
messageDiv.textContent = "Failed to sign up. Please try again.";
|
||||
messageDiv.className = "error";
|
||||
messageDiv.classList.remove("hidden");
|
||||
console.error("Error signing up:", error);
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize app
|
||||
fetchActivities();
|
||||
});
|
||||
50
src/static/index.html
Normal file
50
src/static/index.html
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Mergington High School Activities</title>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Mergington High School</h1>
|
||||
<h2>Extracurricular Activities</h2>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section id="activities-container">
|
||||
<h3>Available Activities</h3>
|
||||
<div id="activities-list">
|
||||
<!-- Activities will be loaded here -->
|
||||
<p>Loading activities...</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="signup-container">
|
||||
<h3>Sign Up for an Activity</h3>
|
||||
<form id="signup-form">
|
||||
<div class="form-group">
|
||||
<label for="email">Student Email:</label>
|
||||
<input type="email" id="email" required placeholder="your-email@mergington.edu" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="activity">Select Activity:</label>
|
||||
<select id="activity" required>
|
||||
<option value="">-- Select an activity --</option>
|
||||
<!-- Activity options will be loaded here -->
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit">Sign Up</button>
|
||||
</form>
|
||||
<div id="message" class="hidden"></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>© 2023 Mergington High School</p>
|
||||
</footer>
|
||||
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
144
src/static/styles.css
Normal file
144
src/static/styles.css
Normal file
@@ -0,0 +1,144 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
margin-bottom: 30px;
|
||||
background-color: #1a237e;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 30px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
main {
|
||||
grid-template-columns: 2fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
section h3 {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
color: #1a237e;
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
margin-bottom: 15px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.activity-card h4 {
|
||||
margin-bottom: 10px;
|
||||
color: #0066cc;
|
||||
}
|
||||
|
||||
.activity-card p {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group select {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #1a237e;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #3949ab;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: #e8f5e9;
|
||||
color: #2e7d32;
|
||||
border: 1px solid #a5d6a7;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: #ffebee;
|
||||
color: #c62828;
|
||||
border: 1px solid #ef9a9a;
|
||||
}
|
||||
|
||||
.info {
|
||||
background-color: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding: 20px;
|
||||
color: #666;
|
||||
}
|
||||
Reference in New Issue
Block a user