#!/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 = "ubuntu1804"

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())

#!/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 = "ubuntu1804"

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())

#!/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. # Hack to get search working # TODO: does not work with 404 pages in sub directories