Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(helm): auto public Helm chart after PR merged #7526

Merged
merged 31 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b927065
ci(helm): auto public Helm chart after PR merged
afdesk Sep 17, 2024
a2792b3
auto update version
afdesk Sep 17, 2024
5eeb8b5
add auto bumping Trivy version
afdesk Sep 17, 2024
4929dc9
stop test running for PRs
afdesk Sep 17, 2024
f11fe42
update scripts
afdesk Sep 17, 2024
2c50e8f
ignore test for Helm Chart
afdesk Sep 17, 2024
fc36fa7
fix paths
afdesk Sep 17, 2024
3de2147
using ORG_REPO_TOKEN
afdesk Sep 17, 2024
f3b1e56
update PR's label
afdesk Sep 17, 2024
cde5dcf
skip test for push action
afdesk Sep 17, 2024
ea1ba74
add closed typde to default values
afdesk Sep 18, 2024
09b27ec
add comments for jobs
afdesk Sep 18, 2024
5023312
rename a branch
afdesk Sep 18, 2024
6be5a2c
remove label
afdesk Oct 17, 2024
7d2fe14
add mage option for update helm version
afdesk Oct 17, 2024
dc3983a
add git commands
afdesk Oct 17, 2024
04e22f7
remove bash script
afdesk Oct 17, 2024
7e2468f
lint refactor package position
afdesk Oct 17, 2024
8912178
update workflow
afdesk Oct 17, 2024
2cd234b
fix: escaping PR description
afdesk Oct 17, 2024
ebbe1bf
remove quotes
afdesk Oct 17, 2024
fcb4bf4
update description
afdesk Oct 17, 2024
5a43735
refactor: rename variables
afdesk Oct 22, 2024
1e4b16c
refactor: megrate to go-version
afdesk Oct 22, 2024
8d5a183
refacror: bump versions inside Chart file
afdesk Oct 22, 2024
27e38b7
refactor: misc
afdesk Oct 22, 2024
f309ab1
test: using t.TempDir
afdesk Oct 24, 2024
adbfad3
refactor: using os instead of ioutil
afdesk Oct 24, 2024
649987e
chore: bump up os version on runner
afdesk Oct 24, 2024
d730f7c
chore: bump up helm clis versions
afdesk Oct 24, 2024
67137a2
test: refactor os actions
afdesk Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/bypass-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ on:
- 'mkdocs.yml'
- 'LICENSE'
- '.release-please-manifest.json'
- 'helm/trivy/Chart.yaml'
pull_request:
paths:
- '**.md'
- 'docs/**'
- 'mkdocs.yml'
- 'LICENSE'
- '.release-please-manifest.json'
- 'helm/trivy/Chart.yaml'
jobs:
test:
name: Test
Expand Down
46 changes: 41 additions & 5 deletions .github/workflows/publish-chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ name: Publish Helm chart
on:
workflow_dispatch:
pull_request:
types:
- opened
- synchronize
- reopened
- closed
afdesk marked this conversation as resolved.
Show resolved Hide resolved
branches:
- main
paths:
DmitriyLewen marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -18,8 +23,10 @@ env:
KIND_VERSION: "v0.14.0"
KIND_IMAGE: "kindest/node:v1.23.6@sha256:b1fa224cc6c7ff32455e0b1fd9cbfd3d3bc87ecaa8fcb06961ed1afb3db0f9ae"
jobs:
# `test-chart` job starts if a PR with Helm Chart is created, merged etc.
test-chart:
runs-on: ubuntu-20.04
if: github.event_name != 'push'
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
Expand All @@ -28,11 +35,12 @@ jobs:
- name: Install Helm
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814
with:
version: v3.5.0
version: v3.14.4
- name: Set up python
uses: actions/setup-python@v5
with:
python-version: 3.7
python-version: '3.x'
check-latest: true
- name: Setup Chart Linting
id: lint
uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992
Expand All @@ -48,11 +56,39 @@ jobs:
sed -i -e '136s,false,'true',g' ./helm/trivy/values.yaml
ct lint-and-install --validate-maintainers=false --charts helm/trivy

# `update-chart-version` job starts if a new tag is pushed
update-chart-version:
if: github.event_name == 'push'
afdesk marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
with:
fetch-depth: 0
- name: Set up Git user
run: |
git config --global user.email "[email protected]"
git config --global user.name "GitHub Actions"

- name: Install tools
uses: aquaproj/[email protected]
with:
aqua_version: v1.25.0
aqua_opts: ""

- name: Create a PR with Trivy version
run: mage helm:updateVersion
env:
# Use ORG_REPO_TOKEN instead of GITHUB_TOKEN
# This allows the created PR to trigger tests and other workflows
GITHUB_TOKEN: ${{ secrets.ORG_REPO_TOKEN }}

# `publish-chart` job starts if a PR with a new Helm Chart is merged or manually
publish-chart:
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
DmitriyLewen marked this conversation as resolved.
Show resolved Hide resolved
needs:
- test-chart
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- 'mkdocs.yml'
- 'LICENSE'
- '.release-please-manifest.json' ## don't run tests for release-please PRs
- 'helm/trivy/Chart.yaml'
merge_group:
env:
GO_VERSION: '1.22'
Expand Down
117 changes: 117 additions & 0 deletions magefiles/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//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)
}

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
}
92 changes: 92 additions & 0 deletions magefiles/helm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//go:build mage_helm

package main

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewVersion(t *testing.T) {
tests := []struct {
name string
currentHelmVersion string
currentTrivyVersion string
newTrivyVersion string
newHelmVersion string
}{
{
"created the first patch",
"0.1.0",
"0.55.0",
"0.55.1",
"0.1.1",
},
{
"created the second patch",
"0.1.1",
"0.55.1",
"0.55.2",
"0.1.2",
},
{
"created the second patch but helm chart was changed",
"0.1.2",
"0.55.1",
"0.55.2",
"0.1.3",
},
{
"created a new minor version",
"0.1.1",
"0.55.1",
"0.56.0",
"0.2.0",
},
{
"created a new major version",
"0.1.1",
"0.55.1",
"1.0.0",
"1.0.0",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
newHelmVersion, err := buildNewHelmVersion(test.currentHelmVersion, test.currentTrivyVersion, test.newTrivyVersion)
assert.NoError(t, err)
assert.Equal(t, test.newHelmVersion, newHelmVersion)
})
}
}

func TestBumpHelmChart_Success(t *testing.T) {
tempFile, err := os.CreateTemp(t.TempDir(), "Chart-*.yaml")
assert.NoError(t, err)

content := `
apiVersion: v2
name: trivy
version: 0.8.0
appVersion: 0.55.0
description: Trivy helm chart
keywords:
- scanner
- trivy
- vulnerability
`
err = os.WriteFile(tempFile.Name(), []byte(content), 0644)
assert.NoError(t, err)

newVersion, err := bumpHelmChart(tempFile.Name(), "0.55.1")
assert.NoError(t, err)
assert.Equal(t, "0.8.1", newVersion)

updatedContent, err := os.ReadFile(tempFile.Name())
assert.NoError(t, err)
assert.Contains(t, string(updatedContent), "appVersion: 0.55.1")
assert.Contains(t, string(updatedContent), "version: 0.8.1")
}
7 changes: 7 additions & 0 deletions magefiles/magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,10 @@ func (CloudActions) Generate() error {
func VEX(_ context.Context, dir string) error {
return sh.RunWith(ENV, "go", "run", "-tags=mage_vex", "./magefiles/vex.go", "--dir", dir)
}

type Helm mg.Namespace

// UpdateVersion updates a version for Trivy Helm Chart and creates a PR
func (Helm) UpdateVersion() error {
return sh.RunWith(ENV, "go", "run", "-tags=mage_helm", "./magefiles")
}