Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 6.x] Add publishDistributionBuildResults and publishIntegTestResults to publish the OpenSearch build and integration test results #460

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ lib = library(identifier: 'jenkins@<tag>', retriever: modernSCM([
| [publishGradleCheckTestResults.groovy](./vars/publishGradleCheckTestResults.groovy) | This library runs part of Gradle Check and publishes the failed test data to the [OpenSearch Metrics Cluster](https://metrics.opensearch.org/_dashboards/app/dashboards#/view/e5e64d40-ed31-11ee-be99-69d1dbc75083).
| [gradleCheckFlakyTestDetector.groovy](./vars/gradleCheckFlakyTestDetector.groovy) | This library detects the flaky tests from [OpenSearch Metrics Cluster](https://metrics.opensearch.org/_dashboards/app/dashboards#/view/e5e64d40-ed31-11ee-be99-69d1dbc75083) and generates a test report.
| [gradleCheckFlakyTestGitHubIssue.groovy](./vars/gradleCheckFlakyTestGitHubIssue.groovy) | This library is used in [gradleCheckFlakyTestDetector.groovy](./vars/gradleCheckFlakyTestDetector.groovy) to create/edit the GitHub Issue using the generated test report.
| [publishDistributionBuildResults.groovy](./vars/publishDistributionBuildResults.groovy) | This library is used for publishing the OpenSearch Project Distribution build results to the OpenSearch Metrics cluster.
| [publishIntegTestResults.groovy](./vars/publishIntegTestResults.groovy) | This library is used for publishing the OpenSearch Project Integration Test results to the OpenSearch Metrics cluster.

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ jacocoTestReport {
}
}

String version = '6.6.1'
String version = '6.7.0'

task updateVersion {
doLast {
Expand Down
212 changes: 212 additions & 0 deletions tests/jenkins/TestPublishDistributionBuildResults.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package jenkins.tests

import org.junit.Before
import static org.mockito.Mockito.*
import groovy.json.JsonSlurper
import org.junit.Test
import groovy.json.JsonOutput

class TestPublishDistributionBuildResults extends BuildPipelineTest {

@Override
@Before
void setUp() {
super.setUp()
binding.setVariable('currentBuild', [
number: 123,
startTimeInMillis: System.currentTimeMillis(),
])
binding.setVariable('env', [
RUN_DISPLAY_URL: 'http://example.com/build/123'
])
binding.setVariable('sh', { cmd -> println cmd })
binding.setVariable('readFile', { filePath -> 'components:\n- name: component1\n repository: repo1\n ref: ref1' })
binding.setVariable('writeFile', { params -> println params.text })
binding.setVariable('withCredentials', { creds, closure -> closure() })
helper.registerAllowedMethod("withAWS", [Map, Closure], { args, closure ->
closure.delegate = delegate
return helper.callClosure(closure)
})
binding.setVariable('curl', { params -> println params })
}

@Test
void testIndexBuildData() {
def indexName = 'test-index'
def testRecordsFile = 'test-records.ndjson'

def script = loadScript('vars/publishDistributionBuildResults.groovy')

def calledCommands = new ArrayList()
script.metaClass.sh = { String command ->
calledCommands << command
if (command.contains("curl -I")) {
return "HTTP/1.1 200 OK"
} else if (command.contains("curl -s -XPUT") && command.contains("test-index")) {
return '{"acknowledged":true}'
} else if (command.contains("curl -XPOST") && command.contains("test-index")) {
return '{"took":10, "errors":false}'
} else {
throw new IllegalArgumentException("Unexpected command: $command")
}
}

script.indexFailedTestData(indexName, testRecordsFile)

def expectedCommandBlock = '''set +e
set +x
echo "INDEX NAME IS test-index"
INDEX_MAPPING='{
"mappings": {
"properties": {
"component": {
"type": "keyword"
},
"component_repo": {
"type": "keyword"
},
"component_ref": {
"type": "keyword"
},
"version": {
"type": "keyword"
},
"distribution_build_number": {
"type": "integer"
},
"distribution_build_url": {
"type": "keyword"
},
"build_start_time": {
"type": "date",
"format": "epoch_millis"
},
"rc": {
"type": "keyword"
},
"rc_number": {
"type": "integer"
},
"component_category": {
"type": "keyword"
},
"component_build_result": {
"type": "keyword"
}
}
}
}'
curl -I "METRICS_HOST_URL/test-index" --aws-sigv4 "aws:amz:us-east-1:es" --user "null:null" -H "x-amz-security-token:null" | grep -E "HTTP\\/[0-9]+(\\.[0-9]+)? 200"
if [ $? -eq 0 ]; then
echo "Index already exists. Indexing Results"
else
echo "Index does not exist. Creating..."
create_index_response=$(curl -s -XPUT "METRICS_HOST_URL/test-index" --aws-sigv4 "aws:amz:us-east-1:es" --user "null:null" -H "x-amz-security-token:null" -H 'Content-Type: application/json' -d "${INDEX_MAPPING}")
if [[ $create_index_response == *'"acknowledged":true'* ]]; then
echo "Index created successfully."
else
echo "Failed to create index. Error message: $create_index_response"
exit 1
fi
fi
if [ -s test-records.ndjson ]; then
echo "File Exists, indexing results."
curl -XPOST "METRICS_HOST_URL/test-index/_bulk" --aws-sigv4 "aws:amz:us-east-1:es" --user "null:null" -H "x-amz-security-token:null" -H "Content-Type: application/x-ndjson" --data-binary "@test-records.ndjson"
else
echo "File Does not exist. No tests records to process."
fi'''
assert calledCommands.size() == 1
assert normalizeString(calledCommands[0]) == normalizeString(expectedCommandBlock)
}

@Test
void testGenerateJson() {
def script = loadScript('vars/publishDistributionBuildResults.groovy')
def result = script.generateJson(
'component1', 'repo1', 'ref1', '1.0', 123,
'http://example.com/build/123', System.currentTimeMillis(), 'rc1', 1, 'test-category', 'failed'
)

def parsedResult = new JsonSlurper().parseText(result)
def expectedJson = [
component: 'component1',
component_repo: 'repo1',
component_ref: 'ref1',
version: '1.0',
distribution_build_number: 123,
distribution_build_url: 'http://example.com/build/123',
// Ignore build_start_time for comparison
rc: 'rc1',
rc_number: 1,
component_category: 'test-category',
component_build_result: 'failed'
]

// Remove the dynamic field for comparison
parsedResult.remove('build_start_time')
assert parsedResult == expectedJson
}

def normalizeString(String str) {
return str.replaceAll(/\s+/, " ").trim()
}

@Test
void testGenerateAndAppendJson() {
def script = loadScript('vars/publishDistributionBuildResults.groovy')
// Test valid parameters
def indexName = "test-index"
def component = "componentA"
def componentRepo = "repoA"
def componentRef = "refA"
def version = "1.0.0"
def distributionBuildNumber = "123"
def distributionBuildUrl = "http://example.com/build/123"
def buildStartTime = "2024-07-19T00:00:00Z"
def rc = true
def rcNumber = "RC1"
def componentCategory = "categoryA"
def status = "success"

def result = script.generateAndAppendJson(indexName, component, componentRepo, componentRef, version, distributionBuildNumber, distributionBuildUrl, buildStartTime, rc, rcNumber, componentCategory, status)
def expectedJson = JsonOutput.toJson([
component: component,
component_repo: componentRepo,
component_ref: componentRef,
version: version,
distribution_build_number: distributionBuildNumber,
distribution_build_url: distributionBuildUrl,
build_start_time: buildStartTime,
rc: rc,
rc_number: rcNumber,
component_category: componentCategory,
component_build_result: status
])
assert result == expectedJson

result = script.generateAndAppendJson(indexName, null, null, null, null, null, null, null, null, null, null, null)
expectedJson = JsonOutput.toJson([
component: null,
component_repo: null,
component_ref: null,
version: null,
distribution_build_number: null,
distribution_build_url: null,
build_start_time: null,
rc: null,
rc_number: null,
component_category: null,
component_build_result: null
])
assert result == expectedJson
}
}
Loading
Loading