diff --git a/bot/controller/controller.go b/bot/controller/controller.go index ecc0ebf..e7202f1 100644 --- a/bot/controller/controller.go +++ b/bot/controller/controller.go @@ -1,46 +1,211 @@ package controller import ( + "encoding/csv" + "fmt" "io" - d "ticket-pimp/bot/domain" - "ticket-pimp/bot/ext" + "strings" + "sync" + "ticket-pimp/internal/domain" + "ticket-pimp/internal/services" + + "github.com/imroc/req/v3" ) type WorkflowController struct { - iGit ext.IGit - iCloud ext.ICloud - iYouTrack ext.IYouTrack - additionalYT ext.IYouTrack - iCoda ext.ICoda + iGit services.IGit + iCloud services.ICloud + iYouTrack services.IYouTrack + additionalYT services.IYouTrack + iCoda services.ICoda } func NewWorkflowController( - gitBaseURL, - gitToken, - cloudBaseURL, - cloudAuthUser, - cloudAuthPass, - ytBaseURL, - ytToken, - addYTURL, - addYTToken string, + git services.IGit, + cloud services.ICloud, + devyt services.IYouTrack, + farmyt services.IYouTrack, + coda services.ICoda, ) *WorkflowController { return &WorkflowController{ - iGit: ext.NewGit(gitBaseURL, gitToken), - iCloud: ext.NewCloud(cloudBaseURL, cloudAuthUser, cloudAuthPass), - iYouTrack: ext.NewYT(ytBaseURL, ytToken), - additionalYT: ext.NewYT(addYTURL, addYTToken), - iCoda: ext.NewCodaClient(), + iGit: git, + iCloud: cloud, + iYouTrack: devyt, + additionalYT: farmyt, + iCoda: coda, } } type IWorkflowController interface { Workflow(name string) (string, error) - CreateRepo(name string) (*d.Git, error) - CreateFolder(name string) (*d.Folder, error) NewTask(summ, desc, c, cLink string) *Task CreateTask(t *Task) (*Task, error) - ThrowConversions(f io.ReadCloser, appID string, token string) *d.ConversionLog + ThrowConversions(f io.ReadCloser, appID string, token string) *domain.ConversionLog +} + +func (wc *WorkflowController) ThrowConversions(f io.ReadCloser, appID string, token string) *domain.ConversionLog { + c := req.C(). + SetBaseURL("https://graph.facebook.com/v15.0/"). + DevMode() + + const currency = "USD" + + r := csv.NewReader(f) + + conversionLog := domain.ConversionLog{} + + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + return nil + } + + advertiser := strings.Split(record[0], ";")[0] + + params := map[string]string{ + "advertiser_id": advertiser, + "event": "CUSTOM_APP_EVENTS", + "application_tracking_enabled": "1", + "advertiser_tracking_enabled": "1", + "custom_events": `[{"_eventName":"fb_mobile_purchase"}]`, + } + + res, _ := c.R(). + SetQueryString(token). + SetQueryParams(params). + Post(appID + "/activities") + + if res.Err != nil { + conversionLog.Advertiser = append(conversionLog.Advertiser, advertiser) + } + + } + + return &conversionLog +} + +type Task struct { + Summary string + Description string + Creator string + CreatorLink string + + Key string + URL string +} + +func (wc *WorkflowController) NewTask(summ, desc, c, cLink string) *Task { + return &Task{ + Summary: summ, + Description: desc, + Creator: c, + CreatorLink: cLink, + } +} + +func (wc *WorkflowController) CreateTask(t *Task) (*Task, error) { + + yt := wc.additionalYT + + projectID, err := yt.GetProjectIDByName("E") + if err != nil { + return nil, err + } + + t.Description += fmt.Sprintf("\n\n Created by: [%s](%s)", t.Creator, t.CreatorLink) + + issue, err := yt.CreateIssue(projectID, t.Creator+" | "+t.Summary, t.Description) + if err != nil { + return nil, err + } + + t.Key = issue.Key + t.URL = fmt.Sprintf("https://mobmarlerino.youtrack.cloud/issue/%s", issue.Key) + + return t, nil +} + +func (wc *WorkflowController) Workflow(name string) (string, error) { + // coda := wc.iCoda + + yt := wc.iYouTrack + + projectID, err := yt.GetProjectIDByName("tst") + if err != nil { + return "", err + } + + // Create an issue at the available project with the provided name + issue, err := yt.CreateIssue(projectID, name, "") + if err != nil { + return "", err + } + + if issue != nil { + var ( + git, gitBuild *domain.Git + cloud *domain.Folder + ) + + var wg sync.WaitGroup + wg.Add(3) + + go func(ref **domain.Git) { + defer wg.Done() + *ref, _ = wc.iGit.CreateRepo(issue.Key) + }(&git) + + go func(ref **domain.Git) { + defer wg.Done() + *ref, _ = wc.iGit.CreateRepo(issue.Key + "-build") + }(&gitBuild) + + go func(ref **domain.Folder) { + defer wg.Done() + *ref, _ = wc.iCloud.CreateFolder(issue.Key + " - " + issue.Summary) + }(&cloud) + + wg.Wait() + + var gitResult, gitBuildResult, cloudResult string + + if git == nil { + gitResult = "cannot create git" + } else { + gitResult = git.HtmlUrl + } + + if gitBuild == nil { + gitBuildResult = "cannot create git" + } else { + gitBuildResult = fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName) + } + + if cloud == nil { + cloudResult = "cannot create folder" + } else { + cloudResult = cloud.PrivateURL + } + + wc.iCoda.CreateTask(domain.CodaIssue{ + ID: issue.Key, + Summary: strings.TrimSpace(name), + Git: gitResult, + GitBuild: gitBuildResult, + Folder: cloudResult, + }) + + yt.UpdateIssue( + issue, + cloudResult, + gitResult, + gitBuildResult, + ) + } + return issue.Key, nil } diff --git a/bot/controller/conversions.go b/bot/controller/conversions.go deleted file mode 100644 index b8abf2a..0000000 --- a/bot/controller/conversions.go +++ /dev/null @@ -1,55 +0,0 @@ -package controller - -import ( - "encoding/csv" - "io" - "strings" - - "github.com/imroc/req/v3" - - d "ticket-pimp/bot/domain" -) - -func (wc *WorkflowController) ThrowConversions(f io.ReadCloser, appID string, token string) *d.ConversionLog { - c := req.C(). - SetBaseURL("https://graph.facebook.com/v15.0/"). - DevMode() - - const currency = "USD" - - r := csv.NewReader(f) - - conversionLog := d.ConversionLog{} - - for { - record, err := r.Read() - if err == io.EOF { - break - } - if err != nil { - return nil - } - - advertiser := strings.Split(record[0], ";")[0] - - params := map[string]string{ - "advertiser_id": advertiser, - "event": "CUSTOM_APP_EVENTS", - "application_tracking_enabled": "1", - "advertiser_tracking_enabled": "1", - "custom_events": `[{"_eventName":"fb_mobile_purchase"}]`, - } - - res, _ := c.R(). - SetQueryString(token). - SetQueryParams(params). - Post(appID + "/activities") - - if res.Err != nil { - conversionLog.Advertiser = append(conversionLog.Advertiser, advertiser) - } - - } - - return &conversionLog -} diff --git a/bot/controller/conversions.js b/bot/controller/conversions.js deleted file mode 100644 index acf6ade..0000000 --- a/bot/controller/conversions.js +++ /dev/null @@ -1,33 +0,0 @@ -function myFunction() { - var sheet = SpreadsheetApp.getActiveSheet(); - var data = sheet.getDataRange().getValues(); - var a1 = data[1][1]; - var a2 = '' - var a3 = data[1][2]; - var reqUrl = data[1][3]; - var startarray = data[1][4] - - var regCount = 0; - var depCount = 0; - // reqUrl = 'https://graph.facebook.com/v15.0/841990173617973/activities?event=CUSTOM_APP_EVENTS&application_tracking_enabled=1&advertiser_tracking_enabled=1&advertiser_id=0a42bbee-c049-4180-ae3f-ce76ff33556e&841990173617973%7Cnjqit85G_uma0voikeP6eJvBiQk&custom_events=[%7B%22_eventName%22:%22fb_mobile_purchase%22%7D]' - reqUrl = reqUrl.replace('A1', a1) - reqUrl = reqUrl.replace('A3', a3) - Logger.log("urll " + reqUrl) - Logger.log("urll " + encodeURI(reqUrl).toString()) - - for (var i = startarray; i < data.length; i++) { - a2 = data[i][0] - reqUrl = reqUrl.replace('A2', a2) - - var params = { - "method": 'post' - } - var response = UrlFetchApp.fetch(encodeURI(reqUrl), params); - Logger.log(i + " " + response.getContentText() + ' ' + response.getResponseCode()); - depCount++; - - } - Logger.log('Reg Count= ' + regCount); - Logger.log('Dep Count= ' + depCount); - - } diff --git a/bot/controller/folder.go b/bot/controller/folder.go deleted file mode 100644 index c294256..0000000 --- a/bot/controller/folder.go +++ /dev/null @@ -1,14 +0,0 @@ -package controller - -import d "ticket-pimp/bot/domain" - -func (wc *WorkflowController) CreateFolder(name string) (*d.Folder, error) { - - //Create ownCloud folder w/ iCloud interface; - cloud, err := wc.iCloud.CreateFolder(name) - if cloud == nil { - return nil, err - } - - return cloud, err -} diff --git a/bot/controller/git.go b/bot/controller/git.go deleted file mode 100644 index 2113ebd..0000000 --- a/bot/controller/git.go +++ /dev/null @@ -1,19 +0,0 @@ -package controller - -import d "ticket-pimp/bot/domain" - -func (wc *WorkflowController) CreateRepo(name string) (*d.Git, error) { - //Create git repository with iGit interface; - repo, err := wc.iGit.NewRepo(name) - if err != nil { - return nil, err - } - - //Set 'apps' as collaborator to created repository; - _, err = wc.iGit.AppsAsCollaboratorTo(repo) - if err != nil { - return nil, err - } - - return repo, nil -} diff --git a/bot/controller/task.go b/bot/controller/task.go deleted file mode 100644 index cfe6e78..0000000 --- a/bot/controller/task.go +++ /dev/null @@ -1,44 +0,0 @@ -package controller - -import "fmt" - -type Task struct { - Summary string - Description string - Creator string - CreatorLink string - - Key string - URL string -} - -func (wc *WorkflowController) NewTask(summ, desc, c, cLink string) *Task { - return &Task{ - Summary: summ, - Description: desc, - Creator: c, - CreatorLink: cLink, - } -} - -func (wc *WorkflowController) CreateTask(t *Task) (*Task, error) { - - yt := wc.additionalYT - - projectID, err := yt.GetProjectIDByName("E") - if err != nil { - return nil, err - } - - t.Description += fmt.Sprintf("\n\n Created by: [%s](%s)", t.Creator, t.CreatorLink) - - issue, err := yt.CreateIssue(projectID, t.Creator+" | "+t.Summary, t.Description) - if err != nil { - return nil, err - } - - t.Key = issue.Key - t.URL = fmt.Sprintf("https://mobmarlerino.youtrack.cloud/issue/%s", issue.Key) - - return t, nil -} diff --git a/bot/controller/ticket-workflow.go b/bot/controller/ticket-workflow.go deleted file mode 100644 index fdfe5a2..0000000 --- a/bot/controller/ticket-workflow.go +++ /dev/null @@ -1,70 +0,0 @@ -package controller - -import ( - "fmt" - "sync" - "ticket-pimp/bot/domain" -) - -func (wc *WorkflowController) Workflow(name string) (string, error) { - coda := wc.iCoda - - yt := wc.iYouTrack - - projectID, err := yt.GetProjectIDByName("APP") - if err != nil { - return "", err - } - - // Create an issue at the available project with the provided name - issue, err := yt.CreateIssue(projectID, name, "") - - if err != nil { - return "", err - } - - if issue != nil { - var ( - git, gitBuild *domain.Git - cloud *domain.Folder - ) - - var wg sync.WaitGroup - wg.Add(3) - - go func(ref **domain.Git) { - defer wg.Done() - *ref, _ = wc.CreateRepo(issue.Key) - }(&git) - - go func(ref **domain.Git) { - defer wg.Done() - *ref, _ = wc.CreateRepo(issue.Key + "-build") - }(&gitBuild) - - go func(ref **domain.Folder) { - defer wg.Done() - *ref, _ = wc.CreateFolder(issue.Key + " - " + issue.Summary) - }(&cloud) - - wg.Wait() - - taskDraft := domain.CodaIssue{ - ID: issue.ID, - Summary: name, - URL: "", - Git: git.HtmlUrl, - GitBuild: fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName), - Folder: cloud.PrivateURL, - } - - coda.CreateTask(taskDraft) - - yt.UpdateIssue( - issue, - cloud.PrivateURL, - git.HtmlUrl, - fmt.Sprintf("ssh://%s/%s.git", gitBuild.SshUrl, gitBuild.FullName)) - } - return issue.Key, nil -} diff --git a/bot/domain/cloud.go b/bot/domain/cloud.go deleted file mode 100644 index 84c66b2..0000000 --- a/bot/domain/cloud.go +++ /dev/null @@ -1,7 +0,0 @@ -package domain - -type Folder struct { - Title string // k - PathTo string // /temp/k - PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333 -} diff --git a/bot/domain/coda.go b/bot/domain/coda.go deleted file mode 100644 index 361bb0d..0000000 --- a/bot/domain/coda.go +++ /dev/null @@ -1,10 +0,0 @@ -package domain - -type CodaIssue struct { - ID string `json:"id"` - Summary string `json:"summary"` - URL string `json:"url"` - Git string `json:"git"` - GitBuild string `json:"git-build"` - Folder string `json:"folder"` -} diff --git a/bot/domain/conversion.go b/bot/domain/conversion.go deleted file mode 100644 index 1931882..0000000 --- a/bot/domain/conversion.go +++ /dev/null @@ -1,5 +0,0 @@ -package domain - -type ConversionLog struct { - Advertiser []string -} diff --git a/bot/domain/git.go b/bot/domain/git.go deleted file mode 100644 index 083805b..0000000 --- a/bot/domain/git.go +++ /dev/null @@ -1,11 +0,0 @@ -package domain - -type Git struct { - Name string `json:"name"` // "poop" - FullName string `json:"full_name"` // "developer/poop" - Private bool `json:"private"` - Url string `json:"url"` // "http://localhost:8081/api/v3/repos/developer/poop" - CloneUrl string `json:"clone_url"` // "http://localhost:8081/git/developer/poop.git" - HtmlUrl string `json:"Html_url"` // "http://localhost:8081/developer/poop" - SshUrl string `json:"ssh_url"` // ?! -} diff --git a/bot/domain/task.go b/bot/domain/task.go deleted file mode 100644 index 1468249..0000000 --- a/bot/domain/task.go +++ /dev/null @@ -1,6 +0,0 @@ -package domain - -type Task struct { - Description string - URL string -} diff --git a/bot/handler/handler.go b/bot/handler/handler.go index 3a0b898..54c66b2 100644 --- a/bot/handler/handler.go +++ b/bot/handler/handler.go @@ -7,7 +7,8 @@ import ( "log" "strings" "ticket-pimp/bot/controller" - d "ticket-pimp/bot/domain" + "ticket-pimp/internal/domain" + "ticket-pimp/internal/services" "github.com/mr-linch/go-tg" "github.com/mr-linch/go-tg/tgb" @@ -15,21 +16,22 @@ import ( type Handler struct { workflow controller.IWorkflowController + git services.IGit + cloud services.ICloud } -func NewHandler(gitBaseURL, gitToken, cloudBaseURL, cloudAuthUser, cloudAuthPass, ytBaseURL, ytToken, addYTURL, addYTToken string) *Handler { +func NewHandler( + git services.IGit, + cloud services.ICloud, + devyt services.IYouTrack, + farmyt services.IYouTrack, + coda services.ICoda, +) *Handler { + return &Handler{ - workflow: controller.NewWorkflowController( - gitBaseURL, - gitToken, - cloudBaseURL, - cloudAuthUser, - cloudAuthPass, - ytBaseURL, - ytToken, - addYTURL, - addYTToken, - ), + workflow: controller.NewWorkflowController(git, cloud, devyt, farmyt, coda), + git: git, + cloud: cloud, } } @@ -46,12 +48,12 @@ type git struct { ssh string } -func newGit(d *d.Git) *git { +func newGit(domain *domain.Git) *git { return &git{ - name: d.Name, - url: d.HtmlUrl, - git: d.CloneUrl, - ssh: fmt.Sprintf("ssh://%s/%s.git", d.SshUrl, d.FullName), + name: domain.Name, + url: domain.HtmlUrl, + git: domain.CloneUrl, + ssh: fmt.Sprintf("ssh://%s/%s.git", domain.SshUrl, domain.FullName), } } @@ -74,8 +76,9 @@ func (h *Handler) NewRepoHandler(ctx context.Context, mu *tgb.MessageUpdate) err return errors.New("empty command provided") } - var g *d.Git - g, err := h.workflow.CreateRepo(str) + var g *domain.Git + + g, err := h.git.CreateRepo(str) if err != nil { return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) @@ -94,7 +97,7 @@ func (h *Handler) NewFolderHandler(ctx context.Context, mu *tgb.MessageUpdate) e return errors.New("empty command provided") } - cloud, err := h.workflow.CreateFolder(str) + cloud, err := h.cloud.CreateFolder(str) if err != nil { return mu.Answer(errorAnswer(err.Error())).ParseMode(tg.HTML).DoVoid(ctx) @@ -121,7 +124,7 @@ func errorAnswer(errorMsg string) string { ) } -func (h *Handler) NewTicketHandler(ctx context.Context, mu *tgb.MessageUpdate) error { +func (h *Handler) DevelopmentTaskHandler(ctx context.Context, mu *tgb.MessageUpdate) error { str := strings.Replace(mu.Text, "/new", "", 1) @@ -148,7 +151,7 @@ func newTicketAnswer(name string) string { ) } -func (h *Handler) NewTaskHandler(ctx context.Context, mu *tgb.MessageUpdate) error { +func (h *Handler) FarmTaskHandler(ctx context.Context, mu *tgb.MessageUpdate) error { taskText := strings.TrimSpace(strings.Replace(mu.Text, "/task", "", 1)) words := strings.Split(taskText, " ") diff --git a/bot/handler/handler_test.go b/bot/handler/handler_test.go index 79993a9..d871058 100644 --- a/bot/handler/handler_test.go +++ b/bot/handler/handler_test.go @@ -2,7 +2,7 @@ package handler import ( "testing" - "ticket-pimp/bot/domain" + "ticket-pimp/internal/domain" ) type test struct { diff --git a/cmd/dev.env b/cmd/dev.env new file mode 100644 index 0000000..76dc072 --- /dev/null +++ b/cmd/dev.env @@ -0,0 +1,23 @@ +CODA_TOKEN = 'f54477f0-98ca-4285-844f-9fa2ef34475d' +CODA_DOC = 'Ic3IZpQ3Wk' +CODA_TOKEN1 = "0d5a6853-8bb1-4208-9014-318094f5b21c" + +CLOUD_BASE_URL = 'http://localhost:8080' +CLOUD_USER = 'admin' +CLOUD_PASS = 'admin' + +ROOTDIR = "/temp/" + +GIT_BASE_URL = 'http://localhost:8081/api/v3' +GIT_TOKEN = '2dc2f4f8e938ff914d2a9e006b22e63a3b8e5561' +GIT_USER = 'developer' + +YT_URL = 'https://marlerino.youtrack.cloud/api' +YT_TOKEN = 'perm:bmF1ZGFjaHU=.NTYtMQ==.4TVHQx65u4EKnCGjadeMB1NMAmSHSL' + +YT_ADDITIONAL_URL = 'https://mobmarlerino.youtrack.cloud/api' +YT_ADDITIONAL_TOKEN = 'perm:cm9vdA==.NDktMA==.iANVnkmP4DiyFrAeaSD6SyCrEiGQzc' + +TG_API = '6002875059:AAFp1ZR9Y68oaqSL6vTNQdhrVgcM_yHouCY' + +DB_LINK = "host=localhost user=postgres password=postgres dbname=pimp port=5432 sslmode=disable" \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index 478b121..dcef9c6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -8,6 +8,7 @@ import ( "os/signal" "syscall" "ticket-pimp/bot/handler" + "ticket-pimp/internal/services" "github.com/joho/godotenv" "github.com/mr-linch/go-tg" @@ -16,7 +17,7 @@ import ( func main() { log.Print("started") - env(".env") + env("dev.env") ctx := context.Background() ctx, cancel := signal.NotifyContext(ctx, os.Interrupt, os.Kill, syscall.SIGTERM) @@ -46,24 +47,44 @@ func runBot(ctx context.Context) error { client := tg.New(os.Getenv("TG_API")) - h := handler.NewHandler( + 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"), + ) + + devYouTrackService := services.NewYT( os.Getenv("YT_URL"), os.Getenv("YT_TOKEN"), + ) + + farmYouTrackService := services.NewYT( os.Getenv("YT_ADDITIONAL_URL"), os.Getenv("YT_ADDITIONAL_TOKEN"), ) + coda := services.NewCodaClient( + os.Getenv("CODA_TOKEN1"), + ) + + h := handler.NewHandler( + gitService, + cloudService, + devYouTrackService, + farmYouTrackService, + coda, + ) router := tgb.NewRouter(). - Message(h.NewTicketHandler, tgb.TextHasPrefix("/new")). + Message(h.DevelopmentTaskHandler, tgb.TextHasPrefix("/new")). Message(h.PingHandler, tgb.Command("ping")). Message(h.NewRepoHandler, tgb.TextHasPrefix("/repo")). Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")). - Message(h.NewTaskHandler, tgb.TextHasPrefix("/task")). + Message(h.FarmTaskHandler, tgb.TextHasPrefix("/task")). Message(h.NewConversion, tgb.TextHasPrefix("/conversion")) return tgb.NewPoller( diff --git a/Dockerfile b/docker/Dockerfile similarity index 88% rename from Dockerfile rename to docker/Dockerfile index fa96389..ac82f29 100644 --- a/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ COPY . . RUN apk add git # Static build required so that we can safely copy the binary over. # `-tags timetzdata` embeds zone info from the "time/tzdata" package. -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -ldflags '-extldflags "-static"' -tags timetzdata cmd/main.go +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -ldflags '-extldflags "-static"' -tags timetzdata ../cmd/main.go FROM scratch # the test program: diff --git a/docker/gitbucket/Dockerfile b/docker/gitbucket/Dockerfile new file mode 100644 index 0000000..f7587fb --- /dev/null +++ b/docker/gitbucket/Dockerfile @@ -0,0 +1,28 @@ +FROM adoptopenjdk/openjdk11-openj9 + +ARG GITBUCKET_HOME + +# create home +RUN mkdir -p $GITBUCKET_HOME + +# mark volumes +VOLUME $GITBUCKET_HOME/repositories +VOLUME $GITBUCKET_HOME/data +VOLUME $GITBUCKET_HOME/gist +VOLUME $GITBUCKET_HOME/plugins + +# Port for web page and Port for SSH access to git repository (Optional) +EXPOSE 8080 8443 29418 + +COPY server-WIN-DOMAIN-CA.cer / +COPY SSLPoke.java / + +# ADD https://github.com/gitbucket/gitbucket/releases/download/4.38.4/gitbucket.war $GITBUCKET_HOME/gitbucket.war +COPY gitbucket.war $GITBUCKET_HOME + +RUN keytool -importcert -file /server-WIN-DOMAIN-CA.cer -alias "server-WIN-DOMAIN-CA" -cacerts -storepass changeit -noprompt + +# set environment +WORKDIR $GITBUCKET_HOME + +CMD ["sh", "-c", "java $JAVA_OPTS -jar $GITBUCKET_HOME/gitbucket.war"] \ No newline at end of file diff --git a/docker/gitbucket/SSLPoke.java b/docker/gitbucket/SSLPoke.java new file mode 100644 index 0000000..b46dcce --- /dev/null +++ b/docker/gitbucket/SSLPoke.java @@ -0,0 +1,40 @@ +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.*; + +/** Establish a SSL connection to a host and port, writes a byte and + * prints the response. See + * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services + */ +public class SSLPoke { + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("Usage: "+SSLPoke.class.getName()+" "); + System.exit(1); + } + try { + SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1])); + + SSLParameters sslparams = new SSLParameters(); + sslparams.setEndpointIdentificationAlgorithm("HTTPS"); + sslsocket.setSSLParameters(sslparams); + + InputStream in = sslsocket.getInputStream(); + OutputStream out = sslsocket.getOutputStream(); + + // Write a test byte to get a reaction :) + out.write(1); + + while (in.available() > 0) { + System.out.print(in.read()); + } + System.out.println("Successfully connected"); + + } catch (Exception exception) { + exception.printStackTrace(); + System.exit(1); + } + } +} \ No newline at end of file diff --git a/docker/gitbucket/docker-compose.yml b/docker/gitbucket/docker-compose.yml new file mode 100644 index 0000000..48fdcbf --- /dev/null +++ b/docker/gitbucket/docker-compose.yml @@ -0,0 +1,68 @@ +version: "3" + +volumes: + mysql: + driver: local + +services: + gitbucket: + build: + context: . + dockerfile: Dockerfile + args: + GITBUCKET_HOME: /mnt/gitbucket + container_name: gitbucket_server + restart: always + ports: + - ${HTTP_PORT}:8080 + - ${HTTPS_PORT}:8443 + # Optional for SSH: + - ${SSH_PORT}:29418 + depends_on: + mariadb: + condition: service_healthy + environment: + - JAVA_OPTS=-Dcom.sun.net.ssl.checkRevocation=false -Dcom.sun.security.enableAIAcaIssuers=true -Docsp.enable=fase -Dtrust_all_cert=true -Djdk.tls.client.protocols=TLSv1.2 -Dcom.sun.net.ssl.enableECC=false + - GITBUCKET_HOME=/mnt/gitbucket + - GITBUCKET_CONNECTORS=http + - GITBUCKET_HOST=0.0.0.0 + - GITBUCKET_PORT=8080 + - GITBUCKET_SECUREPORT=8443 + - GITBUCKET_REDIRECTHTTPS=false + - GITBUCKET_PREFIX=/ + - GITBUCKET_MAXFILESIZE=4294967296 + - GITBUCKET_UPLOADTIMEOUT=120000 + - GITBUCKET_JETTYIDLETIMEOUT=600000 + - GITBUCKET_DB_URL=jdbc:mariadb://mariadb/gitbucket?useUnicode=true&characterEncoding=utf8 + - GITBUCKET_DB_USER=gitbucket + - GITBUCKET_DB_PASSWORD=gitbucket + healthcheck: + test: ["CMD", "/usr/bin/healthcheck"] + interval: 30s + timeout: 10s + retries: 5 + volumes: + - ../disks/disk1/gitbucket_data/repositories/:/mnt/gitbucket/repositories/ + - ../disks/disk1/gitbucket_data/data/:/mnt/gitbucket/data/ + - ../disks/disk1/gitbucket_data/gist/:/mnt/gitbucket/gist/ + - ../disks/disk1/gitbucket_data/plugins/:/mnt/gitbucket/plugins/ + + mariadb: + image: mariadb:10.6 + container_name: gitbucket_mariadb + restart: always + ports: + - ${DB_PORT}:3306 + environment: + - MYSQL_ROOT_PASSWORD=gitbucket + - MYSQL_USER=gitbucket + - MYSQL_PASSWORD=gitbucket + - MYSQL_DATABASE=gitbucket + command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"] + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=gitbucket"] + interval: 10s + timeout: 5s + retries: 5 + volumes: + - mysql:/var/lib/mysql \ No newline at end of file diff --git a/docker/gitbucket/gitbucket.war b/docker/gitbucket/gitbucket.war new file mode 100644 index 0000000..c63e40a Binary files /dev/null and b/docker/gitbucket/gitbucket.war differ diff --git a/docker/gitbucket/server-WIN-DOMAIN-CA.cer b/docker/gitbucket/server-WIN-DOMAIN-CA.cer new file mode 100644 index 0000000..906db20 --- /dev/null +++ b/docker/gitbucket/server-WIN-DOMAIN-CA.cer @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDuTCCAqGgAwIBAgIQcZXcA798CYtB1LtewpzPijANBgkqhkiG9w0BAQsFADBu +MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxHjAcBgoJkiaJk/IsZAEZFg5tYXJsZXJp +bm9ncm91cDEWMBQGCgmSJomT8ixkARkWBnNlcnZlcjEdMBsGA1UEAxMUc2VydmVy +LVdJTi1ET01BSU4tQ0EwIBcNMjIwODE1MTI1NTM3WhgPMjEyMjA4MTUxMzA1Mzda +MG4xFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEeMBwGCgmSJomT8ixkARkWDm1hcmxl +cmlub2dyb3VwMRYwFAYKCZImiZPyLGQBGRYGc2VydmVyMR0wGwYDVQQDExRzZXJ2 +ZXItV0lOLURPTUFJTi1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMBJwWymu7Csp+y8EMiPNo5drsQE58+enNCk13OIemQON5LZwY++BnvIrHvnaCof +Cdb9U2QyWV+Iehv/lNXcBkT6dJCTxUVmn6rXMmwNnBJmGuy0D6APIEPVBO3S7+/R +E4az8ikpVezbqAw/LiSyVMEQFaAEK8RlleBScLw9gpXmcWKljCrO/z+2wO1EGI3z +a1+qFLynQLeyusRj6rvo0U4RTyXdKaA++Ojhx3DV1NopHoSJ7CqXR728ubWK0fvY +0JGMg2ijS1cle7yC96+9ZSjdtktI/9M+8SG/tbpXcpW1bzGM0wCWOos1hLehks7V +c1pBEuVGSKSdtyF/FK2C7YUCAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFL+/yzfaRM/Rcrc9oYEzZf3STypqMBAGCSsGAQQB +gjcVAQQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQA7j2n9ZeKDwbmWCM2P1F9+6EZ8 ++RZ+PEdxqs3aDo6S0Ckr/iopHA9PoexKGVEQN6bzaYxb0XTEbpJ89oI299weJF+W +63zID/lpEzsaSlTWpuj8KBudVoKsJmwJK2akQ2T3MmSiz7drtFOyh5wl9vhoi2cv +H3xhpqOYgh6iRwfwXMLo2YyS4vG6UZtq1GnU/drwVb1gHCoMdz7sFIdxlaw85Ub+ +dlicykBNu60dbvM/iI0qSG25PerjEoOWZAglrPWpsQ0Zy+ChV0lWSp6FIYHjT3Rj +3TUo18LwIUKyorRErOTO4vgYHpqaA/RkAfl0C3cUujMw9eAp1fyd9FH0UcDo +-----END CERTIFICATE----- diff --git a/docker/owncloud/docker-compose.yml b/docker/owncloud/docker-compose.yml new file mode 100644 index 0000000..4218d74 --- /dev/null +++ b/docker/owncloud/docker-compose.yml @@ -0,0 +1,72 @@ +version: "3" + +volumes: + mysql: + driver: local + redis: + driver: local + +services: + owncloud: + image: owncloud/server:${OWNCLOUD_VERSION} + container_name: owncloud_server + restart: always + ports: + - ${HTTP_PORT}:8080 + depends_on: + - mariadb + - redis + environment: + - OWNCLOUD_DOMAIN=${OWNCLOUD_DOMAIN} + - OWNCLOUD_TRUSTED_DOMAINS=${OWNCLOUD_TRUSTED_DOMAINS} + - OWNCLOUD_DB_TYPE=mysql + - OWNCLOUD_DB_NAME=owncloud + - OWNCLOUD_DB_USERNAME=owncloud + - OWNCLOUD_DB_PASSWORD=owncloud + - OWNCLOUD_DB_HOST=mariadb + - OWNCLOUD_ADMIN_USERNAME=${ADMIN_USERNAME} + - OWNCLOUD_ADMIN_PASSWORD=${ADMIN_PASSWORD} + - OWNCLOUD_MYSQL_UTF8MB4=true + - OWNCLOUD_REDIS_ENABLED=true + - OWNCLOUD_REDIS_HOST=redis + healthcheck: + test: ["CMD", "/usr/bin/healthcheck"] + interval: 30s + timeout: 10s + retries: 5 + volumes: + - ../disks/disk1/owncloud_data/:/mnt/data + - ../disks/:/mnt/disks + + mariadb: + image: mariadb:10.6 # minimum required ownCloud version is 10.9 + container_name: owncloud_mariadb + restart: always + ports: + - ${DB_PORT}:3306 + environment: + - MYSQL_ROOT_PASSWORD=owncloud + - MYSQL_USER=owncloud + - MYSQL_PASSWORD=owncloud + - MYSQL_DATABASE=owncloud + command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"] + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=owncloud"] + interval: 10s + timeout: 5s + retries: 5 + volumes: + - mysql:/var/lib/mysql + + redis: + image: redis:6 + container_name: owncloud_redis + restart: always + command: ["--databases", "1"] + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + volumes: + - redis:/data diff --git a/bot/domain/youtrack.go b/internal/domain/models.go similarity index 54% rename from bot/domain/youtrack.go rename to internal/domain/models.go index e52085d..b4e2458 100644 --- a/bot/domain/youtrack.go +++ b/internal/domain/models.go @@ -2,6 +2,40 @@ package domain import "fmt" +type Folder struct { + Title string // k + PathTo string // /temp/k + PrivateURL string // http://domain/apps/files/?dir=/temp/k OR http://domain/f/3333 +} + +type CodaIssue struct { + ID string `json:"id"` + Summary string `json:"summary"` + URL string `json:"url"` + Git string `json:"git"` + GitBuild string `json:"git-build"` + Folder string `json:"folder"` +} + +type ConversionLog struct { + Advertiser []string +} + +type Git struct { + Name string `json:"name"` // "poop" + FullName string `json:"full_name"` // "developer/poop" + Private bool `json:"private"` + Url string `json:"url"` // "http://localhost:8081/api/v3/repos/developer/poop" + CloneUrl string `json:"clone_url"` // "http://localhost:8081/git/developer/poop.git" + HtmlUrl string `json:"Html_url"` // "http://localhost:8081/developer/poop" + SshUrl string `json:"ssh_url"` // ?! +} + +type Task struct { + Description string + URL string +} + type Project struct { ID string `json:"id"` ShortName string `json:"shortName"` @@ -12,23 +46,6 @@ type ProjectID struct { ID string `json:"id"` } -// Find needed project.ID in the project's list -func (plist *ProjectsList) FindProjectByName(searchName string) (string, error) { - - projectID := "" - - for _, elem := range plist.Projects { - if elem.ShortName == searchName { - projectID = elem.ID - } - } - - if projectID == "" { - return "", fmt.Errorf("project %s doesn't exist", searchName) - } - return projectID, nil -} - type IssueCreateRequest struct { ProjectID ProjectID `json:"project"` Key string `json:"idReadable"` @@ -53,3 +70,20 @@ type CustomField struct { type ProjectsList struct { Projects []Project } + +// Find needed project.ID in the project's list +func (plist *ProjectsList) FindProjectByName(searchName string) (string, error) { + + projectID := "" + + for _, elem := range plist.Projects { + if elem.ShortName == searchName { + projectID = elem.ID + } + } + + if projectID == "" { + return "", fmt.Errorf("project %s doesn't exist", searchName) + } + return projectID, nil +} diff --git a/bot/helpers/helpers.go b/internal/helpers/helpers.go similarity index 100% rename from bot/helpers/helpers.go rename to internal/helpers/helpers.go diff --git a/bot/helpers/helpers_test.go b/internal/helpers/helpers_test.go similarity index 100% rename from bot/helpers/helpers_test.go rename to internal/helpers/helpers_test.go diff --git a/bot/helpers/xml_test.go b/internal/helpers/xml_test.go similarity index 100% rename from bot/helpers/xml_test.go rename to internal/helpers/xml_test.go diff --git a/bot/ext/client.go b/internal/services/client.go similarity index 82% rename from bot/ext/client.go rename to internal/services/client.go index d118d2e..2a1c907 100644 --- a/bot/ext/client.go +++ b/internal/services/client.go @@ -1,4 +1,4 @@ -package ext +package services import ( "fmt" @@ -6,12 +6,12 @@ import ( "github.com/imroc/req/v3" ) -type Client struct { +type CommonClient struct { *req.Client } -func NewClient() *Client { - return &Client{req.C(). +func NewClient() *CommonClient { + return &CommonClient{req.C(). OnAfterResponse(func(client *req.Client, resp *req.Response) error { if resp.Err != nil { if dump := resp.Dump(); dump != "" { diff --git a/bot/ext/cloud.go b/internal/services/cloud.go similarity index 78% rename from bot/ext/cloud.go rename to internal/services/cloud.go index 748ea77..517c7c2 100644 --- a/bot/ext/cloud.go +++ b/internal/services/cloud.go @@ -1,21 +1,20 @@ -package ext +package services import ( "fmt" "os" "strconv" - d "ticket-pimp/bot/domain" - "ticket-pimp/bot/helpers" + "ticket-pimp/internal/domain" + "ticket-pimp/internal/helpers" "time" ) type Cloud struct { - *Client + *CommonClient } type ICloud interface { - CreateFolder(name string) (*d.Folder, error) - ShareToExternals(cloud *d.Folder) (*d.Folder, error) + CreateFolder(name string) (*domain.Folder, error) } func NewCloud(base, user, pass string) *Cloud { @@ -26,13 +25,13 @@ func NewCloud(base, user, pass string) *Cloud { SetBaseURL(base) return &Cloud{ - Client: &Client{ + CommonClient: &CommonClient{ client, }, } } -func (c *Cloud) CreateFolder(name string) (*d.Folder, error) { +func (c *Cloud) CreateFolder(name string) (*domain.Folder, error) { rootDir := os.Getenv("ROOTDIR") user := os.Getenv("CLOUD_USER") @@ -41,7 +40,7 @@ func (c *Cloud) CreateFolder(name string) (*d.Folder, error) { name = helpers.GitNaming(name) - cloud := d.Folder{ + cloud := domain.Folder{ Title: name, PrivateURL: "", } @@ -61,12 +60,14 @@ func (c *Cloud) CreateFolder(name string) (*d.Folder, error) { if err := c.setPrivateURL(requestPath, &cloud); err != nil { return &cloud, err } + } else { + fmt.Println(resp.Status) } return &cloud, nil } -func (c *Cloud) setPrivateURL(requestPath string, cloud *d.Folder) error { +func (c *Cloud) setPrivateURL(requestPath string, cloud *domain.Folder) error { payload := []byte(``) @@ -97,7 +98,3 @@ func (c *Cloud) setPrivateURL(requestPath string, cloud *d.Folder) error { return nil } - -func (c *Cloud) ShareToExternals(cloud *d.Folder) (*d.Folder, error) { - return nil, nil -} diff --git a/bot/ext/coda.go b/internal/services/coda.go similarity index 82% rename from bot/ext/coda.go rename to internal/services/coda.go index 1522fcb..ced74ba 100644 --- a/bot/ext/coda.go +++ b/internal/services/coda.go @@ -1,14 +1,14 @@ -package ext +package services import ( "fmt" "log" - "ticket-pimp/bot/domain" + "ticket-pimp/internal/domain" "time" ) type Coda struct { - *Client + *CommonClient } type ICoda interface { @@ -16,15 +16,15 @@ type ICoda interface { CreateTask(task domain.CodaIssue) } -func NewCodaClient() *Coda { +func NewCodaClient(token string) *Coda { client := NewClient(). SetTimeout(5 * time.Second). - SetCommonBearerAuthToken("0d5a6853-8bb1-4208-9014-318094f5b21c"). + SetCommonBearerAuthToken(token). SetBaseURL("https://coda.io/apis/v1") return &Coda{ - Client: &Client{ + CommonClient: &CommonClient{ client, }, } @@ -48,7 +48,6 @@ func (c *Coda) ListDocs() { } log.Print(resp) - } func (c *Coda) CreateTask(task domain.CodaIssue) { diff --git a/bot/ext/git.go b/internal/services/git.go similarity index 63% rename from bot/ext/git.go rename to internal/services/git.go index 0d8d967..503efd2 100644 --- a/bot/ext/git.go +++ b/internal/services/git.go @@ -1,20 +1,19 @@ -package ext +package services import ( "log" "os" - "ticket-pimp/bot/domain" - "ticket-pimp/bot/helpers" + "ticket-pimp/internal/domain" + "ticket-pimp/internal/helpers" "time" ) type Git struct { - *Client + *CommonClient } type IGit interface { - NewRepo(string) (*domain.Git, error) - AppsAsCollaboratorTo(*domain.Git) (*domain.Git, error) + CreateRepo(name string) (*domain.Git, error) } func NewGit(base, token string) *Git { @@ -31,10 +30,26 @@ func NewGit(base, token string) *Git { SetBaseURL(base) return &Git{ - Client: &Client{client}, + CommonClient: &CommonClient{client}, } } +func (gb *Git) CreateRepo(name string) (*domain.Git, error) { + //Create git repository with iGit interface; + repo, err := gb.newRepo(name) + if err != nil { + return nil, err + } + + //Set 'apps' as collaborator to created repository; + _, err = gb.defaultGroupAsCollaborator(repo) + if err != nil { + return nil, err + } + + return repo, nil +} + type request struct { Name string `json:"name"` Private bool `json:"private"` @@ -44,7 +59,7 @@ type permissionRequest struct { Perm string `json:"permission"` } -func (gb *Git) NewRepo(name string) (*domain.Git, error) { +func (gb *Git) newRepo(name string) (*domain.Git, error) { name = helpers.GitNaming(name) payload := request{ @@ -61,14 +76,14 @@ func (gb *Git) NewRepo(name string) (*domain.Git, error) { Post("/user/repos") if resp.Err != nil { - log.Print(resp.Err) + log.Print(resp.Status) return nil, resp.Err } return &git, nil } -func (gb *Git) AppsAsCollaboratorTo(git *domain.Git) (*domain.Git, error) { +func (gb *Git) defaultGroupAsCollaborator(git *domain.Git) (*domain.Git, error) { payload := permissionRequest{ Perm: "admin", diff --git a/bot/ext/yt.go b/internal/services/yt.go similarity index 80% rename from bot/ext/yt.go rename to internal/services/yt.go index 3102653..4db5fda 100644 --- a/bot/ext/yt.go +++ b/internal/services/yt.go @@ -1,11 +1,11 @@ -package ext +package services import ( "fmt" "log" "time" - d "ticket-pimp/bot/domain" + "ticket-pimp/internal/domain" "github.com/imroc/req/v3" ) @@ -16,8 +16,8 @@ type youtrack struct { type IYouTrack interface { GetProjectIDByName(searchName string) (string, error) - CreateIssue(projectID, name, description string) (*d.IssueCreateRequest, error) - UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error) + CreateIssue(projectID, name, description string) (*domain.IssueCreateRequest, error) + UpdateIssue(issue *domain.IssueCreateRequest, folder, git, gitBuild string) (*domain.IssueUpdateRequest, error) } func NewYT(base, token string) *youtrack { @@ -39,9 +39,9 @@ func NewYT(base, token string) *youtrack { // GetProjects // provides an array of existing projects; -func (yt *youtrack) getProjects() (*d.ProjectsList, error) { +func (yt *youtrack) getProjects() (*domain.ProjectsList, error) { - var projects d.ProjectsList + var projects domain.ProjectsList resp, _ := yt.R(). EnableDump(). @@ -76,11 +76,11 @@ func (yt *youtrack) GetProjectIDByName(searchName string) (string, error) { // CreateIssue // example: newIssue := yt.CreateIssue("0-2", "Summary", "Description"); -func (yt *youtrack) CreateIssue(projectID, name string, description string) (*d.IssueCreateRequest, error) { +func (yt *youtrack) CreateIssue(projectID, name string, description string) (*domain.IssueCreateRequest, error) { // Create an issue with the provided:, Project ID, Name, Description; - issue := d.IssueCreateRequest{ - ProjectID: d.ProjectID{ + issue := domain.IssueCreateRequest{ + ProjectID: domain.ProjectID{ ID: projectID, //"id":"0-2" }, Summary: name, @@ -102,11 +102,11 @@ func (yt *youtrack) CreateIssue(projectID, name string, description string) (*d. return &issue, nil } -func (yt *youtrack) UpdateIssue(issue *d.IssueCreateRequest, folder, git, gitBuild string) (*d.IssueUpdateRequest, error) { +func (yt *youtrack) UpdateIssue(issue *domain.IssueCreateRequest, folder, git, gitBuild string) (*domain.IssueUpdateRequest, error) { // Set Folder, Git, GitBuild to the Issue: - update := d.IssueUpdateRequest{ + update := domain.IssueUpdateRequest{ IssueCreateRequest: *issue, - CustomFields: []d.CustomField{ + CustomFields: []domain.CustomField{ { Name: "Директория графики", Type: "SimpleIssueCustomField",