yq/pipeline/alpine-publisher/main.go

191 lines
6.1 KiB
Go

package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"regexp"
"strconv"
"github.com/buger/jsonparser"
"github.com/xanzy/go-gitlab"
)
// Checks for the latest yq version and if there is a new one,
// creates a new branch on alpine gitlab with the changes to update to the new version.
// Make sure to already have a fork of alpine/aports ready and an access token (api) created.
func main() {
// Injected (Env) variables
gitlabToken := os.Getenv("ALPINE_GITLAB_ACCESS_TOKEN")
gitlabForkRepo := os.Getenv("ALPINE_GITLAB_FORK_REPO")
gitUsername := os.Getenv("GIT_USERNAME")
gitEmail := os.Getenv("GIT_EMAIL")
autocreateMergeRequest, _ := strconv.ParseBool(os.Getenv("AUTOCREATE_MERGE_REQUEST"))
// Debug
//gitlabToken = "xxx"
//gitlabForkRepo = "xxx/aports"
//gitUsername = "xxx xxx"
//gitEmail = "xxx@xxx.xxx"
//autocreateMergeRequest = true
// Variables
gitlabBaseUrl := "gitlab.alpinelinux.org"
gitlabRemoteRepo := "alpine/aports"
gitlabMainBranch := "master"
tempCheckoutPath := "./temp_checkout"
// Cleanup
err := os.RemoveAll(tempCheckoutPath)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Checkout a fresh copy of the repo
fmt.Println("Cloning and updating repo...")
cloneUrl := fmt.Sprintf("https://%s/%s.git", gitlabBaseUrl, gitlabForkRepo)
err = exec.Command("git", "clone", cloneUrl, tempCheckoutPath).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Switch to work in this directory from now on
err = os.Chdir(tempCheckoutPath)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Register the upstream
err = exec.Command("git", "remote", "add", "upstream", fmt.Sprintf("https://%s/%s.git", gitlabBaseUrl, gitlabRemoteRepo)).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Update the forks main branch
err = exec.Command("git", "checkout", gitlabMainBranch).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err = exec.Command("git", "fetch", "upstream").Run()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err = exec.Command("git", "merge", fmt.Sprintf("upstream/%s", gitlabMainBranch)).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Get information about the latest version and its hash
fmt.Println("Checking for new version...")
packageUser := "mikefarah"
packageRepo := "yq"
latestVersion := getLatestReleaseFromGithub(packageUser, packageRepo)
hash := calculateMd512FromUrl(fmt.Sprintf("https://github.com/%s/%s/archive/v%s.tar.gz", packageUser, packageRepo, latestVersion))
fmt.Printf("Found version %s\n", latestVersion)
// Prepare the new branch
branchName := fmt.Sprintf("feature/%s_%s_update", packageRepo, latestVersion)
err = exec.Command("git", "checkout", "-b", branchName).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Modify the file
fmt.Println("Updating file...")
apkFilePath := "./community/yq/APKBUILD"
fileContent, err := os.ReadFile(apkFilePath)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
regVersion, _ := regexp.Compile("pkgver=(.*)")
regChecksum, _ := regexp.Compile("(?m)sha512sums=\"(?:.|\n)*?\"")
newContent := regVersion.ReplaceAll(fileContent, []byte(fmt.Sprintf("pkgver=%s", latestVersion)))
newContent = regChecksum.ReplaceAll(newContent, []byte(fmt.Sprintf("sha512sums=\"\n%s yq-%s.tar.gz\n\"", hash, latestVersion)))
err = os.WriteFile(apkFilePath, []byte(newContent), 0)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// Check for changes and push the new branch
out, err := exec.Command("git", "ls-files", "--modified").Output()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
updateVersionText := fmt.Sprintf("Updated yq to %s", latestVersion)
if len(out) > 0 {
fmt.Println("Changes detected, pushing new branch")
err = exec.Command("git", "add", ".").Run()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err = exec.Command("git", "-c", fmt.Sprintf("user.name='%s'", gitUsername), "-c", fmt.Sprintf("user.email='%s'", gitEmail), "commit", "-m", updateVersionText).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err = exec.Command("git", "push", "-u", "--force", fmt.Sprintf("https://gitlab-ci-token:%s@%s/%s.git", gitlabToken, gitlabBaseUrl, gitlabForkRepo), branchName).Run() // #nosec G204
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
fmt.Printf("Pushed new branch. Branch url: https://%s/%s/-/tree/%s\n", gitlabBaseUrl, gitlabForkRepo, branchName)
} else {
fmt.Println("No changes detected, nothing to do.")
}
// Create a merge request for the new branch
if autocreateMergeRequest {
fmt.Println("Creating merge request")
git, _ := gitlab.NewClient(gitlabToken, gitlab.WithBaseURL(fmt.Sprintf("https://%s/api/v4", gitlabBaseUrl)))
projectRemote, _, _ := git.Projects.GetProject(gitlabRemoteRepo, &gitlab.GetProjectOptions{})
projectFork, _, _ := git.Projects.GetProject(gitlabForkRepo, &gitlab.GetProjectOptions{})
targetProjectId := projectRemote.ID
_, _, err := git.MergeRequests.CreateMergeRequest(projectFork.ID, &gitlab.CreateMergeRequestOptions{
Title: &updateVersionText,
SourceBranch: &branchName,
TargetBranch: &gitlabMainBranch,
TargetProjectID: &targetProjectId,
})
if err != nil {
fmt.Println("Error creating Merge Request.")
fmt.Println(err.Error())
os.Exit(1)
}
}
}
func getLatestReleaseFromGithub(user string, repo string) string {
var githubApiUrl = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", user, repo)
var jsonResponse, _ = http.Get(githubApiUrl) // #nosec G107
defer jsonResponse.Body.Close()
var jsonData, _ = ioutil.ReadAll(jsonResponse.Body)
var versionString, _ = jsonparser.GetString(jsonData, "tag_name")
return versionString[1:]
}
func calculateMd512FromUrl(url string) string {
var response, _ = http.Get(url) // #nosec G107
defer response.Body.Close()
var data, _ = ioutil.ReadAll(response.Body)
var hash = sha512.Sum512(data)
return hex.EncodeToString(hash[:])
}