epic: add more formatters, logger
This commit is contained in:
parent
3438637c1e
commit
026e981415
15 changed files with 435 additions and 92 deletions
41
.golangci.yml
Normal file
41
.golangci.yml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
exclude-dirs:
|
||||||
|
- "vendor"
|
||||||
|
exclue-files:
|
||||||
|
- ".*\\.gen\\.go"
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
errcheck:
|
||||||
|
exclude-functions:
|
||||||
|
- github.com/go-chi/render.Render
|
||||||
|
goimports:
|
||||||
|
local-prefixes: "code.alt-gnome.ru/aides-infra/aides-repo-api"
|
||||||
|
gofmt:
|
||||||
|
simplify: true
|
||||||
|
gofumpt:
|
||||||
|
extra-rules: true
|
||||||
|
forbidigo:
|
||||||
|
forbid:
|
||||||
|
- p: ^fmt\.Print.*$
|
||||||
|
msg: Do not commit print statements.
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
- gocritic
|
||||||
|
- govet
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- errcheck
|
||||||
|
- typecheck
|
||||||
|
- forbidigo
|
||||||
|
|
||||||
|
issues:
|
||||||
|
fix: true
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- errcheck
|
21
Makefile
21
Makefile
|
@ -1,14 +1,13 @@
|
||||||
GOFUMPT := go run mvdan.cc/gofumpt@v0.7.0
|
GOLANGCI_LINT := go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
|
||||||
GOIMPORTS := go run golang.org/x/tools/cmd/goimports@v0.28.0
|
SWAG := go run github.com/swaggo/swag/cmd/swag@v1.16.4
|
||||||
GCI := go run github.com/daixiang0/gci@v0.13.5
|
|
||||||
GOLINES := go run github.com/segmentio/golines@v0.12.2
|
|
||||||
|
|
||||||
format:
|
format:
|
||||||
@echo "🛠️ Format code"
|
@echo "🛠️ Format and Lint code with golangci-lint"
|
||||||
$(GOIMPORTS) -w .
|
$(GOLANGCI_LINT) run --fix
|
||||||
$(GCI) write -s standard -s default -s "prefix(code.alt-gnome.ru/aides-infra/aides-repo-api)" .
|
$(SWAG) fmt
|
||||||
$(GOLINES) -w .
|
@echo "✅ Format and Lint done."
|
||||||
$(GOFUMPT) -w .
|
|
||||||
@echo "✅ Format done."
|
|
||||||
|
|
||||||
.PHONY: format
|
swag:
|
||||||
|
$(SWAG) init -g cmd/aides-repo-api/main.go
|
||||||
|
|
||||||
|
.PHONY: format swag
|
||||||
|
|
62
docs/docs.go
62
docs/docs.go
|
@ -60,6 +60,57 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/tasks/{taskID}/upload": {
|
||||||
|
"post": {
|
||||||
|
"description": "Upload multiple files associated with a specific task ID. Each file must be less than 10MB.",
|
||||||
|
"consumes": [
|
||||||
|
"multipart/form-data"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"tasks"
|
||||||
|
],
|
||||||
|
"summary": "Upload files to a task",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Task ID",
|
||||||
|
"name": "taskID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"description": "Files to upload",
|
||||||
|
"name": "files",
|
||||||
|
"in": "formData",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful file upload",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/taskcontroller.TaskUploadResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request or File too large",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errors.ErrResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errors.ErrResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
@ -122,6 +173,17 @@ const docTemplate = `{
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"taskcontroller.TaskUploadResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"taskID": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
|
@ -49,6 +49,57 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/tasks/{taskID}/upload": {
|
||||||
|
"post": {
|
||||||
|
"description": "Upload multiple files associated with a specific task ID. Each file must be less than 10MB.",
|
||||||
|
"consumes": [
|
||||||
|
"multipart/form-data"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"tasks"
|
||||||
|
],
|
||||||
|
"summary": "Upload files to a task",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Task ID",
|
||||||
|
"name": "taskID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"description": "Files to upload",
|
||||||
|
"name": "files",
|
||||||
|
"in": "formData",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful file upload",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/taskcontroller.TaskUploadResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request or File too large",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errors.ErrResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errors.ErrResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
@ -111,6 +162,17 @@
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"taskcontroller.TaskUploadResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"taskID": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,6 +43,13 @@ definitions:
|
||||||
taskID:
|
taskID:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
|
taskcontroller.TaskUploadResponse:
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
taskID:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
info:
|
info:
|
||||||
contact: {}
|
contact: {}
|
||||||
paths:
|
paths:
|
||||||
|
@ -76,4 +83,39 @@ paths:
|
||||||
summary: Create a new task
|
summary: Create a new task
|
||||||
tags:
|
tags:
|
||||||
- Tasks
|
- Tasks
|
||||||
|
/tasks/{taskID}/upload:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- multipart/form-data
|
||||||
|
description: Upload multiple files associated with a specific task ID. Each
|
||||||
|
file must be less than 10MB.
|
||||||
|
parameters:
|
||||||
|
- description: Task ID
|
||||||
|
in: path
|
||||||
|
name: taskID
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: Files to upload
|
||||||
|
in: formData
|
||||||
|
name: files
|
||||||
|
required: true
|
||||||
|
type: file
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Successful file upload
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/taskcontroller.TaskUploadResponse'
|
||||||
|
"400":
|
||||||
|
description: Bad Request or File too large
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/errors.ErrResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/errors.ErrResponse'
|
||||||
|
summary: Upload files to a task
|
||||||
|
tags:
|
||||||
|
- tasks
|
||||||
swagger: "2.0"
|
swagger: "2.0"
|
||||||
|
|
|
@ -3,16 +3,14 @@ package app
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"moul.io/zapgorm2"
|
"moul.io/zapgorm2"
|
||||||
|
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/config"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/config"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/controllers/taskcontroller"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/controllers/taskcontroller"
|
||||||
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/logger"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/models"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/models"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/router"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/router"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/services/cronservice"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/services/cronservice"
|
||||||
|
@ -21,7 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
logger *zap.Logger
|
logger *logger.ZapLogger
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
config *config.Config
|
config *config.Config
|
||||||
|
|
||||||
|
@ -49,25 +47,11 @@ func New() (*App, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) createLogger() {
|
func (app *App) createLogger() {
|
||||||
atomic := zap.NewAtomicLevel()
|
app.logger = logger.GetLogger()
|
||||||
|
|
||||||
atomic.SetLevel(zapcore.DebugLevel)
|
|
||||||
|
|
||||||
enconfig := zap.NewProductionEncoderConfig()
|
|
||||||
enconfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
|
||||||
enconfig.TimeKey = "timestamp"
|
|
||||||
|
|
||||||
logger := zap.New(zapcore.NewCore(
|
|
||||||
zapcore.NewJSONEncoder(enconfig),
|
|
||||||
zapcore.Lock(os.Stdout),
|
|
||||||
atomic,
|
|
||||||
))
|
|
||||||
|
|
||||||
app.logger = logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) createDb() {
|
func (app *App) createDb() {
|
||||||
logger := zapgorm2.New(app.logger)
|
logger := zapgorm2.New(app.logger.GetZap())
|
||||||
logger.SetAsDefault()
|
logger.SetAsDefault()
|
||||||
dsn := fmt.Sprintf(
|
dsn := fmt.Sprintf(
|
||||||
"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
||||||
|
@ -81,7 +65,10 @@ func (app *App) createDb() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
db.AutoMigrate(&models.Task{}, &models.GitRepoAltRepoTask{}, &models.RPMFile{})
|
err = db.AutoMigrate(&models.Task{}, &models.GitRepoAltRepoTask{}, &models.RPMFile{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
db.FirstOrCreate(&models.ALTRepo{
|
db.FirstOrCreate(&models.ALTRepo{
|
||||||
Name: "Sisyphus",
|
Name: "Sisyphus",
|
||||||
})
|
})
|
||||||
|
@ -127,11 +114,13 @@ func (app *App) Init() {
|
||||||
func (app *App) Run() {
|
func (app *App) Run() {
|
||||||
app.logger.Info(
|
app.logger.Info(
|
||||||
"Сервер запущен",
|
"Сервер запущен",
|
||||||
zap.Int(
|
map[string]interface{}{
|
||||||
"port",
|
"port": app.config.Port,
|
||||||
app.config.Port,
|
},
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
http.ListenAndServe(fmt.Sprintf(":%d", app.config.Port), app.router.Setup())
|
err := http.ListenAndServe(fmt.Sprintf(":%d", app.config.Port), app.router.Setup())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,18 @@ func (c *CreateTaskResponse) Render(w http.ResponseWriter, r *http.Request) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Create a new task
|
// Create a new task
|
||||||
// @Description Create a new task for a specific repository
|
//
|
||||||
// @Tags Tasks
|
// @Summary Create a new task
|
||||||
// @Accept json
|
// @Description Create a new task for a specific repository
|
||||||
// @Produce json
|
// @Tags Tasks
|
||||||
// @Param body body CreateTaskDTO true "Request body to create a task"
|
// @Accept json
|
||||||
// @Success 201 {object} CreateTaskResponse
|
// @Produce json
|
||||||
// @Failure 400 {object} errors.ErrResponse "Invalid JSON or missing required fields"
|
// @Param body body CreateTaskDTO true "Request body to create a task"
|
||||||
// @Failure 500 {object} errors.ErrResponse "Internal server error"
|
// @Success 201 {object} CreateTaskResponse
|
||||||
// @Router /tasks [post]
|
// @Failure 400 {object} errors.ErrResponse "Invalid JSON or missing required fields"
|
||||||
|
// @Failure 500 {object} errors.ErrResponse "Internal server error"
|
||||||
|
// @Router /tasks [post]
|
||||||
func (c *TaskController) Create(w http.ResponseWriter, r *http.Request) {
|
func (c *TaskController) Create(w http.ResponseWriter, r *http.Request) {
|
||||||
createTaskDto := CreateTaskDTO{}
|
createTaskDto := CreateTaskDTO{}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package taskcontroller
|
package taskcontroller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
|
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/common/errors"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/common/errors"
|
||||||
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/logger"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/services/taskservice"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/services/taskservice"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,6 +20,19 @@ func (rd *TaskUploadResponse) Render(w http.ResponseWriter, r *http.Request) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload handles file uploads for a specific task.
|
||||||
|
//
|
||||||
|
// @Summary Upload files to a task
|
||||||
|
// @Description Upload multiple files associated with a specific task ID. Each file must be less than 10MB.
|
||||||
|
// @Tags tasks
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Produce json
|
||||||
|
// @Param taskID path string true "Task ID"
|
||||||
|
// @Param files formData file true "Files to upload"
|
||||||
|
// @Success 200 {object} TaskUploadResponse "Successful file upload"
|
||||||
|
// @Failure 400 {object} errors.ErrResponse "Bad Request or File too large"
|
||||||
|
// @Failure 500 {object} errors.ErrResponse "Internal Server Error"
|
||||||
|
// @Router /tasks/{taskID}/upload [post]
|
||||||
func (c *TaskController) Upload(w http.ResponseWriter, r *http.Request) {
|
func (c *TaskController) Upload(w http.ResponseWriter, r *http.Request) {
|
||||||
taskID := chi.URLParam(r, "taskID")
|
taskID := chi.URLParam(r, "taskID")
|
||||||
if taskID == "" {
|
if taskID == "" {
|
||||||
|
@ -41,7 +54,7 @@ func (c *TaskController) Upload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
files := r.MultipartForm.File["files"]
|
files := r.MultipartForm.File["files"]
|
||||||
for _, fileHeader := range files {
|
for _, fileHeader := range files {
|
||||||
if fileHeader.Size > (1024 << 20) { // Limit each file size to 10MB
|
if fileHeader.Size > (1024 << 20) {
|
||||||
render.Render(w, r, &errors.ErrResponse{
|
render.Render(w, r, &errors.ErrResponse{
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
StatusText: "File too large",
|
StatusText: "File too large",
|
||||||
|
@ -55,7 +68,10 @@ func (c *TaskController) Upload(w http.ResponseWriter, r *http.Request) {
|
||||||
Files: files,
|
Files: files,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
log := logger.GetLogger()
|
||||||
|
log.Error("Error while upload task", map[string]interface{}{
|
||||||
|
"err": err,
|
||||||
|
})
|
||||||
render.Render(w, r, &errors.ErrResponse{
|
render.Render(w, r, &errors.ErrResponse{
|
||||||
HTTPStatusCode: http.StatusInternalServerError,
|
HTTPStatusCode: http.StatusInternalServerError,
|
||||||
StatusText: "Internal Server Error",
|
StatusText: "Internal Server Error",
|
||||||
|
|
26
internal/logger/logger.go
Normal file
26
internal/logger/logger.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *ZapLogger
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger определяет интерфейс для логгера
|
||||||
|
type Logger interface {
|
||||||
|
Debug(msg string, fields map[string]interface{})
|
||||||
|
Info(msg string, fields map[string]interface{})
|
||||||
|
Warn(msg string, fields map[string]interface{})
|
||||||
|
Error(msg string, fields map[string]interface{})
|
||||||
|
Fatal(msg string, fields map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogger() *ZapLogger {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = NewZapLogger()
|
||||||
|
})
|
||||||
|
return instance
|
||||||
|
}
|
94
internal/logger/zap_logger.go
Normal file
94
internal/logger/zap_logger.go
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZapLogger struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewZapLogger() *ZapLogger {
|
||||||
|
atomicLevel := zap.NewAtomicLevel()
|
||||||
|
atomicLevel.SetLevel(zapcore.DebugLevel)
|
||||||
|
|
||||||
|
encoderConfig := zap.NewProductionEncoderConfig()
|
||||||
|
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||||
|
encoderConfig.TimeKey = "timestamp"
|
||||||
|
|
||||||
|
core := zapcore.NewCore(
|
||||||
|
zapcore.NewJSONEncoder(encoderConfig),
|
||||||
|
zapcore.Lock(os.Stdout),
|
||||||
|
atomicLevel,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &ZapLogger{
|
||||||
|
logger: zap.New(core),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) GetZap() *zap.Logger {
|
||||||
|
return l.logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) Debug(msg string, fields ...map[string]interface{}) {
|
||||||
|
l.log(zap.DebugLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) Info(msg string, fields ...map[string]interface{}) {
|
||||||
|
l.log(zap.InfoLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) Warn(msg string, fields ...map[string]interface{}) {
|
||||||
|
l.log(zap.WarnLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) Error(msg string, fields ...map[string]interface{}) {
|
||||||
|
l.log(zap.ErrorLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) Fatal(msg string, fields ...map[string]interface{}) {
|
||||||
|
l.log(zap.FatalLevel, msg, fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ZapLogger) log(level zapcore.Level, msg string, fields ...map[string]interface{}) {
|
||||||
|
if len(fields) == 0 || fields[0] == nil {
|
||||||
|
switch level {
|
||||||
|
case zap.DebugLevel:
|
||||||
|
l.logger.Debug(msg)
|
||||||
|
case zap.InfoLevel:
|
||||||
|
l.logger.Info(msg)
|
||||||
|
case zap.WarnLevel:
|
||||||
|
l.logger.Warn(msg)
|
||||||
|
case zap.ErrorLevel:
|
||||||
|
l.logger.Error(msg)
|
||||||
|
case zap.FatalLevel:
|
||||||
|
l.logger.Fatal(msg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
zapFields := convertMapToZapFields(fields[0])
|
||||||
|
switch level {
|
||||||
|
case zap.DebugLevel:
|
||||||
|
l.logger.Debug(msg, zapFields...)
|
||||||
|
case zap.InfoLevel:
|
||||||
|
l.logger.Info(msg, zapFields...)
|
||||||
|
case zap.WarnLevel:
|
||||||
|
l.logger.Warn(msg, zapFields...)
|
||||||
|
case zap.ErrorLevel:
|
||||||
|
l.logger.Error(msg, zapFields...)
|
||||||
|
case zap.FatalLevel:
|
||||||
|
l.logger.Fatal(msg, zapFields...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertMapToZapFields(fields map[string]interface{}) []zap.Field {
|
||||||
|
zapFields := make([]zap.Field, 0, len(fields))
|
||||||
|
for key, value := range fields {
|
||||||
|
zapFields = append(zapFields, zap.Any(key, value))
|
||||||
|
}
|
||||||
|
return zapFields
|
||||||
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
package cronservice
|
package cronservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-co-op/gocron/v2"
|
"github.com/go-co-op/gocron/v2"
|
||||||
|
|
||||||
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepoService interface {
|
type RepoService interface {
|
||||||
|
@ -34,7 +35,10 @@ func (s *Service) SetupCronJobs() {
|
||||||
_, err := s.scheduler.NewJob(
|
_, err := s.scheduler.NewJob(
|
||||||
gocron.CronJob("* * * * *", false),
|
gocron.CronJob("* * * * *", false),
|
||||||
gocron.NewTask(func() {
|
gocron.NewTask(func() {
|
||||||
fmt.Println("Cron run!")
|
log := logger.GetLogger()
|
||||||
|
log.Info(
|
||||||
|
"Cron run!",
|
||||||
|
)
|
||||||
s.repoService.ForceUpdate()
|
s.repoService.ForceUpdate()
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/logger"
|
||||||
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/models"
|
"code.alt-gnome.ru/aides-infra/aides-repo-api/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ func createSymlink(target, link string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGenbasedir(repoDir, arch, repoName string) {
|
func runGenbasedir(repoDir, arch, repoName string) {
|
||||||
|
log := logger.GetLogger()
|
||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
"genbasedir",
|
"genbasedir",
|
||||||
"--bloat",
|
"--bloat",
|
||||||
|
@ -55,18 +57,30 @@ func runGenbasedir(repoDir, arch, repoName string) {
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to run genbasedir for %s: %v\n", arch, err)
|
log.Error(
|
||||||
|
"Failed to run genbasedir",
|
||||||
|
map[string]interface{}{
|
||||||
|
"arch": arch,
|
||||||
|
"error": err,
|
||||||
|
},
|
||||||
|
)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Printf("Successfully ran genbasedir for %s\n", arch)
|
log.Info("Successfully ran genbasedir", map[string]interface{}{
|
||||||
|
"arch": arch,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRepoDirs(repoDir, repoName, arch string) {
|
func createRepoDirs(repoDir, repoName, arch string) {
|
||||||
|
log := logger.GetLogger()
|
||||||
// Create the 'base' directory
|
// Create the 'base' directory
|
||||||
baseDir := path.Join(repoDir, arch, "base")
|
baseDir := path.Join(repoDir, arch, "base")
|
||||||
err := os.MkdirAll(baseDir, os.ModePerm)
|
err := os.MkdirAll(baseDir, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to create directory %s: %v\n", baseDir, err)
|
log.Error("Failed to create directory", map[string]interface{}{
|
||||||
|
"directory": baseDir,
|
||||||
|
"err": err,
|
||||||
|
})
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +88,10 @@ func createRepoDirs(repoDir, repoName, arch string) {
|
||||||
rpmsDir := path.Join(repoDir, arch, fmt.Sprintf("RPMS.%s", repoName))
|
rpmsDir := path.Join(repoDir, arch, fmt.Sprintf("RPMS.%s", repoName))
|
||||||
err = os.MkdirAll(rpmsDir, os.ModePerm)
|
err = os.MkdirAll(rpmsDir, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to create directory %s: %v\n", rpmsDir, err)
|
log.Error("Failed to create directory", map[string]interface{}{
|
||||||
|
"directory": rpmsDir,
|
||||||
|
"err": err,
|
||||||
|
})
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,10 +118,13 @@ func (s *Service) ForceUpdate() {
|
||||||
|
|
||||||
repoPath := path.Join(s.config.GetUploadDir(), "future_repo", "Sisyphus")
|
repoPath := path.Join(s.config.GetUploadDir(), "future_repo", "Sisyphus")
|
||||||
|
|
||||||
os.MkdirAll(
|
err := os.MkdirAll(
|
||||||
repoPath,
|
repoPath,
|
||||||
os.ModePerm,
|
os.ModePerm,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
repoName := "aides"
|
repoName := "aides"
|
||||||
architectures := []string{"x86_64", "noarch"}
|
architectures := []string{"x86_64", "noarch"}
|
||||||
|
@ -114,10 +134,6 @@ func (s *Service) ForceUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, el := range tasks {
|
for _, el := range tasks {
|
||||||
taskPath := path.Join(
|
|
||||||
s.config.GetUploadDir(), "tasks", strconv.FormatUint(uint64(el.ID), 10),
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, fileInfo := range el.Files {
|
for _, fileInfo := range el.Files {
|
||||||
localFilePath := path.Join(
|
localFilePath := path.Join(
|
||||||
strconv.FormatUint(uint64(el.ID), 10), fileInfo.Name,
|
strconv.FormatUint(uint64(el.ID), 10), fileInfo.Name,
|
||||||
|
@ -131,9 +147,10 @@ func (s *Service) ForceUpdate() {
|
||||||
fileInfo.Name,
|
fileInfo.Name,
|
||||||
)
|
)
|
||||||
targetPath := path.Join("../../../../tasks/", localFilePath)
|
targetPath := path.Join("../../../../tasks/", localFilePath)
|
||||||
createSymlink(targetPath, symLink)
|
err := createSymlink(targetPath, symLink)
|
||||||
|
if err != nil {
|
||||||
fmt.Println(path.Join(taskPath, fileInfo.Name))
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,17 +167,21 @@ func (s *Service) ForceUpdate() {
|
||||||
"current_task_id", gorm.Expr("last_task_id"),
|
"current_task_id", gorm.Expr("last_task_id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
os.MkdirAll(path.Join(s.config.GetUploadDir(), "repo"), os.ModePerm)
|
err = os.MkdirAll(path.Join(s.config.GetUploadDir(), "repo"), os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
aPath := path.Join(s.config.GetUploadDir(), "future_repo", "Sisyphus")
|
aPath := path.Join(s.config.GetUploadDir(), "future_repo", "Sisyphus")
|
||||||
bPath := path.Join(s.config.GetUploadDir(), "repo", "Sisyphus")
|
bPath := path.Join(s.config.GetUploadDir(), "repo", "Sisyphus")
|
||||||
cPath := path.Join(s.config.GetUploadDir(), "repo", ".Sisyphus")
|
cPath := path.Join(s.config.GetUploadDir(), "repo", ".Sisyphus")
|
||||||
|
|
||||||
if _, err := os.Stat(bPath); err == nil {
|
if _, err := os.Stat(bPath); err == nil {
|
||||||
fmt.Printf("Moving %s to %s\n", bPath, cPath)
|
|
||||||
if err := os.Rename(bPath, cPath); err != nil {
|
if err := os.Rename(bPath, cPath); err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Rename(aPath, bPath); err != nil {
|
if err := os.Rename(aPath, bPath); err != nil {
|
||||||
|
@ -168,7 +189,10 @@ func (s *Service) ForceUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.RemoveAll(cPath); err != nil {
|
if err := os.RemoveAll(cPath); err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.RemoveAll(path.Join(s.config.GetUploadDir(), "future_repo"))
|
if err := os.RemoveAll(path.Join(s.config.GetUploadDir(), "future_repo")); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (s *Service) onTaskComplete(task *models.Task) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) tasksCleanup(r *models.GitRepoAltRepoTask, N int) {
|
func (s *Service) tasksCleanup(r *models.GitRepoAltRepoTask, n int) {
|
||||||
excludedTaskIDs := []uint{}
|
excludedTaskIDs := []uint{}
|
||||||
if r.CurrentTaskID != nil {
|
if r.CurrentTaskID != nil {
|
||||||
excludedTaskIDs = append(excludedTaskIDs, *r.CurrentTaskID)
|
excludedTaskIDs = append(excludedTaskIDs, *r.CurrentTaskID)
|
||||||
|
@ -68,7 +68,7 @@ func (s *Service) tasksCleanup(r *models.GitRepoAltRepoTask, N int) {
|
||||||
Where("status = ?", models.StatusCompleted).
|
Where("status = ?", models.StatusCompleted).
|
||||||
Where("id NOT IN ?", excludedTaskIDs).
|
Where("id NOT IN ?", excludedTaskIDs).
|
||||||
Order("created_at DESC").
|
Order("created_at DESC").
|
||||||
Limit(N).
|
Limit(n).
|
||||||
Pluck("id", &lastNTaskIDs)
|
Pluck("id", &lastNTaskIDs)
|
||||||
|
|
||||||
excludedTaskIDs = append(excludedTaskIDs, lastNTaskIDs...)
|
excludedTaskIDs = append(excludedTaskIDs, lastNTaskIDs...)
|
||||||
|
|
|
@ -58,7 +58,10 @@ func (s *Service) Upload(input *TaskUploadInput) error {
|
||||||
|
|
||||||
localPath := path.Join(input.TaskID)
|
localPath := path.Join(input.TaskID)
|
||||||
taskFolderPath := path.Join(s.config.GetUploadDir(), "tasks", localPath)
|
taskFolderPath := path.Join(s.config.GetUploadDir(), "tasks", localPath)
|
||||||
os.MkdirAll(taskFolderPath, os.ModePerm)
|
err = os.MkdirAll(taskFolderPath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, fileHeader := range files {
|
for _, fileHeader := range files {
|
||||||
file, err := fileHeader.Open()
|
file, err := fileHeader.Open()
|
||||||
|
@ -121,7 +124,6 @@ func (s *Service) Upload(input *TaskUploadInput) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
task.Status = models.StatusCompleted
|
task.Status = models.StatusCompleted
|
||||||
s.onTaskComplete(&task)
|
|
||||||
|
|
||||||
return nil
|
return s.onTaskComplete(&task)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package taskservice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createSymlink(target, link string) error {
|
|
||||||
if _, err := os.Lstat(link); err == nil {
|
|
||||||
if err := os.Remove(link); err != nil {
|
|
||||||
return fmt.Errorf("failed to remove existing file or symlink: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Symlink(target, link); err != nil {
|
|
||||||
return fmt.Errorf("failed to create symlink: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue