Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@ llmstxt: true

See [`@typespec/versioning` documentation](https://typespec.io/docs/libraries/versioning/guide) for the general versioning concept. This guide expands on how Azure Services should define Preview versions.

## Preview Versioning Rules
See [Common ARM Versioning Scenarios](../ARM/versioning.md) for how to make specific kinds of common API changes in ARM specs.

## Preview Versioning Rules for All Azure APIs

- Always make the last enum value the preview and apply `@previewVersion` to it.
- Only one version may be marked with the `@previewVersion` decorator.
- Mark all changes from the latest stable with appropriate versioning decorators, using `Versions.<PreviewVersion>` as the version argument (where `<PreviewVersion>` is the name of the last enum value)

## Preview Versioning Rules for ARM APIs

ARM APIs sometimes have special requirements for retaining swagger for preview APIs that are not yet retired. For detailed information about ARM API Versioning see [Supporting a Single Active Preview in ARM APIs](./ARM/01-about-versioning.md).

## Preview Versioning Rules for Data Plane APIs

- Always make the last enum the preview and apply `@previewVersion` to it.
- Apply `@added(Versions.PreviewVersion)` to all preview items - these items will not show up in any GA Version
- For a new GA, add a new version enum **BEFORE** the preview enum value. Manually change all **preview** items that are GA'ing so that the `@added` version value matches the new GA enum value
- For any items remaining in **preview**, rename the **old preview** enum value to the **new preview** enum value.

## Usage Examples
### Usage Examples

### New preview Version
#### New preview Version

In the following example we introduce a new preview version called `v3Preview` which includes everything from `v2` plus adds a new property to the `Widget` resource.

Expand Down Expand Up @@ -65,7 +75,7 @@ model Widget {
}
```

### Adding a new stable (GA) version
#### Adding a new stable (GA) version

This example builds on the previous one, where `v3` is introduced which GA's the `nickname` property introduced in `v3Preview`

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: Introduction
llmstxt: true
---

TypeSpec uses a versioning library that models the changes in each new version of the API, rather than having a separate api description for each api-version.
This works well when APIs evolve according to versioning guidelines, without breaking changes. For the most part, this means that this system is very good at
modeling differences between stable api-versions for Azure APIs, but can be cumbersome when describing differences between preview APIs.

Additionally, in Azure. preview APIs have a limited lifespan and limited support in SDKs and other tooling. For this reason and others, specs should only have a _single active preview_ in TypeSpec at any point during the spec development process.

At the same time, Azure ResourceManager teams may need to maintain OpenAPI files for preview versions until they are retired, some reasons for this include:

- RPaaS live validation support
- ARM registration support

See [Should I Retain the OpenAPI for an Old Preview API](#should-i-retain-the-openapi-for-an-old-preview-api) for details.

This document describes how to evolve APIs according to these guidelines, and how to meet both the single active preview guideline and the need to maintain some preview versions in Swagger in some situations, focusing on authoring of new APIs:

- [How to add a new preview version when the last version was preview](./02-preview-after-preview.md)
- [How to add a new stable version when the last version was preview](./03-stable-after-preview.md)
- [How to add a new preview version when the last version was stable](./04-preview-after-stable.md)
- [How to add a new stable version when the last version was stable](./05-stable-after-stable.md)

This document also describes how to convert an existing multi-api typespec spec with multiple previews into a spec with a single active preview. Note that this is not required, but it may significantly simplify the versioning decoration in your spec:

- [How to convert a spec with multiple preview versions into a spec with a single active preview](./uncommon-scenarios/01-converting-specs.md)

Additionally, there are some services that may always have features that remain in preview after a stable version is released. This can happen, for example, if there are multiple independent teams that own different resources in a service and operate on their own schedule. The recommended way to handle this scenario is to model your ResourceProvider as multiple services, so each version and the corresponding SDKs can version independently. For some older services, this is not an option, so there is specialized guidance on how to maintain preview features over stable api releases (described below). If you are thinking about splitting your service, or about creating a new preview version with every stable version, be sure to have a discussion with the [Azure API Stewardship Board](https://aka.ms/azapi/officehours) and the [Azure SDK team](https://eng.ms/docs/products/azure-developer-experience/onboard) first.

- [How to manage a single active preview if your service always has some features in preview](./uncommon-scenarios/02-perpetual-preview.md)

## Should I Retain the OpenAPI for an Old Preview API

It is safe to remove the swagger for an old API version if any of the following is true:

- The api-version is retired
- The OpenAPI document in the azure-rest-api-specs repo is not needed for RPaaS live validation
- The OpenAPI document in the azure-rest-api-specs repo is not needed for ARM registration

It is recommended that preview api-versions are set for retirement within 90 days when a preview or stable API is introduced. See the [Azure Retirement Policy](https://aka.ms/AzureRetirementPolicy) and [Azure Retirement Process](https://aka.ms/cpexretirementsprocess) for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
title: Adding a Preview Version when the Last Version was Preview
llmstxt: true
---

When the last api-version in your TypeSpec spec is a preview, adding a new preview version is simply replacing the latest preview version with a new preview version.

## The Simplest Case: No Stable api-versions

If your spec is in preview and has not ever had a stable api-version, then there is no need to have versioning decoration in your typespec at all:

- Change the api-version to match the new api-version
```diff lang=tsp
enum Versions {
@previewVersion
- `2025-12-01-preview`
+ `2026-01-01-preview`
}
```
- Remove any versioning decorators
- Make any api changes for the new preview, there is no need to use versioning decoration for this.
- Update the example folder name to match the new api-version

```bash
> mv examples/2025-12-01-preview examples/2026-01-01-preview
```

- Update the `api-version` in examples to match the new api-version (search and replace api-version in the examples folder)

```diff lang=json
{
"title": "Create a Widget",
"operationId": "Widgets_Create",
"parameters": {
- "api-version": "2025-12-01-preview",
+ "api-version": "2026-01-01-preview",
}
}
```

- If you **do not need** to retain the OpenAPI for older previews (see [Should I delete an old preview](./01-about-versioning.md#should-i-retain-the-openapi-for-an-old-preview-api) if you are not sure).
- Remove the associated OpenAPI file and examples

```bash
> rm -r 2025-12-01-preview
```

- Remove any references to the old version from README.md

- Update the README.md to include the new api-version

## The General Case: One or more Stable Versions Exist

If there are stable versions before the latest preview version, then you will need to adapt the latest preview version and its decoration for the new preview version.

This includes the following steps:

### Making Changes to your TypeSpec spec

- Rename the latest preview version to match the new preview version, in all instances in the spec
- In vscode, highlight the version name and select `rename symbol` from the context menu to rename the version throughout your spec
- In any editor, search and replace the latest preview version in the spec with the new preview version
- Update the version value of this version to match the new api-version string, for example:
```diff lang=tsp
enum Versions {
@previewVersion
- `2025-12-01-preview`,
+ `2026-01-01-preview`,
}
```
- The new preview version should already be the _last version_ of the versions enum, also ensure it is decorated with `@previewVersion`
- Update any mention in documentation of the old api-version to use the new api-version
- Make changes to the API description based on how the API has changed from the last preview version to the new preview version (if it has changed)
- If any type that was introduced in the latest preview is _not_ in the new preview, simply delete the type
```diff lang=tsp
- @added(Versions.`2026-01-01-preview`)
- model Foo {}
```
- If any type was removed in the latest preview but **appears** in the new preview, remove the decorator
```diff lang=tsp
- @removed(Versions.`2026-01-01-preview`)
model Bar {}
```
- Similarly, if there is any change from the latest preview that does not apply to the new preview version, reverse the decorator.
```diff lang=tsp
- @renamedFrom(Versions.`2026-01-01-preview`, "oldProp")
- newProp: string;
+ oldProp: string;
```
```diff lang=tsp
- @typeChangedFrom(Versions.`2026-01-01-preview`, string)
- changedProp: int32;
+ changedProp: string;
```
```diff lang=tsp
- @madeOptional(Versions.`2026-01-01-preview`)
- requiredProp?: string;
+ requiredProp: string;
```
- If any other types are removed in the new preview (unlikely, because these would be breaking changes from the previous stable and require a breaking change review) mark these with an `@removed` decorator referencing the new version
```diff lang=tsp
+ @removed(Versions.`2026-01-01-preview`)
model Bar {}
```
- If any types are added, renamed, or otherwise modified in the new version, mark them with the appropriate versioning decorator.
- Change the name of the `examples` version folder for the latest preview to match the new preview version
```bash
> mv examples/2025-12-01-preview examples/2026-01-01-preview
```
- Ensure that examples use the correct api-version (search and replace the api-version for all examples in the folder)
```diff lang=json
{
"title": "Create a Widget",
"operationId": "Widgets_Create",
"parameters": {
- "api-version": "2025-12-01-preview",
+ "api-version": "2026-01-01-preview",
}
}
```
- Add and modify examples to match the api changes
### Preparing a PR into the azure-rest-api-specs repo
- Navigate to the root directory of the repo in your local fork or clone
```bash
C:\repos\azure-rest-api-specs\specifications\myRp > cd \repos\azure-rest-api-specs
C:\repos\azure-rest-api-specs >
```
- Pull the latest version from the repo
```bash
C:\repos\azure-rest-api-specs > git fetch upstream main
C:\repos\azure-rest-api-specs > git pull upstream main
```
- Reinstall dependencies
```bash
C:\repos\azure-rest-api-specs > npm ci
```
- Compile your spec
```bash
C:\repos\azure-rest-api-specs > cd specification\myRpShortname\resource-manager\Microsoft.MyRP\MyService
C:\repos\azure-rest-api-specs\specification\myRpShortname\resource-manager\Microsoft.MyRP\MyService > npx tsp compile .
```
- If you _don't_ need the older preview version (see [Should I delete an old preview](./01-about-versioning.md#should-i-retain-the-openapi-for-an-old-preview-api) if you are not sure), remove the OpenAPI directory for that version and update the `README.md` file to use the new version instead.
```bash
C:\repos\azure-rest-api-specs\specification\myRpShortname\resource-manager\Microsoft.MyRP\ > rm -r 2025-12-01-preview
```
- If you _do_ need the older preview version, update README.md to include a new entry for the new preview version.
Loading