├── .eslintrc ├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── documentation.md │ ├── bug_report.md │ └── regression.md ├── LICENSE └── PULL_REQUEST_TEMPLATE.md ├── CHANGELOG.md ├── .gitignore ├── SECURITY.md ├── LICENSE ├── package.json ├── README.md ├── index.js ├── test.js └── CONTRIBUTING.md /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "godaddy", 3 | "rules": { 4 | "strict": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 👉 Please follow one of these issue templates https://github.com/warehouseai/carpenterd-api-client/issues/new/choose 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | - [#3] Add collected documentation and badges. 4 | 5 | [#3]: https://github.com/warehouseai/carpenterd-api-client/pull/3 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 📃 Documentation Bug 3 | about: You want to report something that is wrong or missing from the documentation. 4 | labels: "Type: Docs" 5 | --- 6 | 7 | ## 📃 Summary 8 | 11 | 12 | ## Expected documentation 13 | 16 | -------------------------------------------------------------------------------- /.github/LICENSE: -------------------------------------------------------------------------------- 1 | `ISSUE_TEMPLATE.md` and markdown files under the `ISSUE_TEMPLATE` directory are adapted from `react-native` under MIT. 2 | 3 | https://github.com/facebook/react-native/blob/master/.github/ISSUE_TEMPLATE.md 4 | https://github.com/facebook/react-native/blob/37bf2ce/.github/ISSUE_TEMPLATE.md 5 | 6 | https://github.com/facebook/react-native/tree/master/.github/ISSUE_TEMPLATE 7 | https://github.com/facebook/react-native/tree/37bf2ce/.github/ISSUE_TEMPLATE 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Summary 8 | 9 | 13 | 14 | ## Changelog 15 | 16 | 20 | 21 | ## Test Plan 22 | 23 | 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: You want to report a reproducible bug. 4 | labels: "Type: Bug Report" 5 | --- 6 | 7 | ## 🐛 Bug Report 8 | 12 | 13 | ## To Reproduce 14 | 17 | 18 | ## Expected Behavior 19 | 22 | 23 | ## Code Example 24 | 30 | 31 | ## Environment 32 | 35 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | We take security very seriously at GoDaddy. We appreciate your efforts to 4 | responsibly disclose your findings, and will make every effort to acknowledge 5 | your contributions. 6 | 7 | ## Where should I report security issues? 8 | 9 | In order to give the community time to respond and upgrade, we strongly urge you 10 | report all security issues privately. 11 | 12 | To report a security issue in one of our Open Source projects email us directly 13 | at **oss@godaddy.com** and include the word "SECURITY" in the subject line. 14 | 15 | This mail is delivered to our Open Source Security team. 16 | 17 | After the initial reply to your report, the team will keep you informed of the 18 | progress being made towards a fix and announcement, and may ask for additional 19 | information or guidance. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/regression.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💥 Regression Report 3 | about: You want to report unexpected behavior that worked in previous releases. 4 | labels: "Type: Bug Report", "Impact: Regression" 5 | --- 6 | 7 | ## 💥 Regression Report 8 | 11 | 12 | ## Last working version 13 | 14 | Worked up to version: 15 | 16 | Stopped working in version: 17 | 18 | ## To Reproduce 19 | 20 | 23 | 24 | ## Expected Behavior 25 | 26 | 29 | 30 | ## Code Example 31 | 37 | 38 | ## Environment 39 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 GoDaddy Operating Company, LLC. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carpenterd-api-client", 3 | "version": "2.0.0", 4 | "description": "Node.js API client to interact with the carpenter build service.", 5 | "main": "index.js", 6 | "scripts": { 7 | "eslint": "eslint-godaddy -c .eslintrc ./*.js", 8 | "pretest": "npm run eslint", 9 | "test": "mocha test.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git@github.com:warehouseai/carpenterd-api-client.git" 14 | }, 15 | "keywords": [ 16 | "carpenter", 17 | "api", 18 | "client" 19 | ], 20 | "author": "GoDaddy.com Operating Company, LLC", 21 | "contributors": [ 22 | "Arnout Kazemier ", 23 | "Martijn Swaagman ", 24 | "Charlie Robbins ", 25 | "Jarrett Cruger " 26 | ], 27 | "license": "MIT", 28 | "dependencies": { 29 | "hyperquest": "~2.1.1" 30 | }, 31 | "devDependencies": { 32 | "assume": "^2.1.0", 33 | "eslint": "^5.12.0", 34 | "eslint-config-godaddy": "^3.0.0", 35 | "eslint-plugin-json": "^1.2.0", 36 | "eslint-plugin-mocha": "^5.2.0", 37 | "mocha": "^5.2.0", 38 | "nock": "^10.0.6" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `carpenterd-api-client` 2 | 3 | > ⚠️ **DEPRECATED**: This package is no longer maintained and has been deprecated. Please use an alternative solution or contact the maintainers for more information. 4 | 5 | [![Version npm](https://img.shields.io/npm/v/carpenterd-api-client.svg?style=flat-square)](https://www.npmjs.com/package/carpenterd-api-client) 6 | [![License](https://img.shields.io/npm/l/carpenterd-api-client.svg?style=flat-square)](https://github.com/warehouseai/carpenterd-api-client/blob/master/LICENSE) 7 | [![npm Downloads](https://img.shields.io/npm/dm/carpenterd-api-client.svg?style=flat-square)](https://npmcharts.com/compare/carpenterd-api-client?minimal=true) 8 | [![Dependencies](https://img.shields.io/david/warehouseai/carpenterd-api-client.svg?style=flat-square)](https://github.com/warehouseai/carpenterd-api-client/blob/master/package.json) 9 | 10 | The `carpenterd-api-client` is an API client for the [`carpenterd`][carpenterd] 11 | build service. 12 | 13 | ## Install 14 | 15 | Install `carpenterd-api-client` from the npm registry: 16 | ``` 17 | npm install --save carpenterd-api-client 18 | ``` 19 | 20 | ## Usage 21 | 22 | In all examples we assume that you've already initialized the client as 23 | followed: 24 | 25 | ```js 26 | 'use strict'; 27 | 28 | const Carpenter = require('carpenterd-api-client'); 29 | 30 | const carpenter = new Carpenter('url-to-the-service'); 31 | ``` 32 | 33 | As you can see in the example above, the `Carpenter` constructor requires one 34 | argument: 35 | 36 | - The URL of the carpenter API where we should send the requests to. 37 | 38 | ## API 39 | 40 | ### build 41 | 42 | Trigger a new build on carpenter service. The data provided should have 43 | the same structure and signature as `npm publish` posted JSON. 44 | 45 | ```js 46 | carpenter.build({ data: { 47 | "name": "tester", // name of the package 48 | "dist-tags": { 49 | "latest": "1.0.0" 50 | }, 51 | "versions": { 52 | "1.0.0": { 53 | "name": "tester", 54 | "version": "1.0.0" 55 | ... 56 | } 57 | }, 58 | "_attachment": "" // base64 encoded binary blob 59 | }}, function () { 60 | 61 | }); 62 | ``` 63 | 64 | ### cancel 65 | 66 | Cancel a build on carpenter service. 67 | 68 | ```js 69 | carpenter.cancel({ 70 | "pkg": "tester", // name of the package 71 | "version": "1.0.0", // valid semver 72 | "env": "prod" // optional environment parameter 73 | }}, function () { 74 | 75 | }); 76 | ``` 77 | 78 | ## Tests 79 | 80 | ```sh 81 | npm test 82 | ``` 83 | 84 | [carpenterd]: https://github.com/godaddy/carpenterd 85 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var request = require('hyperquest'), 4 | url = require('url'); 5 | 6 | // 7 | // Methods that require an `application/json` header. 8 | // 9 | var methods = ['POST', 'PUT']; 10 | 11 | /** 12 | * Carpenter API client. 13 | * 14 | * @constructor 15 | * @param {Object|String} opts Options for root URL of carpenter service 16 | * @param {String} opts.url The root URL of the carpenter service 17 | * @param {String} opts.uri The root URL of the carpenter service 18 | * @param {String} opts.href The href for root URL of the carpenter service 19 | * @param {String} opts.protocol Protocol for root URL of the carpenter service 20 | * @param {String} opts.version The carpenter build API version to use (defaults to v2) 21 | * @public 22 | */ 23 | function Carpenter(opts) { 24 | // eslint-disable-next-line no-new 25 | if (!this) new Carpenter(opts); 26 | 27 | if (typeof opts === 'string') { 28 | this.base = opts; 29 | } else if (opts.protocol && opts.href) { 30 | this.base = url.format(opts); 31 | } else if (opts.url || opts.uri) { 32 | this.base = opts.url || opts.uri; 33 | } else { 34 | throw new Error('Carpenter URL required'); 35 | } 36 | 37 | this.version = (opts.version === '1' || opts.version === 'v1' || opts.version === 1) ? '' : 'v2'; 38 | 39 | // 40 | // Handle all possible cases 41 | // 42 | this.base = typeof this.base === 'object' 43 | ? url.format(this.base) 44 | : this.base; 45 | 46 | this.timeout = opts.timeout || 0; 47 | this.agent = opts.agent; 48 | } 49 | 50 | /** 51 | * Trigger a new build. 52 | * 53 | * @param {Object} options Configuration. 54 | * @param {Function} next Completion callback. 55 | * @returns {Stream} the request 56 | * @private 57 | */ 58 | Carpenter.prototype.build = function build(options, next) { 59 | options = options || {}; 60 | options.method = options.method || 'POST'; 61 | 62 | return this.send([ 63 | this.version, 64 | 'build' 65 | ].filter(Boolean).join('/'), options, next); 66 | }; 67 | 68 | /** 69 | * Cancel a build. The parameters are provided by options and filtered to allow 70 | * optional parameters. 71 | * 72 | * @param {Object} options Configuration. 73 | * @param {Function} next Completion callback. 74 | * @returns {Stream} the request 75 | * @private 76 | */ 77 | Carpenter.prototype.cancel = function cancel(options, next) { 78 | options = options || {}; 79 | options.method = 'GET'; 80 | 81 | return this.send([ 82 | 'cancel', 83 | options.pkg, 84 | options.version, 85 | options.env 86 | ].filter(Boolean).join('/'), options, next); 87 | }; 88 | 89 | /** 90 | * Internal API for sending data. 91 | * 92 | * @param {String} pathname Pathname we need to hit. 93 | * @param {Object} options Hyperquest options 94 | * @param {Function} next Completion callback. 95 | * @returns {Stream} the request 96 | * @api private 97 | */ 98 | Carpenter.prototype.send = function send(pathname, options, next) { 99 | var base = url.parse(this.base), 100 | data = false, 101 | req; 102 | 103 | if (typeof pathname === 'object') { 104 | options = pathname; 105 | pathname = null; 106 | } 107 | 108 | if (typeof options === 'function') { 109 | next = options; 110 | options = {}; 111 | } 112 | 113 | options.agent = this.agent; 114 | options.headers = options.headers || {}; 115 | options.timeout = options.timeout || this.timeout; 116 | 117 | base.pathname = pathname || options.pathname || '/'; 118 | 119 | // 120 | // Setup options from method and optional data. 121 | // 122 | data = options.data; 123 | if (typeof data === 'object' || ~methods.indexOf(options.method)) { 124 | options.method = options.method || 'POST'; 125 | options.headers['Content-Type'] = 'application/json'; 126 | } 127 | 128 | // 129 | // Setup hyperquest to formatted URL. 130 | // 131 | req = request(url.format(base), options, next); 132 | 133 | // 134 | // Write JSON data to the request if provided. Yhis is only required for 135 | // POST and PUT as hyperquest by default ends GET, DELETE and HEAD requests. 136 | // 137 | try { 138 | if (~methods.indexOf(options.method)) { 139 | req.end(typeof data === 'object' ? JSON.stringify(data) : data); 140 | } 141 | } catch (error) { 142 | return next(error); 143 | } 144 | 145 | return req; 146 | }; 147 | 148 | // 149 | // Expose the interface. 150 | // 151 | module.exports = Carpenter; 152 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | describe('carpenter-api-client', function () { 2 | 'use strict'; 3 | 4 | var assume = require('assume'), 5 | Carpenter = require('./'), 6 | nock = require('nock'), 7 | url = require('url'); 8 | var carpenter, uri; 9 | 10 | beforeEach(function each() { 11 | uri = 'http://localhost:8999/'; 12 | carpenter = new Carpenter(uri); 13 | }); 14 | 15 | afterEach(function each() { 16 | carpenter = null; 17 | }); 18 | 19 | it('can be configured with object', function () { 20 | carpenter = new Carpenter(url.parse(uri)); 21 | 22 | assume(carpenter.base).to.be.an('string'); 23 | assume(carpenter.base).to.equal(uri); 24 | }); 25 | 26 | it('can be configured with an agent and url', function () { 27 | carpenter = new Carpenter({ 28 | url: uri, 29 | agent: require('http').Agent 30 | }); 31 | 32 | assume(carpenter.agent); 33 | }); 34 | 35 | it('can be configured with default timeout and defaults to 0', function () { 36 | assume(carpenter).to.have.property('timeout', 0); 37 | 38 | carpenter = new Carpenter({ 39 | url: uri, 40 | timeout: 2 * 60 * 1000 41 | }); 42 | 43 | assume(carpenter).to.have.property('timeout', 120000); 44 | }); 45 | 46 | it('can be configured with an agent and url object', function () { 47 | carpenter = new Carpenter({ 48 | url: url.format(uri), 49 | agent: require('http').Agent 50 | }); 51 | 52 | assume(carpenter.base).to.equal(uri); 53 | assume(carpenter.agent); 54 | }); 55 | 56 | it('can be configured with an api version', function () { 57 | [1, '1', 'v1'].forEach(function (version) { 58 | carpenter = new Carpenter({ uri, version }); 59 | 60 | assume(carpenter.version).equals(''); 61 | }); 62 | }); 63 | 64 | it('defaults to the v2 api', function () { 65 | assume(new Carpenter({ uri }).version).equals('v2'); 66 | assume(new Carpenter({ uri, version: 'not one' }).version).equals('v2'); 67 | }); 68 | 69 | describe('#build', function () { 70 | var options = { 71 | data: { 72 | data: { name: 'foo-bar' }, 73 | promote: true 74 | } 75 | }; 76 | 77 | it('sends a request to /v2/build', function (next) { 78 | next = assume.wait(2, next); 79 | 80 | nock(uri) 81 | .post('/v2/build') 82 | .reply(200, function reply(uri, body) { 83 | assume(body.data.name).equals('foo-bar'); 84 | assume(body.promote).equals(true); 85 | nock.cleanAll(); 86 | next(); 87 | 88 | return {}; 89 | }); 90 | 91 | carpenter.build(options, next); 92 | }); 93 | 94 | it('can also send stringified data', function (next) { 95 | next = assume.wait(2, next); 96 | 97 | nock(uri) 98 | .post('/v2/build') 99 | .reply(200, function reply(uri, body) { 100 | assume(body.data.name).equals('foo-bar'); 101 | assume(body.promote).equals(true); 102 | nock.cleanAll(); 103 | next(); 104 | 105 | return {}; 106 | }); 107 | 108 | carpenter.build({ 109 | data: JSON.stringify(options.data) 110 | }, next); 111 | }); 112 | 113 | it('sends a request to /build when using v1 API', function (next) { 114 | carpenter = new Carpenter({ 115 | uri, 116 | version: 'v1' 117 | }); 118 | 119 | next = assume.wait(2, next); 120 | 121 | nock(uri) 122 | .post('/build') 123 | .reply(200, function reply(uri, body) { 124 | assume(body.name).equals('foo-bar'); 125 | nock.cleanAll(); 126 | next(); 127 | 128 | return {}; 129 | }); 130 | 131 | carpenter.build({ 132 | data: { name: 'foo-bar' } 133 | }, next); 134 | }); 135 | }); 136 | 137 | describe('#cancel', function () { 138 | var options = { 139 | pkg: 'foo-bar', 140 | version: '1.0.0', 141 | env: 'prod' 142 | }; 143 | 144 | it('sends a request to /cancel', function (next) { 145 | next = assume.wait(2, next); 146 | 147 | nock(uri) 148 | .get('/cancel/foo-bar/1.0.0/prod') 149 | .reply(200, function reply(uri, body) { 150 | assume(uri).equals('/cancel/foo-bar/1.0.0/prod'); 151 | assume(body).to.be.falsey(); 152 | nock.cleanAll(); 153 | next(); 154 | 155 | return {}; 156 | }); 157 | 158 | carpenter.cancel(options, next); 159 | }); 160 | 161 | it('has optional env parameter', function (next) { 162 | next = assume.wait(2, next); 163 | 164 | delete options.env; 165 | 166 | nock(uri) 167 | .get('/cancel/foo-bar/1.0.0') 168 | .reply(200, function reply(uri, body) { 169 | assume(uri).equals('/cancel/foo-bar/1.0.0'); 170 | assume(body).to.be.falsey(); 171 | nock.cleanAll(); 172 | next(); 173 | 174 | return {}; 175 | }); 176 | 177 | carpenter.cancel(options, next); 178 | }); 179 | }); 180 | }); 181 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is welcome to contribute to GoDaddy's Open Source Software. 4 | Contributing doesn’t just mean submitting pull requests. To get involved you 5 | can, report or triage bugs and participate in discussions on the evolution of 6 | each project. 7 | 8 | No matter how you want to get involved, we ask that you first learn what’s 9 | expected of anyone who participates in the project by reading the Contribution 10 | Guidelines. 11 | 12 | ## Answering Questions 13 | 14 | One of the most important and immediate ways you can support this project is 15 | to or [Github][issues]. Whether you’re 16 | helping a newcomer understand a feature or troubleshooting an edge case with a 17 | seasoned developer, your knowledge and experience with JS can go a long way 18 | to help others. 19 | 20 | ## Reporting Bugs 21 | 22 | **Do not report potential security vulnerabilities here. Refer to 23 | [SECURITY.md](./SECURITY.md) for more details about the process of reporting 24 | security vulnerabilities.** 25 | 26 | Before submitting a ticket, please be sure to have a simple replication of 27 | the behavior. If the issue is isolated to one of the dependencies of this 28 | project. Please create a Github issue in that project. All dependencies are 29 | open source software and can be easily found through [npm]. 30 | 31 | Submit a ticket for your issue, assuming one does not already exist: 32 | - Create it on our [Issue Tracker][issues] 33 | - Clearly describe the issue by following the template layout 34 | - Make sure to include steps to reproduce the bug. 35 | - A reproducible (unit) test could be helpful in solving the bug. 36 | - Describe the environment that (re)produced the problem. 37 | 38 | > For a bug to be actionable, it needs to be reproducible. If you or 39 | > contributors can’t reproduce the bug, try to figure out why. Please take 40 | > care to stay involved in discussions around solving the problem. 41 | 42 | ## Triaging bugs or contributing code 43 | 44 | If you're triaging a bug, try to reduce it. Once a bug can be reproduced, 45 | reduce it to the smallest amount of code possible. Reasoning about a sample 46 | or unit test that reproduces a bug in just a few lines of code is easier than 47 | reasoning about a longer sample. 48 | 49 | From a practical perspective, contributions are as simple as: 50 | - Forking the repository on GitHub. 51 | - Making changes to your forked repository. 52 | - When committing, reference your issue (if present) and include a note about 53 | the fix. 54 | - If possible, and if applicable, please also add/update unit tests for your 55 | changes. 56 | - Push the changes to your fork and submit a pull request to the 'master' 57 | branch of the projects' repository. 58 | 59 | If you are interested in making a large change and feel unsure about its 60 | overall effect, please make sure to first discuss the change and reach a 61 | consensus with core contributors. Then ask about the best way 62 | to go about making the change. 63 | 64 | ## Code Review 65 | 66 | Any open source project relies heavily on code review to improve software 67 | quality: 68 | 69 | > All significant changes, by all developers, must be reviewed before they 70 | > are committed to the repository. Code reviews are conducted on GitHub through 71 | > comments on pull requests or commits. The developer responsible for a code 72 | > change is also responsible for making all necessary review-related changes. 73 | 74 | Sometimes code reviews will take longer than you would hope for, especially 75 | for larger features. Here are some accepted ways to speed up review times for 76 | your patches: 77 | 78 | - Review other people’s changes. If you help out, everybody will be more 79 | willing to do the same for you. Goodwill is our currency. 80 | - Split your change into multiple smaller changes. The smaller your change, 81 | the higher the probability that somebody will take a quick look at it. 82 | - Remember that you’re asking for 83 | valuable time from other professional developers. 84 | 85 | **Note that anyone is welcome to review and give feedback on a change, but 86 | only people with commit access to the repository can approve it.** 87 | 88 | ## Attribution of Changes 89 | 90 | When contributors submit a change to this project, after that change is 91 | approved, other developers with commit access may commit it for the author. 92 | When doing so, it is important to retain correct attribution of the 93 | contribution. Generally speaking, Git handles attribution automatically. 94 | 95 | ## Code Documentation 96 | 97 | Ensure that every function in this project is documented and follows the 98 | standards set by [JSDoc]. Finally, please stick to the code style as defined 99 | by the [Godaddy JS styleguide][style]. 100 | 101 | # Additional Resources 102 | 103 | - [General GitHub Documentation](https://help.github.com/) 104 | - [GitHub Pull Request documentation](https://help.github.com/send-pull-requests/) 105 | - [JSDoc] 106 | 107 | [issues]: https://github.com/warehouseai/carpenterd-api-client/issues 108 | [JSDoc]: http://usejsdoc.org/ 109 | [npm]: http://npmjs.org/ 110 | [style]: https://github.com/godaddy/javascript/#godaddy-style 111 | --------------------------------------------------------------------------------