content: add Publishing Go Modules article

Change-Id: I88fc170cbaca046caea7c66026024e503afb0d1e
Reviewed-on: https://go-review.googlesource.com/c/blog/+/197637
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/content/migrating-to-go-modules.article b/content/migrating-to-go-modules.article
index 162560d..6889fdc 100644
--- a/content/migrating-to-go-modules.article
+++ b/content/migrating-to-go-modules.article
@@ -5,7 +5,12 @@
 Jean de Klerk
 
 * Introduction
-This post is part 2 in a series. See part 1 — [[https://blog.golang.org/using-go-modules][Using Go Modules]].
+
+This post is part 2 in a series.
+
+- Part 1 — [[/using-go-modules][Using Go Modules]]
+- *Part*2*—*Migrating*To*Go*Modules* (this post)
+- Part 3 — [[/publishing-go-modules][Publishing Go Modules]]
 
 Go projects use a wide variety of dependency management strategies. [[https://golang.org/cmd/go/#hdr-Vendor_Directories][Vendoring]] tools such as [[https://github.com/golang/dep][dep]] and [[https://github.com/Masterminds/glide][glide]] are popular, but they have wide differences in behavior and don't always work well together. Some projects store their entire GOPATH directory in a single Git repository. Others simply rely on `go`get` and expect fairly recent versions of dependencies to be installed in GOPATH.
 
@@ -187,7 +192,14 @@
     $ git tag v1.2.0
     $ git push origin v1.2.0
 
-Your new `go.mod` file defines a canonical import path for your module and adds new minimum version requirements. If your users are already using the correct import path, and your dependencies haven't made breaking changes, then adding the `go.mod` file is backwards-compatible — but it's a significant change, and may expose existing problems. If you have existing version tags, you should increment the [[https://semver.org/#spec-item-7][minor version]].
+Your new `go.mod` file defines a canonical import path for your module and adds
+new minimum version requirements. If your users are already using the correct
+import path, and your dependencies haven't made breaking changes, then adding
+the `go.mod` file is backwards-compatible — but it's a significant change, and
+may expose existing problems. If you have existing version tags, you should
+increment the [[https://semver.org/#spec-item-7][minor version]]. See
+[[/publishing-go-modules][Publishing Go Modules]] to learn how to increment and
+publish versions.
 
 * Imports and canonical module paths
 
@@ -199,7 +211,7 @@
 
 * Conclusion
 
-Converting to Go modules should be a straightforward process for most users. Occasional issues may arise due to non-canonical import paths or breaking changes within a dependency. Future posts will explore publishing new versions, v2 and beyond, and ways to debug strange situations.
+Converting to Go modules should be a straightforward process for most users. Occasional issues may arise due to non-canonical import paths or breaking changes within a dependency. Future posts will explore [[/publishing-go-modules][publishing new versions]], v2 and beyond, and ways to debug strange situations.
 
 To provide feedback and help shape the future of dependency management in Go, please send us [[https://golang.org/issue/new][bug reports]] or [[https://golang.org/wiki/ExperienceReports][experience reports]].
 
diff --git a/content/publishing-go-modules.article b/content/publishing-go-modules.article
new file mode 100644
index 0000000..c9a37e5
--- /dev/null
+++ b/content/publishing-go-modules.article
@@ -0,0 +1,242 @@
+Publishing Go Modules
+26 Sep 2019
+Tags: tools, versioning
+
+Tyler Bui-Palsulich
+
+* Introduction
+
+This post is part 3 in a series.
+
+- Part 1 — [[/using-go-modules][Using Go Modules]]
+- Part 2 — [[/migrating-to-go-modules][Migrating To Go Modules]]
+- *Part*3*—*Publishing*Go*Modules* (this post)
+
+This post discusses how to write and publish modules so other modules can depend
+on them.
+
+Please note: this post covers development up to and including `v1`. A future
+article will cover developing a module at `v2` and beyond, which requires
+changing the module's path.
+
+This post uses [[https://git-scm.com/][Git]] in examples.
+[[https://www.mercurial-scm.org/][Mercurial]],
+[[http://wiki.bazaar.canonical.com/][Bazaar]], and others are supported as well.
+
+* Project setup
+
+For this post, you'll need an existing project to use as an example. So, start
+with the files from the end of the
+[[https://blog.golang.org/using-go-modules][Using Go Modules]] article:
+
+	$ cat go.mod
+	module example.com/hello
+
+	go 1.12
+
+	require rsc.io/quote/v3 v3.1.0
+
+	$ cat go.sum
+	golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
+	golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+	rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
+	rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+	rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+	rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+
+	$ cat hello.go
+	package hello
+
+	import "rsc.io/quote/v3"
+
+	func Hello() string {
+		return quote.HelloV3()
+	}
+
+	func Proverb() string {
+		return quote.Concurrency()
+	}
+
+	$ cat hello_test.go
+	package hello
+
+	import (
+		"testing"
+	)
+
+	func TestHello(t *testing.T) {
+		want := "Hello, world."
+		if got := Hello(); got != want {
+			t.Errorf("Hello() = %q, want %q", got, want)
+		}
+	}
+
+	func TestProverb(t *testing.T) {
+		want := "Concurrency is not parallelism."
+		if got := Proverb(); got != want {
+			t.Errorf("Proverb() = %q, want %q", got, want)
+		}
+	}
+
+	$
+
+Next, create a new `git` repository and add an initial commit. If you're
+publishing your own project, be sure to include a `LICENSE` file. Change to the
+directory containing the `go.mod` then create the repo:
+
+	$ git init
+	$ git add LICENSE go.mod go.sum hello.go hello_test.go
+	$ git commit -m "hello: initial commit"
+	$
+
+* Semantic versions and modules
+
+Every required module in a `go.mod` has a
+[[https://semver.org][semantic version]], the minimum version of that dependency
+to use to build the module.
+
+A semantic version has the form `vMAJOR.MINOR.PATCH`.
+
+- Increment the `MAJOR` version when you make a [[https://golang.org/doc/go1compat][backwards incompatible]] change to the public API of your module. This should only be done when absolutely necessary.
+- Increment the `MINOR` version when you make a backwards compatible change to the API, like changing dependencies or adding a new function, method, struct field, or type.
+- Increment the `PATCH` version after making minor changes that don't affect your module's public API or dependencies, like fixing a bug.
+
+You can specify pre-release versions by appending a hyphen and dot separated
+identifiers (for example, `v1.0.1-alpha` or `v2.2.2-beta.2`). Normal releases
+are preferred by the `go` command over pre-release versions, so users must ask
+for pre-release versions explicitly (for example,
+`go`get`example.com/hello@v1.0.1-alpha`) if your module has any normal releases.
+
+`v0` major versions and pre-release versions do not guarantee backwards
+compatibility. They let you refine your API before making stability commitments
+to your users. However, `v1` major versions and beyond require backwards
+compatibility within that major version.
+
+The version referenced in a `go.mod` may be an explicit release tagged in the
+repository (for example, `v1.5.2`), or it may be a
+[[https://golang.org/cmd/go/#hdr-Pseudo_versions][pseudo-version]] based on a
+specific commit (for example, `v0.0.0-20170915032832-14c0d48ead0c`).
+Pseudo-versions are a special type of pre-release version. Pseudo-versions are
+useful when a user needs to depend on a project that has not published any
+semantic version tags, or develop against a commit that hasn't been tagged yet,
+but users should not assume that pseudo-versions provide a stable or well-tested
+API. Tagging your modules with explicit versions signals to your users that
+specific versions are fully tested and ready to use.
+
+Once you start tagging your repo with versions, it's important to keep tagging
+new releases as you develop your module. When users request a new version of
+your module (with `go`get`-u` or `go`get`example.com/hello`), the `go` command
+will choose the greatest semantic release version available, even if that
+version is several years old and many changes behind the primary branch.
+Continuing to tag new releases will make your ongoing improvements available to
+your users.
+
+Do not delete version tags from your repo. If you find a bug or a security issue
+with a version, release a new version. If people depend on a version that you
+have deleted, their builds may fail. Similarly, once you release a version, do
+not change or overwrite it. The
+[[https://blog.golang.org/module-mirror-launch][module mirror and checksum database]]
+store modules, their versions, and signed cryptographic hashes to ensure that
+the build of a given version remains reproducible over time.
+
+* v0: the initial, unstable version
+
+Let's tag the module with a `v0` semantic version. A `v0` version does not make
+any stability guarantees, so nearly all projects should start with `v0` as they
+refine their public API.
+
+Tagging a new version has a few steps:
+
+1. Run `go`mod`tidy`, which removes any dependencies the module might have accumulated that are no longer necessary.
+
+2. Run `go`test`./...` a final time to make sure everything is working.
+
+3. Tag the project with a new version using [[https://git-scm.com/docs/git-tag][`git`tag`]].
+
+4. Push the new tag to the origin repository.
+
+	$ go mod tidy
+	$ go test ./...
+	ok      example.com/hello       0.015s
+	$ git add go.mod go.sum hello.go hello_test.go
+	$ git commit -m "hello: changes for v0.1.0"
+	$ git tag v0.1.0
+	$ git push origin v0.1.0
+	$
+
+Now other projects can depend on `v0.1.0` of `example.com/hello`. For your own
+module, you can run `go`list`-m`example.com/hello@v0.1.0` to confirm the latest
+version is available (this example module does not exist, so no versions are
+available). If you don't see the latest version immediately and you're using the
+Go module proxy (the default since Go 1.13), try again in a few minutes to give
+the proxy time to load the new version.
+
+If you add to the public API, make a breaking change to a `v0` module, or
+upgrade the minor or version of one of your dependencies,  increment the `MINOR`
+version for your next release. For example, the next release after `v0.1.0`
+would be `v0.2.0`.
+
+If you fix a bug in an existing version, increment the `PATCH` version. For
+example, the next release after `v0.1.0` would be `v0.1.1`.
+
+* v1: the first stable version
+
+Once you are absolutely sure your module's API is stable, you can release
+`v1.0.0`. A `v1` major version communicates to users that no incompatible
+changes will be made to the module's API. They can upgrade to new `v1` minor and
+patch releases, and their code should not break. Function and method signatures
+will not change, exported types will not be removed, and so on. If there are
+changes to the API, they will be backwards compatible (for example, adding a new
+field to a struct) and will be included in a new minor release. If there are bug
+fixes (for example, a security fix), they will be included in a patch release
+(or as part of a minor release).
+
+Sometimes, maintaining backwards compatibility can lead to awkward APIs. That's
+OK. An imperfect API is better than breaking users' existing code.
+
+The standard library's `strings` package is a prime example of maintaining
+backwards compatibility at the cost of API consistency.
+
+- [[https://godoc.org/strings#Split][`Split`]] slices a string into all substrings separated by a separator and returns a slice of the substrings between those separators.
+- [[https://godoc.org/strings#SplitN][`SplitN`]] can be used to control the number of substrings to return.
+
+However, [[https://godoc.org/strings#Replace][`Replace`]] took a count of how
+many instances of the string to replace from the beginning (unlike `Split`).
+
+Given `Split` and `SplitN`, you would expect functions like `Replace` and
+`ReplaceN`. But, we couldn't change the existing `Replace` without breaking
+callers, which we promised not to do. So, in Go 1.12, we added a new function,
+[[https://godoc.org/strings#ReplaceAll][`ReplaceAll`]]. The resulting API is a
+little odd, since `Split` and `Replace` behave differently, but that
+inconsistency is better than a breaking change.
+
+Let's say you're happy with the API of `example.com/hello` and you want to
+release `v1` as the first stable version.
+
+Tagging `v1` uses the same process as tagging a `v0` version: run `go`mod`tidy`
+and `go`test`./...`, tag the version, and push the tag to the origin repository:
+
+	$ go mod tidy
+	$ go test ./...
+	ok      example.com/hello       0.015s
+	$ git add go.mod go.sum hello.go hello_test.go
+	$ git commit -m "hello: changes for v1.0.0"
+	$ git tag v1.0.0
+	$ git push origin v1.0.0
+	$
+
+At this point, the `v1` API of `example.com/hello` is solidified. This
+communicates to everyone that our API is stable and they should feel comfortable
+using it.
+
+* Conclusion
+
+This post walked through the process of tagging a module with semantic versions
+and when to release `v1`. A future post will cover how to maintain and publish
+modules at `v2` and beyond.
+
+To provide feedback and help shape the future of dependency management in Go,
+please send us [[https://golang.org/issue/new][bug reports]] or
+[[https://golang.org/wiki/ExperienceReports][experience reports]].
+
+Thanks for all your feedback and help improving Go modules.
diff --git a/content/using-go-modules.article b/content/using-go-modules.article
index 0c146c8..c5380ee 100644
--- a/content/using-go-modules.article
+++ b/content/using-go-modules.article
@@ -7,7 +7,12 @@
 Eno Compton
 
 * Introduction
-This post is part 1 in a series. See part 2 — [[https://blog.golang.org/migrating-to-go-modules][Migrating to Go Modules]].
+
+This post is part 1 in a series.
+
+- *Part*1*—*Using*Go*Modules* (this post)
+- Part 2 — [[/migrating-to-go-modules][Migrating To Go Modules]]
+- Part 3 — [[/publishing-go-modules][Publishing Go Modules]]
 
 Go 1.11 and 1.12 include preliminary
 [[https://golang.org/doc/go1.11#modules][support for modules]],