From 74a1ccca10dc7bc31d0ac708c9a5a8cb2ba830b9 Mon Sep 17 00:00:00 2001 From: Joe Clark <31087804+jc-clark@users.noreply.github.com> Date: Thu, 24 Apr 2025 09:12:19 -0700 Subject: [PATCH 1/2] Add content on setting up Copilot for learning to code (#55316) Co-authored-by: Laura Coursen --- content/get-started/learning-to-code/index.md | 2 + ...setting-up-copilot-for-learning-to-code.md | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 content/get-started/learning-to-code/setting-up-copilot-for-learning-to-code.md diff --git a/content/get-started/learning-to-code/index.md b/content/get-started/learning-to-code/index.md index 75d48adb5ef6..cef59dc7080f 100644 --- a/content/get-started/learning-to-code/index.md +++ b/content/get-started/learning-to-code/index.md @@ -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 --- + diff --git a/content/get-started/learning-to-code/setting-up-copilot-for-learning-to-code.md b/content/get-started/learning-to-code/setting-up-copilot-for-learning-to-code.md new file mode 100644 index 000000000000..ff75f2a2e442 --- /dev/null +++ b/content/get-started/learning-to-code/setting-up-copilot-for-learning-to-code.md @@ -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: Ctrl+Alt+I (Windows/Linux) or Command+Shift+I (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). From 1448c36aa95df4e483d36d00fac93638389ba2fe Mon Sep 17 00:00:00 2001 From: Evan Bonsignori Date: Thu, 24 Apr 2025 11:05:28 -0700 Subject: [PATCH 2/2] fix validationError message body + use LRU/hash for "invalid type" validation errors (#55388) Co-authored-by: Ashish Keshan Co-authored-by: Ashish Keshan --- src/events/middleware.ts | 24 +++++++++++------------- src/events/tests/middleware.ts | 7 +++---- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/events/middleware.ts b/src/events/middleware.ts index 2b1210c1b268..69d52a4f9db1 100644 --- a/src/events/middleware.ts +++ b/src/events/middleware.ts @@ -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 @@ -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) => { diff --git a/src/events/tests/middleware.ts b/src/events/tests/middleware.ts index 37a75ef220ae..6da5601bdfd4 100644 --- a/src/events/tests/middleware.ts +++ b/src/events/tests/middleware.ts @@ -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] } @@ -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 () => {