chore(ci): use qdm12/log library to have timed logs for tests

This commit is contained in:
Quentin McGaw 2025-11-26 12:44:39 +00:00
parent 57d8eb03c5
commit 08a7aae5f1
7 changed files with 46 additions and 21 deletions

View File

@ -7,11 +7,13 @@ import (
"os/signal" "os/signal"
"github.com/qdm12/gluetun/ci/internal" "github.com/qdm12/gluetun/ci/internal"
"github.com/qdm12/log"
) )
func main() { func main() {
logger := log.New()
if len(os.Args) < 2 { if len(os.Args) < 2 {
fmt.Println("Usage: " + os.Args[0] + " <command>") logger.Error("Usage: " + os.Args[0] + " <command>")
os.Exit(1) os.Exit(1)
} }
@ -20,16 +22,16 @@ func main() {
var err error var err error
switch os.Args[1] { switch os.Args[1] {
case "mullvad": case "mullvad":
err = internal.MullvadTest(ctx) err = internal.MullvadTest(ctx, logger)
case "protonvpn": case "protonvpn":
err = internal.ProtonVPNTest(ctx) err = internal.ProtonVPNTest(ctx, logger)
default: default:
err = fmt.Errorf("unknown command: %s", os.Args[1]) err = fmt.Errorf("unknown command: %s", os.Args[1])
} }
stop() stop()
if err != nil { if err != nil {
fmt.Println("❌", err) logger.Error(err.Error())
os.Exit(1) os.Exit(1)
} }
fmt.Println("✅ Test completed successfully.") logger.Info("test completed successfully")
} }

View File

@ -15,15 +15,19 @@ require (
github.com/distribution/reference v0.6.0 // indirect github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/qdm12/log v0.1.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect

View File

@ -20,6 +20,8 @@ github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pM
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@ -33,6 +35,11 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@ -51,6 +58,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/qdm12/log v0.1.0 h1:jYBd/xscHYpblzZAd2kjZp2YmuYHjAAfbTViJWxoPTw=
github.com/qdm12/log v0.1.0/go.mod h1:Vchi5M8uBvHfPNIblN4mjXn/oSbiWguQIbsgF1zdQPI=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
@ -77,6 +86,9 @@ go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOV
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=

View File

@ -5,12 +5,12 @@ import (
"fmt" "fmt"
) )
func MullvadTest(ctx context.Context) error { func MullvadTest(ctx context.Context, logger Logger) error {
expectedSecrets := []string{ expectedSecrets := []string{
"Wireguard private key", "Wireguard private key",
"Wireguard address", "Wireguard address",
} }
secrets, err := readSecrets(ctx, expectedSecrets) secrets, err := readSecrets(ctx, expectedSecrets, logger)
if err != nil { if err != nil {
return fmt.Errorf("reading secrets: %w", err) return fmt.Errorf("reading secrets: %w", err)
} }
@ -23,5 +23,5 @@ func MullvadTest(ctx context.Context) error {
"WIREGUARD_PRIVATE_KEY=" + secrets[0], "WIREGUARD_PRIVATE_KEY=" + secrets[0],
"WIREGUARD_ADDRESSES=" + secrets[1], "WIREGUARD_ADDRESSES=" + secrets[1],
} }
return simpleTest(ctx, env) return simpleTest(ctx, env, logger)
} }

View File

@ -5,11 +5,11 @@ import (
"fmt" "fmt"
) )
func ProtonVPNTest(ctx context.Context) error { func ProtonVPNTest(ctx context.Context, logger Logger) error {
expectedSecrets := []string{ expectedSecrets := []string{
"Wireguard private key", "Wireguard private key",
} }
secrets, err := readSecrets(ctx, expectedSecrets) secrets, err := readSecrets(ctx, expectedSecrets, logger)
if err != nil { if err != nil {
return fmt.Errorf("reading secrets: %w", err) return fmt.Errorf("reading secrets: %w", err)
} }
@ -21,5 +21,5 @@ func ProtonVPNTest(ctx context.Context) error {
"SERVER_COUNTRIES=United States", "SERVER_COUNTRIES=United States",
"WIREGUARD_PRIVATE_KEY=" + secrets[0], "WIREGUARD_PRIVATE_KEY=" + secrets[0],
} }
return simpleTest(ctx, env) return simpleTest(ctx, env, logger)
} }

View File

@ -8,17 +8,24 @@ import (
"strings" "strings"
) )
func readSecrets(ctx context.Context, expectedSecrets []string) (lines []string, err error) { type Logger interface {
Info(msg string)
Infof(format string, args ...any)
}
func readSecrets(ctx context.Context, expectedSecrets []string,
logger Logger,
) (lines []string, err error) {
scanner := bufio.NewScanner(os.Stdin) scanner := bufio.NewScanner(os.Stdin)
lines = make([]string, 0, len(expectedSecrets)) lines = make([]string, 0, len(expectedSecrets))
for i := range expectedSecrets { for i := range expectedSecrets {
fmt.Println("🤫 reading", expectedSecrets[i], "from Stdin...") logger.Infof("🤫 reading %s from Stdin...", expectedSecrets[i])
if !scanner.Scan() { if !scanner.Scan() {
break break
} }
lines = append(lines, strings.TrimSpace(scanner.Text())) lines = append(lines, strings.TrimSpace(scanner.Text()))
fmt.Println("🤫 "+expectedSecrets[i], "secret read successfully") logger.Infof("🤫 %s secret read successfully", expectedSecrets[i])
if ctx.Err() != nil { if ctx.Err() != nil {
return nil, ctx.Err() return nil, ctx.Err()
} }

View File

@ -16,7 +16,7 @@ import (
func ptrTo[T any](v T) *T { return &v } func ptrTo[T any](v T) *T { return &v }
func simpleTest(ctx context.Context, env []string) error { func simpleTest(ctx context.Context, env []string, logger Logger) error {
const timeout = 30 * time.Second const timeout = 30 * time.Second
ctx, cancel := context.WithTimeout(ctx, timeout) ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel() defer cancel()
@ -57,7 +57,7 @@ func simpleTest(ctx context.Context, env []string) error {
return fmt.Errorf("starting container: %w", err) return fmt.Errorf("starting container: %w", err)
} }
return waitForLogLine(ctx, client, containerID, beforeStartTime) return waitForLogLine(ctx, client, containerID, beforeStartTime, logger)
} }
func stopContainer(client *client.Client, containerID string) { func stopContainer(client *client.Client, containerID string) {
@ -74,7 +74,7 @@ func stopContainer(client *client.Client, containerID string) {
var successRegexp = regexp.MustCompile(`^.+Public IP address is .+$`) var successRegexp = regexp.MustCompile(`^.+Public IP address is .+$`)
func waitForLogLine(ctx context.Context, client *client.Client, containerID string, func waitForLogLine(ctx context.Context, client *client.Client, containerID string,
beforeStartTime time.Time, beforeStartTime time.Time, logger Logger,
) error { ) error {
logOptions := container.LogsOptions{ logOptions := container.LogsOptions{
ShowStdout: true, ShowStdout: true,
@ -105,13 +105,13 @@ func waitForLogLine(ctx context.Context, client *client.Client, containerID stri
} }
err := scanner.Err() err := scanner.Err()
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
logSeenLines(linesSeen) logSeenLines(logger, linesSeen)
return fmt.Errorf("reading log stream: %w", err) return fmt.Errorf("reading log stream: %w", err)
} }
// The scanner is either done or cannot read because of EOF // The scanner is either done or cannot read because of EOF
fmt.Println("The log scanner stopped") logger.Info("the log scanner stopped")
logSeenLines(linesSeen) logSeenLines(logger, linesSeen)
// Check if the container is still running // Check if the container is still running
inspect, err := client.ContainerInspect(ctx, containerID) inspect, err := client.ContainerInspect(ctx, containerID)
@ -126,7 +126,7 @@ func waitForLogLine(ctx context.Context, client *client.Client, containerID stri
return ctx.Err() return ctx.Err()
} }
func logSeenLines(lines []string) { func logSeenLines(logger Logger, lines []string) {
fmt.Println("Logs seen so far:") fmt.Println("Logs seen so far:")
for _, line := range lines { for _, line := range lines {
fmt.Println(" " + line) fmt.Println(" " + line)