feat: bring repo up to REPO_POLICIES standards #6
@@ -64,6 +64,6 @@ USER webhooker
|
|||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/.well-known/healthcheck.json || exit 1
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/.well-known/healthcheck || exit 1
|
||||||
|
|
||||||
CMD ["./webhooker"]
|
CMD ["./webhooker"]
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -66,6 +66,39 @@ application lifecycle. It uses `log/slog` for structured logging, GORM
|
|||||||
for database access, and SQLite (via `modernc.org/sqlite`, pure Go, no
|
for database access, and SQLite (via `modernc.org/sqlite`, pure Go, no
|
||||||
CGO) for storage. HTTP routing uses chi.
|
CGO) for storage. HTTP routing uses chi.
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
|
||||||
|
Global rate limiting middleware (e.g. per-IP throttling applied at the
|
||||||
|
router level) must **not** apply to webhook receiver endpoints
|
||||||
|
(`/webhook/{uuid}`). Webhook endpoints receive automated traffic from
|
||||||
|
external services at unpredictable rates, and blanket rate limits would
|
||||||
|
cause legitimate webhook deliveries to be dropped.
|
||||||
|
|
||||||
|
Instead, each webhook endpoint has its own individually configurable rate
|
||||||
|
limit, applied within the webhook handler itself. By default, no rate
|
||||||
|
limit is applied — webhook endpoints accept traffic as fast as it arrives.
|
||||||
|
Rate limits can be configured on a per-webhook basis in the application
|
||||||
|
when needed (e.g. to protect against a misbehaving sender).
|
||||||
|
|
||||||
|
### Database Architecture
|
||||||
|
|
||||||
|
webhooker uses separate SQLite database files rather than a single
|
||||||
|
monolithic database:
|
||||||
|
|
||||||
|
- **Main application database** — Stores application configuration and
|
||||||
|
all standard webapp data: users, sessions, API keys, and global
|
||||||
|
settings.
|
||||||
|
- **Per-processor databases** — Each processor (working name — a better
|
||||||
|
term is needed) gets its own dedicated SQLite database file containing:
|
||||||
|
input logs, processor logs, and all output queues for that specific
|
||||||
|
processor.
|
||||||
|
|
||||||
|
This separation provides several benefits: processor databases can be
|
||||||
|
independently backed up, rotated, or archived; a high-volume processor
|
||||||
|
won't cause lock contention or bloat affecting the main application; and
|
||||||
|
individual processor data can be cleanly deleted when a processor is
|
||||||
|
removed.
|
||||||
|
|
||||||
### Package Layout
|
### Package Layout
|
||||||
|
|
||||||
All application code lives under `internal/` to prevent external imports.
|
All application code lives under `internal/` to prevent external imports.
|
||||||
@@ -98,7 +131,7 @@ The main entry point is `cmd/webhooker/main.go`.
|
|||||||
### API Endpoints
|
### API Endpoints
|
||||||
|
|
||||||
- `GET /` — Web UI index page
|
- `GET /` — Web UI index page
|
||||||
- `GET /.well-known/healthcheck.json` — Health check with uptime, version
|
- `GET /.well-known/healthcheck` — Health check with uptime, version
|
||||||
- `GET /s/*` — Static file serving (CSS, JS)
|
- `GET /s/*` — Static file serving (CSS, JS)
|
||||||
- `GET /metrics` — Prometheus metrics (requires basic auth)
|
- `GET /metrics` — Prometheus metrics (requires basic auth)
|
||||||
- `POST /webhook/{uuid}` — Webhook receiver endpoint
|
- `POST /webhook/{uuid}` — Webhook receiver endpoint
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/handlers"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/healthcheck"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/middleware"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/server"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/session"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/handlers"
|
||||||
|
"sneak.berlin/go/webhooker/internal/healthcheck"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
"sneak.berlin/go/webhooker/internal/middleware"
|
||||||
|
"sneak.berlin/go/webhooker/internal/server"
|
||||||
|
"sneak.berlin/go/webhooker/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Build-time variables set via -ldflags.
|
// Build-time variables set via -ldflags.
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -1,11 +1,10 @@
|
|||||||
module git.eeqj.de/sneak/webhooker
|
module sneak.berlin/go/webhooker
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
toolchain go1.24.1
|
toolchain go1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.eeqj.de/sneak/webhooker/pkg/config v0.0.0-00010101000000-000000000000
|
|
||||||
github.com/99designs/basicauth-go v0.0.0-20230316000542-bf6f9cbbf0f8
|
github.com/99designs/basicauth-go v0.0.0-20230316000542-bf6f9cbbf0f8
|
||||||
github.com/getsentry/sentry-go v0.25.0
|
github.com/getsentry/sentry-go v0.25.0
|
||||||
github.com/go-chi/chi v1.5.5
|
github.com/go-chi/chi v1.5.5
|
||||||
@@ -22,6 +21,7 @@ require (
|
|||||||
gorm.io/driver/sqlite v1.5.4
|
gorm.io/driver/sqlite v1.5.4
|
||||||
gorm.io/gorm v1.25.5
|
gorm.io/gorm v1.25.5
|
||||||
modernc.org/sqlite v1.28.0
|
modernc.org/sqlite v1.28.0
|
||||||
|
sneak.berlin/go/webhooker/pkg/config v0.0.0-00010101000000-000000000000
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -85,4 +85,4 @@ require (
|
|||||||
modernc.org/token v1.0.1 // indirect
|
modernc.org/token v1.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace git.eeqj.de/sneak/webhooker/pkg/config => ./pkg/config
|
replace sneak.berlin/go/webhooker/pkg/config => ./pkg/config
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
pkgconfig "git.eeqj.de/sneak/webhooker/pkg/config"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
pkgconfig "sneak.berlin/go/webhooker/pkg/config"
|
||||||
|
|
||||||
// spooky action at a distance!
|
// spooky action at a distance!
|
||||||
// this populates the environment
|
// this populates the environment
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
pkgconfig "git.eeqj.de/sneak/webhooker/pkg/config"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"go.uber.org/fx/fxtest"
|
"go.uber.org/fx/fxtest"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
pkgconfig "sneak.berlin/go/webhooker/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// createTestConfig creates a test configuration file in memory
|
// createTestConfig creates a test configuration file in memory
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
_ "modernc.org/sqlite" // Pure Go SQLite driver
|
_ "modernc.org/sqlite" // Pure Go SQLite driver
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:revive // DatabaseParams is a standard fx naming convention
|
// nolint:revive // DatabaseParams is a standard fx naming convention
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
pkgconfig "git.eeqj.de/sneak/webhooker/pkg/config"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/fx/fxtest"
|
"go.uber.org/fx/fxtest"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
pkgconfig "sneak.berlin/go/webhooker/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDatabaseConnection(t *testing.T) {
|
func TestDatabaseConnection(t *testing.T) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleLoginPage returns a handler for the login page (GET)
|
// HandleLoginPage returns a handler for the login page (GET)
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/healthcheck"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/session"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/healthcheck"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
"sneak.berlin/go/webhooker/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:revive // HandlersParams is a standard fx naming convention
|
// nolint:revive // HandlersParams is a standard fx naming convention
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/healthcheck"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/session"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
"go.uber.org/fx/fxtest"
|
"go.uber.org/fx/fxtest"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/healthcheck"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
"sneak.berlin/go/webhooker/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHandleIndex(t *testing.T) {
|
func TestHandleIndex(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexResponse struct {
|
type IndexResponse struct {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/database"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:revive // HealthcheckParams is a standard fx naming convention
|
// nolint:revive // HealthcheckParams is a standard fx naming convention
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:revive // LoggerParams is a standard fx naming convention
|
// nolint:revive // LoggerParams is a standard fx naming convention
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package logger
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"go.uber.org/fx/fxtest"
|
"go.uber.org/fx/fxtest"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
basicauth "github.com/99designs/basicauth-go"
|
basicauth "github.com/99designs/basicauth-go"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/go-chi/cors"
|
"github.com/go-chi/cors"
|
||||||
@@ -16,6 +13,9 @@ import (
|
|||||||
ghmm "github.com/slok/go-http-metrics/middleware"
|
ghmm "github.com/slok/go-http-metrics/middleware"
|
||||||
"github.com/slok/go-http-metrics/middleware/std"
|
"github.com/slok/go-http-metrics/middleware/std"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:revive // MiddlewareParams is a standard fx naming convention
|
// nolint:revive // MiddlewareParams is a standard fx naming convention
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/static"
|
|
||||||
sentryhttp "github.com/getsentry/sentry-go/http"
|
sentryhttp "github.com/getsentry/sentry-go/http"
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
"sneak.berlin/go/webhooker/static"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) SetupRoutes() {
|
func (s *Server) SetupRoutes() {
|
||||||
@@ -63,7 +63,7 @@ func (s *Server) SetupRoutes() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
s.router.Get(
|
s.router.Get(
|
||||||
"/.well-known/healthcheck.json",
|
"/.well-known/healthcheck",
|
||||||
s.h.HandleHealthCheck(),
|
s.h.HandleHealthCheck(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/handlers"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/middleware"
|
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/globals"
|
||||||
|
"sneak.berlin/go/webhooker/internal/handlers"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
|
"sneak.berlin/go/webhooker/internal/middleware"
|
||||||
|
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/config"
|
|
||||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
|
"sneak.berlin/go/webhooker/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import "git.eeqj.de/sneak/webhooker/pkg/config"
|
// import "sneak.berlin/go/webhooker/pkg/config"
|
||||||
//
|
//
|
||||||
// // Set the environment explicitly
|
// // Set the environment explicitly
|
||||||
// config.SetEnvironment("prod")
|
// config.SetEnvironment("prod")
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/pkg/config"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
"sneak.berlin/go/webhooker/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExampleSetFs demonstrates how to use an in-memory filesystem for testing
|
// ExampleSetFs demonstrates how to use an in-memory filesystem for testing
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/webhooker/pkg/config"
|
"sneak.berlin/go/webhooker/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example() {
|
func Example() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module git.eeqj.de/sneak/webhooker/pkg/config
|
module sneak.berlin/go/webhooker/pkg/config
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user