Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
56d1aaf
chore!: added otlp tracing supporting
breadrock1 Sep 22, 2025
d20bdf0
chore: go mod tody
breadrock1 Sep 22, 2025
3f6a021
chore: added new env variables
breadrock1 Sep 22, 2025
b1e2b3f
chore: impled tracing chain for interfaces
breadrock1 Sep 23, 2025
2e63a1a
chore: moved tracing to application layer
breadrock1 Sep 23, 2025
dc12679
chore: updated swagger + added /api/v1
breadrock1 Sep 23, 2025
8dd3783
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Sep 26, 2025
f9fa142
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Sep 26, 2025
b415783
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Oct 8, 2025
810d005
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Oct 20, 2025
de4a901
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Nov 4, 2025
ad84b8c
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Nov 22, 2025
382bd26
chore: removed servers from swagger
breadrock1 Nov 27, 2025
a25b383
chore: added new TODO
breadrock1 Nov 27, 2025
4f5f64c
chore: updated swagger docs after all changes
breadrock1 Nov 27, 2025
055ca57
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Dec 25, 2025
5537175
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Dec 30, 2025
a9bc2fa
Merge branch 'master' of github.com:breadrock1/watchtower
breadrock1 Jan 13, 2026
50be558
chore: updated routes and swagger docs
breadrock1 Feb 13, 2026
86d0fc9
chore: refactored configs
breadrock1 Mar 13, 2026
e1c27c7
chore: updated env vars
breadrock1 Mar 13, 2026
6b2eb93
chore: migrate to fiber from echo
breadrock1 Mar 13, 2026
9a68aeb
chore: replaced flag from config to dotenv enabling
breadrock1 Mar 13, 2026
22baba5
chore: updated swagger docs after all changes
breadrock1 Mar 13, 2026
42841e3
merge: local changes for internal
breadrock1 Mar 13, 2026
62b5935
chore: added new mocks into integration tests
breadrock1 Mar 13, 2026
b227dd5
chore: added app server test env
breadrock1 Mar 13, 2026
13f798d
chore: some changes
breadrock1 Mar 13, 2026
75d9e47
chore: impled news bucket and task routes tests
breadrock1 Mar 13, 2026
3d9a0b7
fix: lint warnings
breadrock1 Mar 13, 2026
c7581a8
chore: updated tracer collecting
breadrock1 Mar 15, 2026
c88c6d0
chore: updated tracer and logger mw
breadrock1 Mar 16, 2026
24cae11
chore: updated tracer and logger mw
breadrock1 Mar 16, 2026
f0210c1
fix: makefile launching binary
breadrock1 Mar 17, 2026
ea3946e
fix: config parsing
breadrock1 Mar 17, 2026
e675dcb
feature: impled creating and deleting folder into cloud
breadrock1 Mar 17, 2026
bbaba2d
chore: updated tests after all changes
breadrock1 Mar 17, 2026
d26e09a
chore: updated swagger docs after all changes
breadrock1 Mar 17, 2026
85a6607
chore: added missing URIs filtering
breadrock1 Mar 17, 2026
662ce0f
fix: linter warnings
breadrock1 Mar 27, 2026
d5200b8
chore: impled graceful shutdown
breadrock1 Mar 30, 2026
c8ce98b
chore: added custom prometheus metrics
breadrock1 Mar 31, 2026
3b4e6f2
chore: combined copying and moving objects to common route
breadrock1 Mar 31, 2026
7c6a73d
chore: updated object storage mock
breadrock1 Mar 31, 2026
01fc6e6
chore: added first part of tests
breadrock1 Mar 31, 2026
236302f
chore: updated mod file
breadrock1 Mar 31, 2026
d6a0c81
fix: tests
breadrock1 Mar 31, 2026
d2de4e8
chore: added additional configs path searching
breadrock1 Mar 31, 2026
1f8a876
chore: updated golang version to 1.26
breadrock1 Mar 31, 2026
16880d7
chore: returned back golang version to 1.26
breadrock1 Mar 31, 2026
7338e22
fix: redis unmarshal native
breadrock1 Mar 31, 2026
0ba20de
chore: updated golang lint version to latest
breadrock1 Mar 31, 2026
dec1e16
chore: updated golang lint version to latest
breadrock1 Mar 31, 2026
edd6543
fix: lint warnings
breadrock1 Mar 31, 2026
aca6844
fix: lint warnings
breadrock1 Mar 31, 2026
0f683a4
chore: added drone ci config file
breadrock1 Mar 31, 2026
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
195 changes: 195 additions & 0 deletions .drone/drone.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
kind: pipeline
type: docker
name: watchtower-pr

trigger:
event:
- pull_request
actions:
- synchronized

environment:
GO_VERSION: 1.25

services:
- name: redis
image: redis:alpine

- name: rabbitmq
image: rabbitmq:4-management

- name: minio
image: minio/minio
commands:
- minio server /data
environment:
MINIO_ROOT_USER: "minio-root"
MINIO_ROOT_PASSWORD: "minio-root"

steps:
- name: cache-built-go
image: drillster/drone-volume-cache
settings:
restore: true
mount:
- /usr/local/go
- /drone/src
volumes:
- name: go-targets
path: /cache

- name: build
image: golang:1.25
depends_on:
- cache-built-go
commands:
- go build watchtower/cmd/watchtower
volumes:
- name: go-targets
path: /cache

- name: lint
image: golang:1.25
depends_on:
- build
commands:
- go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
- golangci-lint run ./...
volumes:
- name: go-targets
path: /cache

- name: test
image: golang:1.25
depends_on:
- build
commands:
- sleep 15
- curl -v -u guest:guest -K /drone/src/tests/config/rmq/headers.conf --data-binary '@/drone/src/tests/config/rmq/definitions.json' http://rabbitmq:15672/api/definitions
- sleep 10
- go test watchtower/tests
volumes:
- name: go-targets
path: /cache

volumes:
- name: go-targets
temp: {}


# On merged pull request to main branch or created release branch
---
kind: pipeline
type: docker
name: watchtower-merged

trigger:
event:
- push
branch:
- main
- master
- release/*

environment:
GO_VERSION: 1.25

services:
- name: redis
image: redis:alpine

- name: rabbitmq
image: rabbitmq:4-management

- name: minio
image: minio/minio
commands:
- minio server /data
environment:
MINIO_ROOT_USER: "minio-root"
MINIO_ROOT_PASSWORD: "minio-root"

steps:
- name: cache-built-go
image: drillster/drone-volume-cache
settings:
restore: true
mount:
- /usr/local/go
- /drone/src
volumes:
- name: go-targets
path: /cache

- name: build
image: golang:1.25
depends_on:
- cache-built-go
commands:
- go build watchtower/cmd/watchtower
volumes:
- name: go-targets
path: /cache

- name: lint
image: golang:1.25
depends_on:
- build
commands:
- go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
- golangci-lint run ./...
volumes:
- name: go-targets
path: /cache

- name: test
image: golang:1.25
depends_on:
- build
commands:
- sleep 15
- curl -v -u guest:guest -K /drone/src/tests/config/rmq/headers.conf --data-binary '@/drone/src/tests/config/rmq/definitions.json' http://rabbitmq:15672/api/definitions
- sleep 10
- go test watchtower/tests
volumes:
- name: go-targets
path: /cache

volumes:
- name: go-targets
temp: {}


# Build release on new tag creating event
---
kind: pipeline
type: docker
name: watchtower-release

trigger:
event:
- tag

environment:
REGISTRY_ADDRESS: ${REGISTRY_ADDRESS}

steps:
- name: build-and-push-docker
image: plugins/docker
settings:
repo: git.sova.local:3000/sova-core/watchtower
insecure: true
dockerfile: Dockerfile
registry: git.sova.local:5000
tags:
- ${DRONE_COMMIT_SHA:0:8}
- ${DRONE_TAG}
- latest
username:
from_secret: GITEA_USERNAME
password:
from_secret: GITEA_TOKEN

volumes:
- name: go-targets
temp: {}
6 changes: 4 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
WATCHTOWER__RUN_MODE=development

WATCHTOWER__ORCHESTRATOR__SEMAPHORE_SIZE=10

WATCHTOWER__OTLP__LOGGER__LEVEL=DEBUG
Expand Down Expand Up @@ -25,8 +27,8 @@ WATCHTOWER__TASK__QUEUE__RMQ__EXCHANGE=watchtower
WATCHTOWER__TASK__QUEUE__RMQ__ROUTING_KEY=task
WATCHTOWER__TASK__QUEUE__RMQ__QUEUE=watchtower-tasks

WATCHTOWER__TASK__PROCESSOR__DOCPARSER__ADDRESS=http://localhost:8012/api/v1
WATCHTOWER__TASK__PROCESSOR__DOCPARSER__ADDRESS=http://localhost:8012
WATCHTOWER__TASK__PROCESSOR__DOCPARSER__TIMEOUT=100s

WATCHTOWER__TASK__PROCESSOR__DOCSTORAGE__ADDRESS=http://localhost:2892/api/v1
WATCHTOWER__TASK__PROCESSOR__DOCSTORAGE__ADDRESS=http://localhost:2892
WATCHTOWER__TASK__PROCESSOR__DOCSTORAGE__TIMEOUT=100s
6 changes: 4 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ jobs:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: stable
go-version: 1.25.7
check-latest: 'false'

- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: v2.6.0
version: latest

test:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build:
go build -v -o $(SERVICE_BIN_FILE_PATH) ./cmd/watchtower

run: build
$(SERVICE_BIN_FILE_PATH) -c ./configs/config.toml
$(SERVICE_BIN_FILE_PATH) -d

test:
go test -race ./tests/...
Expand Down
142 changes: 142 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package cmd

import (
"fmt"
"log/slog"
"os"
"strings"

otlp_go "github.com/breadrock1/otlp-go/otlp"
"github.com/spf13/viper"

"watchtower/cmd/watchtower/httpserver"
"watchtower/internal/core/cloud/infrastructure/s3"
"watchtower/internal/process"
"watchtower/internal/support/task/infrastructure/docparser"
"watchtower/internal/support/task/infrastructure/docsearch"
"watchtower/internal/support/task/infrastructure/redis"
"watchtower/internal/support/task/infrastructure/rmq"
)

type Config struct {
Otlp otlp_go.OtlpConfig `mapstructure:"otlp"`
Orchestrator process.Config `mapstructure:"orchestrator"`
Server ServerConfig `mapstructure:"server"`
Storage StorageConfig `mapstructure:"storage"`
Task TaskConfig `mapstructure:"task"`
}

type ServerConfig struct {
Http httpserver.Config `mapstructure:"http"`
}

type StorageConfig struct {
S3 s3.Config `mapstructure:"s3"`
}

type TaskConfig struct {
TaskStorage TaskStorageConfig `mapstructure:"storage"`
TaskQueue TaskQueueConfig `mapstructure:"queue"`
Processor ProcessorConfig `mapstructure:"processor"`
}

type TaskStorageConfig struct {
Redis redis.Config `mapstructure:"redis"`
}

type TaskQueueConfig struct {
Rmq rmq.Config `mapstructure:"rmq"`
}

type ProcessorConfig struct {
DocParser docparser.Config `mapstructure:"docparser"`
DocStorage docsearch.Config `mapstructure:"docstorage"`
}

const (
launchModeEnvKey = "WATCHTOWER__RUN_MODE"
defaultLaunchMode = "development"
serviceEnvPrefix = "WATCHTOWER"
)

func InitConfig() (*Config, error) {
launchMode := os.Getenv(launchModeEnvKey)
if launchMode == "" {
launchMode = defaultLaunchMode
}

viperInst := viper.New()

viperInst.SetConfigName(launchMode)
viperInst.SetConfigType("toml")

viperInst.AddConfigPath(".")
viperInst.AddConfigPath("./configs")
viperInst.AddConfigPath("../configs")

if launchMode == defaultLaunchMode {
// Used to include config from integration tests
viperInst.AddConfigPath("../../configs")
}

if err := viperInst.ReadInConfig(); err != nil {
//nolint
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("config file not found, using env vars")
} else {
return nil, fmt.Errorf("error reading config file: %w", err)
}
}

setupEnv(viperInst)

config := &Config{}
if err := viperInst.Unmarshal(config); err != nil {
confErr := fmt.Errorf("failed while unmarshaling config: %w", err)
return config, confErr
}

return config, nil
}

func setupEnv(viperInst *viper.Viper) {
viperInst.AutomaticEnv()
viperInst.SetEnvPrefix(serviceEnvPrefix)
viperInst.SetEnvKeyReplacer(strings.NewReplacer(".", "__"))

//nolint
envMappings := map[string]string{
"orchestrator.semaphore_size": "ORCHESTRATOR__SEMAPHORE_SIZE",
"otlp.logger.level": "OTLP__LOGGER__LEVEL",
"otlp.logger.address": "OTLP__LOGGER__ADDRESS",
"otlp.logger.enable_loki": "OTLP__LOGGER__ENABLE_LOKI",
"otlp.tracer.address": "OTLP__TRACER__ADDRESS",
"otlp.tracer.enable_jaeger": "OTLP__TRACER__ENABLE_JAEGER",
"server.http.address": "SERVER__HTTP__ADDRESS",
"storage.s3.address": "STORAGE__S3__ADDRESS",
"storage.s3.access_id": "STORAGE__S3__ACCESS_ID",
"storage.s3.secret_key": "STORAGE__S3__SECRET_KEY",
"storage.s3.enable_ssl": "STORAGE__S3__ENABLE_SSL",
"storage.s3.token": "STORAGE__S3__TOKEN",
"task.storage.redis.address": "TASK__STORAGE__REDIS__ADDRESS",
"task.storage.redis.username": "TASK__STORAGE__REDIS__USERNAME",
"task.storage.redis.password": "TASK__STORAGE__REDIS__PASSWORD",
"task.storage.redis.expired": "TASK__STORAGE__REDIS__EXPIRED",
"task.queue.rmq.address": "TASK__QUEUE__RMQ__ADDRESS",
"task.queue.rmq.exchange": "TASK__QUEUE__RMQ__EXCHANGE",
"task.queue.rmq.routing_key": "TASK__QUEUE__RMQ__ROUTING_KEY",
"task.queue.rmq.queue": "TASK__QUEUE__RMQ__QUEUE",
"task.processor.docstorage.address": "TASK__PROCESSOR__DOCSTORAGE__ADDRESS",
"task.processor.docstorage.timeout": "TASK__PROCESSOR__DOCSTORAGE__TIMEOUT",
"task.processor.docparser.address": "TASK__PROCESSOR__DOCPARSER__ADDRESS",
"task.processor.docparser.timeout": "TASK__PROCESSOR__DOCPARSER__TIMEOUT",
}

var bindErr error
for key, value := range envMappings {
bindErr = viperInst.BindEnv(key, fmt.Sprintf("%s__%s", serviceEnvPrefix, value))
if bindErr != nil {
slog.Warn("failed to bind env var", slog.String("err", bindErr.Error()))
}
}
}
Loading
Loading