feat: implement ntfy-discord bridge in Go
Some checks failed
Build and Push / build (push) Failing after 4m36s
Build and Push / test (push) Has been cancelled

- SSE subscription to ntfy with auto-reconnect
- Discord webhook integration with embed formatting
- Priority to color mapping, tag to emoji conversion
- Native HashiCorp Vault support (Kubernetes + token auth)
- Hot reload secrets via fsnotify or Vault polling
- Prometheus metrics (/metrics endpoint)
- Health/ready endpoints for Kubernetes probes
- Comprehensive unit tests and fuzz tests
- Multi-stage Docker build (~10MB scratch image)
- CI/CD pipeline for Gitea Actions
This commit is contained in:
2026-02-02 18:13:55 -05:00
parent b325d9bfec
commit f97ad0e7cb
22 changed files with 2678 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
package vault
import (
"testing"
)
func TestConfig_Defaults(t *testing.T) {
cfg := Config{
Address: "http://vault.vault.svc.cluster.local:8200",
AuthMethod: "kubernetes",
Role: "ntfy-discord",
MountPath: "secret",
SecretPath: "ntfy-discord",
}
if cfg.Address == "" {
t.Error("Address should not be empty")
}
if cfg.AuthMethod != "kubernetes" {
t.Errorf("AuthMethod = %s, want kubernetes", cfg.AuthMethod)
}
if cfg.MountPath != "secret" {
t.Errorf("MountPath = %s, want secret", cfg.MountPath)
}
}
func TestNewClient_InvalidAddress(t *testing.T) {
cfg := Config{
Address: "not-a-valid-url",
AuthMethod: "kubernetes",
Role: "test",
MountPath: "secret",
SecretPath: "test",
}
// This should fail because there's no Kubernetes token
_, err := NewClient(cfg)
if err == nil {
t.Error("expected error for kubernetes auth without token")
}
}
func TestNewClient_TokenAuth_NoToken(t *testing.T) {
cfg := Config{
Address: "http://localhost:8200",
AuthMethod: "token",
MountPath: "secret",
SecretPath: "test",
}
// Should fail because VAULT_TOKEN is not set
_, err := NewClient(cfg)
if err == nil {
t.Error("expected error for token auth without VAULT_TOKEN")
}
}
func TestNewClient_UnsupportedAuthMethod(t *testing.T) {
cfg := Config{
Address: "http://localhost:8200",
AuthMethod: "unsupported",
MountPath: "secret",
SecretPath: "test",
}
_, err := NewClient(cfg)
if err == nil {
t.Error("expected error for unsupported auth method")
}
}
func TestClient_Close_Nil(t *testing.T) {
// Test that Close doesn't panic on a partially initialized client
c := &Client{}
// Should not panic
err := c.Close()
if err != nil {
t.Errorf("Close() error = %v", err)
}
}
func TestConfig_TokenPathDefault(t *testing.T) {
cfg := Config{
TokenPath: "",
}
// Default token path should be empty (will be set in authKubernetes)
if cfg.TokenPath != "" {
t.Errorf("TokenPath = %s, want empty", cfg.TokenPath)
}
}