Compare commits
18 Commits
19f17308b1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 26ce3260b9 | |||
| 8dc7bbc6d4 | |||
| 091ad1fec0 | |||
| ad77710ad1 | |||
| 5860f81aa2 | |||
| 727b083e52 | |||
| 2abed91918 | |||
| fe002edab1 | |||
| 422fedf9cd | |||
| 1b83793f38 | |||
| f56e85cc64 | |||
| 4877f72f04 | |||
| 60b40c84f3 | |||
| c0daf06ee6 | |||
| 41517ff292 | |||
| 16b0a31dd4 | |||
| 49a72dc34b | |||
| a67ef6f2d8 |
@@ -1,4 +0,0 @@
|
||||
SCRIPT_BINARY_PATH=
|
||||
WEBHOOK_SCRIPT_PATH=
|
||||
FILE_TO_WATCH_PATH=
|
||||
TEST_FILE_TO_WATCH_PATH=
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.env
|
||||
coverage/*
|
||||
test_monitor.txt
|
||||
bin
|
||||
bin
|
||||
configs/*
|
||||
28
Dockerfile
Normal file
28
Dockerfile
Normal 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"]
|
||||
8
LICENSE
Normal file
8
LICENSE
Normal file
@@ -0,0 +1,8 @@
|
||||
---- Definitions ----
|
||||
license means right to use
|
||||
|
||||
|
||||
Everybody is invited to contribute to improve this project and the main idea.
|
||||
This idea which is to help the community to develop more secure code.
|
||||
|
||||
By the grace of YAHWEH
|
||||
5
Makefile
5
Makefile
@@ -13,8 +13,7 @@ test-coverage:
|
||||
mkdir ${COVERAGE_DIR}
|
||||
go test -v -coverprofile ${COVERAGE_DIR}/cover.out ./...
|
||||
go tool cover -html ${COVERAGE_DIR}/cover.out -o ${COVERAGE_DIR}/cover.html
|
||||
cd ${COVERAGE_DIR}
|
||||
open cover.html
|
||||
build:
|
||||
rm -rf ${BINARY_DIR}
|
||||
mkdir ${BINARY_DIR}
|
||||
go build -o ${BINARY_DIR}/${BINARY_NAME}
|
||||
env GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -o ./${BINARY_DIR}/${BINARY_NAME} main.go
|
||||
69
README.md
69
README.md
@@ -1,37 +1,78 @@
|
||||
# git-webhook-ci
|
||||
|
||||
Tool to automatize your deploy based on file write changes
|
||||
|
||||
## Description
|
||||
After some change is made in our listener file the script placed on path set on `env` variable called **WEBHOOK_SCRIPT_PATH** will be executed.
|
||||
|
||||
After some change is made in our listener file the script placed on path set on `.yaml` configuration falled placed on `./configs/app.yaml` variable called **webhook_script_path** will be executed.
|
||||
|
||||
## Context
|
||||
|
||||
As a security risk that could be allow a webhook listener on a VPS for your git repository, I've decided
|
||||
to create this package which is a listener to file changes on write. This will trigger a bash script which
|
||||
you shold place on your server to run desired tasks. In my case I've done this to run a bash deploy command like
|
||||
- git pull
|
||||
- build
|
||||
- move build to desired dir
|
||||
- restart services like nginx or whatever
|
||||
|
||||
- git pull
|
||||
- build
|
||||
- move build to desired dir
|
||||
- restart services like nginx or whatever
|
||||
|
||||
## Installation
|
||||
|
||||
### Requirements
|
||||
- [Go version > 1.19](https://go.dev/dl/)
|
||||
|
||||
- [Go version > 1.22](https://go.dev/dl/)
|
||||
- [GNU Make 4.3](https://www.gnu.org/software/make/)
|
||||
- [goreportcard-cli](https://github.com/gojp/goreportcard)
|
||||
- [golangci-lint](https://golangci-lint.run/)
|
||||
|
||||
### Environment Vars
|
||||
As shown in .env.example you have to configure this variables in order to make your binary works right:
|
||||
|
||||
As shown in app.example.yml you have to configure this variables in order to make your binary works right:
|
||||
|
||||
```.env
|
||||
SCRIPT_BINARY_PATH=/bin/bash
|
||||
WEBHOOK_SCRIPT_PATH=/path/to/mybashscript.sh
|
||||
FILE_TO_WATCH_PATH=/path/to/myfile.txt
|
||||
TEST_FILE_TO_WATCH_PATH=./test_monitor.txt
|
||||
script_binary_path: "/bin/bash"
|
||||
webhook_script_path: "./test-script.sh"
|
||||
file_to_watch_path: "./test_monitor.txt"
|
||||
```
|
||||
|
||||
**TEST_FILE_TO_WATCH_PATH** is needed just to run tests
|
||||
|
||||
## How to use
|
||||
|
||||
### Build
|
||||
|
||||
To build you can only just `make build` command
|
||||
|
||||
```bash
|
||||
make build
|
||||
```
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
make test-coverage
|
||||
```
|
||||
|
||||
output:
|
||||
|
||||
```terminal
|
||||
coverage: 80.0% of statements
|
||||
ok gitea.urkob.com/urko/git-webhook-ci/internal/watcher 2.024s coverage: 80.0% of statements
|
||||
coverage: 100.0% of statements
|
||||
ok gitea.urkob.com/urko/git-webhook-ci/pkg/watcher 0.017s coverage: 100.0% of statements
|
||||
```
|
||||
|
||||
## goreportcard
|
||||
|
||||
```bash
|
||||
➜ git-webhook-ci git:(main) ✗ make goreportcard
|
||||
oreportcard-cli -v
|
||||
Grade .......... A+ 100.0%
|
||||
Files .................. 6
|
||||
Issues ................. 0
|
||||
gofmt ............... 100%
|
||||
go_vet .............. 100%
|
||||
gocyclo ............. 100%
|
||||
ineffassign ......... 100%
|
||||
license ............. 100%
|
||||
misspell ............ 100%
|
||||
```
|
||||
|
||||
3
app.example.yml
Normal file
3
app.example.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
script_binary_path: "/bin/bash"
|
||||
webhook_script_path: "./test-script.sh"
|
||||
file_to_watch_path: "./test_monitor.txt"
|
||||
@@ -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:"true" 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(isProd bool) *Config {
|
||||
if !isProd {
|
||||
err := godotenv.Load(rootDir() + "/.env")
|
||||
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
|
||||
}
|
||||
9
go.mod
9
go.mod
@@ -1,17 +1,16 @@
|
||||
module gitea.urkob.com/urko/git-webhook-ci
|
||||
|
||||
go 1.19
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
14
go.sum
14
go.sum
@@ -1,12 +1,8 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
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/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -16,10 +12,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
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/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
3
internal/watcher/testdata/config.yml
vendored
Normal file
3
internal/watcher/testdata/config.yml
vendored
Normal 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"
|
||||
2
internal/watcher/testdata/test-script.sh
vendored
Normal file
2
internal/watcher/testdata/test-script.sh
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
echo "deploy script has been called"
|
||||
@@ -4,13 +4,23 @@ import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
pkgwatcher "gitea.urkob.com/urko/git-webhook-ci/pkg/watcher"
|
||||
"gitea.urkob.com/urko/git-webhook-ci/pkg"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
type watcher struct {
|
||||
fswatcher *fsnotify.Watcher
|
||||
deploy pkgwatcher.DeployFunc
|
||||
deploy pkg.DeployFunc
|
||||
}
|
||||
|
||||
type notifier struct{}
|
||||
|
||||
func (n *notifier) NewWatcher() (*fsnotify.Watcher, error) {
|
||||
return fsnotify.NewWatcher()
|
||||
}
|
||||
|
||||
func NewNotifier() *notifier {
|
||||
return ¬ifier{}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -18,8 +28,8 @@ var (
|
||||
errErrorsClosedChan = errors.New("errors is closed")
|
||||
)
|
||||
|
||||
func NewWatcher(deploy pkgwatcher.DeployFunc) *watcher {
|
||||
wt, err := fsnotify.NewWatcher()
|
||||
func NewWatcher(notifier pkg.NotifyIface, deploy pkg.DeployFunc) *watcher {
|
||||
wt, err := notifier.NewWatcher()
|
||||
if err != nil {
|
||||
log.Printf("fsnotify.NewWatcher: %s\n", err)
|
||||
return nil
|
||||
@@ -45,10 +55,12 @@ func (w *watcher) Listen(binaryPath, scriptPath string, outputErr chan<- error)
|
||||
outputErr <- errEventsClosedChan
|
||||
return
|
||||
}
|
||||
|
||||
if !event.Has(fsnotify.Write) {
|
||||
log.Printf("is not Write: %s\n", event.Name)
|
||||
continue
|
||||
}
|
||||
log.Printf("event: %s | op: %s \n", event.Name, event.Op)
|
||||
|
||||
if err := w.deploy(binaryPath, scriptPath); err != nil {
|
||||
log.Printf("deploy: %s\n", err)
|
||||
|
||||
@@ -3,23 +3,37 @@ package watcher
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.urkob.com/urko/git-webhook-ci/cfg"
|
||||
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"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type testErrorNotifier struct {
|
||||
*fsnotify.Watcher
|
||||
}
|
||||
|
||||
func (n *testErrorNotifier) NewWatcher() (*fsnotify.Watcher, error) {
|
||||
return nil, errIntentional
|
||||
}
|
||||
|
||||
var (
|
||||
mockDeploy pkgwatcher.DeployFunc
|
||||
mockErrorDeploy pkgwatcher.DeployFunc
|
||||
errNotifier = &testErrorNotifier{}
|
||||
okNotifier = ¬ifier{}
|
||||
)
|
||||
|
||||
var (
|
||||
mockDeploy pkg.DeployFunc
|
||||
mockErrorDeploy pkg.DeployFunc
|
||||
errIntentional = errors.New("intentional error")
|
||||
binaryPath = ""
|
||||
scriptPath = ""
|
||||
executionMaxTimeout = time.Second * 2
|
||||
config *cfg.Config
|
||||
cfg *config.Config
|
||||
events = []fsnotify.Event{
|
||||
{
|
||||
Name: "test event",
|
||||
@@ -32,7 +46,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
func TestMain(t *testing.M) {
|
||||
mockDeploy = func(binaryPath, scriptPath string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -40,8 +54,16 @@ func init() {
|
||||
mockErrorDeploy = func(binaryPath, scriptPath string) error {
|
||||
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(false)
|
||||
}
|
||||
|
||||
func sendTestEvents(w *watcher) {
|
||||
@@ -50,33 +72,47 @@ func sendTestEvents(w *watcher) {
|
||||
}
|
||||
}
|
||||
|
||||
func getNewWatcher() *watcher {
|
||||
return NewWatcher(mockDeploy)
|
||||
func newWatcher() *watcher {
|
||||
return NewWatcher(okNotifier, mockDeploy)
|
||||
}
|
||||
|
||||
func getNewWatcherWithError() *watcher {
|
||||
return NewWatcher(mockErrorDeploy)
|
||||
func newWatcherWithDeployError() *watcher {
|
||||
return NewWatcher(okNotifier, mockErrorDeploy)
|
||||
}
|
||||
|
||||
func newWatcherWithCtorError() *watcher {
|
||||
return NewWatcher(errNotifier, mockDeploy)
|
||||
}
|
||||
|
||||
func Test_NewNotifier(t *testing.T) {
|
||||
LoadConfig(t)
|
||||
require.NotNil(t, NewNotifier())
|
||||
}
|
||||
|
||||
func Test_NewWatcher(t *testing.T) {
|
||||
w := getNewWatcher()
|
||||
w := newWatcher()
|
||||
require.NotNil(t, w)
|
||||
}
|
||||
|
||||
func Test_ErrorNewWatcher(t *testing.T) {
|
||||
w := newWatcherWithCtorError()
|
||||
require.Nil(t, w)
|
||||
}
|
||||
|
||||
func Test_Close(t *testing.T) {
|
||||
w := getNewWatcher()
|
||||
w := newWatcher()
|
||||
err := w.Close()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_Monitor(t *testing.T) {
|
||||
w := getNewWatcher()
|
||||
err := w.Monitor(config.TestFileToWatchPath)
|
||||
w := newWatcher()
|
||||
err := w.Monitor(cfg.FileToWatchPath)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_ListenSuccess(t *testing.T) {
|
||||
w := getNewWatcher()
|
||||
w := newWatcher()
|
||||
ctx, errors := listenWithSendEvents(w)
|
||||
|
||||
for {
|
||||
@@ -91,7 +127,7 @@ func Test_ListenSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_ListenError(t *testing.T) {
|
||||
w := getNewWatcherWithError()
|
||||
w := newWatcherWithDeployError()
|
||||
ctx, errors := listenWithSendEvents(w)
|
||||
|
||||
for {
|
||||
@@ -107,7 +143,7 @@ func Test_ListenError(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_ListenErrorChanClose(t *testing.T) {
|
||||
w := getNewWatcher()
|
||||
w := newWatcher()
|
||||
ctx, errors := listenWithSendEvents(w)
|
||||
close(w.fswatcher.Events)
|
||||
for {
|
||||
|
||||
27
kit/config/config.go
Normal file
27
kit/config/config.go
Normal 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
|
||||
}
|
||||
42
main.go
42
main.go
@@ -6,18 +6,24 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"gitea.urkob.com/urko/git-webhook-ci/cfg"
|
||||
"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 watcherIface pkgwatcher.WatcherIface
|
||||
var (
|
||||
watcherIface pkg.WatcherIface
|
||||
notifierIface pkg.NotifyIface
|
||||
)
|
||||
|
||||
func main() {
|
||||
isProd := os.Getenv("ENV") == "prod"
|
||||
config := cfg.NewConfig(isProd)
|
||||
config, err := config.LoadConfig("./configs/app.yaml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
watcherIface = watcher.NewWatcher(pkgwatcher.Deploy)
|
||||
notifierIface = watcher.NewNotifier()
|
||||
watcherIface = watcher.NewWatcher(notifierIface, pkg.Deploy)
|
||||
|
||||
defer func() {
|
||||
if err := watcherIface.Close(); err != nil {
|
||||
@@ -35,21 +41,15 @@ func main() {
|
||||
// Handle termination on ctrl+signalChan
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
go func(errors chan error) {
|
||||
for {
|
||||
select {
|
||||
case <-signalChan:
|
||||
os.Exit(1)
|
||||
case err := <-errors:
|
||||
if err != nil {
|
||||
log.Fatalf("watcherIface.Monitor: %s\n", err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-signalChan:
|
||||
os.Exit(1)
|
||||
case err := <-errors:
|
||||
if err != nil {
|
||||
log.Printf("watcherIface.Monitor: %s\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}(errors)
|
||||
|
||||
// TODO: Improve this: Block main goroutine forever.
|
||||
<-make(chan struct{})
|
||||
}
|
||||
}
|
||||
|
||||
2
pkg/testdata/test-script.sh
vendored
Normal file
2
pkg/testdata/test-script.sh
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
echo "deploy script has been called"
|
||||
@@ -1,12 +1,18 @@
|
||||
package watcher
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
type NotifyIface interface {
|
||||
NewWatcher() (*fsnotify.Watcher, error)
|
||||
}
|
||||
|
||||
type WatcherIface interface {
|
||||
Monitor(path string) error
|
||||
Listen(binaryPath, scriptPath string, outputErr chan<- error)
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
echo "hello"
|
||||
@@ -1,4 +1,4 @@
|
||||
package watcher
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
const (
|
||||
binaryPath = "/bin/bash"
|
||||
scriptPath = "./test-script.sh"
|
||||
scriptPath = "testdata/test-script.sh"
|
||||
)
|
||||
|
||||
func TestDeploy(t *testing.T) {
|
||||
Reference in New Issue
Block a user