Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 111 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,120 @@ Simply create a configuration file to define multiple services and databases to

#### Currently supports

## Monitoring
- HTTP - Headers and all that
- Postgresql
- MySQL
- MariaDB
- MSSQL
- Redis

## Deployment


Deployment options:
- [Dockerfile](https://github.com/wavezync/pulse-bridge/blob/main/Dockerfile) – Self-hosted container registry or Docker Hub image
- Kubernetes

### 💻 Deploy locally (Build from source)

```bash
git clone https://github.com/wavezync/pulse-bridge.git
cd pulse-bridge
go run .
```

### 🐳 Deploy with Docker

```bash
docker pull ghcr.io/wavezync/pulsebridge:latest
docker run -d -p 8080:8080 ghcr.io/wavezync/pulsebridge:latest
```

Update the [config.yml](https://github.com/wavezync/pulse-bridge/blob/main/config.yml) in the project root to add your services and databases. Then rebuild the binary or Docker image and run it.

### 🚢 Deploy with Kubernetes

There are many ways to deploy Pulse Bridge on Kubernetes. Below is a simple example using a Deployment, Service, and ConfigMap.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pulse-bridge
spec:
replicas: 1
selector:
matchLabels:
app: pulse-bridge
template:
metadata:
labels:
app: pulse-bridge
spec:
containers:
- name: pulse-bridge
image: wavezync/pulse-bridge:latest # Replace with your image if needed (recommended)
ports:
- containerPort: 8080
env:
- name: PULSE_BRIDGE_CONFIG
value: "/config/config.yml"
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: pulse-bridge-config
---
apiVersion: v1
kind: Service
metadata:
name: pulse-bridge
spec:
selector:
app: pulse-bridge
ports:
- protocol: TCP
port: 8080
targetPort: 8080
---
apiVersion: v1
kind: ConfigMap
metadata:
name: pulse-bridge-config
data:
config.yml: |
# Paste your Pulse Bridge YAML config here. See the guide below for configuration details.
```


### Environment Configuration

1. .env file:

A .env file is **optional** but can be configured:

```bash
PULSE_BRIDGE_CONFIG=mycustomconfig.yml # Sets the custom configuration file path, defaults to config.yml
HOST=0.0.0.0 # Defaults to 0.0.0.0
PORT=8080 # Defaults to 8080
```

2. CLI arguments:

```bash
pb --config=mycustomconfig.yml --port=8080 --host=0.0.0.0
```

> **Note:** CLI arguments take priority over `.env` file settings.
CLI > .env



## Configuration
## Usage

### Configuring your services

The configuration file is a YAML file where you can define the services and databases you want to monitor.

Expand Down Expand Up @@ -95,7 +202,8 @@ monitors:
query: "SELECT 1"
```

## Monitoring
### Monitoring


You can check the status of your service from the pulse bridge API at the routes:

Expand Down
15 changes: 12 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package cmd

import (
"fmt"
"wavezync/pulse-bridge/cmd/pulsebridge"
"wavezync/pulse-bridge/internal/env"
"wavezync/pulse-bridge/internal/version"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
Expand All @@ -16,10 +18,16 @@ var (
)

var rootCmd = &cobra.Command{
Use: "pulsebridge",
Short: "pulsebridge is a powerful uptime monitoring tool",
Long: `pulsebridge exposes internal service status via HTTP, enabling seamless integration with external monitoring tools like Atlassian Statuspage.`,
Use: "pulsebridge",
Short: "pulsebridge is a powerful uptime monitoring tool",
Long: `pulsebridge exposes internal service status via HTTP, enabling seamless integration with external monitoring tools like Atlassian Statuspage.`,
RunE: func(cmd *cobra.Command, args []string) error {
versionFlag, _ := cmd.Flags().GetBool("version")
if versionFlag {
fmt.Println(version.GetVersionWithBuildInfo())
return nil
}

envConfig := env.Init()

if cmd.Flags().Changed("config") {
Expand All @@ -40,6 +48,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&configPath, "config", "config.yml", "Path to configuration file")
rootCmd.PersistentFlags().StringVar(&host, "host", "0.0.0.0", "Host address to bind the server")
rootCmd.PersistentFlags().IntVar(&port, "port", 8080, "Port to run the server")
rootCmd.PersistentFlags().BoolP("version", "v", false, "Print the version and exit")
}

func Execute() {
Expand Down
103 changes: 103 additions & 0 deletions internal/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package version

import (
"fmt"
"runtime"
"runtime/debug"
"strings"
)

var (
version string
tag string
commit string
dirty bool
)

func init() {
// Always attempt to get build info from the Go runtime, regardless of build type.
if info, ok := debug.ReadBuildInfo(); ok {
if version == "" {
// If version wasn't set via ldflags, try to get it from VCS info
version = getVersionFromVCS(info)
}
commit = getCommit(info)
dirty = getDirty(info)
}

// Fallback version if nothing else is available
if version == "" {
version = "dev"
}
}

func getVersionFromVCS(info *debug.BuildInfo) string {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
// Use commit hash as version if no proper version is available
if len(setting.Value) >= 7 {
return "dev-" + setting.Value[:7]
}
}
}
return ""
}

func getDirty(info *debug.BuildInfo) bool {
for _, setting := range info.Settings {
if setting.Key == "vcs.modified" {
return setting.Value == "true"
}
}
return false
}

func getCommit(info *debug.BuildInfo) string {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
return setting.Value[:7]
}
}
return ""
}

// GetVersion returns the version of pulsebridge. This should be injected at build time
// using: -ldflags="-X 'wavezync/pulse-bridge/internal/version.version=vX.X.X'".
// If not provided, it will attempt to derive a version from VCS info.
func GetVersion() string {
return version
}

// GetVersionWithBuildInfo returns detailed version information including
// commit hash, dirty status, and Go version. This will work when built
// within a Git checkout.
func GetVersionWithBuildInfo() string {
var parts []string

// Add the main version
parts = append(parts, fmt.Sprintf("Version: %s", version))

// Add build metadata
var buildMetadata []string
if tag != "" {
buildMetadata = append(buildMetadata, tag)
}
if commit != "" {
buildMetadata = append(buildMetadata, commit)
}
if dirty {
buildMetadata = append(buildMetadata, "dirty")
}

if len(buildMetadata) > 0 {
parts = append(parts, fmt.Sprintf("Build: %s", strings.Join(buildMetadata, ".")))
}

// Add Go version
parts = append(parts, fmt.Sprintf("Go: %s", runtime.Version()))

// Add architecture
parts = append(parts, fmt.Sprintf("Platform: %s/%s", runtime.GOOS, runtime.GOARCH))

return strings.Join(parts, "\n")
}