When a multi-module Go repository has moved or deleted a module, without deprecation or retraction, the module becomes abandoned. Abandoned modules still exist in documentation and are confusing to users, especially if they are similarly named to their replacement.
How should a project handle these abandoned modules?
- Code that currently compiles, continues to compile.
- Upgrades to code that use the module inform the upgrader to use an alternate solution.
- Go tooling should warn the user when they try to build with the module.
- It is clear to new users the module should not be used.
- Go documentation should clearly state the module should not be used, or it should not contain a listing for the module.
- Support Go 1.17 and above.
The Go module system has two relevant directives: deprecation and retraction
A module can be marked as deprecated in a block of comments containing the string
Deprecated
: (case-sensitive) at the beginning of a paragraph. [...] Deprecation messages are intended to inform users that the module is no longer supported and to provide migration instructions, for example, to the latest major version. Individual minor and patch versions cannot be deprecated;retract
may be more appropriate for that.
Since Go 1.17,
go list -m -u
checks for information on all deprecated modules in the build list.go get
checks for deprecated modules needed to build packages named on the command line.
A retract directive indicates that a version or range of versions of the module defined by go.mod should not be depended upon. A retract directive is useful when a version was published prematurely or a severe problem was discovered after the version was published. Retracted versions should remain available in version control repositories and on module proxies to ensure that builds that depend on them are not broken.
When a module version is retracted, users will not upgrade to it automatically using
go get
,go mod tidy
, or other commands. Builds that depend on retracted versions should continue to work, but users will be notified of retractions when they check for updates withgo list -m -u
or update a related module withgo get
.
Original respository structure:
erase
├── go.mod
├── go.sum
├── LICENSE
├── main.go
├── mushroom
│ ├── go.mod
│ └── mushroom.go
└── README.md
Released as v0.0.2
New repository structure in release v0.0.3
:
erase
├── go.mod
├── go.sum
├── LICENSE
├── main.go
├── mushrooms
│ ├── go.mod
│ └── mushroom.go
└── README.md
Now the Go docs page lists two similar modules.
Old code that depends on github.com/MrAlias/erase/mushroom
still compiles, but it is not obvious to new users which module to use without deeper investigation about each of their versions.
The old abandoned module, mushroom
, needs to be cleaned up.
Communicate to the user that the mushroom
module is no longer supported and to provide migration instructions to start using mushrooms
by deprecating the package.
Ultimately this means ...
- update
mushroom/go.mod
to include a deprecation notice - release an incremented version of
mushroom
to inclued the deprecation notice
The only issue is, the main
branch no longer contains mushroom/go.mod
.
To accomplish this a branch needs to be created from the commit prior to its removal.
git branch erase-mushroom bfd719a~1
Now update mushroom/go.mod
.
sed -i.old '1s;^;// Deprecated: use github.com/MrAlias/erase/mushrooms instead.\n;' mushroom/go.mod
git commit -m "Deprecate github.com/MrAlias/erase/mushroom" mushroom/go.mod
git push origin erase-mushroom
git tag -s -a -m "Release github.com/MrAlias/erase/mushroom v0.0.3" mushroom/v0.0.3
git push origin mushroom/v0.0.3
There is now a new mushroom/v0.0.3
tag in the repository!
And similarly the package documentation lists github.com/MrAlias/erase/mushroom
as deprecated.
Now when packages that use github.com/MrAlias/erase/mushroom
they are presented with the deprecation warning.
$ go get -u
go: module github.com/MrAlias/erase/mushroom is deprecated: use github.com/MrAlias/erase/mushrooms instead.
Similarly for new additions:
$ go get github.com/MrAlias/erase/[email protected]
go: downloading github.com/MrAlias/erase v0.0.3
go: module github.com/MrAlias/erase/mushroom is deprecated: use github.com/MrAlias/erase/mushrooms instead.
The last thing to do for this is to protect the erase-mushroom
branch.
It should not be allowed to be deleted, otherwise the source of the v0.0.3
version of module will not available.
Create an empty branch protection rule in GitHub.
By default, this protection rule will prevent the erase-mushroom
branch from being deleted.
The mushroom
module is deprecated, but the github.com/MrAlias/erase
module documentation still lists it.
Publishing a new version of github.com/MrAlias/erase
does not remove it.