How to unpublish/redact/undo/retract a Go release

I recently rolled out go-semantic-release on dependency-management-data (DMD) to make managing the changelog a little easier, by taking Conventional Commits and converting them to a much nicer changelog.
While dependency-management-data is actively used in production by several organisations, it's still not stable, as I've still got some breaking changes and tweaks to internals that I'd like to do before I call it a stable interface, meaning that the release version is going to be v0.x.y.
As part of rolling out go-semantic-release, one thing I found was that that the default is to push stable release versions (a bad default, in my opinion) and so when I pushed the first commit using go-semantic-release, it detected that there wasn't a v1.0.0 release yet, and so seeing that there were changes to release, it pushed v1.0.0, instead of v0.64.x.
This was problematic for a few reasons - the first was that as I'd mentioned, I didn't want to call the current interface of dependency-management-data stable, but if we were now on the v1.x.x release train, I couldn't start pushing arbitrary changes as folks wouldn't expect there to be a breaking change in a stable version. Secondly, this was the Friday before Christmas, and just hours later I needed to start packing to go to my family's for the next few days, meaning I either needed to fix it now, or risk folks relying on the stability π¬
I also wasn't sure if I even would be able to redact the v1.0.0 release and continue pushing v0.x.y releases, or if Go would say that @latest always pointed to v1.x.y releases.
After some discussion on the Gopher Slack, it was clear that it wasn't clear to folks what should happen, so I set about testing it. The short answer is that yes, if you use the retract directive, that version can still be downloaded, but won't be discovered when i.e. using @latest.
It turns out that the official Go module documentation for the retract directive explains how to retract the version, and even says:
When a user runs
go get example.com/m@latest, thegocommand reads retractions fromv1.0.1, which is now the highest version. Bothv1.0.0andv1.0.1are retracted, so thegocommand will upgrade (or downgrade!) to the next highest version, perhapsv0.9.5.
In my slight panic, I'd not read that at the time, but it's good to know that it's there and super clear.
For example, let's say that I was on v0.1.0, and had accidentally published v1.0.0. To retract this version, we could perform these steps:
- Create a commit, on my default branch, which added a
retract v1.0.0statement - Tag that release as
v1.0.1 - Push that tag
- Run
go get $module@v1.0.1, to make sure that the Go module proxy fetches that particular version with the retraction - Create a commit, on my default branch, which adds a
retract v1.0.0andretract v1.0.1statement, to make sure both the original release, and the release with the retraction, are ignored - Tag that release as
v0.1.1 - Push that tag
- Run
go get $module@latest, which should then resolve tov0.1.1(some delay may be required for the module proxy to see the latest tag as@latest)
After this process, we're now able to correctly push to the v0.x.y release train.
In my case, I also deleted the tags in the repo, as otherwise go-semantic-release will see that there's a previous v1.x.y release, and continue versioning after that.
However, because we've go get'd the versions, the Go Module Proxy has the version cached.