docs: include changelog and contributing page in generated docs. (#1617)

This better unifies where docs can be viewed.

Also deletes some mentions of having to generate the docs manually.
diff --git a/BUILD.bazel b/BUILD.bazel
index 8dd2242..007e524 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -24,6 +24,11 @@
     "version.bzl",
 ])
 
+exports_files(
+    glob(["*.md"]),
+    visibility = ["//docs:__subpackages__"],
+)
+
 filegroup(
     name = "distribution",
     srcs = [
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bf3a496..c6532d9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,10 +65,6 @@
 them are slow. If you're working on a particular area of code, you can run just
 the tests in those directories instead, which can speed up your edit-run cycle.
 
-Note that there are tests to verify generated documentation is correct -- if
-you're modifying the signature of a public function, these tests will likely
-fail and you'll need to [regenerate the api docs](#documentation).
-
 ## Formatting
 
 Starlark files should be formatted by
@@ -150,17 +146,6 @@
 Some checked-in files are generated and need to be updated when a new PR is
 merged.
 
-### Documentation
-
-To regenerate the content under the `docs/` directory, run this command:
-
-```shell
-bazel run //docs:update
-```
-
-This needs to be done whenever the docstrings in the corresponding .bzl files
-are changed; a test failure will remind you to run this command when needed.
-
 ## Core rules
 
 The bulk of this repo is owned and maintained by the Bazel Python community.
diff --git a/docs/sphinx/BUILD.bazel b/docs/sphinx/BUILD.bazel
index 832a58e..95b3cfa 100644
--- a/docs/sphinx/BUILD.bazel
+++ b/docs/sphinx/BUILD.bazel
@@ -55,6 +55,10 @@
     formats = [
         "html",
     ],
+    renamed_srcs = {
+        "//:CHANGELOG.md": "changelog.md",
+        "//:CONTRIBUTING.md": "contributing.md",
+    },
     sphinx = ":sphinx-build",
     strip_prefix = package_name() + "/",
     tags = ["docs"],
diff --git a/docs/sphinx/index.md b/docs/sphinx/index.md
index a84dab5..bec652a 100644
--- a/docs/sphinx/index.md
+++ b/docs/sphinx/index.md
@@ -60,6 +60,8 @@
 pip
 coverage
 gazelle
+Contributing <contributing>
+Changelog <changelog>
 api/index
 glossary
 genindex
diff --git a/sphinxdocs/private/sphinx.bzl b/sphinxdocs/private/sphinx.bzl
index 8b3244b..daff02d 100644
--- a/sphinxdocs/private/sphinx.bzl
+++ b/sphinxdocs/private/sphinx.bzl
@@ -45,7 +45,17 @@
         **kwargs
     )
 
-def sphinx_docs(name, *, srcs = [], sphinx, config, formats, strip_prefix = "", extra_opts = [], **kwargs):
+def sphinx_docs(
+        name,
+        *,
+        srcs = [],
+        renamed_srcs = {},
+        sphinx,
+        config,
+        formats,
+        strip_prefix = "",
+        extra_opts = [],
+        **kwargs):
     """Generate docs using Sphinx.
 
     This generates three public targets:
@@ -62,6 +72,9 @@
     Args:
         name: (str) name of the docs rule.
         srcs: (label list) The source files for Sphinx to process.
+        renamed_srcs: (label_keyed_string_dict) Doc source files for Sphinx that
+            are renamed. This is typically used for files elsewhere, such as top
+            level files in the repo.
         sphinx: (label) the Sphinx tool to use for building
             documentation. Because Sphinx supports various plugins, you must
             construct your own binary with the necessary dependencies. The
@@ -83,6 +96,7 @@
     _sphinx_docs(
         name = name,
         srcs = srcs,
+        renamed_srcs = renamed_srcs,
         sphinx = sphinx,
         config = config,
         formats = formats,
@@ -143,6 +157,12 @@
                   "other options, but before the source/output args.",
         ),
         "formats": attr.string_list(doc = "Output formats for Sphinx to create."),
+        "renamed_srcs": attr.label_keyed_string_dict(
+            allow_files = True,
+            doc = "Doc source files for Sphinx that are renamed. This is " +
+                  "typically used for files elsewhere, such as top level " +
+                  "files in the repo.",
+        ),
         "sphinx": attr.label(
             executable = True,
             cfg = "exec",
@@ -189,6 +209,23 @@
     for orig_file in ctx.files.srcs:
         _symlink_source(orig_file)
 
+    for src_target, dest in ctx.attr.renamed_srcs.items():
+        src_files = src_target.files.to_list()
+        if len(src_files) != 1:
+            fail("A single file must be specified to be renamed. Target {} " +
+                 "generate {} files: {}".format(
+                     src_target,
+                     len(src_files),
+                     src_files,
+                 ))
+        sphinx_src = ctx.actions.declare_file(paths.join(source_prefix, dest))
+        ctx.actions.symlink(
+            output = sphinx_src,
+            target_file = src_files[0],
+            progress_message = "Symlinking (renamed) Sphinx source %{input} to %{output}",
+        )
+        sphinx_source_files.append(sphinx_src)
+
     return sphinx_source_dir_path, source_conf_file, sphinx_source_files
 
 def _run_sphinx(ctx, format, source_path, inputs, output_prefix):