Compare commits

..

3 Commits

Author SHA1 Message Date
Urko. ad77710ad1 fix: Dockerfile 2024-04-29 21:50:35 +02:00
Urko. 5860f81aa2 refactor: change configruation to yml 2024-04-29 21:50:16 +02:00
Urko. 727b083e52 refactor: project structure 2024-04-29 21:29:05 +02:00
16 changed files with 103 additions and 77 deletions

View File

@ -1,4 +0,0 @@
SCRIPT_BINARY_PATH=
WEBHOOK_SCRIPT_PATH=
FILE_TO_WATCH_PATH=
TEST_FILE_TO_WATCH_PATH=

28
Dockerfile Normal file
View File

@ -0,0 +1,28 @@
FROM golang:1.22 as builder
WORKDIR /app
# Copy the local package files to the container's workspace.
COPY go.mod go.sum ./
RUN go mod download
# Copy the project code into the container
COPY . .
# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -v -o git-webhook-ci
# Use a small Alpine Linux image
FROM alpine:latest
# Set the working directory
WORKDIR /root/
# Copy the binary from the builder stage
COPY --from=builder /app/git-webhook-ci .
# Document that the service listens on port 8080.
EXPOSE 8080
# Run the binary.
CMD ["./git-webhook-ci"]

3
app.example.yml Normal file
View File

@ -0,0 +1,3 @@
script_binary_path: "/bin/bash"
webhook_script_path: "./test-script.sh"
file_to_watch_path: "./test_monitor.txt"

View File

@ -1,45 +0,0 @@
package cfg
import (
"log"
"os/exec"
"strings"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
)
type Config struct {
ScriptBinaryPath string `required:"true" split_words:"true"`
WebhookScriptPath string `required:"true" split_words:"true"`
FileToWatchPath string `required:"true" split_words:"true"`
TestFileToWatchPath string `required:"false" split_words:"true"`
}
func RootDir() string {
cmdOut, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
if err != nil {
log.Fatalf("exec.Command: %s", err)
return ""
}
rootDir := strings.TrimSpace(string(cmdOut))
return rootDir
}
func NewConfig(envFilePath string) *Config {
if envFilePath != "" {
err := godotenv.Load(envFilePath)
if err != nil {
log.Fatalf("environment variable ENV is empty and an error occurred while loading the .env file\n")
}
}
cfg := &Config{}
err := envconfig.Process("", cfg)
if err != nil {
log.Fatalf("envconfig.Process: %s\n", err)
}
return cfg
}

3
configs/app.yml Normal file
View File

@ -0,0 +1,3 @@
script_binary_path: "/bin/bash"
webhook_script_path: "./test-script.sh"
file_to_watch_path: "./test_monitor.txt"

3
go.mod
View File

@ -4,9 +4,8 @@ go 1.22
require ( require (
github.com/fsnotify/fsnotify v1.7.0 github.com/fsnotify/fsnotify v1.7.0
github.com/joho/godotenv v1.5.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.2
gopkg.in/yaml.v2 v2.4.0
) )
require ( require (

6
go.sum
View File

@ -3,10 +3,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -20,6 +16,8 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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/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=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

3
internal/watcher/testdata/config.yml vendored Normal file
View File

@ -0,0 +1,3 @@
script_binary_path: "/bin/bash"
webhook_script_path: "testdata/test-script.sh"
file_to_watch_path: "testdata/test_monitor.txt"

View File

@ -4,13 +4,13 @@ import (
"errors" "errors"
"log" "log"
pkgwatcher "gitea.urkob.com/urko/git-webhook-ci/pkg/watcher" "gitea.urkob.com/urko/git-webhook-ci/pkg"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
) )
type watcher struct { type watcher struct {
fswatcher *fsnotify.Watcher fswatcher *fsnotify.Watcher
deploy pkgwatcher.DeployFunc deploy pkg.DeployFunc
} }
type notifier struct{} type notifier struct{}
@ -28,7 +28,7 @@ var (
errErrorsClosedChan = errors.New("errors is closed") errErrorsClosedChan = errors.New("errors is closed")
) )
func NewWatcher(notifier pkgwatcher.NotifyIface, deploy pkgwatcher.DeployFunc) *watcher { func NewWatcher(notifier pkg.NotifyIface, deploy pkg.DeployFunc) *watcher {
wt, err := notifier.NewWatcher() wt, err := notifier.NewWatcher()
if err != nil { if err != nil {
log.Printf("fsnotify.NewWatcher: %s\n", err) log.Printf("fsnotify.NewWatcher: %s\n", err)

View File

@ -3,11 +3,12 @@ package watcher
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"testing" "testing"
"time" "time"
"gitea.urkob.com/urko/git-webhook-ci/cfg" "gitea.urkob.com/urko/git-webhook-ci/kit/config"
pkgwatcher "gitea.urkob.com/urko/git-webhook-ci/pkg/watcher" "gitea.urkob.com/urko/git-webhook-ci/pkg"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -26,13 +27,13 @@ var (
) )
var ( var (
mockDeploy pkgwatcher.DeployFunc mockDeploy pkg.DeployFunc
mockErrorDeploy pkgwatcher.DeployFunc mockErrorDeploy pkg.DeployFunc
errIntentional = errors.New("intentional error") errIntentional = errors.New("intentional error")
binaryPath = "" binaryPath = ""
scriptPath = "" scriptPath = ""
executionMaxTimeout = time.Second * 2 executionMaxTimeout = time.Second * 2
config *cfg.Config cfg *config.Config
events = []fsnotify.Event{ events = []fsnotify.Event{
{ {
Name: "test event", Name: "test event",
@ -45,7 +46,7 @@ var (
} }
) )
func init() { func TestMain(t *testing.M) {
mockDeploy = func(binaryPath, scriptPath string) error { mockDeploy = func(binaryPath, scriptPath string) error {
return nil return nil
} }
@ -53,8 +54,16 @@ func init() {
mockErrorDeploy = func(binaryPath, scriptPath string) error { mockErrorDeploy = func(binaryPath, scriptPath string) error {
return errIntentional return errIntentional
} }
}
func LoadConfig(t *testing.T) {
t.Helper()
cf, err := config.LoadConfig("testdata/config.yaml")
if err != nil {
panic(fmt.Errorf("Error loading config: %w", err))
}
cfg = cf
config = cfg.NewConfig("../../.env")
} }
func sendTestEvents(w *watcher) { func sendTestEvents(w *watcher) {
@ -76,6 +85,7 @@ func newWatcherWithCtorError() *watcher {
} }
func Test_NewNotifier(t *testing.T) { func Test_NewNotifier(t *testing.T) {
LoadConfig(t)
require.NotNil(t, NewNotifier()) require.NotNil(t, NewNotifier())
} }
@ -97,7 +107,7 @@ func Test_Close(t *testing.T) {
func Test_Monitor(t *testing.T) { func Test_Monitor(t *testing.T) {
w := newWatcher() w := newWatcher()
err := w.Monitor(config.TestFileToWatchPath) err := w.Monitor(cfg.FileToWatchPath)
require.NoError(t, err) require.NoError(t, err)
} }

27
kit/config/config.go Normal file
View File

@ -0,0 +1,27 @@
package config
import (
"os"
"gopkg.in/yaml.v2"
)
type Config struct {
ScriptBinaryPath string `yaml:"script_binary_path"`
WebhookScriptPath string `yaml:"webhook_script_path"`
FileToWatchPath string `yaml:"file_to_watch_path"`
}
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var config Config
if err := yaml.Unmarshal(data, &config); err != nil {
return nil, err
}
return &config, nil
}

15
main.go
View File

@ -7,14 +7,14 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"gitea.urkob.com/urko/git-webhook-ci/cfg"
"gitea.urkob.com/urko/git-webhook-ci/internal/watcher" "gitea.urkob.com/urko/git-webhook-ci/internal/watcher"
pkgwatcher "gitea.urkob.com/urko/git-webhook-ci/pkg/watcher" "gitea.urkob.com/urko/git-webhook-ci/kit/config"
"gitea.urkob.com/urko/git-webhook-ci/pkg"
) )
var ( var (
watcherIface pkgwatcher.WatcherIface watcherIface pkg.WatcherIface
notifierIface pkgwatcher.NotifyIface notifierIface pkg.NotifyIface
) )
func main() { func main() {
@ -24,10 +24,13 @@ func main() {
flag.Parse() flag.Parse()
} }
config := cfg.NewConfig(envFilePath) config, err := config.LoadConfig(envFilePath)
if err != nil {
panic(err)
}
notifierIface = watcher.NewNotifier() notifierIface = watcher.NewNotifier()
watcherIface = watcher.NewWatcher(notifierIface, pkgwatcher.Deploy) watcherIface = watcher.NewWatcher(notifierIface, pkg.Deploy)
defer func() { defer func() {
if err := watcherIface.Close(); err != nil { if err := watcherIface.Close(); err != nil {

2
pkg/testdata/test-script.sh vendored Normal file
View File

@ -0,0 +1,2 @@
#!/bin/bash
echo "deploy script has been called"

View File

@ -1,4 +1,4 @@
package watcher package pkg
import ( import (
"fmt" "fmt"

View File

@ -1,15 +1,14 @@
package watcher package pkg
import ( import (
"testing" "testing"
"gitea.urkob.com/urko/git-webhook-ci/cfg"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var ( const (
binaryPath = "/bin/bash" binaryPath = "/bin/bash"
scriptPath = cfg.RootDir() + "/test-script.sh" scriptPath = "testdata/test-script.sh"
) )
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {