├── .gitignore ├── LICENSE ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Soheil Rashidi 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # buno 2 | Buno lets you run custom scripts before and after executing a command. 3 | 4 | This is particularly useful for displaying notifications when your build starts, succeeds or fails. 5 | These scripts can be .gitignored so that each developer in the team gets to setup his/her notifications the way he/she likes. 6 | 7 | ## Install 8 | 9 | ``` 10 | npm install buno 11 | ``` 12 | 13 | ## Usage 14 | 15 | 1. Create a `.buno` directory: 16 | 17 | ``` 18 | mkdir .buno 19 | cd .buno 20 | ``` 21 | 22 | 2. Create your pre/post/error scripts: 23 | 24 | ``` 25 | echo 'echo Building...' > pre && chmod u+x pre 26 | echo 'echo Build finished.' > post && chmod u+x post 27 | echo 'echo Build error!' > error && chmod u+x error 28 | ``` 29 | 30 | 3. Prefix your command with buno: 31 | 32 | ``` 33 | buno [args] 34 | ``` 35 | 36 | ## How it Works 37 | 38 | 1. buno executes the pre script before running the command if it finds one at `.buno/pre`. 39 | 2. buno executes the command. 40 | 3. If the command exits with a status code of zero, it executes the post script if it finds one at `.buno/post`. 41 | 4. If the command exits with a status code of non-zero, it executes the error script if it finds one at `.buno/error`. 42 | 5. Command's status code is returned as buno's status code. 43 | 44 | Note: You can also put your scripts globally in the `~/.buno` directory. 45 | 46 | ## Sample 47 | 48 | The following sample uses 49 | macOS's built-in [say](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/say.1.html) command, 50 | [AnyBar](https://github.com/tonsky/AnyBar) and 51 | [node-notifier](https://github.com/mikaelbr/node-notifier) 52 | to demonstrate how to use buno: 53 | 54 | ``` 55 | # .buno/pre 56 | 57 | say 'building' 58 | echo -n 'orange' | nc -4u -w0 localhost 1738 59 | notify -t 'My Awesome App' -m 'Building' 60 | ``` 61 | 62 | ``` 63 | # .buno/post 64 | 65 | say 'done' 66 | echo -n 'green' | nc -4u -w0 localhost 1738 67 | notify -t 'My Awesome App' -m 'Build finished.' 68 | ``` 69 | 70 | ``` 71 | # .buno/error 72 | 73 | say 'you suck at coding. ha ha!' 74 | echo -n 'red' | nc -4u -w0 localhost 1738 75 | notify -t 'My Awesome App' -m 'Build error!' 76 | ``` 77 | 78 | ``` 79 | buno webpack ./entry.js bundle.js 80 | ``` 81 | 82 | ## Version History 83 | + **1.0** 84 | + Initial release. 85 | 86 | ## Author 87 | **Soheil Rashidi** 88 | 89 | + http://soheilrashidi.com 90 | + http://twitter.com/soheilpro 91 | + http://github.com/soheilpro 92 | 93 | ## Copyright and License 94 | Copyright 2016 Soheil Rashidi 95 | 96 | Licensed under the The MIT License (the "License"); 97 | you may not use this work except in compliance with the License. 98 | You may obtain a copy of the License in the LICENSE file, or at: 99 | 100 | http://www.opensource.org/licenses/mit-license.php 101 | 102 | Unless required by applicable law or agreed to in writing, software 103 | distributed under the License is distributed on an "AS IS" BASIS, 104 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 105 | See the License for the specific language governing permissions and 106 | limitations under the License. 107 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var spawnSync = require('child_process').spawnSync; 6 | var argv = require('yargs') 7 | .boolean('v') 8 | .alias('h', 'help') 9 | .alias('v', 'verbose') 10 | .describe('v', 'Verbose mode') 11 | .help('h') 12 | .example('$0 webpack', 'run webpack') 13 | .example('$0 webpack ./entry.js bundle.js', 'run webpack with args') 14 | .example('$0 -v -- webpack', 'run webpack, in verbose mode') 15 | .argv; 16 | 17 | function fileExists(path) { 18 | try { 19 | return fs.statSync(path).isFile; 20 | } 21 | catch(error) { 22 | return false; 23 | } 24 | } 25 | 26 | function findFile(name) { 27 | var searchPaths = [ 28 | process.cwd(), 29 | process.env.HOME, 30 | ]; 31 | 32 | for (searchPath of searchPaths) { 33 | var filePath = path.join(searchPath, `.buno/${name}`); 34 | 35 | if (fileExists(filePath)) 36 | return filePath; 37 | } 38 | } 39 | 40 | function exec(command) { 41 | return spawnSync(command, { shell: true, stdio: 'inherit' }); 42 | } 43 | 44 | // Pre 45 | var preCommand = findFile('pre'); 46 | 47 | if (preCommand) { 48 | if (argv.verbose) 49 | console.log(`Running pre command: ${preCommand}`) 50 | 51 | var preProcess = exec(preCommand); 52 | 53 | if (preProcess.status !== 0) 54 | return; 55 | } 56 | 57 | // Main 58 | var mainCommand = argv._.join(' '); 59 | 60 | if (argv.verbose) 61 | console.log(`Running command: ${mainCommand}`) 62 | 63 | var mainProcess = exec(mainCommand); 64 | 65 | // Error 66 | var errorCommand = findFile('error'); 67 | 68 | if (mainProcess.status !== 0) { 69 | if (errorCommand) { 70 | if (argv.verbose) 71 | console.log(`Running error command: ${command}`) 72 | 73 | exec(errorCommand); 74 | } 75 | 76 | process.exit(mainProcess.status); 77 | } 78 | 79 | // Post 80 | var postCommand = findFile('post'); 81 | 82 | if (postCommand) { 83 | if (argv.verbose) 84 | console.log(`Running post command: ${postCommand}`) 85 | 86 | exec(postCommand); 87 | } 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "buno", 3 | "version": "1.0.0", 4 | "description": "Run custom scripts before and after executing a command.", 5 | "main": "index.js", 6 | "bin": { 7 | "buno": "./index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/soheilpro/buno.git" 15 | }, 16 | "keywords": [ 17 | "build", 18 | "notification", 19 | "hook" 20 | ], 21 | "author": "Soheil Rashidi", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/soheilpro/buno/issues" 25 | }, 26 | "homepage": "https://github.com/soheilpro/buno#readme", 27 | "dependencies": { 28 | "yargs": "^5.0.0" 29 | } 30 | } 31 | --------------------------------------------------------------------------------