Skip to content
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
- [Java] Replace `minimal-json` with regular expression ([#301](https://github.com/cucumber/ci-environment/pull/301))

### Removed
- [Python] Remove support for end-of-life Python 3.8 and 3.9 ([#297](https://github.com/cucumber/ci-environment/pull/297))

Expand Down
57 changes: 14 additions & 43 deletions java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,28 @@
</dependencyManagement>

<dependencies>

<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId>
<version>0.9.5</version>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>3.0</version>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<scope>test</scope>
</dependency>

Expand Down Expand Up @@ -109,6 +109,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- TODO: Pull up to parent pom-->
<parameters>true</parameters>
</configuration>
<executions>
<execution>
<id>generate-ci-environments</id>
Expand Down Expand Up @@ -169,39 +173,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.eclipsesource.minimal-json:minimal-json</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>com.eclipsesource.json</pattern>
<shadedPattern>io.cucumber.cienvironment.internal.com.eclipsesource.json</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>com.eclipsesource.minimal-json:minimal-json</artifact>
<excludes>
<exclude>META-INF/MANIFEST.MF</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ final class CiEnvironmentImpl implements CiEnvironment {
public String buildNumber;
public Git git;

CiEnvironmentImpl() {
}

CiEnvironmentImpl(String name, String url, String buildNumber, Git git) {
this.name = requireNonNull(name);
this.url = requireNonNull(url);
Expand Down Expand Up @@ -71,9 +68,6 @@ final static class Git implements CiEnvironment.Git {
public String branch;
public String tag;

Git() {
}

Git(String remote, String revision, String branch, String tag) {
this.remote = requireNonNull(remote);
this.revision = requireNonNull(revision);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package io.cucumber.cienvironment;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonValue;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -66,37 +59,9 @@ private static CiEnvironmentImpl.Git detectGit(CiEnvironment ci, Map<String, Str
}

private static String evaluateRevision(CiEnvironment ci, Map<String, String> env) {
String revision = evaluateRevisionGithub(env);
String revision = GithubEventParser.evaluateRevisionGithub(env);
if (revision != null) return revision;
return ci.getGit().map(git -> evaluate(git.getRevision(), env)).orElse(null);
}

/*
* Evaluate the current revision on GitHub.
*
* The GITHUB_SHA environment variable doesn't quite work as expected.
* See:
* * https://github.com/cucumber/ci-environment/issues/67
* * https://github.com/orgs/community/discussions/26325
* * https://github.com/cucumber/ci-environment/issues/86
*/
private static String evaluateRevisionGithub(Map<String, String> env) {
if (!"pull_request".equals(env.get("GITHUB_EVENT_NAME"))) {
return null;
}
if (env.get("GITHUB_EVENT_PATH") == null) {
throw new RuntimeException("GITHUB_EVENT_PATH not set");
}
try (InputStreamReader is = getGithubEvent(env)) {
JsonValue event = Json.parse(is);
return event.asObject().get("pull_request").asObject().get("head").asObject().get("sha").asString();
} catch (Exception e) {
throw new RuntimeException("Could not read .pull_request.head.sha from " + env.get("GITHUB_EVENT_PATH"), e);
}
}

private static InputStreamReader getGithubEvent(Map<String, String> env) throws FileNotFoundException {
return new InputStreamReader(new FileInputStream(env.get("GITHUB_EVENT_PATH")), StandardCharsets.UTF_8);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.cucumber.cienvironment;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

final class GithubEventParser {

/*
* Evaluate the current revision on GitHub.
*
* The GITHUB_SHA environment variable doesn't quite work as expected.
* See:
* * https://github.com/cucumber/ci-environment/issues/67
* * https://github.com/orgs/community/discussions/26325
* * https://github.com/cucumber/ci-environment/issues/86
*/
static String evaluateRevisionGithub(Map<String, String> env) {
if (!"pull_request".equals(env.get("GITHUB_EVENT_NAME"))) {
return null;
}
if (env.get("GITHUB_EVENT_PATH") == null) {
return null;
}
try {
Path path = Paths.get(env.get("GITHUB_EVENT_PATH"));
String event = String.join(" ", Files.readAllLines(path));
return parsePullRequestHeadSha(event);
} catch (IOException e) {
return null;
}
}

private static final Pattern GITHUB_EVENT_PATTERN = Pattern.compile(
// Start of object
"^\\{" +
// Any leading key-value pairs.
".*?" +
// Pull request key
"\"pull_request\" *: *" +
// Start of pull request value, must be an object
"\\{" +
// Any leading key-value pairs.
".*?" +
// Head key
"\"head\" *: *" +
// Start of head value, must be an object
"\\{" +
// Any leading key-value pairs.
".*?" +
// sha key and value, must be a hash-like string
"\"sha\" *: *\"([a-z0-9]+)\"" +
// Any key-value pairs.
".*" +
// End of head value.
"}" +
// Any trailing key-value pairs.
".*" +
// End of pull request value
"}" +
// Any trailing key-value pairs.
".*" +
// End of object
"}$");

static String parsePullRequestHeadSha(String eventJson) {
// Parse json using regex. Not ideal but works for the limited input.
Matcher matcher = GITHUB_EVENT_PATTERN.matcher(eventJson.trim());
if (!matcher.matches()) {
return null;
}
return matcher.group(1);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
import java.util.Map;

import static io.cucumber.cienvironment.DetectCiEnvironment.detectCiEnvironment;
import static io.cucumber.cienvironment.Jackson.OBJECT_MAPPER;
import static java.nio.file.Files.newBufferedReader;
import static java.nio.file.Files.newDirectoryStream;
import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

class DetectCiEnvironmentTest {
private static final ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);

private static List<Path> acceptance_tests_pass() throws IOException {
List<Path> paths = new ArrayList<>();
Expand Down Expand Up @@ -78,7 +77,7 @@ public Expectation convert(Object source, ParameterContext context) throws Argum
env.put(parts[0], parts[1]);
}
}
CiEnvironment expected = mapper.readValue(new File(path + ".json"), CiEnvironmentImpl.class);
CiEnvironment expected = OBJECT_MAPPER.readValue(new File(path + ".json"), CiEnvironmentImpl.class);
return new Expectation(env, expected);
} catch (IOException e) {
throw new ArgumentConversionException("Could not load " + source, e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
package io.cucumber.cienvironment;

import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import static io.cucumber.cienvironment.DetectCiEnvironment.detectCiEnvironment;
import static org.junit.jupiter.api.Assertions.assertEquals;

class GitHubPullRequestIntegrationTest {

@Test
void detects_the_correct_revision_for_pull_requests() {
if ("pull_request".equals(System.getenv().get("GITHUB_EVENT_NAME"))) {
CiEnvironment ciEnvironment = detectCiEnvironment(System.getenv()).orElseThrow(() -> new RuntimeException("No CI environment detected"));
System.out.println("Manually verify that the revision is correct");
System.out.println(ciEnvironment);
}
@EnabledIfEnvironmentVariable(named = "GITHUB_EVENT_NAME", matches = "pull_request", disabledReason = "Must be tested by creating a pull request on Github")
void detects_the_correct_revision_for_pull_requests() throws IOException {
Map<String, String> env = System.getenv();
assertEquals(parsePullRequestHeadShaWithJackson(env), parseRevisionWithRegularExpression(env));
}

private static String parseRevisionWithRegularExpression(Map<String, String> env) {
return detectCiEnvironment(env)
.orElseThrow(() -> new RuntimeException("No CI environment detected"))
.getGit().map(CiEnvironment.Git::getRevision)
.orElseThrow(() -> new RuntimeException("No Github Event detected"));
}

private static String parsePullRequestHeadShaWithJackson(Map<String, String> env) throws IOException {
File file = new File(env.get("GITHUB_EVENT_PATH"));
JsonNode event = Jackson.OBJECT_MAPPER.readTree(file);
return event.get("pull_request").get("head").get("sha").textValue();
}
}
32 changes: 32 additions & 0 deletions java/src/test/java/io/cucumber/cienvironment/Jackson.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.cucumber.cienvironment;

import com.fasterxml.jackson.annotation.JsonCreator.Mode;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.ConstructorDetector;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
import static com.fasterxml.jackson.annotation.JsonInclude.Value.construct;

final class Jackson {
public static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
.addModule(new Jdk8Module())
.addModule(new ParameterNamesModule(Mode.PROPERTIES))
.defaultPropertyInclusion(construct(NON_ABSENT, NON_ABSENT))
.constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
.enable(DeserializationFeature.USE_LONG_FOR_INTS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
.build();

private Jackson() {
}
}