snapshot of https://github.com/ThreeDotsLabs/watermill.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
master / ci (push) Failing after 0s

This commit is contained in:
upstream-mirror
2026-09-15 21:27:46 +05:00
commit ce933d1277
538 changed files with 46504 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
package main
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
)
// simple script to consolidate all gomods to one gomod
// required for GolangCI linter
func main() {
bigFatGomod := ""
for _, fileName := range getGomods() {
dir := filepath.Dir(fileName)
if dir == "." {
continue
}
file, err := os.Open(fileName)
if err != nil {
panic(err)
}
fileMod := ""
scanner := bufio.NewScanner(file)
for scanner.Scan() {
txt := scanner.Text()
if strings.HasPrefix(txt, "go ") {
continue
}
if strings.HasPrefix(txt, "module ") {
continue
}
fileMod += txt + "\n"
}
if err := scanner.Err(); err != nil {
panic(err)
}
if fileMod != "" {
bigFatGomod += "// " + fileName + "\n"
bigFatGomod += fileMod + "\n"
}
_ = file.Close()
// gomod is stupid, and go vendor removes all deps that are not needed
// (and they are not needed if they are already meet in sub go.mods)
if err := os.Remove(fileName); err != nil {
panic(err)
}
}
fmt.Println(bigFatGomod)
}
func getGomods() []string {
var fileList []string
err := filepath.Walk(".", func(path string, f os.FileInfo, err error) error {
if strings.Contains(path, "/vendor/") {
return nil
}
if strings.Contains(path, "go.mod") {
fileList = append(fileList, path)
}
return nil
})
if err != nil {
panic(err)
}
return fileList
}

56
dev/coverage.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/sh
########
# Source: https://gist.github.com/lwolf/3764a3b6cd08387e80aa6ca3b9534b8a
# originally from https://github.com/mlafeldt/chef-runner/blob/v0.7.0/script/coverage
#######
# Generate test coverage statistics for Go packages.
#
# Works around the fact that `go test -coverprofile` currently does not work
# with multiple packages, see https://code.google.com/p/go/issues/detail?id=6909
#
# Usage: script/coverage [--html|--coveralls]
#
# --html Additionally create HTML report and open it in browser
# --coveralls Push coverage statistics to coveralls.io
#
set -e
workdir=.cover
profile="$workdir/cover.out"
mode=count
generate_cover_data() {
rm -rf "$workdir"
mkdir "$workdir"
for pkg in "$@"; do
f="$workdir/$(echo $pkg | tr / -).cover"
go test -covermode="$mode" -coverprofile="$f" "$pkg"
done
echo "mode: $mode" >"$profile"
grep -h -v "^mode:" "$workdir"/*.cover >>"$profile"
}
show_cover_report() {
go tool cover -${1}="$profile"
}
push_to_coveralls() {
echo "Pushing coverage statistics to coveralls.io"
goveralls -coverprofile="$profile"
}
generate_cover_data $(go list ./... | grep -v /vendor/)
show_cover_report func
case "$1" in
"")
;;
--html)
show_cover_report html ;;
--coveralls)
push_to_coveralls ;;
*)
echo >&2 "error: invalid option: $1"; exit 1 ;;
esac

14
dev/prometheus.yml Normal file
View File

@@ -0,0 +1,14 @@
# for Watermill development purposes.
# there is one sample scrape target; add your own if needed.
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'some_metrics_endpoint'
static_configs:
- targets: ['localhost:8080']

View File

@@ -0,0 +1,3 @@
module github.com/ThreeDotsLabs/watermill/dev/update-examples-deps
go 1.25

View File

View File

@@ -0,0 +1,174 @@
package main
import (
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
)
var latestGoVersion string
func main() {
latestGoVersion = getLatestGoVersionFromWebsite()
const workers = 5
wg := sync.WaitGroup{}
wg.Add(workers)
files := make(chan string)
for i := 0; i < workers; i++ {
go func() {
for file := range files {
dir := filepath.Dir(file)
if dir == "." {
continue
}
fmt.Println("update of", file, "@", dir)
if err := replaceGoInDockerCompose(dir); err != nil {
panic(err)
}
if err := updateDeps(dir, file); err != nil {
panic(err)
}
if err := updateWatermill(dir, file); err != nil {
panic(fmt.Sprintf("failed to update %s: %s", file, err))
}
if err := goModTidy(dir, file); err != nil {
panic(err)
}
}
wg.Done()
}()
}
for _, file := range getGomods() {
files <- file
}
close(files)
wg.Wait()
}
func getGomods() []string {
var fileList []string
err := filepath.Walk(".", func(path string, f os.FileInfo, err error) error {
if strings.Contains(path, "go.mod") {
fileList = append(fileList, path)
}
return nil
})
if err != nil {
panic(err)
}
return fileList
}
func getLatestGoVersionFromWebsite() string {
resp, err := http.Get("https://go.dev/VERSION?m=text")
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
version := strings.Split(string(out), "\n")[0]
version = strings.TrimPrefix(version, "go")
// we only want the major.minor version
version = strings.Split(version, ".")[0] + "." + strings.Split(version, ".")[1]
return version
}
func goModTidy(dir string, file string) error {
cmd := []string{"go", "mod", "tidy", "-go=" + latestGoVersion}
fmt.Println("\nrunning", cmd, "in", dir)
cmd2 := exec.Command(cmd[0], cmd[1:]...)
cmd2.Dir = dir
cmd2.Stderr = os.Stderr
cmd2.Stdout = os.Stdout
return cmd2.Run()
}
// replaceGoInDockerCompose replaces the go version in the Dockerfile
// using Go (not sed)
func replaceGoInDockerCompose(dir string) error {
dockerComposeFile := filepath.Join(dir, "docker-compose.yml")
b, err := os.ReadFile(dockerComposeFile)
// return if not exist
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
pattern := `golang:1\.[0-9]+(?:\.[0-9]+)?`
re, err := regexp.Compile(pattern)
if err != nil {
return fmt.Errorf("failed to compile regex: %w", err)
}
newContent := re.ReplaceAllString(string(b), "golang:"+latestGoVersion)
err = os.WriteFile(dockerComposeFile, []byte(newContent), 0644)
if err != nil {
return fmt.Errorf("failed to write updated docker-compose.yml: %w", err)
}
return nil
}
func updateWatermill(dir string, file string) error {
c := []string{"go", "get", "-u", "github.com/ThreeDotsLabs/watermill@latest"}
fmt.Println("\nrunning", c, "in", dir)
cmd := exec.Command(c[0], c[1:]...)
cmd.Dir = dir
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
err := cmd.Run()
return err
}
func updateDeps(dir string, file string) error {
c := []string{"go", "get", "-u", "./..."}
fmt.Println("\nrunning", c, "in", dir)
cmd := exec.Command(c[0], c[1:]...)
cmd.Dir = dir
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
err := cmd.Run()
return err
}

View File

@@ -0,0 +1,14 @@
module github.com/ThreeDotsLabs/watermill/dev/validate-examples
go 1.25.0
require (
github.com/fatih/color v1.19.0
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.22 // indirect
golang.org/x/sys v0.44.0 // indirect
)

View File

@@ -0,0 +1,12 @@
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

View File

@@ -0,0 +1,177 @@
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/fatih/color"
yaml "gopkg.in/yaml.v2"
)
type Config struct {
ValidationCmd string `yaml:"validation_cmd"`
TeardownCmd string `yaml:"teardown_cmd"`
Timeout int `yaml:"timeout"`
ExpectedOutput string `yaml:"expected_output"`
ExpectedOutputs []string `yaml:"expected_outputs"`
}
func (c *Config) LoadFrom(path string) error {
file, err := os.ReadFile(path)
if err != nil {
return err
}
err = yaml.Unmarshal(file, c)
if err != nil {
return err
}
return nil
}
func main() {
path := "../../_examples/"
if len(os.Args) > 1 {
path = filepath.Join(path, os.Args[1])
}
walkErr := filepath.Walk(path, func(exampleConfig string, f os.FileInfo, _ error) error {
if f == nil {
return nil
}
matches, err := filepath.Match(".validate_example*.yml", f.Name())
if err != nil {
return fmt.Errorf("could not match file, err: %w", err)
}
if !matches {
return nil
}
exampleDirectory := filepath.Dir(exampleConfig)
fmt.Printf("validating %s\n", exampleDirectory)
err = validate(exampleConfig)
if err != nil {
return fmt.Errorf("validation for %s failed, err: %v", exampleDirectory, err)
}
return nil
})
if walkErr != nil {
panic(walkErr)
}
}
func validate(path string) error {
config := &Config{}
err := config.LoadFrom(path)
if err != nil {
return fmt.Errorf("could not load config, err: %v", err)
}
dirName := filepath.Base(filepath.Dir(path))
expectedOutputs := config.ExpectedOutputs
if config.ExpectedOutput != "" {
expectedOutputs = append(expectedOutputs, config.ExpectedOutput)
}
fmt.Print("\n\n")
fmt.Println("Validating example:", dirName)
fmt.Println("Waiting for output: ", color.GreenString(fmt.Sprintf("%+q", expectedOutputs)))
cmdAndArgs := strings.Fields(config.ValidationCmd)
validationCmd := exec.Command(cmdAndArgs[0], cmdAndArgs[1:]...)
validationCmd.Dir = filepath.Dir(path)
defer func() {
if config.TeardownCmd == "" {
return
}
cmdAndArgs := strings.Fields(config.TeardownCmd)
teardownCmd := exec.Command(cmdAndArgs[0], cmdAndArgs[1:]...)
teardownCmd.Dir = filepath.Dir(path)
_ = teardownCmd.Run()
}()
stdout, err := validationCmd.StdoutPipe()
if err != nil {
return fmt.Errorf("could not attach to stdout, err: %v", err)
}
stderr, err := validationCmd.StderrPipe()
if err != nil {
return fmt.Errorf("could not attach to stderr, err: %v", err)
}
fmt.Printf("running: %v\n", validationCmd.Args)
err = validationCmd.Start()
if err != nil {
return fmt.Errorf("could not start validation, err: %v", err)
}
defer func() {
err := validationCmd.Process.Kill()
if err != nil {
fmt.Printf("could not kill process in %s, err: %v\n", dirName, err)
}
}()
success := make(chan bool)
lines := make(chan string)
go readLines(stdout, lines)
go readLines(stderr, lines)
outputsFound := map[int]struct{}{}
go func() {
for line := range lines {
fmt.Printf("[%s] > %s\n", color.CyanString(dirName), line)
for num, output := range expectedOutputs {
ok, _ := regexp.MatchString(output, line)
if ok {
outputsFound[num] = struct{}{}
}
}
if len(outputsFound) == len(expectedOutputs) {
success <- true
return
}
}
}()
select {
case <-success:
return nil
case <-time.After(time.Duration(config.Timeout) * time.Second):
return fmt.Errorf("validation command timed out")
}
}
func readLines(reader io.Reader, output chan<- string) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
if scanner.Err() != nil {
if scanner.Err() == io.EOF {
return
}
continue
}
line := scanner.Text()
output <- line
}
}