From 3041720fcd1fb4c6321bbe23764849a1d9892120 Mon Sep 17 00:00:00 2001 From: lukbla Date: Mon, 5 May 2025 14:59:19 +0200 Subject: [PATCH 1/2] CET-19215 add secret scanning --- .../java/org/kohsuke/github/GHRepository.java | 41 ++++ .../kohsuke/github/GHSecretScanningAlert.java | 185 ++++++++++++++++++ .../github/GHSecretScanningAlertState.java | 15 ++ .../GHSecretScanningAlertsIterable.java | 45 +++++ .../github/GHSecretScanningAlertTest.java | 103 ++++++++++ 5 files changed, 389 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHSecretScanningAlert.java create mode 100644 src/main/java/org/kohsuke/github/GHSecretScanningAlertState.java create mode 100644 src/main/java/org/kohsuke/github/GHSecretScanningAlertsIterable.java create mode 100644 src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 784242672c..aa6d7fcdc0 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -3496,6 +3496,47 @@ public void dispatch(String eventType, @Nullable T clientPayload) throws IOE .send(); } + /** + * Lists the secret scanning alerts for this repository + * + * @return the paged iterable + */ + public PagedIterable listSecretScanningAlerts() { + return listSecretScanningAlerts(Collections.emptyMap()); + } + + /** + * Lists the secret scanning alerts for this repository filtered on the alert state + * + * @param state + * state of the alert + * @return the paged iterable + */ + public PagedIterable listSecretScanningAlerts(GHSecretScanningAlertState state) { + return listSecretScanningAlerts(Collections.singletonMap("state", state.name().toLowerCase())); + } + + private PagedIterable listSecretScanningAlerts(Map filters) { + return new GHSecretScanningAlertsIterable(this, + root().createRequest().withUrlPath(getApiTailUrl("secret-scanning/alerts")).with(filters).build()); + } + + /** + * Get secret scanning alert by number + * + * @param number + * number of the secret scanning alert + * @return the secret scanning alert + * @throws IOException + * the io exception + */ + public GHSecretScanningAlert getSecretScanningAlert(long number) throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("secret-scanning/alerts"), String.valueOf(number)) + .fetch(GHSecretScanningAlert.class) + .wrap(this); + } + private T downloadArchive(@Nonnull String type, @CheckForNull String ref, @Nonnull InputStreamFunction streamFunction) throws IOException { diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java new file mode 100644 index 0000000000..8110e1a21d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java @@ -0,0 +1,185 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.io.IOException; +import java.net.URL; +import java.util.Date; + +/** + * Secret scanning alert for a repository + * + * + */ +@SuppressFBWarnings(value = { "UUF_UNUSED_FIELD" }, justification = "JSON API") +public class GHSecretScanningAlert extends GHObject { + @JsonIgnore + private GHRepository owner; + private long number; + private String html_url; + private GHSecretScanningAlertState state; + private String resolution; + private String resolved_at; + private GHUser resolved_by; + private String secret_type; + private Secret secret; + private String push_protection_bypassed; + private GHUser push_protection_bypassed_by; + private String push_protection_bypassed_at; + + GHSecretScanningAlert wrap(GHRepository owner) { + this.owner = owner; + return this; + } + + /** + * Id/number of the alert. + * + * @return the id/number + * @see #getId() + */ + public long getNumber() { + return number; + } + + /** + * Id/number of the alert. + * + * @return the id/number + * @see #getNumber() + */ + @Override + public long getId() { + return getNumber(); + } + + /** + * State of alert + * + * @return the state + */ + public GHSecretScanningAlertState getState() { + return state; + } + + /** + * Resolution of the alert. Can be 'false_positive', 'wont_fix', 'revoked', 'used_in_tests', or null. + * + * @return the resolution + */ + public String getResolution() { + return resolution; + } + + /** + * Time when alert was resolved. Non-null when {@link #getState()} is Resolved + * + * @return the time + */ + public Date getResolvedAt() { + return GitHubClient.parseDate(resolved_at); + } + + /** + * User that has resolved the alert. Non-null when {@link #getState()} is Resolved + * + *

+ * Note: User object returned by secret scanning GitHub API does not contain all fields. Use with caution + *

+ * + * @return the user + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getResolvedBy() { + return resolved_by; + } + + /** + * Type of secret that was detected + * + * @return the secret type + */ + public String getSecretType() { + return secret_type; + } + + /** + * Secret that was detected + * + * @return the secret + */ + public Secret getSecret() { + return secret; + } + + /** + * Whether push protection was bypassed for this alert + * + * @return true if push protection was bypassed, false otherwise + */ + public boolean isPushProtectionBypassed() { + return push_protection_bypassed != null && !push_protection_bypassed.isEmpty(); + } + + /** + * User that bypassed push protection. Non-null when {@link #isPushProtectionBypassed()} is true + * + * @return the user + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getPushProtectionBypassedBy() { + return push_protection_bypassed_by; + } + + /** + * Time when push protection was bypassed. Non-null when {@link #isPushProtectionBypassed()} is true + * + * @return the time + */ + public Date getPushProtectionBypassedAt() { + return GitHubClient.parseDate(push_protection_bypassed_at); + } + + @Override + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(html_url); + } + + /** + * Secret details + */ + @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") + public static class Secret { + private String name; + private String type; + private String value; + + /** + * Name of the secret + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Type of the secret + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * Value of the secret + * + * @return the value + */ + public String getValue() { + return value; + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlertState.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlertState.java new file mode 100644 index 0000000000..200cf55ed5 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlertState.java @@ -0,0 +1,15 @@ +package org.kohsuke.github; + +/** + * What is the current state of the Secret Scanning Alert + */ +public enum GHSecretScanningAlertState { + /** + * Alert is open and still an active issue. + */ + OPEN, + /** + * Issue that has caused the alert has been addressed. + */ + RESOLVED, +} diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlertsIterable.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlertsIterable.java new file mode 100644 index 0000000000..adbe02509e --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlertsIterable.java @@ -0,0 +1,45 @@ +package org.kohsuke.github; + +import java.util.Iterator; + +import javax.annotation.Nonnull; + +class GHSecretScanningAlertsIterable extends PagedIterable { + private final GHRepository owner; + private final GitHubRequest request; + private GHSecretScanningAlert[] result; + + GHSecretScanningAlertsIterable(GHRepository owner, GitHubRequest request) { + this.owner = owner; + this.request = request; + } + + @Nonnull + @Override + public PagedIterator _iterator(int pageSize) { + return new PagedIterator<>( + adapt(GitHubPageIterator + .create(owner.root().getClient(), GHSecretScanningAlert[].class, request, pageSize)), + null); + } + + protected Iterator adapt(final Iterator base) { + return new Iterator() { + public boolean hasNext() { + return base.hasNext(); + } + + public GHSecretScanningAlert[] next() { + GHSecretScanningAlert[] v = base.next(); + if (result == null) { + result = v; + } + + for (GHSecretScanningAlert alert : result) { + alert.wrap(owner); + } + return result; + } + }; + } +} diff --git a/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java b/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java new file mode 100644 index 0000000000..1eb35ada9d --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java @@ -0,0 +1,103 @@ +package org.kohsuke.github; + +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.*; + +/** + *

+ * Note : As the code scanning alerts cannot be tailored as part of test setup, lot of the test cases are dependent on + * manual setup of the mock repo. Assertions and verifications will often simply check that the values are non-null + * rather than depending on hard-coded values, to prevent making the tests flimsy + *

+ */ +public class GHSecretScanningAlertTest extends AbstractGitHubWireMockTest { + private static final String REPO_NAME = "Pixi"; + private GHRepository repo; + + /** + * Gets the mock repo + * + * @throws Exception + * the exception + */ + @Before + public void setUp() throws Exception { + repo = gitHub.getRepository("cortextests" + "/" + "test-code-scanning"); + } + + /** + * Test list code scanning alert payload + */ + @Test + public void testListSecretScanningAlerts() { + // Arrange + + // Act + List alerts = repo.listSecretScanningAlerts()._iterator(2).nextPage(); + + // Assert + assertThat(alerts.size(), equalTo(2)); // This assertion is based on manual setup done on repo to + // guarantee there are atleast 2 issues + + // GHCodeScanningAlert alert = codeQlAlerts.get(0); + // + // // Verify the code scanning tool details + // assertThat(alert.getTool(), not((Object) null)); + // GHCodeScanningAlert.Tool tool = alert.getTool(); + // assertThat(tool.getName(), is("CodeQL")); + // assertThat(tool.getVersion(), not((Object) null)); + // + // // Verify that fields of the code scanning rule are non-null + // assertThat(alert.getRule(), not((Object) null)); + // GHCodeScanningAlert.Rule rule = alert.getRule(); + // assertThat(rule.getId(), not((Object) null)); + // assertThat(rule.getName(), not((Object) null)); + // assertThat(rule.getSeverity(), not((Object) null)); + // assertThat(rule.getSecuritySeverityLevel(), not((Object) null)); + // + // // Act - Search by filtering on alert status + // List openAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.OPEN) + // ._iterator(2) + // .nextPage(); // This assertion is based on manual setup done on repo to + // // guarantee there are atleast 2 issues + // + // // Assert + // assertThat(openAlerts.size(), equalTo(2)); + // GHCodeScanningAlert openAlert = openAlerts.get(0); + // assertThat(openAlert.getState(), is(GHCodeScanningAlertState.OPEN)); + } + + /** + * Test get code scanning alert payload + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testGetCodeScanningAlert() throws IOException { + // Arrange + List dismissedAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.DISMISSED) + ._iterator(1) + .nextPage(); + Assume.assumeThat(dismissedAlerts.size(), greaterThanOrEqualTo(1)); + GHCodeScanningAlert dismissedAlert = dismissedAlerts.get(0); + long idOfDismissed = dismissedAlert.getId(); + + // Act + GHCodeScanningAlert result = repo.getCodeScanningAlert(idOfDismissed); + + // Assert + assertThat(result, not((Object) null)); + assertThat(result.getId(), equalTo(idOfDismissed)); + assertThat(result.getDismissedReason(), equalTo(dismissedAlert.getDismissedReason())); + assertThat(result.getDismissedAt(), equalTo(dismissedAlert.getDismissedAt())); + assertThat(result.getDismissedBy().login, equalTo(dismissedAlert.getDismissedBy().login)); + } + +} From f74b4276b677e930eb0d73c2a686d0772eec6421 Mon Sep 17 00:00:00 2001 From: lukbla Date: Mon, 5 May 2025 18:58:11 +0200 Subject: [PATCH 2/2] CET-19215 add secret scanning --- pom.xml | 2 +- .../kohsuke/github/GHSecretScanningAlert.java | 108 +++++++----- .../github/GHSecretScanningAlertLocation.java | 39 +++++ .../GHSecretScanningAlertLocationDetails.java | 28 +++ .../github/GHSecretScanningAlertTest.java | 90 ++++------ .../repos_cortextests_secret-scanning-1.json | 161 ++++++++++++++++++ ...ret-scanning_secret-scanning_alerts-2.json | 76 +++++++++ ..._secret-scanning_alerts_1_locations-4.json | 16 ++ ..._secret-scanning_alerts_2_locations-3.json | 16 ++ .../repos_cortextests_secret-scanning-1.json | 45 +++++ ...ret-scanning_secret-scanning_alerts-2.json | 44 +++++ ..._secret-scanning_alerts_1_locations-4.json | 44 +++++ ..._secret-scanning_alerts_2_locations-3.json | 44 +++++ 13 files changed, 611 insertions(+), 102 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHSecretScanningAlertLocation.java create mode 100644 src/main/java/org/kohsuke/github/GHSecretScanningAlertLocationDetails.java create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json create mode 100644 src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json diff --git a/pom.xml b/pom.xml index 798f08c8fd..927b6d1675 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.kohsuke cortexapps-github-api - 1.326 + 1.327 GitHub API for Java https://github-api.kohsuke.org/ GitHub API for Java diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java index 8110e1a21d..37e23eda70 100644 --- a/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlert.java @@ -5,7 +5,9 @@ import java.io.IOException; import java.net.URL; +import java.util.Arrays; import java.util.Date; +import java.util.List; /** * Secret scanning alert for a repository @@ -18,16 +20,22 @@ public class GHSecretScanningAlert extends GHObject { private GHRepository owner; private long number; private String html_url; + private String locations_url; private GHSecretScanningAlertState state; private String resolution; private String resolved_at; private GHUser resolved_by; private String secret_type; - private Secret secret; - private String push_protection_bypassed; + private String secret_type_display_name; + private String secret; + + private Boolean push_protection_bypassed; private GHUser push_protection_bypassed_by; private String push_protection_bypassed_at; + private String created_at; + private String updated_at; + GHSecretScanningAlert wrap(GHRepository owner) { this.owner = owner; return this; @@ -54,6 +62,11 @@ public long getId() { return getNumber(); } + @Override + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(html_url); + } + /** * State of alert * @@ -105,11 +118,20 @@ public String getSecretType() { } /** - * Secret that was detected + * Display name for tyype of secret that was detected + * + * @return the secret type display name + */ + public String getSecretTypeDisplayName() { + return secret_type_display_name; + } + + /** + * Secret value that was detected * - * @return the secret + * @return the secret value */ - public Secret getSecret() { + public String getSecret() { return secret; } @@ -118,8 +140,8 @@ public Secret getSecret() { * * @return true if push protection was bypassed, false otherwise */ - public boolean isPushProtectionBypassed() { - return push_protection_bypassed != null && !push_protection_bypassed.isEmpty(); + public Boolean isPushProtectionBypassed() { + return push_protection_bypassed; } /** @@ -141,45 +163,43 @@ public Date getPushProtectionBypassedAt() { return GitHubClient.parseDate(push_protection_bypassed_at); } - @Override - public URL getHtmlUrl() throws IOException { - return GitHubClient.parseURL(html_url); + /** + * Gets created at. + * + * @return the created at + */ + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); } /** - * Secret details - */ - @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") - public static class Secret { - private String name; - private String type; - private String value; - - /** - * Name of the secret - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Type of the secret - * - * @return the type - */ - public String getType() { - return type; - } - - /** - * Value of the secret - * - * @return the value - */ - public String getValue() { - return value; - } + * Gets updated at. + * + * @return the updated at + */ + public Date getUpdatedAt() { + return GitHubClient.parseDate(updated_at); } + + /** + * Gets locations url. + * + * @return the locations url + */ + public String getLocationsUrl() { + return locations_url; + } + + /** + * Gets locations. + * + * @return the locations array + * @throws IOException + * the io exception + */ + public List getLocations() throws IOException { + return Arrays.asList( + root().createRequest().withUrlPath(getLocationsUrl()).fetch(GHSecretScanningAlertLocation[].class)); + } + } diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocation.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocation.java new file mode 100644 index 0000000000..dcf90d0869 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocation.java @@ -0,0 +1,39 @@ +package org.kohsuke.github; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Code scanning alert for a repository + * + * + */ +@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") +public class GHSecretScanningAlertLocation { + private String type; + private GHSecretScanningAlertLocationDetails details; + + /** + * Instantiates a new GH secret scanning alert location. + */ + public GHSecretScanningAlertLocation() { + } + + /** + * The type of location. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * The details of the location. + * + * @return the details + */ + public GHSecretScanningAlertLocationDetails getDetails() { + return details; + } + +} diff --git a/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocationDetails.java b/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocationDetails.java new file mode 100644 index 0000000000..8c0ec0ef20 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHSecretScanningAlertLocationDetails.java @@ -0,0 +1,28 @@ +package org.kohsuke.github; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Code sc for a repository + * + * + */ +@SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") +public class GHSecretScanningAlertLocationDetails { + private String path; + + /** + * Instantiates a new GH secret scanning alert location details. + */ + public GHSecretScanningAlertLocationDetails() { + } + + /** + * The path to the file containing the secret. + * + * @return the path + */ + public String getPath() { + return path; + } +} diff --git a/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java b/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java index 1eb35ada9d..a34cb27bd0 100644 --- a/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java +++ b/src/test/java/org/kohsuke/github/GHSecretScanningAlertTest.java @@ -1,10 +1,8 @@ package org.kohsuke.github; -import org.junit.Assume; import org.junit.Before; import org.junit.Test; -import java.io.IOException; import java.util.List; import static org.hamcrest.Matchers.*; @@ -28,76 +26,54 @@ public class GHSecretScanningAlertTest extends AbstractGitHubWireMockTest { */ @Before public void setUp() throws Exception { - repo = gitHub.getRepository("cortextests" + "/" + "test-code-scanning"); + repo = gitHub.getRepository("cortextests" + "/" + "secret-scanning"); } /** - * Test list code scanning alert payload + * Test list secret scanning alert payload + * + * @throws Exception + * the exception */ @Test - public void testListSecretScanningAlerts() { + public void testListSecretScanningAlerts() throws Exception { // Arrange // Act List alerts = repo.listSecretScanningAlerts()._iterator(2).nextPage(); // Assert - assertThat(alerts.size(), equalTo(2)); // This assertion is based on manual setup done on repo to - // guarantee there are atleast 2 issues + assertThat(alerts.size(), equalTo(2)); - // GHCodeScanningAlert alert = codeQlAlerts.get(0); - // - // // Verify the code scanning tool details - // assertThat(alert.getTool(), not((Object) null)); - // GHCodeScanningAlert.Tool tool = alert.getTool(); - // assertThat(tool.getName(), is("CodeQL")); - // assertThat(tool.getVersion(), not((Object) null)); - // - // // Verify that fields of the code scanning rule are non-null - // assertThat(alert.getRule(), not((Object) null)); - // GHCodeScanningAlert.Rule rule = alert.getRule(); - // assertThat(rule.getId(), not((Object) null)); - // assertThat(rule.getName(), not((Object) null)); - // assertThat(rule.getSeverity(), not((Object) null)); - // assertThat(rule.getSecuritySeverityLevel(), not((Object) null)); - // - // // Act - Search by filtering on alert status - // List openAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.OPEN) - // ._iterator(2) - // .nextPage(); // This assertion is based on manual setup done on repo to - // // guarantee there are atleast 2 issues - // - // // Assert - // assertThat(openAlerts.size(), equalTo(2)); - // GHCodeScanningAlert openAlert = openAlerts.get(0); - // assertThat(openAlert.getState(), is(GHCodeScanningAlertState.OPEN)); - } + GHSecretScanningAlert alert1 = alerts.get(0); + assertThat(alert1.getNumber(), equalTo(2L)); + assertThat(alert1.getState(), equalTo(GHSecretScanningAlertState.OPEN)); + assertThat(alert1.getSecretType(), equalTo("npm_access_token")); + assertThat(alert1.getSecret(), equalTo("secret1")); + assertThat(alert1.isPushProtectionBypassed(), equalTo(false)); + assertThat(alert1.getResolvedBy(), nullValue()); + assertThat(alert1.getResolvedAt(), nullValue()); - /** - * Test get code scanning alert payload - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testGetCodeScanningAlert() throws IOException { - // Arrange - List dismissedAlerts = repo.listCodeScanningAlerts(GHCodeScanningAlertState.DISMISSED) - ._iterator(1) - .nextPage(); - Assume.assumeThat(dismissedAlerts.size(), greaterThanOrEqualTo(1)); - GHCodeScanningAlert dismissedAlert = dismissedAlerts.get(0); - long idOfDismissed = dismissedAlert.getId(); + List locations = alert1.getLocations(); + assertThat(locations.size(), equalTo(1)); + assertThat(locations.get(0).getType(), equalTo("commit")); + assertThat(locations.get(0).getDetails().getPath(), equalTo("secrets/secrets1.env")); - // Act - GHCodeScanningAlert result = repo.getCodeScanningAlert(idOfDismissed); + GHSecretScanningAlert alert2 = alerts.get(1); + assertThat(alert2.getNumber(), equalTo(1L)); + assertThat(alert2.getState(), equalTo(GHSecretScanningAlertState.OPEN)); + assertThat(alert2.getSecretType(), equalTo("stripe_test_secret_key")); + assertThat(alert2.getSecret(), equalTo("secret2")); + assertThat(alert2.isPushProtectionBypassed(), equalTo(true)); + assertThat(alert2.getPushProtectionBypassedBy().getLogin(), equalTo("lukbla")); + assertThat(alert2.getPushProtectionBypassedAt(), equalTo(GitHubClient.parseDate("2025-05-05T15:32:05Z"))); + assertThat(alert2.getResolvedBy(), nullValue()); + assertThat(alert2.getResolvedAt(), nullValue()); - // Assert - assertThat(result, not((Object) null)); - assertThat(result.getId(), equalTo(idOfDismissed)); - assertThat(result.getDismissedReason(), equalTo(dismissedAlert.getDismissedReason())); - assertThat(result.getDismissedAt(), equalTo(dismissedAlert.getDismissedAt())); - assertThat(result.getDismissedBy().login, equalTo(dismissedAlert.getDismissedBy().login)); + List locations2 = alert2.getLocations(); + assertThat(locations2.size(), equalTo(1)); + assertThat(locations2.get(0).getType(), equalTo("commit")); + assertThat(locations2.get(0).getDetails().getPath(), equalTo("secrets.env")); } } diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning-1.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning-1.json new file mode 100644 index 0000000000..ff0f3345d5 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning-1.json @@ -0,0 +1,161 @@ +{ + "id": 978177282, + "node_id": "R_kgDOOk3NAg", + "name": "secret-scanning", + "full_name": "cortextests/secret-scanning", + "private": false, + "owner": { + "login": "cortextests", + "id": 87100841, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjg3MTAwODQx", + "avatar_url": "https://avatars.githubusercontent.com/u/87100841?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/cortextests", + "html_url": "https://github.com/cortextests", + "followers_url": "https://api.github.com/users/cortextests/followers", + "following_url": "https://api.github.com/users/cortextests/following{/other_user}", + "gists_url": "https://api.github.com/users/cortextests/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cortextests/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cortextests/subscriptions", + "organizations_url": "https://api.github.com/users/cortextests/orgs", + "repos_url": "https://api.github.com/users/cortextests/repos", + "events_url": "https://api.github.com/users/cortextests/events{/privacy}", + "received_events_url": "https://api.github.com/users/cortextests/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "html_url": "https://github.com/cortextests/secret-scanning", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/cortextests/secret-scanning", + "forks_url": "https://api.github.com/repos/cortextests/secret-scanning/forks", + "keys_url": "https://api.github.com/repos/cortextests/secret-scanning/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/cortextests/secret-scanning/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/cortextests/secret-scanning/teams", + "hooks_url": "https://api.github.com/repos/cortextests/secret-scanning/hooks", + "issue_events_url": "https://api.github.com/repos/cortextests/secret-scanning/issues/events{/number}", + "events_url": "https://api.github.com/repos/cortextests/secret-scanning/events", + "assignees_url": "https://api.github.com/repos/cortextests/secret-scanning/assignees{/user}", + "branches_url": "https://api.github.com/repos/cortextests/secret-scanning/branches{/branch}", + "tags_url": "https://api.github.com/repos/cortextests/secret-scanning/tags", + "blobs_url": "https://api.github.com/repos/cortextests/secret-scanning/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/cortextests/secret-scanning/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/cortextests/secret-scanning/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/cortextests/secret-scanning/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/cortextests/secret-scanning/statuses/{sha}", + "languages_url": "https://api.github.com/repos/cortextests/secret-scanning/languages", + "stargazers_url": "https://api.github.com/repos/cortextests/secret-scanning/stargazers", + "contributors_url": "https://api.github.com/repos/cortextests/secret-scanning/contributors", + "subscribers_url": "https://api.github.com/repos/cortextests/secret-scanning/subscribers", + "subscription_url": "https://api.github.com/repos/cortextests/secret-scanning/subscription", + "commits_url": "https://api.github.com/repos/cortextests/secret-scanning/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/cortextests/secret-scanning/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/cortextests/secret-scanning/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/cortextests/secret-scanning/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/cortextests/secret-scanning/contents/{+path}", + "compare_url": "https://api.github.com/repos/cortextests/secret-scanning/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/cortextests/secret-scanning/merges", + "archive_url": "https://api.github.com/repos/cortextests/secret-scanning/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/cortextests/secret-scanning/downloads", + "issues_url": "https://api.github.com/repos/cortextests/secret-scanning/issues{/number}", + "pulls_url": "https://api.github.com/repos/cortextests/secret-scanning/pulls{/number}", + "milestones_url": "https://api.github.com/repos/cortextests/secret-scanning/milestones{/number}", + "notifications_url": "https://api.github.com/repos/cortextests/secret-scanning/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/cortextests/secret-scanning/labels{/name}", + "releases_url": "https://api.github.com/repos/cortextests/secret-scanning/releases{/id}", + "deployments_url": "https://api.github.com/repos/cortextests/secret-scanning/deployments", + "created_at": "2025-05-05T15:30:32Z", + "updated_at": "2025-05-05T15:32:18Z", + "pushed_at": "2025-05-05T15:32:15Z", + "git_url": "git://github.com/cortextests/secret-scanning.git", + "ssh_url": "git@github.com:cortextests/secret-scanning.git", + "clone_url": "https://github.com/cortextests/secret-scanning.git", + "svn_url": "https://github.com/cortextests/secret-scanning", + "homepage": null, + "size": 1, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "main", + "permissions": { + "admin": true, + "maintain": true, + "push": true, + "triage": true, + "pull": true + }, + "temp_clone_token": "", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE", + "custom_properties": {}, + "organization": { + "login": "cortextests", + "id": 87100841, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjg3MTAwODQx", + "avatar_url": "https://avatars.githubusercontent.com/u/87100841?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/cortextests", + "html_url": "https://github.com/cortextests", + "followers_url": "https://api.github.com/users/cortextests/followers", + "following_url": "https://api.github.com/users/cortextests/following{/other_user}", + "gists_url": "https://api.github.com/users/cortextests/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cortextests/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cortextests/subscriptions", + "organizations_url": "https://api.github.com/users/cortextests/orgs", + "repos_url": "https://api.github.com/users/cortextests/repos", + "events_url": "https://api.github.com/users/cortextests/events{/privacy}", + "received_events_url": "https://api.github.com/users/cortextests/received_events", + "type": "Organization", + "user_view_type": "public", + "site_admin": false + }, + "security_and_analysis": { + "secret_scanning": { + "status": "enabled" + }, + "secret_scanning_push_protection": { + "status": "disabled" + }, + "dependabot_security_updates": { + "status": "disabled" + }, + "secret_scanning_non_provider_patterns": { + "status": "disabled" + }, + "secret_scanning_validity_checks": { + "status": "disabled" + } + }, + "network_count": 0, + "subscribers_count": 4 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json new file mode 100644 index 0000000000..47513c9d1d --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json @@ -0,0 +1,76 @@ +[ + { + "number": 2, + "created_at": "2025-05-05T15:32:16Z", + "updated_at": "2025-05-05T15:32:16Z", + "url": "https://api.github.com/repos/cortextests/secret-scanning/secret-scanning/alerts/2", + "html_url": "https://github.com/cortextests/secret-scanning/security/secret-scanning/2", + "locations_url": "https://api.github.com/repos/cortextests/secret-scanning/secret-scanning/alerts/2/locations", + "state": "open", + "secret_type": "npm_access_token", + "secret_type_display_name": "npm Access Token", + "secret": "secret1", + "validity": "unknown", + "multi_repo": false, + "is_base64_encoded": false, + "publicly_leaked": true, + "resolution": null, + "resolved_by": null, + "resolved_at": null, + "resolution_comment": null, + "push_protection_bypassed": false, + "push_protection_bypassed_by": null, + "push_protection_bypassed_at": null, + "push_protection_bypass_request_reviewer": null, + "push_protection_bypass_request_reviewer_comment": null, + "push_protection_bypass_request_comment": null, + "push_protection_bypass_request_html_url": null + }, + { + "number": 1, + "created_at": "2025-05-05T15:32:16Z", + "updated_at": "2025-05-05T15:32:16Z", + "url": "https://api.github.com/repos/cortextests/secret-scanning/secret-scanning/alerts/1", + "html_url": "https://github.com/cortextests/secret-scanning/security/secret-scanning/1", + "locations_url": "https://api.github.com/repos/cortextests/secret-scanning/secret-scanning/alerts/1/locations", + "state": "open", + "secret_type": "stripe_test_secret_key", + "secret_type_display_name": "Stripe Test API Secret Key", + "secret": "secret2", + "validity": "unknown", + "multi_repo": false, + "is_base64_encoded": false, + "publicly_leaked": true, + "resolution": null, + "resolved_by": null, + "resolved_at": null, + "resolution_comment": null, + "push_protection_bypassed": true, + "push_protection_bypassed_by": { + "login": "lukbla", + "id": 14848012, + "node_id": "MDQ6VXNlcjE0ODQ4MDEy", + "avatar_url": "https://avatars.githubusercontent.com/u/14848012?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/lukbla", + "html_url": "https://github.com/lukbla", + "followers_url": "https://api.github.com/users/lukbla/followers", + "following_url": "https://api.github.com/users/lukbla/following{/other_user}", + "gists_url": "https://api.github.com/users/lukbla/gists{/gist_id}", + "starred_url": "https://api.github.com/users/lukbla/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/lukbla/subscriptions", + "organizations_url": "https://api.github.com/users/lukbla/orgs", + "repos_url": "https://api.github.com/users/lukbla/repos", + "events_url": "https://api.github.com/users/lukbla/events{/privacy}", + "received_events_url": "https://api.github.com/users/lukbla/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "push_protection_bypassed_at": "2025-05-05T15:32:05Z", + "push_protection_bypass_request_reviewer": null, + "push_protection_bypass_request_reviewer_comment": null, + "push_protection_bypass_request_comment": null, + "push_protection_bypass_request_html_url": null + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json new file mode 100644 index 0000000000..99f13ef626 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json @@ -0,0 +1,16 @@ +[ + { + "type": "commit", + "details": { + "path": "secrets.env", + "start_line": 12, + "end_line": 12, + "start_column": 19, + "end_column": 51, + "blob_sha": "55b3a125e9a9432a82935f27b9c68c5cda615f73", + "blob_url": "https://api.github.com/repos/cortextests/secret-scanning/git/blobs/55b3a125e9a9432a82935f27b9c68c5cda615f73", + "commit_sha": "86d90215490fccfae2479cb037c2924857bda0e3", + "commit_url": "https://api.github.com/repos/cortextests/secret-scanning/git/commits/86d90215490fccfae2479cb037c2924857bda0e3" + } + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json new file mode 100644 index 0000000000..c89ac02b08 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/__files/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json @@ -0,0 +1,16 @@ +[ + { + "type": "commit", + "details": { + "path": "secrets/secrets1.env", + "start_line": 9, + "end_line": 9, + "start_column": 11, + "end_column": 47, + "blob_sha": "55b3a125e9a9432a82935f27b9c68c5cda615f73", + "blob_url": "https://api.github.com/repos/cortextests/secret-scanning/git/blobs/55b3a125e9a9432a82935f27b9c68c5cda615f73", + "commit_sha": "86d90215490fccfae2479cb037c2924857bda0e3", + "commit_url": "https://api.github.com/repos/cortextests/secret-scanning/git/commits/86d90215490fccfae2479cb037c2924857bda0e3" + } + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning-1.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning-1.json new file mode 100644 index 0000000000..8d43cb9130 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning-1.json @@ -0,0 +1,45 @@ +{ + "id": "50b5d778-8619-4fde-b8e4-ffc7c2668f38", + "name": "repos_cortextests_secret-scanning", + "request": { + "url": "/repos/cortextests/secret-scanning", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_cortextests_secret-scanning-1.json", + "headers": { + "Date": "Tue, 06 May 2025 11:34:03 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"6534adbe51208ec686c4c331af35de5ce11f195f8be87f0549cb438eae49f3bd\"", + "Last-Modified": "Mon, 05 May 2025 15:32:18 GMT", + "X-OAuth-Scopes": "gist, notifications, project, repo, user, workflow, write:packages", + "X-Accepted-OAuth-Scopes": "repo", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4987", + "X-RateLimit-Reset": "1746533117", + "X-RateLimit-Used": "13", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-GitHub-Request-Id": "573A:3BFDA3:9D7BC3:A07A43:6819F3AB" + } + }, + "uuid": "50b5d778-8619-4fde-b8e4-ffc7c2668f38", + "persistent": true, + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json new file mode 100644 index 0000000000..5482d76b07 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts-2.json @@ -0,0 +1,44 @@ +{ + "id": "80193c8a-8098-444e-a590-70c276bb94e4", + "name": "repos_cortextests_secret-scanning_secret-scanning_alerts", + "request": { + "url": "/repos/cortextests/secret-scanning/secret-scanning/alerts?per_page=2", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_cortextests_secret-scanning_secret-scanning_alerts-2.json", + "headers": { + "Date": "Tue, 06 May 2025 11:34:04 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"bc86b69e772f3210a4a16816d4d561647a7ed9ecc91ffd21a6e80c57025f8787\"", + "X-OAuth-Scopes": "gist, notifications, project, repo, user, workflow, write:packages", + "X-Accepted-OAuth-Scopes": "public_repo, repo, security_events", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4986", + "X-RateLimit-Reset": "1746533117", + "X-RateLimit-Used": "14", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-GitHub-Request-Id": "56DB:12E1:2323E59:243C72B:6819F3AB" + } + }, + "uuid": "80193c8a-8098-444e-a590-70c276bb94e4", + "persistent": true, + "insertionIndex": 2 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json new file mode 100644 index 0000000000..af2e0aa16f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json @@ -0,0 +1,44 @@ +{ + "id": "fee4f520-dcbd-4a14-97c0-e90f37f38990", + "name": "repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations", + "request": { + "url": "/repos/cortextests/secret-scanning/secret-scanning/alerts/1/locations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_cortextests_secret-scanning_secret-scanning_alerts_1_locations-4.json", + "headers": { + "Date": "Tue, 06 May 2025 11:34:05 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"1698ce505845ba9429be3096423e6e365f50c504f227e13f1962b09f09732931\"", + "X-OAuth-Scopes": "gist, notifications, project, repo, user, workflow, write:packages", + "X-Accepted-OAuth-Scopes": "public_repo, repo, security_events", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4984", + "X-RateLimit-Reset": "1746533117", + "X-RateLimit-Used": "16", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-GitHub-Request-Id": "56EB:9ECAB:8DFAD2:90F7B5:6819F3AD" + } + }, + "uuid": "fee4f520-dcbd-4a14-97c0-e90f37f38990", + "persistent": true, + "insertionIndex": 4 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json new file mode 100644 index 0000000000..1ac9fb79ca --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHSecretScanningAlertTest/wiremock/testListSecretScanningAlerts/mappings/repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json @@ -0,0 +1,44 @@ +{ + "id": "a8c3dc32-9f17-4859-9262-1b42c91fe8c8", + "name": "repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations", + "request": { + "url": "/repos/cortextests/secret-scanning/secret-scanning/alerts/2/locations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_cortextests_secret-scanning_secret-scanning_alerts_2_locations-3.json", + "headers": { + "Date": "Tue, 06 May 2025 11:34:04 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", + "ETag": "W/\"c979a2680d5d142dd92b108df539ea5887a02e138812fcff3e33033da9cc19f8\"", + "X-OAuth-Scopes": "gist, notifications, project, repo, user, workflow, write:packages", + "X-Accepted-OAuth-Scopes": "public_repo, repo, security_events", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4985", + "X-RateLimit-Reset": "1746533117", + "X-RateLimit-Used": "15", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Server": "github.com", + "X-GitHub-Request-Id": "5720:127514:893F1A:8C3BE2:6819F3AC" + } + }, + "uuid": "a8c3dc32-9f17-4859-9262-1b42c91fe8c8", + "persistent": true, + "insertionIndex": 3 +} \ No newline at end of file