|
| 1 | +--- |
| 2 | +title: Introduction |
| 3 | +llmstxt: true |
| 4 | +--- |
| 5 | + |
| 6 | +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 and manage API versions. |
| 7 | + |
| 8 | +See [Common Versioning Scenarios](../ARM/versioning.md) for how to make specific kinds of common API changes in your specs. |
| 9 | + |
| 10 | +## How Versioning Works in TypeSpec |
| 11 | + |
| 12 | +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. |
| 13 | + |
| 14 | +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. |
| 15 | + |
| 16 | +## Preview Versioning Rules for All Azure APIs |
| 17 | + |
| 18 | +- Always make the last enum value the preview and apply `@previewVersion` to it. |
| 19 | +- Only one version may be marked with the `@previewVersion` decorator. |
| 20 | +- 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) |
| 21 | + |
| 22 | +## Preview Versioning Rules for Data Plane APIs |
| 23 | + |
| 24 | +- 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 |
| 25 | +- For any items remaining in **preview**, rename the **old preview** enum value to the **new preview** enum value. |
| 26 | + |
| 27 | +## Common Version Transition Scenarios |
| 28 | + |
| 29 | +This section 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 certain situations: |
| 30 | + |
| 31 | +- [How to add a new preview version when the last version was preview](./02-preview-after-preview.md) |
| 32 | +- [How to add a new stable version when the last version was preview](./03-stable-after-preview.md) |
| 33 | +- [How to add a new preview version when the last version was stable](./04-preview-after-stable.md) |
| 34 | +- [How to add a new stable version when the last version was stable](./05-stable-after-stable.md) |
| 35 | + |
| 36 | +This section 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: |
| 37 | + |
| 38 | +- [How to convert a spec with multiple preview versions into a spec with a single active preview](./uncommon-scenarios/01-converting-specs.md) |
| 39 | + |
| 40 | +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. |
| 41 | + |
| 42 | +- [How to manage a single active preview if your service always has some features in preview (ARM only)](./uncommon-scenarios/02-perpetual-preview.md) |
| 43 | + |
| 44 | +## Should I Retain the OpenAPI for an Old Preview API (ARM Only) |
| 45 | + |
| 46 | +:::note |
| 47 | +This section applies specifically to **Azure Resource Manager (ARM) APIs**. ARM teams may need to maintain OpenAPI files for preview versions until they are retired for reasons including: |
| 48 | + |
| 49 | +- RPaaS live validation support |
| 50 | +- ARM registration support |
| 51 | +::: |
| 52 | + |
| 53 | +It is safe to remove the swagger for an old API version if any of the following is true: |
| 54 | + |
| 55 | +- The api-version is retired |
| 56 | +- The OpenAPI document in the azure-rest-api-specs repo is not needed for RPaaS live validation |
| 57 | +- The OpenAPI document in the azure-rest-api-specs repo is not needed for ARM registration |
| 58 | + |
| 59 | +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. |
| 60 | + |
| 61 | +### Usage Examples |
| 62 | + |
| 63 | +#### New preview version |
| 64 | + |
| 65 | +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. |
| 66 | + |
| 67 | +```diff lang=tsp |
| 68 | +import "@typespec/http"; |
| 69 | +import "@typespec/rest"; |
| 70 | +import "@typespec/versioning"; |
| 71 | +import "@azure-tools/typespec-azure-core"; |
| 72 | + |
| 73 | +using Http; |
| 74 | +using Rest; |
| 75 | +using Versioning; |
| 76 | +using Azure.Core; |
| 77 | + |
| 78 | + |
| 79 | +@versioned(Versions) |
| 80 | +@service(#{ title: "Widget Service" }) |
| 81 | +namespace DemoService; |
| 82 | + |
| 83 | +enum Versions { |
| 84 | + v1, |
| 85 | + v2, |
| 86 | ++ @previewVersion |
| 87 | ++ v3Preview |
| 88 | +} |
| 89 | + |
| 90 | +/** |
| 91 | + * Model defining the Widget resource |
| 92 | + */ |
| 93 | +model Widget { |
| 94 | + /** |
| 95 | + * Identifier of the Widget Resource |
| 96 | + */ |
| 97 | + @visibility(Lifecycle.Read) |
| 98 | + @key id: string; |
| 99 | + /** |
| 100 | + * Weight of the widget |
| 101 | + */ |
| 102 | + weight: int32; |
| 103 | + /** |
| 104 | + * Color of the widget; |
| 105 | + */ |
| 106 | + color: "red" | "blue"; |
| 107 | + /** |
| 108 | + * Nickname of the Widget resource |
| 109 | + */ |
| 110 | ++ @added(Versions.v3Preview) nickname: string; |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +#### Adding a new stable (GA) version |
| 115 | + |
| 116 | +This example builds on the previous one, where `v3` is introduced which GA's the `nickname` property introduced in `v3Preview` |
| 117 | + |
| 118 | +```diff lang=tsp |
| 119 | +import "@typespec/http"; |
| 120 | +import "@typespec/rest"; |
| 121 | +import "@typespec/versioning"; |
| 122 | +import "@azure-tools/typespec-azure-core"; |
| 123 | + |
| 124 | +using Http; |
| 125 | +using Rest; |
| 126 | +using Versioning; |
| 127 | +using Azure.Core; |
| 128 | + |
| 129 | + |
| 130 | +@versioned(Versions) |
| 131 | +@service(#{ title: "Widget Service" }) |
| 132 | +namespace DemoService; |
| 133 | + |
| 134 | +enum Versions { |
| 135 | + v1, |
| 136 | + v2, |
| 137 | +- @previewVersion |
| 138 | +- v3Preview |
| 139 | ++ v3 |
| 140 | +} |
| 141 | + |
| 142 | +/** |
| 143 | + * Model defining the Widget resource |
| 144 | + */ |
| 145 | +model Widget { |
| 146 | + /** |
| 147 | + * Identifier of the Widget Resource |
| 148 | + */ |
| 149 | + @visibility(Lifecycle.Read) |
| 150 | + @key id: string; |
| 151 | + /** |
| 152 | + * Weight of the widget |
| 153 | + */ |
| 154 | + weight: int32; |
| 155 | + /** |
| 156 | + * Color of the widget; |
| 157 | + */ |
| 158 | + color: "red" | "blue"; |
| 159 | + /** |
| 160 | + * Nickname of the Widget resource |
| 161 | + */ |
| 162 | +- @added(Versions.v3Preview) nickname: string; |
| 163 | ++ @added(Versions.v3) nickname: string; |
| 164 | +} |
| 165 | +``` |
0 commit comments