{"id":19427262,"url":"https://github.com/theasp/mini-ci","last_synced_at":"2025-04-24T17:31:25.288Z","repository":{"id":24488552,"uuid":"27893159","full_name":"theasp/mini-ci","owner":"theasp","description":"A lightweight continuous integration daemon","archived":false,"fork":false,"pushed_at":"2017-03-25T14:12:58.000Z","size":206,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-03T08:51:25.837Z","etag":null,"topics":["bash","continuous-integration","git","subversion"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theasp.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-11T21:48:10.000Z","updated_at":"2023-12-17T15:08:17.000Z","dependencies_parsed_at":"2022-07-10T11:16:17.823Z","dependency_job_id":null,"html_url":"https://github.com/theasp/mini-ci","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theasp%2Fmini-ci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theasp%2Fmini-ci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theasp%2Fmini-ci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theasp%2Fmini-ci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theasp","download_url":"https://codeload.github.com/theasp/mini-ci/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250674321,"owners_count":21469198,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","continuous-integration","git","subversion"],"created_at":"2024-11-10T14:11:06.210Z","updated_at":"2025-04-24T17:31:24.968Z","avatar_url":"https://github.com/theasp.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003c!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\"\u003e\n\u003chead\u003e\n\u003ctitle\u003eMini-CI\u003c/title\u003e\n\u003c!-- 2015-02-18 Wed 21:04 --\u003e\n\u003cmeta  http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" /\u003e\n\u003cmeta  name=\"generator\" content=\"Org-mode\" /\u003e\n\u003cmeta  name=\"author\" content=\"Andrew Phillips\" /\u003e\n\u003cstyle type=\"text/css\"\u003e\n \u003c!--/*--\u003e\u003c![CDATA[/*\u003e\u003c!--*/\n  .title  { text-align: center; }\n  .todo   { font-family: monospace; color: red; }\n  .done   { color: green; }\n  .tag    { background-color: #eee; font-family: monospace;\n            padding: 2px; font-size: 80%; font-weight: normal; }\n  .timestamp { color: #bebebe; }\n  .timestamp-kwd { color: #5f9ea0; }\n  .right  { margin-left: auto; margin-right: 0px;  text-align: right; }\n  .left   { margin-left: 0px;  margin-right: auto; text-align: left; }\n  .center { margin-left: auto; margin-right: auto; text-align: center; }\n  .underline { text-decoration: underline; }\n  #postamble p, #preamble p { font-size: 90%; margin: .2em; }\n  p.verse { margin-left: 3%; }\n  pre {\n    border: 1px solid #ccc;\n    box-shadow: 3px 3px 3px #eee;\n    padding: 8pt;\n    font-family: monospace;\n    overflow: auto;\n    margin: 1.2em;\n  }\n  pre.src {\n    position: relative;\n    overflow: visible;\n    padding-top: 1.2em;\n  }\n  pre.src:before {\n    display: none;\n    position: absolute;\n    background-color: white;\n    top: -10px;\n    right: 10px;\n    padding: 3px;\n    border: 1px solid black;\n  }\n  pre.src:hover:before { display: inline;}\n  pre.src-sh:before    { content: 'sh'; }\n  pre.src-bash:before  { content: 'sh'; }\n  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }\n  pre.src-R:before     { content: 'R'; }\n  pre.src-perl:before  { content: 'Perl'; }\n  pre.src-java:before  { content: 'Java'; }\n  pre.src-sql:before   { content: 'SQL'; }\n\n  table { border-collapse:collapse; }\n  caption.t-above { caption-side: top; }\n  caption.t-bottom { caption-side: bottom; }\n  td, th { vertical-align:top;  }\n  th.right  { text-align: center;  }\n  th.left   { text-align: center;   }\n  th.center { text-align: center; }\n  td.right  { text-align: right;  }\n  td.left   { text-align: left;   }\n  td.center { text-align: center; }\n  dt { font-weight: bold; }\n  .footpara:nth-child(2) { display: inline; }\n  .footpara { display: block; }\n  .footdef  { margin-bottom: 1em; }\n  .figure { padding: 1em; }\n  .figure p { text-align: center; }\n  .inlinetask {\n    padding: 10px;\n    border: 2px solid gray;\n    margin: 10px;\n    background: #ffffcc;\n  }\n  #org-div-home-and-up\n   { text-align: right; font-size: 70%; white-space: nowrap; }\n  textarea { overflow-x: auto; }\n  .linenr { font-size: smaller }\n  .code-highlighted { background-color: #ffff00; }\n  .org-info-js_info-navigation { border-style: none; }\n  #org-info-js_console-label\n    { font-size: 10px; font-weight: bold; white-space: nowrap; }\n  .org-info-js_search-highlight\n    { background-color: #ffff00; color: #000000; font-weight: bold; }\n  /*]]\u003e*/--\u003e\n\u003c/style\u003e\n\u003cscript type=\"text/javascript\"\u003e\n/*\n@licstart  The following is the entire license notice for the\nJavaScript code in this tag.\n\nCopyright (C) 2012-2013 Free Software Foundation, Inc.\n\nThe JavaScript code in this tag is free software: you can\nredistribute it and/or modify it under the terms of the GNU\nGeneral Public License (GNU GPL) as published by the Free Software\nFoundation, either version 3 of the License, or (at your option)\nany later version.  The code is distributed WITHOUT ANY WARRANTY;\nwithout even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.\n\nAs additional permission under GNU GPL version 3 section 7, you\nmay distribute non-source (e.g., minimized or compacted) forms of\nthat code without the copy of the GNU GPL normally required by\nsection 4, provided you include this license notice and a URL\nthrough which recipients can access the Corresponding Source.\n\n\n@licend  The above is the entire license notice\nfor the JavaScript code in this tag.\n*/\n\u003c!--/*--\u003e\u003c![CDATA[/*\u003e\u003c!--*/\n function CodeHighlightOn(elem, id)\n {\n   var target = document.getElementById(id);\n   if(null != target) {\n     elem.cacheClassElem = elem.className;\n     elem.cacheClassTarget = target.className;\n     target.className = \"code-highlighted\";\n     elem.className   = \"code-highlighted\";\n   }\n }\n function CodeHighlightOff(elem, id)\n {\n   var target = document.getElementById(id);\n   if(elem.cacheClassElem)\n     elem.className = elem.cacheClassElem;\n   if(elem.cacheClassTarget)\n     target.className = elem.cacheClassTarget;\n }\n/*]]\u003e*///--\u003e\n\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cdiv id=\"content\"\u003e\n\u003ch1 class=\"title\"\u003eMini-CI\u003c/h1\u003e\n\u003cdiv id=\"table-of-contents\"\u003e\n\u003ch2\u003eTable of Contents\u003c/h2\u003e\n\u003cdiv id=\"text-table-of-contents\"\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#sec-1\"\u003e1. Introduction\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-2\"\u003e2. Features\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-3\"\u003e3. Installation\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#sec-3-1\"\u003e3.1. Ubuntu PPA\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-3-2\"\u003e3.2. From Source\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-4\"\u003e4. Usage\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-5\"\u003e5. Configuration\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-6\"\u003e6. Contents of a Job Directory\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#sec-6-1\"\u003e6.1. \u003ccode\u003econfig\u003c/code\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-6-2\"\u003e6.2. \u003ccode\u003etasks.d\u003c/code\u003e\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-7\"\u003e7. Examples\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#sec-7-1\"\u003e7.1. Mini-CI Job Directory\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-7-2\"\u003e7.2. Starting the Mini-CI Daemon as a User\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-7-3\"\u003e7.3. Notifying a Mini-CI Daemon from GIT\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-8\"\u003e8. Plugin API\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#sec-8-1\"\u003e8.1. Repository Plugins\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-8-2\"\u003e8.2. Notification Plugins\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-8-3\"\u003e8.3. Generic Hooks\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#sec-8-4\"\u003e8.4. Example Plugin\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-1\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-1\"\u003e\u003cspan class=\"section-number-2\"\u003e1\u003c/span\u003e Introduction\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-1\"\u003e\n\u003cp\u003e\nMini-CI is a small daemon to perform continuous integration (CI) for a single repository/project.  Most other CI software is complicated to setup and use due to feature bloat and hiding what is going on underneath with GUIs.  If you know how to build your project from the command line, setting up Mini-CI should be easy.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-2\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-2\"\u003e\u003cspan class=\"section-number-2\"\u003e2\u003c/span\u003e Features\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-2\"\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eNO web interface!\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eConfiguration is done with a small config file and shell scripts.\n\u003c/li\u003e\n\u003cli\u003eDaemon controlled through a command.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eNO user authentication!\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eUnix already has multiple users, use groups or make a shared account.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eNO support for multiple projects!\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eYou can run it more than once…\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003ePlugin system\n\u003c/li\u003e\n\u003cli\u003eLow resource requirements.\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eJust a small bash script.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eCan monitor any repository and use any build system.\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eThe only limits are the scripts you provide.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-3\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-3\"\u003e\u003cspan class=\"section-number-2\"\u003e3\u003c/span\u003e Installation\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-3\"\u003e\n\u003c/div\u003e\u003cdiv id=\"outline-container-sec-3-1\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-3-1\"\u003e\u003cspan class=\"section-number-3\"\u003e3.1\u003c/span\u003e Ubuntu PPA\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-3-1\"\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eStable release: \u003ca href=\"https://launchpad.net/~theasp/+archive/ubuntu/mini-ci\"\u003ehttps://launchpad.net/~theasp/+archive/ubuntu/mini-ci\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003eSnapshot release: \u003ca href=\"https://launchpad.net/~theasp/+archive/ubuntu/mini-ci-snapshot\"\u003ehttps://launchpad.net/~theasp/+archive/ubuntu/mini-ci-snapshot\u003c/a\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-3-2\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-3-2\"\u003e\u003cspan class=\"section-number-3\"\u003e3.2\u003c/span\u003e From Source\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-3-2\"\u003e\n\u003cp\u003e\nTo install into \u003ccode\u003e/usr/local\u003c/code\u003e:\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003emake clean install\n\u003c/pre\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\nTo install into your home directory (\u003ccode\u003e~/opt/mini-ci\u003c/code\u003e):\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003emake clean install \u003cspan style=\"color: #ffd787;\"\u003eprefix\u003c/span\u003e=~/opt/mini-ci\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-4\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-4\"\u003e\u003cspan class=\"section-number-2\"\u003e4\u003c/span\u003e Usage\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-4\"\u003e\n\u003cp\u003e\nFrom the output of \u003ccode\u003emini-ci --help\u003c/code\u003e:\n\u003c/p\u003e\n\u003cpre class=\"example\"\u003e\nUsage: mini-ci [option ...] [command ...]\n\nOptions:\n  -d|--job-dir \u003cdir\u003e       directory for job\n  -c|--config-file \u003cfile\u003e  config file to use, relative to job-dir\n  -m|--message [timeout]   send commands to running daemon, then exit\n  -o|--oknodo              exit quietly if already running\n  -D|--debug               log debugging information\n  -F|--foreground          do not become a daemon, run in foreground\n  -h|--help                show usage information and exit\n\nCommands:\n  status  log the current status\n  poll    poll the source code repository for updates, queue update if\n          updates are available\n  update  update the source code repository, queue tasks if updates are made\n  tasks   run the tasks in the tasks directory\n  clean   remove the work directory\n  abort   abort the currently running command\n  quit|shutdown\n          shutdown the daemon, aborting any running command\n  reload  reread the config file, aborting any running command\n\nCommands given while not in message mode will be queued.  For instance\nthe following command will have a repository polled for updates (which\nwill trigger update and tasks if required) then quit.\n  mini-ci -d \u003cdir\u003e -F poll quit\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-5\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-5\"\u003e\u003cspan class=\"section-number-2\"\u003e5\u003c/span\u003e Configuration\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-5\"\u003e\n\u003cp\u003e\nYou can configure a Mini-CI job by copying the \u003ccode\u003eskeleton\u003c/code\u003e directory somewhere and then editing where required.  This directory is referred to has the \"job directory\".  The skeleton contains the file \u003ccode\u003econfig\u003c/code\u003e and the directory \u003ccode\u003etasks.d\u003c/code\u003e, see their description later.  Once you have the configuration in place you can try it by running \u003ccode\u003emini-ci -F\u003c/code\u003e in the directory you created, which will run Mini-CI in the foreground.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-6\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-6\"\u003e\u003cspan class=\"section-number-2\"\u003e6\u003c/span\u003e Contents of a Job Directory\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-6\"\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003e\u003ccode\u003econfig\u003c/code\u003e: The configuration file for the job.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etasks.d\u003c/code\u003e: Contains all the tasks that would be executed during a build of your repository\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eplugins.d\u003c/code\u003e: Contains any additional plugins to be used for this job.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebuilds\u003c/code\u003e: The builds directory contains the output of each build of a job in numbered directories.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eworkspace\u003c/code\u003e: The directory your repository is checked out into, and built in.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emini-ci.log\u003c/code\u003e: The main log for Mini-CI.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003epoll.log\u003c/code\u003e: The log for the last poll operation.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etasks.log\u003c/code\u003e: The log for the last tasks operation.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eupdate.log\u003c/code\u003e: The log for the last update operation.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003econtrol.fifo\u003c/code\u003e: This is a FIFO used to communicate with the Mini-CI daemon.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-6-1\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-6-1\"\u003e\u003cspan class=\"section-number-3\"\u003e6.1\u003c/span\u003e \u003ccode\u003econfig\u003c/code\u003e\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-6-1\"\u003e\n\u003cp\u003e\nThe \u003ccode\u003econfig\u003c/code\u003e file is a shell script that is sourced when Mini-CI is started which contains the configuration to use for your job.  Every option should have sane defaults, so feel free to only have the entries you wish to use.  If you want a variable exported during your job, for instance \u003ccode\u003ePATH\u003c/code\u003e, this would also be a good place to do so.\n\u003c/p\u003e\n\n\u003cp\u003e\nThe \u003ccode\u003econfig\u003c/code\u003e file in \u003ccode\u003eskeleton\u003c/code\u003e is:\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eAll paths are relative to the job directory.\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e####################\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eMain Configuration\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eJOB_NAME: The name of the job.  Defaults to \"$(\u003c/span\u003e\u003cspan style=\"color: #ff875f;\"\u003ebasename\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e $JOB_DIR)\"\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eJOB_NAME\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"$(\u003c/span\u003e\u003cspan style=\"color: #ff875f;\"\u003ebasename\u003c/span\u003e\u003cspan style=\"color: #ffaf87;\"\u003e $JOB_DIR)\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eREPO_PLUGIN: This is the name of a plugin that will handle\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003erepository actions.  The following plugins come with Mini-CI:\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e- git\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e- svn\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e- external\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eREPO_PLUGIN\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"\u003cplugin\u003e\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ePOLL_FREQ: If this is set to a number greater than zero, it will\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003epoll the repository using the repo-handler every this many seconds,\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003estarting at startup.  To have a more complicated scheme, use cron.\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eDefaults to 600.\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003ePOLL_FREQ\u003c/span\u003e=600\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ePOLL_DELAY: If this is set to a number greater than zero, mini-ci\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ewill sleep this many seconds after a poll that indicates a change\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ewas made in the repository.  Use this to delay doing an update to\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eallow a series of commits to take place.  Defaults to 0.\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003ePOLL_DELAY\u003c/span\u003e=0\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eWORKSPACE: The directory where the repository will be checked out\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003einto, and where tasks are launched.  Defaults to \"./workspace\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eWORKSPACE\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./workspace\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eTASKS_DIR: The directory which holds the tasks to be performed on\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ethe checked out repository.  Defaults to \"./tasks.d\"\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eTASKS_DIR\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./tasks.d\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eBUILDS_DIR: The directory which stores the output of each build when\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003etasks run.  Defaults to \"./builds\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eBUILDS_DIR\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./builds\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eCONTROL_FIFO: The fifo that mini-ci will read to accept commands.\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eDefaults to \"./control.fifo\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eCONTROL_FIFO\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./control.fifo\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ePID_FILE: The file containing the process ID for mini-ci.  Defaults\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eto \"./minici.pid\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003ePID_FILE\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./mini-ci.pid\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eSTATUS_FILE: A file where status information is kept.  Defaults to\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e\"./status\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eSTATUS_FILE\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./status\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ePOLL_LOG: Name of the poll log.  Defaults to \"./poll.log\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003ePOLL_LOG\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./poll.log\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eUPDATE_LOG: Name of the update log.  Defaults to \"./update.log\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eUPDATE_LOG\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./update.log\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eTASKS_LOG: Name of the tasks log.  Defaults to \"./tasks.log\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eTASKS_LOG\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./tasks.log\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eMINICI_LOG: Name of the mini-ci log.  Defaults to \"./mini-ci.log\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eMINICI_LOG\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"./mini-ci.log\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e####################\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ePlugin Configuration\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eGIT_URL: The URL to the repository.  Fetching the URL must not ask\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003efor a username or password.  Use ~/.netrc or ssh keys for remote\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003erepositories.\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e#\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eGIT_URL=\"\u003curl\u003e\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eGIT_BRANCH: The branch of the repository.  Only affects the initial\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003echeckout.  Defaults to \"master\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eGIT_BRANCH\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"master\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eSVN_URL: The URL to the repository.  Fetching the URL must not ask\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003efor a username or password.  Use ~/.netrc or ssh keys for remote\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003erepositories.\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e#\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eSVN_URL=\"\u003curl\u003e\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eEMAIL_NOTIFY: A space and/or comma separated list of conditions to\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003enotify about.  Valid options are \"NEVER\", \"ERROR\", \"OK\", \"UNKNOWN\",\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e\"RECOVER\" (when a state changes from \"ERROR\" or \"UNKNOWN\" to \"OK\")\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eand \"NEWPROB\" (when a state changes from \"OK\" to \"ERROR\" or\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e\"UNKNOWN\").  Defaults to \"NEWPROB, RECOVER\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eEMAIL_NOTIFY\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"NEWPROB, RECOVER\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eEMAIL_ADDRESS: A space and/or comma separated list of addresses to\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eemail.  If not specified, will be sent to the user that is running\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ethe script.  Defaults to \"\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eEMAIL_ADDRESS\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eEMAIL_SUBJECT: The subject to have for notification emails.\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eDefaults to \"Mini-CI Notification - $JOB_NAME\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eEMAIL_SUBJECT\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"Mini-CI Notification - $JOB_NAME\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eBUILD_ARCHIVE_WORKSPACE: When set to \"yes\" will copy the workspace into\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ethe $BUILDS_DIR/$BUILD_NUM/workspace.  Defaults to \"no\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eBUILD_ARCHIVE_WORKSPACE\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eBUILD_KEEP: If this is set to a number greater than zero, only this\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003emany build log directories will be kept.  Defaults to \"0\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eBUILD_KEEP\u003c/span\u003e=0\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eBUILD_DEPENDENCY_LIST: This is a list of status files, seperated by\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003espaces, for other Mini-CI jobs that will cause tasks to wait until\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003ethey are \"idle\" and the status of their tasks is \"OK\".  Defaults to\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e\"\".\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eBUILD_DEPENDENCY_LIST\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"\"\u003c/span\u003e\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eBUILD_DEPENDENCY_TIMEOUT: The number of seconds to wait for\u003c/span\u003e\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003edependencies to be ready.  Defaults to \"1200\" (20 minutes).\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eBUILD_DEPENDENCY_TIMEOUT\u003c/span\u003e=1200\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-6-2\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-6-2\"\u003e\u003cspan class=\"section-number-3\"\u003e6.2\u003c/span\u003e \u003ccode\u003etasks.d\u003c/code\u003e\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-6-2\"\u003e\n\u003cp\u003e\nThe \u003ccode\u003etasks.d\u003c/code\u003e directory contains all the tasks that would be executed during a build of your repository.  The \u003ccode\u003eskeleton\u003c/code\u003e contains a few examples.  Each script must match the regular expression \u003ccode\u003e^[a-zA-Z0-9_-]+$\u003c/code\u003e and will be ran in sort order, therefore it is recommended that each script be named in the form \u003ccode\u003e\u003cnnn\u003e-\u003cdescription_of_task\u003e\u003c/code\u003e.  If a script exits with a return code that is not zero, it is considered a build error and no further scripts are executed.\n\u003c/p\u003e\n\n\u003cp\u003e\nMini-CI exports the following variables:\n\u003c/p\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003e\u003ccode\u003eMINI_CI_DIR\u003c/code\u003e: The data directory for Mini-CI\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMINI_CI_VER\u003c/code\u003e: The version of the Mini-CI running\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBUILD_DISPLAY_NAME\u003c/code\u003e: The build number with \"#\" prepended.  i.e. \"#123\"\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBUILD_ID\u003c/code\u003e: The date and time the build started in the following format:  \u003ccode\u003e%Y-%m-%d_%H-%M-%S\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBUILD_OUTPUT_DIR\u003c/code\u003e: The directory used for storage for the current build\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBUILD_NUMBER\u003c/code\u003e: The current build number.\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBUILD_TAG\u003c/code\u003e: A string of the form: \u003ccode\u003emini-ci-${JOB_NAME}-${JOB_NUMBER}\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJOB_DIR\u003c/code\u003e: The directory where the job is stored\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJOB_NAME\u003c/code\u003e: Name of the the job\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWORKSPACE\u003c/code\u003e: The current workspace directory\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGIT_URL\u003c/code\u003e: The URL of the GIT repository (when using the GIT plugin)\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSVN_URL\u003c/code\u003e: The URL of the Subversion repository (when using the Subversion plugin)\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-7\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-7\"\u003e\u003cspan class=\"section-number-2\"\u003e7\u003c/span\u003e Examples\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-7\"\u003e\n\u003c/div\u003e\u003cdiv id=\"outline-container-sec-7-1\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-7-1\"\u003e\u003cspan class=\"section-number-3\"\u003e7.1\u003c/span\u003e Mini-CI Job Directory\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-7-1\"\u003e\n\u003cp\u003e\nThis example will configure to monitor Mini-CI's GIT repository and run tests whenever it's updated.\n\u003c/p\u003e\n\n\u003cp\u003e\nCreate and enter a directory called \u003ccode\u003emini-ci-job\u003c/code\u003e, then place the following in \u003ccode\u003econfig\u003c/code\u003e:\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #ffd787;\"\u003eREPO_PLGUIN\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"git\"\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003eGIT_URL\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"https://github.com/theasp/mini-ci\"\u003c/span\u003e\n\u003cspan style=\"color: #ffd787;\"\u003ePOLL_FREQ\u003c/span\u003e=600\n\u003c/pre\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\nThis configuration will use the GIT repository handler with the URL to the Mini-CI repository, and then poll it every 10 minutes.\n\u003c/p\u003e\n\n\u003cp\u003e\nCreate the directory \u003ccode\u003etasks.d\u003c/code\u003e, then place the following file in \u003ccode\u003etasks.d/100-make\u003c/code\u003e\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #ff8700;\"\u003e#\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e!/bin/\u003c/span\u003e\u003cspan style=\"color: #00ffff;\"\u003esh\u003c/span\u003e\n\n\u003cspan style=\"color: #afd7d7;\"\u003eset\u003c/span\u003e -ex\n\n\u003cspan style=\"color: #ff8700;\"\u003e# \u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003eOverride the prefix to install into ~/opt/mini-ci\u003c/span\u003e\nmake \u003cspan style=\"color: #ffd787;\"\u003eprefix\u003c/span\u003e=~/opt/mini-ci\n\u003c/pre\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\nPlace the following file in \u003ccode\u003etasks.d/500-run_tests\u003c/code\u003e:\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #ff8700;\"\u003e#\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e!/bin/\u003c/span\u003e\u003cspan style=\"color: #00ffff;\"\u003esh\u003c/span\u003e\nmake test\n\u003c/pre\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\nRun \u003ccode\u003echmod +x tasks.d/500-run_tests\u003c/code\u003e to make the script executable.  Now when you run \u003ccode\u003emini-ci -F\u003c/code\u003e in the job directory you will get:\n\u003c/p\u003e\n\n\u003cpre class=\"example\"\u003e\n2014-12-18 17:20:03 mini-ci/7145 Starting up\n2014-12-18 17:20:05 mini-ci/7369 Missing workdir, doing update instead\n2014-12-18 17:20:05 mini-ci/7145 Updating workspace\n2014-12-18 17:20:06 mini-ci/7145 Update finished sucessfully, queuing tasks\n2014-12-18 17:20:06 mini-ci/7145 Mailing update notification to user due to RECOVER (New:OK Old:UNKNOWN)\n2014-12-18 17:20:06 mini-ci/7145 Mailing poll notification to user due to RECOVER (New:OK Old:UNKNOWN)\n2014-12-18 17:20:07 mini-ci/7145 Starting tasks as run number 1\n2014-12-18 17:20:07 mini-ci/7145 Tasks finished sucessfully, run number 1\n2014-12-18 17:20:07 mini-ci/7145 Mailing tasks notification to user due to RECOVER (New:OK Old:UNKNOWN)\n\u003c/pre\u003e\n\n\u003cp\u003e\nMini-CI started in foreground mode, downloaded the repository, then ran all the tasks in the \u003ccode\u003etasks.d\u003c/code\u003e directory.  Notice that it also sent 3 mail notifications due to update, poll and tasks transitioning from \u003ccode\u003eUNKNOWN\u003c/code\u003e to \u003ccode\u003eRECOVER\u003c/code\u003e.  The default email settings will only send mail when they change state.  The process is still running and will check the repository for changes every 10 minutes.\n\u003c/p\u003e\n\n\u003cp\u003e\nYou can stop the daemon by pressing \u003ccode\u003ectrl-c\u003c/code\u003e, or by running \u003ccode\u003emini-ci -m quit\u003c/code\u003e in the job directory in another shell.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-7-2\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-7-2\"\u003e\u003cspan class=\"section-number-3\"\u003e7.2\u003c/span\u003e Starting the Mini-CI Daemon as a User\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-7-2\"\u003e\n\u003cp\u003e\nThe easiest way to run Mini-CI as a user is to have \u003ccode\u003ecron\u003c/code\u003e start it.  For instance, the following crontab will start Mini-CI every 10 minutes, and if it is already running for that job directory it will exit quietly, otherwise it will poll the repository for any updates it missed when it starts:\n\u003c/p\u003e\n\u003cpre class=\"example\"\u003e\n*/10 * * * * mini-ci --oknodo -d ~/some-mini-ci-job-directory poll\n\u003c/pre\u003e\n\n\u003cp\u003e\nMini-CI will run in the background doing it's thing whenever it needs to.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv id=\"outline-container-sec-7-3\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-7-3\"\u003e\u003cspan class=\"section-number-3\"\u003e7.3\u003c/span\u003e Notifying a Mini-CI Daemon from GIT\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-7-3\"\u003e\n\u003cp\u003e\nYou can have git notify Mini-CI upon every push to a repository, which makes polling the repository unnecessary.  Put this in \u003ccode\u003ehooks/post-update\u003c/code\u003e in your git repository directory (or \u003ccode\u003e.git/hooks/post-update\u003c/code\u003e if you aren't using a bare repository), and it will send a message to Mini-CI to do an update, which will trigger a build.\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #ff8700;\"\u003e#\u003c/span\u003e\u003cspan style=\"color: #ff8700;\"\u003e!/bin/\u003c/span\u003e\u003cspan style=\"color: #00ffff;\"\u003esh\u003c/span\u003e\n\n\u003cspan style=\"color: #afd7d7;\"\u003eset\u003c/span\u003e -e\nmini-ci -d ~/some-mini-ci-job-directory -m update\n\u003c/pre\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\nYou can easily change the above script to SSH to another system, or user.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-8\" class=\"outline-2\"\u003e\n\u003ch2 id=\"sec-8\"\u003e\u003cspan class=\"section-number-2\"\u003e8\u003c/span\u003e Plugin API\u003c/h2\u003e\n\u003cdiv class=\"outline-text-2\" id=\"text-8\"\u003e\n\u003cp\u003e\nMini-CI can be extended with plugins written as bash functions.  Any plugin matching \u003ccode\u003e*.sh\u003c/code\u003e in the \u003ccode\u003eplugins.d\u003c/code\u003e directory in either the Mini-CI installation path or the current job directory will be sourced when Mini-CI starts up.  Plugins must declare their variables using \u003ccode\u003edeclare\u003c/code\u003e (or \u003ccode\u003edeclare -x\u003c/code\u003e if the variable is to be exported).  Variables that are to be set using the config file should be set the default value using a function of the name \u003ccode\u003eplugin_on_load_config_pre_\u003cname\u003e\u003c/code\u003e.  In most cases the plugin's functions will run in the same shell as the rest of Mini-CI so that the plugin can modify variables, but this also introduces the chance that a plugin will introduce unwanted side-effects.\n\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-8-1\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-8-1\"\u003e\u003cspan class=\"section-number-3\"\u003e8.1\u003c/span\u003e Repository Plugins\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-8-1\"\u003e\n\u003cp\u003e\nRepository plugins are ran in a subshell with \u003ccode\u003eSTDOUT\u003c/code\u003e redirected to the appropriate logfile.  A repository plugin must provide the following functions:\n\u003c/p\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003e\u003ccode\u003eplugin_repo_update_\u003cname\u003e\u003c/code\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eMust exit with a return code of 0 if successful.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eplugin_repo_poll_\u003cname\u003e\u003c/code\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eMust exit with a return code of 0 if successful.\n\u003c/li\u003e\n\u003cli\u003eMust exit with a return code of 1 if there is an error.\n\u003c/li\u003e\n\u003cli\u003eMust exit with a return code of 2 if the repository is out of date.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-8-2\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-8-2\"\u003e\u003cspan class=\"section-number-3\"\u003e8.2\u003c/span\u003e Notification Plugins\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-8-2\"\u003e\n\u003cp\u003e\nA notification plugin must provide a function named \u003ccode\u003eplugin_notify_\u003cname\u003e\u003c/code\u003e, which accepts the following arguments:\n\u003c/p\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003eitem: The name of the state that triggered the notification, i.e. \u003ccode\u003epoll\u003c/code\u003e, \u003ccode\u003eupdate\u003c/code\u003e, \u003ccode\u003etasks\u003c/code\u003e, etc.\n\u003c/li\u003e\n\u003cli\u003eold: The old status of that state, i.e. \u003ccode\u003eUNKNOWN\u003c/code\u003e, \u003ccode\u003eERROR\u003c/code\u003e, or \u003ccode\u003eOK\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003eold\u003csub\u003etime\u003c/sub\u003e: The time in epoch seconds the old status was set\n\u003c/li\u003e\n\u003cli\u003enew: The new status of the state\n\u003c/li\u003e\n\u003cli\u003enew\u003csub\u003etime\u003c/sub\u003e: The time in epoch seconds the new status was set\n\u003c/li\u003e\n\u003cli\u003eactive\u003csub\u003estates\u003c/sub\u003e: A string containing one of \u003ccode\u003eOK\u003c/code\u003e, \u003ccode\u003eERROR\u003c/code\u003e, \u003ccode\u003eUNKNOWN\u003c/code\u003e, additionally it may contain \u003ccode\u003eNEWPROB\u003c/code\u003e or \u003ccode\u003eRECOVER\u003c/code\u003e.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-8-3\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-8-3\"\u003e\u003cspan class=\"section-number-3\"\u003e8.3\u003c/span\u003e Generic Hooks\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-8-3\"\u003e\n\u003cp\u003e\nYour plugin can provide functions using the following names:\n\u003c/p\u003e\n\u003cul class=\"org-ul\"\u003e\n\u003cli\u003e\u003ccode\u003eon_abort_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_abort_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_acquire_lock_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_acquire_lock_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_clean_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_clean_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_load_config_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_load_config_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_notify_status_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_notify_status_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_poll_finish_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_poll_finish_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_poll_start_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_poll_start_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_process_queue_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_process_queue_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_queue_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_queue_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_quit_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_quit_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_read_commands_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_read_commands_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_read_status_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_read_status_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_reload_config_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_reload_config_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_run_cmd_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_run_cmd_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_run_tasks_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_run_tasks_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_schedule_poll_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_schedule_poll_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_send_message_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_send_message_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_status_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_status_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_tasks_finish_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_tasks_finish_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_tasks_start_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_tasks_start_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_finish_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_finish_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_start_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_start_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_status_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_update_status_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_write_status_post_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eon_write_status_pre_\u003cplugin_name\u003e\u003c/code\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"outline-container-sec-8-4\" class=\"outline-3\"\u003e\n\u003ch3 id=\"sec-8-4\"\u003e\u003cspan class=\"section-number-3\"\u003e8.4\u003c/span\u003e Example Plugin\u003c/h3\u003e\n\u003cdiv class=\"outline-text-3\" id=\"text-8-4\"\u003e\n\u003cp\u003e\nThe \u003ccode\u003ebuild-keep.sh\u003c/code\u003e plugin uses a variable \u003ccode\u003eBUILD_KEEP\u003c/code\u003e which is settable from the config file and used the \u003ccode\u003etasks_finish_post\u003c/code\u003e hook:\n\u003c/p\u003e\n\u003cdiv class=\"org-src-container\"\u003e\n\n\u003cpre class=\"src src-sh\"\u003e\u003cspan style=\"color: #afd7d7;\"\u003edeclare\u003c/span\u003e BUILD_KEEP\n\n\u003cspan style=\"color: #87d7ff;\"\u003eplugin_on_load_config_pre_build_keep\u003c/span\u003e() {\n  \u003cspan style=\"color: #ffd787;\"\u003eBUILD_KEEP\u003c/span\u003e=\u003cspan style=\"color: #ffaf87;\"\u003e\"0\"\u003c/span\u003e\n}\n\n\u003cspan style=\"color: #87d7ff;\"\u003eplugin_on_tasks_finish_post_build_keep\u003c/span\u003e() {\n  \u003cspan style=\"color: #00ffff;\"\u003eif\u003c/span\u003e [[ \u003cspan style=\"color: #ffaf87;\"\u003e\"$BUILD_KEEP\"\u003c/span\u003e -gt 0 ]]; \u003cspan style=\"color: #00ffff;\"\u003ethen\u003c/span\u003e\n    \u003cspan style=\"color: #00ffff;\"\u003ewhile \u003c/span\u003e\u003cspan style=\"color: #afd7d7;\"\u003eread\u003c/span\u003e num; \u003cspan style=\"color: #00ffff;\"\u003edo\u003c/span\u003e\n      [[ -d \u003cspan style=\"color: #ffaf87;\"\u003e\"$BUILDS_DIR/$num\"\u003c/span\u003e ]] \u0026\u0026 rm -r \u003cspan style=\"color: #ffaf87;\"\u003e\"$BUILDS_DIR/$num\"\u003c/span\u003e\n    \u003cspan style=\"color: #00ffff;\"\u003edone\u003c/span\u003e \u003c \u003c(seq 1 $(( $\u003cspan style=\"color: #ffd787;\"\u003eBUILD_NUMBER\u003c/span\u003e - $\u003cspan style=\"color: #ffd787;\"\u003eBUILD_KEEP\u003c/span\u003e)))\n  \u003cspan style=\"color: #00ffff;\"\u003efi\u003c/span\u003e\n}\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"postamble\" class=\"status\"\u003e\n\u003cp class=\"author\"\u003eAuthor: Andrew Phillips \u003c\u003ca href=\"mailto:theasp@gmail.com\"\u003etheasp@gmail.com\u003c/a\u003e\u003e\u003c/p\u003e\n\u003cp class=\"date\"\u003eDate: 2015-02-18 Wed 21:04\u003c/p\u003e\n\u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheasp%2Fmini-ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheasp%2Fmini-ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheasp%2Fmini-ci/lists"}