├── .editorconfig ├── .gitignore ├── LICENSE.md ├── README.md ├── package.json └── src ├── .jshintrc ├── app.js ├── config.js └── jenkins.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.DS_store 3 | *.ds_store 4 | *.log 5 | *.sublime-project 6 | *.sublime-workspace 7 | #* 8 | *# 9 | .#* 10 | *~ 11 | reports 12 | .project 13 | build 14 | coverage 15 | *.env 16 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 David Kelly 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # push-button-deploy 2 | 3 | Trigger Jenkins CI jobs via Amazon Dash Button press. 4 | 5 | ### Setup 6 | 7 | Dash Button presses are detected by listening for network activity with the hardware address of the button. We need to determine the hardware address first. 8 | 9 | ```bash 10 | npm run setup 11 | ``` 12 | 13 | The tool will listen for arp requests and report any hardware addresses discovered while it is running. 14 | 15 | ### Usage 16 | 17 | This app needs to be provided with the hardware address of the button discovered during the setup process via the environment. An optional `.env` file can be added to the base directory of this project to pass environment variables to the script. 18 | 19 | ```bash 20 | HW_ADDR=$dash_mac_address node src/app.js 21 | ``` 22 | 23 | **Example .env file** 24 | 25 | ```bash 26 | # Dash button 27 | HW_ADDR=FF:FF:FF:FF:FF:FF 28 | 29 | # Jenkins 30 | # See https://github.com/jansepar/node-jenkins-api#setup 31 | JENKINS_CONNECTION_STRING=https://username:password@ci.example.com/jenkins 32 | JENKINS_JOB=ci-job 33 | ``` 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "push-button-deploy", 3 | "version": "1.0.0", 4 | "description": "Literally deploy at the press of a button", 5 | "main": "src/app.js", 6 | "dependencies": { 7 | "dotenv": "^2.0.0", 8 | "jenkins-api": "^0.2.8", 9 | "node-dash-button": "^0.3.0" 10 | }, 11 | "scripts": { 12 | "setup": "findbutton", 13 | "pretest": "jshint src", 14 | "test": "echo \"Error: no test specified\" && exit 1", 15 | "start": "node src/app" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/dmkelly/push-button-deploy.git" 20 | }, 21 | "keywords": [ 22 | "amazon", 23 | "dash", 24 | "button", 25 | "ci", 26 | "deploy" 27 | ], 28 | "author": "Dave Kelly", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/dmkelly/push-button-deploy/issues" 32 | }, 33 | "homepage": "https://github.com/dmkelly/push-button-deploy#readme", 34 | "devDependencies": { 35 | "jshint": "^2.9.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Annotated default JSHint configuration file adapted from the 3 | // JSHint documentation http://jshint.com/docs/ tested with version 4 | // 0.9.1 of node-jshint https://npmjs.org/package/jshint 5 | // 6 | // Latest version: https://github.com/NeoPhi/jshint-config/ 7 | // 8 | // ************************************************************ 9 | // Miscellaneous 10 | // ******** 11 | // These options are not part of the standard JSHint documentation. 12 | // ************************************************************ 13 | 14 | // Maximum number of errors before failing 15 | "maxerr": 50, 16 | 17 | // An array of strings, the names of predefined global variables. 18 | "predef": [ 19 | ], 20 | 21 | // An object of global variables, with keys as names and a boolean 22 | // value to determine if they are assignable. 23 | "globals": { 24 | }, 25 | 26 | // ************************************************************ 27 | // Enforcing Options 28 | // ***************** 29 | // These options tell JSHint to be more strict towards your 30 | // code. Use them if you want to allow only a safe subset of 31 | // JavaScript-very useful when your codebase is shared with a big 32 | // number of developers with different skill levels. 33 | // ************************************************************ 34 | 35 | // This option prohibits the use of bitwise operators such as ^ 36 | // (XOR), | (OR) and others. Bitwise operators are very rare in 37 | // JavaScript programs and very often & is simply a mistyped &&. 38 | "bitwise": true, 39 | 40 | // This option allows you to force all variable names to use either 41 | // camelCase style or UPPER_CASE with underscores. 42 | "camelcase": false, 43 | 44 | // This option requires you to always put curly braces around blocks 45 | // in loops and conditionals. JavaScript allows you to omit curly 46 | // braces when the block consists of only one statement, for 47 | // example: 48 | // 49 | // while (day) 50 | // shuffle(); 51 | // 52 | // However, in some circumstances, it can lead to bugs: 53 | // 54 | // while (day) 55 | // shuffle(); 56 | // sleep(); // You would think that this is a part of your loop, 57 | // // but it is not. 58 | // 59 | // Generally, unless you are careful, it is safer to require curly 60 | // braces around all blocks. 61 | "curly": true, 62 | 63 | // This options prohibits the use of == and != in favor of === and 64 | // !==. The former try to coerce values before comparing them which 65 | // can lead to some unexpected results. The latter don't do any 66 | // coercion so they are generally safer. If you would like to learn 67 | // more about type coercion in JavaScript, we recommend Truth, 68 | // Equality and JavaScript by Angus Croll. 69 | // 70 | // Note: Even if this option is off, JSHint will check for unsafe 71 | // comparisons like != null unless option eqnull (see below) is 72 | // turned on. 73 | "eqeqeq": true, 74 | 75 | // This option requires all for in loops to filter object's 76 | // items. The for in statement allows for looping through the names 77 | // of all of the properties of an object including those inherited 78 | // through the prototype chain. This behavior can lead to 79 | // unexpected items in your object so it is generally safer to 80 | // always filter inherited properties out as shown in the example: 81 | // 82 | // for (key in obj) { 83 | // if (obj.hasOwnProperty(key)) { 84 | // // We are sure that obj[key] belongs to the object and was 85 | // // not inherited. 86 | // } 87 | // } 88 | // 89 | // For more in-depth understanding of for in loops in JavaScript, 90 | // read Exploring JavaScript for-in loops by Angus Croll. 91 | "forin": true, 92 | 93 | // This option prohibits the use of immediate function invocations 94 | // without wrapping them in parentheses. Wrapping parentheses 95 | // assists readers of your code in understanding that the expression 96 | // is the result of a function, and not the function itself. 97 | "immed": true, 98 | 99 | // This option enforces specific tab width for your code. For 100 | // example, the following code will trigger a warning on line 4: 101 | // 102 | // /*jshint indent:4 */ 103 | // if (cond) { 104 | // doSomething(); // We used only two spaces for indentation here 105 | // } 106 | "indent": 2, 107 | 108 | // This option prohibits the use of a variable before it was 109 | // defined. JavaScript has function scope only and, in addition to 110 | // that, all variables are always moved-or hoisted- to the top of 111 | // the function. This behavior can lead to some very nasty bugs and 112 | // that's why it is safer to always use variable only after they 113 | // have been explicitly defined. 114 | // 115 | // For more in-depth understanding of scoping and hoisting in 116 | // JavaScript, read JavaScript Scoping and Hoisting by Ben Cherry. 117 | "latedef": true, 118 | 119 | // This option requires you to capitalize names of constructor 120 | // functions. Capitalizing functions that are intended to be used 121 | // with new operator is just a convention that helps programmers to 122 | // visually distinguish constructor functions from other types of 123 | // functions to help spot mistakes when using this. 124 | // 125 | // Not doing so won't break your code in any browsers or 126 | // environments but it will be a bit harder to figure out—by reading 127 | // the code—if the function was supposed to be used with or without 128 | // new. And this is important because when the function that was 129 | // intended to be used with new is used without it, this will point 130 | // to the global object instead of a new object. 131 | // 132 | // function MyConstructor() { 133 | // console.log(this); 134 | // } 135 | // new MyConstructor(); // -> [MyConstructor] 136 | // MyConstructor(); // -> [DOMWindow] 137 | // 138 | // For a more in-depth understanding on how this works, read 139 | // Understanding JavaScript Function Invocation and "this" by Yehuda 140 | // Katz. 141 | "newcap": true, 142 | 143 | // This option prohibits the use of arguments.caller and 144 | // arguments.callee. Both .caller and .callee make quite a few 145 | // optimizations impossible so they were deprecated in future 146 | // versions of JavaScript. In fact, EcmaScript 5 forbids the use of 147 | // arguments.callee in strict mode. 148 | "noarg": true, 149 | 150 | // This option warns when you have an empty block in your 151 | // code. JSLint was originally warning for all empty blocks and we 152 | // simply made it optional. There were no studies reporting that 153 | // empty blocks in JavaScript break your code in any way. 154 | "noempty": true, 155 | 156 | // This option prohibits the use of constructor functions for 157 | // side-effects. Some people like to call constructor functions 158 | // without assigning its result to any variable: 159 | // 160 | // new MyConstructor(); 161 | // 162 | // There is no advantage in this approach over simply calling 163 | // MyConstructor since the object that the operator new creates 164 | // isn't used anywhere so you should generally avoid constructors 165 | // like this one. 166 | "nonew": true, 167 | 168 | // This option prohibits the use of unary increment and decrement 169 | // operators. Some people think that ++ and -- reduces the quality 170 | // of their coding styles and there are programming languages—such 171 | // as Python—that go completely without these operators. 172 | "plusplus": false, 173 | 174 | // This option enforces the consistency of quotation marks used 175 | // throughout your code. It accepts three values: true if you don't 176 | // want to enforce one particular style but want some consistency, 177 | // "single" if you want to allow only single quotes and "double" if 178 | // you want to allow only double quotes. 179 | "quotmark": "single", 180 | 181 | // This option prohibits the use of unsafe . in regular expressions. 182 | "regexp": true, 183 | 184 | // This option prohibits the use of explicitly undeclared 185 | // variables. This option is very useful for spotting leaking and 186 | // mistyped variables. 187 | // 188 | // /*jshint undef:true */ 189 | // function test() { 190 | // var myVar = 'Hello, World'; 191 | // console.log(myvar); // Oops, typoed here. JSHint with undef 192 | // // will complain 193 | // } 194 | // 195 | // If your variable is defined in another file, you can use /*global 196 | // ... */ syntax to tell JSHint about it. See the About page for more 197 | // information. 198 | "undef": true, 199 | 200 | // This option warns when you define and never use your 201 | // variables. It is very useful for general code cleanup, especially 202 | // when used in addition to undef. 203 | // 204 | // /*jshint unused:true */ 205 | // function test(a, b) { 206 | // var c, d = 2; 207 | // return a + d; 208 | // } 209 | // test(1, 2); 210 | // 211 | // // Line 3: 'b' was defined but never used. 212 | // // Line 4: 'c' was defined but never used. 213 | // 214 | // In addition to that, this option will warn you about unused 215 | // global variables declared via /*global ... */. 216 | "unused": true, 217 | 218 | // This option requires all functions to run in EcmaScript 5's 219 | // strict mode. Strict mode is a way to opt in to a restricted 220 | // variant of JavaScript. Strict mode eliminates some JavaScript 221 | // pitfalls that didn't cause errors by changing them to produce 222 | // errors. It also fixes mistakes that made it difficult for the 223 | // JavaScript engines to perform certain optimizations. 224 | // 225 | // Note: This option enables strict mode for function scope only. It 226 | // prohibits the global scoped strict mode because it might break 227 | // third-party widgets on your page. If you really want to use 228 | // global strict mode, see the globalstrict option. 229 | "strict": false, 230 | 231 | // This option makes it an error to leave a trailing whitespace in 232 | // your code. Trailing whitespaces can be source of nasty bugs with 233 | // multi-line strings in JavaScript: 234 | // 235 | // // This otherwise perfectly valid string will error if 236 | // // there is a whitespace after \ 237 | // var str = "Hello \ 238 | // World"; 239 | "trailing": true, 240 | 241 | // This option lets you set the max number of formal parameters 242 | // allowed per function: 243 | // 244 | // /*jshint maxparams:3 */ 245 | // function login(request, onSuccess) { 246 | // // ... 247 | // } 248 | // // JSHint: Too many parameters per function (4). 249 | // function logout(request, isManual, whereAmI, onSuccess) { 250 | // // ... 251 | // } 252 | "maxparams": false, 253 | 254 | // This option lets you control how nested do you want your blocks 255 | // to be: 256 | // 257 | // /*jshint maxdepth:2 */ 258 | // function main(meaning) { 259 | // var day = true; 260 | // if (meaning === 42) { 261 | // while (day) { 262 | // shuffle(); 263 | // if (tired) { // JSHint: Blocks are nested too deeply (3). 264 | // sleep(); 265 | // } 266 | // } 267 | // } 268 | // } 269 | "maxdepth": false, 270 | 271 | // This option lets you set the max number of statements allowed per 272 | // function: 273 | // 274 | // /*jshint maxstatements:4 */ 275 | // function main() { 276 | // var i = 0; 277 | // var j = 0; 278 | // // Function declarations count as one statement. Their bodies 279 | // // don't get taken into account for the outer function. 280 | // function inner() { 281 | // var i2 = 1; 282 | // var j2 = 1; 283 | // return i2 + j2; 284 | // } 285 | // j = i + j; 286 | // return j; // JSHint: Too many statements per function. (5) 287 | // } 288 | "maxstatements": false, 289 | 290 | // This option lets you control cyclomatic complexity throughout 291 | // your code. Cyclomatic complexity measures the number of linearly 292 | // independent paths through a program's source code. Read more 293 | // about cyclomatic complexity on Wikipedia. 294 | "maxcomplexity": false, 295 | 296 | // This option lets you set the maximum length of a line. 297 | "maxlen": false, 298 | 299 | // ************************************************************ 300 | // Relaxing Options 301 | // **************** 302 | // These options allow you to suppress certain types of 303 | // warnings. Use them only if you are absolutely positive that you 304 | // know what you are doing. 305 | // ************************************************************ 306 | 307 | // This option suppresses warnings about missing semicolons. There 308 | // is a lot of FUD (fear, uncertainty and doubt) spread about 309 | // semicolons by quite a few people in the community. The common 310 | // myths are that semicolons are required all the time (they are 311 | // not) and that they are unreliable. JavaScript has rules about 312 | // semicolons which are followed by all browsers so it is up to you 313 | // to decide whether you should or should not use semicolons in your 314 | // code. 315 | // 316 | // For more information about semicolons in JavaScript read An Open 317 | // Letter to JavaScript Leaders Regarding Semicolons by Isaac 318 | // Schlueter and JavaScript Semicolon Insertion. 319 | "asi": false, 320 | 321 | // This option suppresses warnings about the use of assignments in 322 | // cases where comparisons are expected. More often than not, code 323 | // like if (a = 10) {} is a typo. However, it can be useful in cases 324 | // like this one: 325 | // 326 | // for (var i = 0, person; person = people[i]; i++) {} 327 | "boss": false, 328 | 329 | // This option suppresses warnings about the debugger statements in 330 | // your code. 331 | "debug": true, 332 | 333 | // This option suppresses warnings about == null comparisons. Such 334 | // comparisons are often useful when you want to check if a variable 335 | // is null or undefined. 336 | "eqnull": false, 337 | 338 | // This option tells JSHint that your code uses ECMAScript 5 339 | // specific features such as getters and setters. Note that not all 340 | // browsers implement these features. 341 | // 342 | // More info: 343 | // ES5 compatibility table by Juriy Zaytsev 344 | // ECMAScript 5 support in Mozilla 345 | "es5": false, 346 | 347 | // This option tells JSHint that your code uses ES.next specific 348 | // features such as const. Note that these features are not 349 | // finalized yet and not all browsers implement them. 350 | // 351 | // More info: 352 | // Draft Specification for ES.next (ECMA-262 Ed. 6) 353 | "esnext": false, 354 | 355 | // This option suppresses warnings about the use of eval. The use of 356 | // eval is discouraged because it can make your code vulnerable to 357 | // various injection attacks and it makes it hard for JavaScript 358 | // interpreter to do certain optimizations. 359 | "evil": false, 360 | 361 | // This option suppresses warnings about declaring variables inside 362 | // of control structures while accessing them later from the 363 | // outside. Even though JavaScript has only two real scopes—global 364 | // and function—such practice leads to confusion among people new to 365 | // the language and hard-to-debug bugs. This is way, by default, 366 | // JSHint warns about variables that are used outside of their 367 | // intended scope. 368 | "expr": false, 369 | 370 | // This option suppresses warnings about the use of expressions 371 | // where normally you would expect to see assignments or function 372 | // calls. Most of the time, such code is a typo. However, it is not 373 | // forbidden by the spec and that's why this warning is optional. 374 | // 375 | // function test() { 376 | // if (true) { 377 | // var x = 0; 378 | // } 379 | // x += 1; // Default: 'x' used out of scope. 380 | // // No warning when funcscope:true 381 | // } 382 | "funcscope": false, 383 | 384 | // This option suppresses warnings about the use of global strict 385 | // mode. Global strict mode can break third-party widgets so it is 386 | // not recommended. 387 | // 388 | // For more info about strict mode see the strict option. 389 | "globalstrict": false, 390 | 391 | // This option suppresses warnings about the __iterator__ 392 | // property. This property is not supported by all browsers so use 393 | // it carefully. 394 | "iterator": false, 395 | 396 | // This option suppresses warnings about missing semicolons, but 397 | // only when the semicolon is omitted for the last statement in a 398 | // one-line block: 399 | // 400 | // var name = (function() { return 'Anton' }()); 401 | // 402 | // This is a very niche use case that is useful only when you use 403 | // automatic JavaScript code generators. 404 | "lastsemic": false, 405 | 406 | // This option suppresses most of the warnings about possibly unsafe 407 | // line breakings in your code. It doesn't suppress warnings about 408 | // comma-first coding style. To suppress those you have to use 409 | // laxcomma (see below). 410 | "laxbreak": false, 411 | 412 | // This option suppresses warnings about comma-first coding style: 413 | // 414 | // var obj = { 415 | // name: 'Anton' 416 | // , handle: 'valueof' 417 | // , role: 'SW Engineer' 418 | // }; 419 | "laxcomma": false, 420 | 421 | // This option suppresses warnings about functions inside of 422 | // loops. Defining functions inside of loops can lead to bugs such 423 | // as this one: 424 | // 425 | // var nums = []; 426 | // for (var i = 0; i < 10; i++) { 427 | // nums[i] = function (j) { 428 | // return i + j; 429 | // }; 430 | // } 431 | // nums[0](2); // Prints 12 instead of 2 432 | // 433 | // To fix the code above you need to copy the value of i: 434 | // 435 | // var nums = []; 436 | // for (var i = 0; i < 10; i++) { 437 | // (function (i) { 438 | // nums[i] = function (j) { 439 | // return i + j; 440 | // } 441 | // }(i)); 442 | // } 443 | "loopfunc": false, 444 | 445 | // This option suppresses warnings about multi-line 446 | // strings. Multi-line strings can be dangerous in JavaScript 447 | // because all hell breaks loose if you accidentally put a 448 | // whitespace in between the escape character (\) and a new line. 449 | // 450 | // Note that even though this option allows correct multi-line 451 | // strings, it still warns about multi-line strings without escape 452 | // characters or with anything in between the escape character and a 453 | // whitespace. 454 | // 455 | // /*jshint multistr:true */ 456 | // var text = "Hello\ 457 | // World"; // All good. 458 | // text = "Hello 459 | // World"; // Warning, no escape character. 460 | // text = "Hello\ 461 | // World"; // Warning, there is a space after \ (colored pink) 462 | "multistr": false, 463 | 464 | // This option suppresses warnings about switches with just one 465 | // case. Most of the time you want to use if instead of switch if 466 | // there is only one case. However, some code generators prefer to 467 | // generate switch statements. 468 | "onecase": false, 469 | 470 | // This option suppresses warnings about the __proto__ 471 | // property. This property is deprecated and not supported by all 472 | // browsers. 473 | "proto": false, 474 | 475 | // This option suppresses warnings about unescaped - in the end of 476 | // regular expressions. 477 | "regexdash": false, 478 | 479 | // This option suppresses warnings about the use of script-targeted 480 | // URLs—such as javascript:.... 481 | "scripturl": true, 482 | 483 | // This option suppresses warnings about mixed tabs and spaces when 484 | // the latter are used for alignment only. The technique is called 485 | // SmartTabs. 486 | "smarttabs": false, 487 | 488 | // This option suppresses warnings about variable shadowing 489 | // i.e. declaring a variable that had been already declared 490 | // somewhere in the outer scope. 491 | "shadow": false, 492 | 493 | // This option suppresses warnings about using [] notation when it 494 | // can be expressed in dot notation: person['name'] vs. person.name. 495 | "sub": true, 496 | 497 | // This option suppresses warnings about "weird" constructions like 498 | // new function () { ... } and new Object;. Such constructions are 499 | // sometimes used to produce singletons in JavaScript: 500 | // 501 | // var singleton = new function() { 502 | // var privateVar; 503 | // this.publicMethod = function () {} 504 | // this.publicMethod2 = function () {} 505 | // }; 506 | "supernew": false, 507 | 508 | // This option suppresses warnings about possible strict violations 509 | // when the code is running in strict mode and you use this in a 510 | // non-constructor function. You should use this option—in a 511 | // function scope only—when you are positive that your use of this 512 | // is valid in the strict mode (for example, if you call your 513 | // function using Function.call). 514 | // 515 | // Note: This option can be used only inside of a function 516 | // scope. JSHint will fail with an error if you will try to set this 517 | // option globally. 518 | "validthis": false, 519 | 520 | // ************************************************************ 521 | // Environments 522 | // ************ 523 | // These options pre-define global variables that are exposed by 524 | // popular JavaScript libraries and runtime environments—such as 525 | // browser or node.js. Essentially they are shortcuts for explicit 526 | // declarations like /*global $:false, jQuery:false */. 527 | // ************************************************************ 528 | 529 | // This option defines globals exposed by modern browsers: all the 530 | // way from good ol' document and navigator to the HTML5 FileReader 531 | // and other new developments in the browser world. 532 | // 533 | // Note: This option doesn't expose variables like alert or 534 | // console. See option devel for more information. 535 | "browser": false, 536 | 537 | // This option defines globals exposed by CouchDB. CouchDB is a 538 | // document-oriented database that can be queried and indexed in a 539 | // MapReduce fashion using JavaScript. 540 | "couch": false, 541 | 542 | // This option defines globals that are usually used for logging 543 | // poor-man's debugging: console, alert, etc. It is usually a good 544 | // idea to not ship them in production because, for example, 545 | // console.log breaks in legacy versions of Internet Explorer. 546 | "devel": false, 547 | 548 | // This option defines globals exposed by the Dojo Toolkit. 549 | "dojo": false, 550 | 551 | // This option defines globals exposed by the jQuery JavaScript 552 | // library. 553 | "jquery": false, 554 | 555 | // This option defines globals exposed by the MooTools JavaScript 556 | // framework. 557 | "mootools": false, 558 | 559 | // This option defines globals available when your code is running 560 | // inside of the Node runtime environment. Node.js is a server-side 561 | // JavaScript environment that uses an asynchronous event-driven 562 | // model. 563 | "node": true, 564 | 565 | // This option defines non-standard but widely adopted globals such 566 | // as escape and unescape. 567 | "nonstandard": false, 568 | 569 | // This option defines globals exposed by the Prototype JavaScript 570 | // framework. 571 | "prototypejs": false, 572 | 573 | // This option defines globals available when your code is running 574 | // inside of the Rhino runtime environment. Rhino is an open-source 575 | // implementation of JavaScript written entirely in Java. 576 | "rhino": false, 577 | 578 | // This option defines globals available when your code is running 579 | // inside of a Web Worker. Web Workers provide a simple means for 580 | // web content to run scripts in background threads. 581 | "worker": false, 582 | 583 | // This option defines globals available when your code is running 584 | // as a script for the Windows Script Host. 585 | "wsh": false, 586 | 587 | // This option defines globals exposed by the YUI JavaScript 588 | // framework. 589 | "yui": false, 590 | 591 | // ************************************************************ 592 | // Legacy 593 | // ****** 594 | // These options are legacy from JSLint. Aside from bug fixes they 595 | // will not be improved in any way and might be removed at any 596 | // point. 597 | // ************************************************************ 598 | 599 | // This option disallows the use of dangling _ in variables. We 600 | // don't know why would you need it. 601 | "nomen": false, 602 | 603 | // This option allows only one var statement per function. Some 604 | // people think that having a single var in a function, at the top 605 | // of the function, helps readability. Example (taken from 606 | // JSLint/JSHint source code): 607 | // 608 | // x.nud = function () { 609 | // var b, f, i, j, p, seen = {}, t; 610 | // b = token.line !== nexttoken.line; 611 | // if (b) { 612 | // indent += option.indent; 613 | // if (nexttoken.from === indent + option.indent) { 614 | // indent += option.indent; 615 | // } 616 | // } 617 | // // [...] 618 | // }; 619 | "onevar": false, 620 | 621 | // This option makes JSHint stop on the first error or warning. 622 | "passfail": false, 623 | 624 | // This option make JSHint check your source code against Douglas 625 | // Crockford's JavaScript coding style. Unfortunately, his "The Good 626 | // Parts" book aside, the actual rules are not very well documented. 627 | "white": false 628 | } -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = require('./config'); 4 | var jenkins = require('./jenkins'); 5 | var hwAddr = config.button.hwAddr; 6 | 7 | if (!hwAddr) { 8 | console.log('Specify the hardware address of your Dash Button with HW_ADDR env variable'); 9 | process.exit(0); 10 | } 11 | 12 | var dashButton = require('node-dash-button'); 13 | var dash; 14 | 15 | try { 16 | dash = dashButton(hwAddr); 17 | } catch (err) { 18 | console.log(err.message); 19 | process.exit(0); 20 | } 21 | 22 | dash.on('detected', function() { 23 | console.log('Button press detected'); 24 | console.log('Building ' + config.jenkins.job + '...'); 25 | jenkins.build(function(err) { 26 | if (err) { 27 | return console.error(err.message, err.stack); 28 | } 29 | console.log('Build complete'); 30 | }); 31 | }); 32 | 33 | console.log('\nListening for device button press...'); 34 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('dotenv').config({ 4 | silent: true 5 | }); 6 | 7 | var env = process.env; 8 | 9 | var config = { 10 | button: { 11 | hwAddr: env.HW_ADDR 12 | }, 13 | jenkins: { 14 | // See https://github.com/jansepar/node-jenkins-api#setup 15 | connectionString: env.JENKINS_CONNECTION_STRING, 16 | job: env.JENKINS_JOB 17 | } 18 | }; 19 | 20 | module.exports = config; 21 | -------------------------------------------------------------------------------- /src/jenkins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var jenkinsApi = require('jenkins-api'); 4 | var config = require('./config'); 5 | 6 | var jenkins = jenkinsApi.init(config.jenkins.connectionString); 7 | 8 | function build(callback) { 9 | jenkins.build(config.jenkins.job, function(err, res) { 10 | if (err) { 11 | return callback(err); 12 | } 13 | if (res.statusCode < 200 || res.statusCode >= 400) { 14 | return callback(new Error(res.statusMessage)); 15 | } 16 | callback(null, res.body); 17 | }); 18 | } 19 | 20 | module.exports.build = build; 21 | --------------------------------------------------------------------------------