Skip to content

Latest commit

 

History

History
610 lines (391 loc) · 30.3 KB

labs.md

File metadata and controls

610 lines (391 loc) · 30.3 KB

Hands-on GitHub Copilot

Practical Tips and Best Practices

Session labs (codespace version)

Revision 1.4 - 07/16/24

Versions of dialogs, buttons, etc. shown in screenshots may differ from current version of Copilot

Follow the startup instructions in the README.md file IF NOT ALREADY DONE!

NOTE: To copy and paste in the codespace, you may need to use keyboard commands - CTRL-C and CTRL-V.

Lab 1 - Learning how to create good prompts for Copilot

Purpose: In this lab, we’ll start to learn about Copilot and how it generates code based on the prompts we provide

  1. Create a new file. In the terminal, enter

    code index.js
    
  2. Afterwards this file should be open in a tab in the editor.

  3. Let's see how Copilot responds to a generic request. Go to that tab and type in a comment that says

// function to parse data
  1. Hit return and notice the code that Copilot suggested. This is likely more generic than we want, but hit tab to select that line. (Note that you should give Copilot a second to provide code suggestions before moving on to the next line.)

  2. After hitting tab, Copilot will generate another part of the function. (If not, you may need to hit return.) Hit tab to accept it. Continue until you get a complete function (or Copilot stops generating additional code suggestions). One example of what code may look like is below.

Copilot generated function

  1. This prompt is not specific enough for Copilot to interpret what we want to do. Highlight the code and delete it, so we can try again.

  2. Now type a comment at the top that says

// function to parse url
  1. Hit enter and you will probably see a similar line to
function parseURL(url) {
  1. Just hit Tab to accept it and Enter again. Pause. After that Copilot may or may not offer a suggestion. If it does, great - you can just hit Tab and accept it. If not, it may be necessary to further "nudge" Copilot by giving more prompts. Only if you're not getting responses from Copilot, hit return and type the comment below to nudge Copilot.
// parse url

nudge comment

  1. Only if needed, hit return and Copilot should start generating suggestions again. Pause after each return to give Copilot a chance to suggest code. Then you can just hit tab to accept each line and then return to get the next part of the code until the function is complete. You may get some blank lines along the way or for some lines you might need to hit Tab twice to accept the code if it is indented more. But just hit return until you get to the end of a function. (You will be at the end when the indentation is done. Also Copilot may start to suggest another function in comments like // test...)

  2. Suppose you're not happy with that suggestion. Copilot can provide other options for the code. To see those, make sure you are in the editor for the file, then delete all but the first line of the function and put the cursor at the end of the first line.

reset for altenate choices

  1. Hit Ctrl + Enter. A second window will open up with other suggestions. Be patient - it takes a bit of time for Copilot to generate alternative suggestions. After a moment though, you will have up to 10 alternatives to pick from. These will be of varying quality and completeness. You can scan through these and then pick one if suitable by clicking on the Accept suggestion # button under the alternative suggestion. Note that this will add the code to the existing set, so you may need to do some minor editing afterwards.

alternative suggestions

  1. Let's do one more pass at getting a specific prompt for Copilot. Delete all the code currently in index.js. This time we will not enter a comment, but will enter a specific function name. Type the following in the empty file. (There are no parentheses after the splitURLandReturnComponents text.) Do not hit tab or return yet.
function splitURLandReturnComponents
  1. With this function name, Copilot should suggest a full function definition - in fact it may suggest several. To see the options, hover over the first line and a small window should appear. This window will not how many options there are (probably 2 or 3) and provide "<" and ">" links to toggle between them. Click on the "<" and ">" buttons to see the differences in the available suggestions.

alternative suggestions inline

  1. When you find an alternative you like, go ahead and tab to select it.

**[END OF LAB]**

Lab 2 - Using Copilot to simplify code

  1. Create a new file named prime.py. Create it via the same process as we used in Lab 1 by entering the line below in the terminal.
code prime.py
  1. Start typing a function definition as below
def is_prime(n):
  1. Leave the cursor at the end of the line.

starting point

  1. Hit Ctrl+Enter to see options

  2. Pick one of the options that is longer and/or more complex (if there is one) and Accept suggestion #. If there's not one that's longer/more complex, just pick an alternative one and Accept suggestion #.

alternative suggestions

  1. Highlight the code and select the Chat extension icon to open the chat window. Tell Copilot to simplify the code by typing in the chat window.
/simplify

simplifying via chat box

  1. Hover over the simplified text and tell Copilot to insert the suggestion at the cursor to replace the text that's currently there.

replace from chat suggestion

  1. Now, let's introduce an error into the code to see how Copilot can fix it. Pick an instance of a variable name and change it to one that doesn't exist. For example, change an instance of "n" to "x".

introduce error

  1. Notice the light bulb icon that has popped up. Click on that, scroll to the bottom (if needed), and you'll have additional options to fix or explain with Copilot.

Copilot options inline

  1. Go ahead and click on the "Fix using Copilot" option.

  2. After a few moments, it should propose a fix that you can just accept (via the Accept button). You can also click on the Show Changes icon to see before/after for the proposed changes. (If it doesn't propose a fix in the dialog, you can skip to step 12 and use the /fix command in chat instead.)

Fixing with Copilot

  1. (Optional) If you'd like, you can go back and make the error again, highlight the code, and then use the /fix command in the chat window to get the same results.

**[END OF LAB]**

Lab 3 - Using Copilot after the coding

Purpose: In this lab, we’ll see a few other ways to leverage Copilot after the initial coding is done

  1. Now that we have some code to work with, let's see what else Copilot can do for us. Let's have it explain the current code in our prime.py file. Select the code. Then, use the Cmd+I keys to bring up the Copilot interactive chat dialog.

Interactively telling Copilot to explain code

  1. Tell Copilot to explain the code by typing the command below in the dialog. Hit Enter. Then, you should see the output in the dialog. Click on the View in Chat button to see the output in the separate chat window.
/explain

Output of interactively telling Copilot to explain code in dialog Output of interactively telling Copilot to explain code

  1. Now, let's do the same request but through a comment. In the prime.py file, below the code, enter the following comment and hit Enter.
# explain the code above line-by-line
  1. After this, Copilot should start showing the explanation in comments. Just hit tab to accept each line and then Enter to move to the next one.

Output of telling Copilot to explain code via comment

  1. We can also query Copilot inline via asking a question in a comment. Delete the commented explanation and try out the question below. To be clear you can prefix it with :q but that is not required with the chat feature installed.
# q: what does the function above do?

Prompting for what code does with q:

  1. Finally, let's see how to use the doc feature to automatically document our code. Highlight the actual code.

  2. Now, enter Cmd+I and enter the /doc command. After a few moments, Copilot should generate some documentation for the code. You can go ahead and Accept the changes.

Generated doc for the code

  1. While this is useful documentation for the start of the function, we'd like to have more extensive comments in the function body. So,let's get Copilot's help with that. Bring up the chat dialog again with Cmd+I and enter the text "verbosely comment this code". After Copilot completes its suggestions, if you're happy with them, you can just click Accept.

Regenerating doc

**[END OF LAB]**

Lab 4 - Using Copilot to generate tests

Purpose: In this lab, we'll see some examples of having Copilot generate tests

  1. Start out in the prime.py file we've been using. Position the cursor below the code.

  2. Enter a comment to create unit tests

# create a function to do 5 unit tests of the code above
  1. If you don't get a suggestion, enter code below to start nudging. Otherwise you can just accept the suggestion.
def test_is_prime():

generating tests via comment

  1. What if we didn't know how to test the code at all? Let's ask Copilot. Highlight the is_prime() function.

selecting code

  1. Now, switch to the chat interface and ask Copilot using the following prompt:
#selection: How do I test this code?

prompting on how to test

  1. After entering this, you should see an explanation of how to test the code along with suggested testing code. If you expand the reference in the chat output, you can see that it only used the selected lines.

testing explanation

  1. Let's see what the shortcut command would do. In the chat dialog enter "/tests" and then Enter. Copilot will want to add the @workspace agent onto the command. Just remove the @workspace from the beginning of the command. Do not hit enter yet.
/tests
  1. Type a hash/sharp sign after /tests. At this point, Copilot should present a selection dialog. Choose #file from the menu.
/tests #

shortcut test command

  1. A dialog will pop up near the top of the codespace with a selection of files. Select the prime.py file to complete the command.

file choice dialog

  1. Once the command looks like /tests #file:prime.py, go ahead and hit enter to see the suggested test results.

file choice dialog

  1. We can put this into a new file by hovering over the output in the Chat window, then selecting the "..." from the pop-up menu and selecting "Insert into new file". Go ahead and select that option and then you'll have a new file in your editor with the code that you can save as needed.

Insert tests into new file

**[END OF LAB]**

Lab 5 - Using Copilot to help with SQL

Purpose: In this lab, we’ll see some examples of how to have Copilot help with writing SQL

  1. Create a new file named dev.sql. You can create it via entering the line below in the terminal.
code dev.sql
  1. Afterwards this file should be open in a tab in the editor. Assume we want to work with a database or database definition that defines a dataset for students, staff, curriculums, courses, schools of study, locations, and registrations for a university system. Let's see what Copilot would generate for a query to get all students in a course - without any other context.

Enter the following comment below and press Tab to accept suggestions. Remember that you may have to hit Enter multiple times to get Copilot to prompt. Or if you don't get a suggestion or only get a comment, try "nudging" Copilot via typing "select".

-- define a select statement to get all students enrolled in a course
  1. Go ahead and save this file as part of the project. You can do this from the "3-line" menu under File->Save, or just click on the X next to the file's name in it's tab and select to Save it.

Save sql file

  1. If the file is no longer open in the tabs, you can select the "Explorer" icon at the top of the sidebar and select the file in the list to open it back up.

Reopening the file

  1. Let's see if we get any different results if we provide Copilot additional context. Open the file create-tables.sql in the editor from the GitHub repository. (You can either select and open it from the file list or use the command below from the terminal.) Scroll through it and take a quick look at the contents.
code create-tables.sql
  1. Now with that file open, go back up to the top of the dev.sql file. Highlight and delete the comment and resulting query from step 2.

  2. Enter the same comment as before to request the query. (Basically, repeat step 2.) See what Copilot suggests this time. You can accept the suggestions or cycle through options. (If you first get a duplicate line as the query, just hit Enter and Copilot should start making more meaningful suggestions.)

-- define a select statement to get all students enrolled in a course
  1. If all goes well, this second pass should generate a query with many more specific references to the names and identifiers used in create-tables.sql. (If not, delete the result and try again.) Take a look at the query and then compare the names/identifiers used to the ones in the create-tables.sql file. This will show that Copilot picks up on context from other files available to it to make better suggestions.

New query

  1. In some cases, we might be able to use a separate index to speed up operations. Let's ask Copilot to create a new index based on the last query. Add the following line after the current query in the file dev.sql.
-- write an index to improve the performance of the query

index

  1. Let's suppose we also want to have a table to capture student attendance. We can ask Copilot to create the table definition for us.
-- define a table for student attendance to capture attendance by class

(Here again, if you don't get a meaningful response from Copilot, you may need to nudge it by typing CREATE.) In the definition Copilot provided, it may have added a comment for the status in the same format as the comment in the courses.registration table definition in the create-tables.sql file.

status values

  1. Copilot can also create stored procedures. Let's ask it to create a new stored procedure for getting a list of enrolled students at a particular location. Let's use the CMD+I shortcut. Go to the bottom of the dev.sql file, invoke Copilot Chat via the shortcut and then enter the line below in the dialog. You can choose to Accept or Discard the result.
define a stored procedure to get course enrollment by location

prompt for stored procedure

  1. We can be more prescriptive with our stored procedure definition. Let's add a more complex request. Go to the Chat interface extension via clicking on the icon on the tool bar (if its not already opened). In the Chat window, enter the prompt below.
define a stored procedure to get instructor details associated with a location
include instructor details, location details, and courses associated with the instructor
use instructor_id as the input parameter

More extensive stored procedure definition

  1. Finally, let's see Copilot optimize a query for us. Suppose we want to get all the course registrations for September, 2023. Enter the following query in the file.
select * from courses.registrations where year(registration_date) = 2023 and month(registration_date) = 9;
  1. Ask Copilot to optimize the previous query. You can do this via highlighting the query (make sure to highlight the entire query), switch to the separate chat interface and entering "/optimize" in the dialog. You can Accept or Discard the suggested optimization after that.
/optimize

Optimizing a query

**[END OF LAB]**

Lab 6 - Teaching Copilot about updates

Purpose: In this lab, we’ll see an example of what to do when Copilot does not have the most up-to-date information

  1. Create a new file called explore.go via the same approach as you used to create other files.

  2. This file should now be open in an editor tab. Let's say we want to seed a random number generator with Go. Let's ask Copilot to write a function to do that. Prompt it through the CMD+I interface using the statement below. Then you can accept the suggested code.

write a function to seed a random number generator

Asking Copilot to write function to seed a random number generator

  1. Copilot has probably generated code using the rand.Seed function. The challenge is that as of Go 1.20, the Seed function is deprecated. Ref: https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/math/rand/rand.go;l=394

  2. Let's see if Copilot understands that this is deprecrated. We'll ask it via a query. Switch to the separate chat inferface and enter the query below.

Is the Seed function deprecated in Go?

Is Seed function deprecated?

  1. Copilot probably responded with no and some info about the function. So one way we can help Copilot understand language updates is by providing the context in our file. So let's start again. Delete the current content in the explore.go file.

  2. Now,let's provide Copilot some more direct context by copying in updated code examples. After deleting the code block from step 3, copy and paste in the following example of the replacement for the Seed deprecation into your explore.go file. This is taken from pkg.go.dev/math/rand.

	// Create and seed the generator.
	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
	// Using a fixed seed will produce the same output on every run.
	// r := rand.New(rand.NewSource(99))
  1. Now, let's try the creation of the function again. Underneath the comments and code you just pasted, invoke the dialog via CMD+I and enter the statement below again.
write a function to seed a random number generator
  1. This time, the code should be using the same format and NewSource function as you put in the file in step 6. You can just Accept the change. (If you don't see a complete function, but just a single line, try changing the prompt to be "write a complete function to seed a random number generator".

Updated random number gen code after including updated usage

**[END OF LAB]**

Lab 7 - Kubernetes, YAML generation and the 2021 problem

Purpose: Show YAML generation and out of date content.

  1. Create a new file - deployment.yaml
code deployment.yaml
  1. Bring up the Copilot Chat dialog via CMD+I and enter in the following request.
write spec for deployment in Kubernetes with 2 replicas and image from busybox
add command to run in containers: sleep 3600
add label app: myapp
add label type: front-end
  1. After a few moments, you should see it respond with the code. You can just Accept this. Kubernetes manifest

  2. Suppose we don't know how to execute this code. Let's ask Copilot. Highlight the generated YAML in the deployment.yaml file. Then go to the larger Chat interface and ask it. Put the following in the Chat interface.

How do I execute this?
  1. Copilot should respond with something like the following:

How to execute deployment

  1. While we're in the Chat interface, let's ask it for the latest K8s version. Put the following into the dialog.
what is the latest Kubernetes version?
  1. Notice that it identifies the latest version as 1.22 as of September 2021. This highlights the out-of-date issue with the LLM.

Answer to latest K8s version

  1. Let's have Copilot generate some code to work with Kubernetes through the API. In the chat interface, enter the following.
How do I call the K8s API for scaling a deployment to 5 replicas with Python?
  1. The results may tell us that we first need to make sure something like PIP is installed. If so, we don't need to worry about this at the moment. Go to the actual generated code in the chat output. Click in that output area and paste the code into a new file via clicking on the "..." and then the Insert into new file menu option.

Add code to new file

  1. Suppose we change our mind and want to convert this code to Go. Click in the new file, and highlight the new code. Then, in the Chat interface tell it to translate to Go. Then, look in the separate chat output and you should see the equivalent Go code available.
translate to Go 

Go translation

**[END OF LAB]**

Lab 8 - Exploring JavaScript, regular expression generation, and auto-generating data

Purpose: Show Javascript and regular expression generation, auto-generate routine mappings

  1. Create a new file as phone.js
code phone.js
  1. Prompt Copilot to create a function with a regular expression to validate a US phone number. You can use the CMD+I interface and just Accept the results.
create a function to validate any global phone number using a regular expression

Regex function to validate phone #

  1. Let's tell it to document the function by highlighting the code, invoking CMD+I and /doc. You can just Accept the results.

Automatic doc of function

  1. Now let's see how Copilot can generate some data and mappings for us automatically. Enter the prompt below in the main/separate chat text entry area.
create a mapping of all 50 states to area codes where
the key is the state abbreviation and the value
 is an array of area codes with max 10
  1. After running this, Copilot will generate the start of a list as shown below. Hover over the output area and click to insert the updates at the cursor in the phone.js file. (This assumes the cursor is below the previous function in the file.)

Automatic gen of data

  1. Notice that the example mapping was only for the first few states. We want to get the remaining mappings for the other states. Let's craft a prompt to complete the sequence. Enter the following in the main Copilot Chat entry box and then execute it.
create a mapping of the remaining states to area codes where
the key is the state abbreviation and the value
 is an array of area codes with max 10

Completing the mappings

  1. It is likely that the generated text in the chat is still not complete. If that's the case, we may need to find a way to narrow the amount of data that's returned back in one instance by Copilot. Let's try a prompt that limits the max values returned to 5.
create a complete mapping of all 50 states to area codes where
the key is the state abbreviation and the value
 is an array of area codes with max 5

Better prompt for remaining mappings

  1. You can scroll to the bottom to confirm if you got entries for all the states. If you didn't, you could create additional prompts for specific ranges of states, change the number of values downward, etc. You could then copy these into your file if you want. Notice also the disclaimer at the bottom of the output that these may not be actual values.

Disclaimer on actual values

**[END OF LAB]**

Lab 9 - Agents

Purpose: In this lab, we'll see how to work with GitHub Copilot agents.

  1. Now let's see how Copilot can help with tasks using agents. First, we'll have Copilot help us commit a change. Let's use the explore.go file we created in Lab 6. If you haven't already, make sure that file is saved. You can do this by:
  • Select the explore.go file
  • Click on the three-line menu in the top left.
  • From the menu that comes up, select File and then select Save (or use the shortcut).

Save file

  1. Now, let's invoke the @terminal agent to ask a common question about how to stage your code changes. Go to the chat interface and enter the prompt below. Afterwards, the command to do the staging should show up in the chat output.
@terminal how do I stage explore.go?

query output

  1. Hover over the window with the commands in it, and then click on the icon that pops up for the terminal. Click on that to insert the command into the terminal. Then hit return.

insert into terminal

  1. Now let's commit our change through the interface and have Copilot suggest a commit message for us. Click on the source control icon in the sidebar (#1 in the figure below). Your explore.go file should be selected. In the box titled "Message" above the Commit bar, click on the sparkle icon at the far right side (#2 in the figure below).

insert into terminal

  1. After this, Copilot should (hopefully) generate an appropriate commit message in that box. You can then copy the message and paste it into a git commit command in the terminal. If you started your codespace from a fork, you can hit return to complete the commit if you want. This is optional. If you started your codespace via the one-click button, you will not have permissions to commit.
git commit -m "<contents of generated commit message from Copilot goes here>"

commit with generated message

  1. Now, let's switch gears and use the @workspace agent to help identify where we use certain things in our code. With the explore.go file still active in your editor, in the separate chat interface , enter the following prompt:
Which files are using SQL?
  1. After executing this, you'll likely have some suggested information on how to search for files that use SQL in your project with search functionality for Visual Studio Code.

initial query response

  1. This is not the kind of answer we were looking for. Let's repeat the query with the @workspace agent.
@workspace Which files are using SQL?
  1. After executing this, you should see Copilot assessing all of the files in the workspace and then returning a more specific and expected answer.

more specific response

**[END OF LAB]**

Lab 10 - Copilot CLI

Purpose: In this lab, we'll finish up with Copilot by using the CLI.

  1. Finally, let's work with the Copilot command line interface. The codespace already has the GitHub CLI installed, so we just need to install the Copilot extension and authenticate. Enter the following in the terminal.
gh extension install github/gh-copilot
  1. After this, you can invoke the copilot command line to see the options available.
gh copilot

Copilot CLI help

  1. To authenticate, use the command below in the terminal.
gh auth login --web
  1. Follow the prompts. You'll get a one-time activation code that you should copy and then paste in the browser when prompted. (If you happen to get a message about an issue with GITHUB_TOKEN, you can use the command export GITHUB_TOKEN= to clear that.) You'll need to click on the "Authorize GitHub" button on the next screen and then confirm your signin after this to complete the process.
export GITHUB_TOKEN=

Copilot CLI auth

  1. Once you have authenticate, you can try a couple of gh copilot commands like the ones below to see an example of how the CLI works.
gh copilot explain "ps -aux"
gh copilot suggest "install terraform"

**[END OF LAB]**

**THANKS!**