From 6199cebfeb1f73b0488692a4e3a41a167c0dc227 Mon Sep 17 00:00:00 2001 From: Horst Gutmann Date: Mon, 25 Nov 2024 16:06:13 +0100 Subject: [PATCH] ci: inject dockerfile dependency versions from workflow --- .github/workflows/acceptance-tests.yml | 22 +++++++++++- .github/workflows/docker.yml | 30 ++++++++++++++++ Dockerfile | 17 ++++----- Makefile | 3 +- dagger/dagger.gen.go | 48 +++++++++++++++++++++----- dagger/main.go | 17 ++++++--- 6 files changed, 115 insertions(+), 22 deletions(-) diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index bd2b92fa4..d7df1f83e 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -15,6 +15,26 @@ jobs: steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: "Determine dependency versions" + id: "versions" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const helmRelease = await github.rest.repos.getLatestRelease({ + 'owner': 'helm', + 'repo': 'helm', + }); + core.setOutput('helm', helmRelease.data.tag_name); + console.log('Helm version', helmRelease.data.tag_name); + const kustomizeReleases = await github.rest.repos.listReleases({ + 'owner': 'kubernetes-sigs', + 'repo': 'kustomize', + }); + const kustomizeRelease = kustomizeReleases.data.filter(release => release.tag_name.startsWith('kustomize') && !release.draft && !release.prerelease).map(release => release.tag_name.split('/')[1])[0]; + console.log('Kustomize version', kustomizeRelease); + core.setOutput('kustomize', kustomizeRelease); + - name: Call Dagger Function id: dagger uses: dagger/dagger-for-github@e5153f5610d82ac9f3f848f3a25ad9d696641068 # v7.0.1 @@ -22,4 +42,4 @@ jobs: version: "0.14.0" verb: call dagger-flags: "--silent" - args: "acceptance-tests --root-dir .:source-files --acceptance-tests-dir ./acceptance-tests" + args: "acceptance-tests --root-dir .:source-files --acceptance-tests-dir ./acceptance-tests --kustomize-version ${{ steps.versions.outputs.kustomize }} --helm-version ${{ steps.versions.outputs.helm }}" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 56b9cea6b..969bc82e1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -31,7 +31,34 @@ env: type=semver,pattern={{version}},value=${{ inputs.tag }},enable=${{ inputs.tag != '' }} jobs: + determine-versions: + runs-on: ubuntu-latest + outputs: + helm: ${{ steps.versions.outputs.helm }} + kustomize: ${{ steps.versions.outputs.kustomize }} + steps: + - name: "Determine dependency versions" + id: "versions" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const helmRelease = await github.rest.repos.getLatestRelease({ + 'owner': 'helm', + 'repo': 'helm', + }); + core.setOutput('helm', helmRelease.data.tag_name); + console.log('Helm version', helmRelease.data.tag_name); + const kustomizeReleases = await github.rest.repos.listReleases({ + 'owner': 'kubernetes-sigs', + 'repo': 'kustomize', + }); + const kustomizeRelease = kustomizeReleases.data.filter(release => release.tag_name.startsWith('kustomize') && !release.draft && !release.prerelease).map(release => release.tag_name.split('/')[1])[0]; + console.log('Kustomize version', kustomizeRelease); + core.setOutput('kustomize', kustomizeRelease); + build: + needs: + - determine-versions strategy: fail-fast: false matrix: @@ -66,6 +93,9 @@ jobs: context: . labels: ${{ steps.meta.outputs.labels }} outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ github.event_name == 'push' }} + build-args: | + HELM_VERSION=${{ needs.determine-versions.outputs.helm }} + KUSTOMIZE_VERSION=${{ needs.determine-versions.outputs.kustomize }} - name: Export digest id: digest diff --git a/Dockerfile b/Dockerfile index c10adfb5d..9bcda2d0e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,24 +19,25 @@ RUN apk add --no-cache git make bash &&\ FROM golang:1.23.3-alpine AS helm WORKDIR /tmp/helm +ARG HELM_VERSION RUN apk add --no-cache jq curl -RUN export TAG=$(curl --silent "https://api.github.com/repos/helm/helm/releases/latest" | jq -r .tag_name) &&\ - export OS=$(go env GOOS) &&\ +RUN export OS=$(go env GOOS) && \ export ARCH=$(go env GOARCH) &&\ - curl -SL "https://get.helm.sh/helm-${TAG}-${OS}-${ARCH}.tar.gz" > helm.tgz && \ + if [[ -z ${HELM_VERSION} ]]; then export HELM_VERSION=$(curl --silent "https://api.github.com/repos/helm/helm/releases" | jq -r '.[0].tag_name'); fi && \ + curl -SL "https://get.helm.sh/helm-${HELM_VERSION}-${OS}-${ARCH}.tar.gz" > helm.tgz && \ tar -xvf helm.tgz --strip-components=1 FROM golang:1.23.3-alpine AS kustomize WORKDIR /tmp/kustomize +ARG KUSTOMIZE_VERSION RUN apk add --no-cache jq curl # Get the latest version of kustomize # Releases are filtered by their name since the kustomize repository exposes multiple products in the releases -RUN export TAG=$(curl --silent "https://api.github.com/repos/kubernetes-sigs/kustomize/releases" | jq -r '[ .[] | select(.name | startswith("kustomize")) ] | .[0].tag_name') &&\ - export VERSION_TAG=${TAG#*/} &&\ - export OS=$(go env GOOS) &&\ +RUN export OS=$(go env GOOS) &&\ export ARCH=$(go env GOARCH) &&\ - echo "https://github.com/kubernetes-sigs/kustomize/releases/download/${TAG}/kustomize_${VERSION_TAG}_${OS}_${ARCH}.tar.gz" && \ - curl -SL "https://github.com/kubernetes-sigs/kustomize/releases/download/${TAG}/kustomize_${VERSION_TAG}_${OS}_${ARCH}.tar.gz" > kustomize.tgz && \ + if [[ -z ${KUSTOMIZE_VERSION} ]]; then export KUSTOMIZE_VERSION=$(curl --silent "https://api.github.com/repos/kubernetes-sigs/kustomize/releases" | jq -r '[ .[] | select(.name | startswith("kustomize")) ] | .[0].tag_name | split("/")[1]'); fi && \ + echo "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_${OS}_${ARCH}.tar.gz" && \ + curl -SL "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_${OS}_${ARCH}.tar.gz" > kustomize.tgz && \ tar -xvf kustomize.tgz FROM golang:1.23.3 AS build diff --git a/Makefile b/Makefile index 86c2598bd..7039d0e23 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ BIN_DIR := $(GOPATH)/bin GOX := $(BIN_DIR)/gox GOLINTER := $(GOPATH)/bin/golangci-lint + $(GOLINTER): go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3 @@ -15,7 +16,7 @@ test: go test ./... -bench=. -benchmem acceptance-tests: - dagger call acceptance-tests --root-dir .:source-files --acceptance-tests-dir ./acceptance-tests + dagger call acceptance-tests --root-dir .:source-files --acceptance-tests-dir ./acceptance-tests --kustomize-version "" --helm-version "" # Compilation dev: diff --git a/dagger/dagger.gen.go b/dagger/dagger.gen.go index 4e9cd97b7..49e2e2c7b 100644 --- a/dagger/dagger.gen.go +++ b/dagger/dagger.gen.go @@ -157,7 +157,21 @@ func invoke(ctx context.Context, parentJSON []byte, parentName string, fnName st panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg rootDir", err)) } } - return (*Tanka).Build(&parent, ctx, rootDir), nil + var helmVersion string + if inputArgs["helmVersion"] != nil { + err = json.Unmarshal([]byte(inputArgs["helmVersion"]), &helmVersion) + if err != nil { + panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg helmVersion", err)) + } + } + var kustomizeVersion string + if inputArgs["kustomizeVersion"] != nil { + err = json.Unmarshal([]byte(inputArgs["kustomizeVersion"]), &kustomizeVersion) + if err != nil { + panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg kustomizeVersion", err)) + } + } + return (*Tanka).Build(&parent, ctx, rootDir, helmVersion, kustomizeVersion), nil case "GetGoVersion": var parent Tanka err = json.Unmarshal(parentJSON, &parent) @@ -185,6 +199,20 @@ func invoke(ctx context.Context, parentJSON []byte, parentName string, fnName st panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg rootDir", err)) } } + var helmVersion string + if inputArgs["helmVersion"] != nil { + err = json.Unmarshal([]byte(inputArgs["helmVersion"]), &helmVersion) + if err != nil { + panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg helmVersion", err)) + } + } + var kustomizeVersion string + if inputArgs["kustomizeVersion"] != nil { + err = json.Unmarshal([]byte(inputArgs["kustomizeVersion"]), &kustomizeVersion) + if err != nil { + panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg kustomizeVersion", err)) + } + } var acceptanceTestsDir *dagger.Directory if inputArgs["acceptanceTestsDir"] != nil { err = json.Unmarshal([]byte(inputArgs["acceptanceTestsDir"]), &acceptanceTestsDir) @@ -192,7 +220,7 @@ func invoke(ctx context.Context, parentJSON []byte, parentName string, fnName st panic(fmt.Errorf("%s: %w", "failed to unmarshal input arg acceptanceTestsDir", err)) } } - return (*Tanka).AcceptanceTests(&parent, ctx, rootDir, acceptanceTestsDir) + return (*Tanka).AcceptanceTests(&parent, ctx, rootDir, helmVersion, kustomizeVersion, acceptanceTestsDir) default: return nil, fmt.Errorf("unknown function %s", fnName) } @@ -204,18 +232,22 @@ func invoke(ctx context.Context, parentJSON []byte, parentName string, fnName st dag.Function("Build", dag.TypeDef().WithObject("Container")). WithSourceMap(dag.SourceMap("main.go", 15, 1)). - WithArg("rootDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 15, 44)})). + WithArg("rootDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 15, 44)}). + WithArg("helmVersion", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 15, 71)}). + WithArg("kustomizeVersion", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 15, 91)})). WithFunction( dag.Function("GetGoVersion", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind)). - WithSourceMap(dag.SourceMap("main.go", 20, 1)). - WithArg("file", dag.TypeDef().WithObject("File"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 20, 51)})). + WithSourceMap(dag.SourceMap("main.go", 29, 1)). + WithArg("file", dag.TypeDef().WithObject("File"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 29, 51)})). WithFunction( dag.Function("AcceptanceTests", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind)). - WithSourceMap(dag.SourceMap("main.go", 36, 1)). - WithArg("rootDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 36, 54)}). - WithArg("acceptanceTestsDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 36, 81)}))), nil + WithSourceMap(dag.SourceMap("main.go", 45, 1)). + WithArg("rootDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 45, 54)}). + WithArg("helmVersion", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 45, 81)}). + WithArg("kustomizeVersion", dag.TypeDef().WithKind(dagger.TypeDefKindStringKind), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 45, 101)}). + WithArg("acceptanceTestsDir", dag.TypeDef().WithObject("Directory"), dagger.FunctionWithArgOpts{SourceMap: dag.SourceMap("main.go", 45, 126)}))), nil default: return nil, fmt.Errorf("unknown object %s", parentName) } diff --git a/dagger/main.go b/dagger/main.go index b106e0bdb..7e5b412f9 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -12,9 +12,18 @@ import ( type Tanka struct{} -func (m *Tanka) Build(ctx context.Context, rootDir *dagger.Directory) *dagger.Container { +func (m *Tanka) Build(ctx context.Context, rootDir *dagger.Directory, helmVersion string, kustomizeVersion string) *dagger.Container { + buildArgs := make([]dagger.BuildArg, 0, 2) + if helmVersion != "" { + buildArgs = append(buildArgs, dagger.BuildArg{Name: "HELM_VERSION", Value: helmVersion}) + } + if kustomizeVersion != "" { + buildArgs = append(buildArgs, dagger.BuildArg{Name: "KUSTOMIZE_VERSION", Value: kustomizeVersion}) + } return dag.Container(). - Build(rootDir) + Build(rootDir, dagger.ContainerBuildOpts{ + BuildArgs: buildArgs, + }) } func (m *Tanka) GetGoVersion(ctx context.Context, file *dagger.File) (string, error) { @@ -33,12 +42,12 @@ func (m *Tanka) GetGoVersion(ctx context.Context, file *dagger.File) (string, er return "", fmt.Errorf("no Go version found") } -func (m *Tanka) AcceptanceTests(ctx context.Context, rootDir *dagger.Directory, acceptanceTestsDir *dagger.Directory) (string, error) { +func (m *Tanka) AcceptanceTests(ctx context.Context, rootDir *dagger.Directory, helmVersion string, kustomizeVersion string, acceptanceTestsDir *dagger.Directory) (string, error) { goVersion, err := m.GetGoVersion(ctx, rootDir.File("go.mod")) if err != nil { return "", err } - buildContainer := m.Build(ctx, rootDir) + buildContainer := m.Build(ctx, rootDir, helmVersion, kustomizeVersion) k3s := dag.K3S("k3sdemo") k3sSrv, err := k3s.Server().Start(ctx)