quinCI is a self-hosted, minimal GitHub CI server that runs scripts in response to GitHub webhook events.
It is an alternative to complex, monolithic CI servers like Jenkins. Instead of providing a runner architecture, loggers, a plugin system, and pipelines... it just runs script files. If your CI needs are not very complex, quinCI may be easier to set up and debug than Jenkins.
quinCI is a good fit for you if:
- You want to run CI on your own server
- You use GitHub
- You want to run CI when a commit is added to the
master
branch - You want to run CI when a pull request is opened or updated
quinCI runs "tasks" when certain "events" occur. A task is an executable file that lives in your repo in the quinci
folder. An event is something that can happen on GitHub, like a commit being added to master, or a Pull Request being opened.
Whenever quinCI runs a task, the instance of that task running for a given commit or pull request is called a "job".
You can view all the jobs quinCI is running or has run recently by opening the port quinCI is running on in your browser. You can also cancel jobs from this page.
Here's a list of the events quinCI reacts to, and what task it will run for each event:
Event | Task |
---|---|
Commit pushed to or merged into a named branch | matches the branch name, eg main or master |
When you push a commit to master/main, or merge a PR into master/main, quinCI will run the master
or main
task on your repo. To do so, it:
-
Clones your repo
-
Checks out the commit you just pushed
-
Marks the commit status on GitHub as "pending"
-
Runs
./quinci/master
or./quinci/main
inside your repo (depending on the name of the branch that got new commits) -
If
./quinci/master
or./quinci/main
exits with a nonzero status code, quinCI will mark the commit status on GitHub as "failure" and leave a comment on the commit with information about the failure. -
If
./quinci/master
or./quinci/main
exits with a status code of zero, quinCI will mark the commit status on GitHub as "success".
To run tasks for branches with different names, pass a comma-separated list of branch names on the command line using the --named-branches
CLI flag. The default value of --named-branches
is master,main
. When you specify named branches using this CLI flag, it replaces the default value. So, if you want to include the default master
and main
tasks, you will need to include them, eg --named-branches master,main,staging,production
.
Note: When adding a task for a named branch, you may wish to also use
--queue-concurrency
to specify how many jobs can run concurrently for that task. If unspecified, the concurrency defaults to 1, meaning only one job can be running for that task at a time, and other jobs will wait until a running job has completed.
Event | Task |
---|---|
PR opened, or new commits added to PR | pull-request |
When you open a Pull Request or push new commits onto a PR, quinCI will run the pull-request
task on your repo. To do so, it:
- Clones your repo
- Checks out the commit you just pushed or opened a PR for
- Marks the commit status on GitHub as "pending"
- Runs
./quinci/pull-request
inside your repo
quinCI will post a comment when it starts running the task, and another comment when it has finished the task, which will include the results of the build.
- If
./quinci/pull-request
exits with a nonzero status code, quinCI will mark the commit status on GitHub as "failure" and leave a comment on the PR indicating the task failed. - If
./quinci/pull-request
exits with a status code of zero, quinCI will mark the commit status on GitHub as "success" and leave a comment on the PR indicating the task succeeded.
Event | Task |
---|---|
Comment with special phrase posted on PR | pull-request |
In any PR, you can leave a comment with the phrase "quinCI run" or "quinCI test", and quinCI will re-run the pull-request
task.
The phrase only needs to match /quin+c[eyi]+.* (?:re)?(?:run|test)/i
, so you can write "Mr. Quincy, please test the code again, if you wouldn't mind" and it will work, too.
Event | Task |
---|---|
Comment with special phrase posted on commit | varies |
On any commit, you can leave a comment with the phrase "quinCI run master", "quinCI run main", or "quinCI run pull-request" to run the master
, main
, or pull-request
tasks on that commit.
The phrase only needs to match /quin+c[eyi]+.* run ([\w.-]+)/i
, so you can write "Quinncey, could you please run master" and it will work, too.
You can also use this to run custom tasks; for example, if you create the file quinci/deploy
in your repo, you can comment "quinCI run deploy" on a commit, and quinCI will clone the repo, check out the commit, and run ./quinci/deploy
.
Note: When creating a custom task, you may wish to also use
--queue-concurrency
to specify how many jobs can run concurrently for that task. If unspecified, the concurrency defaults to Infinity, meaning as many jobs as are requested can be running for that task at a time.
quinCI expects to find two executable files in your repo: quinci/master
(or quinci/main
), and quinci/pull-request
. Create these in your repo before installing quinCI, or else your builds will fail.
quinci/master
will be run for every commit added to master, quinci/main
will be run for every commit added to main, and quinci/pull-request
will be run for every pull request.
If you override the --named-branches
setting via the CLI in such a way that master
and/or main
are no longer present, you don't need to have executable files at quinci/master
or quinci/main
.
The scripts can do whatever you want. Here's an example quinci/master
script that runs tests and then deploys the code:
#!/usr/bin/env bash
set -e
yarn test
yarn deploy
And here's an example qunci/pull-request
script that just runs the tests (without deploying):
#!/usr/bin/env bash
set -e
yarn test
Make sure to make these files executable:
chmod +x quinci/master
chmod +x quinci/pull-request
quinCI is used as a GitHub App. Because it's self-hosted, the webhook URL and authentication details will vary, so you need to create a custom GitHub App for your quinCI server. You can create a new GitHub App here.
- Name the app whatever you want
- Description is optional
- Homepage URL needs to be filled in but it doesn't matter what it is
- User authorization callback URL needs to be filled in but it doesn't matter what it is
- Leave Setup URL blank
- For the Webhook URL, use a public URL that you will run quinCI on, eg
http://mydomain.com:7777/
. You can use ngrok to expose a URL to your local box for testing. Also, you can change this later without re-creating the GitHub App. - You have to have a Webhook secret. Generate something random. You'll need to include it when running quinCI on your server, so keep it somewhere.
Your app needs these permissions:
- Repository contents: Read only
- Issues: Read & write
- Pull requests: Read & write
- Commit statuses: Read & write
Everything else can be "No access".
Subscribe to these events:
- Commit comment
- Push
- Issue comment
- Pull request
You don't need to subscribe to anything else.
After creating your GitHub App, go to its page under "GitHub Apps" in GitHub Developer settings and copy its ID from the "About" section. You'll need this when running quinCI on your server.
From your GitHub App page, generate a private key and download it (It'll be a .pem
file). You'll need to use it when running quinCI on your server, so keep it somewhere.
Go to your App's page in GitHub Developer settings and click "Install app" to install your Github App onto your repo.
- You need Node.js 8.11.1 or higher to run quinCI.
- Install the quinCI client on your server:
npm i -g quinci
- Copy the
.pem
private key you downloaded earlier somewhere on your server - Make a text file and put your webhook secret in it, and put this file somewhere on your server
- Run
quinci
with the following command line switches:
Options:
--help Show help [boolean]
--version Show version number [boolean]
--port Port to run the HTTP server on [required] [default: 7777]
--app-id GitHub App ID [required]
--app-cert Path to the GitHub App's private key pem file [required]
--webhook-secret-file Path to a text file containing your Webhook secret [required]
--queue-concurrency How many instances of a job are allowed to run at once.
Use 'Infinity' for no limit. [default: "master=1,main=1,pull-request=3"]
--web-url URL at which the web UI can be accessed [required]
--named-branches Comma-separated list of branch names that have
corresponding jobs in the 'quinci' folder in the repo
root, that should be run when commits are pushed to
that branch. [default: "master,main"]
So for example:
quinci --port 8080 --app-id 12345 --app-cert secrets/quinci.private-key.pem --webhook-secret-file secrets/webhook-secret.txt --web-url http://example.com:8080
This will run quinCI in the current directory.
- quinCI will not run in response to actions from users who do not have write access to the repository, as a security measure. If a user without write access opens a PR and you want to run its tests, comment "quinCI test this" on the PR.
- quinCI uses the debug module to log debugging information. To view debug logs while running, set the environment variable
DEBUG
toquinci:*
.
MIT