diff --git a/.gitignore b/.gitignore index 99d3a6abfb..eea1dc3c33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,16 @@ +# binaries kolide -kolide-ose* +kolide-ose *.exe -vendor -app/bindata.go -.DS_Store -node_modules + +# output directories build +vendor +node_modules + +# generated artifacts +app/bindata.go +*.cover + +# operating system artifacts +.DS_Store \ No newline at end of file diff --git a/Makefile b/Makefile index 3e2b77dacd..23d60a2fbc 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,4 @@ -NODE_BIN = $(shell npm bin) -PID_FILE = build/kolide.pid -GO_FILES = $(filter-out ./bindata.go, $(shell find . -type f -name "*.go")) -TEMPLATES = $(wildcard frontend/templates/*) - -ifeq ($(OS), Windows_NT) -OUTFILE = kolide.exe -else -OUTFILE = kolide -endif +WEBPACK = $(shell npm bin)/webpack --config=tools/app/webpack.config.js .prefix: ifeq ($(OS), Windows_NT) @@ -16,38 +7,38 @@ else mkdir -p build endif -all: build - generate: .prefix go-bindata -pkg=app -o=app/bindata.go frontend/templates/ build/ - $(NODE_BIN)/webpack --progress --colors --bail - -.PHONY: build -build: generate .prefix - go build -o $(OUTFILE) + $(WEBPACK) --progress --colors --bail deps: npm install - go get -u github.com/olebedev/on - go get -u github.com/jteeuwen/go-bindata/... go get -u github.com/tools/godep + go get -u github.com/jteeuwen/go-bindata/... +ifneq ($(OS), Windows_NT) + go get -u github.com/olebedev/on +endif -clean: +distclean: mkdir -p build rm -rf build/* -test: - go vet . ./app ./config ./errors ./sessions - go test -v . ./app ./config ./errors ./sessions +ifneq ($(OS), Windows_NT) + +PID_FILE = build/kolide.pid +GO_FILES = $(filter-out ./bindata.go, $(shell find . -type f -name "*.go")) +TEMPLATES = $(wildcard frontend/templates/*) stop: kill `cat $(PID_FILE)` || true -serve: .prefix - BABEL_ENV=dev node hot.proxy & - $(NODE_BIN)/webpack --watch & +watch: .prefix + BABEL_ENV=dev node tools/app/hot.proxy & + $(WEBPACK) --watch & on -m 2 $(GO_FILES) $(TEMPLATES) | xargs -n1 -I{} make restart || make stop restart: stop @echo restarting the app... - $(TARGET) serve & echo $$! > $(PID_FILE) \ No newline at end of file + kolide serve & echo $$! > $(PID_FILE) + +endif \ No newline at end of file diff --git a/README.md b/README.md index bfad879ddd..797b3ffac8 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,96 @@ # Kolide [![CircleCI](https://circleci.com/gh/kolide/kolide-ose.svg?style=svg&circle-token=2573c239b7f18967040d2dec95ca5f71cfc90693)](https://circleci.com/gh/kolide/kolide-ose) -## Building +### Contents -To build the code ensure you have `node` and `npm` installed run the -following from the root of the repository: - -``` -make -``` - -This will produce a binary called `kolide` in the root of the repo. - -## Testing - -To run the application's tests, run the following from the root of the -repository: - -``` -go vet ./... && go test -v ./... -``` +- [Development Environment](#development-environment) + - [Installing dependencies](#installing-dependencies) + - [Building](#building) + - [Testing](#testing) + - [Viewing test coverage](#viewing-test-coverage) + - [Starting the local development environment](#starting-the-local-development-environment) + - [Setting up the database tables](#setting-up-the-database-tables) + - [Running Kolide](#running-kolide) + - [Automatic recompilation](#automatic-recompilation) + - [Stopping the local development environment](#stopping-the-local-development-environment) ## Development Environment -To setup a working local development environment run perform the following tasks: +### Installing dependencies -* Install the following dependencies: -* [Docker & docker-compose](https://www.docker.com/products/overview#/install_the_platform) -* [go 1.6.x](https://golang.org/dl/) -* [nodejs 0.6.x](https://nodejs.org/en/download/current/) (and npm) -* A GNU compatible version of `make` +To setup a working local development environment, you must install the following +minimum toolset: -To install build dependencies, run the following: +* [Docker](https://www.docker.com/products/overview#/install_the_platform) +* [Go](https://golang.org/dl/) (1.6 or greater) +* [Node.js](https://nodejs.org/en/download/current/) (and npm) +* [GNU Make](https://www.gnu.org/software/make/) + +Once you have those minimum requirements, to install build dependencies, run the following: ``` make deps ``` -Once those tools are installed, to set up a canonical development environment -via docker, run the following from the root of the repository: +### Building + +To generate all necessary code (bundling JavaScript into Go, etc), run the +following: + +``` +go generate +``` + +On UNIX (OS X, Linux, etc), run the following to compile the application: + +``` +go build -o kolide +``` + +On Windows, run the following to compile the application: + +``` +go build -o kolide.exe +``` + +### Testing + +To run the application's tests, run the following from the root of the +repository: + +``` +go test +``` + +From the root, `go test` will run a test launcher that executes `go test` and +`go vet` in the appropriate subpackages, etc. If you're working in a specific +subpackage, it's likely that you'll just want to iteratively run `go test` in +that subpackage directly until you are ready to run the full test suite. + +#### Viewing test coverage + +When you run `go test` from the root of the repository, test coverage reports +are generated in every subpackage. For example, the `sessions` subpackage will +have a coverage report generated in `./sessions/sessions.cover` + +To explore a test coverage report on a line-by-line basis in the browser, run +the following: + +```bash +# substitute ./errors/errors.cover, ./app/app.cover, etc +go tool cover -html=./sessions/sessions.cover +``` + +To view test a test coverage report in a terminal, run the following: + +```bash +# substitute ./errors/errors.cover, app/app.cover, etc +go tool cover -func=./sessions/sessions.cover +``` + +### Starting the local development environment + +To set up a canonical development environment via docker, +run the following from the root of the repository: ``` docker-compose up @@ -46,6 +99,8 @@ docker-compose up This requires that you have docker installed. At this point in time, automatic configuration tools are not included with this project. +### Setting up the database tables + Once you `docker-compose up` and are running the databases, you can build the code and run the following command to create the database tables: @@ -53,16 +108,37 @@ the code and run the following command to create the database tables: kolide prepare-db ``` -After you build the code, you will be prepared to run a Kolide development -environment. Run the following: +### Running Kolide + +Now you are prepared to run a Kolide development environment. Run the following: ``` -make serve +kolide serve ``` -You may have to edit the example configuration file to reflect `localhost` if -you're using Docker via a native docker engine or the output of -`docker-machine ip` if you're using Docker via `docker-toolbox`. +If you're running the binary from the root of the repository, where it is built +by default, then the binary will automatically use the provided example +configuration file, which assumes that you are running docker locally, on +`localhost` via a native engine. + +You may have to edit the example configuration file to use the output of +`docker-machine ip` instead of `localhost` if you're using Docker via +[Docker Toolbox](https://www.docker.com/products/docker-toolbox). + +### Automatic recompilation + +If you're editing mostly frontend JavaScript, you may want the Go binary to be +automatically recompiled with a new JavaScript bundle and restarted whenever +you save a JavaScript file. To do this, instead of running `kolide serve`, run +the following: + +``` +make watch +``` + +This is only supported on OS X and Linux. + +### Stopping the local development environment If you'd like to shut down the virtual infrastructure created by docker, run the following from the root of the repository: diff --git a/circle.yml b/circle.yml index 10d210efb5..197e5e4153 100644 --- a/circle.yml +++ b/circle.yml @@ -1,8 +1,8 @@ dependencies: pre: - make deps - - make generate + - go generate test: override: - - make test + - go test -v diff --git a/kolide.go b/kolide.go index f8e986becd..03682dd3f9 100644 --- a/kolide.go +++ b/kolide.go @@ -1,5 +1,7 @@ package main +//go:generate make generate + import ( "fmt" "math/rand" diff --git a/meta_test.go b/meta_test.go new file mode 100644 index 0000000000..081dea3ca9 --- /dev/null +++ b/meta_test.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + "os/exec" + "testing" +) + +// goSourceDirectories declares all Go subpackages of this package +var goSourceDirectories = []string{ + "app", + "config", + "errors", + "sessions", +} + +var goSourceDirectoriesCount int + +func init() { + goSourceDirectoriesCount = len(goSourceDirectories) +} + +// Run go vet on all Go subpackages in parallel +func TestGoVet(t *testing.T) { + t.Parallel() + done := make(chan bool, goSourceDirectoriesCount) + for _, dir := range goSourceDirectories { + go func(dir string) { + output, err := exec.Command( + "go", + "vet", + fmt.Sprintf("./%s", dir), + ).Output() + if err != nil { + t.Log(string(output)) + t.Error(err.Error()) + } + done <- true + }(dir) + } + for i := 1; i <= goSourceDirectoriesCount; i++ { + <-done + } +} + +// Run go test and generate test coverage reports on all Go subpackages in parallel +func TestGoTest(t *testing.T) { + t.Parallel() + done := make(chan bool, goSourceDirectoriesCount) + for _, dir := range goSourceDirectories { + go func(dir string) { + output, err := exec.Command( + "go", + "test", + fmt.Sprintf("-coverprofile=./%s/%s.cover", dir, dir), + "-v", + fmt.Sprintf("./%s", dir), + ).Output() + t.Log(string(output)) + if err != nil { + t.Error(err.Error()) + } + done <- true + }(dir) + } + for i := 1; i <= goSourceDirectoriesCount; i++ { + <-done + } +} diff --git a/hot.proxy.js b/tools/app/hot.proxy.js similarity index 100% rename from hot.proxy.js rename to tools/app/hot.proxy.js diff --git a/webpack.config.js b/tools/app/webpack.config.js similarity index 83% rename from webpack.config.js rename to tools/app/webpack.config.js index fa469665ce..a01530ea05 100644 --- a/webpack.config.js +++ b/tools/app/webpack.config.js @@ -34,12 +34,14 @@ if (process.env.NODE_ENV === 'production') { postCssLoader.splice(1, 1) // drop human readable names }; +var repo = path.join(__dirname, "../../") + var config = { entry: { - bundle: path.join(__dirname, 'frontend/index.js') + bundle: path.join(repo, 'frontend/index.js') }, output: { - path: path.join(__dirname, 'build'), + path: path.join(repo, 'build'), publicPath: "/assets/", filename: '[name].js' }, @@ -53,7 +55,7 @@ var config = { {test: /\.json$/, loader: 'json-loader'}, { test: /\.jsx?$/, - include: path.join(__dirname, 'frontend'), + include: path.join(repo, 'frontend'), loaders: ['babel'] } ] @@ -61,9 +63,9 @@ var config = { resolve: { extensions: ['', '.js', '.jsx', '.css'], alias: { - '#app': path.join(__dirname, 'frontend'), - '#c': path.join(__dirname, 'frontend/components'), - '#css': path.join(__dirname, 'frontend/css') + '#app': path.join(repo, 'frontend'), + '#c': path.join(repo, 'frontend/components'), + '#css': path.join(repo, 'frontend/css') } }, svgo1: { @@ -87,10 +89,10 @@ var config = { postcss: function() { return [autoprefixer, precss({ variables: { - variables: require('./frontend/css/vars') + variables: require(path.join(repo, 'frontend/css/vars')) } }), functions({ - functions: require('./frontend/css/funcs') + functions: require(path.join(repo, 'frontend/css/funcs')) })] } };