| #!/usr/bin/env python3 | |
| # | |
| # Copyright 2021 The Bazel Authors. All rights reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| import collections | |
| import os | |
| import shutil | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import bazelci | |
| DEFAULT_FLAGS = ["--action_env=PATH=/usr/local/bin:/usr/bin:/bin", "--sandbox_tmpfs_path=/tmp"] | |
| PLATFORM = "ubuntu2404" | |
| Settings = collections.namedtuple( | |
| "Settings", | |
| ["target", "build_flags", "output_dir", "gcs_bucket", "gcs_subdir", "landing_page", "rewrite"], | |
| ) | |
| BUILDKITE_BUILD_NUMBER = os.getenv("BUILDKITE_BUILD_NUMBER") | |
| def rewrite_staging_urls(content): | |
| new_content = content.replace( | |
| "docs.bazel.build", "docs-staging.bazel.build/{}".format(BUILDKITE_BUILD_NUMBER) | |
| ) | |
| # Hack to get search working | |
| new_content = new_content.replace("009927877080525621790:2pxlpaexqpc", "12ee759976b5ec02f", 1) | |
| return new_content.replace('"/', '"/{}/'.format(BUILDKITE_BUILD_NUMBER)) | |
| DOCGEN_SETTINGS = { | |
| "bazel-trusted": { | |
| "https://github.com/bazelbuild/bazel.git": Settings( | |
| target="//site", | |
| build_flags=[], | |
| output_dir="bazel-bin/site/site-build", | |
| gcs_bucket="docs.bazel.build", | |
| gcs_subdir="", | |
| landing_page="versions/master/bazel-overview.html", | |
| rewrite=None, | |
| ), | |
| "https://github.com/bazelbuild/bazel-blog.git": Settings( | |
| target="//:site", | |
| build_flags=[], | |
| output_dir="bazel-bin/site-build", | |
| gcs_bucket="blog.bazel.build", | |
| gcs_subdir="", | |
| landing_page="index.html", | |
| rewrite=None, | |
| ), | |
| "https://github.com/bazelbuild/bazel-website.git": Settings( | |
| target="//:site", | |
| build_flags=[], | |
| output_dir="bazel-bin/site-build", | |
| gcs_bucket="www.bazel.build", | |
| gcs_subdir="", | |
| landing_page="index.html", | |
| rewrite=None, | |
| ), | |
| }, | |
| "bazel": { | |
| "https://bazel.googlesource.com/bazel.git": Settings( | |
| target="//site", | |
| build_flags=bazelci.remote_caching_flags(PLATFORM), | |
| output_dir="bazel-bin/site/site-build", | |
| gcs_bucket="docs-staging.bazel.build", | |
| gcs_subdir=BUILDKITE_BUILD_NUMBER, | |
| landing_page="versions/master/bazel-overview.html", | |
| rewrite=rewrite_staging_urls, | |
| ), | |
| }, | |
| } | |
| def rewrite_and_copy(src_root, dest_root, rewrite): | |
| for src_dir, dirs, files in os.walk(src_root): | |
| dest_dir = src_dir.replace(src_root, dest_root, 1) | |
| os.mkdir(dest_dir) | |
| for filename in files: | |
| src_file = os.path.join(src_dir, filename) | |
| dest_file = os.path.join(dest_dir, filename) | |
| if src_file.endswith(".html"): | |
| with open(src_file, "r", encoding="utf-8") as src: | |
| content = src.read() | |
| with open(dest_file, "w", encoding="utf-8") as dest: | |
| dest.write(rewrite(content)) | |
| else: | |
| shutil.copyfile(src_file, dest_file) | |
| def get_destination(bucket, subdir): | |
| if not subdir: | |
| return bucket | |
| return "{}/{}".format(bucket, subdir) | |
| def get_url(settings): | |
| return "https://{}/{}".format( | |
| get_destination(settings.gcs_bucket, settings.gcs_subdir), settings.landing_page | |
| ) | |
| def main(argv=None): | |
| org = os.getenv("BUILDKITE_ORGANIZATION_SLUG") | |
| repo = os.getenv("BUILDKITE_REPO") | |
| settings = DOCGEN_SETTINGS.get(org, {}).get(repo) | |
| if not settings: | |
| bazelci.eprint("docgen is not enabled for '%s' org and repository %s", org, repo) | |
| return 1 | |
| bazelci.print_expanded_group(":bazel: Building documentation from {}".format(repo)) | |
| try: | |
| bazelci.execute_command( | |
| ["bazel", "build"] + DEFAULT_FLAGS + settings.build_flags + [settings.target] | |
| ) | |
| except subprocess.CalledProcessError as e: | |
| bazelci.eprint("Bazel failed with exit code {}".format(e.returncode)) | |
| return e.returncode | |
| src_root = os.path.join(os.getcwd(), settings.output_dir) | |
| if settings.rewrite: | |
| bazelci.print_expanded_group(":bazel: Rewriting links in documentation files") | |
| dest_root = os.path.join(tempfile.mkdtemp(), "site") | |
| rewrite_and_copy(src_root, dest_root, settings.rewrite) | |
| src_root = dest_root | |
| bucket = "gs://{}".format(settings.gcs_bucket) | |
| dest = get_destination(bucket, settings.gcs_subdir) | |
| bazelci.print_expanded_group(":bazel: Uploading documentation to {}".format(dest)) | |
| try: | |
| bazelci.execute_command(["gsutil", "-m", "rsync", "-r", "-c", "-d", src_root, dest]) | |
| bazelci.execute_command( | |
| ["gsutil", "web", "set", "-m", "index.html", "-e", "404.html", bucket] | |
| ) | |
| # TODO: does not work with 404 pages in sub directories | |
| except subprocess.CalledProcessError as e: | |
| bazelci.eprint("Upload to GCS failed with exit code {}".format(e.returncode)) | |
| return e.returncode | |
| bazelci.print_collapsed_group(":bazel: Publishing documentation URL") | |
| message = "You can find the documentation at {}".format(get_url(settings)) | |
| bazelci.execute_command( | |
| ["buildkite-agent", "annotate", "--style=info", message, "--context", "doc_url"] | |
| ) | |
| bazelci.execute_command(["buildkite-agent", "meta-data", "set", "message", message]) | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) |