gh_deploy.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import logging
  2. import subprocess
  3. import os
  4. import re
  5. from pkg_resources import parse_version
  6. import mkdocs
  7. from mkdocs.utils import ghp_import
  8. log = logging.getLogger(__name__)
  9. default_message = """Deployed {sha} with MkDocs version: {version}"""
  10. def _is_cwd_git_repo():
  11. try:
  12. proc = subprocess.Popen(
  13. ['git', 'rev-parse', '--is-inside-work-tree'],
  14. stdout=subprocess.PIPE,
  15. stderr=subprocess.PIPE
  16. )
  17. except FileNotFoundError:
  18. log.error("Could not find git - is it installed and on your path?")
  19. raise SystemExit(1)
  20. proc.communicate()
  21. return proc.wait() == 0
  22. def _get_current_sha(repo_path):
  23. proc = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], cwd=repo_path,
  24. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  25. stdout, _ = proc.communicate()
  26. sha = stdout.decode('utf-8').strip()
  27. return sha
  28. def _get_remote_url(remote_name):
  29. # No CNAME found. We will use the origin URL to determine the GitHub
  30. # pages location.
  31. remote = "remote.%s.url" % remote_name
  32. proc = subprocess.Popen(["git", "config", "--get", remote],
  33. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  34. stdout, _ = proc.communicate()
  35. url = stdout.decode('utf-8').strip()
  36. host = None
  37. path = None
  38. if 'github.com/' in url:
  39. host, path = url.split('github.com/', 1)
  40. elif 'github.com:' in url:
  41. host, path = url.split('github.com:', 1)
  42. return host, path
  43. def _check_version(branch):
  44. proc = subprocess.Popen(['git', 'show', '-s', '--format=%s', 'refs/heads/{}'.format(branch)],
  45. stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  46. stdout, _ = proc.communicate()
  47. msg = stdout.decode('utf-8').strip()
  48. m = re.search(r'\d+(\.\d+)+((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?', msg, re.X | re.I)
  49. previousv = parse_version(m.group()) if m else None
  50. currentv = parse_version(mkdocs.__version__)
  51. if not previousv:
  52. log.warning('Version check skipped: No version specified in previous deployment.')
  53. elif currentv > previousv:
  54. log.info(
  55. 'Previous deployment was done with MkDocs version {}; '
  56. 'you are deploying with a newer version ({})'.format(previousv, currentv)
  57. )
  58. elif currentv < previousv:
  59. log.error(
  60. 'Deployment terminated: Previous deployment was made with MkDocs version {}; '
  61. 'you are attempting to deploy with an older version ({}). Use --ignore-version '
  62. 'to deploy anyway.'.format(previousv, currentv)
  63. )
  64. raise SystemExit(1)
  65. def gh_deploy(config, message=None, force=False, ignore_version=False):
  66. if not _is_cwd_git_repo():
  67. log.error('Cannot deploy - this directory does not appear to be a git '
  68. 'repository')
  69. remote_branch = config['remote_branch']
  70. remote_name = config['remote_name']
  71. if not ignore_version:
  72. _check_version(remote_branch)
  73. if message is None:
  74. message = default_message
  75. sha = _get_current_sha(os.path.dirname(config.config_file_path))
  76. message = message.format(version=mkdocs.__version__, sha=sha)
  77. log.info("Copying '%s' to '%s' branch and pushing to GitHub.",
  78. config['site_dir'], config['remote_branch'])
  79. result, error = ghp_import.ghp_import(config['site_dir'], message, remote_name,
  80. remote_branch, force)
  81. if not result:
  82. log.error("Failed to deploy to GitHub with error: \n%s", error)
  83. raise SystemExit(1)
  84. else:
  85. cname_file = os.path.join(config['site_dir'], 'CNAME')
  86. # Does this repository have a CNAME set for GitHub pages?
  87. if os.path.isfile(cname_file):
  88. # This GitHub pages repository has a CNAME configured.
  89. with(open(cname_file, 'r')) as f:
  90. cname_host = f.read().strip()
  91. log.info('Based on your CNAME file, your documentation should be '
  92. 'available shortly at: http://%s', cname_host)
  93. log.info('NOTE: Your DNS records must be configured appropriately for '
  94. 'your CNAME URL to work.')
  95. return
  96. host, path = _get_remote_url(remote_name)
  97. if host is None:
  98. # This could be a GitHub Enterprise deployment.
  99. log.info('Your documentation should be available shortly.')
  100. else:
  101. username, repo = path.split('/', 1)
  102. if repo.endswith('.git'):
  103. repo = repo[:-len('.git')]
  104. url = 'https://{}.github.io/{}/'.format(username, repo)
  105. log.info('Your documentation should shortly be available at: ' + url)