From fa9890420cf5dbbca652fceb05708b67c393ebb5 Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 14:27:37 +0000
Subject: [PATCH 1/7] Use fmt/log.Println, not the println builtin

---
 daemon.go | 4 ++--
 domain.go | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/daemon.go b/daemon.go
index 8d68bb4..bbe6911 100644
--- a/daemon.go
+++ b/daemon.go
@@ -188,7 +188,7 @@ func daemonize(config appConfig, uid, gid uint) {
 	// Run daemon in chroot environment
 	temporaryExecutable, err := daemonChroot(cmd)
 	if err != nil {
-		println("Chroot failed", err)
+		log.Println("Chroot failed", err)
 		return
 	}
 	defer os.Remove(temporaryExecutable)
@@ -211,7 +211,7 @@ func daemonize(config appConfig, uid, gid uint) {
 
 	// Start the process
 	if err = cmd.Start(); err != nil {
-		println("Start failed", err)
+		log.Println("Start failed", err)
 		return
 	}
 
diff --git a/domain.go b/domain.go
index 46f57ed..19e099a 100644
--- a/domain.go
+++ b/domain.go
@@ -34,7 +34,7 @@ func (d *domain) serveFile(w http.ResponseWriter, r *http.Request, fullPath stri
 		return err
 	}
 
-	println("Serving", fullPath, "for", r.URL.Path)
+	fmt.Println("Serving", fullPath, "for", r.URL.Path)
 	http.ServeContent(w, r, filepath.Base(file.Name()), fi.ModTime(), file)
 	return nil
 }
@@ -52,7 +52,7 @@ func (d *domain) serveCustomFile(w http.ResponseWriter, r *http.Request, code in
 		return err
 	}
 
-	println("Serving", fullPath, "for", r.URL.Path, "with", code)
+	fmt.Println("Serving", fullPath, "for", r.URL.Path, "with", code)
 
 	// Serve the file
 	_, haveType := w.Header()["Content-Type"]
-- 
GitLab


From 91734e88d1763f69e66cec5ea7e5c5cf8c099e7f Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:19:16 +0000
Subject: [PATCH 2/7] Run the tests with more verbose output and a shorter
 timeout

---
 Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 2c1b8e1..96adaa0 100644
--- a/Makefile
+++ b/Makefile
@@ -40,10 +40,10 @@ complexity:
 
 test:
 	go get golang.org/x/tools/cmd/cover
-	go test ./... -cover
+	go test ./... -cover -v -timeout 1m
 
 acceptance: gitlab-pages
-	go test ./... -run-acceptance-tests
+	go test ./... -run-acceptance-tests -v -timeout 1m
 
 docker:
 	docker run --rm -it -v ${PWD}:/go/src/pages -w /go/src/pages golang:1.5 /bin/bash
-- 
GitLab


From 934a76c536c7de5b3dba17e6b110f60d002cfbc6 Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:19:46 +0000
Subject: [PATCH 3/7] Run the tests with gitlab-pages daemonised in the CI
 environment

---
 helpers_test.go | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/helpers_test.go b/helpers_test.go
index e7fd744..99a44ea 100644
--- a/helpers_test.go
+++ b/helpers_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"bytes"
 	"crypto/tls"
 	"fmt"
 	"io/ioutil"
@@ -15,6 +16,16 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+type tWriter struct {
+	t *testing.T
+}
+
+func (t *tWriter) Write(b []byte) (int, error) {
+	t.t.Log(string(bytes.TrimRight(b, "\r\n")))
+
+	return len(b), nil
+}
+
 var chdirSet = false
 
 func setUpTests() {
@@ -131,6 +142,8 @@ func RunPagesProcess(t *testing.T, pagesPath string, listeners []ListenSpec, pro
 
 	args, tempfiles := getPagesArgs(t, listeners, promPort)
 	cmd := exec.Command(pagesPath, args...)
+	cmd.Stdout = &tWriter{t}
+	cmd.Stderr = &tWriter{t}
 	cmd.Start()
 	t.Logf("Running %s %v", pagesPath, args)
 
@@ -144,10 +157,10 @@ func RunPagesProcess(t *testing.T, pagesPath string, listeners []ListenSpec, pro
 	for _, spec := range listeners {
 		spec.WaitUntilListening()
 	}
-	time.Sleep(50 * time.Millisecond)
+	time.Sleep(500 * time.Millisecond)
 
 	return func() {
-		cmd.Process.Kill()
+		cmd.Process.Signal(os.Interrupt)
 		cmd.Process.Wait()
 		for _, tempfile := range tempfiles {
 			os.Remove(tempfile)
@@ -176,9 +189,11 @@ func getPagesArgs(t *testing.T, listeners []ListenSpec, promPort string) (args,
 		args = append(args, "-metrics-address", promPort)
 	}
 
-	if os.Geteuid() == 0 && os.Getenv("SUDO_UID") != "" && os.Getenv("SUDO_GID") != "" {
-		t.Log("Pages process will drop privileges")
-		args = append(args, "-daemon-uid", os.Getenv("SUDO_UID"), "-daemon-gid", os.Getenv("SUDO_GID"))
+	// At least one of `-daemon-uid` and `-daemon-gid` must be non-zero
+	if os.Geteuid() == 0 {
+		t.Log("Running pages as a daemon")
+		args = append(args, "-daemon-uid", "0")
+		args = append(args, "-daemon-gid", "65534") // Root user can switch to "nobody"
 	}
 
 	return
-- 
GitLab


From 114d0f4075bdba7600f59e38771a75b82c9ae7c0 Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:24:06 +0000
Subject: [PATCH 4/7] Document some caveats around the daemon mode

---
 README.md | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 295ca7a..7ff395c 100644
--- a/README.md
+++ b/README.md
@@ -39,15 +39,18 @@ If load balancer is run in SSL-offloading mode the custom TLS certificate will n
 
 Example:
 ```
-go build
+CGO_ENABLED=0 GO15VENDOREXPERIMENT=1 go build
 ./gitlab-pages -listen-https "" -listen-http ":8090" -pages-root path/to/gitlab/shared/pages -pages-domain example.com
 ```
 
 ### Run daemon **in secure mode**
 
-The daemon can be run in chroot with dropped privileges.
+When compiled with `CGO_ENABLED=0` (which is the default), `gitlab-pages` is a
+static binary and so can be run in chroot with dropped privileges.
 
-Run daemon as root user and pass the `-daemon-uid` and `-daemon-gid`.
+To enter this mode, run `gitlab-pages` as the root user and pass it the
+`-daemon-uid` and `-daemon-gid` arguments to specify the user you want it to run
+as.
 
 The daemon start listening on ports as root, reads certificates as root and re-executes itself as specified user.
 When re-executing it copies it's own binary to `pages-root` and changes root to that directory.
@@ -74,8 +77,8 @@ This is most useful in dual-stack environments (IPv4+IPv6) where both Gitlab Pag
 
 ### Enable Prometheus Metrics
 
-For monitoring purposes, one could pass the `-metrics-address` flag when 
-starting. This will expose general metrics about the Go runtime and pages 
+For monitoring purposes, one could pass the `-metrics-address` flag when
+starting. This will expose general metrics about the Go runtime and pages
 application for [Prometheus](https://prometheus.io/) to scrape.
 
 Example:
-- 
GitLab


From 275cafa033f087748f66d12197d447e56537a048 Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:39:22 +0000
Subject: [PATCH 5/7] Rework the acceptance tests to use go test -short as a
 qualifier

---
 Makefile           |  5 +++--
 acceptance_test.go | 13 ++++++++-----
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index 96adaa0..1bee4e6 100644
--- a/Makefile
+++ b/Makefile
@@ -40,10 +40,11 @@ complexity:
 
 test:
 	go get golang.org/x/tools/cmd/cover
-	go test ./... -cover -v -timeout 1m
+	go test ./... -short -cover -v -timeout 1m
 
 acceptance: gitlab-pages
-	go test ./... -run-acceptance-tests -v -timeout 1m
+	go get golang.org/x/tools/cmd/cover
+	go test ./... -cover -v -timeout 1m
 
 docker:
 	docker run --rm -it -v ${PWD}:/go/src/pages -w /go/src/pages golang:1.5 /bin/bash
diff --git a/acceptance_test.go b/acceptance_test.go
index 1cfd133..e1a7167 100644
--- a/acceptance_test.go
+++ b/acceptance_test.go
@@ -4,12 +4,12 @@ import (
 	"flag"
 	"io/ioutil"
 	"net/http"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-var shouldRun = flag.Bool("run-acceptance-tests", false, "Run the acceptance tests?")
 var pagesBinary = flag.String("gitlab-pages-binary", "./gitlab-pages", "Path to the gitlab-pages binary")
 
 // TODO: Use TCP port 0 everywhere to avoid conflicts. The binary could output
@@ -25,12 +25,15 @@ var listeners = []ListenSpec{
 }
 
 func skipUnlessEnabled(t *testing.T) {
-	if *shouldRun {
-		return
+	if testing.Short() {
+		t.Log("Acceptance tests disabled")
+		t.SkipNow()
 	}
 
-	t.Log("Acceptance tests disabled")
-	t.SkipNow()
+	if _, err := os.Stat(*pagesBinary); os.IsNotExist(err) {
+		t.Errorf("Couldn't find gitlab-pages binary at %s", *pagesBinary)
+		t.FailNow()
+	}
 }
 
 func TestUnknownHostReturnsNotFound(t *testing.T) {
-- 
GitLab


From 8f4b98799e67025cb236972c7739ac6c9a1b808d Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:48:16 +0000
Subject: [PATCH 6/7] Run the acceptance test suite on all golang versions

---
 .gitlab-ci.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ef8afaf..14e0b55 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,11 +12,13 @@ test:1.5:
   image: golang:1.5
   script:
   - make verify-lite
+  - make acceptance
 
 test:1.6:
   image: golang:1.6
   script:
   - make verify
+  - make acceptance
 
 test:1.7:
   image: golang:1.7
-- 
GitLab


From a3c94ef64ab5f7d1a49da2e99fb4f92d3b1f2a0f Mon Sep 17 00:00:00 2001
From: Nick Thomas <nick@gitlab.com>
Date: Wed, 8 Mar 2017 15:48:43 +0000
Subject: [PATCH 7/7] Run tests on golang 1.8

---
 .gitlab-ci.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 14e0b55..c3a2fb8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -25,3 +25,9 @@ test:1.7:
   script:
   - make verify
   - make acceptance
+
+test:1.8:
+  image: golang:1.8
+  script:
+  - make verify
+  - make acceptance
-- 
GitLab