Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
# Copyright 2017 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

import os
import textwrap

from pants.backend.docgen.targets.doc import Page
from pants.backend.docgen.tasks.markdown_to_html import MarkdownToHtml
from pants.base.exceptions import TaskError
from pants.task.task import Task
from pants.util import desktop
from pants.util.dirutil import safe_open

from pants.contrib.confluence.util.confluence_util import Confluence, ConfluenceError


# Copied from `pants.backend.docgen.tasks.confluence_publish`
# TODO: Rethink this. We shouldn't require subclassing this. Instead, the wiki identity should come
# from options. However if we decide against that, we should rename this ConfluencePublishBase.
class ConfluencePublish(Task):
    """A task to publish Page targets to Confluence wikis."""

    @classmethod
    def register_options(cls, register):
        super().register_options(register)

        # TODO: https://github.com/pantsbuild/pants/issues/395:
        # url should probably be a param of the wiki, not a config.
        register("--url", help="The url of the confluence site to post to.")
        register(
            "--force",
            type=bool,
            help="Force publish the page even if its contents is "
            "identical to the contents on confluence.",
        )
        register(
            "--open",
            type=bool,
            help="Attempt to open the published confluence wiki page in a browser.",
        )
        register("--user", help="Confluence user name, defaults to unix user.")

    @classmethod
    def prepare(cls, options, round_manager):
        round_manager.require(MarkdownToHtml.WIKI_HTML_PRODUCT)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.url = str(self.get_options().url)
        self.force = self.get_options().force
        self.open = self.get_options().open
        self._wiki = None
        self.user = str(self.get_options().user)

    def wiki(self):
        raise NotImplementedError(
            "Subclasses must provide the wiki target they are associated with"
        )

    def api(self):
        return "confluence1"

    def execute(self):
        if not self.url:
            raise TaskError(
                "Unable to proceed publishing to confluence. Please set the url option."
            )

        pages = []
        targets = self.context.targets()
        for target in targets:
            if isinstance(target, Page):
                for wiki_artifact in target.payload.provides:
                    pages.append((target, wiki_artifact))

        urls = list()

        genmap = self.context.products.get(MarkdownToHtml.WIKI_HTML_PRODUCT)
        for page, wiki_artifact in pages:
            html_info = genmap.get((wiki_artifact, page))
            if len(html_info) > 1:
                raise TaskError(f"Unexpected resources for {page}: {html_info}")
            basedir, htmls = list(html_info.items())[0]
            if len(htmls) != 1:
                raise TaskError(f"Unexpected resources for {page}: {htmls}")
            with safe_open(os.path.join(basedir, htmls[0]), "r") as contents:
                url = self.publish_page(
                    page.address,
                    wiki_artifact.config["space"],
                    wiki_artifact.config["title"],
                    contents.read(),
                    # Default to none if not present in the hash.
                    parent=wiki_artifact.config.get("parent"),
                )
                if url:
                    urls.append(url)
                    self.context.log.info(f"Published {page} to {url}")

        if self.open and urls:
            try:
                desktop.ui_open(*urls)
            except desktop.OpenError as e:
                raise TaskError(e)

    def publish_page(self, address, space, title, content, parent=None):
        body = (
            textwrap.dedent(
                """

                <!-- DO NOT EDIT - generated by pants from {} -->

                {}
                """
            )
            .strip()
            .format(address, content)
        )

        pageopts = dict(versionComment="updated by pants!")
        wiki = self.login()
        existing = wiki.getpage(space, title)
        if existing:
            if not self.force and existing["content"].strip() == body.strip():
                self.context.log.warn(f"Skipping publish of '{title}' - no changes")
                return

            pageopts["id"] = existing["id"]
            pageopts["version"] = existing["version"]

        try:
            page = wiki.create_html_page(space, title, body, parent, **pageopts)
            return page["url"]
        except ConfluenceError as e:
            raise TaskError(f"Failed to update confluence: {e!r}")

    def login(self):
        if not self._wiki:
            try:
                self._wiki = Confluence.login(self.url, self.user, self.api())
            except ConfluenceError as e:
                raise TaskError(f"Failed to login to confluence: {e!r}")
        return self._wiki