Repository URL to install this package:
|
Version:
1.26.0.dev0+gite506aa5f ▾
|
# 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