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

Onboard repo code coverage metrics #93

Merged
merged 1 commit into from
Oct 29, 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
6 changes: 6 additions & 0 deletions .github/workflows/cdk-ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ jobs:
with:
node-version: '20.8.0'

- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: 'corretto'
java-version: '17'

- name: Run CDK Test
run: |
./gradlew clean build
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ dependencies {

implementation 'software.amazon.awssdk:s3:2.28.17'

implementation 'org.json:json:20240303'

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'

Expand Down
16 changes: 14 additions & 2 deletions src/main/java/org/opensearchmetrics/dagger/MetricsModule.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/*
* 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 org.opensearchmetrics.dagger;

import com.fasterxml.jackson.databind.ObjectMapper;
import dagger.Module;
import dagger.Provides;
import org.opensearchmetrics.metrics.general.*;
import org.opensearchmetrics.metrics.label.LabelMetrics;
import org.opensearchmetrics.metrics.release.CodeCoverage;
import org.opensearchmetrics.metrics.release.ReleaseBranchChecker;
import org.opensearchmetrics.metrics.release.ReleaseIssueChecker;
import org.opensearchmetrics.metrics.release.ReleaseLabelIssuesFetcher;
Expand Down Expand Up @@ -144,7 +154,9 @@
public ReleaseMetrics getReleaseMetrics(OpenSearchUtil openSearchUtil, ObjectMapper objectMapper,
ReleaseRepoFetcher releaseRepoFetcher, ReleaseLabelIssuesFetcher releaseLabelIssuesFetcher,
ReleaseLabelPullsFetcher releaseLabelPullsFetcher, ReleaseVersionIncrementChecker releaseVersionIncrementChecker,
ReleaseBranchChecker releaseBranchChecker, ReleaseNotesChecker releaseNotesChecker, ReleaseIssueChecker releaseIssueChecker) {
return new ReleaseMetrics(openSearchUtil, objectMapper, releaseRepoFetcher, releaseLabelIssuesFetcher, releaseLabelPullsFetcher, releaseVersionIncrementChecker, releaseBranchChecker, releaseNotesChecker, releaseIssueChecker);
ReleaseBranchChecker releaseBranchChecker, ReleaseNotesChecker releaseNotesChecker, ReleaseIssueChecker releaseIssueChecker, CodeCoverage codeCoverage) {
return new ReleaseMetrics(openSearchUtil, objectMapper, releaseRepoFetcher,

Check warning on line 158 in src/main/java/org/opensearchmetrics/dagger/MetricsModule.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearchmetrics/dagger/MetricsModule.java#L158

Added line #L158 was not covered by tests
releaseLabelIssuesFetcher, releaseLabelPullsFetcher, releaseVersionIncrementChecker,
releaseBranchChecker, releaseNotesChecker, releaseIssueChecker, codeCoverage);
}
}
10 changes: 10 additions & 0 deletions src/main/java/org/opensearchmetrics/lambda/MetricsLambda.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* 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 org.opensearchmetrics.lambda;

import com.amazonaws.services.lambda.runtime.Context;
Expand Down Expand Up @@ -56,6 +65,7 @@ public Void handleRequest(Void input, Context context) {
metricsCalculation.generateGeneralMetrics(keys);
metricsCalculation.generateLabelMetrics(keys);
metricsCalculation.generateReleaseMetrics();
metricsCalculation.generateCodeCovMetrics();
} catch (Exception e) {
throw new RuntimeException("Error running Metrics Calculation", e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* 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 org.opensearchmetrics.metrics;

import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -6,8 +15,11 @@
import org.opensearch.index.query.BoolQueryBuilder;
import org.opensearchmetrics.metrics.general.*;
import org.opensearchmetrics.metrics.label.LabelMetrics;
import org.opensearchmetrics.metrics.release.CodeCoverage;
import org.opensearchmetrics.metrics.release.ReleaseInputs;
import org.opensearchmetrics.metrics.release.ReleaseMetrics;
import org.opensearchmetrics.model.codecov.CodeCovResponse;
import org.opensearchmetrics.model.codecov.CodeCovResult;
import org.opensearchmetrics.model.label.LabelData;
import org.opensearchmetrics.model.general.MetricsData;
import org.opensearchmetrics.model.release.ReleaseMetricsData;
Expand Down Expand Up @@ -199,4 +211,42 @@
openSearchUtil.bulkIndex("opensearch_release_metrics", metricFinalData);
}

public void generateCodeCovMetrics() {
ReleaseInputs[] releaseInputs = ReleaseInputs.getAllReleaseInputs();
Map<String, String> metricFinalData =
Arrays.stream(releaseInputs)
.filter(ReleaseInputs::getTrack)
.flatMap(releaseInput -> releaseMetrics.getReleaseRepos(releaseInput.getVersion()).entrySet().stream()
.flatMap(entry -> {
String repoName = entry.getKey();
String componentName = entry.getValue();
CodeCovResult codeCovResult = new CodeCovResult();
codeCovResult.setRepository(repoName);
codeCovResult.setComponent(componentName);
codeCovResult.setCurrentDate(currentDate.toString());
try {
codeCovResult.setId(String.valueOf(UUID.nameUUIDFromBytes(MessageDigest.getInstance("SHA-1")
.digest(("codecov-metrics-" + releaseInput.getBranch() + releaseInput.getVersion() + "-" + currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "-" + repoName)
.getBytes()))));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);

Check warning on line 232 in src/main/java/org/opensearchmetrics/metrics/MetricsCalculation.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearchmetrics/metrics/MetricsCalculation.java#L231-L232

Added lines #L231 - L232 were not covered by tests
}
codeCovResult.setReleaseVersion(releaseInput.getVersion());
codeCovResult.setVersion(releaseInput.getVersion());
codeCovResult.setReleaseState(releaseInput.getState());
codeCovResult.setBranch(releaseInput.getBranch());
CodeCovResponse codeCovResponse = releaseMetrics.getCodeCoverage(releaseInput.getBranch(), repoName);
codeCovResult.setCommitId(codeCovResponse.getCommitId());
codeCovResult.setState(codeCovResponse.getState());
codeCovResult.setCoverage(codeCovResponse.getCoverage());
codeCovResult.setUrl(codeCovResponse.getUrl());
return Stream.of(codeCovResult);
}))
.collect(Collectors.toMap(CodeCovResult::getId,
codeCovResult -> codeCovResult.getJson(codeCovResult, objectMapper)));
String codeCovIndexName = "opensearch-codecov-metrics-" + currentDate.format(DateTimeFormatter.ofPattern("MM-yyyy"));
openSearchUtil.createIndexIfNotExists(codeCovIndexName);
openSearchUtil.bulkIndex(codeCovIndexName, metricFinalData);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* 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 org.opensearchmetrics.metrics.release;

import com.google.common.annotations.VisibleForTesting;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.json.JSONArray;
import org.json.JSONObject;
import org.opensearchmetrics.model.codecov.CodeCovResponse;

import javax.inject.Inject;
import java.io.IOException;
import java.util.Optional;

public class CodeCoverage {
private final CloseableHttpClient httpClient;

@Inject
public CodeCoverage() {
this(HttpClients.createDefault());
}

@VisibleForTesting
CodeCoverage(CloseableHttpClient httpClient) {
prudhvigodithi marked this conversation as resolved.
Show resolved Hide resolved
this.httpClient = httpClient;
}

public CodeCovResponse coverage(String branch, String repo) {
String codeCovRepoURL = String.format("https://api.codecov.io/api/v2/github/opensearch-project/repos/%s/commits?branch=%s", repo, branch);
gaiksaya marked this conversation as resolved.
Show resolved Hide resolved
CodeCovResponse codeCovResponse = new CodeCovResponse();
codeCovResponse.setUrl(codeCovRepoURL);
HttpGet request = new HttpGet(codeCovRepoURL);
CloseableHttpResponse response;
try {
response = httpClient.execute(request);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (response.getStatusLine().getStatusCode() == 200) {
String codeCovApiResult;
try {
codeCovApiResult = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject jsonObject = new JSONObject(codeCovApiResult);
JSONArray resultsCoverage = jsonObject.getJSONArray("results");
Optional<JSONObject> firstResult = Optional.ofNullable(resultsCoverage)
.filter(results -> results.length() > 0)
.map(results -> results.getJSONObject(0));
firstResult.ifPresentOrElse(
result -> {
codeCovResponse.setState(Optional.ofNullable(result.optString("state"))
.orElse("no-coverage"));
codeCovResponse.setCommitId(result.optString("commitid", "none"));
codeCovResponse.setCoverage(
Optional.ofNullable(result.optJSONObject("totals"))
.map(totals -> totals.optDouble("coverage", 0.0))
.orElse(0.0)
);
},
() -> {
codeCovResponse.setState("no-coverage");
codeCovResponse.setCommitId("none");
codeCovResponse.setCoverage(0.0);
}
);
}
} finally {
try {
response.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return codeCovResponse;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
/*
* 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 org.opensearchmetrics.metrics.release;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.opensearchmetrics.model.codecov.CodeCovResponse;
import org.opensearchmetrics.model.codecov.CodeCovResult;
import org.opensearchmetrics.util.OpenSearchUtil;

import javax.inject.Inject;
import java.io.IOException;
import java.nio.charset.CoderResult;
import java.util.List;
import java.util.Map;

Expand All @@ -24,11 +37,13 @@ public class ReleaseMetrics {

private final ReleaseIssueChecker releaseIssueChecker;

private final CodeCoverage codeCoverage;

@Inject
public ReleaseMetrics(OpenSearchUtil openSearchUtil, ObjectMapper objectMapper, ReleaseRepoFetcher releaseRepoFetcher,
ReleaseLabelIssuesFetcher releaseLabelIssuesFetcher, ReleaseLabelPullsFetcher releaseLabelPullsFetcher,
ReleaseVersionIncrementChecker releaseVersionIncrementChecker, ReleaseBranchChecker releaseBranchChecker,
ReleaseNotesChecker releaseNotesChecker, ReleaseIssueChecker releaseIssueChecker) {
ReleaseNotesChecker releaseNotesChecker, ReleaseIssueChecker releaseIssueChecker, CodeCoverage codeCoverage) {
this.openSearchUtil = openSearchUtil;
this.objectMapper = objectMapper;
this.releaseRepoFetcher = releaseRepoFetcher;
Expand All @@ -38,6 +53,7 @@ public ReleaseMetrics(OpenSearchUtil openSearchUtil, ObjectMapper objectMapper,
this.releaseBranchChecker = releaseBranchChecker;
this.releaseNotesChecker = releaseNotesChecker;
this.releaseIssueChecker = releaseIssueChecker;
this.codeCoverage = codeCoverage;
}

public Map<String, String> getReleaseRepos(String releaseVersion) {
Expand Down Expand Up @@ -73,5 +89,9 @@ public String getReleaseIssue (String releaseVersion, String repo) {
return releaseIssueChecker.releaseIssue(releaseVersion, repo, openSearchUtil);
}

public CodeCovResponse getCodeCoverage (String branch, String repo) {
return codeCoverage.coverage(branch, repo);
}


}
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* 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 org.opensearchmetrics.metrics.release;

import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -36,6 +45,7 @@ public boolean releaseVersionIncrement(String releaseVersion, String repo, Strin
}
}


public boolean checkOpenSearchVersion(String releaseVersion, String branch) {
String url = String.format("https://raw.githubusercontent.com/opensearch-project/OpenSearch/%s/buildSrc/version.properties", branch);
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 org.opensearchmetrics.model.codecov;
prudhvigodithi marked this conversation as resolved.
Show resolved Hide resolved

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

import java.io.IOException;

@Data
public class CodeCovResponse {

@JsonProperty("commitid")
private String commitId;

@JsonProperty("url")
private String url;

@JsonProperty("state")
private String state;


@JsonSerialize(using = CodeCovDoubleSerializer.class)
@JsonProperty("coverage")
private Double coverage;
}

class CodeCovDoubleSerializer extends JsonSerializer<Double> {

@Override
public void serialize(Double value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value == null) {
jsonGenerator.writeNumber(0.0);
} else {
jsonGenerator.writeNumber(value);
}
}
}
Loading
Loading