Permalink
Browse files

initial commit

  • Loading branch information...
altercation committed Apr 4, 2011
0 parents commit 053de997c74b3d81508459a8caf6212c82272b41
160 README.md
@@ -0,0 +1,160 @@
+ethanschoonover.com site source
+===============================
+
+I use [Hakyll](http://jaspervdj.be/hakyll/) to maintain this site. See the
+`bin` directory for the site.hs which builds the site statically.
+
+Source structure
+----------------
+
+ ├── bin hakyll source code
+ ├── etc nginx local config files
+ ├── files downloads, global to site
+ ├── pages special pages (colophon, error pages)
+ │   └── errors
+ ├── posts one time posts, with possible updates
+ ├── projects ongoing, updated projects
+ ├── resources static resources
+ │   ├── css
+ │   ├── img
+ │   └── js
+ ├── src non hakyll source files
+ │   └── psd
+ └── templates templates used by hakyll
+
+Deployment process overview
+---------------------------
+
+Local site modifications are tested until correct and pushed to github for
+offsite storage. When site updates are ready for public deployment I push to my
+web server.
+
+Some subdirectories, notably the project subdirectories, are managed using
+git-subtree. The web pages for those project are identical to the github
+repository for those projects. The Hakyll site.hs code processes them and
+converts the github specific absolute urls to be relative to my server's
+webroot.
+
+Git subtree has the advantage of allowing me to work on the project from either
+the main project directory on my machine or from the website directory (for
+local site preview). Additionally, the project itself is maintained with
+several git-subtree subdirectories, allowing me to break out the vim
+subdirectory as it's own repository and work on it, for instance, from within
+my personal dotfiles.
+
+See <http://chrisdone.com/posts/2010-04-04-hakyll-and-git-for-you-blog.html>
+for other details on a similar hakyll-github-server deployment process that
+I took inspiration from.
+
+Key commands
+------------
+
+* Building Hakyll site.hs
+
+ `ghc --make bin/site`
+
+* Clean and preview site locally. `bin` is in my path so I can just use `site`
+ and it will source locally.
+
+ `site clean`
+ `site preview`
+ `site preview 8900` (alternate port)
+
+* Create git-subtree repo (my own standardized naming conventions)
+
+ * Add remotes:
+
+ git remote add remote-solarized \
+ git@github.com:altercation/solarized.git
+
+ * Add subtrees:
+
+ git subtree add --prefix=projects/solarized \
+ remote-solarized master
+
+ * Pull changes into local subtree
+
+ git subtree pull --prefix=projects/solarized \
+ remote-solarized master
+
+ * Push changes from local subtree
+
+ git subtree push --prefix=projects/solarized \
+ remote-solarized master
+
+* Push to github
+
+ standard commit and push
+
+* Deploy to live site
+
+ git push aithops
+
+Deployment Server
+-----------------
+
+* Site root and config
+
+ /srv/www
+ ├── commons
+ │   └── errors
+ │   ├── 403
+ │   ├── 404
+ │   └── 50x
+ ├── domains
+ │   └── domain.tld
+ ├── etc
+ └── logs
+
+* Create repository and configure on remote
+
+ www@aithops$ mkdir ethanschoonover.com
+ www@aithops$ cd ethanschoonover.com
+ www@aithops$ git init
+ www@aithops$ git config receive.denyCurrentBranch 'ignore'
+ www@aithops$ cd ..
+ www@aithops$ chmod -R g+w ethanschoonover.com
+
+* Post-receive Hook
+
+ ethanschoonover.com/.git/hooks/post-receive file:
+
+ #!/bin/bash
+
+ export LANG=en_US.UTF-8
+
+ if [ -n $GIT_DIR ]; then
+ unset GIT_DIR
+ cd ..
+ fi
+
+ # force checkout
+ git checkout -f
+
+ # build site binary (if no change it won't build)
+ ghc --make bin/site
+
+ #backup current state for quick recovery, just in case
+ rm -rf _previous
+ cp -r _site _previous
+
+ # build site to _site directory
+ # note: this is not a full rebuild, but could be
+ # if we did a relink to the _previous directory prior
+ # to the rebuild, then a link back to _site
+ bin/site build
+
+ # ensure we have the correct link on initial build
+ # (commented out option force overrides)
+ # ln -sfn _site _live
+ if [ ! -h _live ]; then
+ ln -s _site _live;
+ fi
+
+Notes
+-----
+
+See my dotfile repository for my master gitignore file. I've added both _cache
+and _site there (along with the standard haskell ignores) and locally I've
+added bin/site (the compile hakyll binary).
+
@@ -0,0 +1,155 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Prelude hiding (id)
+import Control.Category (id)
+import Control.Arrow ((>>>), (>>^), (***), arr)
+import Control.Monad (forM_)
+import Data.Monoid (mempty, mconcat)
+import System.FilePath
+import Hakyll
+
+main :: IO ()
+main = hakyll $ do
+
+-----------------------------------------------------------------------
+-- copy resources files & process css as necessary
+-----------------------------------------------------------------------
+
+ route "resources/css/**" $ setRoot `composeRoutes` setExtension "css"
+ compile "resources/css/**" $ byExtension (error "not a valid css file")
+ [ (".css", sass)
+ , (".scss", sass) ]
+
+ forM_ [ "resources/*"
+ , "resources/js/**"
+ , "resources/img/**"] $ \resource -> do
+ route resource $ setRoot
+ compile resource $ copyFileCompiler
+
+-----------------------------------------------------------------------
+-- compile templates and pages
+-----------------------------------------------------------------------
+
+ compile "templates/*" templateCompiler
+
+-- create site pages
+-----------------------------------------------------------------------
+
+ forM_ [ "p*/***.md"
+ , "p*/***.mkd"
+ , "p*/***.mkdn"
+ , "p*/***.mdown"
+ , "p*/***.markdown"
+ , "p*/***.pandoc"
+ , "p*/***.pdc"
+ , "p*/***.lhs"
+ ] $ \page -> do
+ route page $ ifMatch "**README.*" setRoot `composeRoutes` toIndex
+ route page $ ifMatch "**index.*" setRoot `composeRoutes` toIndex
+ route page $ setRoot `composeRoutes` cleanURL
+ compile page $ unGitHubCompiler
+ >>> applyTemplateCompiler "templates/default.html"
+
+ -- TODO: this currently overwrites markdown files in subdirectories
+ forM_ ["p*/*/*/**"] $ \file -> do
+ route file $ setRoot `composeRoutes` idRoute
+ compile file $ copyFileCompiler
+
+-- special root pages
+-----------------------------------------------------------------------
+ route "index.html" $ idRoute
+ create "index.html" $ constA mempty
+ >>> arr (setField "pagetitle" "Ethan Schoonover")
+ >>> requireAllA "posts/***.md" (id *** arr newest10 >>> postList)
+ >>> requireAllA "projects/***.md" projectList
+ >>> applyTemplateCompiler "templates/home.html"
+ >>> applyTemplateCompiler "templates/default.html"
+
+ route "posts/index.html" $ idRoute
+ create "posts/index.html" $ constA mempty
+ >>> arr (setField "pagetitle" "Posts - Ethan Schoonover")
+ >>> requireAllA "posts/***.md" postList
+ >>> applyTemplateCompiler "templates/posts.html"
+ >>> applyTemplateCompiler "templates/default.html"
+
+ route "projects/index.html" $ idRoute
+ create "projects/index.html" $ constA mempty
+ >>> arr (setField "pagetitle" "Projects - Ethan Schoonover")
+ >>> requireAllA "projects/***.md" projectList
+ >>> applyTemplateCompiler "templates/projects.html"
+ >>> applyTemplateCompiler "templates/default.html"
+
+-----------------------------------------------------------------------
+-- custom compilers
+-----------------------------------------------------------------------
+
+sass :: Compiler Resource String
+sass = getResourceString >>> unixFilter "sass" ["-s", "--scss"]
+ >>> arr compressCss
+
+unGitHub :: Compiler String String
+unGitHub = unixFilter "sed" ["s+https://github.com/[^/]*/\\([^:/]*\\)/raw/master+/\\1+g"]
+
+defaultCompiler :: Compiler Resource (Page String)
+defaultCompiler = getResourceString
+ >>> arr readPage
+ >>> addDefaultFields
+ >>> arr applySelf
+ >>> arr buildTitle
+ >>> pageRenderPandoc
+ >>> applyTemplateCompiler "templates/default.html"
+
+unGitHubCompiler :: Compiler Resource (Page String)
+unGitHubCompiler = getResourceString
+ >>> unGitHub
+ >>> arr readPage
+ >>> addDefaultFields
+ >>> arr applySelf
+ >>> arr buildTitle
+ >>> pageRenderPandoc
+
+-- custom routes
+-----------------------------------------------------------------------
+setRoot :: Routes
+setRoot = customRoute stripTopDir
+
+stripTopDir :: Identifier -> FilePath
+stripTopDir = joinPath . tail . splitPath . toFilePath
+
+cleanURL :: Routes
+cleanURL = customRoute fileToDirectory
+
+fileToDirectory :: Identifier -> FilePath
+fileToDirectory = (flip combine) "index.html" . dropExtension . toFilePath
+
+toIndex :: Routes
+toIndex = customRoute fileToIndex
+
+fileToIndex :: Identifier -> FilePath
+fileToIndex = (flip combine) "index.html" . dropFileName . toFilePath
+
+-- misc utils
+-----------------------------------------------------------------------
+newest10 :: [Page a] -> [Page a]
+newest10 = take 10 . reverse . sortByBaseName
+
+stripIndexLink :: Page a -> Page a
+stripIndexLink = changeField "url" dropFileName
+
+buildTitle :: Page a -> Page a
+buildTitle = renderField "title" "pagetitle" (++ " - Ethan Schoonover")
+
+postList :: Compiler (Page String, [Page String]) (Page String)
+postList = buildList "postlist" "templates/item.html"
+
+projectList :: Compiler (Page String, [Page String]) (Page String)
+projectList = buildList "projectlist" "templates/item.html"
+
+buildList :: String -> Identifier -> Compiler (Page String, [Page String]) (Page String)
+buildList field template = setFieldA field $
+ arr (reverse . sortByBaseName)
+ >>> arr (map stripIndexLink)
+ >>> require template (\p t -> map (applyTemplate t) p)
+ >>> arr mconcat
+ >>> arr pageBody
@@ -0,0 +1,14 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[remote "origin"]
+ url = git@github.com:altercation/ethanschoonover.com.git
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
+[remote "aithops"]
+ url = ssh://aithops//srv/www/domains/ethanschoonover.com
+ push = +master:refs/heads/master
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# necessary on archlinux, at least, as the locale was not picked up otherwise
+export LANG=en_US.UTF-8
+
+if [ -n $GIT_DIR ]; then
+ unset GIT_DIR
+ cd ..
+fi
+
+# force checkout
+git checkout -f
+
+# build site binary (if no change it won't build)
+ghc --make bin/site
+
+#backup current state for quick recovery, just in case
+rm -rf _previous
+cp -r _site _previous
+
+# build site to _site directory
+bin/site build
+
+# ensure we have the correct link on initial build
+# (commented out option force overrides)
+# ln -sfn _site _live
+if [ ! -h _live ]; then
+ ln -s _site _live;
+fi
@@ -0,0 +1,5 @@
+# Domain specific rewrite
+server {
+ server_name ~^([^.]\.)?ejas.net$;
+ rewrite ^ $scheme://ethanschoonover.com/$request_uri permanent;
+}
@@ -0,0 +1,16 @@
+#----------------------------------------------------------------------
+#
+# domain specific values
+#
+#----------------------------------------------------------------------
+
+# Site specific valid_referers (cumulative with main nginx.conf)
+#-----------------------------------------------------------------------
+valid_referers none blocked ~(([^.]*\.)?ethanschoonover\.com) ;
+
+# Values for special file and contact links
+#-----------------------------------------------------------------------
+if ($domain = "ethanschoonover.com") {
+set $shortname "es"; # default is hostname without tld
+set $emailname "es"; # default is 'contact'
+}
Oops, something went wrong.

0 comments on commit 053de99

Please sign in to comment.