Merge: Win travis build

* commit '6503bab1aaa27ff43175d069413630a420093be0':
  *: added cross-env to npm scripts
  run npm build on windows
  *: added more logging
  -: fix autohosts tests on Windows
  -: fix qlog test on Windows
  *: fix nvs script
  *: travis - use nvs on Windows
  *: travis-win -- try nvm
  *(global): travis: choco install nodejs
  +(global): windows travis build
This commit is contained in:
Andrey Meshkov 2020-04-15 16:13:24 +03:00
commit 215e3eeaf6
11 changed files with 217 additions and 67 deletions

View file

@ -7,14 +7,41 @@ go:
os:
- linux
- osx
- windows
before_install:
- nvm install node
- npm install -g npm
- curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.23.8
- |-
case $TRAVIS_OS_NAME in
linux | osx)
nvm install node
npm install -g npm
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(go env GOPATH)/bin v1.23.8
;;
windows)
# Using NVS for managing Node.js versions on Windows
NVS_HOME="C:\ProgramData\nvs"
git clone --single-branch https://github.com/jasongin/nvs $NVS_HOME
source $NVS_HOME/nvs.sh
nvs add latest
nvs use latest
;;
esac
install:
- npm --prefix client ci
- |-
case $TRAVIS_OS_NAME in
linux | osx)
node --version
npm --version
npm --prefix client ci
;;
windows)
node --version
npm --version
nvs --version
npm --prefix client ci
;;
esac
cache:
directories:
@ -23,10 +50,24 @@ cache:
- $HOME/Library/Caches/go-build
script:
- /bin/bash ci.sh
- |-
case $TRAVIS_OS_NAME in
linux | osx)
/bin/bash ci.sh
;;
windows)
npm --prefix client run build-prod
go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
;;
esac
after_success:
- bash <(curl -s https://codecov.io/bash)
- |-
case $TRAVIS_OS_NAME in
linux)
bash <(curl -s https://codecov.io/bash)
;;
esac
notifications:
slack: performix:yXTihlSzsLFSZiqbXMNzvTSX
@ -60,6 +101,8 @@ matrix:
file_glob: true
skip_cleanup: true
# Docker build configuration
- if: repo = AdguardTeam/AdGuardHome
- name: docker
if: type != pull_request AND (branch = master OR tag IS present) AND repo = AdguardTeam/AdGuardHome
go:

52
client/package-lock.json generated vendored
View file

@ -3522,6 +3522,58 @@
"gud": "^1.0.0"
}
},
"cross-env": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz",
"integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.1"
},
"dependencies": {
"cross-spawn": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz",
"integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",

11
client/package.json vendored
View file

@ -3,9 +3,9 @@
"version": "0.1.0",
"private": true,
"scripts": {
"build-dev": "NODE_ENV=development ./node_modules/.bin/webpack --config webpack.dev.js",
"watch": "NODE_ENV=development ./node_modules/.bin/webpack --config webpack.dev.js --watch",
"build-prod": "NODE_ENV=production ./node_modules/.bin/webpack --config webpack.prod.js",
"build-dev": "cross-env NODE_ENV=development webpack --config webpack.dev.js",
"watch": "cross-env NODE_ENV=development webpack --config webpack.dev.js --watch",
"build-prod": "cross-env NODE_ENV=production webpack --config webpack.prod.js",
"lint": "eslint client/"
},
"dependencies": {
@ -49,6 +49,7 @@
"clean-webpack-plugin": "^0.1.19",
"compression-webpack-plugin": "^1.1.11",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^7.0.2",
"css-loader": "^2.1.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
@ -70,11 +71,11 @@
"style-loader": "^0.21.0",
"stylelint": "^9.10.1",
"stylelint-webpack-plugin": "0.10.4",
"svg-url-loader": "^2.3.2",
"uglifyjs-webpack-plugin": "^1.2.7",
"url-loader": "^1.0.1",
"webpack": "3.8.1",
"webpack-dev-server": "^3.1.14",
"webpack-merge": "^4.1.3",
"svg-url-loader": "^2.3.2"
"webpack-merge": "^4.1.3"
}
}

View file

@ -71,6 +71,8 @@ type User struct {
// InitAuth - create a global object
func InitAuth(dbFilename string, users []User, sessionTTL uint32) *Auth {
log.Info("Initializing auth module: %s", dbFilename)
a := Auth{}
a.sessionTTL = sessionTTL
a.sessions = make(map[string]*session)
@ -83,7 +85,7 @@ func InitAuth(dbFilename string, users []User, sessionTTL uint32) *Auth {
}
a.loadSessions()
a.users = users
log.Debug("Auth: initialized. users:%d sessions:%d", len(a.users), len(a.sessions))
log.Info("Auth: initialized. users:%d sessions:%d", len(a.users), len(a.sessions))
return &a
}

View file

@ -43,10 +43,10 @@ const (
// Update-related variables
var (
versionString string
updateChannel string
versionCheckURL string
ARMVersion string
versionString = "dev"
updateChannel = "none"
versionCheckURL = ""
ARMVersion = ""
)
const versionCheckPeriod = time.Hour * 8
@ -155,11 +155,11 @@ func run(args options) {
configureLogger(args)
// print the first message after logger is configured
msg := "AdGuard Home, version %s, channel %s\n, arch %s %s"
msg := "AdGuard Home, version %s, channel %s, arch %s %s"
if ARMVersion != "" {
msg = msg + " v" + ARMVersion
}
log.Printf(msg, versionString, updateChannel, runtime.GOOS, runtime.GOARCH, ARMVersion)
log.Printf(msg, versionString, updateChannel, runtime.GOOS, runtime.GOARCH)
log.Debug("Current working directory is %s", Context.workDir)
if args.runningAsService {
log.Info("AdGuard Home is running as a service")
@ -169,6 +169,7 @@ func run(args options) {
Context.firstRun = detectFirstRun()
if Context.firstRun {
log.Info("This is the first time AdGuard Home is launched")
requireAdminRights()
}
@ -197,6 +198,7 @@ func run(args options) {
err = parseConfig()
if err != nil {
log.Error("Failed to parse configuration, exiting")
os.Exit(1)
}
@ -211,6 +213,7 @@ func run(args options) {
config.DHCP.ConfigModified = onConfigModified
Context.dhcpServer = dhcpd.Create(config.DHCP)
if Context.dhcpServer == nil {
log.Error("Failed to initialize DHCP server, exiting")
os.Exit(1)
}
Context.autoHosts.Init("")

View file

@ -107,14 +107,14 @@ schema_version: 5
// . Wait until the filters are downloaded
// . Stop and cleanup
func TestHome(t *testing.T) {
// Reinit context
// Init new context
Context = homeContext{}
dir := prepareTestDir()
defer func() { _ = os.RemoveAll(dir) }()
_ = os.MkdirAll(filepath.Join(Context.getDataDir(), filterDir), 0755)
fn := filepath.Join(dir, "AdGuardHome.yaml")
// Prepare the test config
assert.True(t, ioutil.WriteFile(fn, []byte(yamlConf), 0644) == nil)
fn, _ = filepath.Abs(fn)
@ -135,11 +135,11 @@ func TestHome(t *testing.T) {
time.Sleep(100 * time.Millisecond)
}
assert.Truef(t, err == nil, "%s", err)
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, http.StatusOK, resp.StatusCode)
resp, err = h.Get("http://127.0.0.1:3000/control/status")
assert.Truef(t, err == nil, "%s", err)
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// test DNS over UDP
r := upstream.NewResolver("127.0.0.1:5354", 3*time.Second)

View file

@ -42,6 +42,8 @@ type Web struct {
// CreateWeb - create module
func CreateWeb(conf *WebConfig) *Web {
log.Info("Initialize web module")
w := Web{}
w.conf = conf

View file

@ -206,7 +206,9 @@ func (l *queryLog) getData(params getDataParams) map[string]interface{} {
fileEntries, oldest, total := l.searchFiles(params)
if params.OlderThan.IsZero() {
params.OlderThan = now
// In case if the timer is not precise (for instance, on Windows)
// We really want to get all records including those added just before the call
params.OlderThan = now.Add(time.Millisecond)
}
// add from memory buffer

View file

@ -23,7 +23,7 @@ type AutoHosts struct {
hostsFn string // path to the main hosts-file
hostsDirs []string // paths to OS-specific directories with hosts-files
watcher *fsnotify.Watcher // file and directory watcher object
updateChan chan bool // signal for 'update' goroutine
updateChan chan bool // signal for 'updateLoop' goroutine
onChanged onChangedT // notification to other modules
}
@ -68,20 +68,22 @@ func (a *AutoHosts) Init(hostsFn string) {
// Start - start module
func (a *AutoHosts) Start() {
go a.update()
log.Debug("Start AutoHosts module")
go a.updateLoop()
a.updateChan <- true
go a.watcherLoop()
err := a.watcher.Add(a.hostsFn)
if err != nil {
log.Error("AutoHosts: %s", err)
log.Error("Error while initializing watcher for a file %s: %s", a.hostsFn, err)
}
for _, dir := range a.hostsDirs {
err = a.watcher.Add(dir)
if err != nil {
log.Error("AutoHosts: %s", err)
log.Error("Error while initializing watcher for a directory %s: %s", dir, err)
}
}
}
@ -89,7 +91,8 @@ func (a *AutoHosts) Start() {
// Close - close module
func (a *AutoHosts) Close() {
a.updateChan <- false
a.watcher.Close()
close(a.updateChan)
_ = a.watcher.Close()
}
// Read IP-hostname pairs from file
@ -174,7 +177,7 @@ func (a *AutoHosts) watcherLoop() {
log.Debug("AutoHosts: modified: %s", event.Name)
select {
case a.updateChan <- true:
// sent a signal to 'update' goroutine
// sent a signal to 'updateLoop' goroutine
default:
// queue is full
}
@ -189,41 +192,48 @@ func (a *AutoHosts) watcherLoop() {
}
}
// Read static hosts from system files
func (a *AutoHosts) update() {
// updateLoop - read static hosts from system files
func (a *AutoHosts) updateLoop() {
for {
select {
case ok := <-a.updateChan:
if !ok {
log.Debug("Finished AutoHosts update loop")
return
}
table := make(map[string][]net.IP)
a.load(table, a.hostsFn)
for _, dir := range a.hostsDirs {
fis, err := ioutil.ReadDir(dir)
if err != nil {
if !os.IsNotExist(err) {
log.Error("AutoHosts: Opening directory: %s: %s", dir, err)
}
continue
}
for _, fi := range fis {
a.load(table, dir+"/"+fi.Name())
}
}
a.lock.Lock()
a.table = table
a.lock.Unlock()
a.notify()
a.updateHosts()
}
}
}
// updateHosts - loads system hosts
func (a *AutoHosts) updateHosts() {
table := make(map[string][]net.IP)
a.load(table, a.hostsFn)
for _, dir := range a.hostsDirs {
fis, err := ioutil.ReadDir(dir)
if err != nil {
if !os.IsNotExist(err) {
log.Error("AutoHosts: Opening directory: %s: %s", dir, err)
}
continue
}
for _, fi := range fis {
a.load(table, dir+"/"+fi.Name())
}
}
a.lock.Lock()
a.table = table
a.lock.Unlock()
a.notify()
}
// Process - get the list of IP addresses for the hostname
// Return nil if not found
func (a *AutoHosts) Process(host string) []net.IP {

View file

@ -17,38 +17,73 @@ func prepareTestDir() string {
return dir
}
func TestAutoHosts(t *testing.T) {
func TestAutoHostsResolution(t *testing.T) {
ah := AutoHosts{}
dir := prepareTestDir()
defer func() { _ = os.RemoveAll(dir) }()
f, _ := ioutil.TempFile(dir, "")
defer os.Remove(f.Name())
defer func() { _ = os.Remove(f.Name()) }()
defer f.Close()
_, _ = f.WriteString(" 127.0.0.1 host localhost \n")
ah.Init(f.Name())
ah.Start()
// wait until we parse the file
time.Sleep(50 * time.Millisecond)
// Update from the hosts file
ah.updateHosts()
// Existing host
ips := ah.Process("localhost")
assert.True(t, ips[0].Equal(net.ParseIP("127.0.0.1")))
ips = ah.Process("newhost")
assert.True(t, ips == nil)
assert.NotNil(t, ips)
assert.Equal(t, 1, len(ips))
assert.Equal(t, net.ParseIP("127.0.0.1"), ips[0])
// Unknown host
ips = ah.Process("newhost")
assert.Nil(t, ips)
// Test hosts file
table := ah.List()
ips, _ = table["host"]
assert.True(t, ips[0].String() == "127.0.0.1")
assert.NotNil(t, ips)
assert.Equal(t, 1, len(ips))
assert.Equal(t, "127.0.0.1", ips[0].String())
}
func TestAutoHostsFSNotify(t *testing.T) {
ah := AutoHosts{}
dir := prepareTestDir()
defer func() { _ = os.RemoveAll(dir) }()
f, _ := ioutil.TempFile(dir, "")
defer func() { _ = os.Remove(f.Name()) }()
defer f.Close()
// Init
_, _ = f.WriteString(" 127.0.0.1 host localhost \n")
ah.Init(f.Name())
ah.updateHosts()
// Unknown host
ips := ah.Process("newhost")
assert.Nil(t, ips)
// Stat monitoring for changes
ah.Start()
defer ah.Close()
// Update file
_, _ = f.WriteString("127.0.0.2 newhost\n")
_ = f.Sync()
// wait until fsnotify has triggerred and processed the file-modification event
time.Sleep(50 * time.Millisecond)
// Check if we are notified about changes
ips = ah.Process("newhost")
assert.True(t, ips[0].Equal(net.ParseIP("127.0.0.2")))
ah.Close()
assert.NotNil(t, ips)
assert.Equal(t, 1, len(ips))
assert.Equal(t, "127.0.0.2", ips[0].String())
}

View file

@ -13,7 +13,7 @@ func SetRlimit(val uint) {
func HaveAdminRights() (bool, error) {
var token windows.Token
h, _ := windows.GetCurrentProcess()
h := windows.CurrentProcess()
err := windows.OpenProcessToken(h, windows.TOKEN_QUERY, &token)
if err != nil {
return false, err