From 52114a124518c5062db94a1bfe42b99410d77c46 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Mon, 8 Jun 2026 15:37:20 +0200 Subject: [PATCH 1/7] Bump goreleaser Signed-off-by: Jean-Philippe Evrard --- .mise/config.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mise/config.toml b/.mise/config.toml index c615508..d4b77b5 100644 --- a/.mise/config.toml +++ b/.mise/config.toml @@ -1,9 +1,9 @@ [tools] -cosign = "2.2.3" +cosign = "3.0.6" go = "1.26.4" golangci-lint = "2.12.2" -goreleaser = "1.24.0" +goreleaser = "2.16.0" kind = "0.32.0" kubectl = "1.36.1" shellcheck = "0.11.0" -syft = "1.0.1" +syft = "1.45.1" From e531f64b85b637d0fafe1542a59f2f07743e4975 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Mon, 8 Jun 2026 17:37:41 +0200 Subject: [PATCH 2/7] feat(release): let GoReleaser manage artifacts GoReleaser now builds the multi-arch images, publishes SBOM/provenance metadata, signs image digests, and attaches the generated combined Kubernetes manifest to tagged GitHub releases. This is to have goReleaser as a single point of work for release automation. With this, so tags and main commits follow one consistent image pipeline. We keep the CI and developer image builds intentionally local. PR, periodic, main, and tag scan jobs build only `kured:dev` and scan that local image with Trivy, which avoids pushing disposable images and keeps the tested image identical to the one used by kind-based e2e tests. Simplify the Makefile around the remaining artifact boundaries: `build` for a local GoReleaser binary build, `dev-image` for local Docker/e2e/scan use, and `release` for the GoReleaser publish path. Remove the old manual manifest target because the release manifest is now generated during the tagged release flow. To avoid a mess with all the configuration files, I move everything into a `.config` folder, for the tools supporting it. This also meant updating golangci-lint to a valid v2 config, and simplify the Dockerfile to the layout expected by GoReleaser `dockers_v2` using `TARGETPLATFORM`. Handle Prometheus client initialization errors explicitly so the stricter errcheck configuration keeps the existing fail-closed reboot-blocking behavior, to fix the golangci-lint issue that appeared. Signed-off-by: Jean-Philippe Evrard --- .config/golangci.yaml | 30 ++++++++ .config/goreleaser.yaml | 99 +++++++++++++++++++++++++ .config/goreleaser/render-manifest.sh | 10 +++ .github/workflows/on-main-push.yaml | 77 +++++++++---------- .github/workflows/on-pr.yaml | 25 ++----- .github/workflows/on-tag.yaml | 62 ++++------------ .github/workflows/periodics-weekly.yaml | 7 +- .gitignore | 1 + .golangci.yml | 37 --------- .goreleaser.yml | 32 -------- CONTRIBUTING.md | 41 +--------- Dockerfile | 26 +------ Makefile | 52 ++++++------- pkg/blockers/prometheus.go | 8 +- 14 files changed, 235 insertions(+), 272 deletions(-) create mode 100644 .config/golangci.yaml create mode 100644 .config/goreleaser.yaml create mode 100644 .config/goreleaser/render-manifest.sh delete mode 100644 .golangci.yml delete mode 100644 .goreleaser.yml diff --git a/.config/golangci.yaml b/.config/golangci.yaml new file mode 100644 index 0000000..a08ba3f --- /dev/null +++ b/.config/golangci.yaml @@ -0,0 +1,30 @@ +version: "2" +#timeout : 5m we can add this if needed +run: + modules-download-mode: readonly + tests: false +linters: + enable: + - govet + - staticcheck + - unused + - contextcheck + - goconst + - gosec + - testifylint + - errcheck + - revive + settings: + errcheck: + check-type-assertions: true + check-blank: true + revive: + severity: warning + confidence: 0.8 + rules: + - name: indent-error-flow + - name: var-naming + - name: import-shadowing + # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#package-comments + - name: package-comments # This is not working! + disabled: true diff --git a/.config/goreleaser.yaml b/.config/goreleaser.yaml new file mode 100644 index 0000000..557be29 --- /dev/null +++ b/.config/goreleaser.yaml @@ -0,0 +1,99 @@ +version: 2 + +project_name: kured + +before: + hooks: + - go mod tidy + - sh .config/goreleaser/render-manifest.sh {{ .Version }} ghcr.io/{{ .Env.IMAGE_NAME }} + +builds: + - id: kured + main: ./cmd/kured + binary: kured + env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + - arm + - "386" + goarm: + - "6" + - "7" + ldflags: + - -s -w -X main.version={{ if .IsSnapshot }}{{ .ShortCommit }}{{ else }}{{ .Version }}{{ end }} + mod_timestamp: "{{ .CommitTimestamp }}" + flags: + - -trimpath + +snapshot: + version_template: "{{ .ShortCommit }}" + +archives: + - formats: + - binary + +checksum: + name_template: checksums.txt + +sboms: + - artifacts: binary + documents: + - "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}.sbom.json" + +dockers_v2: + - id: kured + ids: + - kured + images: + - "ghcr.io/{{ .Env.IMAGE_NAME }}" + tags: + - "{{ if and (not .IsSnapshot) (ne .Tag .ShortCommit) }}{{ .Tag }}{{ end }}" + - "{{ .ShortCommit }}" + platforms: + - linux/amd64 + - linux/arm64 + - linux/arm/v7 + - linux/arm/v6 + - linux/386 + sbom: true + labels: + "org.opencontainers.image.created": "{{ .Date }}" + "org.opencontainers.image.description": "Kubernetes Reboot Daemon" + "org.opencontainers.image.licenses": "Apache-2.0" + "org.opencontainers.image.revision": "{{ .FullCommit }}" + "org.opencontainers.image.source": "{{ .GitURL }}" + "org.opencontainers.image.title": "{{ .ProjectName }}" + "org.opencontainers.image.version": "{{ .Version }}" + annotations: + "org.opencontainers.image.created": "{{ .Date }}" + "org.opencontainers.image.description": "Kubernetes Reboot Daemon" + "org.opencontainers.image.licenses": "Apache-2.0" + "org.opencontainers.image.revision": "{{ .FullCommit }}" + "org.opencontainers.image.source": "{{ .GitURL }}" + "org.opencontainers.image.title": "{{ .ProjectName }}" + "org.opencontainers.image.version": "{{ .Version }}" + flags: + - "--provenance=true" + +docker_digest: + name_template: digests.txt + +docker_signs: + - artifacts: all + args: + - sign + - --yes + - "${artifact}@${digest}" + +release: + disable: '{{ if eq .Env.DISABLE_GITHUB_RELEASE "true" }}true{{ else }}false{{ end }}' + name_template: "Kured {{ .Version }}" + extra_files: + - glob: ".tmp/goreleaser/kured-{{ .Version }}-combined.yaml" + +changelog: + disable: true diff --git a/.config/goreleaser/render-manifest.sh b/.config/goreleaser/render-manifest.sh new file mode 100644 index 0000000..dd7f7e7 --- /dev/null +++ b/.config/goreleaser/render-manifest.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -eu + +version="${1:?version is required}" +image="${2:?image is required}" +out=".tmp/goreleaser/kured-${version}-combined.yaml" + +mkdir -p .tmp/goreleaser +cat kured-rbac.yaml > "${out}" +sed "s#image: ghcr.io/.*kured.*#image: ${image}:${version}#g" kured-ds.yaml >> "${out}" diff --git a/.github/workflows/on-main-push.yaml b/.github/workflows/on-main-push.yaml index 15cfcc9..fc8a810 100644 --- a/.github/workflows/on-main-push.yaml +++ b/.github/workflows/on-main-push.yaml @@ -1,5 +1,3 @@ -# We publish every merged commit in the form of an image -# named kured:- name: Push image of latest main on: push: @@ -15,11 +13,11 @@ permissions: jobs: tag-scan-and-push-final-image: - name: "Build, scan, and publish tagged image" + name: Build, scan, and publish main image runs-on: ubuntu-latest permissions: id-token: write - contents: write + contents: read packages: write steps: - name: Harden Runner @@ -28,11 +26,38 @@ jobs: egress-policy: audit - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 - uses: jdx/mise-action@dba19683ed58901619b14f395a24841710cb4925 # v4.1.0 with: version: 2026.6.1 + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + + - name: Find current commit + id: version + run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + - name: Build local image for scan + run: VERSION="${{ steps.version.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image + env: + IMAGE_NAME: ${{ github.repository }} + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + image-ref: kured:dev + format: 'table' + exit-code: '1' + ignore-unfixed: true + vuln-type: 'os,library' + severity: 'CRITICAL,HIGH' + - name: Login to ghcr.io uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: @@ -40,44 +65,10 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Find current tag version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - id: tags - - - name: Build binaries - run: make kured-release-snapshot + - name: Build, publish, SBOM, and sign image + run: make release env: + DISABLE_GITHUB_RELEASE: "true" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Build image - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 - with: - context: . - platforms: linux/arm64, linux/amd64, linux/arm/v7, linux/arm/v6, linux/386 - push: true - labels: ${{ steps.meta.outputs.labels }} - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.sha_short }} - - - name: Generate SBOM - run: | - syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.sha_short }} -o spdx > kured.sbom - - - name: Sign and attest artifacts - run: | - cosign sign -y -r ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.sha_short }} - cosign sign-blob -y --output-signature kured.sbom.sig --output-certificate kured.sbom.pem kured.sbom - cosign attest -y --type spdx --predicate kured.sbom ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.sha_short }} - cosign attach sbom --type spdx --sbom kured.sbom ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.sha_short }} + GORELEASER_CURRENT_TAG: ${{ steps.version.outputs.sha_short }} + IMAGE_NAME: ${{ github.repository }} diff --git a/.github/workflows/on-pr.yaml b/.github/workflows/on-pr.yaml index 4ddcc36..92ff99d 100644 --- a/.github/workflows/on-pr.yaml +++ b/.github/workflows/on-pr.yaml @@ -2,6 +2,10 @@ name: PR on: pull_request: push: + branches-ignore: + - main + tags-ignore: + - "*" jobs: pr-short-tests: @@ -47,9 +51,6 @@ jobs: with: version: 2026.6.1 - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 @@ -58,12 +59,12 @@ jobs: id: tags - name: Build image - run: VERSION="${{ steps.tags.outputs.sha_short }}" DH_ORG="${{ github.repository_owner }}" make image + run: VERSION="${{ steps.tags.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: - image-ref: 'ghcr.io/${{ github.repository }}:${{ steps.tags.outputs.sha_short }}' + image-ref: kured:dev format: 'table' exit-code: '1' ignore-unfixed: true @@ -103,16 +104,9 @@ jobs: with: version: 2026.6.1 - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - name: Find current tag version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - id: tags - - name: Run specific e2e tests run: make e2e-test ARGS="-run ^${{ matrix.testname }}/${{ matrix.kubernetes_version }}" @@ -139,15 +133,8 @@ jobs: with: version: 2026.6.1 - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - name: Find current tag version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - id: tags - - name: Run specific e2e tests run: make e2e-test ARGS="-run ^${{ matrix.testname }}" diff --git a/.github/workflows/on-tag.yaml b/.github/workflows/on-tag.yaml index 6b1cea3..99ad8a7 100644 --- a/.github/workflows/on-tag.yaml +++ b/.github/workflows/on-tag.yaml @@ -1,7 +1,3 @@ -# when we add a tag to the repo, we should publish the kured image to a public repository -# if it's safe. -# It doesn't mean it's ready for release, but at least it's getting us started. -# The next step is to have a PR with the helm chart, to bump the version of the image used name: Tag repo on: push: @@ -17,7 +13,7 @@ permissions: jobs: tag-scan-and-push-final-image: - name: "Build, scan, and publish tagged image" + name: Build, scan, and publish tagged image runs-on: ubuntu-latest permissions: id-token: write @@ -30,14 +26,16 @@ jobs: egress-policy: audit - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 - uses: jdx/mise-action@dba19683ed58901619b14f395a24841710cb4925 # v4.1.0 with: version: 2026.6.1 - - name: Find current tag version - run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - id: tags + - name: Find current commit + id: version + run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - name: Set up QEMU uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 @@ -45,24 +43,15 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - name: Build binaries - run: make kured-release-tag + - name: Build local image for scan + run: VERSION="${{ steps.version.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Build single image for scan - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 - with: - context: . - push: false - load: true - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} + IMAGE_NAME: ${{ github.repository }} - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: - image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }}' + image-ref: kured:dev format: 'table' exit-code: '1' ignore-unfixed: true @@ -76,29 +65,8 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - - name: Build release images - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 - with: - context: . - platforms: linux/arm64, linux/amd64, linux/arm/v7, linux/arm/v6, linux/386 - push: true - labels: ${{ steps.meta.outputs.labels }} - tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} - - - name: Generate SBOM - run: | - syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} -o spdx > kured.sbom - - - name: Sign and attest artifacts - run: | - cosign sign -y -r ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} - cosign sign-blob -y --output-signature kured.sbom.sig kured.sbom - cosign attest -y --type spdx --predicate kured.sbom ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} - cosign attach sbom --type spdx --sbom kured.sbom ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.version }} + - name: Build, publish, SBOM, and sign images + run: make release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + IMAGE_NAME: ${{ github.repository }} diff --git a/.github/workflows/periodics-weekly.yaml b/.github/workflows/periodics-weekly.yaml index 2d2345d..77c300a 100644 --- a/.github/workflows/periodics-weekly.yaml +++ b/.github/workflows/periodics-weekly.yaml @@ -87,9 +87,6 @@ jobs: with: version: 2026.6.1 - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 @@ -98,11 +95,11 @@ jobs: id: tags - name: Build artifacts - run: VERSION="${{ steps.tags.outputs.sha_short }}" DH_ORG="${{ github.repository_owner }}" make image + run: VERSION="${{ steps.tags.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: - image-ref: 'ghcr.io/${{ github.repository }}:${{ steps.tags.outputs.sha_short }}' + image-ref: kured:dev format: 'table' exit-code: '1' ignore-unfixed: true diff --git a/.gitignore b/.gitignore index 9e49413..6440617 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ cmd/kured/kured vendor build dist +.tmp/goreleaser test.json tests/kind/testfiles/*.yaml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index c586189..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,37 +0,0 @@ -version: "2" -#timeout : 5m we can add this if needed -modules-download-mode: readonly -run: - tests: false -linters: - enable: - - govet - - staticcheck - - unused - - contextcheck - - goconst - - gosec - - testifylint - - errcheck - - revive - -linters-settings: - errcheck: - check-type-assertions: true - check-blank: true - revive: - severity: warning - confidence: 0.8 - rules: - - name: indent-error-flow - - name: var-naming - - name: import-shadowing - # https://github.com/mgechev/revive/blob/HEAD/RULES_DESCRIPTIONS.md#package-comments - - name: package-comments # This is not working! - disabled: true -output: - format: colored-line-number - print-issued-lines: true - print-linter-name: true - uniq-by-line: false - sort-results: true diff --git a/.goreleaser.yml b/.goreleaser.yml deleted file mode 100644 index 45fc36b..0000000 --- a/.goreleaser.yml +++ /dev/null @@ -1,32 +0,0 @@ -project_name: kured -before: - hooks: - - go mod tidy -builds: - - main: ./cmd/kured - env: - - CGO_ENABLED=0 - goos: - - linux - goarch: - - amd64 - - arm64 - - arm - - "386" - goarm: - - "6" - - "7" - ldflags: - - -s -w -X main.version={{ if .IsSnapshot }}{{ .ShortCommit }}{{ else }}{{ .Version }}{{ end }} - mod_timestamp: "{{ .CommitTimestamp }}" - flags: - - -trimpath - -snapshot: - name_template: "{{ .ShortCommit }}" - -release: - disable: true - -changelog: - skip: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 70fec70..6543987 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -94,7 +94,7 @@ We also have other tests: All these tests are run on every PR/tagged release. See [.github/workflows](.github/workflows) for more details. -We use [GoReleaser to build](.goreleaser.yml). +We use [GoReleaser to build](.config/goreleaser.yaml). ## Regular development activities / maintenance @@ -199,7 +199,7 @@ A test-run with `minikube` could look like this: minikube start --driver=kvm2 --kubernetes-version # build kured image and publish to registry accessible by minikube -make image minikube-publish +make dev-image minikube-publish # edit kured-ds.yaml to # - point to new image @@ -301,52 +301,20 @@ See also our GitHub issues with the label [`testing`](https://github.com/kubereb Ensure you have used the latest patch version in the tree. Check the documentation "Updating k8s support" if the minor version was not yet applied. -### Update the manifests with the new version - -```sh -export VERSION=1.20.0 -make DH_ORG="kubereboot" VERSION="${VERSION}" manifest -``` -Create a commit updating the manifest with future image [like this one](https://github.com/kubereboot/kured/commit/58091f6145771f426b4b9e012a43a9c847af2560). - -### Create the combined manifest for the new release - -Now create the `kured--combined.yaml` for e.g. `1.20.0`: - -```sh -export VERSION=1.20.0 -export MANIFEST="kured-$VERSION-combined.yaml" -make DH_ORG="kubereboot" VERSION="${VERSION}" manifest # just to be safe -cat kured-rbac.yaml > "$MANIFEST" -cat kured-ds.yaml >> "$MANIFEST" -``` - ### Create the new version tag on the repo (optional, can also be done directly in GH web interface) Tag the previously created commit with the future release version. -The GitHub Actions workflow will push the new image to the registry. +The GitHub Actions workflow will push the new image to the registry and attach the generated combined manifest to the GitHub release. ### Publish new version release artifacts -Now you can head to the GitHub UI for releases, drafting a new -release. Chose, as tag, the new version number. - -Click to generate the release notes. - -Fill, as name, "Kured ". - -Edit the generated text. +GoReleaser creates the GitHub release for the tag. Edit the generated release notes if needed. Please describe what's new and noteworthy in the release notes, list the PRs that landed and give a shout-out to everyone who contributed. Please also note down on which releases the upcoming `kured` release was tested on or what it supports. (Check old release notes if you're unsure.) -Before clicking on publishing release, upload the yaml manifest -(`kured--combined.yaml`) file. - -Click on publish the release and set as the latest release. - ### Prepare Helm chart Create a commit to [bump the chart and kured version like this one](https://github.com/kubereboot/charts/commit/e0191d91c21db8338be8cbe56f8991a557048110). @@ -354,4 +322,3 @@ Create a commit to [bump the chart and kured version like this one](https://gith ### Prepare Documentation Ensure the [compatibility matrix](https://kured.dev/docs/installation/) is updated to the new version you want to release. - diff --git a/Dockerfile b/Dockerfile index fb92075..cf3dafb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,7 @@ -FROM alpine:3.23.4@sha256:5b10f432ef3da1b8d4c7eb6c487f2f5a8f096bc91145e68878dd4a5019afde11 AS bin - -ARG TARGETOS -ARG TARGETARCH -ARG TARGETVARIANT - -COPY dist/ /dist -RUN set -ex \ - && case "${TARGETARCH}" in \ - amd64) \ - SUFFIX="_v1" \ - ;; \ - arm) \ - SUFFIX="_${TARGETVARIANT:1}" \ - ;; \ - *) \ - SUFFIX="" \ - ;; \ - esac \ - && cp /dist/kured_${TARGETOS}_${TARGETARCH}${SUFFIX}/kured /dist/kured; - FROM alpine:3.23.4@sha256:5b10f432ef3da1b8d4c7eb6c487f2f5a8f096bc91145e68878dd4a5019afde11 + +ARG TARGETPLATFORM + RUN apk update --no-cache && apk upgrade --no-cache && apk add --no-cache ca-certificates tzdata -COPY --from=bin /dist/kured /usr/bin/kured +COPY ${TARGETPLATFORM}/kured /usr/bin/kured ENTRYPOINT ["/usr/bin/kured"] diff --git a/Makefile b/Makefile index 1ef091b..eac4e8b 100644 --- a/Makefile +++ b/Makefile @@ -1,37 +1,36 @@ .DEFAULT: all -.PHONY: all clean image minikube-publish manifest test kured-all lint +.PHONY: all clean install-tools build dev-image release dev-manifest e2e-test minikube-publish test lint lint-docs DH_ORG ?= kubereboot -VERSION=$(shell git rev-parse --short HEAD) +IMAGE_NAME ?= $(DH_ORG)/kured +VERSION ?= $(shell git rev-parse --short HEAD) +GORELEASER_CONFIG ?= .config/goreleaser.yaml +GOLANGCI_CONFIG ?= .config/golangci.yaml +LOCAL_PLATFORM ?= linux/amd64 SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E") -all: image +DEV_IMAGE := kured:dev + +all: build -.PHONY: install-tools install-tools: command -v mise 2>&1 || { echo "please install mise to continue" >&2; exit 127; } mise install clean: - rm -rf ./dist + rm -rf ./dist ./.tmp/goreleaser -kured: - goreleaser build --clean --single-target --snapshot +build: + IMAGE_NAME="$(IMAGE_NAME)" goreleaser build --clean --single-target --snapshot -f $(GORELEASER_CONFIG) -kured-all: - goreleaser build --clean --snapshot +release: + IMAGE_NAME="$(IMAGE_NAME)" goreleaser release --clean -f $(GORELEASER_CONFIG) -kured-release-tag: - goreleaser release --clean - -kured-release-snapshot: - goreleaser release --clean --snapshot - -image: kured - $(SUDO) docker buildx build --no-cache --load -t ghcr.io/$(DH_ORG)/kured:$(VERSION) . - -dev-image: image - $(SUDO) docker tag ghcr.io/$(DH_ORG)/kured:$(VERSION) kured:dev +dev-image: + mkdir -p dist/docker/$(LOCAL_PLATFORM) + CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$(VERSION)" -o dist/docker/$(LOCAL_PLATFORM)/kured ./cmd/kured + cp Dockerfile dist/docker/Dockerfile + $(SUDO) docker buildx build --load --platform $(LOCAL_PLATFORM) -t $(DEV_IMAGE) dist/docker dev-manifest: # basic e2e scenario @@ -49,13 +48,8 @@ e2e-test: dev-manifest dev-image echo "Running ALL go tests" go test -count=1 -v --parallel 4 ./... $(ARGS) -minikube-publish: image - $(SUDO) docker save ghcr.io/$(DH_ORG)/kured | (eval $$(minikube docker-env) && docker load) - -manifest: - sed -i "s#image: ghcr.io/.*kured.*#image: ghcr.io/$(DH_ORG)/kured:$(VERSION)#g" kured-ds.yaml - sed -i "s#image: ghcr.io/.*kured.*#image: ghcr.io/$(DH_ORG)/kured:$(VERSION)#g" kured-ds-signal.yaml - echo "Please generate combined manifest if necessary" +minikube-publish: dev-image + $(SUDO) docker save $(DEV_IMAGE) | (eval $$(minikube docker-env) && docker load) test: lint @echo "Running short go tests" @@ -65,8 +59,8 @@ lint: @echo "Running shellcheck" find . -name '*.sh' | xargs -n1 shellcheck @echo "Running golangci-lint..." - golangci-lint run ./... + golangci-lint run --config $(GOLANGCI_CONFIG) ./... lint-docs: @echo "Running lychee" - mise x lychee@latest -- lychee --verbose --no-progress '*.md' '*.yaml' '*/*/*.go' --exclude-link-local \ No newline at end of file + mise x lychee@latest -- lychee --verbose --no-progress '*.md' '*.yaml' '*/*/*.go' --exclude-link-local diff --git a/pkg/blockers/prometheus.go b/pkg/blockers/prometheus.go index 843e7bf..0135870 100644 --- a/pkg/blockers/prometheus.go +++ b/pkg/blockers/prometheus.go @@ -30,12 +30,13 @@ type PrometheusBlockingChecker struct { filterMatchOnly bool // storing the promClient promClient papi.Client + initErr error } // NewPrometheusBlockingChecker creates a new PrometheusBlockingChecker using the given // Prometheus API config, alert filter, and filtering options. func NewPrometheusBlockingChecker(config papi.Config, alertFilter *regexp.Regexp, firingOnly bool, filterMatchOnly bool) PrometheusBlockingChecker { - promClient, _ := papi.NewClient(config) + promClient, err := papi.NewClient(config) return PrometheusBlockingChecker{ promConfig: config, @@ -43,6 +44,7 @@ func NewPrometheusBlockingChecker(config papi.Config, alertFilter *regexp.Regexp firingOnly: firingOnly, filterMatchOnly: filterMatchOnly, promClient: promClient, + initErr: err, } } @@ -80,6 +82,10 @@ func (pb PrometheusBlockingChecker) MetricLabel() string { // block-list and will NOT block rebooting. query by includeLabel means, // if the query finds an alert, it will include it to the block-list, and it WILL block rebooting. func (pb PrometheusBlockingChecker) ActiveAlerts() ([]string, error) { + if pb.initErr != nil { + return nil, pb.initErr + } + api := v1.NewAPI(pb.promClient) // get all alerts from prometheus From 51903f13643c7fb9f383bfac2cc536e7207c4f86 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Mon, 8 Jun 2026 17:57:54 +0200 Subject: [PATCH 3/7] cleanup more of the makefile We remove a step that is now useless. Signed-off-by: Jean-Philippe Evrard --- Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index eac4e8b..14a8ad3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .DEFAULT: all -.PHONY: all clean install-tools build dev-image release dev-manifest e2e-test minikube-publish test lint lint-docs +.PHONY: all clean install-tools dev-image release dev-manifest e2e-test minikube-publish test lint lint-docs DH_ORG ?= kubereboot IMAGE_NAME ?= $(DH_ORG)/kured @@ -11,7 +11,7 @@ SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E") DEV_IMAGE := kured:dev -all: build +all: test install-tools: command -v mise 2>&1 || { echo "please install mise to continue" >&2; exit 127; } @@ -20,9 +20,6 @@ install-tools: clean: rm -rf ./dist ./.tmp/goreleaser -build: - IMAGE_NAME="$(IMAGE_NAME)" goreleaser build --clean --single-target --snapshot -f $(GORELEASER_CONFIG) - release: IMAGE_NAME="$(IMAGE_NAME)" goreleaser release --clean -f $(GORELEASER_CONFIG) From c36ae33c678849e453c4f0e20b175184c0803f1a Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Mon, 8 Jun 2026 18:28:28 +0200 Subject: [PATCH 4/7] fix: stop building main branch containers Without this, we will continue building and storing artifacts that are used by less than 10% of our community. This means maintaining different workflows and complicates goreleaser for really no reason. If someone has a strong opposition to this practice, please tell me, I will revert this commit. Signed-off-by: Jean-Philippe Evrard --- ...on-pr.yaml => on-branch-push-and-prs.yaml} | 17 ++--- .github/workflows/on-main-push.yaml | 74 ------------------- .github/workflows/on-tag.yaml | 9 +-- .github/workflows/periodics-weekly.yaml | 6 +- 4 files changed, 9 insertions(+), 97 deletions(-) rename .github/workflows/{on-pr.yaml => on-branch-push-and-prs.yaml} (93%) delete mode 100644 .github/workflows/on-main-push.yaml diff --git a/.github/workflows/on-pr.yaml b/.github/workflows/on-branch-push-and-prs.yaml similarity index 93% rename from .github/workflows/on-pr.yaml rename to .github/workflows/on-branch-push-and-prs.yaml index 92ff99d..03b7b72 100644 --- a/.github/workflows/on-pr.yaml +++ b/.github/workflows/on-branch-push-and-prs.yaml @@ -1,11 +1,12 @@ -name: PR +name: Branch push and PR on: pull_request: push: - branches-ignore: - - main - tags-ignore: - - "*" + branches: + - "**" + +permissions: + contents: read jobs: pr-short-tests: @@ -54,12 +55,8 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - name: Find current tag version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - id: tags - - name: Build image - run: VERSION="${{ steps.tags.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image + run: make dev-image - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 diff --git a/.github/workflows/on-main-push.yaml b/.github/workflows/on-main-push.yaml deleted file mode 100644 index fc8a810..0000000 --- a/.github/workflows/on-main-push.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: Push image of latest main -on: - push: - branches: - - main - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -permissions: - contents: read - -jobs: - tag-scan-and-push-final-image: - name: Build, scan, and publish main image - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - packages: write - steps: - - name: Harden Runner - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 - with: - egress-policy: audit - - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - - - uses: jdx/mise-action@dba19683ed58901619b14f395a24841710cb4925 # v4.1.0 - with: - version: 2026.6.1 - - - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Find current commit - id: version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - - - name: Build local image for scan - run: VERSION="${{ steps.version.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image - env: - IMAGE_NAME: ${{ github.repository }} - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 - with: - image-ref: kured:dev - format: 'table' - exit-code: '1' - ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' - - - name: Login to ghcr.io - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build, publish, SBOM, and sign image - run: make release - env: - DISABLE_GITHUB_RELEASE: "true" - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GORELEASER_CURRENT_TAG: ${{ steps.version.outputs.sha_short }} - IMAGE_NAME: ${{ github.repository }} diff --git a/.github/workflows/on-tag.yaml b/.github/workflows/on-tag.yaml index 99ad8a7..b2bf069 100644 --- a/.github/workflows/on-tag.yaml +++ b/.github/workflows/on-tag.yaml @@ -33,10 +33,6 @@ jobs: with: version: 2026.6.1 - - name: Find current commit - id: version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - - name: Set up QEMU uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 @@ -44,9 +40,7 @@ jobs: uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Build local image for scan - run: VERSION="${{ steps.version.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image - env: - IMAGE_NAME: ${{ github.repository }} + run: make dev-image - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 @@ -69,4 +63,3 @@ jobs: run: make release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - IMAGE_NAME: ${{ github.repository }} diff --git a/.github/workflows/periodics-weekly.yaml b/.github/workflows/periodics-weekly.yaml index 77c300a..3532dbc 100644 --- a/.github/workflows/periodics-weekly.yaml +++ b/.github/workflows/periodics-weekly.yaml @@ -90,12 +90,8 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - name: Find current tag version - run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - id: tags - - name: Build artifacts - run: VERSION="${{ steps.tags.outputs.sha_short }}" IMAGE_NAME="${{ github.repository }}" make dev-image + run: make dev-image - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: From b91831b9bba3948711471cd63e2db8909c993c9a Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Mon, 8 Jun 2026 18:52:50 +0200 Subject: [PATCH 5/7] Migrate mise config file Now that we have a .config folder, we can move mise into such folder, to clean up the root of the directory We therefore fix the contributing guide link with new location. Signed-off-by: Jean-Philippe Evrard --- .mise/config.toml => .config/mise.toml | 0 CONTRIBUTING.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .mise/config.toml => .config/mise.toml (100%) diff --git a/.mise/config.toml b/.config/mise.toml similarity index 100% rename from .mise/config.toml rename to .config/mise.toml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6543987..64f9332 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,7 +40,7 @@ Your system needs at least the following binaries installed: ### Fetch the additional binaries required Please run `make install-tools` once on a fresh repository clone to download necessary developer tools. -Installed tools are listed in [.mise directory](.mise/config.toml). +Installed tools are listed in mise.toml in our .config directory (`.config/mise.toml`). ### Configure your git for the "Certificate of Origin" From 2a23325b81a3b979a431b11dfadc4f2bad2841dd Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Tue, 9 Jun 2026 09:25:47 +0200 Subject: [PATCH 6/7] chore(tests): Cleanup test matrix There is no point of having a more complex series of jobs. This puts all the manifests testing cases into one kind of pipeline, simplifying debugging. Signed-off-by: Jean-Philippe Evrard --- .github/workflows/on-branch-push-and-prs.yaml | 43 ++++--------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/.github/workflows/on-branch-push-and-prs.yaml b/.github/workflows/on-branch-push-and-prs.yaml index 03b7b72..bc226d2 100644 --- a/.github/workflows/on-branch-push-and-prs.yaml +++ b/.github/workflows/on-branch-push-and-prs.yaml @@ -73,8 +73,8 @@ jobs: # - Test manifests changes (obviously), ensuring they don't break existing clusters # - Ensure manifests work with the latest versions even with no manifest change # (compared to helm charts, manifests cannot easily template changes based on versions) + # - Test some features are working as expected. # Helm charts are _trailing_ releases, while manifests are done during development. - # This test uses the "command" reboot-method. e2e-manifests: name: End-to-End test with kured with code and manifests from HEAD runs-on: ubuntu-latest @@ -82,39 +82,14 @@ jobs: fail-fast: false matrix: testname: - - "TestE2EWithCommand" - - "TestE2EWithSignal" - - "TestE2EConcurrentWithCommand" - - "TestE2EConcurrentWithSignal" - kubernetes_version: - - "previous" - - "current" - steps: - - name: Harden Runner - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 - with: - egress-policy: audit - - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - - uses: jdx/mise-action@dba19683ed58901619b14f395a24841710cb4925 # v4.1.0 - with: - version: 2026.6.1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Run specific e2e tests - run: make e2e-test ARGS="-run ^${{ matrix.testname }}/${{ matrix.kubernetes_version }}" - - - e2e-tests-singleversion: - name: End-to-End test targetting a single version of kubernetes - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - testname: + - "TestE2EWithCommand/current" + - "TestE2EWithCommand/previous" + - "TestE2EWithSignal/current" + - "TestE2EWithSignal/previous" + - "TestE2EConcurrentWithCommand/current" + - "TestE2EConcurrentWithCommand/previous" + - "TestE2EConcurrentWithSignal/current" + - "TestE2EConcurrentWithSignal/previous" - "TestCordonningIsKept/concurrency1" - "TestCordonningIsKept/concurrency2" - "TestE2EBlocker/podblocker" From 315d8e0475e720b0e4c87c6b59417b12dd35c378 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Tue, 9 Jun 2026 09:49:54 +0200 Subject: [PATCH 7/7] Add github release changelog text generation Without this, we will not produce text that is basically exactly what we do. By using goreleaser github-native method, we will also generate the usual changelog. The only remaining part would be to edit it for the extra manual messages we add. Signed-off-by: Jean-Philippe Evrard --- .config/goreleaser.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.config/goreleaser.yaml b/.config/goreleaser.yaml index 557be29..4221ee3 100644 --- a/.config/goreleaser.yaml +++ b/.config/goreleaser.yaml @@ -24,14 +24,11 @@ builds: - "6" - "7" ldflags: - - -s -w -X main.version={{ if .IsSnapshot }}{{ .ShortCommit }}{{ else }}{{ .Version }}{{ end }} + - -s -w -X main.version={{ .Version }} mod_timestamp: "{{ .CommitTimestamp }}" flags: - -trimpath -snapshot: - version_template: "{{ .ShortCommit }}" - archives: - formats: - binary @@ -51,7 +48,7 @@ dockers_v2: images: - "ghcr.io/{{ .Env.IMAGE_NAME }}" tags: - - "{{ if and (not .IsSnapshot) (ne .Tag .ShortCommit) }}{{ .Tag }}{{ end }}" + - "{{ if ne .Tag .ShortCommit }}{{ .Tag }}{{ end }}" - "{{ .ShortCommit }}" platforms: - linux/amd64 @@ -90,10 +87,9 @@ docker_signs: - "${artifact}@${digest}" release: - disable: '{{ if eq .Env.DISABLE_GITHUB_RELEASE "true" }}true{{ else }}false{{ end }}' name_template: "Kured {{ .Version }}" extra_files: - glob: ".tmp/goreleaser/kured-{{ .Version }}-combined.yaml" changelog: - disable: true + use: github-native