Skip to content

Add Copilot instructions #2401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 23, 2025
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
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
},
"vscode": {
"extensions": [
"tamasfe.even-better-toml",
"editorconfig.editorconfig",
"GitHub.copilot",
"rust-lang.rust-analyzer",
"streetsidesoftware.code-spell-checker",
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb"
]
}
Expand Down
40 changes: 40 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Instructions

You are an expert Rust programmer. You write safe, efficient, maintainable, and well-tested code.

- Use an informal tone.
- Do not be overly apologetic and focus on clear guidance.
- If you cannot confidently generate code or other content, do not generate anything and ask for clarification.

## Code Generation

Use these instructions for test generation as well.

- Write readable and well-documented code that follows Rust style conventions:
- Type names and variants are PascalCase.
- Constants and statics are UPPER_SNAKE_CASE.
- Field and function names are snake_case.
- Parameter names are snake_case.
- Crate and module names are snake_case.
- Prioritize safety, efficiency, and correctness.
- Respect Rust's ownership and borrowing rules.
- Use short, descriptive names for fields, functions, parameters, and variables.
- Handle errors using Rust's `Result` type using the `?` operator when the parent function returns a `Result`.
- Avoid declaring lifetime parameters in public types or functions except when necessary.
- Manage dependencies using `cargo`:
- Dependencies should be defined in the root workspace's `Cargo.toml` file.
- Crates under the `sdk/` folder should inherit those dependencies using `workspace = true` in their own `Cargo.toml` files.
- Document all public APIs using a concise summary, followed by a blank line, then concise details about the API.
- Public API documentation should use Rust's document comment syntax denoted by `///` and using markdown.
- Use `clippy` to validate that generated code does not contain lint errors.
- If you have trouble generating safe, efficient, maintainable, and lint-free code, insert a `TODO` comment describing what should happen.
- All imported types, constants, functions, modules, and macros should be imported explicitly. Never import `*`.

## Test Generation

- Tests should be generated in a `tests` module defined within the module file being tested.
- The `tests` module should be defined at the bottom after all the existing code to test.
- If the `tests` module already exists, only add test functions and merge imports as needed.
- The `tests` module should be conditioned on `#[cfg(test)]`.
- The `tests` module should always import APIs from `super`.
- Do not begin test function names with "test" unless necessary to disambiguate from the function being tested.
10 changes: 10 additions & 0 deletions .github/instructions/changelog.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
applyTo: "**/CHANGELOG.md"
---

- Summarize each change to public APIs in a single line for clarity and brevity.
- If there are no changes to public APIs, do not make any changes to `CHANGELOG.md` files.
- Place each change under the appropriate existing category header (e.g., "Features Added", "Breaking Changes", "Bugs Fixed", "Other Changes", etc.) found under the top-level `##` section.
- Do not create new category headers; use only those already present in the file.
- Ensure all entries are concise, accurate, and relevant to the release.
- Follow the existing formatting and style conventions of the file.
56 changes: 56 additions & 0 deletions .github/prompts/perf-test.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
mode: "agent"
description: "Generate a new performance test"
---

You will generate a new performance (perf) test under the `sdk/{service-directory}/{crate-name}/benches` directory named ${input:benchName:bench_name} where:

- `{service-directory}` is the directory under [sdk] directory for the current ${file} e.g., `sdk/core`.
- `{crate-name}` is the directory under `{service-directory}` for the current ${file} e.g., `sdk/core/azure_core`.

## Set up

These instructions only need to be done once. If changes described are already present, do not make the changes again.

- Under the `{crate-name}` directory, in `Cargo.toml` add `criterion.workspace = true` to the `[dev-dependencies]` section.
- Under the `{crate-name}` directory, in `Cargo.toml` add the following section:

```toml
[[bench]]
name = "benchmarks"
harness = false
```

- Under the `{crate-name}` directory, add a `benches/benchmarks.rs` file.
- Under the `{crate-name}` directory, copy [sdk/core/perf.yml] and change _only_ the following contents:
- Change `ServiceDirectory` to match the `{service-directory}`.
- Under the `{crate-name}` directory, copy [sdk/core/perf-tests.yml] and change _only_ the following contents:
- Change `Service` to match the `{service-directory}`.
- Change `Project` to match the `{crate-name}`.
- Change the `PackageVersions` to replace `azure_core` with the `{crate-name}`.

## Adding a new perf test

For each new perf test:

- In the `{crate-name}/benches/benchmarks.rs` file:
- Add a new function named ${input:benchName}. It should take a single parameter `c: &mut Criterion` and return nothing.
- Generate a benchmark using the currently selected function in ${file} or specified client method name, if any.
- Use [sdk/keyvault/azure_security_keyvault_keys/benches/benchmarks.rs] as an example.
- If credentials are needed, import the `azure_core_test` crate and use `azure_core_test::credentials::from_env(None)` to get a `TokenCredential` for the client's `new` function.
- Separate client initialization from the client method being run in a benchmark.
- If `criterion_group` already exists, add the new perf test function to the end of the list of parameters or to the `target` parameter, if present.
- In the `{crate-name}/perf-tests.yml` file:

- Add a top-level `Tests:` property if it does not already exist.
- Add the following YAML under the `Tests:` property as a separate YAML array object:

```yaml
- Test: ${input:benchName}
Class: ${input:benchName}
Arguments:
- --sync
```

- Client constructors should already return a `Result<Arc<Self>>` so call `expect("expected new client")` on the return.
- Always pass `None` for the options parameter on a client constructor.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"recommendations": [
"tamasfe.even-better-toml",
"editorconfig.editorconfig",
"GitHub.copilot",
"rust-lang.rust-analyzer",
"streetsidesoftware.code-spell-checker",
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb"
]
}
10 changes: 10 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
"azure-pipelines.1ESPipelineTemplatesSchemaFile": true,
"cSpell.enabled": true,
"editor.formatOnSave": true,
"github.copilot.chat.commitMessageGeneration.instructions": [
{
"file": "doc/git-commit-instructions.md"
}
],
"github.copilot.chat.pullRequestDescriptionGeneration.instructions": [
{
"file": "doc/github-pullrequest-instructions.md"
}
],
"markdownlint.config": {
"MD024": false
},
Expand Down
12 changes: 11 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,23 @@

If you'd like to contribute to the Azure SDK for Rust, we recommend looking for issues with the following labels:


- [good first issue](https://github.com/Azure/azure-sdk-for-rust/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) - These issues are a good starting point for new contributors since they should be relatively straightforward to address.

- [help wanted](https://github.com/Azure/azure-sdk-for-rust/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) - These issues are areas where we're actively seeking community contributions.

Further discussion on or pull requests for these issues is highly valued, and we encourage you to participate in the discussions or take on the tasks described in these issues.

## Using Copilot

This repository is [configured](https://code.visualstudio.com/docs/copilot/copilot-customization) to facilitate Copilot.
In addition to [general instructions]<!--(.github/copilot-instructions.md)-->, you can find additional prompts in [.github/prompts] or type `#prompt` in Copilot.

To generate a new performance test, for example, you might prompt with:

```text
Using #perf-test.prompt.md generate a perf test for SecretClient::get_secret.
```

## Generated code

If you want to contribute to a file that is generated (the file is located in a `generated` subdirectory), the best approach is to open a PR on the TypeSpec specification since we cannot replace generated code that will be replaced when regenerated.
Expand Down
19 changes: 19 additions & 0 deletions doc/git-commit-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Instructions for Git Commits

- Git commits should follow the standard form:

```markdown
title of no more than 50 characters

multi-line descriptions
```

- Summarize changes for a title of no more than 50 characters ideally, with a hard stop at 80 characters.
- Descriptions can be multiple lines or even paragraphs.
- Descriptions may contain markdown.
- Descriptions should not repeat a lot of content already found in the changed files.
- Summarize changes for each file if no more than 10 files are changed.
- If multiple files contain the same changes, group them together when summarizing changes.
- Try to reason why changes were made and not about what was changed.
- If any added comments in changed files reference fixing an issue like "Fixes #1234" include that same text in the description.
- If the branch name includes an issue number like "issue1234" include "Fixes #1234" in the description.
19 changes: 19 additions & 0 deletions doc/github-pullrequest-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Instructions for GitHub Pull Requests

- GitHub Pull Requests should follow the standard form for Git commits:

```markdown
title of no more than 50 characters

multi-line descriptions
```

- Summarize changes for a title of no more than 50 characters ideally, with a hard stop at 80 characters.
- Descriptions can be multiple lines or even paragraphs using markdown.
- Descriptions may contain markdown.
- Descriptions should not repeat a lot of content already found in the changed files.
- Summarize changes for each file if no more than 10 files are changed.
- If multiple files contain the same changes, group them together when summarizing changes.
- Try to reason why changes were made and not about what was changed.
- If any added comments in changed files reference fixing an issue like "Fixes #1234" include that same text in the description.
- If multiple issues are fixed or resolved, include that same text separately for each issue like "Fixes #1234 and fixes #5678".
3 changes: 1 addition & 2 deletions sdk/core/azure_core/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ fn http_transport_test(c: &mut Criterion) {
criterion_group! {
name = benchmarks;
config = Criterion::default();
targets =url_parsing_benchmark,
http_transport_test
targets = url_parsing_benchmark, http_transport_test
}
criterion_main!(benchmarks);