A tool to create RPM repositories on the fly.
- rpmbuild
- perl
Under redhat, suse etc (yumland)
rpm -i rpmbuilderutil-1.0.0-1.x86_64.rpm
Under debian
alien -i rpmbuilderutil-1.0.0-1.x86_64.rpm
rpmbuilderutil --verbose --config build.json --rpmout /rpm/output/path/ --basepath /path/to/your/file/base/ --target development --help
argument | function | default |
---|---|---|
help | shows a help dialog | |
config | define the configuration file | build.json |
rpmout | output directory for generated rpm | current working dir |
basepath | base directory of your project | current working dir |
target | placeholder for special purpose | "" |
The configuration file contains either a json object or a json array of objects. So you can create different rpm for different server targets at once for example.
[
{
"rpm" : "myprogram-{VERSION}-{RELEASE}.{ARCH}",
"name" : "myprogram",
"version" : "1.0.0",
"target" : "development",
"description" : "myprogram does a lot of stuff"
},
{
"rpm" : "myprogram-{VERSION}-{RELEASE}.{ARCH}",
"name" : "myprogram",
"version" : "1.0.0",
"target" : "production",
"description" : "myprogram does a lot of stuff"
}
]
All elements on the first level will be available for substitutions.
{
"element1" : "{ELEMENT2}.bar",
"element2" : "foo"
}
will be resolved to
{
"element1" : "foo.bar",
"element2" : "foo"
}
The element files is an array of file objects. Those object requires a type, source, destination and mode.
- type available types are file or directory
- source source file path relative to your basepath
- destination destination file path absolute to the new system (prefix /)
- mode mode of the file or directory
{
"rpm" : "myprogram-{VERSION}-{RELEASE}.{ARCH}",
"name" : "myprogram",
"version" : "1.0.0",
"target" : "development",
"description" : "myprogram does a lot of stuff",
"files" : [
{
"type" : "file",
"source" : "/path/to/file",
"destination" : "/usr/local/share/myprogram/file",
"mode" : "0644"
}
]
}
You can install a file that depends on an object element. Use target for this purpose. You can pass it as external argument too.
{
"target" : "development",
"files" : [
{
"type" : "file",
"source" : "myprogram/configuration/myprogram.{TARGET}.conf",
"destination" : "/etc/myprogram.conf",
"mode" : "0644"
}
]
}
This will install /basepath/myproject/configuration/myprogram.development.conf to /etc/myprogram.conf with owner(rw), group(r), other(r) rights. You can also do runtime text substitutions on the files. This will edit the destination file and not the source file.
{
"files" : [
{
"type" : "file",
"source" : "myprogram/script/initd.sh",
"destination" : "/etc/init.d/myprogram",
"mode" : "0755",
"substitution" : {
"MYBINPATH" : "/usr/local/bin/myprogram",
"MYCONFIG" : "/etc/myprogram.conf",
"MYLOGFILE" : "/var/log/myprogram.log"
}
}
]
}
This will edit basepath/myprogram/script/initd.sh and install the result
{
"target" : "development",
"files" : [
{
"type" : "directory",
"source" : "myproject/data/{TARGET}",
"destination" : "/usr/share/myproject/data",
"mode" : "0644"
}
]
}
Installs all files from /basepath/myproject/data/development/ to /usr/share/myproject/data/ with owner(rw), group(r), other(r)
Use include to filter a subset of the files.
{
"target" : "development",
"files" : [
{
"type" : "directory",
"source" : "myproject/data/{TARGET}",
"destination" : "/usr/share/myproject/data",
"mode" : "0644",
"include" : [
".xml",
".foo",
"/images/"
]
}
]
}
If the include string matches the filepath then the file pass the include filter
There are 4 events that could be handled
- preinstall Before the installation starts
- postinstall After the installation is done
- preuninstall Before the uninstall
- postuninstall After the uninstall
You can either put shell commands to the handler or you use build in macros
{
"preinstall": [
"echo 'preinstall'"
],
"postinstall" : [
"echo 'postinstall'",
"macro::touchfile('/var/log/myprogram.log', 'myuser', 'mygroup', '0664')"
],
"preuninstall" : [
"echo 'preuninstall'"
],
"postuninstall" : [
"echo 'postuninstall'"
]
}
- macro::checkfile(path) If path is not a regular file exit with 10
- macro::checkfolder(path) If path is not a folder exit with 11
- macro::execute(cmd) Execute a shell command. If command failed exit with 12
- macro::execute(delete)
- macro::touchfile(path[,owner][,group][,mode]) Creates a file with user, group and file permissions
The element require is a map of requirements.
application:version
Version can have different six comparators.
- > application version must be greater than version
- >= application version must be greater than or equal to version
- = application version must be equal to version
- <= application version must be less than version
- < application version must be less than version
- ***** don't care about the application version
{
"require" : {
"php" : ">=5.3.3",
"apache" : "*",
"perl" : "*"
}
}
This program is a simple perl script that wraps around rpmbuild. It requires rpmbuild and perl. Final exe should be stored under /usr/local/bin/rpmbuilderutil So we have rpmbuilderutil/rpmbuilderutil.pl and we want to deploy this as executable program on other machines. The build.json for this task looks very simple:
{
"rpm" : "rpmbuilderutil-{VERSION}-{RELEASE}.{ARCH}",
"name" : "rpmbuilderutil",
"version" : "1.0.0",
"description" : "Utility tool to create rpm packages on the fly",
"require" : {
"rpmbuild": "*",
"perl" : "*"
},
"files" : [
{
"type" : "file",
"source" : "rpmbuilderutil.pl",
"destination" : "/usr/local/bin/rpmbuilderutil",
"mode" : "0755"
}
]
}
The rpm key defines the rpm output. rpmbuilderutil-{VERSION}-{RELEASE}.{ARCH} will be transformed into something like rpmbuilderutil-1.0.0-1.x86_64(.rpm)
As actor i want to create a deployable rpm of a zf2 (skeleton) application. The rpm should install itself to /var/www/htdocs/, copy target depending config, set the httpd vhost conf /etc/httpd/conf.d/sites-enabled/.conf, set the log path to /var/log/apache2/-error.log and restart the apache after the installation
The following steps should be done by the ci
- checkout the source
- run composer to get dependencies
- run rpmbuilderutil
- push created RPM to artifactory or deploy
By hand
[jami@shodo rpmbuilderutil]# cd example/webapp/
[jami@shodo webapp]# ./composer.phar install
[jami@shodo webapp]# rpmbuilderutil
The deploy by rpm -i webapp-1.0.0-1.x86_64.rpm Finally set your hosts or dns to webapp.localhost
{
"rpm" : "{NAME}-{VERSION}-{RELEASE}.{ARCH}",
"name" : "webapp",
"version" : "1.0.0",
"target" : "development",
"group" : "internet",
"description" : "Webapp that do stuff",
"webroot" : "/var/www/htdocs/{NAME}",
"require" : {
"httpd" : "*",
"php" : ">5.0.0"
},
"files" : [
{
"type" : "file",
"source" : "vhost/vhost.{TARGET}.conf",
"destination" : "/etc/httpd/conf.d/sites-enabled/{NAME}.conf",
"mode" : "0644",
"substitution" : {
"DOCUMENTROOT" : "{WEBROOT}/public",
"LOGERRORPATH" : "/var/log/apache2/webapp-error.log"
}
},
{
"type" : "directory",
"source" : "project",
"destination" : "{WEBROOT}",
"mode" : "0644",
"include" : [
".php",
".phtml",
"public",
"vendor",
"language"
]
},
{
"type" : "file",
"source" : "targetconfig/databases.{TARGET}.php",
"destination" : "{WEBROOT}/config/autoload/databases.local.php",
"mode" : "0644"
}
],
"postinstall" : [
"apachectl restart"
]
}