Running commands
As 'The basics' section explained, each of the main sections within a configuration file allows commands you define to be run.
These commands are just normal bash commands that you would normally have to run if you were doing a full manual install of your software. For example, enabling a service after your package has been installed:
To be able to use commands in deploys you will need a good understanding of each part of this document:
- Where you can specify commands
- How you can specify commands
- When each 'commands sections' is run
- How paths work when installing packages
- Commands can't require any user input
Command sections
Each of the following key-value sections within the configuration file can have commands specified within them. For a full description of these key-values please see our full reference.
- build -> commmands
- install -> commands
- before_install
- before_upgrade
- after_install
- after_upgrade
- before_uninstall
- after_uninstall
The build
and install
sections have an explicit commands
key-value due to both of these sections having other possible key-values within them.
...
build:
commands: |
python3.6 -m venv ./venv/
./venv/bin/pip install -r requirements.txt
Each of the before_install
, before_upgrade
, after_install
, after_upgrade
, before_uninstall
, after_uninstall
are all implicitly command sections and don't require a commands key:
...
after_install: |
systemctl enable myapp
systemctl start myapp
How to specify commands
Commands can be added in a few different ways, you can choose whichever one is easier for you.
A commands field value data type can be either a string (single or multi-line) or a list with several different key-value options.
Single line strings
...
after_install: systemctl enable myapp --now
Multiline strings
It is advised to use a pipe (|
) to indicate multi-line strings instead of a right angle bracket (>
) if you want one command per line. A pipe will keep newlines indicating each line is a new command whereas a right angle bracket will cause the line to be folded and each line added together. See yaml-multiline.info for more information.
...
after_upgrade: |
systemctl daemon-reload
systemctl restart myapp
:ist of key-values
You can use a list of key-values with the keys run
or files
.
run
will simply run each line in order:
...
after_upgrade:
- run: systemctl daemon-reload
- run: systemctl restart myapp
The file
key takes a string value which is a relative path to a file in your git repository, meaning the same commands can be used across multiple configuration files:
...
after_upgrade:
- file: ./install_commands.sh # Relative path from the git repo root
The path to the file needs to be relative from the repository root and it is not required for the file to be copied to the end-user machine on install.
In the above example the parser will take each line in the file ./install_commands.sh
and run them one after another. This does mean things like shebangs
and set
may not be respected.
You can use a mix of file
and run
in the same commands list (or multiples of each):
...
after_install:
- file: ./migration_commands.sh
- file: ./app_commands.txt
- run: systemctl start myapp
When command sections are run
Due to when the different sections are run in the install process, you need to be careful with CLI's and files could exist at the time the command will run.
For example, trying to use the script your package installs in the before_install
section will obviously fail as your software has not been installed yet.
build
commands - run during the build on a PKG Deploy server, not on the end-user machine. This means no absolute paths can be used as you can't assume the file will exist on the build server. Be careful with paths herebefore_install
commands - run before any of the install section has ever been run. After the dependencies stated inrequires
have been checked but before they have been installedbefore_upgrade
commands - run before the install section but your software must have been installed before. Don't assume the user is upgrading the version directly before, it could be a while since they upgradedinstall
commands - Commands needed to actually install the software on the end-user machine. Any commands here can't assume installed files exist yet. Be careful with paths hereafter_install
commands - Run after the install section has finished. You can assume all of the files are in their installed location.after_upgrade
commands - Run after the install section has finished. You can assume all of the files are in their installed location.before_uninstall
commands - Run before installed files are removed from the end-users machineafter_uninstall
commands - Run after all the packaged files are removed from the end-users machine
Paths within commands
Due to timings of when commands outlined above are run, you need to be careful writing commands which interact with files.
There are a few other times when you need to be careful when running commands which interact with files due to where commands are run and where files are located at the time.
Please ensure you use relative paths when referring to files or directories located in your git repository in the build
and install
sections. The relative path starts at the root of the git repository.
Use absolute paths when referring to files or directories on the end-user machine. This includes files and directories that have been installed via your package.
Build section
Not run on the end-user machine. Assume totally blank server except for the git repository you are installing.
Install section
As mentioned above when talking about copying files, install instructions don't use normal paths on the end-user machine. That means it's generally not a good idea to use absolute paths within the commands part of the install section.
As a general rule, if one of your commands assumes a file is in its installed location or modifies a file put in place by a dependency please use the after_install
or after_upgrade
sections.
Staging area paths
WARNING this is not advised. Please be VERY sure you can't put the commands in the after_install
or after_upgrade
keys
It should be mentioned it is possible to define the correct path to any file in the staging area is needed. Below are the paths you can use depending on the package format you are creating:
rpm
- File path must start with%{buildroot}
. For example:rm %{buildroot}/var/lib/myapp/file.txt
deb
- File path must start with%{buildroot}
. For example:rm ${DESTDIR}/var/lib/myapp/file.txt
No user input
Any commands you run that require a prompt / user input will cause the build to fail. You need to ensure that any command you use does not prompt for user input.
E.g. Use rm -f file.txt
instead of rm file.txt