From d72a6005bbfd876fc89922cd4cdf36fbd6653b90 Mon Sep 17 00:00:00 2001 From: Matthias Bertschy Date: Thu, 3 Apr 2025 12:52:15 +0200 Subject: [PATCH] use goreleaser for all builds and release publication Signed-off-by: Matthias Bertschy --- .github/workflows/00-pr-scanner.yaml | 34 +---- .github/workflows/a-pr-scanner.yaml | 76 +---------- .github/workflows/z-close-typos-issues.yaml | 20 --- .goreleaser.yaml | 120 ++++++++++++++--- .krew.yaml | 42 ------ build/Dockerfile | 21 +-- build/goreleaser-post-e2e.sh | 138 ++++++++++++++++++++ build/kubescape-cli.Dockerfile | 3 +- docs/TODO_GORELEASER_E2E.md | 131 +++++++++++++++++++ 9 files changed, 379 insertions(+), 206 deletions(-) delete mode 100644 .github/workflows/z-close-typos-issues.yaml delete mode 100644 .krew.yaml create mode 100644 build/goreleaser-post-e2e.sh create mode 100644 docs/TODO_GORELEASER_E2E.md diff --git a/.github/workflows/00-pr-scanner.yaml b/.github/workflows/00-pr-scanner.yaml index d1b57a67..fd84a584 100644 --- a/.github/workflows/00-pr-scanner.yaml +++ b/.github/workflows/00-pr-scanner.yaml @@ -23,20 +23,20 @@ jobs: pr-scanner: permissions: actions: read + attestations: read checks: read + contents: write deployments: read + discussions: read id-token: write issues: read models: read - discussions: read packages: read pages: read pull-requests: write repository-projects: read security-events: read statuses: read - attestations: read - contents: write uses: ./.github/workflows/a-pr-scanner.yaml with: RELEASE: "" @@ -44,31 +44,3 @@ jobs: CGO_ENABLED: 0 GO111MODULE: "" secrets: inherit - - binary-build: - if: ${{ github.actor == 'kubescape' }} - permissions: - actions: read - checks: read - contents: write - deployments: read - discussions: read - id-token: write - issues: read - models: read - packages: write - pages: read - pull-requests: read - repository-projects: read - security-events: read - statuses: read - attestations: read - uses: ./.github/workflows/b-binary-build-and-e2e-tests.yaml - with: - COMPONENT_NAME: kubescape - CGO_ENABLED: 0 - GO111MODULE: "" - GO_VERSION: "1.25" - RELEASE: "latest" - CLIENT: test - secrets: inherit diff --git a/.github/workflows/a-pr-scanner.yaml b/.github/workflows/a-pr-scanner.yaml index ac945f91..2efe892e 100644 --- a/.github/workflows/a-pr-scanner.yaml +++ b/.github/workflows/a-pr-scanner.yaml @@ -56,7 +56,7 @@ jobs: with: distribution: goreleaser version: latest - args: release --clean --snapshot + args: build --clean --snapshot --single-target env: RELEASE: ${{ inputs.RELEASE }} CLIENT: ${{ inputs.CLIENT }} @@ -66,7 +66,7 @@ jobs: env: RELEASE: ${{ inputs.RELEASE }} KUBESCAPE_SKIP_UPDATE_CHECK: "true" - run: ${{ env.DOCKER_CMD }} python3 smoke_testing/init.py ${PWD}/dist/kubescape-ubuntu-latest + run: ${{ env.DOCKER_CMD }} python3 smoke_testing/init.py ${PWD}/dist/cli_linux_amd64_v1/kubescape - name: golangci-lint continue-on-error: false @@ -75,75 +75,3 @@ jobs: version: v2.1 args: --timeout 10m only-new-issues: true - - scanners: - env: - GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - name: PR Scanner - runs-on: ubuntu-large - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - submodules: recursive - - uses: actions/setup-go@v4 - name: Installing go - with: - go-version: "1.25" - - name: Scanning - Forbidden Licenses (go-licenses) - id: licenses-scan - continue-on-error: true - run: | - echo "## Installing go-licenses tool" - go install github.com/google/go-licenses@latest - echo "## Scanning for forbiden licenses ##" - go-licenses check . - - name: Scanning - Credentials (GitGuardian) - if: ${{ env.GITGUARDIAN_API_KEY }} - continue-on-error: true - id: credentials-scan - uses: GitGuardian/ggshield-action@master - with: - args: -v --all-policies - env: - GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} - GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} - GITHUB_PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }} - GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} - - name: Scanning - Vulnerabilities (Snyk) - if: ${{ env.SNYK_TOKEN }} - id: vulnerabilities-scan - continue-on-error: true - uses: snyk/actions/golang@master - with: - command: test --all-projects - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - - - name: Test coverage - id: unit-test - run: go test -v ${{ inputs.UNIT_TESTS_PATH }} -covermode=count -coverprofile=coverage.out - - - name: Convert coverage count to lcov format - uses: jandelgado/gcov2lcov-action@v1 - - - name: Submit coverage tests to Coveralls - continue-on-error: true - uses: coverallsapp/github-action@v1 - with: - github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} - path-to-lcov: coverage.lcov - - - name: Comment results to PR - continue-on-error: true # Warning: This might break opening PRs from forks - uses: peter-evans/create-or-update-comment@v4 - with: - issue-number: ${{ github.event.pull_request.number }} - body: | - Scan results: - - License scan: ${{ steps.licenses-scan.outcome }} - - Credentials scan: ${{ steps.credentials-scan.outcome }} - - Vulnerabilities scan: ${{ steps.vulnerabilities-scan.outcome }} - reactions: 'eyes' diff --git a/.github/workflows/z-close-typos-issues.yaml b/.github/workflows/z-close-typos-issues.yaml deleted file mode 100644 index 94a2e9bd..00000000 --- a/.github/workflows/z-close-typos-issues.yaml +++ /dev/null @@ -1,20 +0,0 @@ -permissions: read-all -on: - issues: - types: [opened, labeled] -jobs: - open_PR_message: - if: github.event.label.name == 'typo' - runs-on: ubuntu-latest - steps: - - uses: ben-z/actions-comment-on-issue@1.0.2 - with: - message: "Hello! :wave:\n\nThis issue is being automatically closed, Please open a PR with a relevant fix." - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - auto_close_issues: - runs-on: ubuntu-latest - steps: - - uses: lee-dohm/close-matching-issues@v2 - with: - query: 'label:typo' - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 340aeb3c..975135c5 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -11,40 +11,104 @@ before: hooks: # You may remove this if you don't use go modules. - go mod tidy + - go test -v ./... + - go -C httphandler test -v ./... archives: - - id: binaries + - id: cli + ids: + - cli formats: - binary - name_template: >- - {{ .Binary }} - - id: default - formats: - tar.gz - name_template: >- - {{ .Binary }} builds: - - goos: + - id: cli + binary: kubescape + env: + - CGO_ENABLED=0 + goos: - linux - - windows - - darwin goarch: - amd64 - arm64 - - riscv64 ldflags: - -s -w - -X "github.com/kubescape/kubescape/v3/core/cautils.BuildNumber={{.Env.RELEASE}}" - -X "github.com/kubescape/kubescape/v3/core/cautils.Client={{.Env.CLIENT}}" - binary: >- - {{ .ProjectName }}- - {{- if eq .Arch "amd64" }} - {{- else }}{{ .Arch }}-{{ end }} - {{- if eq .Os "darwin" }}macos - {{- else if eq .Os "linux" }}ubuntu - {{- else }}{{ .Os }}{{ end }}-latest - no_unique_dist_dir: true + hooks: + post: + - "/bin/sh -lc 'sh build/goreleaser-post-e2e.sh'" + - id: downloader + dir: downloader + binary: downloader + env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + - id: http + dir: httphandler + binary: ksserver + env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + +nfpms: + - id: cli + package_name: kubescape + ids: + - cli + vendor: Kubescape + homepage: https://kubescape.io/ + maintainer: matthiasb@kubescape.io + formats: + - apk + - deb + - rpm + bindir: /usr/bin + +docker_signs: + - stdin: "{{ .Env.COSIGN_PWD }}" + +dockers_v2: + - id: cli + images: + - "quay.io/kubescape/kubescape-cli" + tags: + - "{{ .Tag }}" + labels: + "org.opencontainers.image.description": "Kubescape CLI" + "org.opencontainers.image.created": "{{.Date}}" + "org.opencontainers.image.name": "{{.ProjectName}}" + "org.opencontainers.image.revision": "{{.FullCommit}}" + "org.opencontainers.image.version": "{{.Version}}" + "org.opencontainers.image.source": "{{.GitURL}}" + ids: + - cli + dockerfile: build/kubescape-cli.Dockerfile + - id: http + images: + - "quay.io/kubescape/kubescape" + tags: + - "{{ .Tag }}" + labels: + "org.opencontainers.image.description": "Kubescape microservice" + "org.opencontainers.image.created": "{{.Date}}" + "org.opencontainers.image.name": "{{.ProjectName}}" + "org.opencontainers.image.revision": "{{.FullCommit}}" + "org.opencontainers.image.version": "{{.Version}}" + "org.opencontainers.image.source": "{{.GitURL}}" + ids: + - downloader + - http + dockerfile: build/Dockerfile changelog: sort: asc @@ -58,5 +122,19 @@ checksum: sboms: - artifacts: binary - documents: - - "{{ .Binary }}.sbom" + +krews: + - name: kubescape + ids: + - cli + homepage: https://kubescape.io/ + description: It includes risk analysis, security compliance, and misconfiguration scanning with an easy-to-use CLI interface, flexible output formats, and automated scanning capabilities. + short_description: Scan resources and cluster configs against security frameworks. + +release: + draft: true + footer: >- + + --- + + Released by [GoReleaser](https://github.com/goreleaser/goreleaser). diff --git a/.krew.yaml b/.krew.yaml deleted file mode 100644 index 9a8f14cc..00000000 --- a/.krew.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: krew.googlecontainertools.github.com/v1alpha2 -kind: Plugin -metadata: - name: kubescape -spec: - homepage: https://github.com/kubescape/kubescape/ - shortDescription: Scan resources and cluster configs against security frameworks. - version: {{ .TagName }} - description: | - It includes risk analysis, security compliance, and misconfiguration scanning - with an easy-to-use CLI interface, flexible output formats, and automated scanning capabilities. - platforms: - - selector: - matchLabels: - os: darwin - arch: amd64 - {{ addURIAndSha "https://github.com/kubescape/kubescape/releases/download/{{ .TagName }}/kubescape-macos-latest.tar.gz" .TagName }} - bin: kubescape - - selector: - matchLabels: - os: darwin - arch: arm64 - {{ addURIAndSha "https://github.com/kubescape/kubescape/releases/download/{{ .TagName }}/kubescape-arm64-macos-latest.tar.gz" .TagName }} - bin: kubescape - - selector: - matchLabels: - os: linux - arch: amd64 - {{ addURIAndSha "https://github.com/kubescape/kubescape/releases/download/{{ .TagName }}/kubescape-ubuntu-latest.tar.gz" .TagName }} - bin: kubescape - - selector: - matchLabels: - os: linux - arch: arm64 - {{ addURIAndSha "https://github.com/kubescape/kubescape/releases/download/{{ .TagName }}/kubescape-arm64-ubuntu-latest.tar.gz" .TagName }} - bin: kubescape - - selector: - matchLabels: - os: windows - arch: amd64 - {{ addURIAndSha "https://github.com/kubescape/kubescape/releases/download/{{ .TagName }}/kubescape-windows-latest.tar.gz" .TagName }} - bin: kubescape.exe diff --git a/build/Dockerfile b/build/Dockerfile index f94d1b1e..a059b4f4 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,25 +1,12 @@ -FROM --platform=$BUILDPLATFORM golang:1.25-trixie AS builder - -ENV GO111MODULE=on CGO_ENABLED=0 -WORKDIR /work -ARG TARGETOS TARGETARCH - -RUN --mount=target=. \ - --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg \ - cd httphandler && GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/ksserver . -RUN --mount=target=. \ - --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg \ - go run downloader/main.go - FROM gcr.io/distroless/static-debian13:nonroot USER nonroot WORKDIR /home/nonroot/ -COPY --from=builder /out/ksserver /usr/bin/ksserver -COPY --from=builder /root/.kubescape /home/nonroot/.kubescape +ARG TARGETPLATFORM +COPY $TARGETPLATFORM/downloader /usr/bin/downloader +RUN ["downloader"] +COPY $TARGETPLATFORM/ksserver /usr/bin/ksserver ARG image_version client ENV RELEASE=$image_version CLIENT=$client diff --git a/build/goreleaser-post-e2e.sh b/build/goreleaser-post-e2e.sh new file mode 100644 index 00000000..3e0fdc5a --- /dev/null +++ b/build/goreleaser-post-e2e.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env sh +# +# goreleaser-post-e2e.sh +# +# A small, robust POSIX shell script intended to be called from the goreleaser +# `builds[].hooks.post` entry. It is responsible for optionally running the +# repository smoke/e2e tests against the artifact produced in `dist/`. +# +# Usage: +# RUN_E2E=true -> enable running smoke/e2e tests +# E2E_FAIL_ON_ERROR=1 -> (default) treat test failures as fatal (exit non-zero) +# E2E_FAIL_ON_ERROR=0 -> treat test failures as non-fatal (log, but exit 0) +# +# The script is written to be defensive and to work under /bin/sh on CI runners. +# Use POSIX-safe flags only. +set -eu + +# Helper for logging +_now() { + date --iso-8601=seconds 2>/dev/null || date +} +log() { + printf '%s [goreleaser-post-e2e] %s\n' "$(_now)" "$*" +} + +# Small helper to interpret various truthy forms (1/true/yes/y) +is_true() { + case "${1:-}" in + 1|true|TRUE|yes|YES|y|Y) return 0 ;; + *) return 1 ;; + esac +} + +# Determine repo root relative to this script (script is expected to live in kubescape/build/) +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +: "${RUN_E2E:=false}" +# Default to non-fatal E2E failures. To make failures fatal, set a truthy value such as 1 or true. +: "${E2E_FAIL_ON_ERROR:=0}" + +log "Starting goreleaser post-build e2e script" +log "RUN_E2E=${RUN_E2E}" +log "E2E_FAIL_ON_ERROR=${E2E_FAIL_ON_ERROR}" + +if ! is_true "${RUN_E2E}"; then + log "RUN_E2E is not enabled. Skipping e2e/smoke tests. (RUN_E2E=${RUN_E2E})" + exit 0 +fi + +# Locate an artifact in dist/. Prefer the first file starting with 'kubescape' +ART_PATH="" +if [ -d "$REPO_ROOT/dist" ]; then + for cand in "$REPO_ROOT"/dist/*; do + # If no files matched, the glob may remain literal on some shells; guard: + if [ ! -e "$cand" ]; then + continue + fi + base="$(basename "$cand")" + case "$base" in + kubescape* ) + # skip obvious checksum files + case "$base" in + *.sha256|*.sha256sum) continue ;; + esac + if [ -f "$cand" ]; then + ART_PATH="$cand" + break + fi + ;; + * ) + # not a kubescape artifact + ;; + esac + done +fi + +if [ -z "$ART_PATH" ]; then + log "No kubescape artifact found in dist/. Skipping e2e/smoke tests." + exit 0 +fi + +log "Using artifact: $ART_PATH" +# Make binary executable if it is a binary +chmod +x "$ART_PATH" >/dev/null 2>&1 || true + +# Locate python runner +PYTHON="" +if command -v python3 >/dev/null 2>&1; then + PYTHON=python3 +elif command -v python >/dev/null 2>&1; then + PYTHON=python +fi + +if [ -z "$PYTHON" ]; then + log "python3 (or python) not found in PATH." + if is_true "${E2E_FAIL_ON_ERROR}"; then + log "E2E_FAIL_ON_ERROR enabled -> failing the release because python is missing." + exit 2 + else + log "E2E_FAIL_ON_ERROR disabled -> continuing without running tests." + exit 0 + fi +fi + +# Check for smoke test runner +SMOKE_RUNNER="$REPO_ROOT/smoke_testing/init.py" +if [ ! -f "$SMOKE_RUNNER" ]; then + log "Smoke test runner not found at $SMOKE_RUNNER" + if is_true "${E2E_FAIL_ON_ERROR}"; then + log "E2E_FAIL_ON_ERROR enabled -> failing the release because smoke runner is missing." + exit 3 + else + log "E2E_FAIL_ON_ERROR disabled -> continuing without running tests." + exit 0 + fi +fi + +log "Running smoke tests with $PYTHON $SMOKE_RUNNER \"$ART_PATH\"" +# Run the test runner, propagate exit code +set +e +"$PYTHON" "$SMOKE_RUNNER" "$ART_PATH" +rc=$? +set -e + +if [ $rc -eq 0 ]; then + log "Smoke/e2e tests passed (exit code 0)." + exit 0 +fi + +log "Smoke/e2e tests exited with code: $rc" +if is_true "${E2E_FAIL_ON_ERROR}"; then + log "E2E_FAIL_ON_ERROR enabled -> failing the release (exit code $rc)." + exit $rc +else + log "E2E_FAIL_ON_ERROR disabled -> continuing despite test failures." + exit 0 +fi diff --git a/build/kubescape-cli.Dockerfile b/build/kubescape-cli.Dockerfile index 2fb82ab6..f92e1a23 100644 --- a/build/kubescape-cli.Dockerfile +++ b/build/kubescape-cli.Dockerfile @@ -6,7 +6,8 @@ WORKDIR /home/nonroot/ ARG image_version client TARGETARCH ENV RELEASE=$image_version CLIENT=$client -COPY kubescape-${TARGETARCH}-ubuntu-latest /usr/bin/kubescape +ARG TARGETPLATFORM +COPY $TARGETPLATFORM/kubescape /usr/bin/kubescape RUN ["kubescape", "download", "artifacts"] ENTRYPOINT ["kubescape"] diff --git a/docs/TODO_GORELEASER_E2E.md b/docs/TODO_GORELEASER_E2E.md new file mode 100644 index 00000000..1312a5a3 --- /dev/null +++ b/docs/TODO_GORELEASER_E2E.md @@ -0,0 +1,131 @@ +# TODO: Goreleaser E2E / Smoke Test Integration +Path: `kubescape/docs/TODO_GORELEASER_E2E.md` + +Summary +------- +This document lists ideas, constraints, and next steps for moving e2e / smoke testing into the `goreleaser` pipeline via `build` hooks. The repository already contains a smoke test runner at `smoke_testing/init.py`. The goal is to provide a robust, configurable, and CI-friendly approach that runs tests only when the environment supports them. + +Design principles +----------------- +- Keep heavy integration/tests opt-in. Building and releasing should not require kind/docker/python unless explicitly requested. +- Make the goreleaser hook a single shell script (single invocation) so `if/fi`, variables, and state persist across lines. +- Prefer discovery of artifacts (glob) over hardcoded filenames when possible, but keep sensible defaults. +- Make failures configurable: sometimes tests should fail the release; sometimes they should be advisory (continue on error). + +Prerequisites (runner) +---------------------- +- `python3` available on PATH (or adjust to use a virtualenv in CI). +- Container runtime and `kind` if running cluster-based tests. +- Sufficient disk and RAM for `kind` clusters. +- Required secrets/environment variables present in CI for any tests that need authentication (see "Secrets" below). + +High-level TODOs +---------------- +1. Ensure goreleaser hook is a single script + - Update `builds[].hooks.post` in `.goreleaser.yaml` to be one multi-line script (YAML literal) so the entire script runs in a single shell. + - Confirm behavior locally by running goreleaser snapshot in an environment with `RUN_E2E=true`. + +2. Add opt-in trigger and documented env flag + - Use `RUN_E2E` (boolean-like) to decide whether to run post-build tests. + - Document how to enable it in CI: + - Example (GitHub Actions env): + - `RUN_E2E: "true"` + - `RELEASE: ${{ inputs.RELEASE }}` + - `CLIENT: ${{ inputs.CLIENT }}` + - Consider also adding a `GORELEASER_E2E_MODE` with values `smoke|system|none`. + +3. Artifact discovery + - Avoid relying on a single filename. Implement a small discovery step: + - Look for `dist/kubescape*` and pick the most appropriate artifact (prefer linux binary or the packaged format you want). + - Example logic: + - `ARTIFACT="$(ls dist | grep kubescape | grep -v '\.sha256' | head -n1)"` + - Use `ART_PATH="$(pwd)/dist/$ARTIFACT"` + - Add a fallback or an informative message when no artifact is found. + +4. Decide failure policy + - Two possible behaviors: + - Fail the goreleaser run when tests fail (useful for gating releases). + - Allow the release to continue and treat tests as best-effort (useful when you want to still publish). + - Implement via environment flag `E2E_FAIL_ON_ERROR=true|false`. If `false`, wrap test command with `|| true`. + +5. Integrate with existing smoke tests + - Use the existing `smoke_testing/init.py` to run basic smoke tests. + - Ensure the test runner can accept local artifact path as an argument (it already does in repository). + - If tests require additional args or secrets, allow passing them via env vars into the goreleaser hook. + +6. Optional: Run full system-tests (more complex) + - Steps the goreleaser hook would perform if `GORELEASER_E2E_MODE=system`: + - Clone `armosec/system-tests` into a temp directory. + - Create and activate Python virtualenv and `pip install -r requirements.txt`. + - Create a `kind` cluster (requires docker + kind). + - Pass the built artifact path to the test runner (similar to the GitHub workflow `run-tests` job). + - This is heavy and should be gated behind explicit flags and runner capabilities. + - Consider running this only in a dedicated CI job (not on goreleaser invoked in arbitrary environments). + +7. Secrets and CI environment + - Document secrets required by system tests (examples found in current GH Actions workflow): + - `CUSTOMER`, `USERNAME`, `PASSWORD`, `CLIENT_ID_PROD`, `SECRET_KEY_PROD`, `REGISTRY_USERNAME`, `REGISTRY_PASSWORD`. + - If tests need image pushes or pulls, ensure `QUAYIO_REGISTRY_USERNAME` and `QUAYIO_REGISTRY_PASSWORD` (or equivalent) are available. + - Ensure secrets are not echoed in logs. + +8. Logging and artifacts + - Ensure test output is streamed to the goreleaser logs for debugging. + - Upload test results (JUnit XML, screenshots) as artifacts in CI (not possible directly from goreleaser, but CI can capture logs/artifacts). + - If goreleaser is running in GitHub Actions, consider writing a step after goreleaser to run tests instead of embedding them in goreleaser. This allows richer workflows and artifact uploading. + +9. Implement robust teardown / cleanup + - If running `kind` clusters, ensure proper cleanup of clusters and temporary resources on success or failure. + +10. Security considerations + - Don't run privileged operations or accept untrusted input in the goreleaser hook. + - Avoid storing secrets in plaintext in config files. Use CI secret stores. + - If running tests that push signed artifacts or containers, ensure signing keys/passwords are protected (e.g., use cosign with ephemeral or protected secrets). + +11. Optional: Containerize test runner + - Create a small container image that contains all test dependencies (python, kind, kubectl, etc.). + - Instead of running tests directly in the goreleaser hook, run the container and mount the `dist/` dir into it. This reduces host dependency issues and makes execution reproducible. + - Example pattern: `docker run --rm -v $(pwd)/dist:/dist my-test-runner:latest /dist/kubescape-...` + +12. Example hook behaviour (concept) + - Single-script pattern to put in `.goreleaser.yaml`: + - check `RUN_E2E` + - discover artifact + - set `E2E_FAIL_ON_ERROR` behavior + - run `python3 smoke_testing/init.py "$ART_PATH"` + - exit non-zero or continue depending on policy + +13. Testing and validation + - Test the hook locally with goreleaser snapshot on a machine that has python3 installed: + - `RUN_E2E=true goreleaser release --snapshot --clean` + - Validate the script works both when `RUN_E2E` is unset and when set. + - Add unit/integration tests for the discovery logic if possible (small shell script unit tests). + +14. Documentation + - Add a short how-to in `CONTRIBUTING.md` or `docs/` describing: + - How to enable e2e tests in CI (env vars). + - What prerequisites the runner must provide. + - The meaning of `RUN_E2E`, `E2E_FAIL_ON_ERROR`, and `GORELEASER_E2E_MODE`. + +Concrete next steps (priority order) +----------------------------------- +1. Replace the current split-line hook with a single-script hook (already implemented locally). Verify the script runs end-to-end in CI. +2. Implement artifact discovery (glob) in the script and add `E2E_FAIL_ON_ERROR` support. +3. Add a short README entry (this TODO) into `docs/` explaining how to enable the tests and what runner prerequisites exist. +4. If required, implement an optional containerized test-runner image to reduce host dependencies. +5. If full system-tests are desired in goreleaser, implement a gated flow using `GORELEASER_E2E_MODE=system` that clones `armosec/system-tests` and runs the test runner (requires careful gating, secrets and runner capability checks). +6. Add a CI job (GitHub Actions) that runs goreleaser with `RUN_E2E=true` on a runner that has all required tools, captures test artifacts and test reports, and properly tears down resources. + +Notes & caveats +-------------- +- Running heavy system tests from within goreleaser can make releases brittle. Consider keeping goreleaser focused on build/release and run heavyweight tests as separate CI jobs that depend on goreleaser artifacts. +- The goreleaser action may run in containers where tools are limited; prefer invoking goreleaser in a full runner if you want to run `kind` and docker-based tests. +- If you want the release to be atomic (only publish if tests pass), make sure the goreleaser invocation happens in a CI job that has the necessary environment and ensures test success before pushing artifacts upstream. + +Where to go from here +--------------------- +- I can: + - Provide a ready-to-drop `hooks.post` script with artifact discovery and configurable failure behavior. + - Prepare a sample GitHub Actions job that runs goreleaser with `RUN_E2E=true` on a runner that has `python3`, `docker`, and `kind`. + - Draft a simple containerized test-runner Dockerfile for reliable execution. + +Pick which of these you'd like me to do next and I will produce the code/snippets (hook script, GitHub Actions job, or Dockerfile).