Files
trivy/magefiles/helm.go

124 lines
3.9 KiB
Go

//go:build mage_helm
package main
import (
"fmt"
"log"
"os"
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/magefile/mage/sh"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"
)
const chartFile = "./helm/trivy/Chart.yaml"
func main() {
trivyVersion, err := version()
if err != nil {
log.Fatalf("could not determine Trivy version: %v", err)
}
// Checkout the main branch to get the latest chart version, that was changed after the previous release
// It needs for correctly updating the chart version of patch releases
if err := sh.Run("git", "checkout", "main"); err != nil {
log.Fatalf("failed to run `git checkout main`: %w", err)
}
newHelmVersion, err := bumpHelmChart(chartFile, trivyVersion)
if err != nil {
log.Fatalf("could not bump Trivy version to %q: %v", trivyVersion, err)
}
log.Printf("Current helm version will bump up %q with Trivy %q", newHelmVersion, trivyVersion)
newBranch := fmt.Sprintf("ci/helm-chart/bump-trivy-to-%s", trivyVersion)
title := fmt.Sprintf("ci(helm): bump Trivy version to %s for Trivy Helm Chart %s", trivyVersion, newHelmVersion)
description := fmt.Sprintf("This PR bumps Trivy up to the %s version for the Trivy Helm chart %s.",
trivyVersion, newHelmVersion)
cmds := [][]string{
[]string{"git", "switch", "-c", newBranch},
[]string{"git", "add", chartFile},
[]string{"git", "commit", "-m", title},
[]string{"git", "push", "origin", newBranch},
[]string{"gh", "pr", "create", "--base", "main", "--head", newBranch, "--title", title, "--body", description, "--repo", "$GITHUB_REPOSITORY"},
}
if err := runShCommands(cmds); err != nil {
log.Fatal(err)
}
log.Print("Successfully created PR with a new helm version")
}
type Chart struct {
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion"`
}
// bumpHelmChart bumps up helm and trivy versions inside a file (Chart.yaml)
// it returns a new helm version and error
func bumpHelmChart(filename, trivyVersion string) (string, error) {
input, err := os.ReadFile(filename)
if err != nil {
return "", xerrors.Errorf("could not read file %q: %w", filename, err)
}
currentHelmChart := &Chart{}
if err := yaml.Unmarshal(input, currentHelmChart); err != nil {
return "", xerrors.Errorf("could not unmarshal helm chart %q: %w", filename, err)
}
newHelmVersion, err := buildNewHelmVersion(currentHelmChart.Version, currentHelmChart.AppVersion, trivyVersion)
if err != nil {
return "", xerrors.Errorf("could not build new helm version: %v", err)
}
cmds := [][]string{
[]string{"sed", "-i", "-e", fmt.Sprintf("s/appVersion: %s/appVersion: %s/g", currentHelmChart.AppVersion, trivyVersion), filename},
[]string{"sed", "-i", "-e", fmt.Sprintf("s/version: %s/version: %s/g", currentHelmChart.Version, newHelmVersion), filename},
}
if err := runShCommands(cmds); err != nil {
return "", xerrors.Errorf("could not update Helm Chart %q: %w", newHelmVersion, err)
}
return newHelmVersion, nil
}
func runShCommands(cmds [][]string) error {
for _, cmd := range cmds {
if err := sh.Run(cmd[0], cmd[1:]...); err != nil {
return xerrors.Errorf("failed to run %v: %w", cmd, err)
}
}
return nil
}
func buildNewHelmVersion(currentHelm, currentTrivy, newTrivy string) (string, error) {
currentHelmVersion, err := semver.Parse(currentHelm)
if err != nil {
return "", xerrors.Errorf("could not parse current helm version: %w", err)
}
currentTrivyVersion, err := semver.Parse(currentTrivy)
if err != nil {
return "", xerrors.Errorf("could not parse current trivy version: %w", err)
}
newTrivyVersion, err := semver.Parse(newTrivy)
if err != nil {
return "", xerrors.Errorf("could not parse new trivy version: %w", err)
}
if newTrivyVersion.Major().Compare(currentTrivyVersion.Major()) > 0 {
return currentHelmVersion.IncMajor().String(), nil
}
if newTrivyVersion.Minor().Compare(currentTrivyVersion.Minor()) > 0 {
return currentHelmVersion.IncMinor().String(), nil
}
return currentHelmVersion.IncPatch().String(), nil
}