- write to db new ticket;

- fixed telegram bot init function with telegram options;
This commit is contained in:
naudachu 2023-11-01 14:03:01 +05:00
parent 0785ebf4df
commit 310a3d9f55
17 changed files with 312 additions and 60 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.vscode/ .vscode/
**/**/*.env **/**/*.env
docker/**

View File

@ -1,29 +1,37 @@
package controller package controller
import ( import (
"context"
"fmt" "fmt"
"log"
"strings" "strings"
"sync" "sync"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
"ticket-pimp/internal/services" "ticket-pimp/internal/services"
db "ticket-pimp/internal/storage/db/tickets"
"time"
"github.com/jackc/pgx/v5/pgtype"
) )
type WorkflowController struct { type WorkflowController struct {
iGit services.IGit iGit services.IGit
iCloud services.ICloud iCloud services.ICloud
iCoda services.ICoda iCoda services.ICoda
db *db.Queries
} }
func NewWorkflowController( func NewWorkflowController(
git services.IGit, git services.IGit,
cloud services.ICloud, cloud services.ICloud,
coda services.ICoda, coda services.ICoda,
db *db.Queries,
) *WorkflowController { ) *WorkflowController {
return &WorkflowController{ return &WorkflowController{
iGit: git, iGit: git,
iCloud: cloud, iCloud: cloud,
iCoda: coda, iCoda: coda,
db: db,
} }
} }
@ -79,6 +87,19 @@ func (wc *WorkflowController) Workflow(name, key, id string) (string, error) {
} else { } else {
cloudResult = cloud.PrivateURL cloudResult = cloud.PrivateURL
} }
ctx := context.TODO()
insertedTicket, err := wc.db.CreateTicket(ctx, db.CreateTicketParams{
Key: pgtype.Text{String: appKey, Valid: true},
ProjectGit: pgtype.Text{String: gitResult, Valid: true},
BuildGit: pgtype.Text{String: gitBuildResult, Valid: true},
Folder: pgtype.Text{String: cloudResult, Valid: true},
CreatedAt: pgtype.Timestamptz{Time: time.Now(), InfinityModifier: 0, Valid: true},
})
if err != nil {
log.Fatal(err)
}
log.Print(insertedTicket)
wc.iCoda.CreateApp(domain.CodaApplication{ wc.iCoda.CreateApp(domain.CodaApplication{
ID: appKey, ID: appKey,

View File

@ -3,6 +3,7 @@ package handler
import ( import (
"ticket-pimp/bot/controller" "ticket-pimp/bot/controller"
"ticket-pimp/internal/services" "ticket-pimp/internal/services"
db "ticket-pimp/internal/storage/db/tickets"
) )
type Handler struct { type Handler struct {
@ -12,18 +13,21 @@ type Handler struct {
coda services.ICoda coda services.ICoda
key string key string
id string id string
db *db.Queries
} }
func NewHandler( func NewHandler(
git services.IGit, git services.IGit,
cloud services.ICloud, cloud services.ICloud,
coda services.ICoda, coda services.ICoda,
db *db.Queries,
) *Handler { ) *Handler {
return &Handler{ return &Handler{
workflow: controller.NewWorkflowController(git, cloud, coda), workflow: controller.NewWorkflowController(git, cloud, coda, db),
git: git, git: git,
cloud: cloud, cloud: cloud,
coda: coda, coda: coda,
db: db,
} }
} }

View File

@ -9,8 +9,11 @@ import (
"syscall" "syscall"
"ticket-pimp/bot/handler" "ticket-pimp/bot/handler"
discordbot "ticket-pimp/discord-bot" discordbot "ticket-pimp/discord-bot"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services" "ticket-pimp/internal/services"
db "ticket-pimp/internal/storage/db/tickets"
"github.com/jackc/pgx/v5"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/mr-linch/go-tg" "github.com/mr-linch/go-tg"
"github.com/mr-linch/go-tg/tgb" "github.com/mr-linch/go-tg/tgb"
@ -18,34 +21,92 @@ import (
func main() { func main() {
log.Print("started") log.Print("started")
env("develop.env") config := env("develop.env")
run(config)
}
if err := runDiscrodBot(); err != nil { func run(conf domain.Config) {
log.Fatal(fmt.Errorf("discord bot cannot be runned: %v", err)) ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM)
}
ctx := context.Background()
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt, os.Kill, syscall.SIGTERM)
defer cancel() defer cancel()
if err := runTgBot(ctx); err != nil { conn, err := pgx.Connect(
fmt.Println(err) ctx,
fmt.Sprintf(
"postgresql://%s:%s@%s:%s/%s",
conf.DB.User,
conf.DB.Pass,
conf.DB.Host,
conf.DB.Port,
conf.DB.Name,
))
if err != nil {
log.Fatalf("DB connection failed: %v", err)
}
defer conn.Close(ctx)
opts := TelegramOptions{
ticketsRepo: db.New(conn),
gitService: services.NewGit(conf.Git),
cloudService: services.NewCloud(conf.Cloud),
coda: services.NewCodaClient(conf.Coda),
appConfig: &conf,
}
go func() {
if err := runDiscrodBot(conf); err != nil {
log.Fatalf("discord bot cannot be runned: %v", err)
}
}()
if err := runTgBot(ctx, opts); err != nil {
log.Fatalf("telegram bot cannot be runned: %v", err)
defer os.Exit(1) defer os.Exit(1)
} }
} }
// env // env
// env function reads provided file and setup envirmental variables; // env function reads provided file and setup envirmental variables;
func env(envFilePath string) { func env(envFilePath string) domain.Config {
err := godotenv.Load(envFilePath) err := godotenv.Load(envFilePath)
if err != nil { if err != nil {
log.Fatal("Error while loading env file") log.Fatal("Error while loading env file")
} }
return domain.Config{
Git: domain.GitConfig{
BaseUrl: os.Getenv("GIT_BASE_URL"),
Token: os.Getenv("GIT_TOKEN"),
User: os.Getenv("GIT_USER"),
},
Cloud: domain.CloudConfig{
BaseUrl: os.Getenv("CLOUD_BASE_URL"),
User: os.Getenv("CLOUD_USER"),
Pass: os.Getenv("CLOUD_PASS"),
RootDir: os.Getenv("ROOTDIR"),
},
Coda: domain.CodaConfig{
Farm: os.Getenv("CODA_TOKEN1"),
Develop: os.Getenv("CODA_TOKEN2"),
},
DB: domain.DBConfig{
Host: os.Getenv("DB_HOST"),
Port: os.Getenv("DB_PORT"),
Name: os.Getenv("DB_NAME"),
User: os.Getenv("DB_USER"),
Pass: os.Getenv("DB_PASS"),
SslMode: os.Getenv("SSLMODE"),
},
Telegram: domain.TelegramConfig{
Token: os.Getenv("TG_API"),
},
Discord: domain.DiscordConfig{
Token: os.Getenv("DISCORD_TOKEN"),
},
}
} }
func runDiscrodBot() error { func runDiscrodBot(conf domain.Config) error {
token := os.Getenv("DISCORD_TOKEN") token := conf.Discord.Token
dbot, err := discordbot.NewDiscordBot(token) dbot, err := discordbot.NewDiscordBot(token)
if err != nil { if err != nil {
@ -81,34 +142,29 @@ func runDiscrodBot() error {
return nil return nil
} }
type TelegramOptions struct {
ticketsRepo *db.Queries
gitService *services.Git
cloudService *services.Cloud
coda *services.Coda
appConfig *domain.Config
}
// runTgBot ... // runTgBot ...
// ..function creates new Telegram BOT instance // ..function creates new Telegram BOT instance
// ..throw env variables through bot's handlers // ..throw env variables through bot's handlers
// ..setup tg bot router; // ..setup tg bot router;
// and finally returns tgb.Poller // and finally returns tgb.Poller
func runTgBot(ctx context.Context) error { func runTgBot(ctx context.Context, opts TelegramOptions) error {
client := tg.New(os.Getenv("TG_API")) log.Print("Start telegram bot init..")
client := tg.New(opts.appConfig.Telegram.Token)
gitService := services.NewGit(
os.Getenv("GIT_BASE_URL"),
os.Getenv("GIT_TOKEN"),
)
cloudService := services.NewCloud(
os.Getenv("CLOUD_BASE_URL"),
os.Getenv("CLOUD_USER"),
os.Getenv("CLOUD_PASS"),
)
coda := services.NewCodaClient(
os.Getenv("CODA_TOKEN1"),
)
h := handler.NewHandler( h := handler.NewHandler(
gitService, opts.gitService,
cloudService, opts.cloudService,
coda, opts.coda,
opts.ticketsRepo,
) )
router := tgb.NewRouter(). router := tgb.NewRouter().

View File

@ -98,3 +98,61 @@ func CreateRepoHandler(repoNameMinLength int) CommandHandler {
}, },
} }
} }
func CreateTicketHandler(repoNameMinLength int) CommandHandler {
return CommandHandler{
Command: discordgo.ApplicationCommand{
Name: "new",
Description: "Create new development ticket",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "project_name",
Description: "Temporary project name",
Required: true,
MinLength: &repoNameMinLength,
},
},
},
Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
// Access options in the order provided by the user.
options := i.ApplicationCommandData().Options
// Or convert the slice into a map
optionMap := make(map[string]*discordgo.ApplicationCommandInteractionDataOption, len(options))
for _, opt := range options {
optionMap[opt.Name] = opt
}
// This example stores the provided arguments in an []interface{}
// which will be used to format the bot's response
margs := make([]interface{}, 0, len(options))
msgformat := "You learned how to use command options! " +
"Take a look at the value(s) you entered:\n"
if option, ok := optionMap["repo_type"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())
msgformat += "> string-option: %s\n"
}
if option, ok := optionMap["repo_name"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())
msgformat += "> string-option: %s\n"
}
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
// Ignore type for now, they will be discussed in "responses"
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf(
msgformat,
margs...,
),
},
})
},
}
}

3
go.mod
View File

@ -5,6 +5,7 @@ go 1.20
require ( require (
github.com/bwmarrin/discordgo v0.27.1 github.com/bwmarrin/discordgo v0.27.1
github.com/imroc/req/v3 v3.35.2 github.com/imroc/req/v3 v3.35.2
github.com/jackc/pgx v3.6.2+incompatible
github.com/jackc/pgx/v5 v5.4.3 github.com/jackc/pgx/v5 v5.4.3
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/mr-linch/go-tg v0.9.1 github.com/mr-linch/go-tg v0.9.1
@ -19,7 +20,9 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/onsi/ginkgo/v2 v2.10.0 // indirect github.com/onsi/ginkgo/v2 v2.10.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect github.com/quic-go/qtls-go1-20 v0.2.2 // indirect

8
go.sum
View File

@ -27,15 +27,21 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mr-linch/go-tg v0.9.1 h1:4KNe7zwFG6svgM9w6pIcH3R7QWa6hIK8tCisQiFRCpU= github.com/mr-linch/go-tg v0.9.1 h1:4KNe7zwFG6svgM9w6pIcH3R7QWa6hIK8tCisQiFRCpU=
github.com/mr-linch/go-tg v0.9.1/go.mod h1:276w69YW4pEo3ZYta+LQe4v/ut2w2h1ksP4ziBWkK98= github.com/mr-linch/go-tg v0.9.1/go.mod h1:276w69YW4pEo3ZYta+LQe4v/ut2w2h1ksP4ziBWkK98=
github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs= github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE= github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@ -48,6 +54,7 @@ github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62po
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g= github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -101,3 +108,4 @@ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

45
internal/domain/config.go Normal file
View File

@ -0,0 +1,45 @@
package domain
type Config struct {
Git GitConfig
Cloud CloudConfig
Coda CodaConfig
DB DBConfig
Telegram TelegramConfig
Discord DiscordConfig
}
type GitConfig struct {
BaseUrl string
Token string
User string
}
type CloudConfig struct {
BaseUrl string
User string
Pass string
RootDir string
}
type CodaConfig struct {
Farm string
Develop string
}
type DBConfig struct {
Host string
Port string
Name string
User string
Pass string
SslMode string
}
type TelegramConfig struct {
Token string
}
type DiscordConfig struct {
Token string
}

View File

@ -2,7 +2,6 @@ package services
import ( import (
"fmt" "fmt"
"os"
"strconv" "strconv"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
"ticket-pimp/internal/helpers" "ticket-pimp/internal/helpers"
@ -11,29 +10,31 @@ import (
type Cloud struct { type Cloud struct {
*CommonClient *CommonClient
Config domain.CloudConfig
} }
type ICloud interface { type ICloud interface {
CreateFolder(name string) (*domain.Folder, error) CreateFolder(name string) (*domain.Folder, error)
} }
func NewCloud(base, user, pass string) *Cloud { func NewCloud(conf domain.CloudConfig) *Cloud {
client := NewClient(). client := NewClient().
SetTimeout(5*time.Second). SetTimeout(5*time.Second).
SetCommonBasicAuth(user, pass). SetCommonBasicAuth(conf.User, conf.Pass).
SetBaseURL(base) SetBaseURL(conf.BaseUrl)
return &Cloud{ return &Cloud{
CommonClient: &CommonClient{ CommonClient: &CommonClient{
client, client,
}, },
Config: conf,
} }
} }
func (c *Cloud) CreateFolder(name string) (*domain.Folder, error) { func (c *Cloud) CreateFolder(name string) (*domain.Folder, error) {
rootDir := os.Getenv("ROOTDIR") rootDir := c.Config.RootDir
user := os.Getenv("CLOUD_USER") user := c.Config.User
davPath := "/remote.php/dav/files/" davPath := "/remote.php/dav/files/"
parentPath := "/apps/files/?dir=" parentPath := "/apps/files/?dir="

View File

@ -3,7 +3,6 @@ package services
import ( import (
"fmt" "fmt"
"log" "log"
"os"
"ticket-pimp/internal/domain" "ticket-pimp/internal/domain"
"time" "time"
@ -12,6 +11,7 @@ import (
type Coda struct { type Coda struct {
*CommonClient *CommonClient
Config domain.CodaConfig
} }
type ICoda interface { type ICoda interface {
@ -21,17 +21,18 @@ type ICoda interface {
GetRowLink(id string) (string, error) GetRowLink(id string) (string, error)
} }
func NewCodaClient(token string) *Coda { func NewCodaClient(conf domain.CodaConfig) *Coda {
client := NewClient(). client := NewClient().
SetTimeout(15 * time.Second). SetTimeout(15 * time.Second).
SetCommonBearerAuthToken(token). SetCommonBearerAuthToken(conf.Farm).
SetBaseURL("https://coda.io/apis/v1") SetBaseURL("https://coda.io/apis/v1")
return &Coda{ return &Coda{
CommonClient: &CommonClient{ CommonClient: &CommonClient{
client, client,
}, },
Config: conf,
} }
} }
@ -57,7 +58,7 @@ func (c *Coda) CreateApp(task domain.CodaApplication) {
resp, _ := c.R(). resp, _ := c.R().
SetBody(task). SetBody(task).
SetContentType("application/json"). SetContentType("application/json").
SetBearerAuthToken(os.Getenv("CODA_TOKEN2")). SetBearerAuthToken(c.Config.Develop).
Post("/docs/Ic3IZpQ3Wk/hooks/automation/grid-auto-NlUwM7F7Cr") Post("/docs/Ic3IZpQ3Wk/hooks/automation/grid-auto-NlUwM7F7Cr")
fmt.Print(resp) fmt.Print(resp)

View File

@ -15,10 +15,10 @@ type IGit interface {
CreateRepo(name string) (*domain.Git, error) CreateRepo(name string) (*domain.Git, error)
} }
func NewGit(base, token string) *Git { func NewGit(conf domain.GitConfig) *Git {
headers := map[string]string{ headers := map[string]string{
"Accept": "application/vnd.github+json", "Accept": "application/vnd.github+json",
"Authorization": "Token " + token, "Authorization": "Token " + conf.Token,
"X-GitHub-Api-Version": "2022-11-28", "X-GitHub-Api-Version": "2022-11-28",
"Content-Type": "application/json", "Content-Type": "application/json",
} }
@ -26,7 +26,7 @@ func NewGit(base, token string) *Git {
client := NewClient(). client := NewClient().
SetTimeout(5 * time.Second). SetTimeout(5 * time.Second).
SetCommonHeaders(headers). SetCommonHeaders(headers).
SetBaseURL(base) SetBaseURL(conf.BaseUrl)
return &Git{ return &Git{
CommonClient: &CommonClient{client}, CommonClient: &CommonClient{client},

View File

@ -2,7 +2,7 @@
// versions: // versions:
// sqlc v1.23.0 // sqlc v1.23.0
package store_tickets package db
import ( import (
"context" "context"

View File

@ -2,7 +2,7 @@
// versions: // versions:
// sqlc v1.23.0 // sqlc v1.23.0
package store_tickets package db
import ( import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"

View File

@ -3,7 +3,7 @@
// sqlc v1.23.0 // sqlc v1.23.0
// source: tickets.sql // source: tickets.sql
package store_tickets package db
import ( import (
"context" "context"
@ -11,6 +11,45 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
const createTicket = `-- name: CreateTicket :one
INSERT INTO tickets (
key, project_git, build_git, folder, created_at
) VALUES (
$1, $2, $3, $4, $5
)
RETURNING id, key, project_git, build_git, folder, created_at, deleted_at, updated_at
`
type CreateTicketParams struct {
Key pgtype.Text
ProjectGit pgtype.Text
BuildGit pgtype.Text
Folder pgtype.Text
CreatedAt pgtype.Timestamptz
}
func (q *Queries) CreateTicket(ctx context.Context, arg CreateTicketParams) (Ticket, error) {
row := q.db.QueryRow(ctx, createTicket,
arg.Key,
arg.ProjectGit,
arg.BuildGit,
arg.Folder,
arg.CreatedAt,
)
var i Ticket
err := row.Scan(
&i.ID,
&i.Key,
&i.ProjectGit,
&i.BuildGit,
&i.Folder,
&i.CreatedAt,
&i.DeletedAt,
&i.UpdatedAt,
)
return i, err
}
const deleteTicketByID = `-- name: DeleteTicketByID :exec const deleteTicketByID = `-- name: DeleteTicketByID :exec
UPDATE tickets SET deleted_at = current_timestamp WHERE id = $1 UPDATE tickets SET deleted_at = current_timestamp WHERE id = $1
` `

View File

@ -5,6 +5,6 @@ sql:
schema: "migrate" schema: "migrate"
gen: gen:
go: go:
package: "store_tickets" package: "db"
sql_package: "pgx/v5" sql_package: "pgx/v5"
out: "store_tickets" out: "db/tickets"

View File

@ -1,3 +1,11 @@
-- name: CreateTicket :one
INSERT INTO tickets (
key, project_git, build_git, folder, created_at
) VALUES (
$1, $2, $3, $4, $5
)
RETURNING *;
-- name: ListTickets :many -- name: ListTickets :many
SELECT * FROM tickets WHERE deleted_at IS NULL; SELECT * FROM tickets WHERE deleted_at IS NULL;

View File

@ -25,14 +25,13 @@ sql-migrate up
# To-do P1: # To-do P1:
- [x] Выбирать проект в YouTrack по имени во время flow, а не по ID - [ ] Сделать нормальный Gracefull ShutDown с потоками и всей хернёй
- [x] Делать запросы в Git, ownCloud параллельно;
- [x] Сохранять правильную ссылку на Git;
- [x] Сохранять правильную ссылку на GitBuild;
- [x] Сделать бота в Telegram;
# To-do P2*: # To-do P2*:
- [ ] Нормальное сообщение об ошибке с созданием репо с уже существующим именем;
- [ ] Отказ от инициализации бота (автоинкремент ключа по данным базы?)
- [ ] В уведомлении об успешном создании сообщать всю инфу: - [ ] В уведомлении об успешном создании сообщать всю инфу:
- git; - git;
- git-build url + ssh url; - git-build url + ssh url;
@ -44,5 +43,13 @@ sql-migrate up
- [ ] Складывать в описание репозитория ссылку на тикет; - [ ] Складывать в описание репозитория ссылку на тикет;
- [ ] Сделать базулю с достойными пользователями; - [ ] Сделать базулю с достойными пользователями;
# Готово:
- [x] Выбирать проект в YouTrack по имени во время flow, а не по ID
- [x] Делать запросы в Git, ownCloud параллельно;
- [x] Сохранять правильную ссылку на Git;
- [x] Сохранять правильную ссылку на GitBuild;
- [x] Сделать бота в Telegram;
- [x] Run bot on docker scratch: https://github.com/jeremyhuiskamp/golang-docker-scratch/blob/main/README.mdа - [x] Run bot on docker scratch: https://github.com/jeremyhuiskamp/golang-docker-scratch/blob/main/README.mdа
- [x] Сохранять короткую ссылку на графику; - [x] Сохранять короткую ссылку на графику;