Mholloway has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/390877 )
Change subject: Hygiene: Delete template docs ...................................................................... Hygiene: Delete template docs This is general template documentation and need not be committed to this repo. Change-Id: I7ba901ed556c1c73157933a314da76cd0af1dacc --- D doc/README.md D doc/api-design.md D doc/coding.md D doc/commands.md D doc/config.md D doc/deployment.md D doc/template.md 7 files changed, 0 insertions(+), 918 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/mobileapps refs/changes/77/390877/1 diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index d837f0a..0000000 --- a/doc/README.md +++ /dev/null @@ -1,14 +0,0 @@ -This directory contains the documentation for the service template, aimed at -getting you started up and running quickly. - -The documentation should be read in the following order: - -1. [Short API design practices](api-design.md) -2. [Service template overview](template.md) -3. [Configuration](config.md) -4. [Useful Commands](commands.md) -5. [Coding Guide](coding.md) -6. [Deployment](deployment.md) - -Have fun while creating RESTful API services! - diff --git a/doc/api-design.md b/doc/api-design.md deleted file mode 100644 index 20f2e5b..0000000 --- a/doc/api-design.md +++ /dev/null @@ -1,83 +0,0 @@ -# API Design - -Before you start coding your service, you need to think hard about your API's -design, especially for a public service exposing its API. Below are a couple of -practices you should follow. - -- [Statelessness](#statelessness) -- [Versioning](#versioning) -- [Hierarchical URI Layout](#hierarchical-uri-layout) -- [HTTP Verbs](#http-verbs) -- [Documentation](#documentation) -- [See Also](#see-also) - -## Statelessness - -RESTful API services should be -[stateless](https://en.wikipedia.org/wiki/Service_statelessness_principle), since -they are conceptually modelled around *resources* (as opposed to *systems*). -Accordingly, your service should take actions depending on assumptions about the -caller or the current state of the service's process (e.g. that the user is -logged in, that they are allowed to modify a resource, etc.) - -## Versioning - -You should always version all of your API. Always. Period. Applications depend on -its stability and invariance. It is tolerable to add endpoints to an API -version, but removing or modifying existing ones is not an option. Thus, -versioning provides an easy way for you to improve upon the API while avoiding -third-party application breakage. The template enforces this practice by -requiring all of your [route files](../routes/) specify the API version. - -## Hierarchical URI Layout - -Use a hierarchical URI layout that is intuitive and makes sense. Grouping -endpoints under a common URI prefix allows both you and the future API consumer -to reason about the API. As an example, consider -[RESTBase](https://www.mediawiki.org/wiki/RESTBase)'s API layout: - -``` -/{domain} - -- /v1 - |- /page - | |- /title - | |- /html - | |- /data-parsoid - | -- /revision - -- /transform - |- /html/to/wikitext - |- /wikitext/to/html - -- /html/to/html -``` - -The API is grouped in two *sections* - `page` and `transform`. The former -exposes endpoints dealing with Wiki pages, while the latter comprises endpoints -transforming one format to another. - -## HTTP Verbs - -There are many [HTTP -verbs](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) you can use and -expose in your API. Use them appropriately. Especially, **do not allow GET -requests to modify** any type of content. - -## Documentation - -Document your API meticulously, and keep it up to date with the code. Remember -that API's are meant to be consumed by external applications, whose developers -most often do not know the internal workings of your stack. A good starting -point is to look into [Swagger](https://github.com/swagger-api/swagger-spec), a -specification for API declaration and documentation from which nice, demo-able -documentation such as [this](http://rest.wikimedia.org/en.wikipedia.org/v1/?doc) -can be automatically generated. - -## See Also - -The above is just a short list of things you should think about when designing -your API. Here are some resources you might find useful at this step: - -- https://github.com/Wikia/guidelines/tree/master/APIDesign -- https://restful-api-design.readthedocs.org/en/latest/ -- http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api -- http://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling - diff --git a/doc/coding.md b/doc/coding.md deleted file mode 100644 index 73cbe64..0000000 --- a/doc/coding.md +++ /dev/null @@ -1,414 +0,0 @@ -# Coding Guide - -Let's get started! - -- [Route Set-up](#route-set-up) -- [Routes](#routes) -- [Promises](#promises) - - [I/O](#io) - - [External Requests](#external-requests) -- [Error Handling](#error-handling) -- [Logging and Metrics](#logging-and-metrics) - - [Logging](#logging) - - [Metrics Collection](#metrics-collection) -- [Test Cases](#test-cases) - -## Route Set-up - -All of the routes are read from the [routes directory](../routes) and are -automatically mounted on start-up. The first step is to create a new route file -by copying the [route template](../routes/empty.js.template): - -```bash -$ cd routes -$ cp empty.js.template people.js -``` - -Now, open `people.js` in your favourite editor. The first thing you need to -decide is the mount path for the routes contained in the file and the API -version the route belongs to. Let's say that this file will contain routes -pertaining to famous people, so a path like `/people/` makes sense here. -Obviously, the API version is going to be `1`. Change lines 32 - 36 to reflect -this: - -```javascript -return { - path: '/people', - api_version: 1, - router: router -}; -``` - -This causes all of the routes you create in `people.js` to be mounted on -`/{domain}/v1/people/`, where `{domain}` represents the sought domain (such as -`en.wikipedia.org`, `www.mediawiki.org`, etc.). - -## Routes - -Creating routes is accomplished by calling `router.METHOD(path, handlerFunction)` -where `METHOD` is the HTTP verb you want to create the route for (`get`, `put`, -`post`, etc.), and `handlerFunction` is the callback function called when the -relative path `path` is matched. We are now ready to set up our first route. -Replace line 23 with the following code: - -```javascript -router.get('/:name', function(req, res) { - - res.status(200).json({ - name: decodeURIComponent(req.params.name) - }); - -}); -``` - -The route's path is `:name`, which signifies a variable path. In this case, it -is the name of the person the request is about. Thus, both -`/people/Albert_Einstein` and `/people/David_Lynch` will match the route. The -callback's body is rather simple: we set the response's status to `200` and send -back a JSON containing the person's name. To learn more about routes and their -various options, read Express.js' [routing -guide](http://expressjs.com/guide/routing.html). - -## Promises - -The service template includes the [bluebird -module](https://github.com/petkaantonov/bluebird) for handling asynchronous -patterns via promises. Prime examples of when they should be used are performing -external requests or I/O actions. Promises allow the service process not to -block on them and continue serving other requests until the action is completed. - -### I/O - -Coming back to our example route, let's say that we want to serve a simple HTML -document on the endpoint `/people/:name/about`. To do so, first we need to -require and *promisify* the `fs` module. Put this line in the header of your -routes file (right below line 6): - -```javascript -var fs = BBPromise.promisifyAll(require('fs')); -``` - -This creates additional functions, which are *promisified* versions of the -original ones exported by the `fs` module. Henceforth, we can read a file either -using the built-in `fs.readFile()` or its promise-aware counterpart -`fs.readFileAsync()`. - -Armed with this knowledge, we can now easily create a route handler: - -```javascript -router.get('/:name/about', function(req, res) { - - // read the file - return fs.readFileAsync(__dirname + '/../static/index.html') - // and then send back its contents - .then(function(src) { - res.status(200).type('html').send(src); - }); - -}); -``` -As you can see, promises allow us to specify chained actions in a natural way -(using the `.then()` continuation pattern). Note that, when using promises in -services derived from this template it is important that you `return` the -promise to the caller. Doing so allows the template's framework to automatically -handle any possible errors during the promise's execution. - -### External Requests - -One other area where promises come in handy is making external requests. Suppose -we want to serve the latest news about a person from -[Wikinews](http://www.wikinews.org). The template includes -[preq](https://github.com/wikimedia/preq) -- a module promisifying the popular -[request](https://github.com/request/request) module -- which we can use -right away: - -```javascript -router.get('/:name/news/:lang?', function(req, res) { - - // set the language if not set - var lang = req.params.lang || 'en'; - - // get the news - return preq.get({ - uri: 'https://' + lang + '.wikinews.org/wiki/' - + encodeURIComponent(req.params.name) - }).then(function(wnRes) { - res.status(200).type('html').send(wnRes.body); - }); - -}); -``` - -#### MediaWiki API Requests - -If one wants to issue requests to MW API, `apiUtil.mwApiGet()` can be used. For -example, getting certain properties of a page is as easy as: - -```javascript -router.get('/page/:title', function(req, res) { - - // construct the query for the MW Action API - var apiQuery = { - format: 'json', - formatversion: 2, - action: 'query', - prop: 'pageprops', - titles: req.params.title - }; - - return apiUtil.mwApiGet(app, req.params.domain, apiQuery) - .then(function(apiRes) { - if(!apiRes.body || !apiRes.body.query || - !Array.isArray(apiRes.body.query.pages)) { - throw new HTTPError({ - status: 500, - title: 'Could not get properties', - detail: 'Could not get page properties for ' + req.params.title - }); - } - res.status(200).type('json').end(apiRes.body.query.pages[0]); - }) - -}); -``` - -#### REST API Requests - -Likewise, the template supports REST API requests out of the box via the -`apiUtil.restApiGet()` library function. To get the Parsoid HTML for a title, -use: - -```javascript -router.get('/page/:title', function(req, res) { - - return apiUtil.restApiGet(app, req.params.domain, - 'page/html/' + encodeURIComponent(req.params.title)) - .then(function(restRes) { - res.status(200).type('html').end(restRes.body); - }); - -}); -``` - -Note that you can also modify any part of the request; you can supply the -method to use (`get` by default), the query parameters, headers or body. For -example, if you don't want the REST API to send redirects, but to retrieve the -parsed content of the page in case of redirect pages, you can use: - -```javascript - return apiUtil.restApiGet(app, req.params.domain, - 'page/html/' + encodeURIComponent(req.params.title), - { - query: { redirect: false } - }) -``` - -## Error Handling - -As mentioned earlier, the template is capable of automatically handling errors -for you. However, you might want to take matters into your own hands in some -occasions. The template provides a convenient `HTTPError` object class which you -can use. - -Let's revise the handler for the `/people/:name/about` route. It does not seem -to be very useful, as it returns the same content for any given name. We would -like it to return content relevant to the person whose name was specified in the -request URI by looking up the file `/static/name.html`. If the file does not -exist, a `404` should be returned to the caller. - -```javascript -router.get('/:name/about', function(req, res) { - - return fs.readFileAsync(__dirname + '/../static/' - + encodeURIComponent(req.params.name) + '.html') - .then(function(src) { - res.status(200).type('html').send(src) - }).catch(function(err) { - throw new HTTPError({ - status: 404, - type: 'not_found', - title: 'Not Found', - detail: 'No information could be found on ' + req.params.name - }); - }); - -}); -``` - -Note that you can also attach additional debug information to the `HTTPError` -object to help you track down bugs. This information is going to be logged, but -will not reach the client, thus ensuring no sensitive information is leaked -unintentionally. To do so, simply add any property you deem important when -creating / throwing the error. - -## Logging and Metrics - -Logging and metrics collection is supported out of the box via -[service-runner](https://github.com/wikimedia/service-runner). They are exposed -in route handler files via the `req.logger` and `app.metrics` objects. - -### Logging - -To log something, simply use `req.logger.log(level, what)`. The logger itself is -a [bunyan](https://github.com/trentm/node-bunyan) wrapper, and thus supports the -following levels: - -- `trace` -- `debug` -- `info` -- `warn` -- `error` -- `fatal` - -Additionally, it is good practice to attach a component name to the log level as -it eases log indexing and filtering later in production. For example, if a log -entry has the `debug` level and pertains to one of our example routes, the log -level could be set to `debug/people`. The `what` portion of the log entry can be -either a string message, or any *stringifiable* object. As an example, let's -log the person's name given to the `/people/:name/about` route and the file name -that is going to be looked up: - -```javascript -router.get('/:name/about', function(req, res) { - - var info = { - name: req.params.name, - path: __dirname + '/../static/' - + encodeURIComponent(req.params.name) + '.html' - }; - - req.logger.log('debug/people/about', info); - - return fs.readFileAsync(info.path) - .then(function(src) { - res.status(200).type('html').send(src) - }).catch(function(err) { - throw new HTTPError({ - status: 404, - type: 'not_found', - title: 'Not Found', - detail: 'No information could be found on ' + info.name - }); - }); - -}); -``` - -As you can see, the request object (`req`) has an additional property - -`req.logger`, which allows you to log messages and objects in the context of the -current request. To do so, it attaches a unique *request ID* to each logged -information. If you would like to log context-free information, you can use the -`app.logger` object instead, even though that is not recommended. - -### Metrics Collection - -Collecting metrics is a great way to have insights into the overall health and -performance of your service. When using the template, this is as easy as calling -one of the following methods: - -- `app.metrics.timing` -- `app.metrics.increment` -- `app.metrics.decrement` -- `app.metrics.histogram` -- `app.metrics.gauge` -- `app.metrics.unique` - -How can one collect them? Let's show it on `/people/:name/news`. This route uses -an external request to complete its action, which means that you have little -control over your service's response time, as it is dominated by the request to -Wikinews. Two interesting metrics that we can collect here (and that directly -affect the service's response time) are the external request's response time and -the size of its response. We can measure the former with `app.metrics.timing()` -and the latter with `app.metrics.histogram()`. Additionally, it interesting to -see the distribution of languages, which can be achieved with -`app.metrics.unique()`. - -```javascript -router.get('/:name/news/:lang?', function(req, res) { - - // set the language if not set - var lang = req.params.lang || 'en'; - - // count the language occurrence - app.metrics.unique('people.news.lang', lang); - // start measuring the time - var startTime = Date.now(); - - // get the news - return preq.get({ - uri: 'https://' + lang + '.wikinews.org/wiki/' - + encodeURIComponent(req.params.name) - }).then(function(wnRes) { - // external request done, report the request time - app.metrics.timing('people.news.time', Date.now() - startTime); - // also report the payload's size - app.metrics.histogram('people.news.size', wnRes.body.length); - res.status(200).type('html').send(wnRes.body); - }); - -}); -``` -For more information on the available methods, see the [service-runner -documentation](https://github.com/wikimedia/service-runner#metric-reporting). - -## Test Cases - -The service needs to thoroughly tested since other services and clients are -going to depend on it. The template uses -[mocha](https://github.com/mochajs/mocha) for test execution and provides some -useful utility functions in [test/utils](../test/utils). - -To create a test suite for our example routes, create the `people` directory in -`/test/features/` and two files inside of it: `about.js` and `news.js`. These -will test the example routes. Let's start with `about.js`: - -```javascript -'use strict'; - - -// mocha defines to avoid JSHint breakage -/* global describe, it, before, beforeEach, after, afterEach */ - - -var preq = require('preq'); -var assert = require('../../utils/assert.js'); -var server = require('../../utils/server.js'); - - -describe('people - about', function() { - - this.timeout(20000); - - before(function () { return server.start(); }); - - // common URI prefix - var uri = server.config.uri + 'en.wikipedia.org/v1/people/'; - - it('get HTML for index', function() { - return preq.get({ - uri: uri + 'index/about' - }).then(function(res) { - // check the status - assert.status(res, 200); - // check the returned Content-Type header - assert.contentType(res, 'text/html'); - // inspect the body - assert.notDeepEqual(res.body, undefined, 'No body returned!'); - }); - }); - - it('fail for a non-existent person', function() { - return preq.get({ - uri: uri + 'Walt_Disney/about' - }).then(function(res) { - // if we are here, no error was thrown, not good - throw new Error('Expected an error to be thrown, got status: ', res.status); - }, function(err) { - // inspect the status - assert.deepEqual(err.status, 404); - }); - }); - -}); -``` - diff --git a/doc/commands.md b/doc/commands.md deleted file mode 100644 index 01b6c5a..0000000 --- a/doc/commands.md +++ /dev/null @@ -1,101 +0,0 @@ -# Useful Commands - -- [npm 101](#npm-101) -- [Service-related Tasks](#service-related-tasks) -- [Docker](#docker) - -## npm 101 - -[npm](https://www.npmjs.com/) is the package manager for Node.js modules. It is -used for managing and publishing modules. - -The template (and your future service) needs its dependencies to be present. -Install them with: - -``` -npm install -``` - -Sometimes the configuration can get a bit messed up you may experience strange -*npm*-related errors when running your service. The remedy is: - -``` -rm -rf node_modules -npm install -``` - -If you need to add a dependency, this will install it and add it your -`package.json`: - -``` -npm install --save <name_of_module> -``` - -## Service-related Tasks - -The template comes with some handy `npm` tasks. To start your service based on -the configuration in `config.yaml`, use simply: - -``` -npm start -``` - -Starting unit tests is as easy as: - -``` -npm test -``` - -A code coverage utility is also available: - -``` -npm run-script coverage -``` - -Once the script finishes, open up `coverage/lcov-report/index.html` which will -show you detailed reports about which lines of code have been covered by the -unit tests. - -## Docker - -Included in the template is also a Dockerfile, allowing you to run and test your -service in a production-like environment inside of a Docker container. You need -to have [docker](https://www.docker.com/) installed if you are on a Linux host, -or [boot2docker](http://boot2docker.io/) in case of OSX/Windows hosts. - -To start your service in the container, execute: - -``` -npm run-script docker-start -``` - -The first time you run it, it takes a while as the script automatically builds -the full image and then starts the service. - -If you want to test your service instead, use: - -``` -npm run-script docker-test -``` - -Similarly, to run code coverage, run: - -``` -npm run-script docker-cover -``` - -*Note:* On Linux hosts, running `docker` requires superuser rights, so you may -need to prefix the commands with `sudo`. If you are on a Ubuntu box, you may -circumvent that by adding yourself to the `docker` group: - -``` -sudo gpasswd -a <your_username> docker -``` - -After you log out completely and log back in, you should be able to run the -above scripts without resorting to `sudo`. - -## Deployment - -See [this document](deployment.md) for how to get ready to deploy your service. - diff --git a/doc/config.md b/doc/config.md deleted file mode 100644 index e2009f8..0000000 --- a/doc/config.md +++ /dev/null @@ -1,49 +0,0 @@ -# Configuration - -The first thing you should configure is the service's general information (name, -description, etc.). Open up [`package.json`](../package.json) and change (at -least) the following fields: - -- `name` -- `version` -- `description` -- `repository/url` -- `keywords` -- `author` -- `contributors` -- `licence` -- `bugs` -- `homepage` - -Now change the service's name in [`config.dev.yaml`](../config.dev.yaml#L26) and -[`config.prod.yaml`](../config.prod.yaml#L26). While you are there, you might -want to look at and play with other configuration parameters, such as: - -- `num_workers` - the number of workers to start; some special values are: - - `0` will not do any forking, but run the service in the master process - - `ncpu` will spawn as many worker processes as there are CPU cores on the - host -- `worker_heap_limit_mb` - the maximum amount of memory (in MB) a worker's heap - can have -- `logging` and `metrics` - the configuration for logging and metrics facilities -- `services` - the block instructing the master process which services to start; - there can be more than one service, if, e.g., your service depends on another - Node.js service being present; each service has further the following - information: - - `name` - the service's name - - `module` - the module starting the service; if not given, the service's name - is used instead - - `conf` - the configuration object passed directly to the service; settings - to consider (remember to update them in both - [`config.dev.yaml`](../config.dev.yaml) as well as - [`config.prod.yaml`](../config.prod.yaml)): - - `port` - the port to start the service on (default: `8888`) - - `interface` - where to bind the service's server (default: `0.0.0.0`) - - you may add here any other configuration options needed by your service, - as long as it is [valid YAML](http://www.yaml.org/spec/1.2/spec.html); - these will be accessible via the `app.conf` object - -For more information on configuration possibilities, take a look at the -[service-runner -documentation](https://github.com/wikimedia/service-runner#config-loading). - diff --git a/doc/deployment.md b/doc/deployment.md deleted file mode 100644 index 68a421c..0000000 --- a/doc/deployment.md +++ /dev/null @@ -1,190 +0,0 @@ -# Deployment - -Getting your service ready to be deployed on WMF production machines involves -several tasks. This document explains the steps needed to get started and how to -keep your deployable copy up-to-date. - -## Repositories - -Because Node.js services use npm dependencies which can be binary, these need to -be pre-built. Therefore, two repositories are needed; one for the source code of -your service, and the other, so-called *deploy* repository. Both should be -available as WM's Gerrit repositories with the paths -*mediawiki/services/your-service-name* and -*mediawiki/services/your-service-name/deploy*. When [requesting -them](https://www.mediawiki.org/wiki/Git/New_repositories/Requests) ask for the -former to be a clone of [the service -template](https://github.com/wikimedia/service-template-node) and the latter to -be empty. - -It is important to note that the deploy repository is only to be updated -directly before (re-)deploying the service, and not on each patch merge entering -the *master* branch of the regular repository. In other words, **the deploy -repository mirrors the code deployed in production at all times**. - -The remainder of the document assumes these two repositories have been created -and that you have cloned them using your Gerrit account, i.e. not anonymously, -with the following outline: - -``` -~/code/ - |- your-service - -- deploy -``` - -Furthermore, it is assumed that you have initialised the deploy repository: - -```bash -$ cd ~/code/deploy -$ git review -s -$ touch README.md -$ git add README.md -$ git commit -m "Initial commit" -$ git push -u origin master # or git review -R if this fails -# go to Gerrit and +2 your change, if needed and then: -$ git pull -``` - -Finally, if you haven't yet done so, do [basic service -configuration](config.md). - -The remainder of the document refers to these two repositories as the *source -repository* and the *deploy repository*, respectively. - -## Configuration - -The service template includes an automation script which updates the deploy -repository, but it needs to be configured properly in order to work. - -### package.json - -The first part of the configuration involves keeping your source repository's -`package.json` updated. Look for its [deploy stanza](../package.json#L49). -Depending on the exact machine on which your service will be deployed, you may -need to set `target` to either `ubuntu` or `debian`. - -If you want to specify a version of Node.JS, different from the official distribution -package, set the value of the `node` stanza to the desired version, following -[nvm](https://github.com/creationix/nvm) versions naming. -To explicitly force official distribution package, `"system"` version can be used. - -The important thing is keeping the `dependencies` field up to date at all times. -There you should list all of the extra packages that are needed in order to -build the npm module dependencies. The `_all` field denotes packages which -should be installed regardless of the target distribution, but you can add -other, distribution-specific package lists, e.g.: - -```javascript -"deploy": { - "target": "ubuntu", - "node": "system", - "dependencies": { - "ubuntu": ["pkg1", "pkg2"], - "debian": ["pkgA", "pkgB"], - "_all": ["pkgOne", "pkgTwo"] - } -} -``` - -In this example, with the current configuration, packages *pkg1*, *pkg2*, -*pkgOne* and *pkgTwo* are going to be installed before building the -dependencies. If, instead, the target is changed to `debian`, then *pkgA*, -*pkgB*, *pkgOne* and *pkgTwo* are selected. - -As a rule of thumb, **whenever you need to install extra packages into your -development environment for satisfying node module dependencies, add them to -*deploy.dependencies* to ensure the successful build and update of the deploy -repository**. - -### Local git - -The script needs to know where to find your local copy of the deploy repository. -To that end, when in your source repository, run: - -``` -git config deploy.dir /absolute/path/to/deploy/repo -``` - -Using the aforementioned local outline, you would type: - -``` -git config deploy.dir /home/YOU/code/deploy -``` - -The source repository is itself a submodule of the deploy repository. If its -name as specified in `package.json`'s `name` field does not match the actual -repository's name in Gerrit, run: - -``` -git config deploy.name name_in_gerrit -``` - -That will make the system look for the repository -`mediawiki/services/name_in_gerrit` when checking it out in the deploy -repository. If, however, you do not use MediaWiki's Gerrit installation to host -your repository, you can specify a different one using the `deploy.submodule` -configuration directive by supplying the full remote reference URL: - -``` -git config deploy.submodule https://github.com/your_team/repo_name -``` - -The deploy-repo builder script assumes the name of the remote to check out in -the deploy repository is `origin`. An alternative name can be configured by -invoking (in the source repository): - - -``` -git config deploy.remote deploy_repo_remote_name -``` - -## Testing - -Before updating the deploy repository you need to make sure your configuration -works as expected. To do that, in your source repository run: - -``` -./server.js docker-test -``` - -The script will build a new Docker image, install the needed packages and npm -dependencies and run the test suite. Tweak your code and configuration until -everything works as expected (and commit those changes). - -## Update - -The final step is updating the deploy repository. First. make sure that your -source repository has got the latest dependencies installed: - -``` -rm -rf node_modules/ && npm install -``` - -Update the deploy repository by running from the source repository: - -``` -./server.js build --deploy-repo -``` - -The script will: -- create the proper deploy repository outline -- fetch the updates -- ensure the submodule is present -- update the submodule -- build the npm dependencies -- commit the changes with a pretty-formatted message - -There is also a handy shortcut for sending the patch to Gerrit immediately. To -do so, add the `--review` argument to the call: - -``` -./server.js build --deploy-repo --review -``` - -Note that if no changes were made to the source repository, the script aborts -its execution. If, nevertheless, you need to rebuild the dependencies, you can -do so using: - -``` -./server.js build --deploy-repo --force -``` diff --git a/doc/template.md b/doc/template.md deleted file mode 100644 index f9d28ad..0000000 --- a/doc/template.md +++ /dev/null @@ -1,67 +0,0 @@ -# Service Template Overview - -This service template allows you to quickly dive into coding your own RESTful API -service. - -- [Stack](#stack) -- [Repository Outline](#repository-outline) - -## Stack - -The template makes use the following components: - -- [service-runner](https://github.com/wikimedia/service-runner) -- [express.js](http://expressjs.com/) -- [Bluebird Promises](https://github.com/petkaantonov/bluebird) -- [mocha](http://mochajs.org/) -- [istanbul](https://github.com/gotwarlost/istanbul) -- [docker](https://www.docker.com/) - -Everything begins and ends with *service-runner*. It is the supervisor in charge -of starting the service and controlling its execution. It spawns worker -processes, each of which accepts and handles connections. If some workers use -too much heap memory, they are restarted. Additionally, it provides your service -with configurable logging and metrics facilities. - -When it comes to request handling, *express.js* and *Bluebird* take the centre -stage. *express.js* is in charge of receiving the requests, routing and -dispatching them to the correct handlers and send responses back to the clients. -*Bluebird* comes into play when there are actions which warrant asynchronous -processing (such as reading files, dispatching requests to external resources, -etc.). You can find example route handlers constructing the response both -synchronously and asynchronously in this template's [routes](../routes/) -directory. - -Finally, testing is an important aspect of service programming, not only for -their creators, but also testers (think CI) and consumers. The template uses -*mocha* for carrying out the testing, and *istanbul* for reporting code coverage -with tests. There are quite a few tests [available](../test/) for you to check -out. - -The WMF is in the process of switching its production servers to Debian Jessie. -As people developing services might use different platforms, the template -provides also a Dockerfile, with which one can execute their service inside a -container running the production OS. - -## Repository Outline - -Below is a simplified repository outline listing the important files/directories -for service development. - -- [`package.json`](../package.json) - the file containing the service's name and - dependencies -- [`config.dev.yaml`](../config.dev.yaml) and - [`config.prod.yaml`](../config.prod.yaml) - contain development and production - configuration settings for the service -- [`server.js`](../server.js) - the service's starter script -- [`app.js`](../app.js) - contains the application declaration and loading logic -- [`routes`](../routes/) - contains the definitions of the loaded routes; this - is where most of your coding is to take place -- [`lib/util.js`](../lib/util.js) - contains some utility functions and classes -- [`static`](../static/) - this is where served static files go (HTML, CSS, - client-side JS, etc.) -- [`test`](../test/) - contains the test files for the example routes in the - template; you should add your own here -- docker script - a utility script building the service's docker image and - starting the container, now part of [service-runner](wikimedia/service-runner) - -- To view, visit https://gerrit.wikimedia.org/r/390877 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7ba901ed556c1c73157933a314da76cd0af1dacc Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/services/mobileapps Gerrit-Branch: master Gerrit-Owner: Mholloway <mhollo...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits