Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions content/get-started/learning-to-code/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ children:
- /getting-started-with-git
- /finding-and-understanding-example-code
- /reusing-other-peoples-code-in-your-projects
- /setting-up-copilot-for-learning-to-code
- /learning-to-debug-with-github-copilot
- /storing-your-secrets-safely
shortTitle: Learn to code
---

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: Setting up Copilot for learning to code
intro: 'Configure {% data variables.product.prodname_copilot_short %} to help you learn coding concepts and actively build your programming skills.'
versions:
fpt: '*'
topics:
- Copilot
shortTitle: Set up Copilot for learning
---

## Can {% data variables.product.prodname_copilot_short %} help me learn to code?

Yes! {% data variables.product.prodname_copilot_short %} can adapt to meet your changing needs throughout your coding journey. When you're an experienced developer, you'll use {% data variables.product.prodname_copilot_short %} as a coding assistant. While you're learning to code, it's more beneficial as a **supportive companion**.

In this guide, you’ll learn how to set up {% data variables.product.prodname_copilot_short %} to act as a **tutor** that will help you build a deep understanding of programming concepts, rather than relying on it to write your code for you. To optimize your learning, follow these steps for each repository you work on!

## Prerequisites

This guide assumes that you'll use {% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vscode_shortname %}. To get set up, see [Set up Copilot in {% data variables.product.prodname_vscode_shortname %}](https://code.visualstudio.com/docs/copilot/setup-simplified) in the {% data variables.product.prodname_vscode %} documentation.

## Step 1: Disable code completions

First, let's disable code completions. This will give you the opportunity to deepen your understanding of programming concepts by writing more code yourself.

1. In {% data variables.product.prodname_vscode_shortname %}, open your project.
1. Create a folder in the root directory called `.vscode`.
1. Inside `.vscode`, create a file called `settings.json`.
1. Add the following text to the file:

```json copy
{
"github.copilot.enable": {
"*": false
}
}
```

1. Save the file. {% data variables.product.prodname_copilot_short %} code completions are now disabled for this project in {% data variables.product.prodname_vscode_shortname %}.

## Step 2: Add learning instructions

Now, let's provide {% data variables.product.prodname_copilot_chat_short %} with instructions to act like a tutor that supports your learning.

1. In the root folder of your project, create a file called `copilot-instructions.md`.
1. Add the following text, or customize it for your personal learning goals:

```markdown copy
I am learning to code. You are to act as a tutor; assume I am a beginning coder. Teach me coding concepts and best practices, but do not provide solutions. Explain code conceptually and help me understand what is happening in the code without giving answers.

Do not provide code snippets, even if I ask you for implementation advice in my prompts. Teach me all the basic coding concepts in your answers. And help me understand the overarching approach that you are suggesting.

Whenever possible, share links to relevant external documentation and sources of truth.

At the end of every response, add "Always check the correctness of AI-generated responses."
```

1. Save the file. {% data variables.product.prodname_copilot_short %} will use these instructions when you ask questions in {% data variables.product.prodname_copilot_chat_short %}.

## Step 3: Use {% data variables.product.prodname_copilot_chat_short %} to learn

You're ready to start building real coding skills with {% data variables.product.prodname_copilot_short %}'s help!

Throughout your work on the project, engage in a long-running conversation with **{% data variables.product.prodname_copilot_chat_short %}**. Treat it as your **personal tutor**, asking questions as they arise and using it to navigate challenges or clarify concepts.

> [!TIP] You can open {% data variables.product.prodname_copilot_chat_short %} with a keyboard shortcut: <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>I</kbd> (Windows/Linux) or <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> (Mac).

{% data variables.product.prodname_copilot_chat_short %} is especially helpful for debugging your code. For step-by-step guidance, see [AUTOTITLE](/get-started/learning-to-code/learning-to-debug-with-github-copilot).
24 changes: 11 additions & 13 deletions src/events/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,19 @@ router.post(
const validEvents: any[] = []
const validationErrors: any[] = []

// We use a LRU cache & a hash of the request IP + error message
// to prevent sending multiple validation errors per user that can spam requests to Hydro
const getValidationErrorHash = (validateErrors: ErrorObject[]) =>
`${req.ip}:${(validateErrors || [])
.map(
(error: ErrorObject) => error.message + error.instancePath + JSON.stringify(error.params),
)
.join(':')}`

for (const eventBody of eventsToProcess) {
try {
// Skip event if it doesn't have a type or if the type is not in the allowed types
if (!eventBody.type || !allowedTypes.has(eventBody.type)) {
validationErrors.push({ event: eventBody, error: 'Invalid type' })
continue
}
const type: EventType = eventBody.type
Expand All @@ -71,18 +80,7 @@ router.post(
}
const validate = validators[type]
if (!validate(body)) {
validationErrors.push({
event: body,
error: validate.errors || [],
})
// This protects so we don't bother sending the same validation
// error, per user, more than once (per time interval).
// This helps if we're bombarded with junk bot traffic. So it
// protects our Hydro instance from being overloaded with things
// that aren't helping anybody.
const hash = `${req.ip}:${(validate.errors || [])
.map((error: ErrorObject) => error.message + error.instancePath)
.join(':')}`
const hash = getValidationErrorHash(validate.errors || [])
if (!sentValidationErrors.has(hash)) {
sentValidationErrors.set(hash, true)
formatErrors(validate.errors || [], body).map((error) => {
Expand Down
7 changes: 3 additions & 4 deletions src/events/tests/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ describe('POST /events', () => {
vi.setConfig({ testTimeout: 60 * 1000 })

async function checkEvent(data: any) {
// if data is not an array, make it one
if (!Array.isArray(data)) {
data = [data]
}
Expand Down Expand Up @@ -89,9 +88,9 @@ describe('POST /events', () => {
})

test('should require a type', async () => {
const { statusCode, body } = await checkEvent({ ...pageExample, type: undefined })
expect(statusCode).toBe(400)
expect(body).toContain('"error":"Invalid type"}')
const { statusCode } = await checkEvent({ ...pageExample, type: undefined })
// should skip events with no type
expect(statusCode).toBe(200)
})

test('should require an event_id in uuid', async () => {
Expand Down
Loading