Zero. Foreword
The open source framework used in this tutorial is as follows:
name | open source address | effect |
---|---|---|
Cobra | command line tool | https://github.com/spf13/cobra |
Aurora | font color | https://github.com/logrusorgru/aurora |
go-zero | go-z framework template function | https://github.com/zeromicro/go-zero |
The complete source code of this project : https://github.com/ctra-wang/cobra-gen-drone
1. Getting to know Cobra for the first time
1. The role of Cobra
Overview : Cobra is a Golang package that provides a simple interface to create command-line programs. At the same time, Cobra is also an application program, which is used to generate an application framework to develop Cobra-based applications.
Representative works :docker
,k8s
,helm
etc.
The detailed use will not be introduced in detail here
- Recommended articles are as follows:
Official documentation: https://cobra.dev/
- Recommended videos are as follows:
二、go template
Here is the template we want to render (the file ending in .tpl format).
By rendering the template, we can output the final file we want
1. go template use
Detailed use and instructions will not be introduced
- Recommended articles are as follows:
Go template usage: https://blog.csdn.net/skh2015java/article/details/126213329
Regarding template :
We can use .tpl files, or directly wrap them with `` strings for rendering. Mainly use the characteristics of { {}} double curly braces in go
3. Start the project
The entire project directory is as follows:
1. Create a project catalog
1.1. Create go.mod and cmd folders
go mod init xxxx
mkdir cmd
1.2, create the main file
package main
import (
"app/cmd"
)
func main() {
cmd.Execute()
}
1.3. Create cmd.go in the cmd folder
code show as below
package cmd
import (
"fmt"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"os"
)
// droneCmd represents the drone command
var droneCmd = &cobra.Command{
Use: "drone",
Short: "drone is very good",
Long: `创建drone的指令`,
RunE: DroneGenerator, //步骤一
}
var (
//步骤三
DroneName string
GoPrivate string
ServiceName string
ServiceType string
GitBranch string
Registry string
Repo string
Tag string
)
func Execute() {
if err := droneCmd.Execute(); err != nil {
fmt.Println(aurora.Red(err.Error()))
os.Exit(1)
}
}
func init() {
// drone --droneName="base" --go_private="gitee.com" --service_name="baserpc.go" --service_type="rpc" --gitBranch="master" --registry="registry.cn-beijing.aliyuncs.com" --repo="registry.cn-beijing.aliyuncs.com/ctra_test/ctra-go-zhiye-rpc" --tag="latest"
// drone -d="base" -g="gitee.com" -s="baserpc.go" -x="rpc" -b="master" -r="registry.cn-beijing.aliyuncs.com" -o="registry.cn-beijing.aliyuncs.com/ctra_test/ctra-go-zhiye-rpc" -t="latest"
// 步骤二
droneCmd.Flags().StringVarP(&DroneName, aurora.Yellow("droneName").String(), "d", "", aurora.Green(`The Drone name`).String())
droneCmd.Flags().StringVarP(&GoPrivate, "go_private", "g", "", aurora.Green(`Go private (default "gitee.com")`).String())
droneCmd.Flags().StringVarP(&ServiceName, "service_name", "s", "", aurora.Green(`The service name of the project`).String())
droneCmd.Flags().StringVarP(&ServiceType, "service_type", "x", "", aurora.Green(`The service type, such as rpc | api`).String())
droneCmd.Flags().StringVarP(&GitBranch, "gitBranch", "b", "", `The branch of the remote repo, it does work with --remote (default "master")`)
droneCmd.Flags().StringVarP(&Registry, "registry", "r", "", `The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure`)
droneCmd.Flags().StringVarP(&Repo, "repo", "o", "", aurora.Green(`The project git repository`).String())
droneCmd.Flags().StringVarP(&Tag, "tag", "t", "", aurora.Green("Git tag (default \"latest\")").String())
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
droneCmd.PersistentFlags().String("droneName", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// droneCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
1.4. Create drone.go in the cmd folder
package cmd
import (
_ "embed"
"fmt"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"os"
"strings"
"text/template"
)
var (
//go:embed drone.tpl
UsageTpl string
)
type Drone struct {
//步骤三
DroneName string
GoPrivate string
ServiceName string
ServiceType string
GitBranch string
Registry string
Repo string
Tag string
}
func DroneGenerator(_ *cobra.Command, _ []string) error {
// 步骤四
// 对所有的传入的参数进行一一判断
dronename := DroneName
if len(dronename) == 0 {
dronename = "dronegen-greet"
}
goprivate := GoPrivate
fmt.Println(len(strings.Split(goprivate, ".")))
if len(strings.Split(goprivate, ".")) <= 1 {
return fmt.Errorf("error go private!")
}
serviceName := ServiceName
serviceType := ServiceType
gitBranch := GitBranch
registry := Registry
repo := Repo
tag := Tag
file, err := os.Create("drone.yml")
if err != nil {
fmt.Println("文件创建失败:", err)
return err
} else {
fmt.Println("文件创建成功!")
}
defer file.Close()
text, err := pathx.LoadTemplate("dronegen", "drone.tpl", UsageTpl)
if err != nil {
fmt.Println("打开模板失败:", err)
return err
} else {
fmt.Println("打开模板成功!")
}
t := template.Must(template.New("dronegen").Parse(text))
return t.Execute(file, Drone{
DroneName: dronename,
GoPrivate: goprivate,
ServiceName: serviceName,
ServiceType: serviceType,
GitBranch: gitBranch,
Registry: registry,
Repo: repo,
Tag: tag,
})
fmt.Println(aurora.Green("Done."))
return nil
}
1.5. Create drone.tpl template file
kind: pipeline
type: docker
name: {
{
.DroneName}}-{
{
.ServiceType}}
steps:
- name: build-go
image: golang:1.20.3
depends_on: [clone]
volumes:
- name: go_cache
path: /go/pkg/mod
commands:
- go env -w CGO_ENABLED=0
- go env -w GOPROXY=https://goproxy.cn,direct
- go env -w GOPRIVATE= {
{
.GoPrivate}}
- go mod tidy && go build -trimpath -ldflags "-s -w" -o app {
{
.ServiceName}}.go
- name: build-{
{
.ServiceType}}
image: plugins/docker:20
environment:
DRONE_REPO_BRANCH: {
{
.GitBranch}}
depends_on: [build-go]
settings:
dockerfile: Dockerfile
registry: {
{
.Registry}}
repo: {
{
.Repo}}:{
{
.Tag}}
auto_tag: true
insecure: true
username:
from_secret: docker_username
password:
from_secret: docker_password
trigger:
ref:
- refs/tags/*
- refs/heads/master
volumes:
- name: go_cache
host:
path: /root/.go/cache
2. How to debug in goland?
This kind of command line code debugging is completely different from the traditional main entry program debugging
2.1、Edit configurations
configure here
2.2、program argument
This is very important, if the instruction value we need to enter is not set here, the corresponding breakpoint cannot be entered
3. Compile and execute
3.1, compile the file into a binary file
go build main.go
3.2. Execution
long command
drone -d="base" -g="gitee.com" -s="baserpc.go" -x="rpc" -b="master" -r="registry.cn-beijing.aliyuncs.com" -o="registry.cn-beijing.aliyuncs.com/ctra_test/ctra-go-zhiye-rpc" -t="latest"
short command
drone --droneName="base" --go_private="gitee.com" --service_name="baserpc.go" --service_type="rpc" --gitBranch="master" --registry="registry.cn-beijing.aliyuncs.com" --repo="registry.cn-beijing.aliyuncs.com/ctra_test/ctra-go-zhiye-rpc" --tag="latest"
You can see that the drone.yml file has been generated
4. Pay attention to the big pit here
Take a look at the configuration page of Drone.
The default file name prefix of Configuration is点!!!
os.create()
Functions in Golang
file, err := os.Create("drone.yml")
if err != nil {
fmt.Println("文件创建失败:", err)
return err
} else {
fmt.Println("文件创建成功!")
}
If we use the default
.drone.yml
, we will not generate this file wherever we execute the compiled file! ! Ten Pit
file, err := os.Create(".drone.yml")