alfred-ci
v0.0.12
Published
Alfred is a CI/CD server for Node.
Downloads
4
Readme
alfred-server
Alfred is a (very much a work in progress!) CI/CD server written in Javascript for Node.js. Everything - pipelines included - is defined in Javascript.
Installation
npm install -g alfred-ci
alfred-ci
You'll need to manually edit the database connection details in configAndData/settings.js and to setup the schema, run the database/install.sql
file (this will be happening automatically soon).
If you see install errors due to node-gyp
, make sure you have run apt-get install build-essentials
on Linux and npm i -g windows-build-tools
on Windows.
Startup
To start Alfred, you'd usually run it with the config path you'd like to use. The config path contains your overall config, encrypted credentials and the pipelines themselves:
alfred-ci --config ./path-to-a-suitable-config-directory/
If you don't provide a path, ./configAndData/
is used by default. If the directory is empty then Alfred will create the pipelines
directory and copy in a default settings.js
too.
Creating your first pipeline
An Alfred pipeline is just a Javascript function which creates a series of 'stages'. To create one, first create a JS file like this:
configDirectory/pipelines/a-suitable-pipeline-name-or-id/pipeline.js
Here's a basic hello world pipeline:
module.exports = (pipeline, app) => {
// Adds the stage called "hello-world" stored in templates/stages/hello-world.js
pipeline.add("hello-world");
// You can also directly add functions too (but we give the stage a name so it can be configured/ identified):
// pipeline.add("hello-world", () => console.log('Hello world!'));
}
Run the pipeline via the Alfred web API:
http://localhost:8088/v1/pipeline/start?name=a-suitable-pipeline-name-or-id
Templates
You might have a workflow which is similar across a variety of your projects but only varies in their configuration. For example if you make websites then the testing and deployment process of most of those websites is probably the same, aside from server specific config. This is where you can make use of a template and pipeline.import
:
module.exports = (pipeline, app) => {
// Project specific settings:
var settings = {
stages: {
'git-pull': { // Overrides settings for a stage called "git-pull".
url: 'https://...',
credentials: CREDS_ID_OR_RAW_OBJECT
}
}
};
// Import your standard pipeline:
// (Ideally you want as many projects as possible to use the same pipe).
// Import returns a promise which resolves when the pipeline is ready to be started (not when it has finished).
// Add await/ then if you'd like to override or add additional project specific stages.
// Most standard pipes are ready immediately anyway but you should always return/ resolve the import promise.
return pipeline.import("standard", settings);
}
Import simply applies the named template to this pipeline which comes from (in the above example) templates/pipelines/standard.js
. You can even import repeatedly if you want and stages will just be added together or overriden if the same stage name occurs multiple times.
The settings hierarchy
In order to minimise repetition of settings, there is a hierarchy of settings overriding others:
- Run settings: When you run a pipeline directly (using
app.pipeline.run("pipeline-name", {stages: {"git-pull": {url: ..}}})
) you can provide settings. These override all other settings. - Imported pipeline settings: Overriden by run settings. E.g:
pipeline.import("standard", {stages: {"git-pull": {url: ..}})
. These are generally the ones you'll use. - Stage settings: The various stage adding methods like
pipeline.add
accept settings too.pipeline.add("git-pull", undefined, {url: ..})
- When possible, the stage itself should use suitable defaults. These are overriden by everything else.
Credentials
Alfred includes an easy to use encrypted credential store so you should generally use that instead of writing your more sensitive details in the settings like this:
// Don't do this!
var settings = {
stages: {
'git-pull': {
url: 'https://...',
credentials: {
username: 'avoid-doing-this',
password: 'whenever-possible'
}
}
}
};
// Better!
var settings = {
stages: {
'git-pull': {
url: 'https://...',
credentials: 'alfreds-github-login'
}
}
};
In order to create alfreds-github-login
, either call app.credentials.add('alfreds-github-login', {username: '...', password: '..'})
or add it via the credentials API endpoint:
POST to http://localhost:8088/v1/credential/add
or http://localhost:8088/v1/credential/update
{
key: 'alfreds-github-login',
data: {
username: 'i-am-alfred',
password: '...'
}
}
'alfreds-github-login' is now a permanently stored encrypted credential. You can use that textual name to reference it when it's needed (in stages that support it). Stages that use sensitive credentials can load it using:
app.credentials.load('alfreds-github-login')
(if you pass something that isn't a string, then it will just return whatever you gave it in order to easily support inline credentials too).