Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 Jun 18, 2026
4f28a24
Address review feedback: unlabeled guard, remove C++/Rust
samvaity Jun 22, 2026
37aa3d1
Add unit tests and namespace format validation
samvaity Jun 22, 2026
67ed6c8
Address review: split workflow, use repo helpers, add zod schema
samvaity Jun 23, 2026
01ea7c6
Fix CI: prettier formatting and cspell word
samvaity Jun 23, 2026
cf496ef
Fix: use sparse-checkout add instead of git checkout for hydration
samvaity Jun 24, 2026
c11675f
Parse tspconfig.yaml directly, add commit status gate, fix plane dete…
samvaity Jun 24, 2026
1b9a3b6
Split status workflow into separate files following repo convention
samvaity Jun 24, 2026
02ccf7e
Fix: deduplicate job name in code workflow to match repo convention
samvaity Jun 25, 2026
a55968c
Address review: add else fallback in status check, fix check name in …
samvaity Jun 29, 2026
bb3a30c
Add Namespace Approval to summarize-checks for Next Steps to Merge
samvaity Jun 29, 2026
9dc65fd
Add Java Maven artifact dual namespace, selective reset, lint and typ…
samvaity Jul 1, 2026
849da69
Fix namespace approval TS type errors
samvaity Jul 1, 2026
843da16
Address review feedback: error handling, shared helpers, and cleanup
samvaity Jul 2, 2026
9f03703
Fix CodeQL ReDoS alert: replace regex with string methods in tspconfi…
samvaity Jul 2, 2026
759d377
Add coverage test for tspconfig filter in changed-files
samvaity Jul 2, 2026
2a9c182
Fix namespace-approval TypeScript null and env typing errors
samvaity Jul 2, 2026
7cead2e
Address review issues: shared approvers, pagination, async format, ti…
samvaity Jul 6, 2026
93c8ba4
Prevent duplicate 'Namespace Approved' comments on concurrent label e…
samvaity Jul 6, 2026
54ea1e9
Rename labels to namespace-<lang>-*, add @handles, integrate with NSTM
samvaity Jul 6, 2026
05b0587
Extract shared labels helper, remove createLabel, clarify plane detec…
samvaity Jul 6, 2026
b430ea0
Fix NSTM: clarify namespace-approved-all is mgmt-plane only
samvaity Jul 7, 2026
c890e3e
changed-files helper cleanup
mikeharder Jul 8, 2026
3a7483f
Merge branch 'main' into namespace-approval
mikeharder Jul 8, 2026
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
101 changes: 101 additions & 0 deletions .github/NAMESPACE-REVIEW-PROCESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# 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.

This process is automated via GitHub Actions on this repository.

## How It Works

### Detection

When a PR modifies any `tspconfig.yaml` file, the workflow:

1. Identifies which languages have namespace/package-name configuration
2. Extracts namespaces using the `@azure-tools/typespec-metadata` emitter (primary) with YAML parsing fallback
3. Determines if the service is data-plane or management-plane
4. Applies `<lang>-namespace-pending` labels for each detected language
Comment thread
samvaity marked this conversation as resolved.
Resolved

### Approval

- **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:

- ✅ Passes when all `*-namespace-pending` labels have corresponding `*-namespace-approved` labels
- ❌ 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** a namespace value (not just TypeSpec code), 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

TypeSpec-only changes (no namespace modification) do **not** reset approval.

## 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 |

Where `<lang>` is one of: `dotnet`, `java`, `python`, `typescript`, `go`, `cpp`, `rust`
Comment thread
samvaity marked this conversation as resolved.
Resolved

## Authorized Approvers

Defined in [`.github/namespace-approvers.yml`](../.github/namespace-approvers.yml):

<!-- cspell:disable -->

| Scope | Approvers |
| -------------------- | ----------------------------- |
| .NET | @jsquire, @m-nash |
| Java | @JonathanGiles, @alzimmermsft |
| Python | @xirzec, @kashifkhan |
| TypeScript | @xirzec, @maorleger |
| Go | @jhendrixMSFT |
| C++ | @LarryOsterman |
| Rust | @heaths, @LarryOsterman |
| Mgmt (all languages) | @ArthurMa1978, @m-nash |

<!-- cspell:enable -->

## For Service Teams

No action needed beyond your normal workflow:

1. Add/modify namespace in your `tspconfig.yaml`
2. Open a PR as usual
3. The bot will apply pending labels and post a status table
4. Wait for architects to approve — they're notified via labels
5. Once approved, the status check passes and the PR can merge

## 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).
31 changes: 31 additions & 0 deletions .github/namespace-approvers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# cspell:words jsquire alzimmermsft xirzec kashifkhan maorleger jhendrixMSFT LarryOsterman heaths 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
cpp:
- LarryOsterman
rust:
- heaths
- LarryOsterman

management-plane:
all:
- ArthurMa1978
- m-nash
102 changes: 102 additions & 0 deletions .github/workflows/namespace-approval.yml
Comment thread
samvaity marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Namespace Approval

on:
pull_request:
types:
Comment thread
samvaity marked this conversation as resolved.
Resolved
- opened
- synchronize
- labeled
- unlabeled

permissions:
pull-requests: write
Comment thread
samvaity marked this conversation as resolved.
Resolved
contents: read

jobs:
detect-namespaces:
if: github.event.action == 'opened' || github.event.action == 'synchronize'
name: Detect Namespace Changes

runs-on: ubuntu-24.04

outputs:
has_pending: ${{ steps.detect.outputs.has_pending }}

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
Comment thread
samvaity marked this conversation as resolved.
Resolved

- 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

- id: detect
name: Detect namespace changes
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 });

validate-approval:
if: github.event.action == 'labeled'
name: Validate Namespace Approval

runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.base.ref }}
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: [detect-namespaces, validate-approval]
if: always()

runs-on: ubuntu-24.04

steps:
- name: Verify namespace approval status
uses: actions/github-script@v8
with:
script: |
const { data: pr } = await github.rest.pulls.get({
Comment thread
samvaity marked this conversation as resolved.
Resolved
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});
const labels = pr.labels.map((l) => l.name);

if (!labels.includes("namespace-review-required")) {
core.info("No namespace review required, passing");
return;
}

const pendingLabels = labels.filter((l) => l.endsWith("-namespace-pending"));
if (pendingLabels.length > 0) {
core.setFailed(
`Namespace approval pending for: ${pendingLabels
.map((l) => l.replace("-namespace-pending", ""))
.join(", ")}`,
);
} else if (labels.includes("namespace-approved")) {
core.info("All namespaces approved - merge allowed");
}
Loading
Loading