// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

plugins {
    id 'com.gradle.enterprise' version '3.13.4'
    id 'com.gradle.common-custom-user-data-gradle-plugin' version '1.11'
}

def isGithubActions = System.getenv('GITHUB_ACTIONS') != null
def isJenkins = System.getenv('JENKINS_URL') != null
def isCI = isGithubActions || isJenkins

gradleEnterprise {
    server = "https://ge.apache.org"
    buildScan {
        capture { taskInputFiles = true }
        uploadInBackground = !isCI
        publishAlways()
        publishIfAuthenticated()
        obfuscation {
            // This obfuscates the IP addresses of the build machine in the build scan.
            // Alternatively, the build scan will provide the hostname for troubleshooting host-specific issues.
            ipAddresses { addresses -> addresses.collect { address -> "0.0.0.0"} }
        }
    }
}

buildCache {
    local {
        enabled = !isCI
    }

    remote(gradleEnterprise.buildCache) {
        enabled = false
    }
}

include 'clients',
    'connect:api',
    'connect:basic-auth-extension',
    'connect:file',
    'connect:json',
    'connect:mirror',
    'connect:mirror-client',
    'connect:runtime',
    'connect:test-plugins',
    'connect:transforms',
    'core',
    'examples',
    'generator',
    'group-coordinator',
    'jmh-benchmarks',
    'log4j-appender',
    'metadata',
    'raft',
    'server-common',
    'shell',
    'storage',
    'storage:api',
    'streams',
    'streams:examples',
    'streams:streams-scala',
    'streams:test-utils',
    'streams:upgrade-system-tests-0100',
    'streams:upgrade-system-tests-0101',
    'streams:upgrade-system-tests-0102',
    'streams:upgrade-system-tests-0110',
    'streams:upgrade-system-tests-10',
    'streams:upgrade-system-tests-11',
    'streams:upgrade-system-tests-20',
    'streams:upgrade-system-tests-21',
    'streams:upgrade-system-tests-22',
    'streams:upgrade-system-tests-23',
    'streams:upgrade-system-tests-24',
    'streams:upgrade-system-tests-25',
    'streams:upgrade-system-tests-26',
    'streams:upgrade-system-tests-27',
    'streams:upgrade-system-tests-28',
    'streams:upgrade-system-tests-30',
    'streams:upgrade-system-tests-31',
    'streams:upgrade-system-tests-32',
    'streams:upgrade-system-tests-33',
    'streams:upgrade-system-tests-34',
    'streams:upgrade-system-tests-35',
    'tools',
    'tools:tools-api',
    'trogdor'

rootProject.name = 'kafka'
