|
1 | 1 | ## The `./go` script: a unified development environment interface
|
2 | 2 |
|
| 3 | +Source: https://github.com/mbland/go-script-bash |
| 4 | + |
3 | 5 | [](https://travis-ci.org/mbland/go-script-bash)
|
4 | 6 | [](https://coveralls.io/github/mbland/go-script-bash?branch=master)
|
5 | 7 |
|
6 | 8 | A `./go` script aims to abstract away many of the steps needed to develop (and
|
7 |
| -sometimes deploy) a software project. It is a replacement for READMEs and |
8 |
| -other documents that may become out-of-date, and when maintained properly, |
9 |
| -should provide a cohesive and discoverable interface for common project tasks. |
10 |
| - |
11 |
| -This framework was inspired by: |
12 |
| - |
13 |
| -- "In Praise of the ./go Script: Parts I and II" by Pete Hodgson |
14 |
| - - https://www.thoughtworks.com/insights/blog/praise-go-script-part-i |
15 |
| - - https://www.thoughtworks.com/insights/blog/praise-go-script-part-ii |
16 |
| -- rbenv: https://github.com/rbenv/rbenv |
17 |
| - |
18 |
| -**Note:** Not to be confused with the [Go programming |
19 |
| -language](https://golang.org). This convention is completely unrelated, |
20 |
| -though it does bear a great deal of resemblance to the Go language's `go` |
21 |
| -command. |
| 9 | +sometimes deploy) a software project. It is a replacement for READMEs and other |
| 10 | +documents that may become out-of-date, and when maintained properly, should |
| 11 | +provide a cohesive and discoverable interface for common project tasks. |
22 | 12 |
|
23 | 13 | ### Table of contents
|
24 | 14 |
|
| 15 | +- [Introduction](#introduction) |
25 | 16 | - [Environment setup](#environment-setup)
|
26 | 17 | - [How to use this framework](#how-to-use-this-framework)
|
27 | 18 | - [Feedback and contributions](#feedback-and-contributions)
|
28 | 19 | - [Installing Bash](#installing-bash)
|
29 | 20 | - [Open Source](#open-source)
|
30 | 21 | - [Prior work](#prior-work)
|
31 | 22 |
|
| 23 | +### Introduction |
| 24 | +#### What's a `./go` script? |
| 25 | + |
| 26 | +The `./go` script idea came from Pete Hodgson's blog posts [In Praise of the |
| 27 | +./go Script: Part |
| 28 | +I](https://www.thoughtworks.com/insights/blog/praise-go-script-part-i) and [Part |
| 29 | +II](https://www.thoughtworks.com/insights/blog/praise-go-script-part-ii). To |
| 30 | +paraphrase Pete's original idea, rather than dump project setup, development, |
| 31 | +testing, and installation/deployment commands into a `README` that tends to get |
| 32 | +stale, or rely on oral tradition to transmit project maintenance knowledge, |
| 33 | +automate these tasks by encapsulating them all inside a single script in the |
| 34 | +root directory of your project source tree, conventionally named "`go`". Then |
| 35 | +the interface to these tasks becomes something like `./go setup`, `./go test`, |
| 36 | +and `./go deploy`. Not only would this script save time for people already |
| 37 | +familiar with the project, but it smooths the learning curve, prevents common |
| 38 | +mistakes, and lowers friction for new contributors. This is as desirable a state |
| 39 | +for Open Source projects as it is for internal ones. |
| 40 | + |
| 41 | +#### Is this related to the Go programming language? |
| 42 | + |
| 43 | +No. The `./go` script convention in general and this framework in particular are |
| 44 | +completely unrelated to the [Go programming language](https://golang.org). In |
| 45 | +fact, the actual `./go` script can be named anything. However, the [`go` command |
| 46 | +from the Go language distribution](https://golang.org/cmd/go/) encapsulates many |
| 47 | +common project functions in a similar fashion. |
| 48 | + |
| 49 | +#### Why write a framework? |
| 50 | + |
| 51 | +Of course, the danger is that this `./go` script may become as unwieldy as the |
| 52 | +`README` it's intended to replace, depending on the project's complexity. Even |
| 53 | +if it's heavily used and kept up-to-date, maintenance may become an intensive, |
| 54 | +frightening chore, especially if not covered by automated tests. Knowing what |
| 55 | +the script does, why it does it, and how to run it may become more and more |
| 56 | +challenging—resulting in the same friction, confusion, and fear the script was |
| 57 | +trying to avoid. |
| 58 | + |
| 59 | +The `./go` script framework makes it easy to provide a uniform and easy-to-use |
| 60 | +project maintenance interface that fits your project perfectly regardless of the |
| 61 | +mix of tools and languages, then it gets out of the way as fast as possible. The |
| 62 | +hope is that by [making the right thing the easy |
| 63 | +thing](https://mike-bland.com/2016/06/16/making-the-right-thing-the-easy-thing.html), |
| 64 | +scripts using the framework will evolve and stay healthy along with the rest of |
| 65 | +your project sources, which makes everyone working with the code less frustrated |
| 66 | +and more productive all-around. |
| 67 | + |
| 68 | +This framework accomplishes this by: |
| 69 | + |
| 70 | +* encouraging modular, composable `./go` commands implemented as individual |
| 71 | + scripts—in the language of your choice! |
| 72 | +* providing a set of builtin utility commands and shell command aliases—see |
| 73 | + `./go help builtins` and `./go help aliases` |
| 74 | +* supporting automatic tab-completion of commands and arguments through a |
| 75 | + lightweight API—see `./go help env` and `./go help complete` |
| 76 | +* implementing a quick, flexible, robust, and convenient documentation |
| 77 | + system—document your script in the header, and help shows up automatically as |
| 78 | +`./go help my-command`! See `./go help help`. |
| 79 | + |
| 80 | +Plus, its own tests serve as a model for testing command scripts of all shapes |
| 81 | +and sizes. |
| 82 | + |
| 83 | +The inspiration for this model (and initial implementation hints) came from [Sam |
| 84 | +Stephenson's `rbenv` Ruby version manager](https://github.com/rbenv/rbenv). |
| 85 | + |
| 86 | +#### Why Bash? |
| 87 | + |
| 88 | +[It's the ultimate backstage |
| 89 | +pass!](http://www.imdb.com/title/tt0118971/quotes?item=qt1467557) It's the |
| 90 | +default shell for most mainstream UNIX-based operating systems, easily installed |
| 91 | +on other UNIX-based operating systems, and is readily available even on Windows. |
| 92 | + |
| 93 | +#### Will this work on Windows? |
| 94 | + |
| 95 | +Yes. It is an explicit goal to make it as easy to use the framework on Windows |
| 96 | +as possible. Since [Git for Windows](https://git-scm.com/downloads) in |
| 97 | +particular ships with Bash as part of its environment, and Bash is available |
| 98 | +within Windows 10 as part of the [Windows Subsystem for |
| 99 | +Linux](https://msdn.microsoft.com/en-us/commandline/wsl/about) (Ubuntu on |
| 100 | +Windows), it's more likely than not that Bash is already available on a Windows |
| 101 | +developer's system. It's also available from the |
| 102 | +[MSYS2](https://msys2.github.io/) and [Cygwin](https://www.cygwin.com/) |
| 103 | +environments. |
| 104 | + |
| 105 | +#### Why not use tool X instead? |
| 106 | + |
| 107 | +Of course there are many common tools that may be used for managing project |
| 108 | +tasks. For example: [Make](https://www.gnu.org/software/make/manual/), |
| 109 | +[Rake](http://rake.rubyforge.org/), [npm](https://docs.npmjs.com/), |
| 110 | +[Gulp](http://gulpjs.com/), [Grunt](http://gruntjs.com/), |
| 111 | +[Bazel](https://www.bazel.io/), and the Go programming language's `go` tool. |
| 112 | +There are certainly more powerful scripting languages: |
| 113 | +[Perl](https://www.perl.org/), [Python](https://www.python.org/), |
| 114 | +[Ruby](https://www.ruby-lang.org/en/), and even [Node.js](https://nodejs.org/) |
| 115 | +is a possibility. There are even more powerful shells, such as the |
| 116 | +[Z-Shell](https://www.zsh.org/) and the [fish shell](https://fishshell.com/). |
| 117 | + |
| 118 | +The `./go` script framework isn't intended to replace all those other tools and |
| 119 | +languages, but to make it easier to use each of them for what they're good for. |
| 120 | +It makes it easier to write good, testable, maintainable, and extensible shell |
| 121 | +scripts so you don't have to push any of those other tools beyond their natural |
| 122 | +limits. |
| 123 | + |
| 124 | +Bash scripting is _really good_ for automating a lot of traditional command line |
| 125 | +tasks, and it can be pretty awkward to achieve the same effect using other |
| 126 | +tools—especially if your project uses a mix of languages, where using a tool |
| 127 | +common to one language environment to automate tasks in another can get weird. |
| 128 | +(Which is part of the reason why there are so many build tools tailored to |
| 129 | +different languages in the first place, to say nothing of the different |
| 130 | +languages themselves.) |
| 131 | + |
| 132 | +If you want to incorporate different scripting languages or shells into your |
| 133 | +project maintenance, this framework makes it easy to do so. However, by starting |
| 134 | +with Bash, you can implement a `./go init` command to check that these other |
| 135 | +languages or shells are installed and either install them automatically or |
| 136 | +prompt the user on how to do so. Since Bash is (almost certainly) already |
| 137 | +present, users can run your `./go` script right away and get the setup or hints |
| 138 | +that they need, rather than wading through system requirements and documentation |
| 139 | +before being able to do anything. |
| 140 | + |
| 141 | +Even if `./go init` tells the user "go to this website and install this other |
| 142 | +thing", that's still an immediate, tactile experience that triggers a reward |
| 143 | +response and invites further exploration. (Think of |
| 144 | +[Zork](https://en.wikipedia.org/wiki/Zork) and the first ["open |
| 145 | +mailbox"](http://steel.lcc.gatech.edu/~marleigh/zork/transcript.html) |
| 146 | +command.) |
| 147 | + |
| 148 | +#### Where can I run it? |
| 149 | + |
| 150 | +The real question is: Where _can't_ you run it? |
| 151 | + |
| 152 | +The core framework is written 100% in |
| 153 | +[Bash](https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29) and it's been tested |
| 154 | +under Bash 3.2, 4.2, 4.3, and 4.4 across OS X, Ubuntu Linux, Arch Linux, Alpine |
| 155 | +Linux, FreeBSD 9.3, FreeBSD 10.3, and Windows 10 (using all the environments |
| 156 | +described in the "Will this work on Windows?" section above). |
| 157 | + |
| 158 | +#### How is it tested? |
| 159 | + |
| 160 | +The project's own `./go test` command does it all. Combined with automatic |
| 161 | +tab-completion enabled by `./go env` and pattern-matching via `./go glob`, the |
| 162 | +`./go test` command provides a convenient means of selecting subsets of test |
| 163 | +cases while focusing on a particular piece of behavior. (See `./go help test`.) |
| 164 | + |
| 165 | +The tests are written using [Sam Stephenson's Bash Automated Testing System |
| 166 | +(BATS)](https://github.com/sstephenson/bats). Code coverage comes from [Simon |
| 167 | +Kagstrom's `kcov` code coverage tool](https://github.com/SimonKagstrom/kcov), |
| 168 | +which not only provides code coverage for Bash scripts (!!!) but can push the |
| 169 | +results to Coveralls! |
| 170 | + |
32 | 171 | ### Environment setup
|
33 | 172 |
|
34 | 173 | To run a `./go` script that uses this module, or to add it to your own project,
|
|
0 commit comments