Use Vagrant for easy development setup (#297)

* Use vagrant

* Stop using polling

* Fix test

* Document

* Fix
This commit is contained in:
Sung Won Cho 2019-11-03 20:04:17 -08:00 committed by GitHub
commit 4a3fd2d1a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 273 additions and 128 deletions

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
/vendor
/build
/.vagrant
*.log

View file

@ -1,26 +1,49 @@
# Contributing to Dnote
This repository contains the server side and the client side code for Dnote.
Dnote is an open source project.
* [Setting up](#setting-up)
* [Command Linux Interface](#command-line-interface)
* [Server](#server)
* [Command Linux Interface](#command-line-interface)
## Setting up
1. Install the following prerequisites if necessary:
Dnote uses [Vagrant](https://github.com/hashicorp/vagrant) to provision a consistent development environment.
* [Go programming language](https://golang.org/dl/) 1.13+
* [Node.js](https://nodejs.org/) 10.16+
* Postgres 10.9+
*Prerequisites*
2. Get the Dnote code:
* Vagrant ([Download](https://www.vagrantup.com/downloads.html))
* VirtualBox ([Download](https://www.virtualbox.org/))
```sh
go get github.com/dnote/dnote
Following steps will set up your development environment and install dependencies in a virtual machine.
1. Run `vagrant up` to start a virtual machine and bootstrap the development environment.
2. Run `vagrant rsync-auto` to sync the files with the virtual machine.
*Workflow*
* You can make changes to the source code from the host machine.
* Any commands need to be run inside the virtual machine. You can connect to it by running `vagrant ssh`.
## Server
The server consists of the frontend web application and a web server.
### Development
* Run `make dev-server` to start a local server.
* You can access the server on `localhost:3000` on your machine.
### Test
```bash
# Run tests for the frontend web application
make test-web
# Run tests for API
make test-api
```
3. Run `make` to install dependencies
## Command Line Interface
@ -69,24 +92,3 @@ DNOTE_DEBUG=1 dnote sync
- disable the homebrew release by commenting out relevant code in the release script.
- mark release as pre-release on GitHub release
## Server
The server consists of the frontend web application and a web server.
### Development
* Create a postgres database by running `createdb -O postgres dnote`
* If the role does not exist, you can create it by running `sudo -u postgres createuser postgres`
* Run `make dev-server` to start a local server
### Test
```bash
# Run tests for the frontend web application
make test-web
# Run tests for API
make test-api
```

9
Gopkg.lock generated
View file

@ -244,6 +244,14 @@
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]]
digest = "1:a278d57d6315d6f405dbaebdece8eb0a17e243e5f96456b00bfc0dbfb3fe3286"
name = "github.com/radovskyb/watcher"
packages = ["."]
pruneopts = "UT"
revision = "f5989f8deca223d590d5a130c77ea375fe9fde30"
version = "v1.0.7"
[[projects]]
digest = "1:ed615c5430ecabbb0fb7629a182da65ecee6523900ac1ac932520860878ffcad"
name = "github.com/robfig/cron"
@ -424,6 +432,7 @@
"github.com/lib/pq",
"github.com/mattn/go-sqlite3",
"github.com/pkg/errors",
"github.com/radovskyb/watcher",
"github.com/robfig/cron",
"github.com/rubenv/sql-migrate",
"github.com/sergi/go-diff/diffmatchpatch",

View file

@ -108,3 +108,7 @@
[[constraint]]
name = "github.com/gobuffalo/packr"
version = "2.5.2"
[[constraint]]
name = "github.com/radovskyb/watcher"
version = "1.0.7"

View file

@ -29,7 +29,7 @@ ifndef COMPILEDAEMON
endif
@echo "==> installing go dependencies"
@dep ensure
@dep ensure -v
.PHONY: install-go
install-js:

20
Vagrantfile vendored Normal file
View file

@ -0,0 +1,20 @@
# -*- mode: ruby -*-
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.synced_folder '.', '/go/src/github.com/dnote/dnote', type: "rsync", create: true, rsync__args: ["--verbose", "--archive", "--delete", "-z"]
config.vm.network "forwarded_port", guest: 3000, host: 3000
config.vm.network "forwarded_port", guest: 8080, host: 8080
config.vm.network "forwarded_port", guest: 5432, host: 5433
config.vm.provision 'shell', path: './scripts/vagrant/install_utils.sh'
config.vm.provision 'shell', path: './scripts/vagrant/install_go.sh', privileged: false
config.vm.provision 'shell', path: './scripts/vagrant/install_node.sh', privileged: false
config.vm.provision 'shell', path: './scripts/vagrant/install_postgres.sh', privileged: false
config.vm.provision 'shell', path: './scripts/vagrant/bootstrap.sh', privileged: false
config.vm.provider "virtualbox" do |v|
v.memory = 4000
v.cpus = 2
end
end

View file

@ -1,6 +1,6 @@
{
"name": "dnote-extension",
"version": "1.1.1",
"version": "2.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1923,13 +1923,13 @@
}
},
"concurrently": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-4.1.2.tgz",
"integrity": "sha512-Kim9SFrNr2jd8/0yNYqDTFALzUX1tvimmwFWxmp/D4mRI+kbqIIwE2RkBDrxS2ic25O1UgQMI5AtBqdtX3ynYg==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.0.0.tgz",
"integrity": "sha512-1yDvK8mduTIdxIxV9C60KoiOySUl/lfekpdbI+U5GXaPrgdffEavFa9QZB3vh68oWOpbCC+TuvxXV9YRPMvUrA==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"date-fns": "^1.30.1",
"date-fns": "^2.0.1",
"lodash": "^4.17.15",
"read-pkg": "^4.0.1",
"rxjs": "^6.5.2",
@ -1945,43 +1945,12 @@
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
@ -2026,6 +1995,12 @@
"pump": "^3.0.0"
}
},
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
},
"invert-kv": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
@ -2105,14 +2080,6 @@
"dev": true,
"requires": {
"has-flag": "^2.0.0"
},
"dependencies": {
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
}
}
},
"which-module": {
@ -2458,9 +2425,9 @@
"dev": true
},
"date-fns": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
"integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.6.0.tgz",
"integrity": "sha512-F55YxqRdEfP/eYQmQjLN798v0AwLjmZ8nMBjdQvNwEE3N/zWVrlkkqT+9seBlPlsbkybG4JmWg3Ee3dIV9BcGQ==",
"dev": true
},
"debug": {
@ -3998,14 +3965,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4020,20 +3985,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -4150,8 +4112,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -4163,7 +4124,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -4178,7 +4138,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -4290,8 +4249,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -4303,7 +4261,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4425,7 +4382,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",

View file

@ -89,7 +89,7 @@ func NotEqual(t *testing.T, a, b interface{}, message string) {
// DeepEqual fails a test if the actual does not deeply equal the expected
func DeepEqual(t *testing.T, a, b interface{}, message string) {
if reflect.DeepEqual(a, b) {
if cmp.Equal(a, b) {
return
}

View file

@ -24,7 +24,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
"github.com/dnote/dnote/pkg/assert"
@ -321,9 +320,7 @@ func TestMigrateToV6(t *testing.T) {
t.Fatal(errors.Wrap(err, "Failed to unmarshal the result into Dnote").Error())
}
if ok := reflect.DeepEqual(expected, got); !ok {
t.Errorf("Payload does not match.\nActual: %+v\nExpected: %+v", got, expected)
}
assert.DeepEqual(t, expected, got, "payload mismatch")
}
func TestMigrateToV7(t *testing.T) {

View file

@ -22,7 +22,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
"time"
@ -176,9 +175,7 @@ func TestGetNotes(t *testing.T) {
Total: 2,
}
if ok := reflect.DeepEqual(payload, expected); !ok {
t.Errorf("Payload does not match.\nActual: %+v\nExpected: %+v", payload, expected)
}
assert.DeepEqual(t,payload, expected, "payload mismatch")
}
func TestGetNote(t *testing.T) {
@ -256,9 +253,7 @@ func TestGetNote(t *testing.T) {
},
}
if ok := reflect.DeepEqual(payload, expected); !ok {
t.Errorf("Payload does not match.\nActual: %+v\nExpected: %+v", payload, expected)
}
assert.DeepEqual(t,payload, expected, "payload mismatch")
}
// TODO: finish the test after implementing note sharing

View file

@ -22,7 +22,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
"github.com/dnote/dnote/pkg/assert"
@ -407,9 +406,7 @@ func TestCreateBook(t *testing.T) {
},
}
if ok := reflect.DeepEqual(got, expected); !ok {
t.Errorf("Payload does not match.\nActual: %+v\nExpected: %+v", got, expected)
}
assert.DeepEqual(t, got, expected, "payload mismatch")
}
func TestCreateBookDuplicate(t *testing.T) {

View file

@ -138,7 +138,7 @@ func startCmd() {
log.Printf("Dnote version %s is running on port %s", versionTag, *port)
addr := fmt.Sprintf(":%s", *port)
http.ListenAndServe(addr, srv)
log.Fatalln(http.ListenAndServe(addr, srv))
}
func versionCmd() {

View file

@ -0,0 +1,78 @@
package main
import (
"log"
"os"
"os/exec"
"syscall"
"time"
"github.com/radovskyb/watcher"
)
func command(binary string, args []string, entryPoint string) *exec.Cmd {
cmd := exec.Command(binary, args...)
// Notice this change.
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Dir = entryPoint
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
// Using Start and not Run.
err := cmd.Start()
if err != nil {
log.Printf("Command finished with error: %v", err)
}
return cmd
}
func execCmd() *exec.Cmd {
return command("go", []string{"run", "main.go", "start", "-port", "3000"}, "..")
}
func main() {
w := watcher.New()
w.IgnoreHiddenFiles(true)
w.SetMaxEvents(1)
var e *exec.Cmd
go func() {
for {
select {
case <-w.Event:
log.Println("Change detected. Restarting server...")
// Killing the process here.
if e != nil {
pgid, err := syscall.Getpgid(e.Process.Pid)
if err == nil {
syscall.Kill(-pgid, syscall.SIGKILL)
}
e.Wait()
}
// Starting it again here or starting for the first time.
e = execCmd()
case err := <-w.Error:
log.Fatalln(err)
case <-w.Closed:
return
}
}
}()
if err := w.AddRecursive(".."); err != nil {
log.Fatalln(err)
}
e = execCmd()
log.Printf("watching %d files", len(w.WatchedFiles()))
if err := w.Start(time.Millisecond * 500); err != nil {
log.Fatalln(err)
}
}

View file

@ -49,5 +49,5 @@ set -x
hub release create \
"${file_flags[@]}" \
"${flags[@]}" \
--message="$version_tag"\
--message="Please see the [CHANGELOG](https://github.com/dnote/dnote/blob/master/CHANGELOG.md)"\
"$version_tag"

17
scripts/vagrant/bootstrap.sh Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -ex
echo "export DNOTE=/go/src/github.com/dnote/dnote" >> /home/vagrant/.bash_profile
echo "cd /go/src/github.com/dnote/dnote" >> /home/vagrant/.bash_profile
# install dependencies
(cd /go/src/github.com/dnote/dnote && make install)
# set up database
sudo -u postgres createdb dnote
sudo -u postgres createdb dnote_test
# allow connection from host and allow to connect without password
sudo sed -i "/port*/a listen_addresses = '*'" /etc/postgresql/11/main/postgresql.conf
sudo sed -i 's/host.*all.*.all.*md5/# &/' /etc/postgresql/11/main/pg_hba.conf
sudo sed -i "$ a host all all all trust" /etc/postgresql/11/main/pg_hba.conf
sudo service postgresql restart

26
scripts/vagrant/install_go.sh Executable file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091
set -eux
VERSION=1.13.4
OS=linux
ARCH=amd64
tarball=go$VERSION.$OS-$ARCH.tar.gz
wget -q https://dl.google.com/go/"$tarball"
sudo tar -C /usr/local -xzf "$tarball"
sudo tar -xf "$tarball"
sudo mkdir -p /go/src
sudo mkdir -p /go/bin
sudo mkdir -p /go/pkg
sudo chown -R vagrant:vagrant /go
GOPATH=/go
echo "export GOPATH=$GOPATH" >> /home/vagrant/.bash_profile
echo "export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin" >> /home/vagrant/.bash_profile
source /home/vagrant/.bash_profile
go version
go env

19
scripts/vagrant/install_node.sh Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC1091
set -eux
VERSION=10.15.0
NVM_VERSION=v0.35.0
# Install nvm
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/"$NVM_VERSION"/install.sh | bash
cat >> /home/vagrant/.bash_profile<< EOF
export NVM_DIR="\$([ -z "\${XDG_CONFIG_HOME-}" ] && printf %s "\${HOME}/.nvm" || printf %s "\${XDG_CONFIG_HOME}/nvm")"
[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh" # This loads nvm
EOF
source /home/vagrant/.bash_profile
# Install a node and alias
nvm install --no-progress "$VERSION" 1>/dev/null
nvm alias default "$VERSION"
nvm use default

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -ex
sudo apt-get install wget ca-certificates
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
sudo apt-get update
sudo apt-get install -y postgresql-11

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -eux
sudo apt-get update
sudo apt-get install -y htop git wget build-essential
# Install Chrome
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add
echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt-get -y update
sudo apt-get install -y google-chrome-stable

28
web/package-lock.json generated
View file

@ -12041,13 +12041,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -12064,8 +12062,7 @@
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
@ -12172,8 +12169,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@ -12195,7 +12191,6 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -13092,7 +13087,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -13301,7 +13297,8 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
@ -13326,6 +13323,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -13505,7 +13503,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -13561,6 +13560,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -13604,12 +13604,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},

View file

@ -21,6 +21,7 @@ appPath="$basePath"/web
ROOT_URL=$ROOT_URL \
VERSION="$VERSION" \
"$appPath"/node_modules/.bin/webpack-dev-server\
--env.isTest="$IS_TEST"\
--env.isTest="$IS_TEST" \
--host 0.0.0.0 \
--config "$appPath"/webpack/dev.config.js
)