Repository navigation
Add automated namespace approval workflow for spec PRs #44085
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
Mike Harder (mikeharder)
merged 24 commits into
Azure:main
from
samvaity:namespace-approval
Jul 8, 2026
Merged
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
3b59a3d
Add automated namespace approval workflow for spec PRs
samvaity 4f28a24
Address review feedback: unlabeled guard, remove C++/Rust
samvaity 37aa3d1
Add unit tests and namespace format validation
samvaity 67ed6c8
Address review: split workflow, use repo helpers, add zod schema
samvaity 01ea7c6
Fix CI: prettier formatting and cspell word
samvaity cf496ef
Fix: use sparse-checkout add instead of git checkout for hydration
samvaity c11675f
Parse tspconfig.yaml directly, add commit status gate, fix plane dete…
samvaity 1b9a3b6
Split status workflow into separate files following repo convention
samvaity 02ccf7e
Fix: deduplicate job name in code workflow to match repo convention
samvaity a55968c
Address review: add else fallback in status check, fix check name in …
samvaity bb3a30c
Add Namespace Approval to summarize-checks for Next Steps to Merge
samvaity 9dc65fd
Add Java Maven artifact dual namespace, selective reset, lint and typ…
samvaity 849da69
Fix namespace approval TS type errors
samvaity 843da16
Address review feedback: error handling, shared helpers, and cleanup
samvaity 9f03703
Fix CodeQL ReDoS alert: replace regex with string methods in tspconfi…
samvaity 759d377
Add coverage test for tspconfig filter in changed-files
samvaity 2a9c182
Fix namespace-approval TypeScript null and env typing errors
samvaity 7cead2e
Address review issues: shared approvers, pagination, async format, ti…
samvaity 93c8ba4
Prevent duplicate 'Namespace Approved' comments on concurrent label e…
samvaity 54ea1e9
Rename labels to namespace-<lang>-*, add @handles, integrate with NSTM
samvaity 05b0587
Extract shared labels helper, remove createLabel, clarify plane detec…
samvaity b430ea0
Fix NSTM: clarify namespace-approved-all is mgmt-plane only
samvaity c890e3e
changed-files helper cleanup
mikeharder 3a7483f
Merge branch 'main' into namespace-approval
mikeharder File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # cspell:words jsquire alzimmermsft xirzec kashifkhan maorleger jhendrixMSFT ArthurMa1978 | ||
| # Namespace Approvers Configuration | ||
| # This file defines who can approve namespace changes per language. | ||
| # To update, submit a PR to this file. In the future, this may be | ||
| # synced automatically from ARCHITECTS files in each language repo. | ||
|
|
||
| data-plane: | ||
| dotnet: | ||
| - jsquire | ||
| - m-nash | ||
| java: | ||
| - JonathanGiles | ||
| - alzimmermsft | ||
| python: | ||
| - xirzec | ||
| - kashifkhan | ||
| typescript: | ||
| - xirzec | ||
| - maorleger | ||
| go: | ||
| - jhendrixMSFT | ||
|
|
||
| management-plane: | ||
| all: | ||
| - ArthurMa1978 | ||
| - m-nash |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Namespace Format Rules | ||
| # These regex patterns validate namespace/package naming conventions per language. | ||
| # Namespaces that fail validation are flagged in the bot comment before manual review. | ||
| # | ||
| # To update: submit a PR modifying the patterns below. | ||
| # Each language can have one rule or multiple rules (array). | ||
| # Each rule has a `pattern` (regex) and optional `description`. | ||
| # | ||
| # Maintainer: @ArthurMa1978 | ||
|
|
||
| dotnet: | ||
| pattern: '^Azure\.ResourceManager\.(?:[A-Z][a-zA-Z0-9]*)(?:\.[A-Z][a-zA-Z0-9]*)?$' | ||
| description: "Azure.ResourceManager.{Name} or Azure.ResourceManager.{SuperService}.{Name} (PascalCase)" | ||
|
|
||
| java: | ||
| - pattern: "^azure-resourcemanager-[a-z0-9]+(?:-[a-z0-9]+)?$" | ||
| description: "Maven artifact: azure-resourcemanager-{name} (lowercase)" | ||
| - pattern: '^com\.azure\.resourcemanager\.[a-z0-9]+(?:\.[a-z0-9]+)?$' | ||
| description: "Java package: com.azure.resourcemanager.{name} (lowercase)" | ||
|
|
||
| go: | ||
| pattern: "^sdk/resourcemanager/(?:[a-z0-9]+)/(?:arm[a-z0-9]+)$" | ||
| description: "sdk/resourcemanager/{name}/arm{name} (lowercase)" | ||
|
|
||
| typescript: | ||
| pattern: "^@azure/arm-[a-z0-9]+$" | ||
| description: "@azure/arm-{name} (lowercase)" | ||
|
|
||
| python: | ||
| pattern: "^azure-mgmt-[a-z0-9]+$" | ||
| description: "azure-mgmt-{name} (lowercase)" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| name: "Namespace Approval - Analyze Code" | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: | ||
| - opened | ||
| - synchronize | ||
| - reopened | ||
| - edited | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| detect-namespaces: | ||
| name: "Namespace Approval - Analyze Code" | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| sparse-checkout: | | ||
| .github/ | ||
| fetch-depth: 2 | ||
|
|
||
| - name: Setup Node and install dependencies | ||
| uses: ./.github/actions/setup-node-install-deps | ||
|
|
||
| - name: Detect namespace changes | ||
| id: detect | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| script: | | ||
| const { default: detectNamespaces } = | ||
| await import('${{ github.workspace }}/.github/workflows/src/namespace-approval/detect-namespaces.js'); | ||
| await detectNamespaces({ github, context, core }); | ||
|
|
||
| - name: Upload namespace results | ||
| if: always() && steps.detect.outputs.results | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: namespace-results | ||
| path: ${{ steps.detect.outputs.results_path }} | ||
| if-no-files-found: ignore | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| name: "Namespace Approval - Set Status" | ||
|
|
||
| on: | ||
| pull_request_target: | ||
| types: | ||
| - labeled | ||
| - unlabeled | ||
| workflow_run: | ||
| workflows: ["Namespace Approval - Analyze Code"] | ||
| types: [completed] | ||
|
|
||
| permissions: | ||
| actions: read | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| post-results: | ||
| if: github.event_name == 'workflow_run' | ||
| name: Post Namespace Results | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| sparse-checkout: | | ||
| .github/ | ||
|
|
||
| - name: Setup Node and install dependencies | ||
| uses: ./.github/actions/setup-node-install-deps | ||
|
|
||
| - name: Install dependencies for github-script actions | ||
| uses: ./.github/actions/install-deps-github-script | ||
|
|
||
| - name: Post namespace review comment | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| script: | | ||
| const { default: postResults } = | ||
| await import('${{ github.workspace }}/.github/workflows/src/namespace-approval/post-results.js'); | ||
| await postResults({ github, context, core }); | ||
|
|
||
| validate-approval: | ||
| if: > | ||
| github.event_name == 'pull_request_target' && | ||
| (github.event.action == 'labeled' || github.event.action == 'unlabeled') | ||
| name: Validate Namespace Approval | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| sparse-checkout: | | ||
| .github/ | ||
|
|
||
| - name: Install dependencies for github-script actions | ||
| uses: ./.github/actions/install-deps-github-script | ||
|
|
||
| - name: Validate namespace approval label | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| script: | | ||
| const { default: validateApproval } = | ||
| await import('${{ github.workspace }}/.github/workflows/src/namespace-approval/validate-approval.js'); | ||
| await validateApproval({ github, context, core }); | ||
|
|
||
| status-check: | ||
| name: Namespace Approval Status | ||
| needs: [post-results, validate-approval] | ||
| if: always() | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| sparse-checkout: | | ||
| .github/ | ||
|
|
||
| - name: Install dependencies for github-script actions | ||
| uses: ./.github/actions/install-deps-github-script | ||
|
|
||
| - name: Verify namespace approval status | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| script: | | ||
| const { default: statusCheck } = | ||
| await import('${{ github.workspace }}/.github/workflows/src/namespace-approval/status-check.js'); | ||
| await statusCheck({ github, context, core }); |
99 changes: 99 additions & 0 deletions
99
.github/workflows/src/namespace-approval/NAMESPACE-REVIEW-PROCESS.md
|
mikeharder marked this conversation as resolved.
Resolved
samvaity marked this conversation as resolved.
Resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Namespace Approval Process | ||
|
|
||
| ## Overview | ||
|
|
||
| When a service team adds or modifies SDK namespace configuration in their `tspconfig.yaml`, the namespace must be approved by authorized architects before the spec PR can merge. | ||
|
samvaity marked this conversation as resolved.
Resolved
|
||
|
|
||
| This process is automated via GitHub Actions on this repository. | ||
|
|
||
| ## How It Works | ||
|
|
||
| ### Detection | ||
|
|
||
| When a PR modifies any `tspconfig.yaml` file, the analyze-code workflow: | ||
|
samvaity marked this conversation as resolved.
Resolved
|
||
|
|
||
| 1. Identifies which languages have namespace/package-name configuration | ||
| 2. Extracts namespaces using the `@azure-tools/typespec-metadata` emitter | ||
| 3. Determines if the service is data-plane or management-plane | ||
| 4. Uploads namespace results for the status workflow | ||
|
|
||
| ### Status + Approval | ||
|
|
||
| The status workflow posts the namespace review comment, applies `<lang>-namespace-pending` labels, and validates architect approval labels. | ||
|
|
||
| - **Data plane:** Each language architect approves their language by applying `<lang>-namespace-approved` | ||
| - **Management plane:** ArthurMa1978 or m-nash can apply `namespace-approved-all` to approve all languages at once | ||
|
|
||
| ### Status Check | ||
|
|
||
| A required status check (`namespace-approval`) blocks merge until all pending namespaces are approved. The check: | ||
|
samvaity marked this conversation as resolved.
Resolved
samvaity marked this conversation as resolved.
Resolved
|
||
|
|
||
| - ✅ Passes when all `*-namespace-pending` labels have corresponding `*-namespace-approved` labels | ||
|
samvaity marked this conversation as resolved.
Resolved
|
||
| - ❌ Fails when any pending namespace lacks approval | ||
| - ⏭️ Skipped when the PR doesn't modify tspconfig.yaml (no namespace changes) | ||
|
|
||
| ### Reset on Change | ||
|
|
||
| If a service team pushes a commit that changes namespace configuration, the approval for that language is reset: | ||
|
|
||
| - The `<lang>-namespace-approved` label is removed | ||
| - The `<lang>-namespace-pending` label is re-applied | ||
| - The status check fails again until re-approved | ||
|
|
||
| ## Labels | ||
|
|
||
| | Label | Applied by | Meaning | | ||
| | --------------------------- | ---------------- | ---------------------------------------- | | ||
| | `<lang>-namespace-pending` | Bot | Namespace detected, awaiting approval | | ||
| | `<lang>-namespace-approved` | Architect | Namespace approved for this language | | ||
| | `namespace-approved-all` | Architect (mgmt) | Shortcut: approves all pending languages | | ||
| | `Mgmt` | Bot | PR is management plane | | ||
|
samvaity marked this conversation as resolved.
Resolved
|
||
|
|
||
| Where `<lang>` is one of: `dotnet`, `java`, `python`, `typescript`, `go` | ||
|
|
||
| ## Authorized Approvers | ||
|
|
||
| Defined in [`.github/namespace-approvers.yml`](../../../namespace-approvers.yml): | ||
|
|
||
| <!-- cspell:disable --> | ||
|
|
||
| | Scope | Approvers | | ||
| | -------------------- | ------------------------------ | | ||
| | .NET | @jsquire, @m-nash | | ||
| | Java | @JonathanGiles, @alzimmermsft | | ||
| | Python | @xirzec, @kashifkhan | | ||
| | TypeScript | @xirzec, @maorleger | | ||
| | Go | @jhendrixMSFT | | ||
| | Mgmt (all languages) | @ArthurMa1978, @m-nash | | ||
|
|
||
| <!-- cspell:enable --> | ||
|
|
||
| ## For Service Teams | ||
|
|
||
| No action needed beyond your normal workflow: | ||
|
samvaity marked this conversation as resolved.
Resolved
|
||
|
|
||
| 1. Add or modify namespace in your `tspconfig.yaml` | ||
| 2. Open a PR as usual | ||
| 3. The bot posts a status table and applies pending labels | ||
| 4. Wait for architects to approve | ||
| 5. Once approved, the status check passes and the PR can merge | ||
|
|
||
|
samvaity marked this conversation as resolved.
Resolved
|
||
| ## For Architects | ||
|
|
||
| 1. Watch for PRs with `<lang>-namespace-pending` labels | ||
| 2. Review the proposed namespace in the PR diff | ||
| 3. If acceptable, apply `<lang>-namespace-approved` label | ||
| 4. For management plane PRs, you can use `namespace-approved-all` to approve all at once | ||
|
|
||
| ## Configuration | ||
|
|
||
| To update approvers, submit a PR modifying `.github/namespace-approvers.yml`. Changes take effect immediately on merge. | ||
|
|
||
| ## Relationship to API Review | ||
|
|
||
| Namespace approval is **separate from API review**: | ||
|
|
||
| - **Namespace approval** (this repo): gates spec PR merge, ensures library naming is correct | ||
| - **API review** (azure-sdk repo): reviews API surface design (methods, models, parameters) | ||
|
|
||
| A new service typically needs namespace approval first (on their spec PR), then API review later (when SDK is built). | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.