There are many continuous integration & delivery tools, but they are primarily targeted at own
infrastructure. The demand for a new meta-tool is to merge many operations of different
technologies like npm, composer, bundle, nvm, rvm, php-build and others under a single tool for
runtime setup, project development, build, deployment and running.
NOTE: current primary focus is on web projects, but other cases like Puppet modules are supported.
2. Concept
A command line tool must be available through shell search path or called via absolute path.
The command name is "cid" - Continuous Integration & Delivery Tool.
"cid" must work on existing projects with no modifications, but with extra parameters required.
If special "futoin.json" configuration file is present in project root then extra parameters'
default values should be taken from the configuration file.
It should be possible to specify any of the actions manually through configuration file. Otherwise,
the tool should auto-detect action implementation.
The tool should support the following actions:
tag
prepare
build
package
check
promote
deploy
run
ci_build
tool
init
migrate
vcs
rms
service
2.1. Tag
A standard procedure for updating for release and tagging source code.
2.2. Preparation
A standard procedure for project development or release is source checkout, dependency checkout
and workspace configuration.
For build tools, working copy clean up is expected.
2.3. Building
A standard procedure for detecting available build systems and executing them in predefined order.
Binary artifact may be a product of such action.
2.4. Checking
A standard procedure for detecting available test systems and executing them in predefined order.
2.5. Packaging
A standard procedure for detecting packaging method to create a single
binary artifact for deployment.
2.6. Promotion
A standard procedure for promoting a binary package into predefined release
management systems (RMS).
Build - binary artifact, product of clean build process
CIBuilds - RMS pool with development builds without source tagging
ReleaseBuilds - RMS pool with builds from source tags
ProductionBuilds - QA validated and Management approved Release Builds
{Arbitrary} - any custom binary artifact pool
Note: promotion from pool to pool must not modify binary artifacts. Otherwise,
a separate project must exist, which uses original project binary artifact as
dependency for input and own binary artifact promotion chains
2.7. Deployment
The primary focus of the action is for setup of web projects. The process should
properly check requirements, setup file permissions, manage persistent data,
manage configuration and support rolling deployment with no service interruption.
2.8. Running
This action should focused on execution in development and testing process and
may not be implemented at all, if not applicable.
2.9. Integration into provisioning systems
In multi-tenant environments, it may not be desired to give application user
full control over system. However, some tools may require privileged administrator
access for installation and update. Also, it's not desired to have multiple copies
of same tool, but secure sharing is required.
For such cases, an external to CID provisioning system may set external setup
callback command to be used instead of CID itself for tool setup. The external command
is responsible for proper filtering.
For purpose own easy integration, target deploy dir must have auto-generated
".futoin.merged.json" which should include all data from project, deployment, user,
global and runtime. The file must not be manually editable and should be overwitten
on each deployment. CID itself must never consult to it.
As some tools and services may be configured by provisioning system, there are
.env.externalSetup and .env.externalServices configuration options available.
The same identifiers should be used in command line options. All configuration nodes are optional
and auto-detectable in most cases.
Note: this tree represents actual state CID works with. All internal API either work with full
configuration root or only with its .env part. There should be no other configuration data.
3.1.1.1. Project configuration
.name - project's full unique name
.version - project's version
.vcsRepo - source repository
.vcs - version control system type:
"svn"
"git"
"hg"
.deployBuild - force build on deploy, if true
.permissiveChecks - allows check failure, if true
.rmsRepo - binary artifact Release Management System location
.rmsPool - sub-path/pool in .rmsRepo
.rms - release management system type:
"svn" - use Subversion as binary artifact repository
"scp" - use SSHv2 FTP
"archiva" - use Apache Archiva
"artifactory" - use JFrog Artifactory
"nexus" - use Sonatype Nexus
.tools - {}, map of required tool=>version pairs.
Default version is marked as true or '*'.
Tool name is all lower case letters with optional digits (except the first position).
.toolTune - {}, map of maps tool=>settings=>value for fine tuning of tool behavior.
Note: it should be used for build-time tools, but it can also be used for global .entryPoints tuning by tool.
.package - [], content of package relative to project root. Default: [ "." ]
.packageGzipStatic = True, creates .gz files for found .js, .json, .css, .svg and .txt files
.packageChecksums = True, creates .package.checksums of files
.persistent - [], list of persistent read-write directory paths.
Content of related deployment package paths is copied to persistent location.
.writable - [], list of non-persistent read-write directory paths.
.socketProtocol = one of ['http', 'fcgi', 'wsgi', 'rack', 'jsgi', 'psgi']
.debugOverhead - extra memory per instance in "dev" deployment
.debugConnOverhead - extra memory per connection in "dev" deployment
.socketType - generally, for setup in deployment config
.socketPort - default/base port to assign to service
.maxRequestSize - maximal size of single request
.configenv - {} - list of environment variables to be set in deployment
type - FutoIn variable type
desc - variable description
.webcfg - additional web server configuration (to be used by web server)
.root - web root folder relative to project root
.main - default index handler from .entryPoints (auto-select, if single one)
.mounts - {} - path prefix to details in form of:
string - name of related entry point
map - advanced config
.app - name of related entry point
.static = false - try to serve static files, if true
.tune = {} - fine options
.pattern = true - enable other options based on pattern match
.staticGzip = true - try to use pre-compressed "*.gz" files
.gzip = false - compress in transmission
.expires = 'max' - add expires header
.autoindex = false - enable auto-indexing
.index = 'index.html' - default index file
.etag = false - enable ETag
.spaRoutes = false - Single Page Application routes (try URI and then .index)
.actions - {}, optional override of auto-detect commands.
Each either a string or list of strings.
Use '@default' in [] to run the default auto-detected tasks too.
Use of '@default' in deploy config means actions defined/detected in project config.
Start command with '@cid' to invoke FutoIn CID itself.
.tag - custom shell command for tagging
.prepare - custom shell command for source preparation
.build - custom shell command for building from source
.package - custom shell command for binary artifact creation
.promote - custom shell command for binary artifact promotion
.migrate - custom shell command in deployment procedure
.deploy - custom shell command for deployment from binary artifact
.{custom} - any arbitrary user-defined extension to use with "cid run"
.plugins = {} - optional custom plugins, see .env counterpart
.env - {}, the only part allowed to be defined in user or system configs
.type - "prod", "test" and "dev" (default - "prod")
.persistentDir = {.deployDir}/persistent - root for persistent data
.vars - arbitrary environment variables to set on execution
.plugins = {} - custom plugins, implementation defined
$tool => $module_name pair - individual tool
.pluginPacks = [] - custom plugin packs, implementation defined
$module_name - define module providing list of plugins
.binDir = ${HOME}/bin - user bin folder
.externalSetup = false
a shell command to call instead of CID with the same parameters, if set to string
disable tool setup, if true
.externalServices = []
list of tools which should not be accounted in resource distribution
it's expected the tools are externally configured by provisioning system
.timeouts - timeout configuration for various operations (may not be always supported)
.connect = 10 - initial connection timeout
.read = 60 - network timeout for individual read calls
.total = .read * 60 - network timeout for single request
.{tool}Bin - path to "$tool" command line binary
.{tool}Dir - path root "$tool", if applicable
.{tool}Ver - required version of "$tool", if applicable
.{tool}{misc} - any tool-specific misc. configuration
3.1.1.3. Deployment configuration
.deploy
.maxTotalMemory - memory limit for deployment
.maxCpuCount - CPU count the deployment expected to utilize
.listenAddress - address to bind services by default
.user - user for service execution
.group - group for service execution
.runtimeDir = {.deployDir}/.runtime - location for temporary files required for runtime:
UNIX socket files
UNIX pipes
Process ID files
On-the-fly configuration files
.tmpDir = {.deployDir}/.tmp - location for other temporary files
.autoServices - map of lists, to be auto-generated in deployment process
.maxMemory - maximal memory per instance (for deployment config)
.maxCpuCount - maximal CPU count an instance can use (for multiCore)
.maxConnections - expected number of clients the instance can handle
.maxFD - maximal file descriptors
.socketType - one of .entryPoints[.entryPoint].socketTypes
.socketAddress - assigned socket address, if applicable
.socketPort - assigned socket port, if applicable
.socketPath - assigned socket path, if applicable
tool-specific - any tool-specific value like "nginxConf"
3.1.1.4. Runtime configuration (available to plugins)
.target - (dynamic variable) current build target
.vcsRef - (dynamic variable) current branch name
.wcDir - (dynamic variable) working directory name for fresh clone/checkout
.deployDir - (dynamic variable) root for current package deployment
.reDeploy - (dynamic variable) force deploy, if true
.debugBuild - (dynamic variable) build in debug mode
.tool - (dynamic variable) current tool to be used
.toolVer - (dynamic variable) required version for current tool
.toolOrder - (dynamic variable) full ordered by dependency list of active tools
.packageFiles - (dynamic variable), list of packages created by tools
3.1.1.5. Python-based CID implementation notes
.plugins expects to fully qualified module named with {tool}Tool class.
.pluginPacks expect fully qualified module name with submodules
in {tool}tool.py format having {tool}Tool class
3.1.2. Process environment
Each tool may have a whitelist of related environment variables for .env sections.
This variables may be passed through process environment as well. Example:
remove all not managed or obsolete files in {.deployDir}
3.2.7.7. deployment assumptions
Each web application must have own deployment root folder
Each web application should have own user
Each web application should get proper ownership and read-only permissions
Application package must not have modifiable content
Each read-write path should get symlink to {.env.persistentDir}/{path} and survive across deployments
.action.migrate must run and successfully complete
${.deployDir}/current must always point to fully configured deployment
For security reasons it is not possible to include project-specific config
for web server running as root user. Also, sensitive data like TLS private
keys must not be available to application user. Therefore a performance
penalty of reverse proxy may apply, but large high available deployments should
have load balancer/reverse proxy any way.
Lock file must be acquired during deployment procedure.
Not empty {.deploDir} must contain deploy lock file for safety reasons.
3.2.8. cid run [<command> [-- <command_args..>]]
Primary case is execution in development and testing environment.
If command is missing then execute all .entryPoints in parallel
Use single instance per entry point
Use default memory limits
Else if command is present in .entryPoints then execute as related tool
Else if command is present in .actions then execute that in shell
cid rms pool create [--rmsRepo=] - ensure pool exists (may require admin privileges)
cid rms pool list [--rmsRepo=] - list available pools
3.2.15. cid service ...
Interface for Continuous Deployment execution control. It is expected to call this commands
from systemd, sysv-init or other system daemon control functionality.
cid service exec <entry_point> <<instance> [--deployDir=deploy_dir] -
replace CID with foreground execution of pre-configured instance.
cid service stop <entry_point> <<instance> <<pid> [--deployDir=deploy_dir] -
stop previously started instance.
cid service reload <entry_point> <<instance> <<pid> [--deployDir=deploy_dir] -
reload previously started instance.
cid service list [args...] - list services and instance count deployed (to be executed)
[--adapt] - adapt to newly set limits before execution of services
support generic deploy options
In case containers like Docker is used then there is a separate helper command to be used
as entry point:
cid service master [args..] - run deployment-related services as children and restart on failure.
[--adapt] - adapt to newly set limits before execution of services
support generic deploy options
In case there is no deployment, but service run is desired in development process:
cid devserve [args..] - run services as children and restart on failure.
support generic deploy options
Each run creates a new temporary folder
3.2.16. cid build-dep <name>...
Install development files for specific build dependency.
The list of dependencies is implementation-defined.
If build dependency matches supported tool then full initialization of
.config.env is performed.