dockerbuild/main.go
Ondrej Vlach 302df33baa
All checks were successful
Go Test / test (push) Successful in 25s
initial commit
2025-05-30 20:10:33 +02:00

144 lines
3.9 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"strings"
"time"
gha "github.com/sethvargo/go-githubactions"
)
func getShortHash() string {
// Get short git commit hash
gitCmd := exec.Command("git", "rev-parse", "--short", "HEAD")
gitCmd.Dir = "."
gitCmd.Stderr = os.Stderr
hashBytes, err := gitCmd.Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get git hash: %v\n", err)
os.Exit(1)
}
shortHash := string(hashBytes)
shortHash = shortHash[:len(shortHash)-1] // remove trailing newline
return shortHash
}
func parseSecrets(secretsInput string) map[string]string {
secrets := make(map[string]string)
if secretsInput != "" {
scanner := bufio.NewScanner(strings.NewReader(secretsInput))
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
val := strings.Trim(strings.TrimSpace(parts[1]), `"`)
secrets[key] = val
}
}
}
return secrets
}
func buildDockerCommand(context string, dockerFile string, secrets map[string]string, tagLatest string, tagNightly string) *exec.Cmd {
// Parse secrets and write to .secrets file
buildArgs := []string{}
if len(secrets) > 0 {
f, err := os.CreateTemp("", ".secrets")
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create .secrets file: %v\n", err)
os.Exit(1)
}
defer f.Close()
for secretKey, secretVal := range secrets {
_, err := fmt.Fprintf(f, "%s=%s\n", secretKey, secretVal)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write secret: %v\n", err)
os.Exit(1)
}
}
buildArgs = append(buildArgs, "--secret", "id=build_secrets,src="+f.Name())
}
// Build command
buildArgsExpanded := append([]string{"build", context, "-f", dockerFile, "-t", tagLatest, "-t", tagNightly}, buildArgs...)
buildCmd := exec.Command("docker", buildArgsExpanded...)
buildCmd.Env = append(os.Environ(), "DOCKER_BUILDKIT=1")
buildCmd.Stdout = os.Stdout
buildCmd.Stderr = os.Stderr
return buildCmd
}
func pushDockerCommand(tag string) *exec.Cmd {
// Push nightly tag
pushNightlyCmd := exec.Command("docker", "push", tag)
pushNightlyCmd.Stdout = os.Stdout
pushNightlyCmd.Stderr = os.Stderr
return pushNightlyCmd
}
func main() {
basePath := gha.GetInput("path")
imageName := gha.GetInput("image-name")
dockerFile := gha.GetInput("dockerfile")
context := gha.GetInput("context")
secrets := parseSecrets(gha.GetInput("secrets"))
date := time.Now().Format("2006-01-02")
shortHash := getShortHash()
if basePath == "" {
fmt.Fprintln(os.Stderr, "Error: 'path' input is required")
os.Exit(1)
}
if imageName == "" {
fmt.Fprintln(os.Stderr, "Error: 'image-name' input is required")
os.Exit(1)
}
if basePath[len(basePath)-1] != '/' {
basePath += "/"
}
// Construct image names
imageBase := fmt.Sprintf("%s%s", basePath, imageName)
tagLatest := fmt.Sprintf("%s:latest", imageBase)
tagNightly := fmt.Sprintf("%s:nightly-%s.%s", imageBase, date, shortHash)
// Build Docker command
buildCmd := buildDockerCommand(context, dockerFile, secrets, tagLatest, tagNightly)
fmt.Println("Running:", buildCmd.String())
if err := buildCmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Build failed: %v\n", err)
os.Exit(1)
}
// Push nightly tag
pushNightlyCmd := pushDockerCommand(tagNightly)
fmt.Println("Running:", pushNightlyCmd.String())
if err := pushNightlyCmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Push nightly failed: %v\n", err)
os.Exit(1)
}
// Push latest tag
pushLatestCmd := pushDockerCommand(tagLatest)
fmt.Println("Running:", pushLatestCmd.String())
if err := pushLatestCmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Push latest failed: %v\n", err)
os.Exit(1)
}
gha.SetOutput("image_tag", fmt.Sprintf("%s:%s", imageBase, shortHash))
gha.SetOutput("full_image_name", tagLatest)
}