Compare commits

...

15 Commits

Author SHA1 Message Date
naudachu 3af1726c1d commented out old functions 2024-04-01 13:15:23 +05:00
naudachu cb57f2e0ce removing old (possibly broken) commands; 2024-02-01 21:30:41 +05:00
naudachu b2850d668a fixed parent permission problem; 2024-02-01 21:03:08 +05:00
naudachu d599eb9825 fixed emojies bug with adding emojies to the buttons; 2024-02-01 20:55:09 +05:00
naudachu 9a1420eae0 remove logs spam 2023-12-03 17:37:15 +05:00
naudachu 40fcb5896a - fixed problem with empty project; 2023-12-03 17:02:47 +05:00
naudachu 696d0f2233 Merge branch 'dev' 2023-12-01 12:59:28 +05:00
naudachu 10ce5eeef0 - added title field to the db 2023-12-01 12:58:42 +05:00
naudachu 0776156d33 router simple groups 2023-11-27 19:05:12 +05:00
naudachu 5d6adb2a9a simple routeer finished 2023-11-27 18:18:45 +05:00
naudachu 954ee0ca5a fix prod env 2023-11-22 12:01:27 +05:00
naudachu d7f172c597 - fixed env file 2023-11-21 17:39:13 +05:00
naudachu cc7cf3ac00 d 2023-11-21 16:52:05 +05:00
naudachu 9962cb96a2 - fix branch name in a new workflow 2023-11-21 15:41:35 +05:00
naudachu 94e7949238 - fix wrong file name for docker workflow 2023-11-21 15:40:07 +05:00
9 changed files with 261 additions and 214 deletions

View File

@ -1,31 +0,0 @@
name: Build and Publish Docker Container
on:
push:
branches:
- main
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ secrets.GITHUB_USERNAME }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}/my-docker-container:latest

View File

@ -16,12 +16,12 @@ import (
) )
var ( var (
minLength int = 3 // minLength int = 3
repoType string = "repo_type" // repoType string = "repo_type"
projectRepo string = "project_repo" // projectRepo string = "project_repo"
buildRepo string = "build_repo" // buildRepo string = "build_repo"
nameOption string = "name" // nameOption string = "name"
tagsPreset = [3]discordgo.ForumTag{ tagsPreset = [3]discordgo.ForumTag{
{ {
Name: "В работе", Name: "В работе",
Moderated: true, Moderated: true,
@ -38,88 +38,89 @@ var (
EmojiName: "🚧", EmojiName: "🚧",
}, },
} }
commands = []discordgo.ApplicationCommand{
{ // commands = []discordgo.ApplicationCommand{
Name: "ping", // {
Description: "pongs in a reply", // Name: "ping",
}, // Description: "pongs in a reply",
{ // },
Name: "coda_ticket", // {
Description: "Creates ticket in Coda.io w/ provided info", // Name: "coda_ticket",
}, // Description: "Creates ticket in Coda.io w/ provided info",
{ // },
Name: "init_project", // {
Description: "Connect project with Coda ID", // Name: "init_project",
Options: []*discordgo.ApplicationCommandOption{ // Description: "Connect project with Coda ID",
{ // Options: []*discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString, // {
Name: "key", // Type: discordgo.ApplicationCommandOptionString,
Description: "Project's key from Coda.io", // Name: "key",
Required: true, // Description: "Project's key from Coda.io",
MinLength: &minLength, // Required: true,
}, // MinLength: &minLength,
}, // },
}, // },
{ // },
Name: "project", // {
Description: "Create new development ticket", // Name: "project",
Options: []*discordgo.ApplicationCommandOption{ // Description: "Create new development ticket",
{ // Options: []*discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString, // {
Name: "project_name", // Type: discordgo.ApplicationCommandOptionString,
Description: "Temporary project name", // Name: "project_name",
Required: true, // Description: "Temporary project name",
MinLength: &minLength, // Required: true,
}, // MinLength: &minLength,
}, // },
}, // },
{ // },
Name: "info", // {
Description: "Get project's info", // Name: "info",
}, // Description: "Get project's info",
{ // },
Name: "repo", // {
Description: "Creates repository of selected type. Name used for projects channels only", // Name: "repo",
Options: []*discordgo.ApplicationCommandOption{ // Description: "Creates repository of selected type. Name used for projects channels only",
{ // Options: []*discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString, // {
Name: repoType, // Type: discordgo.ApplicationCommandOptionString,
Description: "The type of repo", // Name: repoType,
Required: true, // Description: "The type of repo",
Choices: []*discordgo.ApplicationCommandOptionChoice{ // Required: true,
{ // Choices: []*discordgo.ApplicationCommandOptionChoice{
Name: "Unity project repo", // {
Value: projectRepo, // Name: "Unity project repo",
}, // Value: projectRepo,
{ // },
Name: "XCode build repo", // {
Value: buildRepo, // Name: "XCode build repo",
}, // Value: buildRepo,
}, // },
}, // },
{ // },
Type: discordgo.ApplicationCommandOptionString, // {
Name: nameOption, // Type: discordgo.ApplicationCommandOptionString,
Description: "Type the repository's name", // Name: nameOption,
Required: false, // Description: "Type the repository's name",
MinLength: &minLength, // Required: false,
}, // MinLength: &minLength,
}, // },
}, // },
{ // },
Name: "folder", // {
Description: "Command for cloud folder creation", // Name: "folder",
Options: []*discordgo.ApplicationCommandOption{ // Description: "Command for cloud folder creation",
{ // Options: []*discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString, // {
Name: nameOption, // Type: discordgo.ApplicationCommandOptionString,
Description: "Type the folder's name", // Name: nameOption,
Required: false, // Description: "Type the folder's name",
MinLength: &minLength, // Required: false,
}, // MinLength: &minLength,
}, // },
}, // },
} // },
// }
) )
func initBotWith(token string) *discordgo.Session { func initBotWith(token string) *discordgo.Session {
@ -195,20 +196,43 @@ func updateForum(conf *domain.Config, s *discordgo.Session) ([]discordgo.ForumTa
return dchan.AvailableTags, nil return dchan.AvailableTags, nil
} }
func commandRegistration(s *discordgo.Session, commands []discordgo.ApplicationCommand) []*discordgo.ApplicationCommand { // commandRegistration
log.Println("Adding commands...") // unused, cause method was deprecated;
var cmds []*discordgo.ApplicationCommand // func commandRegistration(s *discordgo.Session, commands []discordgo.ApplicationCommand) []*discordgo.ApplicationCommand {
for _, cmd := range commands { // oldCommands, err := s.ApplicationCommands(s.State.User.ID, s.State.Application.GuildID)
cmd, err := s.ApplicationCommandCreate(s.State.User.ID, "", &cmd) // if err != nil {
if err != nil { // log.Panicf("Cannot get old commands: %v", err)
log.Panicf("Cannot create '%v' command: %v", cmd.Name, err) // }
}
cmds = append(cmds, cmd)
log.Println(cmd.Name + " command added")
}
return cmds
}
// var removedCommands []string
// for _, cmd := range oldCommands {
// err := s.ApplicationCommandDelete(s.State.User.ID, s.State.Application.GuildID, cmd.ID)
// if err != nil {
// log.Printf("commands removed: %v", removedCommands)
// log.Panicf("removing old comands failed with %s command, err: %v", cmd.Name, err)
// }
// removedCommands = append(removedCommands, cmd.Name)
// }
// log.Printf("commands removed: %v", removedCommands)
// log.Println("Adding commands...")
// var cmds []*discordgo.ApplicationCommand
// for _, cmd := range commands {
// cmd, err := s.ApplicationCommandCreate(s.State.User.ID, "", &cmd)
// if err != nil {
// log.Panicf("Cannot create '%v' command: %v", cmd.Name, err)
// }
// cmds = append(cmds, cmd)
// log.Println(cmd.Name + " command added")
// }
// return cmds
// }
// Run - метод
//
// 1. Инициализирует бота Discord, создаёт некоторое подобие роутера
// 2. Объявляет доступные роутинги
// 3. Объявляет доступные для роутов хэндлеры
func Run(conf *domain.Config, opts DiscordOptions) error { func Run(conf *domain.Config, opts DiscordOptions) error {
// bot init // bot init
@ -223,23 +247,25 @@ func Run(conf *domain.Config, opts DiscordOptions) error {
r := discord_router.NewApp(s) r := discord_router.NewApp(s)
var commonMw = []discord_router.Middleware{ // Depretated
h.WithInitialResponse, // var commonMw = []discord_router.Middleware{
h.RejectPM, // h.WithInitialResponse,
} // h.RejectPM,
// }
// Handle commands // Depretated
r. // r.Use(commonMw...).
Route("ping", r.Wrapped(h.Ping, commonMw...)). // Route("ping", h.Ping).
Route("project", r.Wrapped(h.CreateProject, commonMw...)). // Route("project", h.CreateProject).
Route("info", r.Wrapped(h.ProjectInfo, commonMw...)). // Route("info", h.ProjectInfo).
Route("repo", r.Wrapped(h.CreateGit, commonMw...)). // Route("repo", h.CreateGit).
Route("folder", r.Wrapped(h.CreateFolder, commonMw...)). // Route("folder", h.CreateFolder).
Route("init_project", r.Wrapped(h.InitChannelAsProject, commonMw...)). // Route("init_project", h.InitChannelAsProject).
Route("coda_ticket", r.Wrapped(h.CreateCoda, commonMw...)) // Route("coda_ticket", h.CreateCoda)
// Handle components // and components
r. r.
/*Use().*/ // Combining into group duplicates replies
Route("task_start", h.HandleTaskButtons). Route("task_start", h.HandleTaskButtons).
Route("task_close", h.HandleTaskButtons) Route("task_close", h.HandleTaskButtons)
@ -264,7 +290,7 @@ func Run(conf *domain.Config, opts DiscordOptions) error {
h.SetAvailableTags(tags) h.SetAvailableTags(tags)
// commands registration // commands registration
cmds := commandRegistration(s, commands) // cmds := commandRegistration(s, commands)
// gracefull shutdown // gracefull shutdown
defer s.Close() defer s.Close()
@ -273,12 +299,12 @@ func Run(conf *domain.Config, opts DiscordOptions) error {
<-stop <-stop
log.Println("Graceful shutdown") log.Println("Graceful shutdown")
log.Println("Removing commands...") // log.Println("Removing commands...")
for _, h := range cmds { // for _, h := range cmds {
err := s.ApplicationCommandDelete(s.State.User.ID, "", h.ID) // err := s.ApplicationCommandDelete(s.State.User.ID, "", h.ID)
if err != nil { // if err != nil {
log.Panicf("Cannot delete '%v' command: %v", h.Name, err) // log.Panicf("Cannot delete '%v' command: %v", h.Name, err)
} // }
} // }
return nil return nil
} }

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"ticket-pimp/adapters" "ticket-pimp/adapters"
"ticket-pimp/client/discord/discord_router" router "ticket-pimp/client/discord/discord_router"
"ticket-pimp/internal/controller" "ticket-pimp/internal/controller"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
"ticket-pimp/internal/helpers" "ticket-pimp/internal/helpers"
@ -32,7 +32,7 @@ func New(
} }
} }
func (h *Handler) RejectPM(f discord_router.HandlerFunc) discord_router.HandlerFunc { func (h *Handler) RejectPM(f router.HandlerFunc) router.HandlerFunc {
return func(s *discordgo.Session, i *discordgo.InteractionCreate) { return func(s *discordgo.Session, i *discordgo.InteractionCreate) {
dchan, err := s.Channel(i.ChannelID) dchan, err := s.Channel(i.ChannelID)
@ -75,7 +75,7 @@ func respondWithReject(s *discordgo.Session, i *discordgo.InteractionCreate) {
} }
// Моментальный ответ для избежания столкновения с протуханием токена // Моментальный ответ для избежания столкновения с протуханием токена
func (h *Handler) WithInitialResponse(f discord_router.HandlerFunc) discord_router.HandlerFunc { func (h *Handler) WithInitialResponse(f router.HandlerFunc) router.HandlerFunc {
return func(s *discordgo.Session, i *discordgo.InteractionCreate) { return func(s *discordgo.Session, i *discordgo.InteractionCreate) {
initialResponse := discordgo.InteractionResponse{ initialResponse := discordgo.InteractionResponse{
@ -119,10 +119,9 @@ func (h *Handler) Ping(s *discordgo.Session, i *discordgo.InteractionCreate) {
} }
// ListenPosts // ListenPosts
/* //
..listens to new posts in specific channel // ..listens to new posts in specific channel
to act them like a task // to act them like a task
*/
func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate) { func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate) {
// Check if thread starter is not a bot, and thread started at the tasks channel; // Check if thread starter is not a bot, and thread started at the tasks channel;
@ -133,6 +132,12 @@ func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate)
// Get all messages from the channel: // Get all messages from the channel:
msgs, _ := s.ChannelMessages(th.ID, 1, "", "", "") msgs, _ := s.ChannelMessages(th.ID, 1, "", "", "")
if len(msgs) == 0 {
log.Println("msgs are empty")
s.ChannelMessageSend(th.ID, "чет пошло не так, пингани @naudachu плиз")
return
}
// Take the first one: // Take the first one:
msg, _ := s.ChannelMessage(th.ID, msgs[0].ID) msg, _ := s.ChannelMessage(th.ID, msgs[0].ID)
@ -178,12 +183,24 @@ func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate)
Label: "Start", Label: "Start",
Style: discordgo.SuccessButton, Style: discordgo.SuccessButton,
Disabled: false, Disabled: false,
Emoji: discordgo.ComponentEmoji{
Name: "🚀",
ID: "",
Animated: false,
},
URL: "",
CustomID: "task_start", CustomID: "task_start",
}, },
discordgo.Button{ discordgo.Button{
Label: "Close", Label: "Close",
Style: discordgo.DangerButton, Style: discordgo.DangerButton,
Disabled: true, Disabled: true,
Emoji: discordgo.ComponentEmoji{
Name: "🍀",
ID: "",
Animated: false,
},
URL: "",
CustomID: "task_close", CustomID: "task_close",
}, },
}, },
@ -191,7 +208,7 @@ func (h *Handler) ListenPosts(s *discordgo.Session, th *discordgo.ThreadCreate)
}, },
}) })
if err != nil { if err != nil {
log.Printf("th start message edition is not complete: %v", err) log.Printf("th start message edition is not complete: %v", err) // todo return error. Error causes panics into next method;
} }
err = h.controller.UpdateTasksMessageID(context.TODO(), taskMessage.ID, t.ID) err = h.controller.UpdateTasksMessageID(context.TODO(), taskMessage.ID, t.ID)
@ -278,6 +295,12 @@ func (h *Handler) HandleTaskButtons(s *discordgo.Session, i *discordgo.Interacti
Label: "Close", Label: "Close",
Style: discordgo.DangerButton, Style: discordgo.DangerButton,
Disabled: doneButtonIsDisabled, Disabled: doneButtonIsDisabled,
Emoji: discordgo.ComponentEmoji{
Name: "🍀",
ID: "",
Animated: false,
},
URL: "",
CustomID: "task_close", CustomID: "task_close",
}, },
}, },
@ -295,10 +318,9 @@ func (h *Handler) HandleTaskButtons(s *discordgo.Session, i *discordgo.Interacti
} }
// CreateFolder // CreateFolder
/* //
- creates project's cloud folder; // - creates project's cloud folder;
- writed folder link to db; // - writed folder link to db;
*/
func (h *Handler) CreateFolder(s *discordgo.Session, i *discordgo.InteractionCreate) { func (h *Handler) CreateFolder(s *discordgo.Session, i *discordgo.InteractionCreate) {
const ( const (
nameOption string = "folder_name" nameOption string = "folder_name"
@ -329,14 +351,14 @@ func (h *Handler) CreateFolder(s *discordgo.Session, i *discordgo.InteractionCre
// Creating request: // Creating request:
var req controller.FolderRequest var req controller.FolderRequest
name, insertedValueNotNil := optionMap[nameOption] name, insertedValueNotNil := optionMap[nameOption]
dchan, err := s.Channel(i.ChannelID) currentChannel, err := s.Channel(i.ChannelID)
if err != nil { if err != nil {
log.Printf("error while identifying channel: %v", err) log.Printf("error while identifying channel: %v", err)
} else { } else {
if dchan.ParentID == h.conf.IsProjectChannel { if currentChannel.ParentID == h.conf.IsProjectChannel {
req.ChannelID = dchan.ID req.ChannelID = currentChannel.ID
if insertedValueNotNil { if insertedValueNotNil {
req.InsertedName = name.StringValue() req.InsertedName = name.StringValue()
} }
@ -589,10 +611,16 @@ func (h *Handler) CreateProject(s *discordgo.Session, i *discordgo.InteractionCr
return return
} }
// Edit created channel: parent, err := s.Channel(h.conf.IsProjectChannel)
if err != nil {
log.Printf("get project as channel object failed: %v", err)
}
// Edit created channel (new key needed, so use to make edit after creation)
edit := discordgo.ChannelEdit{ edit := discordgo.ChannelEdit{
Name: p.Key + "-" + helpers.Cut(projectTitle), Name: p.Key + "-" + helpers.Cut(projectTitle),
ParentID: h.conf.IsProjectChannel, ParentID: h.conf.IsProjectChannel,
PermissionOverwrites: parent.PermissionOverwrites,
} }
dchan, err = s.ChannelEdit(dchan.ID, &edit) dchan, err = s.ChannelEdit(dchan.ID, &edit)

View File

@ -27,6 +27,7 @@ func (re *RouteEntry) Match(i *discordgo.InteractionCreate) bool {
type Router struct { type Router struct {
session *discordgo.Session session *discordgo.Session
routes []RouteEntry routes []RouteEntry
group []Group
} }
func NewApp(s *discordgo.Session) *Router { func NewApp(s *discordgo.Session) *Router {
@ -52,23 +53,49 @@ func (r *Router) Serve(s *discordgo.Session, i *discordgo.InteractionCreate) {
e.Handler(s, i) e.Handler(s, i)
} }
} }
//[ ] Is there something like 404?!
for _, g := range r.group {
for _, e := range g.routes {
ok := e.Match(i)
if ok {
if len(g.middleware) < 1 {
e.Handler(s, i)
}
wrapped := e.Handler
// loop in reverse to preserve middleware order
for i := len(g.middleware) - 1; i >= 0; i-- {
wrapped = g.middleware[i](wrapped)
}
wrapped(s, i)
}
}
}
} }
type Middleware func(HandlerFunc) HandlerFunc type Middleware func(HandlerFunc) HandlerFunc
func (r *Router) Wrapped(f HandlerFunc, m ...Middleware) HandlerFunc { type Group struct {
routes []RouteEntry
if len(m) < 1 { middleware []Middleware
return f }
}
func (r *Router) Use(m ...Middleware) *Group {
wrapped := f
r.group = append(r.group, Group{
// loop in reverse to preserve middleware order routes: []RouteEntry{},
for i := len(m) - 1; i >= 0; i-- { middleware: m,
wrapped = m[i](wrapped) })
}
return &r.group[len(r.group)-1]
return wrapped }
func (g *Group) Route(cmd string, handlerFunc HandlerFunc) *Group {
g.routes = append(g.routes, RouteEntry{
CommandName: cmd,
Handler: handlerFunc,
})
return g
} }

View File

@ -2,6 +2,7 @@ package controller
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
) )
@ -13,6 +14,10 @@ func (wc *WorkflowController) CreateCoda(guildID string, chanID string) (string,
return "", err return "", err
} }
if p == nil {
return "", errors.New("project wasn't found in the db")
}
requestResult, err := wc.ICoda.CreateApp(domain.CodaApplication{ requestResult, err := wc.ICoda.CreateApp(domain.CodaApplication{
ID: p.Key, ID: p.Key,
Summary: p.Name, Summary: p.Name,
@ -23,5 +28,4 @@ func (wc *WorkflowController) CreateCoda(guildID string, chanID string) (string,
}) })
return requestResult, err return requestResult, err
} }

View File

@ -11,6 +11,10 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
// Get - *not used*
//
// Достаёт запись из таблицы config
// config - ключ приложений и номер последнего созданного приложения (// todo или следующего?)
func (wc *WorkflowController) Get(ctx context.Context) (*domain.ApplicationConfig, error) { func (wc *WorkflowController) Get(ctx context.Context) (*domain.ApplicationConfig, error) {
c, err := wc.q.GetConfig(ctx) c, err := wc.q.GetConfig(ctx)
return &domain.ApplicationConfig{ return &domain.ApplicationConfig{
@ -51,7 +55,7 @@ func (wc *WorkflowController) ProjectCreate(ctx context.Context, project domain.
// Set ID from the DB raw: // Set ID from the DB raw:
project.ID = string(appconfig.TicketID.Int32) project.ID = string(appconfig.TicketID.Int32)
projectRow, err := qtx.CreateTicket(ctx, db.CreateTicketParams{ _, err = qtx.CreateTicket(ctx, db.CreateTicketParams{
Key: pgtype.Text{String: project.Key, Valid: true}, Key: pgtype.Text{String: project.Key, Valid: true},
Channelid: pgtype.Text{String: project.ChannelID, Valid: true}, Channelid: pgtype.Text{String: project.ChannelID, Valid: true},
Title: pgtype.Text{String: project.Name, Valid: true}, Title: pgtype.Text{String: project.Name, Valid: true},
@ -61,7 +65,6 @@ func (wc *WorkflowController) ProjectCreate(ctx context.Context, project domain.
return nil, err return nil, err
} else { } else {
tx.Commit(ctx) tx.Commit(ctx)
fmt.Println(projectRow)
} }
return &project, nil return &project, nil

View File

@ -12,12 +12,11 @@ import (
) )
// WriteTaskToDB // WriteTaskToDB
/* //
Makes an SQL query to create new tasks row from domain.Task entity // Makes an SQL query to create new tasks row from domain.Task entity
- Creator field: telegram nickname or Discord's Mention(); // - Creator field: telegram nickname or Discord's Mention();
- Creator link (tg ID) in telegram case; // - Creator link (tg ID) in telegram case;
- Description from telegram/discord message bodies; // - Description from telegram/discord message bodies;
*/
func (wc *WorkflowController) WriteTaskToDB(t *domain.Task) (*domain.Task, error) { func (wc *WorkflowController) WriteTaskToDB(t *domain.Task) (*domain.Task, error) {
dbtask, err := wc.q.InsertTask(context.TODO(), db.InsertTaskParams{ dbtask, err := wc.q.InsertTask(context.TODO(), db.InsertTaskParams{
Creator: pgtype.Text{String: t.Creator, Valid: true}, Creator: pgtype.Text{String: t.Creator, Valid: true},

View File

@ -76,21 +76,6 @@ func (c *Coda) CreateApp(task domain.CodaApplication) (string, error) {
return "", fmt.Errorf("unexpected coda response: %s", whResponse.ReqID) return "", fmt.Errorf("unexpected coda response: %s", whResponse.ReqID)
} }
// arr := strings.Split(whResponse.ReqID, sep)
// if arr[0] == "mutate" {
// mutate = arr[1]
// }
// mutateResponse, err := c.R().
// SetContentType("application/json").
// SetBearerAuthToken(c.Config.Develop).
// Get(fmt.Sprintf("/mutationStatus/%s", mutate))
// if err != nil {
// return "", fmt.Errorf("unable to get coda mutate result: %s", mutate)
// }
// _ = mutateResponse
return whResponse.ReqID, nil return whResponse.ReqID, nil
} }

View File

@ -1,15 +1,21 @@
# Сборка: # Сборка:
Подготовка контейнера проекта: Подготовка контейнера проекта:
1. Поменять в коде файл окружения на '.env' 1. Поменять в коде файл окружения на '.env'
2. Собрать контейнер: `docker build -t naudachu/ticket-pimp:latest --pull .` 2. Собрать контейнер: `docker build -t naudachu/pimp-containerized:latest --pull .`
3. Затолкать контейнер в docker hub: `docker push naudachu/ticket-pimp:latest` 3. Затолкать контейнер в docker hub: `docker push naudachu/pimp-containerized:latest` (надо залогинится мб `docker login -u naudachu --password-stdin`)
# Запуск контейнера на сервере: # Запуск контейнера на сервере:
1. Вытягиваем новый образ: `scp ./compose.yaml root@serverhost:~/compose.yaml` 1. Вытягиваем новый образ: `scp ./compose.yaml root@serverhost:~/compose.yaml`
2. Запуск контейнера: `docker-compose up -d` 2. Запуск контейнера: `docker-compose up -d`
# Разработка: ## Обновление кода контейнера:
1. Осуществить сборку и отправку контейнера в докерхаб
2. Зайти на боевую машину по ssh
3. Выполнить `docker pull naudachu/pimp-containerized:latest`
4. Выполнить `docker-compose up -d`
5. Подчистить старый образ через `docker rmi {image_id}`, предварительно посмотрев список образов `docker images`
# Разработка:
## Запуск вспомогательного контейнера с базой: ## Запуск вспомогательного контейнера с базой:
`docker-compose up -d` `docker-compose up -d`