diff --git a/.buildkite/scripts/common.sh b/.buildkite/scripts/common.sh index 1e941a5823e..fee21e2df0b 100755 --- a/.buildkite/scripts/common.sh +++ b/.buildkite/scripts/common.sh @@ -499,25 +499,44 @@ create_elastic_package_profile() { prepare_stack() { echo "--- Prepare stack" + local requiredSubscription="${ELASTIC_SUBSCRIPTION:-""}" + local requiredLogsDB="${STACK_LOGSDB_ENABLED:-"false"}" + local args="-v" + local version_set="" if [ -n "${STACK_VERSION}" ]; then args="${args} --version ${STACK_VERSION}" + version_set="${STACK_VERSION}" else local version version=$(oldest_supported_version) + if [[ "${requiredLogsDB}" == "true" ]]; then + # If LogsDB index mode is enabled, the required Elastic stack should be at least 8.17.0 + # In 8.17.0 LogsDB index mode was made GA. + local less_than="" + if ! less_than=$(mage -d "${WORKSPACE}" -w . isVersionLessThanLogsDBGA "${version}") ; then + echo "${FATAL_ERROR}" + return 1 + fi + if [[ "${less_than}" == "true" ]]; then + version="8.17.0" + fi + fi if [[ "${version}" != "null" ]]; then args="${args} --version ${version}" + version_set="${version}" fi fi + echoerr "- Stack Version: \"${version_set}\"" - if [ "${STACK_LOGSDB_ENABLED:-false}" == "true" ]; then + if [ "${requiredLogsDB:-false}" == "true" ]; then echoerr "- Enable LogsDB" args="${args} -U stack.logsdb_enabled=true" fi - if [ "${ELASTIC_SUBSCRIPTION:-""}" != "" ]; then + if [ "${requiredSubscription}" != "" ]; then echoerr "- Set Subscription ${ELASTIC_SUBSCRIPTION}" - args="${args} -U stack.elastic_subscription=${ELASTIC_SUBSCRIPTION}" + args="${args} -U stack.elastic_subscription=${requiredSubscription}" fi if [[ "${STACK_VERSION}" =~ ^7\.17 ]]; then @@ -686,6 +705,20 @@ is_subscription_compatible() { return 0 } +is_logsdb_compatible() { + if [[ "${STACK_VERSION:-""}" != "" ]]; then + # Assumption that if this variable is set, it is supported + echo "true" + return 0 + fi + + if ! reason=$(mage -d "${WORKSPACE}" -w . isLogsDBSupportedInPackage); then + return 1 + fi + echo "${reason}" + return 0 +} + is_pr_affected() { local package="${1}" local from="${2}" @@ -696,6 +729,19 @@ is_pr_affected() { return 1 fi + if [[ "${STACK_LOGSDB_ENABLED:-"false"}" == "true" ]]; then + # Packages require to support 8.17.0 or higher as part of their Kibana constraints (manifest) + local logsdb_compatible="" + if ! logsdb_compatible=$(is_logsdb_compatible); then + echo "${FATAL_ERROR}" + return 1 + fi + if [[ "${logsdb_compatible}" == "false" ]]; then + echo "[${package}] PR is not affected: not supported LogsDB (${STACK_VERSION})" + return 1 + fi + fi + if is_serverless; then if is_package_excluded_in_config "${package}" "${WORKSPACE}/kibana.serverless.config.yml"; then echo "[${package}] PR is not affected: package ${package} excluded in Kibana config for ${SERVERLESS_PROJECT}" diff --git a/dev/citools/logsdb.go b/dev/citools/logsdb.go new file mode 100644 index 00000000000..70829a82214 --- /dev/null +++ b/dev/citools/logsdb.go @@ -0,0 +1,59 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package citools + +import ( + "fmt" + + "github.com/Masterminds/semver/v3" +) + +var ( + semver8_17_0 = semver.MustParse("8.17.0") + semver8_19_99 = semver.MustParse("8.19.99") + semver9_99_99 = semver.MustParse("9.99.99") +) + +func IsVersionLessThanLogsDBGA(version *semver.Version) bool { + return version.LessThan(semver8_17_0) +} + +func packageKibanaConstraint(path string) (*semver.Constraints, error) { + manifest, err := readPackageManifest(path) + if err != nil { + return nil, err + } + + kibanaConstraint := manifest.Conditions.Kibana.Version + if kibanaConstraint == "" { + return nil, nil + } + + constraints, err := semver.NewConstraint(kibanaConstraint) + if err != nil { + return nil, err + } + + return constraints, nil +} + +func IsLogsDBSupportedInPackage(path string) (bool, error) { + constraint, err := packageKibanaConstraint(path) + if err != nil { + return false, fmt.Errorf("failed to read kibana.constraint fro mmanifest: %w", err) + } + + if constraint == nil { + // Package does not contain any kibana.version + return true, nil + } + + // Ensure that the package supports LogsDB mode + // It is not used here "semver8_17_0" since a constraint like "^8.18.0 || ^9.0.0" would return false + if constraint.Check(semver8_19_99) || constraint.Check(semver9_99_99) { + return true, nil + } + return false, nil +} diff --git a/dev/citools/logsdb_test.go b/dev/citools/logsdb_test.go new file mode 100644 index 00000000000..1db3db1997c --- /dev/null +++ b/dev/citools/logsdb_test.go @@ -0,0 +1,104 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package citools + +import ( + "os" + "path/filepath" + "testing" + + "github.com/Masterminds/semver/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIsVersionLessThanLogsDBGA(t *testing.T) { + cases := []struct { + title string + version *semver.Version + expected bool + }{ + { + title: "less than LogsDB GA", + version: semver.MustParse("8.12.0"), + expected: true, + }, + { + title: "greater or equal than LogsSB GA", + version: semver.MustParse("8.17.0"), + expected: false, + }, + } + + for _, c := range cases { + t.Run(c.title, func(t *testing.T) { + value := IsVersionLessThanLogsDBGA(c.version) + assert.Equal(t, c.expected, value) + }) + } + +} + +func TestIsLogsDBSupportedInPackage(t *testing.T) { + cases := []struct { + title string + contents string + expectedError bool + supported bool + }{ + { + title: "Supported LogsDB field", + contents: `name: "logsdb" +conditions: + kibana: + version: "^7.16.0 || ^8.0.0 || ^9.0.0" +`, + expectedError: false, + supported: true, + }, + { + title: "Kibana constraint dotted field", + contents: `name: "subscription" +conditions: + kibana.version: "^7.16.0 || ^8.0.0 || ^9.0.0" +`, + expectedError: false, + supported: true, + }, + { + title: "LogsDB not supported", + contents: `name: "subscription" +conditions: + kibana.version: "^7.16.0" +`, + expectedError: false, + supported: false, + }, + { + title: "No Kibana constraint", + contents: `name: "subscription" +`, + expectedError: false, + supported: true, + }, + } + + for _, c := range cases { + t.Run(c.title, func(t *testing.T) { + directory := t.TempDir() + pkgManifestPath := filepath.Join(directory, "manifest.yml") + err := os.WriteFile(pkgManifestPath, []byte(c.contents), 0o644) + require.NoError(t, err) + supported, err := IsLogsDBSupportedInPackage(pkgManifestPath) + if c.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, c.supported, supported) + } + }) + } + +} diff --git a/dev/testsreporter/_static/summary.tmpl b/dev/testsreporter/_static/summary.tmpl index 8eaff258350..260d1ad665f 100644 --- a/dev/testsreporter/_static/summary.tmpl +++ b/dev/testsreporter/_static/summary.tmpl @@ -1,8 +1,12 @@ {{ if ne .stackVersion "" -}} - Stack version: {{ .stackVersion }} {{ else -}} +{{ if .logsDB -}} +- Stack version: maximum of either the version used in PR builds or 8.17.0 (GA version for LogsDB index mode) +{{ else -}} - Stack version: Same as in Pull Request builds {{ end -}} +{{ end -}} {{ if .serverless -}} - Serverless: {{ .serverlessProject}} {{ end -}} diff --git a/dev/testsreporter/format_test.go b/dev/testsreporter/format_test.go index 88b0ded576b..ea969ef0f40 100644 --- a/dev/testsreporter/format_test.go +++ b/dev/testsreporter/format_test.go @@ -124,7 +124,7 @@ func TestSummary(t *testing.T) { `, }, { - title: "summary logsdb", + title: "summary logsdb without stack version defined", resultError: &packageError{ dataError: dataError{ logsDB: true, @@ -135,7 +135,7 @@ func TestSummary(t *testing.T) { }, teams: []string{"team1", "team2"}, }, - expected: `- Stack version: Same as in Pull Request builds + expected: `- Stack version: maximum of either the version used in PR builds or 8.17.0 (GA version for LogsDB index mode) - LogsDB: enabled - Package: foo - Failing test: mytest diff --git a/go.mod b/go.mod index 52b7c1c0353..1e9018f4048 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/elastic/integrations go 1.24.2 require ( + github.com/Masterminds/semver/v3 v3.3.1 github.com/blang/semver v3.5.1+incompatible github.com/cli/go-gh/v2 v2.12.0 github.com/elastic/elastic-package v0.111.0 @@ -34,7 +35,6 @@ require ( github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/PaesslerAG/gval v1.2.2 // indirect github.com/PaesslerAG/jsonpath v0.1.1 // indirect diff --git a/magefile.go b/magefile.go index 0a0ef0e4839..c22b4a6c334 100644 --- a/magefile.go +++ b/magefile.go @@ -14,6 +14,7 @@ import ( "path/filepath" "strconv" + "github.com/Masterminds/semver/v3" "github.com/magefile/mage/mg" "github.com/magefile/mage/sh" "github.com/pkg/errors" @@ -233,3 +234,32 @@ func IsSubscriptionCompatible() error { fmt.Println("false") return nil } + +// IsLogsDBSupportedInPackage checks wheter or not the package in the current directory supports LogsDB +func IsLogsDBSupportedInPackage() error { + supported, err := citools.IsLogsDBSupportedInPackage("manifest.yml") + if err != nil { + return err + } + if !supported { + fmt.Println("false") + return nil + } + fmt.Println("true") + return nil +} + +// IsVersionLessThanLogsDBGA checks wheter or not the given version supports LogsDB. Minimum version that supports LogsDB as GA 8.17.0. +func IsVersionLessThanLogsDBGA(version string) error { + stackVersion, err := semver.NewVersion(version) + if err != nil { + return fmt.Errorf("failed to parse version %q: %w", version, err) + } + lessThan := citools.IsVersionLessThanLogsDBGA(stackVersion) + if lessThan { + fmt.Println("true") + return nil + } + fmt.Println("false") + return nil +}