255 lines
7.0 KiB
Go
255 lines
7.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
)
|
|
|
|
func main() {
|
|
// Create a logger to write error messages
|
|
logFile, err := os.OpenFile("action.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
|
if err != nil {
|
|
fmt.Printf("Error while creating the log file: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
defer logFile.Close()
|
|
multiWriter := io.MultiWriter(os.Stdout, logFile)
|
|
logger := log.New(multiWriter, "", log.LstdFlags)
|
|
|
|
// Retrieve environment variables
|
|
issueOdooTicketString := os.Getenv("ODOO_TICKET_NUMBER")
|
|
logger.Printf("ODOO_TICKET_NUMBER: %s\n", issueOdooTicketString)
|
|
|
|
issueTitle := os.Getenv("ISSUE_TITLE")
|
|
|
|
labelsEnv := os.Getenv("ISSUE_LABELS")
|
|
logger.Printf("ISSUE_LABELS: %s\n", labelsEnv)
|
|
|
|
issueNumberString := os.Getenv("ISSUE_NUMBER")
|
|
|
|
giteaToken := os.Getenv("GITEA_TOKEN")
|
|
giteaAPIURL := "https://gitea.ethumada.com"
|
|
repoOwner := os.Getenv("REPO_OWNER")
|
|
repoName := os.Getenv("REPO_NAME")
|
|
|
|
if issueOdooTicketString == "" || issueNumberString == "" || issueTitle == "" || giteaToken == "" || repoOwner == "" || repoName == "" {
|
|
logger.Println("Error: some environment variables are missing.")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Convert the issue number to int64
|
|
issueNumber, err := strconv.ParseInt(issueNumberString, 10, 64)
|
|
if err != nil {
|
|
logger.Printf("Error while converting the issue number: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Convert the odoo ticket number to int64
|
|
issueOdooTicketID, err := strconv.ParseInt(issueOdooTicketString, 10, 64)
|
|
if err != nil {
|
|
logger.Printf("Error while converting the Odoo ticket number: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
logger.Printf("Odoo ticket ID: %d\n", issueOdooTicketID)
|
|
|
|
// Map labels to Git Flow prefixes
|
|
labels := parseLabels(labelsEnv, logger)
|
|
if len(labels) > 0 {
|
|
logger.Printf("Extracted labels: %s\n", strings.Join(labels, ", "))
|
|
}
|
|
prefix := "feature"
|
|
prefix, err = getPrefixFromLabels(labels)
|
|
if err != nil {
|
|
logger.Printf("Error while determining the prefix: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
logger.Printf("Chosen prefix: %s\n", prefix)
|
|
|
|
// Form the branch name in the format "prefix/ticket-number"
|
|
branchName := fmt.Sprintf("%s/ticket-%d", prefix, issueOdooTicketID)
|
|
|
|
logger.Printf("Branch name set to: %s\n", branchName)
|
|
|
|
// Configure Git
|
|
logger.Println("Configuring Git...")
|
|
err = runCommand(logger, "git", "config", "--global", "user.name", "gitea-actions")
|
|
if err != nil {
|
|
logger.Printf("Error while configuring Git: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = runCommand(logger, "git", "fetch", "origin")
|
|
if err != nil {
|
|
logger.Printf("Error while updating remote references")
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = runCommand(logger, "git", "config", "--global", "user.email", "actions@gitea.com")
|
|
if err != nil {
|
|
logger.Printf("Error while configuring Git: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Check if the branch already exists
|
|
logger.Printf("Checking if branch '%s' exists...\n", branchName)
|
|
output, err := exec.Command("git", "ls-remote", "--heads", "origin", branchName).CombinedOutput()
|
|
if err != nil {
|
|
logger.Printf("Error while checking the branch: %v\nOutput: %s\n", err, string(output))
|
|
os.Exit(1)
|
|
}
|
|
|
|
branchExists := false
|
|
if strings.TrimSpace(string(output)) != "" {
|
|
branchExists = true
|
|
}
|
|
|
|
if branchExists {
|
|
logger.Printf("Branch '%s' already exists. No action taken.\n", branchName)
|
|
} else {
|
|
// Create and push the branch
|
|
originBranch := "origin/develop"
|
|
|
|
logger.Printf("Prefix is : %s", prefix)
|
|
if prefix == "hotfix" {
|
|
originBranch = "origin/main"
|
|
} else {
|
|
logger.Printf("hotfix != %s", prefix)
|
|
}
|
|
|
|
logger.Printf("Creating branch '%s' from '%s'.\n", branchName, originBranch)
|
|
err = runCommand(logger, "git", "checkout", "-b", branchName, originBranch)
|
|
if err != nil {
|
|
logger.Printf("Error while creating the branch: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = runCommand(logger, "git", "push", "origin", branchName)
|
|
if err != nil {
|
|
logger.Printf("Error while pushing the branch: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
logger.Printf("Branch '%s' successfully created and pushed.\n", branchName)
|
|
}
|
|
|
|
// Assign the branch to the issue via the Gitea API
|
|
logger.Printf("Assigning branch '%s' to issue #%d.\n", branchName, issueOdooTicketID)
|
|
|
|
// Create the Gitea client
|
|
client, err := gitea.NewClient(giteaAPIURL, gitea.SetToken(giteaToken))
|
|
if err != nil {
|
|
logger.Printf("Error while creating the Gitea client: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Prepare options to edit the issue
|
|
editIssueOption := gitea.EditIssueOption{
|
|
Ref: &branchName,
|
|
}
|
|
|
|
// Update the issue with the branch reference
|
|
_, _, err = client.EditIssue(repoOwner, repoName, issueNumber, editIssueOption)
|
|
if err != nil {
|
|
logger.Printf("Error while assigning the branch to the issue: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
logger.Printf("Branch '%s' successfully assigned to issue #%d.\n", branchName, issueNumber)
|
|
}
|
|
|
|
// Function to map labels to prefixes
|
|
func getPrefixFromLabels(labels []string) (string, error) {
|
|
// Define the label ➔ prefix correspondence
|
|
labelPrefixMap := map[string]string{
|
|
"enhancement": "feature",
|
|
"invalid": "bugfix",
|
|
"bug": "hotfix",
|
|
}
|
|
|
|
// Create a mapping with lower-case keys
|
|
labelPrefixMapLower := make(map[string]string)
|
|
for key, value := range labelPrefixMap {
|
|
keyLower := strings.ToLower(key)
|
|
labelPrefixMapLower[keyLower] = value
|
|
}
|
|
|
|
for _, label := range labels {
|
|
trimmed := strings.TrimSpace(label)
|
|
labelLower := strings.ToLower(trimmed)
|
|
fmt.Printf("Current label: %s\n", labelLower)
|
|
if prefix, exists := labelPrefixMapLower[labelLower]; exists {
|
|
return prefix, nil
|
|
}
|
|
}
|
|
|
|
return "feature", nil
|
|
}
|
|
|
|
// Parse ISSUE_LABELS env which can be:
|
|
// - JSON array of strings: ["bug", "enhancement"]
|
|
// - JSON array of objects: [{"name":"bug"},{"name":"ui"}]
|
|
// - Comma-separated string: "bug, enhancement"
|
|
func parseLabels(raw string, logger *log.Logger) []string {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
|
|
// Try JSON array of strings
|
|
var arrStr []string
|
|
if err := json.Unmarshal([]byte(raw), &arrStr); err == nil {
|
|
return arrStr
|
|
}
|
|
|
|
// Try JSON array of objects with name
|
|
type lbl struct {
|
|
Name string `json:"name"`
|
|
}
|
|
var arrObj []lbl
|
|
if err := json.Unmarshal([]byte(raw), &arrObj); err == nil {
|
|
out := make([]string, 0, len(arrObj))
|
|
for _, o := range arrObj {
|
|
if o.Name != "" {
|
|
out = append(out, o.Name)
|
|
}
|
|
}
|
|
if len(out) > 0 {
|
|
return out
|
|
}
|
|
}
|
|
|
|
// Fallback: comma-separated values
|
|
if strings.Contains(raw, ",") {
|
|
parts := strings.Split(raw, ",")
|
|
for i := range parts {
|
|
parts[i] = strings.TrimSpace(parts[i])
|
|
}
|
|
return parts
|
|
}
|
|
|
|
// Last resort: if it looks like JSON but couldn't parse, log and return nil
|
|
if strings.HasPrefix(raw, "[") || strings.HasPrefix(raw, "{") {
|
|
logger.Printf("Warning: could not parse ISSUE_LABELS JSON: %s\n", raw)
|
|
return nil
|
|
}
|
|
|
|
// Otherwise single token
|
|
return []string{raw}
|
|
}
|
|
|
|
func runCommand(logger *log.Logger, name string, arg ...string) error {
|
|
cmd := exec.Command(name, arg...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
logger.Printf("Executing command: %s %s\n", name, strings.Join(arg, " "))
|
|
return cmd.Run()
|
|
}
|