blog-rekahsoft-ca/README.org

381 lines
16 KiB
Org Mode
Raw Normal View History

#+TITLE: Source Code for [[http://www.blog.rekahsoft.ca][#! Lambda Slang]]
2021-11-26 02:56:38 +00:00
#+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
2021-11-26 02:56:38 +00:00
#+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
2021-11-26 02:56:38 +00:00
* 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
2021-11-26 02:56:38 +00:00
- [[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
2021-11-26 06:46:49 +00:00
[[https://guix.gnu.org/][Gnu Guix]] is used to package this project and manage its dependencies, as well as to provide
reproducible development environments.
2023-05-31 02:05:30 +00:00
** 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
2023-05-31 02:05:30 +00:00
(templates, post, pages, etc..).
2021-11-26 06:46:49 +00:00
** 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:
2023-05-31 02:05:30 +00:00
#+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 $@
2021-11-26 06:46:49 +00:00
#+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
2023-05-31 02:05:30 +00:00
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.
2021-11-26 06:46:49 +00:00
2023-05-31 02:05:30 +00:00
*** 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.
2023-05-31 02:05:30 +00:00
To start a deployment environment, run the following:
2023-05-31 02:05:30 +00:00
#+begin_src sh :mkdirp yes :tangle ./scripts/start-deployment-environment.sh :tangle-mode (identity #o555)
cd infra
2023-05-31 02:05:30 +00:00
guix time-machine -C channels.scm -- shell -CN -E '^LANG$' -E '^TERM$' -E '^AWS.*$'
#+end_src
*** Composing Site Development and Deployment Environments
2023-05-31 02:05:30 +00:00
#+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
2023-05-31 02:05:30 +00:00
** 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,
2023-05-31 02:05:30 +00:00
~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
2021-11-26 06:46:49 +00:00
#+end_src
2023-05-31 02:05:30 +00:00
*** Clean Site
2021-11-26 02:56:38 +00:00
[[*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
2021-11-26 02:56:38 +00:00
2023-05-31 02:05:30 +00:00
*** 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.
2021-11-26 02:56:38 +00:00
#+begin_src sh
site watch
2021-11-26 02:56:38 +00:00
#+end_src
2023-05-31 02:05:30 +00:00
*** 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.
2023-05-31 02:05:30 +00:00
#+name: watch-all
2023-05-31 02:05:30 +00:00
#+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.
2023-05-31 02:05:30 +00:00
** 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~.
2023-05-31 02:05:30 +00:00
** 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
2023-05-31 02:05:30 +00:00
** Deploy the Site
2021-11-26 02:56:38 +00:00
Run a terraform apply to deploy to the selected environment.
2021-11-26 02:56:38 +00:00
#+begin_src sh
make deploy
#+end_src
2021-11-26 02:56:38 +00:00
2023-05-31 02:05:30 +00:00
** Working with Terraform Directly
2021-11-26 02:56:38 +00:00
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.
2023-05-31 02:05:30 +00:00
* 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
2023-05-31 02:05:30 +00:00
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.
2023-05-31 02:05:30 +00:00
#+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
2023-05-31 02:05:30 +00:00
.PHONY: bootstrap
bootstrap:
<<bootstrap>>
2023-05-31 02:05:30 +00:00
.PHONY: dev
dev:
./scripts/start-development-environment.sh
2023-05-31 02:05:30 +00:00
.PHONY: dev-deploy
dev-deploy:
./scripts/start-deployment-environment.sh
2023-05-31 02:05:30 +00:00
.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>>
2023-05-31 02:05:30 +00:00
.PHONY: build
build-release:
./scripts/build-release.sh
.PHONY: vendor
vendor:
./scripts/vendor-deps.sh
2023-05-31 02:05:30 +00:00
.PHONY: clean
clean:
./scripts/clean-guix-store.sh
rm -rf scripts lib/MathJax Makefile
2023-05-31 02:05:30 +00:00
#+end_src
* Continuous Integration & Delivery
** TODO Generate ~.drone.yaml~
#+begin_src sh
2023-05-31 02:05:30 +00:00
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
2021-11-26 02:56:38 +00:00
#+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]].