|
| 1 | +# GitHub Copilot Instructions for azure-openapi-validator |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +This is `azure-openapi-validator` (aka `LintDiff`), a linter for Azure OpenAPI specifications. It is an extension of AutoRest and supports Spectral lint rule format. The repository contains automated linter rules that apply to API specs in the azure-rest-api-specs repository. |
| 6 | + |
| 7 | +## Architecture |
| 8 | + |
| 9 | +This is a monorepo managed by Rush.js with the following main packages: |
| 10 | + |
| 11 | +- `packages/azure-openapi-validator/core` - Core functionality (`@microsoft.azure/openapi-validator-core`) |
| 12 | +- `packages/azure-openapi-validator/autorest` - AutoRest extension (`@microsoft.azure/openapi-validator`) |
| 13 | +- `packages/rulesets` - Ruleset implementations (`@microsoft.azure/openapi-validator-rulesets`) |
| 14 | + - `src/spectral/` - Spectral format rules |
| 15 | + - `src/native/` - Native TypeScript rules |
| 16 | +- `regression` - Regression tests |
| 17 | + |
| 18 | +## Build and Test Commands |
| 19 | + |
| 20 | +### Prerequisites |
| 21 | +- Node.js >= 18.0.0 (some packages like rulesets require >= 20) |
| 22 | +- Rush.js (`npm install -g @microsoft/rush`) |
| 23 | + |
| 24 | +### Essential Commands |
| 25 | + |
| 26 | +**Build:** |
| 27 | +```bash |
| 28 | +rush update # Install dependencies |
| 29 | +rush build # Build all projects |
| 30 | +``` |
| 31 | + |
| 32 | +**Test:** |
| 33 | +```bash |
| 34 | +rush test # Run all tests |
| 35 | +npx jest --config packages/rulesets/jest.native.config.js # Native tests only (in packages/rulesets) |
| 36 | +npx jest --config packages/rulesets/jest.config.js # Spectral tests only (in packages/rulesets) |
| 37 | +``` |
| 38 | + |
| 39 | +**Lint:** |
| 40 | +```bash |
| 41 | +rush lint # Run linter on all projects |
| 42 | +rush lint:fix # Auto-fix linting issues |
| 43 | +``` |
| 44 | + |
| 45 | +**Other:** |
| 46 | +```bash |
| 47 | +rush prep # Complete pre-PR workflow: update, build, lint, test, regen-ruleindex, change |
| 48 | +rush regen-ruleindex # Regenerate docs/rules.md after rule changes |
| 49 | +rush change # Generate Rush changelog entries |
| 50 | +rush regression-test # Run regression tests |
| 51 | +``` |
| 52 | + |
| 53 | +## Development Workflow |
| 54 | + |
| 55 | +### Before Submitting a PR |
| 56 | +1. Ensure branch is based on up-to-date `main` |
| 57 | +2. Run `rush prep` - this will execute all necessary checks |
| 58 | +3. If adding/modifying rules, run `rush regen-ruleindex` to update `docs/rules.md` |
| 59 | +4. Run `rush change` and follow prompts to generate changelog entries |
| 60 | +5. For significant changes, manually update `changelog.md` |
| 61 | + |
| 62 | +### Adding New Linter Rules |
| 63 | +1. Add the new rule with appropriate severity and documentation |
| 64 | +2. Add a label to your PR in the format `test-<RuleName>` to trigger the staging-lint check pipeline |
| 65 | +3. Verify the rule works correctly by checking the staging-lint check results |
| 66 | +4. Iterate on the rule based on validation results until it works as expected |
| 67 | +5. Once the PR is merged, the rule is automatically deployed and released |
| 68 | + |
| 69 | +## Coding Conventions |
| 70 | + |
| 71 | +### TypeScript |
| 72 | +- Target: ES2019 |
| 73 | +- Module: CommonJS |
| 74 | +- Strict null checks enabled |
| 75 | +- No implicit any |
| 76 | +- Import helpers from tslib (set `noEmitHelpers: true`, `importHelpers: true`) |
| 77 | + |
| 78 | +### Code Style |
| 79 | +- **Prettier** configured as auto-formatter |
| 80 | + - No semicolons (`semi: false`) |
| 81 | + - Print width: 140 characters |
| 82 | +- **ESLint** enforced - all projects must pass `rush lint` with `--max-warnings=0` |
| 83 | +- Use existing libraries when possible |
| 84 | +- Prefer clear, descriptive variable names |
| 85 | + |
| 86 | +### Null Safety Pattern |
| 87 | +**Important:** After calling `Workspace.resolveRef()`, always check both `!source` and `!source.value` since the function's return type is `EnhancedSchema | undefined`, and the value property can be undefined when the $ref target doesn't exist. |
| 88 | + |
| 89 | +Example: |
| 90 | +```typescript |
| 91 | +const source = Workspace.resolveRef(enhancedSchema, inventory) |
| 92 | +if (!source || !source.value) { |
| 93 | + // Handle undefined case |
| 94 | + return |
| 95 | +} |
| 96 | +// Safe to use source.value |
| 97 | +``` |
| 98 | + |
| 99 | +### Rule Properties |
| 100 | +When writing validation rules: |
| 101 | +- Provide clear error messages |
| 102 | +- Include documentation links |
| 103 | +- Set appropriate severity (error/warning/info) |
| 104 | +- Follow existing rule patterns in `packages/rulesets/src/` |
| 105 | + |
| 106 | +## Testing |
| 107 | + |
| 108 | +- Jest is used for testing |
| 109 | +- Spectral tests are in `packages/rulesets/src/spectral/test/` |
| 110 | +- Native tests are in `packages/rulesets/src/native/tests/` and match `*-test(s).ts` |
| 111 | +- Coverage threshold: ≥80% statement coverage for `src/spectral/functions/*.ts` |
| 112 | +- Native tests use `jest.native.config.js` |
| 113 | +- Spectral tests use `jest.config.js` |
| 114 | + |
| 115 | +## Common Tasks |
| 116 | + |
| 117 | +### Testing Rules with Staging-Lint Check |
| 118 | +The `.github/workflows/staging-lint-checks.yaml` workflow allows you to test specific rules: |
| 119 | +- Add a label to your PR in format `test-<RuleName>` (e.g., `test-ProvisioningStateSpecifiedForLROPut`) |
| 120 | +- You can also specify rules in the PR body: `rules: RuleName1, RuleName2` |
| 121 | +- The workflow runs selected rules against a subset of Azure REST API specs |
| 122 | +- Check the workflow results and linter-findings artifact to validate rule behavior |
| 123 | + |
| 124 | +### Running Locally from Source |
| 125 | +See CONTRIBUTING.md section "How to run LintDiff locally from source" |
| 126 | + |
| 127 | +### Setting Rule to Staging Only (Legacy) |
| 128 | +The `stagingOnly: true` property in Spectral rules still exists but the deployment process has evolved. For new rules, use the staging-lint check workflow (above) to validate before production deployment. See CONTRIBUTING.md section "How to set a Spectral rule to run only in staging" for details on the stagingOnly property. |
| 129 | + |
| 130 | +### Regenerating Rules Documentation |
| 131 | +```bash |
| 132 | +rush regen-ruleindex |
| 133 | +``` |
| 134 | +This updates `docs/rules.md` with the current rules index. |
| 135 | + |
| 136 | +### Reproducing LintDiff Failures |
| 137 | +Follow instructions in CONTRIBUTING.md under "How to locally reproduce a LintDiff failure" |
| 138 | + |
| 139 | +## Important Files |
| 140 | + |
| 141 | +- `rush.json` - Monorepo configuration |
| 142 | +- `common/config/rush/command-line.json` - Custom Rush commands |
| 143 | +- `docs/rules.md` - Generated index of all rules (regenerate with `rush regen-ruleindex`) |
| 144 | +- `CONTRIBUTING.md` - Detailed contribution guidelines (41KB+) |
| 145 | +- `changelog.md` - Project changelog |
| 146 | + |
| 147 | +## Documentation |
| 148 | + |
| 149 | +All rules should have documentation in `docs/` directory. When adding a new rule, create a corresponding `.md` file in `docs/` with: |
| 150 | +- Rule description |
| 151 | +- Examples of violations |
| 152 | +- Examples of correct usage |
| 153 | +- Links to relevant Azure API guidelines |
| 154 | + |
| 155 | +## Dependencies |
| 156 | + |
| 157 | +- Rush.js uses pnpm (v8.15.7) as the underlying package manager (configured in rush.json) |
| 158 | +- Strict peer dependencies enabled |
| 159 | +- Node.js >= 18.0.0 supported by Rush (individual packages like rulesets may require >= 20) |
| 160 | + |
| 161 | +## Deployment |
| 162 | + |
| 163 | +Changes merge to `main` deploy to staging LintDiff. For production deployment: |
| 164 | +1. Create release PR with changelog |
| 165 | +2. Tag release |
| 166 | +3. Build and publish to npm |
| 167 | +4. Verify deployment using CloudMine/Kusto queries |
| 168 | + |
| 169 | +See CONTRIBUTING.md "How to deploy your changes" for detailed instructions. |
0 commit comments