--- name: pre-commit-checks description: Pre-commit validation checks for azure-sdk-for-net. Use this before committing or pushing changes to SDK packages. Runs dotnet format, exports public API listings, updates snippets, and regenerates code as needed. --- # Pre-Commit Validation Checks Run these checks after making changes to SDK packages under `sdk/` and **before** staging, committing, or pushing. These steps may produce additional file changes that must be included in the commit. > **General rule:** Steps 3–5 are conditional to save time, but if you are unsure whether a step is needed, **always run it**. It is better to run an unnecessary script than to miss a required regeneration. ## 1. Determine scope from changed files - Derive the changed file list from `git status --porcelain` (or by combining `git diff --name-only HEAD` with `git ls-files -o --exclude-standard`) so that **untracked (new) files are included**. - From the changed file list, extract **all unique ServiceDirectories** — the first path segment after `sdk/` (e.g., `sdk/storage/...` → `storage`, `sdk/ai/...` → `ai`). - For each ServiceDirectory, identify **all affected packages** = distinct `sdk/{ServiceDirectory}/{PackageName}/` paths. - For each affected package, identify: - **All csproj files** that had changes beneath them (src, tests, samples, perf, stress, or any other project type). - **The src csproj** specifically = `sdk/{service}/{package}/src/{Package}.csproj` — this is used for GenerateCode. - The remaining steps must be run **for each affected project/ServiceDirectory**. If changes span multiple ServiceDirectories or packages, run for each one. ## 2. Run `dotnet format` (for every changed csproj) For **every** csproj that had files change beneath it — src, tests, samples, perf, stress, or any other project type — run: ```shell dotnet format ``` Identify affected csproj files by looking at the full changed file list: include any project where either (a) there is a changed `.cs` file with that `.csproj` as its nearest parent, or (b) the `.csproj` itself changed, or files such as `.props`, `.targets`, or `.md` changed under that project. This fixes style/formatting issues and may modify `.cs` files. ## 3. Conditionally run `dotnet build /t:GenerateCode` (per src csproj) **Exclusion:** Skip this step entirely for the `provisioning` service directory. Provisioning libraries use their own generator and are not generated via TypeSpec/AutoRest. **Trigger condition — for each affected package's src csproj:** Run this if ANY of the following files are in the changed file list: - Any file matching `sdk/{service}/{package}/src/Generated/**` - `sdk/{service}/{package}/tsp-location.yaml` - `sdk/{service}/{package}/src/autorest.md` - Any `.cs` file under `sdk/{service}/{package}/src/` where a `CodeGen*` attribute was added, removed, or modified (e.g., `CodeGenType`, `CodeGenModel`, `CodeGenClient`, `CodeGenMember`, `CodeGenSuppress`, `CodeGenSerialization`, `CodeGenVisibility`). These attributes in custom (non-generated) code influence the generated output. **Important:** Do not manually edit files under `src/Generated/`. Changes to generated code should only come from running the `GenerateCode` target. **Command:** ```shell dotnet build sdk/{service}/{package}/src/{Package}.csproj /t:GenerateCode ``` This regenerates code from TypeSpec/AutoRest specs. It may modify files under `src/Generated/`. ## 4. Conditionally run `Export-API.ps1` (per ServiceDirectory) **Trigger condition — per ServiceDirectory:** Run this if ANY of the following are true for ANY affected package within this ServiceDirectory: - Step 3 above ran for any package in this ServiceDirectory (generated code may affect public API). - Changed `.cs` files under `sdk/{service}/{package}/src/` for any package in this ServiceDirectory contain public API surface changes. To determine this, inspect the diffs for: - New, removed, or renamed `public` or `protected` types (`class`, `interface`, `struct`, `enum`, `record`). - New, removed, or changed signatures of `public` or `protected` members (methods, properties, constructors, events, fields). - Visibility changes (e.g., `internal` → `public`). - Changes to base classes or implemented interfaces on public types. - New `.cs` files under `src/` that contain `public` types. **Skip Export-API if** changes are limited to: - Method body implementations (no signature changes). - `internal` or `private` members only. - XML doc comments or code comments. - `.csproj` configuration changes. **Command:** ```shell eng\scripts\Export-API.ps1 {ServiceDirectory} ``` This regenerates API listing files under `sdk/{service}/{package}/api/*.cs`. Uses `dotnet build /t:ExportApi` internally. Note: Export-API operates at the ServiceDirectory level (not per-csproj), so run it once per affected ServiceDirectory. ## 5. Conditionally run `Update-Snippets.ps1` (per ServiceDirectory) **Trigger condition — for each affected ServiceDirectory:** Run this if ANY of the following are true: - Changed `*.md` files under `sdk/{service}/` contain snippet references (`` ```C# Snippet: `` markers). - Changed `.cs` files contain snippet regions (`#region Snippet:`). **Command:** ```shell eng\scripts\Update-Snippets.ps1 {ServiceDirectory} ``` Note: Update-Snippets operates at the ServiceDirectory level (not per-csproj), so run it once per affected ServiceDirectory. This runs `snippet-generator` to sync code snippets into markdown files. May modify `*.md` and `*.cs` files. ## 6. Verify and include all changes - After running all applicable steps for all affected projects and ServiceDirectories, check for new/modified files with `git status`. - All changes produced by these steps must be included in the commit. - Do NOT commit if any of the above steps failed. ## Execution order Run the following steps in this order, respecting their scope (per package vs per ServiceDirectory): 1. **`dotnet format`** first — run on all changed csproj files (src, tests, etc.) for each affected package. 2. **`GenerateCode`** second — per src csproj, regenerates from specs (may override format changes in Generated/) for each affected package. 3. **`Export-API`** third — run once per affected ServiceDirectory, after all GenerateCode runs for packages in that ServiceDirectory are complete; captures the final public API surface after generation. 4. **`Update-Snippets`** fourth — run once per affected ServiceDirectory, after Export-API; captures any snippet changes from all prior steps. When multiple packages/ServiceDirectories are affected, run steps 1–2 for each affected package, then steps 3–4 once per affected ServiceDirectory. Step 6 (verify) runs once at the end.