📜 ⬆️ ⬇️

Using deb-packages for code distribution

In this article I want to tell about how you can implement a build system for deb-packages for some abstract project. There are several advantages in distributing and deploying software based on packages:In addition, when deploying software based on packages, and not based on SVN, you are guaranteed to be protected from problems with .svn-folders .

Project structure


And so, consider some web-project my-app, which is under the control of SVN, with the following file structure:
 / | -config
  |  | -parameters.ini
  | -htdocs
  |  | -index.php
  | -libs
  | -templates


Package structure


To build packages, we will need some set of files and scripts, which we will place in the .package folder, which in turn will be added to the project root. The structure of this folder will be as follows:
 /|-.structure
  |  | -DEBIAN
  |  |  | -conffiles
  |  |  | -control
  |  |  | -postinst
  |  |  | -postrm
  |  |  | -preinst
  |  |  | -prerm
  |  |  | -templates
  |  | -etc
  |  | -var
  |  |  | -log
  |  |  | -www
  | -package.xml
  | -package.properties

Essentially, the .structure directory is our future package. The DEBIAN subdirectory contains service files, which will be discussed below. All other directories completely follow the hierarchy of the Debian Linux file system directories. The package.xml and package.properties files contain scripts and settings for creating packages using the Apache Ant utility. But first things first.

Debian Directory


The DEBIAN directory contains project settings files and pre / post install / uninstall scripts.
')
The conffiles file contains a list of configuration files that should not be overwritten during installation:
/etc/my-app/parameters.ini

In our case, the project settings file will be listed here.

The control file contains general information about the package:
Package: my-app
Version: {{{VERSION}}}
Section: user
Priority: optional
Architecture: all
Installed-Size: 0
Maintainer: Mikhail Krestjaninoff <mikhail.krestjaninoff@gmail.com>
Depends: nginx, php5-common (>= 5.2), php5-cli
Description: My application

Special attention in this file deserve the points Version and Depends. We specifically specify the {{{VERSION}}} constant as the version of the package, since we will replace it with the actual value in the future when building the package. In the list of dependencies, we indicated only nginx and php, however, if your project uses any additional packages (for example, php modules), you can explicitly list them, thereby reducing the risks of the project working incorrectly when laying out on the combat server.

The preinst file contains the preset script:
#!/bin/sh

In our case, no preliminary action is required, this file is empty.

The postinst file contains a post-install script. In this case, the script will set permissions, configure the config using the debconf utility and create directories for temporary files:
 #!/bin/sh if [ configure = "$1" ]; then # Set permissions chown -R www-data:www-data /etc/my-app/ chmod -R 0664 /etc/my-app/ chown -R www-data:www-data /var/www/my-app/ chmod -R 0664 /var/www/my-app/ chown -R www-data:www-data /var/log/my-app/ chmod -R 0664 /var/log/my-app/ # Set up configuration file . /usr/share/debconf/confmodule db_input critical db/dsn || true db_go db_fset db/dsn seen false || true db_get db/dsn || true DSN=$RET DSN=`echo "$DSN" | sed 's/\//\\\\\//g'`; sed -is/{{DSN}}/$DSN/ /etc/my-app/parameters.ini # Create directories for temporary files CACHE_DIR="/var/www/my-app/templates/cache" COMPILED_DIR="/var/www/my-app/templates/compiled" if [ ! -d $CACHE_DIR ] then mkdir -p $CACHE_DIR chown -R www-data:www-data $CACHE_DIR chmod -R 0664 $CACHE_DIR fi if [ ! -d $COMPILED_DIR ] then mkdir -p $COMPILED_DIR chown -R www-data:www-data $COMPILED_DIR chmod -R 0664 $COMPILED_DIR fi fi 

If necessary, scripts can also be added to this file to create a project database. With the update of the database, the task is somewhat more complicated. However, you can try to partially resolve it by storing 2 sql files in a project: with a full set of commands to reproduce the structure / data (initial installation) and changes relative to the previous release (for updating).

The prerm file contains the pre-delete script. In this case, the script will delete directories for temporary files:
 #!/bin/sh if [ remove == "$1" -o purge == "$1" ]; then # Remove directories for temporary files CACHE_DIR="/var/www/my-app/templates/cache" if [ -e $CACHE_DIR ]; then rm -rf $CACHE_DIR fi COMPILED_DIR="/var/www/my-app/templates/compiled" if [ -e $COMPILED_DIR ]; then rm -rf $COMPILED_DIR fi fi 


The templates file contains the field templates for the debconf utility:
 Template: db/dsn Type: string Default: postgres://user@passwd:localhost/my-app Description: Database Source Name. Example: postgres://user@passwd:localhost/my-app 

You can read more about the contents of the DEBIAN catalog on opennet or in the official documentation .

Package Build Scripts


Now, in order to create a full-fledged package based on our project, we need to fill in the package file structure (the file system with the root in the .structure directory with data). To do this, you will have to create a small set of scripts that copy the necessary data from the project file system to the package file system. I used Apache Ant for this purpose, with the result that I had the package.xml and package.properties files.

The package.properties file contains settings for building the package:
 package.name=my-app package.version=1.0.0 

The main build script is contained in the package.xml file:
<? xml version ="1.0" encoding ="UTF-8" ? >
< project basedir =".." default ="prepare" name ="package-builder" >

< property file ="./.package/package.properties" />
< property name ="location" value ="." />
< property name ="package.structure" value ="${location}/.package/.structure" />
< property name ="package.source" value ="${location}/.package/source" />
< property name ="package.target" value ="${location}/.package/target" />

<!-- Init project -->
< target name ="init" >
< mkdir dir ="${package.source}" />
< mkdir dir ="${package.target}" />
</ target >

<!-- Clean project -->
< target name ="clean" >
< delete dir ="${package.source}" />
< delete dir ="${package.target}" />
</ target >

<!-- Prepare project files for package -->
< target depends ="init" name ="prepare" >

< copy toDir ="${package.source}" >
< fileset dir ="${package.structure}" >
< include name ="**/*" />
< exclude name =".svn" />
</ fileset >
</ copy >

< mkdir dir ="${package.source}/etc/${package.name}" />
< copy toDir ="${package.source}/etc/${package.name}" >
< fileset dir ="config" >
< include name ="**/*" />
< exclude name =".svn" />
</ fileset >
</ copy >

< mkdir dir ="${package.source}/var/www/${package.name}/htdocs" />
< copy toDir ="${package.source}/var/www/${package.name}/htdocs" >
< fileset dir ="htdocs" >
< include name ="**/*" />
< exclude name =".svn" />
</ fileset >
</ copy >

< mkdir dir ="${package.source}/var/www/${package.name}/libs" />
< copy toDir ="${package.source}/var/www/${package.name}/libs" >
< fileset dir ="libs" >
< include name ="**/*" />
< exclude name =".svn" />
</ fileset >
</ copy >

< mkdir dir ="${package.source}/var/www/${package.name}/templates" />
< copy toDir ="${package.source}/var/www/${package.name}/templates" >
< fileset dir ="templates" >
< include name ="**/*" />
< exclude name =".svn" />
< exclude name ="cache" />
< exclude name ="compiled" />
</ fileset >
</ copy >

</ target >

<!-- Build packege -->
< target depends ="prepare" name ="build" >

<!-- Change owner to root -->
< exec executable ="fakeroot" dir ="${package.source}" >
< arg line ="chown -R root:root ." />
</ exec >

<!-- Allow execution for installation scripts -->
< exec executable ="fakeroot" dir ="${package.source}/DEBIAN" >
< arg line ="chmod 0755 preinst postinst prerm postrm" />
</ exec >

<!-- Set package version -->
< exec executable ="sed" >
< arg line ="-is/{{{VERSION}}}/${package.version}/ ${package.source}/DEBIAN/control" />
</ exec >

<!-- Build package -->
< exec executable ="dpkg-deb" >
< arg line ="--build ${package.source} ${package.target}/${package.name}_${package.version}_all.deb" />
</ exec >

</ target >

</ project >


* This source code was highlighted with Source Code Highlighter .

Build Package


And so, the creation of the .package directory is complete. Now we can commit it to SVN along with the rest of the project. When we need to build a package (for example, give a release / tag for testing or displaying into battle), it will be enough to go to the .package directory and execute the command ant -f package.xml build , which will create a new one for us in the .package / target directory deb package ready to use!

Source: https://habr.com/ru/post/76757/


All Articles