| <!--{ | |
| "Title": "Module release and versioning workflow" | |
| }--> | |
| When you develop modules for use by other developers, you can follow a workflow | |
| that helps ensure a reliable, consistent experience for developers using the | |
| module. This topic describes the high-level steps in that workflow. | |
| For an overview of module development, see [Developing and publishing | |
| modules](developing). | |
| **See also** | |
| * If you're merely wanting to use external packages in your code, be sure to | |
| see [Managing dependencies](/doc/modules/managing-dependencies). | |
| * With each new version, you signal the changes to your module with its | |
| version number. For more, see [Module version numbering](/doc/modules/version-numbers). | |
| ## Common workflow steps {#common-steps} | |
| The following sequence illustrates release and versioning workflow steps for an | |
| example new module. For more about each step, see the sections in this topic. | |
| 1. **Begin a module** and organize its sources to make it easier for developers | |
| to use and for you to maintain. | |
| If you're brand new to developing modules, check out [Tutorial: Create a Go | |
| module](/doc/tutorial/create-module). | |
| In Go's decentralized module publishing system, how you organize your code | |
| matters. For more, see [Managing module source](/doc/modules/managing-source). | |
| 1. Set up to **write local client code** that calls functions in the | |
| unpublished module. | |
| Before you publish a module, it's unavailable for the typical dependency | |
| management workflow using commands such as `go get`. A good way to test your | |
| module code at this stage is to try it while it is in a directory local to | |
| your calling code. | |
| See [Coding against an unpublished module](#unpublished) for more about | |
| local development. | |
| 1. When the module's code is ready for other developers to try it out, | |
| **begin publishing v0 pre-releases** such as alphas and betas. See | |
| [Publishing pre-release versions](#pre-release) for more. | |
| 1. **Release a v0** that's not guaranteed to be stable, but which users can try | |
| out. For more, see [Publishing the first (unstable) version](#first-unstable). | |
| 1. After your v0 version is published, you can (and should!) continue to | |
| **release new versions** of it. | |
| These new versions might include bug fixes (patch releases), additions to | |
| the module's public API (minor releases), and even breaking changes. Because | |
| a v0 release makes no guarantees of stability or backward compatibility, you | |
| can make breaking changes in its versions. | |
| For more, see [Publishing bug fixes](#bug-fixes) and [Publishing | |
| non-breaking API changes](#non-breaking). | |
| 1. When you're getting a stable version ready for release, you **publish | |
| pre-releases as alphas and betas**. For more, see [Publishing pre-release | |
| versions](#pre-release). | |
| 1. Release a v1 as the **first stable release**. | |
| This is the first release that makes commitments about the module's | |
| stability. For more, see [Publishing the first stable | |
| version](#first-stable). | |
| 1. In the v1 version, **continue to fix bugs** and, where necessary, make | |
| additions to the module's public API. | |
| For more, see [Publishing bug fixes](#bug-fixes) and [Publishing | |
| non-breaking API changes](#non-breaking). | |
| 1. When it can't be avoided, publish breaking changes in a **new major version**. | |
| A major version update -- such as from v1.x.x to v2.x.x -- can be a very | |
| disruptive upgrade for your module's users. It should be a last resort. For | |
| more, see [Publishing breaking API changes](#breaking). | |
| ## Coding against an unpublished module {#unpublished} | |
| When you begin developing a module or a new version of a module, you won't yet | |
| have published it. Before you publish a module, you won't be able to use Go | |
| commands to add the module as a dependency. Instead, at first, when writing | |
| client code in a different module that calls functions in the unpublished | |
| module, you'll need to reference a copy of the module on the local file system. | |
| You can reference a module locally from the client module's go.mod file by using | |
| the `replace` directive in the client module's go.mod file. For more | |
| information, see in [Requiring module code in a local | |
| directory](managing-dependencies#local_directory). | |
| ## Publishing pre-release versions {#pre-release} | |
| You can publish pre-release versions to make a module available for others to | |
| try it out and give you feedback. A pre-release version includes no guarantee of | |
| stability. | |
| Pre-release version numbers are appended with a pre-release identifier. For more | |
| on version numbers, see [Module version numbering](/doc/modules/version-numbers). | |
| Here are two examples: | |
| ``` | |
| v0.2.1-beta.1 | |
| v1.2.3-alpha | |
| ``` | |
| When making a pre-release available, keep in mind that developers using the | |
| pre-release will need to explicitly specify it by version with the `go get` | |
| command. That's because, by default, the `go` command prefers release versions | |
| over pre-release versions when locating the module you're asking for. So | |
| developers must get the pre-release by specifying it explicitly, as in the | |
| following example: | |
| ``` | |
| go get example.com/theirmodule@v1.2.3-alpha | |
| ``` | |
| You publish a pre-release by tagging the module code in your repository, | |
| specifying the pre-release identifier in the tag. For more, see [Publishing a | |
| module](publishing). | |
| ## Publishing the first (unstable) version {#first-unstable} | |
| As when you publish a pre-release version, you can publish release versions that | |
| don't guarantee stability or backward compatibility, but give your users an | |
| opportunity to try out the module and give you feedback. | |
| Unstable releases are those whose version numbers are in the v0.x.x range. A v0 | |
| version makes no stability or backward compatibility guarantees. But it gives | |
| you a way to get feedback and refine your API before making stability | |
| commitments with v1 and later. For more see, [Module version | |
| numbering](version-numbers). | |
| As with other published versions, you can increment the minor and patch parts of | |
| the v0 version number as you make changes toward releasing a stable v1 version. | |
| For example, after releasing a v.0.0.0, you might release a v0.0.1 with the | |
| first set of bug fixes. | |
| Here's an example version number: | |
| ``` | |
| v0.1.3 | |
| ``` | |
| You publish an unstable release by tagging the module code in your repository, | |
| specifying a v0 version number in the tag. For more, see [Publishing a | |
| module](publishing). | |
| ## Publishing the first stable version {#first-stable} | |
| Your first stable release will have a v1.x.x version number. The first stable | |
| release follows pre-release and v0 releases through which you got feedback, | |
| fixed bugs, and stabilized the module for users. | |
| With a v1 release, you're making the following commitments to developers using | |
| your module: | |
| * They can upgrade to the major version's subsequent minor and patch releases | |
| without breaking their own code. | |
| * You won't be making further changes to the module's public API -- including | |
| its function and method signatures -- that break backward compatibility. | |
| * You won't be removing any exported types, which would break backward | |
| compatibility. | |
| * Future changes to your API (such as adding a new field to a struct) will be | |
| backward compatible and will be included in a new minor release. | |
| * Bug fixes (such as a security fix) will be included in a patch release or as | |
| part of a minor release. | |
| **Note:** While your first major version might be a v0 release, a v0 version | |
| does not signal stability or backward compatibility guarantees. As a result, | |
| when you increment from v0 to v1, you needn't be mindful of breaking backward | |
| compatibility because the v0 release was not considered stable. | |
| For more about version numbers, see [Module version numbering](/doc/modules/version-numbers). | |
| Here's an example of a stable version number: | |
| ``` | |
| v1.0.0 | |
| ``` | |
| You publish a first stable release by tagging the module code in your | |
| repository, specifying a v1 version number in the tag. For more, see [Publishing | |
| a module](publishing). | |
| ## Publishing bug fixes {#bug-fixes} | |
| You can publish a release in which the changes are limited to bug fixes. This is | |
| known as a patch release. | |
| A _patch release_ includes only minor changes. In particular, it includes no | |
| changes to the module's public API. Developers of consuming code can upgrade to | |
| this version safely and without needing to change their code. | |
| **Note:** Your patch release should try not to upgrade any of that module's own | |
| transitive dependencies by more than a patch release. Otherwise, someone | |
| upgrading to the patch of your module could wind up accidentally pulling in a | |
| more invasive change to a transitive dependency that they use. | |
| A patch release increments the patch part of the module's version number. For | |
| more see, [Module version numbering](/doc/modules/version-numbers). | |
| In the following example, v1.0.1 is a patch release. | |
| Old version: `v1.0.0` | |
| New version: `v1.0.1` | |
| You publish a patch release by tagging the module code in your repository, | |
| incrementing the patch version number in the tag. For more, see [Publishing a | |
| module](publishing). | |
| ## Publishing non-breaking API changes {#non-breaking} | |
| You can make non-breaking changes to your module's public API and publish those | |
| changes in a _minor_ version release. | |
| This version changes the API, but not in a way that breaks calling code. This | |
| might include changes to a module’s own dependencies or the addition of new | |
| functions, methods, struct fields, or types. Even with the changes it includes, | |
| this kind of release guarantees backward compatibility and stability for | |
| existing code that calls the module's functions. | |
| A minor release increments the minor part of the module's version number. For | |
| more, see [Module version numbering](/doc/modules/version-numbers). | |
| In the following example, v1.1.0 is a minor release. | |
| Old version: `v1.0.1` | |
| New version: `v1.1.0` | |
| You publish a minor release by tagging the module code in your repository, | |
| incrementing the minor version number in the tag. For more, see [Publishing a | |
| module](publishing). | |
| ## Publishing breaking API changes {#breaking} | |
| You can publish a version that breaks backward compatibility by publishing a | |
| _major_ version release. | |
| A major version release doesn't guarantee backward compatibility, typically | |
| because it includes changes to the module's public API that would break code | |
| using the module's previous versions. | |
| Given the disruptive effect a major version upgrade can have on code relying on | |
| the module, you should avoid a major version update if you can. For more about | |
| major version updates, see [Developing a major version update](/doc/modules/major-version). | |
| For strategies to avoid making breaking changes, see the blog post [Keeping your | |
| modules compatible](/blog/module-compatibility). | |
| Where publishing other kinds of versions requires essentially tagging the module | |
| code with the version number, publishing a major version update requires more | |
| steps. | |
| 1. Before beginning development of the new major version, in your repository | |
| create a place for the new version's source. | |
| One way to do this is to create a new branch in your repository that is | |
| specifically for the new major version and its subsequent minor and patch | |
| versions. For more, see [Managing module source](/doc/modules/managing-source). | |
| 1. In the module's go.mod file, revise the module path to append the new major | |
| version number, as in the following example: | |
| ``` | |
| example.com/mymodule/v2 | |
| ``` | |
| Given that the module path is the module's identifier, this change | |
| effectively creates a new module. It also changes the package path, ensuring | |
| that developers won't unintentionally import a version that breaks their | |
| code. Instead, those wanting to upgrade will explicitly replace occurrences | |
| of the old path with the new one. | |
| 1. In your code, change any package paths where you're importing packages in | |
| the module you're updating, including packages in the module you're updating. | |
| You need to do this because you changed your module path. | |
| 1. As with any new release, you should publish pre-release versions to get | |
| feedback and bug reports before publishing an official release. | |
| 1. Publish the new major version by tagging the module code in your repository, | |
| incrementing the major version number in the tag -- such as from v1.5.2 to | |
| v2.0.0. | |
| For more, see [Publishing a module](/doc/modules/publishing). |