# -*- coding: utf-8 -*- # 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 # documentation files (the "Software"), to deal in the # Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice # shall be included in all copies or substantial portions of # the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS # OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """Deploy site to GitHub Pages.""" from __future__ import print_function from datetime import datetime import io import os import subprocess from textwrap import dedent from nikola.plugin_categories import Command from nikola.plugins.command.check import real_scan_files from nikola.utils import get_logger, req_missing, makedirs, unicode_str, STDERR_HANDLER from nikola.__main__ import main from nikola import __version__ def uni_check_output(*args, **kwargs): """Run command and return output as Unicode (UTf-8).""" o = subprocess.check_output(*args, **kwargs) return o.decode('utf-8') def check_ghp_import_installed(): """Check if ghp-import is 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.""" name = 'github_deploy' doc_usage = '' doc_purpose = 'deploy the site to GitHub Pages' doc_description = dedent( """\ This command can be used to deploy your site to GitHub Pages. It uses ghp-import to do this task. """ ) logger = None def _execute(self, command, args): """Run the deployment.""" self.logger = get_logger(CommandGitHubDeploy.name, STDERR_HANDLER) # 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') return build # Clean non-target files only_on_output, _ = real_scan_files(self.site) for f in only_on_output: os.unlink(f) # Commit and push self._commit_and_push() return def _commit_and_push(self): """Commit all the files and push.""" 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__) ) output_folder = self.site.config['OUTPUT_FOLDER'] command = ['ghp-import', '-n', '-m', commit_message, '-p', '-r', remote, '-b', deploy, output_folder] 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) ) return e.returncode self.logger.info("Successful deployment") # 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()))