1 | # AEgir
|
2 |
|
3 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
|
4 | [![Travis CI](https://flat.badgen.net/travis/ipfs/aegir)](https://travis-ci.com/ipfs/aegir)
|
5 | [![Dependency Status](https://david-dm.org/ipfs/aegir.svg?style=flat-square)](https://david-dm.org/ipfs/aegir)
|
6 |
|
7 | > Automated JavaScript project management.
|
8 |
|
9 | ## Lead Maintainer
|
10 |
|
11 | [Hugo Dias](https://github.com/hugomrdias)
|
12 |
|
13 |
|
14 | ## Project Structure
|
15 |
|
16 | The project structure when using this is quite strict, to ease
|
17 | replication and configuration overhead.
|
18 |
|
19 | All source code should be placed under `src`, with the main entry
|
20 | point being `src/index.js`.
|
21 |
|
22 | All test files should be placed under `test`. Individual test files should end in `.spec.js` and setup files for the node and the browser should be `test/node.js` and `test/browser.js` respectively.
|
23 |
|
24 | Your `package.json` should have the following entries and should pass `aegir lint-package-json`.
|
25 |
|
26 |
|
27 | ```json
|
28 | "main": "src/index.js",
|
29 | "files": [
|
30 | "src",
|
31 | "dist"
|
32 | ],
|
33 | "scripts": {
|
34 | "lint": "aegir lint",
|
35 | "release": "aegir release",
|
36 | "build": "aegir build",
|
37 | "test": "aegir test",
|
38 | "test:node": "aegir test --target node",
|
39 | "test:browser": "aegir test --target browser"
|
40 | }
|
41 | ```
|
42 | ## Travis Setup
|
43 |
|
44 | Check this tutorial https://github.com/ipfs/aegir/wiki/Travis-Setup
|
45 |
|
46 |
|
47 | ## Stack Requirements
|
48 |
|
49 | To bring you its many benefits, `aegir` requires
|
50 |
|
51 | - JS written in [Standard](https://github.com/feross/standard) style
|
52 | - Tests written in [Mocha](https://github.com/mochajs/mocha)
|
53 | - [Karma](https://github.com/karma-runner/karma) for browser tests
|
54 |
|
55 | ## Testing helpers
|
56 | In addition to running the tests `aegir` also provides several helpers to be used by the tests.
|
57 |
|
58 | #### Fixtures
|
59 |
|
60 | Loading fixture files in node and the browser can be painful, that's why aegir provides
|
61 | a method to do this. For it to work you have to put your fixtures in the folder `test/fixtures`, and then
|
62 |
|
63 | ```js
|
64 | // test/awesome.spec.js
|
65 | const loadFixture = require('aegir/fixtures')
|
66 |
|
67 | const myFixture = loadFixture('test/fixtures/largefixture')
|
68 | ```
|
69 |
|
70 | The path to the fixture is relative to the module root.
|
71 |
|
72 | If you write a module like [interface-ipfs-core](https://github.com/ipfs/interface-ipfs-core)
|
73 | which is to be consumed by other modules tests you need to pass in a third parameter such that
|
74 | the server is able to serve the correct files.
|
75 |
|
76 | For example
|
77 |
|
78 | ```js
|
79 | // awesome-tests module
|
80 | const loadFixture = require('aegir/fixtures')
|
81 |
|
82 | const myFixture = loadFixture('test/fixtures/coolfixture', 'awesome-tests')
|
83 | ```
|
84 |
|
85 |
|
86 | ```js
|
87 | // tests for module using the awesome-tests
|
88 | require('awesome-tests')
|
89 | ```
|
90 |
|
91 | ```js
|
92 | // .aegir.js file in the module using the awesome-tests module
|
93 | 'use strict'
|
94 |
|
95 | module.exports = {
|
96 | karma: {
|
97 | files: [{
|
98 | pattern: 'node_modules/awesome-tests/test/fixtures/**/*',
|
99 | watched: false,
|
100 | served: true,
|
101 | included: false
|
102 | }]
|
103 | }
|
104 | }
|
105 | ```
|
106 |
|
107 | #### Echo Server
|
108 | HTTP echo server for testing purposes.
|
109 |
|
110 | ```js
|
111 | const EchoServer = require('aegir/utils/echo-server')
|
112 | const server = new EchoServer()
|
113 | await server.start()
|
114 |
|
115 | // search params echo endpoint
|
116 | const req = await fetch('http://127.0.0.1:3000/echo/query?test=one')
|
117 | console.log(await req.text())
|
118 |
|
119 | // body echo endpoint
|
120 | const req = await fetch('http://127.0.0.1:3000/echo', {
|
121 | method: 'POST',
|
122 | body: '{"key": "value"}'
|
123 | })
|
124 | console.log(await req.text())
|
125 |
|
126 | // redirect endpoint
|
127 | const req = await fetch('http://127.0.0.1:3000/redirect?to=http://127.0.0.1:3000/echo')
|
128 | console.log(await req.text())
|
129 |
|
130 | // download endpoint
|
131 | const req = await fetch('http://127.0.0.1:3000/download?data=helloWorld')
|
132 | console.log(await req.text())
|
133 |
|
134 | await server.stop()
|
135 |
|
136 | ```
|
137 |
|
138 | #### Get Port
|
139 | Helper to find an available port to put a server listening on.
|
140 | ```js
|
141 | const getPort = require('aegir/utils/get-port')
|
142 | const port = await getPort(3000, '127.0.0.1')
|
143 | // if 3000 is available returns 3000 if not returns a free port.
|
144 |
|
145 | ```
|
146 |
|
147 | ## Tasks
|
148 |
|
149 | ### Linting
|
150 |
|
151 | Linting uses [eslint](http://eslint.org/) and [standard](https://github.com/feross/standard)
|
152 | with [some custom rules](https://github.com/ipfs/eslint-config-aegir) to enforce some more strictness.
|
153 |
|
154 | You can run it using
|
155 |
|
156 | ```bash
|
157 | $ aegir lint
|
158 | $ aegir lint-package-json
|
159 | ```
|
160 |
|
161 | ### Testing
|
162 |
|
163 | You can run it using
|
164 |
|
165 | ```bash
|
166 | $ aegir test
|
167 | ```
|
168 |
|
169 | There are also browser and node specific tasks
|
170 |
|
171 | ```bash
|
172 | $ aegir test --target node
|
173 | $ aegir test --target browser
|
174 | $ aegir test --target webworker
|
175 | ```
|
176 |
|
177 |
|
178 | ### Coverage
|
179 |
|
180 | #### Node
|
181 | You can run your tests with `nyc` using
|
182 |
|
183 | ```bash
|
184 | $ npx nyc -s aegir test -t node
|
185 | # to check the report locally
|
186 | $ npx nyc report --reporter=html && open coverage/index.html
|
187 | # or just for a text based reporter
|
188 | $ npx nyc report
|
189 | ```
|
190 | #### Browser
|
191 | > Not available yet PR open.
|
192 |
|
193 |
|
194 | To auto publish coverage reports from Travis to Codecov add this to
|
195 | your `.travis.yml` file.
|
196 |
|
197 | ```yml
|
198 | after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov
|
199 | ```
|
200 |
|
201 | ### Building
|
202 |
|
203 |
|
204 | You can run it using
|
205 |
|
206 | ```bash
|
207 | $ aegir build
|
208 | ```
|
209 | This will build a browser ready version into `dist`, so after publishing the results will be available under
|
210 |
|
211 | ```
|
212 | https://unpkg.com/<module-name>/dist/index.js
|
213 | https://unpkg.com/<module-name>/dist/index.min.js
|
214 | ```
|
215 |
|
216 | **Specifying a custom entry file for Webpack**
|
217 |
|
218 | By default, `aegir` uses `src/index.js` as the entry file for Webpack. You can customize which file to use as the entry point by specifying `entry` field in your user configuration file. To do this, create `.aegir.js` file in your project's root diretory and add point the `entry` field to the file Webpack should use as the entry:
|
219 |
|
220 | ```javascript
|
221 | module.exports = {
|
222 | entry: "src/browser-index.js",
|
223 | }
|
224 | ```
|
225 |
|
226 | Webpack will use the specified file as the entry point and output it to `dist/<filename>`, eg. `dist/browser-index.js`.
|
227 |
|
228 | If `.aegir.js` file is not present in the project, webpack will use `src/index.js` as the default entry file.
|
229 |
|
230 | #### Generating Webpack stats.json
|
231 |
|
232 | Pass the `--analyze` option to have Webpack generate a `stats.json` file for the bundle and save it in the project root (see https://webpack.js.org/api/stats/). e.g.
|
233 |
|
234 | ```bash
|
235 | aegir build --analyze
|
236 | ```
|
237 |
|
238 | ### Releasing
|
239 |
|
240 | 1. Run linting
|
241 | 2. Run tests
|
242 | 3. Build everything
|
243 | 4. Bump the version in `package.json`
|
244 | 5. Generate a changelog based on the git log
|
245 | 6. Commit the version change & `CHANGELOG.md`
|
246 | 7. Create a git tag
|
247 | 8. Run `git push` to `origin/master`
|
248 | 9. Publish a release to Github releases
|
249 | 10. Generate documentation and push to github
|
250 | 11. Publish to npm
|
251 |
|
252 | ```bash
|
253 | # Major release
|
254 | $ aegir release --type major
|
255 | # Minor relase
|
256 | $ aegir release --type minor
|
257 | # Patch release
|
258 | $ aegir release
|
259 |
|
260 | # Major prerelease (1.0.0 -> 2.0.0-rc.0)
|
261 | $ aegir release --type premajor --preid rc --dist-tag next
|
262 | # Minor prerelease (1.0.0 -> 1.1.0-rc.0)
|
263 | $ aegir release --type preminor --preid rc --dist-tag next
|
264 | # Patch prerelease (1.0.0 -> 1.0.1-rc.0)
|
265 | $ aegir release --type prepatch --preid rc --dist-tag next
|
266 |
|
267 | # Increment prerelease (1.1.0-rc.0 -> 1.1.0-rc.1)
|
268 | $ aegir release --type prerelease --preid rc --dist-tag next
|
269 | ```
|
270 |
|
271 | > This requires `AEGIR_GHTOKEN` to be set.
|
272 |
|
273 | You can also specify the same targets as for `test`.
|
274 |
|
275 | If no `CHANGELOG.md` is present, one is generated the first time a release is done.
|
276 |
|
277 | You can skip all changelog generation and the github release by passing
|
278 | in `--no-changelog`.
|
279 |
|
280 | If you want no documentation generation you can pass `--no-docs` to the release task to disable documentation builds.
|
281 |
|
282 | #### Scoped Github Token
|
283 |
|
284 | Performing a release involves creating new commits and tags and then pushing them back to the repository you are releasing from. In order to do this you should create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) and store it in the environmental variable `AEGIR_GHTOKEN`.
|
285 |
|
286 | The only access scope it needs is `public_repo`.
|
287 |
|
288 | Be aware that by storing it in `~/.profile` or similar you will make it available to any program that runs on your computer.
|
289 |
|
290 | ### Documentation
|
291 |
|
292 | You can use `aegir docs` to generate documentation. This uses [documentation.js](http://documentation.js.org/) with the theme [clean-documentation-theme](https://github.com/dignifiedquire/clean-documentation-theme).
|
293 |
|
294 | To publish the documentation automatically to the `gh-pages` branch you can run
|
295 |
|
296 | ```bash
|
297 | $ aegir docs --publish
|
298 | ```
|
299 |
|
300 | ## License
|
301 |
|
302 | MIT
|