使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS

本文章采用几个任务执行

最终想要实现效果,
1、golang做成一个服务占用一个端口,然后监测gitlab仓库webhook
2、前端人员提交代码到gitlab,golang触发去拉取代码,放到本地指定目录
3、go判断目录进行区分,静态资源,跟图库
4、静态资源上传到远程服务器html目录下
5、图库资源上传到阿里云OSS里面
6、刷新一下CDN缓存

目前没有服务化,尝试监听gitlab的webhook,但是推送代码,golang没有触发,目前还在解决中。。。。。

以下是源代码

任务一拉取代码

代码如下

//这个是需要手动执行,没有做成服务
package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func main() {
	// 判断当前环境是否有 Git
	//if _, err := exec.LookPath("git"); err != nil {
	//  fmt.Println("当前没有Git环境,建议你安装一下Git环境")
	//  return
	//}

	// 执行 git clone 命令克隆代码仓库,并输入账户密码
	fmt.Println("开始执行 git clone 命令...")
	cmd1 := exec.Command("git", "clone", "-b", "oss", "xxxxx", "D:/impromptu")
	cmd1.Stdin = os.Stdin
	cmd1.Stdout = os.Stdout
	cmd1.Stderr = os.Stderr
	cmd1.Env = append(cmd1.Env, "GIT_TERMINAL_PROMPT=1")
	cmd1.Env = append(cmd1.Env, "GIT_ASKPASS=")
	cmd1.Run()
	fmt.Println("oss代码已经拉取下来,存放在本地:D:/impromptu")

	//执行上传文件到linux静态资源文件
	fmt.Println("开始上传文件到 Linux服务器...")
	cmd := exec.Command("E:/go/goproject/src/go_code/project01/upload.exe")
	out1, err := cmd.Output()
	if err != nil {
		fmt.Println(err)
		return
	}
	if strings.Contains(string(out1), "successfully") {
		fmt.Println("上传文到服务器 执行成功,请到浏览器刷新查看是否更新")
	} else {
		fmt.Println("你的文件上传到服务器失败,请查看问题!")
	}

	//执行 上传文件到oss Go 文件
	fmt.Println("开始上传文件到 OSS...")
	cmd2 := exec.Command("E:/go/goproject/src/go_code/golang01/oss.exe")
	out, err := cmd2.Output()
	if err != nil {
		fmt.Println(err)
		return
	}
	if strings.Contains(string(out), "successfully") {
		fmt.Println("上传oss文件执行成功,请到oss查看文件是否存在")
	} else {
		fmt.Println("你的oss上传文件失败,请查看问题!")
	}

	// 执行刷新cdn缓存 Go 文件
	fmt.Println("执行刷新cdn缓存 Go 文件...")
	cmd3 := exec.Command("E:/go/goproject/src/go_code/golang02/cdn.exe")
	out2, err := cmd3.Output()
	if err != nil {
		fmt.Println(err)
		return
	}
	if strings.Contains(string(out2), "successfully") {
		fmt.Println("刷新cdn缓存文件执行成功,请到CDN查看操作记录")
	} else {
		fmt.Println("你的刷新cdn缓存失败,请查看问题!")
	}
}

执行结果

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第1张图片

查看有没有拉取代码下来

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第2张图片

任务二上传静态文件到服务器

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

func main() {
	// 获取远程服务器地址和 port
	host := "xxx"
	port := "xxxx"

	// 获取远程服务器用户名和登录密码
	user := "root"
	password := "xxxx"

	// 获取本地文件路径和文件名
	localPath := "D:\\impromptu\\web" // 本地文件夹路径

	// 获取远程服务器目标路径
	remotePath := "/front/nginx/html/test/web" // 远程目录路径

	// 建立 SSH 连接
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}
	conn, err := ssh.Dial("tcp", host+":"+port, config)
	if err != nil {
		fmt.Printf("无法连接到远程服务器:%s\n", err.Error())
		os.Exit(1)
	}
	defer conn.Close()

	// 建立 SFTP 客户端
	client, err := sftp.NewClient(conn)
	if err != nil {
		fmt.Printf("创建 SFTP 客户端失败:%s\n", err.Error())
		os.Exit(1)
	}
	defer client.Close()

	// 遍历本地目录中的文件,并上传到远程服务器
	err = filepath.Walk(localPath, func(filePath string, info os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf("遍历本地目录失败:%s\n", err.Error())
			return err
		}

		// 判断是否是目录,如果是则创建远程目录
		if info.IsDir() {
			// 获取相对路径,并拼接到远程目录路径上
			relativePath := strings.TrimPrefix(filePath, localPath)
			remoteDir := filepath.ToSlash(filepath.Join(remotePath, relativePath))

			err = client.MkdirAll(remoteDir)
			if err != nil {
				fmt.Printf("创建远程目录失败:%s\n", err.Error())
				return err
			}
			fmt.Printf("已在远程服务器上创建目录:%s\n", remoteDir)
		} else {
			// 读取文件内容并上传到远程服务器
			fileBytes, err := ioutil.ReadFile(filePath)
			if err != nil {
				fmt.Printf("读取本地文件失败:%s\n", err.Error())
				return err
			}

			// 获取文件名,并拼接到远程目录路径上
			fileName := info.Name()
			remoteFile := filepath.ToSlash(filepath.Join(remotePath, fileName))

			remoteWriter, err := client.Create(remoteFile)
			if err != nil {
				fmt.Printf("在远程服务器上创建文件失败:%s\n", err.Error())
				return err
			}

			_, err = remoteWriter.Write(fileBytes)
			if err != nil {
				fmt.Printf("向远程服务器写入文件内容失败:%s\n", err.Error())
				return err
			}
			fmt.Printf("已将本地文件 %s 上传到远程服务器:%s\n", filePath, remoteFile)
		}

		return nil
	})

	if err != nil {
		fmt.Printf("上传文件失败:%s\n", err.Error())
		os.Exit(1)
	}

	fmt.Println("文件上传完成!successfully.")
}

执行结果

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第3张图片

查看服务器上面有没有资源

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第4张图片

任务三上-图库到阿里云OSS

// 这个是分资源上传到oss
package main

import (
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	// 阿里云OSS相关配置信息
	endpoint := "xxxxx"
	accessKeyId := "xxxx"
	accessKeySecret := "xxxx"
	bucketName := "oss-cicd"

	// 创建阿里云OSS客户端
	client, err := oss.New(endpoint, accessKeyId, accessKeySecret)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 获取要操作的Bucket
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 定义本地目录和OSS目录
	localDir := "D:/impromptu/oss/"
	ossDir := "oss/"

	// 递归遍历本地目录下所有文件和子目录
	err = filepath.Walk(localDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 如果是子目录,则在OSS上创建同名目录
		if info.IsDir() {
			dirName := strings.TrimPrefix(strings.ReplaceAll(path, "\\", "/"), localDir)
			if dirName == "" {
				return nil
			}
			ossPath := filepath.ToSlash(filepath.Join(ossDir, dirName)) + "/"
			fmt.Printf("Creating OSS directory %s\n", ossPath)
			err = bucket.PutObject(ossPath, strings.NewReader(""))
			if err != nil {
				return err
			}
		} else {
			// 如果是文件,则上传到OSS中对应的目录
			fileName := strings.TrimPrefix(strings.ReplaceAll(path, "\\", "/"), localDir)
			ossPath := filepath.ToSlash(filepath.Join(ossDir, fileName))
			fmt.Printf("Uploading file %s to OSS path %s\n", path, ossPath)

			// 读取本地文件内容
			content, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			}

			// 上传文件到OSS
			err = bucket.PutObject(ossPath, strings.NewReader(string(content)))
			if err != nil {
				return err
			}
		}

		return nil
	})

	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	fmt.Println("All objects uploaded successfully.")
}

执行结果

使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第5张图片

查看阿里云OSS
使用 Golang 在 GitLab 上拉取代码并将静态资源部署到 Nginx,同时将图库上传至阿里云 OSS_第6张图片

任务四-刷新阿里云CDN

这一步如果你们没有CDN可以忽略,我们有配置cdn内容分发网络,每次更新都需要刷新一下缓存

// This file is auto-generated, don't edit it. Thanks.
package main

import (
	"fmt"
	cdn "github.com/alibabacloud-go/cdn-20180510/v2/client"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
)

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
func CreateClient(accessKeyId *string, accessKeySecret *string) (_result *cdn.Client, _err error) {
	config := &openapi.Config{
		// 必填,您的 AccessKey ID
		AccessKeyId: accessKeyId,
		// 必填,您的 AccessKey Secret
		AccessKeySecret: accessKeySecret,
	}
	// 访问的域名
	config.Endpoint = tea.String("cdn.aliyuncs.com")
	_result = &cdn.Client{}
	_result, _err = cdn.NewClient(config)
	return _result, _err
}

func _main() (_err error) {
	// 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
	// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html
	client, _err := CreateClient(tea.String("xxxx"), tea.String("xxxx"))
	if _err != nil {
		return _err
	}

	refreshObjectCachesRequest := &cdn.RefreshObjectCachesRequest{
		ObjectPath: tea.String("https://xxxx.com/"),
		ObjectType: tea.String("Directory"),
	}
	runtime := &util.RuntimeOptions{}
	tryErr := func() (_e error) {
		defer func() {
			if r := tea.Recover(recover()); r != nil {
				_e = r
			}
		}()
		// 复制代码运行请自行打印 API 的返回值
		_, _err = client.RefreshObjectCachesWithOptions(refreshObjectCachesRequest, runtime)
		if _err != nil {
			return _err
		}

		return nil
	}()

	if tryErr != nil {
		var error = &tea.SDKError{}
		if _t, ok := tryErr.(*tea.SDKError); ok {
			error = _t
		} else {
			error.Message = tea.String(tryErr.Error())
		}
		// 如有需要,请打印 error
		_, _err = util.AssertAsString(error.Message)
		fmt.Println(_err)
		if _err != nil {
			return _err
		}
	}
	return _err
}

func main() {
	err := _main()
	if err != nil {
		panic(err)
	}
	fmt.Println("完成刷新CDN缓存 successfully.")
}

ea.SDKError{}
if _t, ok := tryErr.(*tea.SDKError); ok {
error = _t
} else {
error.Message = tea.String(tryErr.Error())
}
// 如有需要,请打印 error
_, _err = util.AssertAsString(error.Message)
fmt.Println(_err)
if _err != nil {
return _err
}
}
return _err
}

func main() {
err := _main()
if err != nil {
panic(err)
}
fmt.Println(“完成刷新CDN缓存 successfully.”)
}


你可能感兴趣的:(go语言专栏,golang,gitlab,nginx)