使用 cobra 开发 glab4f 命令行过程
我想用 cobra(golang) 做一个简单的命令行工具,用来管理 gitlab ci 里的环境变量。
使用方式如下:
1. glab4f .env1 .env2
2. glab4f envdir
具体细节
1. 命令行可以读取多个环境变量 .env1 .env2
2. 读取环境变量里的变量名和值,并将其写入 gitlab ci 的环境变量里。
3. 如果目标为 dir 的情况会依次读取当前目录下所有的.env 文件,并将其内容写入 gitlab ci 的环境变量里。
4. env如果以 env@production 这种方式命名,则当 @ 后面的内容作为 Environment scope
使用方式如下:
1. glab4f .env1 .env2
2. glab4f envdir
具体细节
1. 命令行可以读取多个环境变量 .env1 .env2
2. 读取环境变量里的变量名和值,并将其写入 gitlab ci 的环境变量里。
3. 如果目标为 dir 的情况会依次读取当前目录下所有的.env 文件,并将其内容写入 gitlab ci 的环境变量里。
4. env如果以 env@production 这种方式命名,则当 @ 后面的内容作为 Environment scope
要实现这个功能,你可以使用 Go 语言和 Cobra 库来构建一个命令行工具。以下是一个简单的实现步骤和代码示例:
1. 安装 Cobra
首先,你需要安装 Cobra 库。你可以使用以下命令来安装:
go get -u github.com/spf13/cobra/cobra
2. 创建项目结构
创建一个新的 Go 项目,并使用 Cobra 初始化命令行工具:
cobra init --pkg-name glab4f
这将会生成一个基本的项目结构。
3. 添加命令
在生成的 cmd/root.go
文件中,添加一个新的命令来处理 .env
文件和目录。
package cmd
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "glab4f",
Short: "A tool to manage GitLab CI environment variables",
Long: `A tool to manage GitLab CI environment variables from .env files or directories.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println("Please provide .env files or a directory")
return
}
for _, arg := range args {
if isDir(arg) {
processDir(arg)
} else {
processFile(arg)
}
}
},
}
func isDir(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
func processDir(dirPath string) {
filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(info.Name(), ".env") {
processFile(path)
}
return nil
})
}
func processFile(filePath string) {
envScope := ""
if strings.Contains(filePath, "@") {
parts := strings.Split(filePath, "@")
envScope = parts[1]
}
file, err := os.Open(filePath)
if err != nil {
fmt.Printf("Error opening file %s: %v\n", filePath, err)
return
}
defer file.Close()
// Read and parse the .env file
// Here you would read the file line by line and extract the key-value pairs
// Then, you would use the GitLab API to set the environment variables
fmt.Printf("Processing file: %s with environment scope: %s\n", filePath, envScope)
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
4. 解析 .env
文件
在 processFile
函数中,你需要解析 .env
文件并提取键值对。你可以使用 bufio.Scanner
来逐行读取文件,并使用 strings.Split
来分割键值对。
func processFile(filePath string) {
envScope := ""
if strings.Contains(filePath, "@") {
parts := strings.Split(filePath, "@")
envScope = parts[1]
}
file, err := os.Open(filePath)
if err != nil {
fmt.Printf("Error opening file %s: %v\n", filePath, err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.TrimSpace(line) == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
// Here you would call the GitLab API to set the environment variable
fmt.Printf("Setting variable: %s=%s with scope: %s\n", key, value, envScope)
}
if err := scanner.Err(); err != nil {
fmt.Printf("Error reading file %s: %v\n", filePath, err)
}
}
5. 调用 GitLab API
你需要使用 GitLab 的 API 来设置环境变量。你可以使用 Go 的 net/http
包或者其他 HTTP 客户端库来发送请求。
func setGitLabVariable(key, value, envScope string) {
// Replace with your GitLab project ID and access token
projectID := "your-project-id"
accessToken := "your-access-token"
url := fmt.Sprintf("https://gitlab.com/api/v4/projects/%s/variables", projectID)
payload := map[string]string{
"key": key,
"value": value,
"environment_scope": envScope,
}
jsonData, err := json.Marshal(payload)
if err != nil {
fmt.Printf("Error marshalling payload: %v\n", err)
return
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
req.Header.Set("PRIVATE-TOKEN", accessToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error sending request: %v\n", err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
fmt.Printf("Failed to set variable: %s\n", resp.Status)
return
}
fmt.Printf("Successfully set variable: %s\n", key)
}
6. 编译和运行
最后,编译并运行你的命令行工具:
go build -o glab4f
./glab4f .env1 .env2
./glab4f envdir
总结
这个示例展示了如何使用 Cobra 创建一个简单的命令行工具来管理 GitLab CI 的环境变量。你可以根据需要进一步扩展和优化这个工具,例如添加错误处理、日志记录、配置文件支持等。