381 lines
16 KiB
Org Mode
381 lines
16 KiB
Org Mode
#+TITLE: Source Code for [[http://www.blog.rekahsoft.ca][#! Lambda Slang]]
|
|
#+AUTHOR: Collin J. Doering
|
|
|
|
#+BEGIN_EXPORT html
|
|
<p><a href="https://ci.home.rekahsoft.ca/rekahsoft-public/blog-rekahsoft-ca"><img src="https://ci.home.rekahsoft.ca/api/badges/rekahsoft-public/blog-rekahsoft-ca/status.svg?ref=refs/heads/master" alt="Build Status"></a></p>
|
|
#+END_EXPORT
|
|
|
|
#+begin_abstract
|
|
[[http://www.blog.rekahsoft.ca][#! Lambda Slang]] is the personal technical blog of *Collin Doering*, built using software that
|
|
[[https://www.gnu.org/philosophy/free-sw.html][respects our freedoms]].
|
|
#+end_abstract
|
|
|
|
* Features
|
|
|
|
- [[http://en.wikipedia.org/wiki/Single-page_application][Single Page Application (SPA)]]
|
|
- Write blog posts and pages in markdown
|
|
- Support for math markup via MathJax
|
|
- RSS/Atom feed
|
|
|
|
* Tools
|
|
|
|
The creation of this website was made possible by the following open source tools and
|
|
libraries:
|
|
|
|
- [[http://jaspervdj.be/hakyll/][Hakyll]] is used to generate site from static files
|
|
- [[http://fvisser.nl/clay/][Clay]] is used for CSS pre-processing
|
|
- [[http://www.getskeleton.com/][Skeleton]] is used for CSS boilerplate
|
|
- [[http://www.mathjax.org/][MathJax]] is used for rendering mathematics
|
|
- [[http://jquery.com][JQuery]] is used for various DOM manipulations
|
|
- [[https://guix.gnu.org/][Gnu Guix]] is used to manage development environments and packaging
|
|
- [[http://inkscape.org/][Inkscape]] and the [[http://www.gimp.org/][Gimp]] were used to create various images/artwork
|
|
- [[http://www.gnu.org/software/freefont/][Gnu Free Fonts]], specifically *FreeMono* is used as main font
|
|
- [[http://www.gnu.org/software/emacs/][Gnu Emacs]] because there is no place like home; and no greater editor!
|
|
|
|
* License
|
|
|
|
Simply put, you're welcome to use the code used to generate this site though there are a few
|
|
restrictions:
|
|
|
|
- Any images and artwork that embody the likeness of "#! Lambda Slang" are not to be distributed or
|
|
used and are strictly copyright
|
|
- The content of pages and posts can be used with attribution, providing you aren't making money off of it
|
|
|
|
Various licenses ([[https://www.gnu.org/licenses/gpl.html][GPLv3]], [[http://creativecommons.org/licenses/by-nc-sa/4.0/][Creative Commons BY-NC-SA License]], and [[http://creativecommons.org/licenses/by-nc-nd/4.0/][Creative Commons BY-NC-ND
|
|
License]]) are deployed dependent on which part of the site is in question. Please see the
|
|
[[./LICENSE][LICENSE]] file for full details.
|
|
|
|
* Repository Structure
|
|
|
|
- ~blog-rekahsoft-ca.cabal~ :: Cabal package definition.
|
|
- ~bootstrap.sh~ :: Generate development scripts, Makefile, and setup vendor links based on this literate configurationl
|
|
- ~channels.scm~ :: Guix Channel File.
|
|
- ~clay/*.hs~ :: Clay source files.
|
|
- ~css/*.css~ :: CSS source files (will be minified).
|
|
- ~drafts/*.md~ :: Draft posts.
|
|
- ~files/images/~ :: Folder for images used in posts.
|
|
- ~files/source/~ :: Folder for source code used in blog posts/pages.
|
|
- ~fonts/*.{ttf,woff,...}~ :: Font files
|
|
- ~guix.scm~ :: Guix package definition for this site-builder and its resulting site.
|
|
- ~images/*~ :: Folder for images used on pages or in templates.
|
|
- ~images-src/*~ :: Folder for the image source files (should be 1-to-1 with files in ~images/*~).
|
|
- ~infra/~ :: Infrastructure folder; contains terraform based Infrastructure As Code (IAC).
|
|
- ~infra/channels.scm~ :: Symlink to ~../channels.scm~ (can be independent if needed).
|
|
- ~infra/*.tf~ :: Terraform source files.
|
|
- ~infra/*.tfvars~ :: Terraform variables files for each environment (non-secrets).
|
|
- ~infra/Makefile~ :: Makefile used for terraform deployments.
|
|
- ~infra/manifest.scm~ :: Guix manifest that defines the necessary deployment environment.
|
|
- ~js/*.js~ :: Javascript files.
|
|
- ~lib/*~ :: Javascript libraries.
|
|
- ~LICENSE~ :: License file.
|
|
- ~pages/*.markdown~ :: Page content.
|
|
- ~posts/*.markdown~ :: Blog posts.
|
|
- ~README.org~ :: Org-mode documentation.
|
|
- ~robots.txt~ :: Robot Exclusion Protocol file.
|
|
- ~Setup.hs~ :: Cabal build script for this site.
|
|
- ~src/*.hs~ :: Hakyll powered site builder.
|
|
- ~templates/~ :: Folder for all template files.
|
|
- ~templates/default.html~ :: Entry point template (defines html document used for all pages).
|
|
- ~templates/pages/*.html~ :: Html page templates (correspond 1-to-1 with pages/*.markdown files).
|
|
- ~templates/partials/*.html~ :: Partial template files, for use within templates.
|
|
- ~templates/tag-page.html~ :: Template for creating pages about tags with a specific tag.
|
|
|
|
* Guix Development Environment
|
|
|
|
[[https://guix.gnu.org/][Gnu Guix]] is used to package this project and manage its dependencies, as well as to provide
|
|
reproducible development environments.
|
|
|
|
** Prerequisites
|
|
|
|
The only prerequisite for starting a development environment for this project is [[https://guix.gnu.org/][GNU Guix]].
|
|
Optionally, [[https://direnv.net/][direnv]] can be used to enable a non-containerized development environment that is
|
|
abridged with your existing shell.
|
|
|
|
** Quick Start
|
|
|
|
First run the bootstrap script, which uses this documentation to generate a ~Makefile~ that
|
|
can be used for development.
|
|
|
|
#+name: bootstrap
|
|
#+begin_src sh
|
|
./bootstrap.sh
|
|
#+end_src
|
|
|
|
Then run the development 'auto-watching' environment:
|
|
|
|
#+begin_src sh
|
|
make
|
|
#+end_src
|
|
|
|
This starts a containerized local development environment that uses [[https://github.com/ndmitchell/ghcid/][ghcid]] to watch haskell
|
|
sources and restart hakyll's [[*Watch][site watch]] feature when changes occur. The site will be
|
|
available at http://localhost:3000, and will automatically rebuild as site files change
|
|
(templates, post, pages, etc..).
|
|
|
|
** Start Development Environment
|
|
|
|
The development environment is defined by the following files:
|
|
|
|
- [[./channels.scm][channels.scm]] :: Specifically defines a set of available software, their versions and their build recipe.
|
|
- [[./guix.scm][guix.scm]] :: Defines the package for this site, ~blog-rekahsoft-ca~.
|
|
|
|
To start a development environment, run the following:
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/start-development-environment.sh :tangle-mode (identity #o555)
|
|
guix time-machine -C channels.scm -- shell -CN -E '^LANG$' -E '^TERM$' -f guix.scm -Df guix.scm $@
|
|
#+end_src
|
|
|
|
This uses the [[info:guix#Invoking guix time-machine][guix time-machine]] feature to ensure the development environment is reproducible
|
|
by supplying a set of guix channels, effectively pinning all software versions used. The [[info:guix#Invoking guix shell][guix
|
|
shell]] command is used within the time-machine to start a development environment in a
|
|
container (~-C~), which shares the hosts network namespace (~-N~). The environment variable
|
|
~LANG~ is passed into the container to ensure locales work as expected; without this, site
|
|
building will fail! Additionally, the environment variable ~TERM~ is passed into the
|
|
container to ensure the development shell behaves correctly. The option ~-f guix.scm~ loads
|
|
the ~blog-rekahsoft-ca~ package, and ~-Df guix.scm~ indicates that development dependencies
|
|
of the ~blog-rekahsoft-ca~ package should be included in the environment.
|
|
|
|
*** Deployment Environment
|
|
|
|
[[https://guix.gnu.org/][Gnu Guix]] is used, similar to in the [[*Start Development Environment][previous section]], to create environments with all tools
|
|
necessary for deployments, with a notable difference being a ~guix.scm~ file is not provided
|
|
or needed, as the deployment environment is used solely for its side effects.
|
|
|
|
- [[./infra/channels.scm][infra/channels.scm]] :: Symlink to [[./channels.scm][../channels.scm]] to make the guix cli workflow nicer when
|
|
in the ~infra~ directory. Technically this doesn't need to be a symlink, and could be a
|
|
different set of channels or version of channels compared to the channels file at the
|
|
top-level of the repository, however this would complicate [[*Composing Site Development and Deployment Environments][Composing Site Development and
|
|
Deployment Environments]], so its preferred that all guix environments for the project,
|
|
including the development and deployment environment use the same set of Guix channels.
|
|
- [[./infra/manifest.scm][infra/manifest.scm]] :: Defines packages required for deployment of this site.
|
|
|
|
To start a deployment environment, run the following:
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/start-deployment-environment.sh :tangle-mode (identity #o555)
|
|
cd infra
|
|
guix time-machine -C channels.scm -- shell -CN -E '^LANG$' -E '^TERM$' -E '^AWS.*$'
|
|
#+end_src
|
|
|
|
*** Composing Site Development and Deployment Environments
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/start-development-and-deployment-environment.sh :tangle-mode (identity #o555)
|
|
guix time-machine -C channels.scm -- shell -CN -E '^LANG$' -E '^TERM$' -E '^AWS.*$' -f guix.scm -Df guix.scm -m infra/manifest.scm $@
|
|
#+end_src
|
|
|
|
** Hakyll Site Commands
|
|
*** Build Site
|
|
|
|
This website is built from a collection of markdown files and templates that are processed by
|
|
pandoc and are stitched together using Hakyll. To build the html/css/jss and all other assets
|
|
required to deploy and distribute the site, the hakyll derived site-builder,
|
|
~blog-rekahsoft-ca~ must be invoked. For convenience, an alias ~site~ is provided for the
|
|
site builder as part of its guix package. Here is it being used to build the site:
|
|
|
|
#+begin_src sh
|
|
site build
|
|
#+end_src
|
|
|
|
*** Clean Site
|
|
|
|
[[*Build Site][Building the site]] has the side effect of writing a couple files/directories to disk as a
|
|
result of the build process. In some cases, its useful to start of with a clean slate and
|
|
remove any files that were generated for the site. To so so, the ~clean~ sub-command can be
|
|
used:
|
|
|
|
#+begin_src sh
|
|
site clean
|
|
#+end_src
|
|
|
|
*** Watch
|
|
|
|
During development of new content or adjustments to the site, it is useful to autocompile
|
|
upon changes to any site files (templates, pages, posts, etc..). This functionality is
|
|
provided by Hakyll.
|
|
|
|
#+begin_src sh
|
|
site watch
|
|
#+end_src
|
|
|
|
*** TODO ~site deploy~ command
|
|
|
|
#+begin_src sh
|
|
site deploy
|
|
#+end_src
|
|
|
|
** Clean up Guix Store
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/clean-guix-store.sh :tangle-mode (identity #o555)
|
|
guix gc --list-dead | grep -e '^/gnu/store/.*-blog-rekahsoft-ca-.*' | xargs guix gc -D
|
|
#+end_src
|
|
|
|
** Enhanced Watch
|
|
|
|
When making adjustments to the site builder itself, it is useful to have functionality
|
|
similar to the site content watching feature of Hakyll, but for haskell source files.
|
|
Luckily, [[https://github.com/ndmitchell/ghcid/][ghcid]] can be used for this, and is included in the projects development
|
|
dependencies, specified in the ~guix.scm~ file.
|
|
|
|
#+name: watch-all
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/watch-all.sh :tangle-mode (identity #o555)
|
|
ghcid --test _devWatch
|
|
#+end_src
|
|
|
|
* Building a Release
|
|
|
|
The software built that itself builds this blog is released as a Guix package. It is
|
|
currently not, and is not ever expected to be distributed via a channel, as it provides
|
|
little benefit to anyone except myself, and is meant to operate along with stateful data,
|
|
including the site templates, content, pages, posts, etc..
|
|
|
|
To build a release, run the following command:
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/build-release.sh :tangle-mode (identity #o555)
|
|
guix time-machine -C channels.scm -- build -f guix.scm
|
|
#+end_src
|
|
|
|
This will produce a guix package with the following three outputs:
|
|
|
|
- ~out~ :: The ~blog-rekahsoft-ca~ site builder (also available as ~site~), and ~gencss~ css
|
|
generator binaries
|
|
- ~site~ :: A build of the website made with the site builder, etc.. in the ~out~ output of
|
|
this package, using the content at the same version
|
|
- ~static~ :: License file and any other file that should be distributed (eg manual)
|
|
|
|
** TODO What is done with the release?
|
|
|
|
* Deploying the Site
|
|
|
|
Terraform is used to deploy this site. Its configuration files are located in ~./infra~.
|
|
|
|
Under normal conditions, all deployments occur from my internal ci/cd system. This ensures
|
|
that the deployment process is reliable, repeatable and quick. However, in the case of both
|
|
development and emergency deployments, clear documentation surrounding the deployment process
|
|
is necessary.
|
|
|
|
** Start [[*Deployment Environment][Deployment Environment]]
|
|
** Setup a Particular Environment
|
|
|
|
Three environments (terraform workspaces) are currently available, including:
|
|
|
|
- default :: unused default terraform workspace
|
|
- staging :: https://www.blog.staging.rekahsoft.ca
|
|
- production :: https://www.blog.rekahsoft.ca
|
|
|
|
#+begin_src sh
|
|
make setup ENV=<env>
|
|
#+end_src
|
|
|
|
From this point onward, any ~make~ target run will operate on the selected environment,
|
|
unless its switched with the ~workspace~ or ~setup~ targets, or manually with ~terraform~.
|
|
|
|
** See What Infrastructure Will Change
|
|
|
|
Run a terraform plan to see how the selected environments infrastructure will change.
|
|
|
|
#+begin_src sh
|
|
make plan
|
|
#+end_src
|
|
|
|
** Deploy the Site
|
|
|
|
Run a terraform apply to deploy to the selected environment.
|
|
|
|
#+begin_src sh
|
|
make deploy
|
|
#+end_src
|
|
|
|
** Working with Terraform Directly
|
|
|
|
Within a development environment, ~terraform~, its providers and all other dependencies are
|
|
available. As such, its possible to directly leverage ~terraform~ and its various operations.
|
|
This is particularly useful when debugging or adding make targets.
|
|
|
|
* TODO Writing a Blog Post
|
|
|
|
The most natural way to edit and preview a post is to use [[https://direnv.net/][direnv]] along with this repository,
|
|
which uses ~guix shell~ to transparently provide all necessary tools, including [[*Hakyll Site Commands][Hakyll Site
|
|
Commands]]. When using direnv, a containerized environment will not be used, however for
|
|
content development, this is not a concern.
|
|
|
|
#+begin_src sh
|
|
guix time-machine -C channels.scm -- shell -CN -E LANG -E TERM -f guix.scm
|
|
#+end_src
|
|
|
|
* DOING Vendor external libraries using Guix
|
|
|
|
Some ...
|
|
|
|
#+begin_src sh :mkdirp yes :tangle ./scripts/vendor-deps.sh :tangle-mode (identity #o555)
|
|
[ -h lib/MathJax ] && rm lib/MathJax
|
|
[ -e lib/MathJax ] && echo "lib/MathJax exists, but not as a symlink; please manually remove it!" && exit 1
|
|
ln -s $(guix time-machine -C channels.scm -- shell -Df guix.scm -- bash -c 'echo $GUIX_ENVIRONMENT')/share/javascript/mathjax lib/MathJax
|
|
#+end_src
|
|
|
|
* Makefile
|
|
|
|
In order to simplify running the various commands outlined throughout this document, a
|
|
~Makefile~ is defined below.
|
|
|
|
#+begin_src makefile :noweb yes :tangle Makefile :tangle-mode (identity #o444)
|
|
# THIS IS A GENERATED FILE, DO NOT EDIT!
|
|
# Instead modify README.org appropriately
|
|
|
|
.DEFAULT_GOAL := watch
|
|
|
|
.PHONY: bootstrap
|
|
bootstrap:
|
|
<<bootstrap>>
|
|
|
|
.PHONY: dev
|
|
dev:
|
|
./scripts/start-development-environment.sh
|
|
|
|
.PHONY: dev-deploy
|
|
dev-deploy:
|
|
./scripts/start-deployment-environment.sh
|
|
|
|
.PHONY: dev-all
|
|
dev-all:
|
|
./scripts/start-development-and-deployment-environment.sh
|
|
|
|
.PHONY: watch-all
|
|
watch-all:
|
|
./scripts/watch-all.sh
|
|
|
|
.PHONY: watch
|
|
watch:
|
|
./scripts/start-development-environment.sh -- <<watch-all>>
|
|
|
|
.PHONY: build
|
|
build-release:
|
|
./scripts/build-release.sh
|
|
|
|
.PHONY: vendor
|
|
vendor:
|
|
./scripts/vendor-deps.sh
|
|
|
|
.PHONY: clean
|
|
clean:
|
|
./scripts/clean-guix-store.sh
|
|
rm -rf scripts lib/MathJax Makefile
|
|
#+end_src
|
|
|
|
* Continuous Integration & Delivery
|
|
|
|
** TODO Generate ~.drone.yaml~
|
|
|
|
#+begin_src sh
|
|
drone jsonnet --stream --format
|
|
#+end_src
|
|
*Note:* currently ~drone-cli~ is not packaged for Guix, so for the time being, it can be run
|
|
with docker as follows, where ~<version>~ is the drone-cli version.
|
|
|
|
#+begin_src shell
|
|
docker run -v ${PWD}:/tmp/app -w /tmp/app --rm -it drone/cli:<versin> jsonnet --stream --format
|
|
#+end_src
|
|
|
|
* Known Issues
|
|
|
|
If you have an issue while browsing [[http://www.blog.rekahsoft.ca][my blog]] please let me know via [[https://www.blog.rekahsoft.ca/contact.html][email]].
|