xref: /aosp_15_r20/external/bazel-skylib/docs/private/stardoc_with_diff_test.bzl (revision bcb5dc7965af6ee42bf2f21341a2ec00233a8c8a)
1# Copyright 2022 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Helpers for keeping stardoc documentation up-to-date.
16
17These are currently a private API in bazel-skylib.
18See discussion:
19https://github.com/bazelbuild/bazel-skylib/pull/321#issuecomment-1081166216
20
21If you need a similar feature, you can consider using a similar rule
22available from a third-party:
23https://github.com/aspect-build/bazel-lib/blob/main/docs/docs.md
24"""
25
26load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
27load("@bazel_skylib//rules:write_file.bzl", "write_file")
28load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc")
29
30def stardoc_with_diff_test(
31        name,
32        bzl_library_target,
33        out_label):
34    """Creates a stardoc target coupled with a `diff_test` for a given `bzl_library`.
35
36    This is helpful for minimizing boilerplate in repos with lots of stardoc targets.
37
38    Args:
39        name: the stardoc target name
40        bzl_library_target: the label of the `bzl_library` target to generate documentation for
41        out_label: the label of the output MD file
42    """
43    out_file = out_label.replace("//", "").replace(":", "/")
44
45    # Generate MD from .bzl
46    stardoc(
47        name = name,
48        out = out_file.replace(".md", "-docgen.md"),
49        input = bzl_library_target + ".bzl",
50        deps = [bzl_library_target],
51    )
52
53    # Ensure that the generated MD has been updated in the local source tree
54    diff_test(
55        name = out_file.replace("/", "_").replace(".md", "-difftest"),
56        failure_message = "Please run \"bazel run //docs:update\"",
57        # Source file
58        file1 = out_label,
59        # Output from stardoc rule above
60        file2 = out_file.replace(".md", "-docgen.md"),
61        tags = ["no_windows"],
62    )
63
64def update_docs(
65        name = "update",
66        docs_folder = "docs"):
67    """Creates a `sh_binary` target which copies over generated doc files to the local source tree.
68
69    This is to be used in tandem with `stardoc_with_diff_test()` to produce a convenient workflow
70    for generating, testing, and updating all doc files as follows:
71
72    ``` bash
73    bazel build //{docs_folder}/... && bazel test //{docs_folder}/... && bazel run //{docs_folder}:update
74    ```
75
76    eg.
77
78    ``` bash
79    bazel build //docs/... && bazel test //docs/... && bazel run //docs:update
80    ```
81
82    The `update_docs()` invocation must come after/below any `stardoc_with_diff_test()` invocations
83    in the BUILD file.
84
85    Args:
86        name: the name of the `sh_binary` target
87        docs_folder: the name of the folder containing the doc files in the local source tree
88    """
89    content = ["#!/usr/bin/env bash", "cd ${BUILD_WORKSPACE_DIRECTORY}"]
90    data = []
91    for r in native.existing_rules().values():
92        if r["kind"] == "stardoc_markdown_renderer":
93            doc_gen = r["out"]
94            if doc_gen.startswith(":"):
95                doc_gen = doc_gen[1:]
96            doc_dest = doc_gen.replace("-docgen.md", ".md")
97            data.append(doc_gen)
98            content.append("cp -fv bazel-bin/{0}/{1} {2}".format(docs_folder, doc_gen, doc_dest))
99
100    update_script = name + ".sh"
101    write_file(
102        name = "gen_" + name,
103        out = update_script,
104        content = content,
105    )
106
107    native.sh_binary(
108        name = name,
109        srcs = [update_script],
110        data = data,
111    )
112