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