diff --git a/cli/cli.lisp b/cli/cli.lisp index 495581f..ab31512 100644 --- a/cli/cli.lisp +++ b/cli/cli.lisp @@ -23,7 +23,7 @@ ;; Required information :author \"~a\" ;; to be placed on post pages and in the copyright/CC-BY-SA notice :deploy-dir \"deploy/\" ;; for Coleslaw's generated HTML to go in - :domain \"\" ;; to generate absolute links to the site content + :domain \"\" ;; to generate absolute links to the site content. Note: with :cname option of gh-pages, this requires a url scheme, e.g. https://fake.org :routing ((:post \"posts/~~a\") ;; to determine the URL scheme of content on the site (:tag-index \"tag/~~a\") (:month-index \"date/~~a\") @@ -42,7 +42,13 @@ (mathjax) (sitemap) (static-pages) - ; (versioned) ;; *Remove comment to enable symlinked, timestamped deploys. + ;; deployment plugins + ;; deployment to github pages + ; (gh-pages :url \"git@github.com:myaccount/myrepo.git\" + ; ; :cname t ;; if you want to use the custom domain --- see http://pages.github.com/ + ; ) + ;; versioned deployment. Remove comment to enable symlinked, timestamped deploys. + ; (versioned) ;; default deploy method is rsync (rsync \"-avz\" \"--delete\" \"--exclude\" \".git/\" \"--exclude\" \".gitignore\" \"--copy-links\") ) @@ -124,10 +130,12 @@ Excerpt separator is `` by default. (stage)) (defun stage () - (coleslaw:main *default-pathname-defaults* :deploy nil)) + (prog1 (coleslaw:main *default-pathname-defaults* :deploy nil) + (format t "~&Page generated at the staging dir ~a~%" (getf (read-rc) :staging-dir)))) (defun deploy () - (coleslaw:main *default-pathname-defaults* :deploy t)) + (prog1 (coleslaw:main *default-pathname-defaults* :deploy t) + (format t "~&Page deployed at the deploy dir ~a~%" (getf (read-rc) :deploy-dir)))) (defun preview (&optional (path (getf (read-rc) :staging-dir))) ;; clack depends on the global binding of *default-pathname-defaults*. diff --git a/docs/plugin-use.md b/docs/plugin-use.md index d653fea..e7cb443 100644 --- a/docs/plugin-use.md +++ b/docs/plugin-use.md @@ -58,14 +58,27 @@ post with `format: cl-who` and the plugin will do the rest. **Example**: `(gfycat)` -## Hosting via Github Pages +## Deploying / Hosting via Github Pages -**Description**: Allows hosting with CNAMEs via - [github-pages](http://pages.github.com/). Parses the host from the - `:domain` section of your config by default. Pass in a string to - override. +**Description**: -**Example**: `(gh-pages :cname t)` +Coleslaw deploys the blog to the specified branch of the given url. +* `url` -- a string, git repository url that you already have a push access. +* `branch` -- a string, the branch to publish, either `"gh-pages"` or `"master"` can be used. +* `remote` -- a string, the remote name that we use in the deploy directory. defaulted to `"origin"`. +* `cname` -- a string denoting the custom domain name, or `t`. If `cname` is `t`, the value is inferred + from the domain name specified in the `.coleslawrc`. + The value is written into `CNAME` file in the repository root. + For details, see [github-pages](http://pages.github.com/). + +**Example**: + +``` lisp +(gh-pages :url "git@github.com:myaccount/myrepo.git" + :branch "gh-pages" + :remote "origin" + :cname t) +``` ## Incremental Builds diff --git a/plugins/gh-pages.lisp b/plugins/gh-pages.lisp index 794561d..576bcbe 100644 --- a/plugins/gh-pages.lisp +++ b/plugins/gh-pages.lisp @@ -1,33 +1,38 @@ (eval-when (:compile-toplevel :load-toplevel) - (ql:quickload 'puri)) - + (ql:quickload 'puri :silent t)) (defpackage :coleslaw-gh-pages (:use :cl) - (:import-from :puri #:parse-uri #:uri-host) - (:import-from :coleslaw #:*config* - #:deploy - #:deploy-dir - #:domain - #:rel-path) + (:import-from :coleslaw + #:*config* + #:domain + #:deploy + #:staging-dir + #:deploy-dir) (:export #:enable)) (in-package :coleslaw-gh-pages) -(defvar *cname* nil - "The domain CNAME for github to serve pages from.") +(defvar *options* nil) -(defmethod deploy :after (staging) - (let ((blog (rel-path (deploy-dir *config*) ".curr"))) - (delete-file (rel-path blog "index.html")) - (cl-fad:copy-file (rel-path blog "1.html") (rel-path blog "index.html")) - (with-open-file (out (rel-path blog "CNAME") - :direction :output - :if-exists :supersede - :if-does-not-exist :create) - (format out "~A~%" *cname*)))) +(defmethod deploy (staging) + (uiop:run-program (list* (namestring + (merge-pathnames "plugins/publish-gh-pages.sh" + coleslaw-conf:*basedir*)) + (namestring + (merge-pathnames (staging-dir *config*))) + (namestring + (merge-pathnames (deploy-dir *config*))) + *options*) + :output t + :error-output t)) -(defun enable (&key cname) - (typecase cname - (string (setf *cname* cname)) - (t (setf *cname* (uri-host (parse-uri (domain *config*))))) - (otherwise (error "Not a valid CNAME: ~A" cname)))) +(defun enable (&key url (branch "gh-pages") (remote "origin") cname) + (check-type url string) + (check-type remote string) + (check-type branch string) + (if (eq t cname) + (progn + (setf cname (puri:uri-host (puri:parse-uri (domain *config*)))) + (check-type cname string) + (setf *options* (list url branch remote cname))) + (setf *options* (list url branch remote)))) diff --git a/plugins/publish-gh-pages.sh b/plugins/publish-gh-pages.sh new file mode 100755 index 0000000..528fbf0 --- /dev/null +++ b/plugins/publish-gh-pages.sh @@ -0,0 +1,55 @@ +#!/bin/bash -x + +set -e + +staging=$1 +deploy=$2 +url=$3 +branch=$4 +remote=$5 +cname=$6 + +if [[ -d $deploy && ! -d $deploy/.git ]] +then + echo "Target directory $deploy exists and is not a git repository. Aborting" >&2 + exit 1 +fi + +if [[ ! -d $deploy ]] +then + git clone --no-checkout --origin $remote $url $deploy +fi + +cd $deploy + +# safe and most reliable way to check if the branch exist +if git show-ref --verify --quiet refs/heads/$branch +then + # if the branch exists locally + git checkout $branch +elif git show-ref --verify --quiet refs/remotes/$remote/$branch +then + # if the branch does not exist locally but exist in the specified remote --- + # Note, git checkout $branch will search the branch with the same name with + # ALL remotes, and set it as the tracking branch if there is a single such + # remote, but does not allow the user to necessarily specify which. + git checkout -b $branch --track $remote/$branch +else + # if there is no matching branch, make an orphan branch + git checkout --orphan $branch +fi + +rsync -avz --delete --exclude .git/ --copy-links $staging $deploy + +if [[ ! -z "$cname" ]] +then + echo $cname > CNAME +fi + +git add -A # add all changes in the worktree +git add $(git ls-files -o ) # add all untracked files in the worktree + +git commit -m "Deployed on $(date)" + +git push $remote $branch +