使用Golang创建属于自己的GitHub Action

使用Golang创建属于自己的GitHub Action Creating Your OWN GitHub Action Using Go (golang) [Getting Started]

1 回复

更多关于使用Golang创建属于自己的GitHub Action的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用Golang创建GitHub Action的完整实现

下面是一个完整的Go语言GitHub Action示例,它可以在工作流中执行自定义逻辑:

1. 项目结构

my-github-action/
├── action.yml
├── main.go
├── go.mod
└── Dockerfile

2. action.yml - Action元数据

name: 'Go GitHub Action'
description: 'A custom GitHub Action built with Go'
inputs:
  greeting:
    description: 'Greeting message'
    required: true
    default: 'Hello'
  who-to-greet:
    description: 'Person to greet'
    required: true
    default: 'World'
outputs:
  time:
    description: 'The time we greeted you'
runs:
  using: 'docker'
  image: 'Dockerfile'

3. main.go - 核心逻辑

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"time"
)

func main() {
	// 读取输入参数
	greeting := getInput("greeting")
	whoToGreet := getInput("who-to-greet")
	
	// 执行Action逻辑
	message := fmt.Sprintf("%s, %s!", greeting, whoToGreet)
	fmt.Println(message)
	
	// 设置输出参数
	setOutput("time", time.Now().Format(time.RFC3339))
	
	// 设置GitHub Action环境变量
	setEnv("GREETING_MESSAGE", message)
}

func getInput(name string) string {
	return os.Getenv(fmt.Sprintf("INPUT_%s", toEnvVarName(name)))
}

func setOutput(name, value string) {
	outputFile := os.Getenv("GITHUB_OUTPUT")
	if outputFile != "" {
		f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY, 0644)
		if err == nil {
			defer f.Close()
			fmt.Fprintf(f, "%s=%s\n", name, value)
		}
	}
	fmt.Printf("::set-output name=%s::%s\n", name, value)
}

func setEnv(name, value string) {
	envFile := os.Getenv("GITHUB_ENV")
	if envFile != "" {
		f, err := os.OpenFile(envFile, os.O_APPEND|os.O_WRONLY, 0644)
		if err == nil {
			defer f.Close()
			fmt.Fprintf(f, "%s=%s\n", name, value)
		}
	}
}

func toEnvVarName(s string) string {
	var result []rune
	for i, r := range s {
		if r == '-' {
			continue
		}
		if i > 0 && s[i-1] == '-' {
			result = append(result, toUpper(r))
		} else {
			result = append(result, r)
		}
	}
	return string(result)
}

func toUpper(r rune) rune {
	if r >= 'a' && r <= 'z' {
		return r - ('a' - 'A')
	}
	return r
}

4. Dockerfile - 容器配置

FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY *.go ./
RUN go build -o /action

FROM alpine:latest
COPY --from=builder /action /action
ENTRYPOINT ["/action"]

5. go.mod - 模块定义

module github.com/yourusername/my-github-action

go 1.21

6. 使用示例 - 在工作流中调用

name: Test Go Action
on: [push]

jobs:
  test-action:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run Custom Go Action
        id: greet
        uses: yourusername/my-github-action@v1
        with:
          greeting: 'Hola'
          who-to-greet: 'GitHub Actions'
      
      - name: Use Output
        run: |
          echo "Greeted at ${{ steps.greet.outputs.time }}"
          echo "Message was ${{ env.GREETING_MESSAGE }}"

7. 本地测试脚本

// test_local.go
package main

import (
	"os"
	"testing"
)

func TestActionLocally() {
	// 模拟GitHub Action环境变量
	os.Setenv("INPUT_greeting", "Hello")
	os.Setenv("INPUT_who-to-greet", "Local Test")
	os.Setenv("GITHUB_OUTPUT", "/tmp/output.txt")
	os.Setenv("GITHUB_ENV", "/tmp/env.txt")
	
	main()
	
	// 读取输出
	output, _ := os.ReadFile("/tmp/output.txt")
	env, _ := os.ReadFile("/tmp/env.txt")
	
	fmt.Printf("Output: %s\n", output)
	fmt.Printf("Env: %s\n", env)
}

这个实现展示了如何创建一个完整的GitHub Action,包括参数处理、输出设置、环境变量管理,以及如何打包为Docker容器。Action可以通过GitHub Marketplace分发或在仓库中直接引用。

回到顶部