main.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "math/rand"
  7. "net/url"
  8. "os"
  9. "strconv"
  10. "time"
  11. )
  12. type envs struct {
  13. username string
  14. hostname string
  15. }
  16. type pipeline struct {
  17. ID int `json:"id"`
  18. Stage string `json:"stage"`
  19. Status string `json:"status"`
  20. Name string `json:"name"`
  21. Pipeline struct {
  22. CreatedAt string `json:"created_at"`
  23. ID string `json:"id"`
  24. Status string `json:"status"`
  25. WebURL string `json:"web_url"`
  26. } `json:"pipeline"`
  27. WebURL string `json:"web_url"`
  28. }
  29. var (
  30. counter int
  31. branch string
  32. project string
  33. err error
  34. resp []byte
  35. sample []string
  36. ripest []string
  37. fulresp []pipeline
  38. urlstring = "https://gitlab.com/api/v4/projects/"
  39. headers = map[string]string{
  40. "PRIVATE-TOKEN": "",
  41. "Content-Type": "application/json",
  42. }
  43. //for custom header
  44. env = envs{
  45. username: "USER",
  46. hostname: "HOSTNAME",
  47. }
  48. )
  49. func myUsage() {
  50. fmt.Printf("Usage:\n %s [OPTIONS] project stage1 stage2 ...\nOptions:\n", os.Args[0])
  51. flag.PrintDefaults()
  52. fmt.Printf("Example:\n %s -b master /backend/tabl-suite migrate deploy \n", os.Args[0])
  53. fmt.Printf(" OR\n %s --b master /frontend \"run tests\" deploy \n", os.Args[0])
  54. fmt.Printf(" OR\n %s -b=master /backend/suite Db_migrate deploy \n\n", os.Args[0])
  55. }
  56. func breakError(err error, message string) {
  57. if message != "" {
  58. fmt.Printf(message)
  59. }
  60. fmt.Println(err)
  61. os.Exit(1)
  62. }
  63. func checkStage(stg string) bool {
  64. for i := 0; i < len(ripest); i++ {
  65. if stg == ripest[i] {
  66. return true
  67. }
  68. }
  69. return false
  70. }
  71. func main() {
  72. flag.Usage = myUsage
  73. //flags
  74. flag.StringVar(&branch, "b", "develop", "Source branch")
  75. flag.Parse()
  76. if len(flag.Args()) == 0 {
  77. fmt.Printf("\n Required parameters are missing \n")
  78. flag.Usage()
  79. os.Exit(1)
  80. }
  81. args := ToLow(flag.Args()) //Подразумевает что проект тоже будет с маленькой буквы
  82. for i := 1; i <= len(args)-1; i++ {
  83. if "build" == args[i] {
  84. fmt.Println(` Warning: stage "build" usually starts automatically when the pipeline start`)
  85. }
  86. }
  87. project = url.PathEscape(args[0])
  88. _, err = GetReq(nil, urlstring+project, headers)
  89. if err != nil {
  90. breakError(err, "\n Possibly a mistake in the name of the project\n")
  91. }
  92. stendname, err := CustomEnv(env.hostname, env.username)
  93. if err != nil {
  94. breakError(err, "")
  95. }
  96. //Create new branch
  97. if branch != "develop" {
  98. _, err = GetReq(nil, urlstring+project+"/repository/branches/"+url.PathEscape(branch), headers)
  99. if err != nil {
  100. breakError(err, "\n Maybe the wrong branch?\n")
  101. }
  102. }
  103. newbranch := "cli/" + stendname + "-" + RandString(strconv.Itoa(1 + rand.New(rand.NewSource(time.Now().UnixNano())).Intn(10000-2)))[:6]
  104. _, err = PostReq(nil, urlstring+project+"/repository/branches/"+"?branch="+newbranch+"&ref="+branch, headers)
  105. if err != nil {
  106. breakError(err, "")
  107. }
  108. //Run pipline
  109. data := map[string]interface{}{
  110. "ref": newbranch,
  111. "variables": [1]map[string]string{{
  112. "key": "CUSTOM_ENV",
  113. "value": stendname,
  114. }},
  115. }
  116. resp, err = PostReq(data, urlstring+project+"/pipeline", headers)
  117. if err != nil {
  118. breakError(err, "")
  119. }
  120. var respid pipeline
  121. json.Unmarshal(resp, &respid)
  122. if respid.ID != 0 { //Если в ответе айди не пустое
  123. fmt.Printf(" Pipeline was created: %s\n", respid.WebURL) //Пишем ссылку
  124. for { //И начинаем бесконечный цикл
  125. time.Sleep(10 * time.Second)
  126. //Запрашиваем джобы
  127. resp, err = GetReq(nil, urlstring+project+"/pipelines/"+strconv.Itoa(respid.ID)+"/jobs", headers)
  128. if err != nil {
  129. breakError(err, "")
  130. }
  131. json.Unmarshal(resp, &fulresp)
  132. if len(sample) < len(fulresp) {
  133. for i := 0; i < len(fulresp); i++ {
  134. gdv := fulresp[i]
  135. //var gdv []string
  136. stages := gdv.Stage
  137. sample = append(sample, stages)
  138. }
  139. }
  140. if len(sample) == len(fulresp) {
  141. if Compar(args[1:], sample) != true {
  142. _, err = DelReq(nil, urlstring+project+"/repository/branches/"+url.PathEscape(newbranch), headers)
  143. if err != nil {
  144. breakError(err, "")
  145. }
  146. err := fmt.Errorf("\n Apparently you are mistaken in the name of the stages.\n %s", respid.WebURL)
  147. breakError(err, "")
  148. }
  149. }
  150. for i := 0; i < len(fulresp); i++ { //Проверка статутсов
  151. abc := fulresp[i]
  152. if abc.Status == "failed" || abc.Status == "canceled" {
  153. _, err = DelReq(nil, urlstring+project+"/repository/branches/"+url.PathEscape(newbranch), headers)
  154. if err != nil {
  155. breakError(err, "")
  156. }
  157. err = fmt.Errorf("\n Something went wrong while doing the job.\n Status received: %s\n More details: %s", abc.Status, abc.Pipeline.WebURL)
  158. breakError(err, "")
  159. }
  160. if abc.Status == "pending" || abc.Status == "running" {
  161. continue
  162. }
  163. if abc.Status == "success" && checkStage(abc.Stage) != true && len(ripest) == len(args)-1 {
  164. fmt.Printf(" %s: success \n", abc.Name)
  165. _, err = DelReq(nil, urlstring+project+"/repository/branches/"+url.PathEscape(newbranch), headers)
  166. if err != nil {
  167. breakError(err, "")
  168. }
  169. os.Exit(0)
  170. }
  171. if abc.Status == "success" && checkStage(abc.Stage) != true {
  172. fmt.Printf(" %s: success \n", abc.Name)
  173. ripest = append(ripest, abc.Stage)
  174. continue
  175. }
  176. if len(args) != 1 && checkStage(abc.Stage) != true && len(ripest) > 0 {
  177. for i := 0; i < len(args); i++ {
  178. if len(ripest) > counter && counter < len(args) && abc.Stage == args[counter+1] {
  179. counter++
  180. _, err = PostReq(nil, urlstring+project+"/jobs/"+strconv.Itoa(abc.ID)+"/play", headers)
  181. if err != nil {
  182. breakError(err, "")
  183. } else {
  184. continue
  185. }
  186. }
  187. }
  188. } else if len(args) == 1 && checkStage(abc.Stage) == true {
  189. _, err = DelReq(nil, urlstring+project+"/repository/branches/"+url.PathEscape(newbranch), headers)
  190. if err != nil {
  191. breakError(err, "")
  192. }
  193. os.Exit(0)
  194. } else {
  195. continue
  196. }
  197. }
  198. }
  199. }
  200. } //main