The Emacs Machine Provisioner
Did I hear you say you want to do continuous delivery with EmacsLisp?
Did I hear you say you want to quickly provision your EmacsLisp packages?
I realize the answer to those questions is unlikely to be yes but bear with me anyway because here's a crazy idea:
gem install vagrant git clone git://github.com/nicferrier/emacs-provisioner-vagrant.git emacs-machiner cd emacs-machiner rake emacs_git_url=git://github.com/emacsmirror/emacs.git \ myrepo=git://github.com/nicferrier/emacs-ci-demo.git
you probably need ruby 1.9 to make vagrant (or rake) work
- downloads the required Vagrant base box (unless you already have it)
- make a virtual machine from the Vagrant base box
- clone the Emacs source repo
emacs_git_urlinside the virtual machine
- clones the my_repo you provide in
- then installs the Emacs from the repo you specified
- the runs a
build.elfile inside your repo to do any repo specific things
There are 2 reasons I needed this, firstly I want to be able to test Emacs Lisp code in a clean and predictable environment, for example against a particular version of Emacs. Some form of continuous integration system would be very useful. Other people in the Emacs community are also talking about this, for example Sigma is the author of the Emacs git tool, magit and he wants to be able to have a repeatable build of Emacs that he can test against different versions of Git.
The second reason I needed this is that I want a recreatably clean environment to run Emacs Lisp code in, particularly Elnode my Emacs Lisp server. I want to be able to specify a base and then add extra packages and configuration to create an Emacs Machine for a running program. An Elnode server might include nginx for example.
Emacs batch scripting
The first step in building an Emacs Machine is to have a way of creating the Emacs Lisp environment inside Emacs. ELPA, the Emacs packaging system has recently made this quite nice.
Here's an example build file for this blog:
(setq package-dir (concat (file-name-directory (or (buffer-file-name) load-file-name)) ".elpa")) (setq package-user-dir package-dir) (when (file-exists-p package-dir) (delete-directory package-dir t)) (setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/") ("marmalade" . "http://marmalade-repo.org/packages/"))) (package-initialize) (package-refresh-contents) (let ((nicblogmake (concat (file-name-directory (or (buffer-file-name) load-file-name)) "nicblog-make.el"))) (package-install-file nicblogmake)) (require 'nicblog-make) (nicblog-make-run)
If you know Emacs Lisp you'll notice that it's all portable as to it's location in the file system. So you can add this to any local package. You can see that Emacs packages are used, the installation of the local file "nicblog-make.el" as a package causes any packages it has defined as dependancies to be collected from ELPA; here's the header of my blog file:
;;; nicblog-make.el --- Make nic's blog ;;; Copyright (C) 2012 by Nic Ferrier ;; Author: Nic Ferrier <firstname.lastname@example.org> ;; Maintainer: Nic Ferrier <email@example.com> ;; Created: 28th March 2012 ;; Version: 0.0.1 ;; Package-Requires: ((creole "0.8.3")) ;; Keywords: lisp, creole, wiki
creole package will be downloaded from ELPA and deployed
into the Emacs where the script is run.
It's easy to make a
build.el like the above because you can test
it iteratively using your local Emacs instance, like this:
emacs -Q -batch --script build.el
If I pass the repo that this file sits in to my rake command then my blog will be built in the Emacs Machine.
Right now it stops at the
build.el but what's really needed is
the ability to do more provisioning. For example, to make this blog
run I really need to add nginx into the VM and it would be nice to do
that repeatably. I'm working on changes that would make that possible.
Another step forward would be to create a system that let people other than the package owner run tests for the package owner. Most of us Emacs hackers don't have unlimited resources, it would be great if people could help us with testing and this might be one way it could be done.
Shout me on twitter if you have an idea for how to use the Emacs Machine provisioner!
Sigma, the author of Magit has come up with this approach.