Skip to content

Commit

Permalink
Onboard repo code coverage metrics
Browse files Browse the repository at this point in the history
Signed-off-by: Prudhvi Godithi <pgodithi@amazon.com>
  • Loading branch information
prudhvigodithi committed Oct 29, 2024
1 parent 6c900a3 commit 3a1cffd
Show file tree
Hide file tree
Showing 19 changed files with 996 additions and 62 deletions.
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 LabelMetrics getLabelMetrics() {
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 @@ public void generateReleaseMetrics() {
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) {
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);
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;

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

0 comments on commit 3a1cffd

Please sign in to comment.