Deploy tool for Haskell applications, like Capistrano for Rails
Hapistrano is a deployment library for Haskell applications similar to
Ruby’s Capistrano.
We created Hapistrano because:
Hapistrano (like Capistrano for Ruby) deploys applications to a new
directory marked with a timestamp on the remote host. It creates this
new directory quickly by placing a git repository for caching purposes
on the remote server.
When the build process completes, it switches a symlink to the current
release directory, and optionally restarts the web server.
By default, Hapistrano keeps the last five releases on the target host
filesystem and deletes previous releases to avoid filling up the disk.
Hapistrano 0.4.0.0 looks for a configuration file called hap.yaml
that
typically looks like this:
deploy_path: '/var/projects/my-project'
host: user@myserver.com
port: 2222
# To perform version control operations
repo: 'https://github.com/stackbuilders/hapistrano.git'
revision: origin/main
# To copy the contents of the directory
local_directory: '/tmp/my-project'
build_script:
- stack setup
- stack build
restart_command: systemd restart my-app-service
The following parameters are required:
deploy_path
— the root of the deploy target on the remote host.source
of the repository, you have the following options:repo
— the origin repository.revision
— the SHA1 or branch to deploy. If a branch, you will need toorigin/branch_name
due to the way that the cache repo islocal_directory
— when this parameter is set, hapistrano will copy theThe following parameters are optional:
host
— the target host, if missing, localhost
will be assumed (whichhap
locally). You can specify theuser@server.com
.port
— SSH port number to use. If missing, 22 will be used.shell
— Shell to use. Currently supported: zsh
ans bash
. If missing, Bash
will be used.ssh_args
— Optional ssh arguments. Only -p
is passed via the port
variable.build_script
— instructions how to build the application in the form ofrestart_command
— if you need to restart a remote web server after avc_action
- Controls if version control related activity shouldfalse
.linux
- Specify, whether or not, the target system where Hapistrano willtrue
release_format
- The release timestamp format, thekeep_releases
- The number of releases to keep, thekeep_one_failed
- A boolean specifying whether to keep all failed releaseslinked_files:
- Listed files that will be symlinked from the {deploy_path}/shared
foldershared/foo/file.txt
).linked_dirs:
- Listed directories that will be symlinked from the {deploy_path}/shared
folder/
foo/
) because we use parseRelFile
to createrun_locally:
- Instructions to run locally on your machine in the
run_locally:
- pwd
- bash deploy.sh
Note how we are even able to execute a bash script named deploy.sh
above. Be sure to use set -e
in your bash script to avoid
headaches. Hapistrano will stop the execution on non-zero exit
codes. Without the usage of set -e
, there is a possibility that your
bash script may return a zero exit code even if your intermediate
command resulted in an error.
After creating a configuration file as above, deploying is as simple as:
$ hap deploy
Rollback is also trivial:
$ hap rollback # to rollback to previous successful deploy
$ hap rollback -n 2 # go two deploys back in time, etc.
maintenance_directory:
- The name of the directory on which the maintenance file will be placed. {deploy_path}/{maintenance_directory}
. The default directory name is maintenance
maintenance_filename:
- The name of the file that is going to be created in the maintenance_directory. It has to have the .html
extension to be seen in the browser. {deploy_path}/{maintenance_directory}/{maintenance_filename}
. The default filename is maintenance.html
Configuration files are parsed using
loadYamlSettings,
therefore, variable substitution is supported. Considering the following configuration file:
revision: "_env:HAPISTRANO_REVISION:origin/main
...
The revision
value could be overwritten as follows:
HAPISTRANO_REVISION=origin/feature_branch hap deploy
Sometimes the target machine (server) is not capable of compiling your
application because e.g. it has not enough memory and GHC exhausts it all.
You can copy pre-compiled files from local machine or CI server usingcopy_files
and copy_dirs
parameters:
copy_files:
- src: '/home/stackbuilders/my-file.txt'
dest: 'my-file.txt'
copy_dirs:
- src: .stack-work
dest: .stack-work
src
maybe absolute or relative, it’s path to file or directory on local
machine, dest
may only be relative (it’s expanded relatively to cloned
repo) and specifies where to put the files/directories on target machine.
Directories and files with clashing names will be overwritten. Directories
are copied recursively.
Beginning with Hapistrano 0.3.1.0 it’s possible to deploy to several
machines concurrently. The only things you need to do is to adjust your
configuration file and use targets
parameter instead of host
and port
,
like this:
targets:
- host: myserver-a.com
port: 2222
- host: myserver-b.com
# the rest is the same
Additionally, starting with 0.4.9.0 it is possible to run commands only on the
lead target during a concurrent deploying process ensuring that certain tasks
only get executed once. The lead target is considered the first entry in thetargets
list:
targets:
- host: app1.example.com # lead server
- host: app2.example.com
build_script:
- command: ./run_database_migrations
only_lead: true
- ./build
# the rest is the same
A few things to note here:
host
item is required for every target, but port
may be omitted and
then it defaults to 22
.
The deployment will run concurrently and finish when interactions with all
targets have finished either successfully or not. If at least one
interaction was unsuccessful, the hap
tool will exit with non-zero exit
code.
The log is printed in such a way that messages from several machines get
intermixed, but it’s guaranteed that they won’t overlap (printing itself
is sequential) and the headers will tell you exactly which machine was
executing which command.
If you don’t specify host
and targets
, hap
will assume localhost
as
usually, which is mainly useful for testing.
Starting with version 0.4.4.0
all new Docker images would be published to
[GitHub’s Container Registry][ghcr], while the old versions remain available on
[Docker Hub][dockerhub]. To download the latest
version available, change the
image reference as follows:
- stackbuilders/hapistrano:latest
+ ghcr.io/stackbuilders/hapistrano:latest
Check the documentation here
Alternatively, install only Nix following the instructions detailed
here.
Update package index:
cabal update
Enable tests:
cabal configure --enable-tests
Install project dependencies:
cabal build --only-dependencies
Compile the project:
cabal build
Run tests:
cabal test
Present a maintenance page to visitors. Disables your application’s web interface by writing a {maintenance_filename} file to each web server. The servers must be configured to detect the presence of this file, and if it is present, always display it instead of performing the request.
The maintenance page will just say the site is down for maintenance, and will be back shortly.
To enable maintenance mode run:
hap maintenance enable
Disabling maintenance mode will remove the file from the {maintenance_directory} it can be done with the following command:
hap maintenance disable
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT, see the LICENSE file.
Do you want to contribute to this project? Please take a look at our contributing guideline to know how you can help us build it.