Skip to content

Commit

Permalink
chore: migrage tibuild code from from pingcap-qe/tibuild to tibuild…
Browse files Browse the repository at this point in the history
… folder

Signed-off-by: wuhuizuo <[email protected]>
  • Loading branch information
wuhuizuo committed Dec 5, 2023
1 parent a3d0cd3 commit af73c35
Show file tree
Hide file tree
Showing 152 changed files with 55,329 additions and 0 deletions.
24 changes: 24 additions & 0 deletions tibuild/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin/
venv/

# Test binary, built with `go test -c`
*.testgit

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
.idea/
.vscode/

# Self configuration files
config.yaml
deployments/kubernetes/tibuild-configs.yaml
# System temporary file, like cache file
.DS_Store
83 changes: 83 additions & 0 deletions tibuild/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Variables contain directory/file and so on
GO_BUILD_DIR = ./bin
WEBSITE_DIR = ./website/

GO_BINARY = ${GO_BUILD_DIR}/tibuild
WEBSITE_BINARY = ${WEBSITE_DIR}/build/

DOCKER_ADDRESS = hub.pingcap.net
DOCKER_NAME = tibuild/tibuild
DOCKER_TAG ?= $(shell git describe --dirty --always)
DOCKER_IMG ?= ${DOCKER_ADDRESS}/${DOCKER_NAME}:${DOCKER_TAG}
DOCKER_FILE = ./deployments/docker/Dockerfile
K8S_METADATA_NAME = tibuild
K8S_DEPLOYMENT_FILE = ./deployments/kubernetes/
TIBUILD_MAIN_FILE = ./cmd/tibuild/

# =============================================================================
# The following are common build commands
# =============================================================================
build: build.web build.server

clean:
@rm -rf ${GO_BUILD_DIR}
@rm -rf ${WEBSITE_BINARY}
@echo "clear all temporary files and folders successful hahaha!"

run: clean build
./${GO_BINARY}

build.web:
cd ${WEBSITE_DIR} && \
yarn install && \
yarn build

swagger:
swag init -d cmd/tibuild,pkg/rest

test:
go test ./...

build.server: swagger test
go build -o ${GO_BINARY} ${TIBUILD_MAIN_FILE}


# =============================================================================
# The following are common deployment commands
# =============================================================================
website/node_modules :
cd website && yarn install

docker: website/node_modules
docker buildx build --platform=linux/amd64,linux/arm64 -f ${DOCKER_FILE} -t ${DOCKER_IMG} . --push

docker.run:
docker run -p 8080:8080 -t ${DOCKER_NAME}

k8s.init:
kubectl apply -f ${K8S_DEPLOYMENT_FILE}/namespace.yaml
kubectl apply -f ${K8S_DEPLOYMENT_FILE}/deployment.yaml
kubectl apply -f ${K8S_DEPLOYMENT_FILE}/service.yaml
@echo "k8s deploy project successful hahaha!"

k8s.update:
kubectl rollout restart deployment/${K8S_METADATA_NAME} -n ${K8S_METADATA_NAME}

k8s.clean:
kubectl delete all,ingress --all -n ${K8S_METADATA_NAME}
@echo "k8s clean all resources successful hahaha!"

tbctl:
docker buildx build ./tbctl -t hub.pingcap.net/tibuild/tbctl --platform linux/amd64,linux/arm64 --push

# =============================================================================
# Help documentation for commands
# =============================================================================
help:
@echo "make build : build all binaries"
@echo "make run : build all binaries and run"
@echo "make clean : clear all temporary files and folders generated by the 'make build' or 'make run'"


.PHONY: build run clean help tbctl
.PHONY: build.web build.server docker docker.run k8s k8s.clean swagger test
6 changes: 6 additions & 0 deletions tibuild/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
approvers:
- lijie0123
- wuhuizuo

reviewers:
- purelind
58 changes: 58 additions & 0 deletions tibuild/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# TiBuild
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)

This repository is a build platform for PingCAP, Welcome bros!

## Design
[click and jump](https://pingcap.feishu.cn/wiki/wikcndnDJhhpnNZb5wivmJPPHJb)

## Technologies
+ Backend: Golang & [Gin](https://github.com/gin-gonic/gin)
+ Database: [Mysql of Gorm](https://github.com/go-gorm/gorm)
+ Common Utils: [Github](https://github.com/google/go-github) & [Config](https://github.com/jinzhu/configor)
+ Deployments: Docker & Kubernetes
+ Frontend: [Create-React-App for framework](https://github.com/facebook/create-react-app) & [Material-UI/MUI for components](https://github.com/mui-org/material-ui) & [Axios for remote procedure call](https://github.com/axios/axios)

## Quick Start
```
git clone https://github.com/PingCAP-QE/ee-apps.git
cd ee-apps/tibuild/
# create a config.yaml in root path (detail like /tibuild/config_example.yaml)
make run
```
After waiting a few seconds, application is available and can be visited in the browser:[localhost:8080](http://localhost:8080/)

## User Guide
[click and jump](https://pingcap.feishu.cn/wiki/wikcnlRSh8dyOoHGbMQEJN9x77d)

## File Structure
```
tibuild
├── .gitignore
├── README.md
├── go.mod # Golang environment configuration
├── go.sum
├── config.yaml # Global configuration
├── Makefile # Code compilation and other instructions
└── scripts/ # Scripts to perform various operations, keep the root level Makefile small and simple
└── cmd/ # Main application starters of Golang
└── api/ # REST API registry & Static file router, reference: https://github.com/gin-gonic/gin
├── api.go
└── deployments/
└── docker/ # Build docker image contains website and server binary
└── kubernetes/ # Deployment yaml for k8s
└── commons/ # Common utils for whole project
└── configs/ # Global configuration reader
└── database/ # Database connectors
└── httpclient/ # Http client utils
└── internalpkg/ # Business code & function
└── entity/ # Object entity
└── service/ # Service for controller/
└── controller/ # Deal with http request
└── dto/ # Output struct(no database)
└── website/ # UI components and pages. detail can jump to website/README.MD
├── yarn.lock # React environment configuration for machines
├── package.json # React environment configuration for people
└── src/ # index.js & routes.js/ Components/ Pages/ ...
└── public/ # HomePage: index.html and icons
```
118 changes: 118 additions & 0 deletions tibuild/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package api

import (
"context"
"net/http"
"tibuild/commons/configs"
"tibuild/commons/database"
"tibuild/internalpkg/controller"
controllers "tibuild/pkg/rest/controller"
"tibuild/pkg/rest/service"

_ "tibuild/docs"

"github.com/gin-contrib/requestid"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)

// Create gin-routers
func Routers(file string, cfg *configs.ConfigYaml) (router *gin.Engine) {
router = gin.Default()

// Error
routeError(router)

// Cors
routeCors(router)

// Root html & Folder static/ for JS/CSS & home/*any for website('url' match to website/src/routes.js)
routeHtml(router, file)

// Real REST-API registry
routeRestAPI(router, cfg)

routeDocs(router)

return router
}

func routeError(router *gin.Engine) {
router.Use(APIErrorJSONReporter())
}

func routeCors(router *gin.Engine) {
router.Use(Cors())
}

func routeHtml(router *gin.Engine, file string) {
router.Use(
static.Serve("/", static.LocalFile(file, true)),
)
router.Use(
static.Serve("/static", static.LocalFile(file, true)),
)
homePages := router.Group("/home")
{
homePages.GET("/*any", func(c *gin.Context) {
c.FileFromFS("/", http.Dir(file))
})
}
}

func routeDocs(router *gin.Engine) {
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
}

func routeRestAPI(router *gin.Engine, cfg *configs.ConfigYaml) {

build := router.Group("/build")
{
// 获取类-每个构建类型下的流水线
build.GET("/pipelines-for-build-type", controller.PipelineForBuildType)
// 获取类-每条流水线的执行列表
build.GET("/pipeline-list-show", controller.PipelinesShow)
// 获取类-每条流水线的可选参数值
build.GET("/params-available-for-pipeline", controller.ParamsAvailableForPipeline)
// 获取类-执行结果记录轮询
build.GET("/request-rotation", controller.RequestRotation)
//获取类-执行结果记录查询
build.GET("/request-result", controller.RequestResult)
// 触发类-触发流水线构建
build.POST("/pipeline-trigger", controller.PipelineTrigger)
// github sso 认证
build.GET("/token", controller.GithubSSOToken)

}

apiGroup := router.Group("/api")
apiGroup.Use(requestid.New())
hotfixGroup := apiGroup.Group("/hotfix")
hotfixHandler := controllers.NewHotfixHandler(cfg.Github.Token)
{
hotfixGroup.POST("/create-branch", hotfixHandler.CreateBranch)
hotfixGroup.POST("/create-tag", hotfixHandler.CreateTag)
}

jenkins, err := service.NewJenkins(context.Background(), "https://cd.pingcap.net/", cfg.Jenkins.UserName, cfg.Jenkins.PassWord)
if err != nil {
panic(err)
}
devBuildGroup := apiGroup.Group("/devbuilds")
devBuildHandler := controllers.NewDevBuildHandler(context.Background(), jenkins, database.DBConn.DB)
{
devBuildGroup.POST("", devBuildHandler.Create)
devBuildGroup.GET("", devBuildHandler.List)
devBuildGroup.GET("/:id", devBuildHandler.Get)
devBuildGroup.PUT("/:id", devBuildHandler.Update)
devBuildGroup.POST("/:id/rerun", devBuildHandler.Rerun)
}

artifactHelper := controllers.NewArtifactHelperHandler(jenkins)
artifactGroup := apiGroup.Group("/artifact")
{
artifactGroup.POST("/sync-image", artifactHelper.SyncImage)
}
}
56 changes: 56 additions & 0 deletions tibuild/api/api_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package api

import (
"log"
"net/http"

"github.com/gin-gonic/gin"
)

// error return struct definition
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
}

func (err APIError) Error() string {
return err.Message
}

// middleware error handler in server package
func APIErrorJSONReporter() gin.HandlerFunc {
return APIErrorJSONReporterHandler(gin.ErrorTypeAny)
}

func APIErrorJSONReporterHandler(errType gin.ErrorType) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
innerErrors := c.Errors.ByType(errType)

if len(innerErrors) > 0 {
err := innerErrors[0].Err
parsedError := &APIError{
Code: http.StatusInternalServerError,
Message: err.Error(),
}
log.Println(parsedError)

// var parsedError *APIError
// switch err.(type) {
// case *APIError:
// parsedError = err.(*APIError)
// default:
// parsedError = &APIError{
// Code: http.StatusInternalServerError,
// Message: "Internal Server Error",
// }
// }

// Put the error into response
c.IndentedJSON(parsedError.Code, parsedError)
c.Abort()
return
}

}
}
26 changes: 26 additions & 0 deletions tibuild/api/cors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package api

import (
"net/http"

"github.com/gin-gonic/gin"
)

// Supoort Rest-API CORS
func Cors() gin.HandlerFunc {

return func(c *gin.Context) {
method := c.Request.Method
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "Content-Type, AccessToken, X-CSRF-Token, Authorization, Token")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PATCH")
c.Header("Access-Control-Expose-Headers",
"Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials", "true")
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
c.Next()
}

}
18 changes: 18 additions & 0 deletions tibuild/cmd/branch_create_helper/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"context"
"fmt"
"tibuild/pkg/rest/controller"
"tibuild/pkg/rest/service"
)

func main() {
prodName := "tidb"
baseVersion := "v5.4.1"
prod := service.StringToProduct(prodName)
if prod == service.ProductUnknown {
fmt.Println("bad prod name" + prodName)
}
controller.NewChatPrintRepoService().CreateBranch(context.TODO(), service.BranchCreateReq{Prod: prod, BaseVersion: baseVersion})
}
Loading

0 comments on commit af73c35

Please sign in to comment.