diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..514ebd5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,94 @@ +# .NET Repository + +**Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.** + +## Working Effectively + +### Essential Build Commands +- **Restore dependencies**: `dotnet restore` + +- **Build the entire solution**: `dotnet build` + +- **Run tests**: `dnx --yes retest` + - Runs all unit tests across the solution + - If tests fail due to Azure Storage, run the following commands and retry: `npm install azurite` and `npx azurite &` + +### Build Validation and CI Requirements +- **Always run before committing**: + * `dnx --yes retest` + * `dotnet format whitespace -v:diag --exclude ~/.nuget` + * `dotnet format style -v:diag --exclude ~/.nuget` + +### Project Structure and Navigation + +| Directory | Description | +|-----------|-------------| +| `src/` | Contains the repo source code. | +| `bin/` | Contains built packages (if any) | + +### Code Style and Formatting + +#### EditorConfig Rules +The repository uses `.editorconfig` at the repo root for consistent code style. + +- **Indentation**: 4 spaces for C# files, 2 spaces for XML/YAML/JSON +- **Line endings**: LF (Unix-style) +- **Sort using directives**: System.* namespaces first (`dotnet_sort_system_directives_first = true`) +- **Type references**: Prefer language keywords over framework type names (`int` vs `Int32`) +- **Modern C# features**: Use object/collection initializers, coalesce expressions when possible, use var when the type is apparent from the right-hand side of the assignment +- **Visibility modifiers**: only explicitly specify visibility when different from the default (e.g. `public` for classes, no `internal` for classes or `private` for fields, etc.) + +#### Formatting Validation +- CI enforces formatting with `dotnet format whitespace` and `dotnet format style` +- Run locally: `dotnet format whitespace --verify-no-changes -v:diag --exclude ~/.nuget` +- Fix formatting: `dotnet format` (without `--verify-no-changes`) + +### Testing Practices + +#### Test Framework +- **xUnit** for all unit and integration tests +- **Moq** for mocking dependencies +- Located in `src/*.Tests/` + +#### Test Attributes +Custom xUnit attributes are sometimes used for conditional test execution: +- `[SecretsFact("XAI_API_KEY")]` - Skips test if required secrets are missing from user secrets or environment variables +- `[LocalFact("SECRET")]` - Runs only locally (skips in CI), requires specified secrets +- `[CIFact]` - Runs only in CI environment + +### Dependency Management + +#### Adding Dependencies +- Add to appropriate `.csproj` file +- Run `dotnet restore` to update dependencies +- Ensure version consistency across projects where applicable + +#### CI/CD Pipeline +- **Build workflow**: `.github/workflows/build.yml` - runs on PR and push to main/rel/feature branches +- **Publish workflow**: Publishes to Sleet feed when `SLEET_CONNECTION` secret is available +- **OS matrix**: Configured in `.github/workflows/os-matrix.json` (defaults to ubuntu-latest) + +### Special Files and Tools + +#### dnx Command +- **Purpose**: built-in tool for running arbitrary dotnet tools that are published on nuget.org. `--yes` auto-confirms install before run. +- **Example**: `dnx --yes retest` - runs tests with automatic retry on transient failures (retest being a tool package published at https://www.nuget.org/packages/retest) +- **In CI**: `dnx --yes retest -- --no-build` (skips build, runs tests only) + +#### Directory.Build.rsp +- MSBuild response file with default build arguments +- `-nr:false` - disables node reuse +- `-m:1` - single-threaded build (for stability) +- `-v:m` - minimal verbosity + +#### Code Quality +- All PRs must pass format validation +- Tests must pass on all target frameworks +- Follow existing patterns and conventions in the codebase + +## Documenting Work + +Project implemention details, design and key decisions should be documented in a top-level AGENTS.md file at the repo root. +Keep this file updated whenever you make change significant changes for future reference. + +User-facing features and APIs should be documented to highlight (not extensively, as an overview) key project features and capabilities, in the readme.md file at the repo root. diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 56ff299..99eec76 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -49,7 +49,11 @@ jobs: # if we don't have at least 100 requests left, wait until reset if ($rate.remaining -lt 100) { $wait = ($rate.reset - (Get-Date (Get-Date).ToUniversalTime() -UFormat %s)) - echo "Rate limit remaining is $($rate.remaining), waiting for $($wait / 1000) seconds to reset" + if ($wait -gt 300) { + echo "Rate limit remaining is $($rate.remaining), reset in $wait seconds (more than 5'). Aborting." + exit 1 + } + echo "Rate limit remaining is $($rate.remaining), waiting $wait seconds to reset" sleep $wait $rate = gh api rate_limit | convertfrom-json | select -expandproperty rate echo "Rate limit has reset to $($rate.remaining) requests" diff --git a/.netconfig b/.netconfig index cb40687..3bfc328 100644 --- a/.netconfig +++ b/.netconfig @@ -81,12 +81,12 @@ sha = 0683ee777d7d878d4bf013d7deea352685135a05 [file "src/Directory.Build.props"] url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.props - etag = bca64456d4e2cd05375a72b6de376b2c51edf6ad49029aa9a729f4a349a54656 + etag = bd05f9f240823c0ac79ddfefe654061550c36f82dd94fa513b82900e92686a5f weak sha = 4b84c540df6f37c30fb38df7947d79871c34f036 [file "src/Directory.Build.targets"] url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.targets - etag = 09ce6b3f9521f8eedc44b77e7b7eaf90bf5df36e1ffb7f78ca27658812180977 + etag = 907682e5632a2ba430357e6e042a4ca33cb8c94a3a215d3091aa03f5958a4877 weak sha = 4b84c540df6f37c30fb38df7947d79871c34f036 [file "src/kzu.snk"] @@ -130,7 +130,7 @@ [file ".github/workflows/triage.yml"] url = https://github.com/devlooped/oss/blob/main/.github/workflows/triage.yml sha = 33000c0c4ab4eb4e0e142fa54515b811a189d55c - etag = 013a47739e348f06891f37c45164478cca149854e6cd5c5158e6f073f852b61a + etag = 152cd3a559c08da14d1da12a5262ba1d2e0ed6bed6d2eabf5bd209b0c35d8a75 weak [file ".github/workflows/dotnet-file-core.yml"] url = https://github.com/devlooped/oss/blob/main/.github/workflows/dotnet-file-core.yml @@ -156,3 +156,7 @@ [file "oss.cs"] url = https://github.com/devlooped/oss/blob/main/oss.cs skip +[file ".github/copilot-instructions.md"] + url = https://github.com/devlooped/oss/blob/main/.github/copilot-instructions.md + etag = 6ee650d118a57494d3545d54718ccaa5257b09d54504e9c21514fe596edd9678 + weak diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e0b14f6..91e383a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -167,7 +167,7 @@ - + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 42998e0..a3df56d 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -174,7 +174,7 @@ @@ -184,15 +184,16 @@ - - - + + + OSMFEULA.txt true +