aboutsummaryrefslogtreecommitdiffstats
path: root/nikola/plugins/command/github_deploy.py
diff options
context:
space:
mode:
authorLibravatarAgustin Henze <tin@sluc.org.ar>2015-07-08 07:35:02 -0300
committerLibravatarAgustin Henze <tin@sluc.org.ar>2015-07-08 07:35:02 -0300
commitb0b24795b24ee6809397fbbadf42f31f310a219f (patch)
tree46d05bb47460b4ec679211717c4ab07414b80d9c /nikola/plugins/command/github_deploy.py
parent5ec02211214350ee558fd9f6bb052264fd24f75e (diff)
Imported Upstream version 7.6.0upstream/7.6.0
Diffstat (limited to 'nikola/plugins/command/github_deploy.py')
-rw-r--r--nikola/plugins/command/github_deploy.py220
1 files changed, 39 insertions, 181 deletions
diff --git a/nikola/plugins/command/github_deploy.py b/nikola/plugins/command/github_deploy.py
index 13da48c..888a4f9 100644
--- a/nikola/plugins/command/github_deploy.py
+++ b/nikola/plugins/command/github_deploy.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2014 Puneeth Chaganti and others.
+# Copyright © 2014-2015 Puneeth Chaganti and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -25,15 +25,15 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from __future__ import print_function
+from datetime import datetime
+import io
import os
-import shutil
import subprocess
-import sys
from textwrap import dedent
from nikola.plugin_categories import Command
from nikola.plugins.command.check import real_scan_files
-from nikola.utils import ask_yesno, get_logger
+from nikola.utils import get_logger, req_missing, makedirs, unicode_str
from nikola.__main__ import main
from nikola import __version__
@@ -43,79 +43,53 @@ def uni_check_output(*args, **kwargs):
return o.decode('utf-8')
+def check_ghp_import_installed():
+ try:
+ subprocess.check_output(['ghp-import', '-h'])
+ except OSError:
+ # req_missing defaults to `python=True` — and it’s meant to be like this.
+ # `ghp-import` is installed via pip, but the only way to use it is by executing the script it installs.
+ req_missing(['ghp-import'], 'deploy the site to GitHub Pages')
+
+
class CommandGitHubDeploy(Command):
- """ Deploy site to GitHub pages. """
+ """ Deploy site to GitHub Pages. """
name = 'github_deploy'
doc_usage = ''
- doc_purpose = 'deploy the site to GitHub pages'
+ doc_purpose = 'deploy the site to GitHub Pages'
doc_description = dedent(
"""\
- This command can be used to deploy your site to GitHub pages.
- It performs the following actions:
+ This command can be used to deploy your site to GitHub Pages.
- 1. Ensure that your site is a git repository, and git is on the PATH.
- 2. Ensure that the output directory is not committed on the
- source branch.
- 3. Check for changes, and prompt the user to continue, if required.
- 4. Build the site
- 5. Clean any files that are "unknown" to Nikola.
- 6. Create a deploy branch, if one doesn't exist.
- 7. Commit the output to this branch. (NOTE: Any untracked source
- files, may get committed at this stage, on the wrong branch!)
- 8. Push and deploy!
+ It uses ghp-import to do this task.
- NOTE: This command needs your site to be a git repository, with a
- master branch (or a different branch, configured using
- GITHUB_SOURCE_BRANCH if you are pushing to user.github
- .io/organization.github.io pages) containing the sources of your
- site. You also, obviously, need to have `git` on your PATH,
- and should be able to push to the repository specified as the remote
- (origin, by default).
"""
)
logger = None
- _deploy_branch = ''
- _source_branch = ''
- _remote_name = ''
-
def _execute(self, command, args):
self.logger = get_logger(
CommandGitHubDeploy.name, self.site.loghandlers
)
- self._source_branch = self.site.config.get(
- 'GITHUB_SOURCE_BRANCH', 'master'
- )
- self._deploy_branch = self.site.config.get(
- 'GITHUB_DEPLOY_BRANCH', 'gh-pages'
- )
- self._remote_name = self.site.config.get(
- 'GITHUB_REMOTE_NAME', 'origin'
- )
-
- self._ensure_git_repo()
-
- self._exit_if_output_committed()
- if not self._prompt_continue():
- return
+ # Check if ghp-import is installed
+ check_ghp_import_installed()
+ # Build before deploying
build = main(['build'])
if build != 0:
self.logger.error('Build failed, not deploying to GitHub')
- sys.exit(build)
+ return build
+ # Clean non-target files
only_on_output, _ = real_scan_files(self.site)
for f in only_on_output:
os.unlink(f)
- self._checkout_deploy_branch()
-
- self._copy_output()
-
+ # Commit and push
self._commit_and_push()
return
@@ -123,150 +97,34 @@ class CommandGitHubDeploy(Command):
def _commit_and_push(self):
""" Commit all the files and push. """
- deploy = self._deploy_branch
- source = self._source_branch
- remote = self._remote_name
-
+ source = self.site.config['GITHUB_SOURCE_BRANCH']
+ deploy = self.site.config['GITHUB_DEPLOY_BRANCH']
+ remote = self.site.config['GITHUB_REMOTE_NAME']
source_commit = uni_check_output(['git', 'rev-parse', source])
commit_message = (
'Nikola auto commit.\n\n'
'Source commit: %s'
'Nikola version: %s' % (source_commit, __version__)
)
-
- commands = [
- ['git', 'pull', remote, '%s:%s' % (deploy, deploy)],
- ['git', 'add', '-A'],
- ['git', 'commit', '-m', commit_message],
- ['git', 'push', remote, '%s:%s' % (deploy, deploy)],
- ['git', 'checkout', source],
- ]
-
- for command in commands:
- self.logger.info("==> {0}".format(command))
- try:
- subprocess.check_call(command)
- except subprocess.CalledProcessError as e:
- self.logger.error(
- 'Failed GitHub deployment — command {0} '
- 'returned {1}'.format(e.cmd, e.returncode)
- )
- sys.exit(e.returncode)
-
- def _copy_output(self):
- """ Copy all output to the top level directory. """
output_folder = self.site.config['OUTPUT_FOLDER']
- for each in os.listdir(output_folder):
- if os.path.exists(each):
- if os.path.isdir(each):
- shutil.rmtree(each)
-
- else:
- os.unlink(each)
-
- shutil.move(os.path.join(output_folder, each), '.')
-
- def _checkout_deploy_branch(self):
- """ Check out the deploy branch
-
- Creates an orphan branch if not present.
-
- """
- deploy = self._deploy_branch
+ command = ['ghp-import', '-n', '-m', commit_message, '-p', '-r', remote, '-b', deploy, output_folder]
+ self.logger.info("==> {0}".format(command))
try:
- subprocess.check_call(
- [
- 'git', 'show-ref', '--verify', '--quiet',
- 'refs/heads/%s' % deploy
- ]
- )
- except subprocess.CalledProcessError:
- self._create_orphan_deploy_branch()
- else:
- subprocess.check_call(['git', 'checkout', deploy])
-
- def _create_orphan_deploy_branch(self):
- """ Create an orphan deploy branch """
-
- result = subprocess.check_call(
- ['git', 'checkout', '--orphan', self._deploy_branch]
- )
- if result != 0:
- self.logger.error('Failed to create a deploy branch')
- sys.exit(1)
-
- result = subprocess.check_call(['git', 'rm', '-rf', '.'])
- if result != 0:
- self.logger.error('Failed to create a deploy branch')
- sys.exit(1)
-
- with open('.gitignore', 'w') as f:
- f.write('%s\n' % self.site.config['OUTPUT_FOLDER'])
- f.write('%s\n' % self.site.config['CACHE_FOLDER'])
- f.write('*.pyc\n')
- f.write('*.db\n')
-
- subprocess.check_call(['git', 'add', '.gitignore'])
- subprocess.check_call(['git', 'commit', '-m', 'Add .gitignore'])
-
- def _ensure_git_repo(self):
- """ Ensure that the site is a git-repo.
-
- Also make sure that a remote with the specified name exists.
-
- """
-
- try:
- remotes = uni_check_output(['git', 'remote'])
+ subprocess.check_call(command)
except subprocess.CalledProcessError as e:
- self.logger.notice('github_deploy needs a git repository!')
- sys.exit(e.returncode)
- except OSError as e:
- import errno
- self.logger.error('Running git failed with {0}'.format(e))
- if e.errno == errno.ENOENT:
- self.logger.notice('Is git on the PATH?')
- sys.exit(1)
- else:
- if self._remote_name not in remotes:
- self.logger.error(
- 'Need a remote called "%s" configured' % self._remote_name
- )
- sys.exit(1)
-
- def _exit_if_output_committed(self):
- """ Exit if the output folder is committed on the source branch. """
-
- source = self._source_branch
- subprocess.check_call(['git', 'checkout', source])
-
- output_folder = self.site.config['OUTPUT_FOLDER']
- output_log = uni_check_output(
- ['git', 'ls-files', '--', output_folder]
- )
-
- if len(output_log.strip()) > 0:
self.logger.error(
- 'Output folder is committed on the source branch. '
- 'Cannot proceed until it is removed.'
+ 'Failed GitHub deployment — command {0} '
+ 'returned {1}'.format(e.cmd, e.returncode)
)
- sys.exit(1)
-
- def _prompt_continue(self):
- """ Show uncommitted changes, and ask if user wants to continue. """
+ return e.returncode
- changes = uni_check_output(['git', 'status', '--porcelain'])
- if changes.strip():
- changes = uni_check_output(['git', 'status']).strip()
- message = (
- "You have the following changes:\n%s\n\n"
- "Anything not committed, and unknown to Nikola may be lost, "
- "or committed onto the wrong branch. Do you wish to continue?"
- ) % changes
- proceed = ask_yesno(message, False)
- else:
- proceed = True
+ self.logger.info("Successful deployment")
- return proceed
+ # Store timestamp of successful deployment
+ timestamp_path = os.path.join(self.site.config["CACHE_FOLDER"], "lastdeploy")
+ new_deploy = datetime.utcnow()
+ makedirs(self.site.config["CACHE_FOLDER"])
+ with io.open(timestamp_path, "w+", encoding="utf8") as outf:
+ outf.write(unicode_str(new_deploy.isoformat()))