diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..2d339b8 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,58 @@ +name: CI/CD Pipeline + +on: + push: + tags: + - "*" + +jobs: + release: + name: Build and Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Extract tag name + id: get-tag + run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 1.23.1 + + - name: Update version in main.go + run: | + TAG=${{ env.TAG }} + if [ -f main.go ]; then + sed -i 's/Newt version replaceme/Newt version '"$TAG"'/' main.go + echo "Updated main.go with version $TAG" + else + echo "main.go not found" + fi + + - name: Build and push Docker images + run: | + TAG=${{ env.TAG }} + make docker-build-release tag=$TAG + + - name: Build binaries + run: | + make go-build-release + + - name: Upload artifacts from /bin + uses: actions/upload-artifact@v3 + with: + name: binaries + path: bin/ diff --git a/Makefile b/Makefile index b895de1..3dbb196 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,14 @@ all: build push +docker-build-release: + @if [ -z "$(tag)" ]; then \ + echo "Error: tag is required. Usage: make build-all tag="; \ + exit 1; \ + fi + docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/newt:latest -f Dockerfile --push . + docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/newt:$(tag) -f Dockerfile --push . + build: docker build -t fosrl/newt:latest . @@ -13,12 +21,12 @@ test: local: CGO_ENABLED=0 go build -o newt -release: +go-build-release: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/newt_linux_arm64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/newt_linux_amd64 CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o bin/newt_darwin_arm64 CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o bin/newt_darwin_amd64 - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o newt_windows_amd64.bin/exe + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o bin/newt_windows_amd64.exe CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -o bin/newt_freebsd_amd64 CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -o bin/newt_freebsd_arm64 diff --git a/main.go b/main.go index bff80ac..786ecbd 100644 --- a/main.go +++ b/main.go @@ -283,17 +283,21 @@ func main() { if logLevel == "" { flag.StringVar(&logLevel, "log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)") } + + // do a --version check + version := flag.Bool("version", false, "Print the version") + flag.Parse() + if *version { + fmt.Println("Newt version replaceme") + os.Exit(0) + } + logger.Init() loggerLevel := parseLogLevel(logLevel) logger.GetLogger().SetLevel(parseLogLevel(logLevel)) - // Validate required fields - if endpoint == "" || id == "" || secret == "" { - logger.Fatal("endpoint, id, and secret are required either via CLI flags or environment variables") - } - // parse the mtu string into an int mtuInt, err = strconv.Atoi(mtu) if err != nil { diff --git a/proxy/manager.go b/proxy/manager.go index 92218fa..b6c521b 100644 --- a/proxy/manager.go +++ b/proxy/manager.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "net" + "strings" "sync" "time" @@ -279,6 +280,22 @@ func (pm *ProxyManager) handleUDPProxy(conn *gonet.UDPConn, targetAddr string) { if !pm.running { return } + + // Check for connection closed conditions + if err == io.EOF || strings.Contains(err.Error(), "use of closed network connection") { + logger.Info("UDP connection closed, stopping proxy handler") + + // Clean up existing client connections + clientsMutex.Lock() + for _, targetConn := range clientConns { + targetConn.Close() + } + clientConns = nil + clientsMutex.Unlock() + + return + } + logger.Error("Error reading UDP packet: %v", err) continue } diff --git a/websocket/client.go b/websocket/client.go index 879a109..8a7d3f9 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -305,6 +305,10 @@ func (c *Client) establishConnection() error { go c.readPump() if c.onConnect != nil { + err := c.saveConfig() + if err != nil { + logger.Error("Failed to save config: %v", err) + } if err := c.onConnect(); err != nil { logger.Error("OnConnect callback failed: %v", err) }