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