grunt


Deploy a gebo agent

This document provides step-by-step instructions on how to deploy a gebo agent. It is comprehensive so that you may copy, paste, and execute the commands and deploy the configurations provided, from beginning to end.

Getting Started

This document is intended to stand alone so that you do not need to read previous tutorial posts. As such, some of the following steps may have already been executed. They do not need to be executed again.

Setup the database

These steps may already have been executed.

Install MongoDB on your system, if you haven’t already:

Start MongoDB by executing this at the command line:

1
sudo service mongodb start

These instructions are also outlined in your new gebo’s README.md.

Setup grunt

1
2
sudo npm install grunt-cli -g
sudo npm install grunt-init -g

The first command enables you to run the grunt installed locally, automatically. The second allows you to call grunt-init on this template.

Get the gebo template

This is going in your ~/.grunt-init/ directory

1
git clone https://github.com/RaphaelDeLaGhetto/grunt-init-gebo.git ~/.grunt-init/gebo

Create a new project:

1
2
3
mkdir myfirstagent
cd myfirstagent
grunt-init gebo

Upon execution gebo-init will prompt you for some input, with some fields prefilled:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Please answer the following:
[?] Project name (myfirstagent)
[?] Description (The best project ever.)
[?] Version (0.0.0)
[?] Project git repository (git://github.com/RaphaelDeLaGhetto/myfirstagent.git)
[?] Project homepage (https://github.com/RaphaelDeLaGhetto/myfirstagent)
[?] Project issues tracker (https://github.com/RaphaelDeLaGhetto/myfirstagent/issues)
[?] Licenses (MIT)
[?] Author name (RaphaelDeLaGhetto)
[?] Author email (daniel@capitolhill.ca)
[?] Author url (none)
[?] What versions of node does it run on? (>= 0.10.0)
[?] Main module/entry point (<project-name>.js)
[?] Npm test command (grunt nodeunit)
[?] Do you need to make any changes to the above before continuing? (y/N)

Once everything is configured to your liking, execute:

1
sudo npm install

Test

If everything has been initialized correctly, the tests will pass:

1
grunt nodeunit

Run the development server

1
node myfirstagent.js

and go to http://localhost:3000. You will be redirected to an HTTPS site, which will require making an exception in your browser, as you currently only have self-signed certificates.

Make a friendo

A gebo will only perform an action if an agent has permission to request that action. These permissions are analogous to Linux-style read/write/execute permissions on an action or database resource.

From the project directory…

Register agent

This is mostly for human agents who need traditional username/password access through some human-agent interface. A friendo does not need to be a registered agent, though a registered agent does need to be a friendo with permissions set to access any given gebo resource (unless that registered agent is an administrator).

1
grunt registeragent:SomeGuy:someguy@example.com:secretpassword123:false

Friendo agent

A friendo is an agent to whom you may assign an access token.

1
grunt friendo:SomeGuy:someguy@example.com

Set permissions

The someactionorresource parameter may also specify a database collection name. The boolean parameters below correspond to read/write/execute. Here, the SomeGuy agent has permission to execute on someactionorresource.

1
grunt setpermission:someguy@example.com:someactionorresource:false:false:true

Create token

This token allows an agent access to all the resources to which he’s already been granted permission.

1
grunt createtoken:myfirsthai@example.com:ThisIsMyTokenLetMeIn123

Development

The vanilla gebo agent doesn’t do much. He just sends a friendly greeting to his friendos. Eventually you will implement richer functionality…

Project directory

The gebo grunt-init template produces this directory structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
.. (up a dir)
/home/daniel/test/myfirstagent/
▾ agent/
index.js
▸ cert/
▸ node_modules/
▸ test/
gebo.json
Gruntfile.js
LICENSE-MIT
myfirstagent.js
package.json
README.md

A gebo’s behaviour is defined in agent/index.js.

Configure

Configurations are manipulated in gebo.json. By default, the configuration looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"name":"myfirstagent",
"email":"myfirstagent@example.com",
"domain":"https://localhost",
"port":3000,
"httpsPort":3443,
"docs": "docs",
"testEmail": "myfirstagent-test@example.com",
"logLevel":"trace",
"ssl": {
"key": "./cert/key.pem",
"cert": "./cert/cert.pem"
}
}

Next

Instantiate a gebo HAI…


grunt-init and the Jest preprocessor

I like developing with React. I find myself using it more and more, so today I decided to create a project scaffold to automate project creation with grunt-init.

Being obsessive about testing (and conformity), I adopted Jest to test my interfaces, simply because that’s what the good folk over at Facebook use too. As such, unit testing was to be built into my project template right from the beginning. This is where I ran into a problem…

grunt-init calls on a file called template.js. The code in this file typically prompts the user for project-specific details (name, description, homepage, etc.) and writes all the information to the project’s package.json file. You can see my full template here. The following shows the project.json properties that are not configurable by the user:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ...
props.scripts = {
"test": "jest"
};
props.keywords = [];
props.dependencies = {};
props.devDependencies = {
"grunt": "~0.4.x",
"grunt-contrib-clean": "~0.6.x",
"grunt-contrib-concat": "~0.5.x",
"grunt-contrib-connect": "~0.8.x",
"grunt-contrib-copy": "~0.6.x",
"grunt-contrib-livereload": "~0.1.x",
"grunt-contrib-uglify": "~0.6.x",
"grunt-contrib-watch": "^0.6.x",
"grunt-open": "^0.2.x",
"grunt-react": "^0.9.x",
"grunt-regarde": "~0.1.x",
"grunt-usemin": "^2.4.x",
"jest-cli": "^0.1.x",
"jquery": "^2.1.x",
"matchdep": "~0.3.x",
"react": "^0.11.x",
"react-tools": "^0.11.x"
};
// ...
// Generate package.json file.
init.writePackageJSON('package.json', props);

These props primarily consist of the development dependencies I always uses when developing with React. They are written to the file by the init.writePackageJSON function. For those familiar with Jest, you know that package.json needs a little Jest-specific addition for the the script preprocessor, which looks like this:

1
2
3
4
5
6
"jest": {
"scriptPreprocessor": "<rootDir>/__tests__/preprocessor.js",
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react"
]
},

Being somewhat naive, I assumed that I could simply add the jest property to the props object like this:

1
2
3
4
5
6
props.jest = {
"scriptPreprocessor": "<rootDir>/__tests__/preprocessor.js",
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react"
]
};

This does not work. init.writePackageJSON only sets the typical package.json options. The jest property is not typical, and the official documentation is not especially helpful. Here’s the relevant part pertaining to the init.writePackageJSON function:

The callback can be used to post-process properties to add/remove/whatever.

So yes, it is possible. You just have to add/remove/whatever the jest property. After poking around the code a little bit, I figured out that this is how you do it:

1
2
3
4
5
6
7
8
9
10
// Generate package.json file.
init.writePackageJSON('package.json', props, function(pkg, props) {
pkg.jest = {
"scriptPreprocessor": "<rootDir>/__tests__/preprocessor.js",
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react"
]
};
return pkg;
});

See my ever-changing React project template here: https://github.com/RaphaelDeLaGhetto/grunt-init-gebo-react-hai.