Arbit - project tracking

Arbit - project tracking

You are viewing an old version of this wiki page. You can also read the most recent version of this page. Last version

Arbit installer

This document discusses the creation of an installer for arbit, which can be easily used by new users to install and test arbit.

Target groups

The following target groups should be kept in mind when designing an installer:

  • Shared-host users

    They are probably the largest, but also most problematic, group of users. Shared-hosts often do have strange setups and might not be accessible by shell. A web-installer is a must for them.

  • Dedicated-server users

    They can already install arbit by executing some CLI commands. A simpler interface for installing and updating an arbit installation would be preferred, though.

  • Administrators

    Administrators of multiple arbit instances or other web applications should be able to manage those smoothly. They are not our primary target for now.

Common use case

The most common use case to install arbit consists of a very few easy steps:

  1. Download arbit installer package.

  2. Copy package to shared host.

  3. Call URL pointing to the installer.

  4. Enter security code, to get access to the installer.

  5. Enter the required data, check for required dependencies, click "Install".

  6. Have access to an usable arbit instance.

Requirements

Our requirements generally match the requirements described by Christian Weiske in a blog post dedicated to PHP web application installers.

Our installer does not need to be skinnable from the start, but it would be nice, to make this kind-of reusable. Also for now we only need to support CouchDB, but support for relational database will also be required at some point. Using something like a Database Schema component seems to be the way to go there.

The full list:

General

  • The installer should run on "any" installation and fail gracefully, if something is not available. This also means that the installer should work with PHP 5.1.4.

  • Handling of dependent tasks. The configuration of a first task might require configuring another additional task. Example for arbit: The selected modules for a project will require configuring those modules.

  • Provided as a single PHP file, or a single directory.

  • Ability to upgrade existing installations.

Security

  • Require creation of file to proceed with installation

    • Or check for existence of a file the user has to create

    • Ask for install password that has been written in a non-webaccessible file on the server

  • Lock installation tool to a single IP address (optional)

  • Remove write rights from whole application directory after installation, if wished even from config file

    • Make installer unavailable after installation

Check and verify system requirements

  • Minimum PHP version

    • PEAR libraries (optional)

    • PHP extensions

  • safe_mode

  • Session availability

  • File upload settings (file_uploads, upload_max_filesize) and post_max_size, perhaps generating .htaccess with correct settings automatically

  • Checking a list of required PHP functions, i.e. exec (disable_functions)

  • Script time limit (max_execution_time)

  • Allowed RAM size (memory_limit) (optional)

  • Writability of directories and files, creating them if necessary (i.e. cache dirs)

  • PHP ini settings

Collecting configuration data

  • Database settings

    • Support for different database systems (optional)

    • Importing an SQL dump from file (optional)

    • Creating the database, possibly with a different user that has admin rights (optional)

    • Checking for connectivity

  • Setting directories i.e. for cache files

  • Setting all kinds of other configuration options (select from array of options, true/false, integer with ranges, email addresses etc.)

  • Defining default config values

  • Titles and longer descriptions for config options

  • Having mandatory and optional settings. Optional ones are skippable.

Interface

  • Skinnable (optional)

  • Wizard-based on multiple pages (optional)

  • Command line (CLI) support

  • Translations (optional)

Ideas

PHAR archives are most probably the way to go, since they provide read access to the included files, and can also provide a web and CLI executable. This would make it possible to upload one single file and run the installer directly from that one.

This could easily satisfy the first two groups of users and implement the given use case. With enough command line options this could also enable mass administration of arbit installations.

Specification language

PEAR uses XML files to specify library installers, which is quite intuitive to do, since everybody can define them and they can be evaluated by PHP code later.

Application installers will most probably require more custom requirement checks and configuration options, which would require to make the XML configuration extensible and load user defined requirement checks / configuration options on request.

Another option is to use a simple PHP script, which defines the Installer in PHP code. This also enables to define XML configuration files later which are evaluated into the same code. Using PHP code for the installer definition would make it easy to add / implement custom requirements and configuration options.

Dependencies

The requirement mentions multiple tasks, or steps during the installation process. Those tasks, or installer modules may depend on each other and may be optional, or depending on the configuration of a prior module.

For example, the arbit phpunit module depends on the source module. On the other hand the source module only has to be configured, if it has been selected as an active module for the current project.

Additional optional tasks can only be determined during the configuration process. Thus configuration options should be able to return a list of additional tasks which need to be executed. Tasks as a project configuration step must be possible to be emitted multiple times ("Configure 3 new projects in arbit during the setup").

An installation process thus may look like:

  1. Main configuration screen. Want 2 projects

    1. Configure project with 3 modules

      1. Configure module 3

      2. Configure module 2

      3. Configure module 1

    2. Configure another project…

During each step requirements of the respective module / task need to be checked, and then configuration options are provided to the user. Each configuration option may cause another set of dependent tasks. Generally the number of tasks should be kept small, since installers with too many configuration options may actually bother a user.

A basic installer definition could look like:

<?php

$i = new Installer();

$i['task1'] = $task1 = new InstallerTask();

//
// Define the requirements, which should be checked by the installer
//
$r = new InstallerRequirements();
$task1->requirements = new InstallerRequirementsAnd(
    // Basic PHP version requirements
    new InstallerRequirementPhpVersion( '5.3.1' ),

    // PHP extension requirements
    new InstallerRequirementPhpExtension( 'pcre', '7' ),
    new InstallerRequirementPhpExtension( 'spl' ),
    new InstallerRequirementsOr(
        new InstallerRequirementPhpExtension( 'gd' ),
        new InstallerRequirementPhpExtension( 'cairo' )
    ),

    // External library requirements
    new InstallerRequirementPearLibrary( 'pear.php.net', 'CodeSniffer', '1.0.3' ),
    new InstallerRequirementPearLibrary( 'components.ez.no', 'Graph', '1.2.1' ),

    // Custom requirements, need to extend from InstallerRequirements
    new myRequirement( '…' )
);

//
// Define the installer configuration options
//
$task1->configuration = $c = new InstallerConfiguration();
$c['notifications'] = new InstallerConfigurationBooleanSetting(
    'Notification',
    'Notify project about installation data.',
    true
);
$c['db'] = new InstallerConfigurationDatabaseSetting(
    'Database',
    'Database used to store project data.',
    array( 'mysql', 'mysqli', 'pdo_mysql', 'couchdb' )
);
// Custom configuration directives can then also be implemented and used…
$c['my'] = new mySetting( '…' );

$task1->action[] = new InstallerActionCopySource( … );
$task1->action[] = new InstallerActionCreateDirectory( … );
$task1->action[] = new InstallerActionUpdateConfiguration( … );

$task1->verfication = new InstallerVerifications(
    new InstallerVerficationFileHashes( array(
        'file' => 'hash', …
    ) )
);

//
// Configure source and generate installer from that
//
$i->source(
    // Can additionally use FilterIterators, etc.
    new RecursiveDirectoryIterator( '/path/to/project' )
);

$phar = new InstallerGeneratorPhar();
$phar->webInstaller->setCustomCss( '/path/to/css.php' );
$phar->package( $i, 'installer.phar' );


The basic structure enables any bool combination of requirements, and even dependency of requirements for each task.

Configuration options must be visited into web installers and CLI installers, which then can automatically define the required CLI arguments to provide settings directly with the command non-interactively. As mentioned earlier each configuration may return an array with additional tasks which need to be executed.

It should / would also be possible to implement different installer generators. For arbit, with the PHP 5.3 dependency, we would only need to generate a PHAR installer, but it could also be sensible to define other generators, which, for example, generate an index.php for the installer and store all required data in directory structures which need to be extracted to the target host. It could also be possible to write an installer which fetches the actual project data on request during the installation process.

Design

A basic installer consists of tasks, which each consist of the following parts:

Requirements

Basic requirements, which can be checked before the installation starts, like required PHP extensions or required PHP version.

Configuration options

The configuration options define properties of the installation and should be provided before the installation starts. Some of those configuration options need to be serialized into application configuration options later, some are just important during the installation process itself. Configuration options need to verify their provided values, like a database configuration option may verify that the provided connection information actually works.

Actions

Actions may just be copying the source code, but there also might be several scripts, which need to be executed after the source has been installed. Maybe to update application config values with values provided during the installation, or setting directories writable for caching, etc.

Verification

The verification can be optional, but may be used to check if everything went OK during the installation or for example even ensure the files have been stored successfully by comparing their hash sums.

The example showed only one tasks, there may, of course, be any number of installation tasks.

Execution

The installer will start with a configured starting task, and execute its requirements and configuration stage. This will be continued for each dependent task, which resulted from the configuration of the first task following a DFS algorithm scheme.

After all configuration data has been aggregated the actions will be executed, which, of course, will have access to all configuration data. The actions then may copy source to the installation target directory and also update configuration files, handle general file system operations, etc.

Writing to some configuration file should be possible for different formats, e.g. yaml, ini, xml. Probably make it possible to add some custom writer.