diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0d581a6fd..87299800f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,25 +32,25 @@ jobs: - name: Run unit tests (Java 23) env: USER: unittest - USE_DOCKER_SERVICE: false + USE_EXTERNAL_SERVICE: false run: ./gradlew --no-daemon test -x spotlessCheck -x spotlessApply -x spotlessJava -P edgeDepsTest -PtestJavaVersion=23 - name: Run independent resource tuner test env: USER: unittest - USE_DOCKER_SERVICE: false + USE_EXTERNAL_SERVICE: false run: ./gradlew --no-daemon temporal-sdk:testResourceIndependent -x spotlessCheck -x spotlessApply -x spotlessJava -P edgeDepsTest -PtestJavaVersion=23 - name: Run Spring Boot 3 compatibility tests env: USER: unittest - USE_DOCKER_SERVICE: false + USE_EXTERNAL_SERVICE: false run: ./gradlew --no-daemon :temporal-spring-boot-autoconfigure:test -x spotlessCheck -x spotlessApply -x spotlessJava -P edgeDepsTest -P springBoot3Test -PtestJavaVersion=23 - name: Run Spring Boot 4 compatibility tests env: USER: unittest - USE_DOCKER_SERVICE: false + USE_EXTERNAL_SERVICE: false run: ./gradlew --no-daemon :temporal-spring-boot-autoconfigure:test -x spotlessCheck -x spotlessApply -x spotlessJava -P edgeDepsTest -P springBoot4Test -PtestJavaVersion=23 - name: Publish Test Report @@ -125,20 +125,20 @@ jobs: env: USER: unittest TEMPORAL_SERVICE_ADDRESS: localhost:7233 - USE_DOCKER_SERVICE: true + USE_EXTERNAL_SERVICE: true run: ./gradlew --no-daemon test -x spotlessCheck -x spotlessApply -x spotlessJava -PtestJavaVersion=11 - name: Run Jackson 3 converter tests (Java 17) env: USER: unittest - USE_DOCKER_SERVICE: false + USE_EXTERNAL_SERVICE: false run: ./gradlew --no-daemon :temporal-sdk:jackson3Tests -x spotlessCheck -x spotlessApply -x spotlessJava -PtestJavaVersion=17 - name: Run virtual thread tests (Java 21) env: USER: unittest TEMPORAL_SERVICE_ADDRESS: localhost:7233 - USE_DOCKER_SERVICE: true + USE_EXTERNAL_SERVICE: true run: ./gradlew --no-daemon :temporal-sdk:virtualThreadTests -x spotlessCheck -x spotlessApply -x spotlessJava -PtestJavaVersion=21 - name: Publish Test Report diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b0c1a0fd7..f3e646ac3e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,14 @@ before we can merge in any of your changes ## Development Environment -- Java 23+ -- Docker to run Temporal Server +- **Java 23+** is required to run Gradle and to compile the project. +- Some tests assume you also have **Java 17 and 21** installed. +- Some optional tests also require the [Temporal CLI](https://docs.temporal.io/cli#installation). + +You can install the Java dependencies all in one go with [mise](https://mise.jdx.dev/), which reads from [mise.toml](./mise.toml). If you're using mise and Gradle isn't automatically picking up the older JDKs as toolchains, try [this workaround](https://mise.jdx.dev/lang/java.html#gradle-toolchains-detection). + +If you're using Apple Silicon, see the [note on Rosetta](#note-on-rosetta). + ## Build @@ -41,26 +47,32 @@ fatal: No names found, cannot describe anything. This can be done resolved by running `git fetch --tags` on your branch. Note, make sure your fork has tags copied from the main repo. -## Test and Build +## Testing -Run a local temporal server with the [temporal CLI](https://docs.temporal.io/cli#installation): +Run tests: ```bash -temporal server start-dev +./gradlew test ``` -(If this does not work, see instructions for running the Temporal Server at https://github.com/temporalio/temporal/blob/master/README.md.) - -Then run all the tests with: +Run a single test or group of tests: ```bash -./gradlew test +./gradlew :temporal-sdk:test --offline --tests "io.temporal.activity.ActivityPauseTest" +./gradlew :temporal-sdk:test --offline --tests "io.temporal.workflow.*" ``` -Build with: +By default, integration tests run against the built-in time-skipping test server. Some tests require features that the built-in server doesn't support; those tests will be skipped. To run the skipped tests: +1. Install the [temporal CLI](https://docs.temporal.io/cli#installation), which comes with a built-in dev server. +2. Find the flags that the dev server will need to run the tests by grepping for `temporal server` in [./github/workflows/ci.yml](./github/workflows/ci.yml). +3. Start the server: +```bash +temporal server start-dev --YOUR-FLAGS-HERE +``` +4. Set the `USE_EXTERNAL_SERVICE` environment variable and run the tests: ```bash -./gradlew build +USE_EXTERNAL_SERVICE=true ./gradlew test ``` ## Note on Rosetta diff --git a/mise.toml b/mise.toml index dbdf2a1ebd..8bcc927862 100644 --- a/mise.toml +++ b/mise.toml @@ -1,15 +1,2 @@ -# TIP -# -# For the best SDK development experience, make to hava all of the following -# JDKs installed on your machine (`mise install java@[version]`): -# - `java@temurin-11` -# - `java@temurin-17` -# - `java@temurin-23` -# -# Java 21+ is required for anything that requires gradle. -# -# If you find out that gradle isn't automatically picking it up older JDKs as -# toolchains, see https://mise.jdx.dev/lang/java.html#gradle-toolchains-detection. - [tools] -java = "temurin-23" +java = ["temurin-23", "temurin-21", "temurin-17"] diff --git a/temporal-sdk/src/test/java/io/temporal/activity/ActivityPauseTest.java b/temporal-sdk/src/test/java/io/temporal/activity/ActivityPauseTest.java index fbab79d2c1..862b964307 100644 --- a/temporal-sdk/src/test/java/io/temporal/activity/ActivityPauseTest.java +++ b/temporal-sdk/src/test/java/io/temporal/activity/ActivityPauseTest.java @@ -62,6 +62,7 @@ public String execute() { } public static class HeartBeatingActivityImpl implements TestActivities.TestActivity1 { + @Override public String execute(String arg) { ActivityInfo info = Activity.getExecutionContext().getInfo(); diff --git a/temporal-sdk/src/test/java/io/temporal/worker/StickyWorkerTest.java b/temporal-sdk/src/test/java/io/temporal/worker/StickyWorkerTest.java index 508ab585b6..f14a207aaf 100644 --- a/temporal-sdk/src/test/java/io/temporal/worker/StickyWorkerTest.java +++ b/temporal-sdk/src/test/java/io/temporal/worker/StickyWorkerTest.java @@ -46,32 +46,15 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@RunWith(Parameterized.class) public class StickyWorkerTest { - private static final boolean useDockerService = - Boolean.parseBoolean(System.getenv("USE_DOCKER_SERVICE")); + private static final boolean useExternalService = + Boolean.parseBoolean(System.getenv("USE_EXTERNAL_SERVICE")); private static final String serviceAddress = System.getenv("TEMPORAL_SERVICE_ADDRESS"); - @Parameterized.Parameter public boolean useExternalService; - - @Parameterized.Parameters(name = "{1}") - public static Object[] data() { - if (!useDockerService) { - return new Object[][] {{false, "TestService"}}; - } else { - return new Object[][] {{true, "Docker"}}; - } - } - - @Parameterized.Parameter(1) - public String testType; - @Rule public TestName testName = new TestName(); private Scope metricsScope; @@ -536,7 +519,6 @@ public TestEnvironmentWrapper(WorkerFactoryOptions options) { .setMetricsScope(metricsScope) .setWorkflowClientOptions(clientOptions) .setWorkerFactoryOptions(options) - .setUseExternalService(useExternalService) .setTarget(serviceAddress) .build(); testEnv = TestWorkflowEnvironment.newInstance(testOptions); diff --git a/temporal-sdk/src/test/java/io/temporal/workerFactory/WorkerFactoryTests.java b/temporal-sdk/src/test/java/io/temporal/workerFactory/WorkerFactoryTests.java index 856ba8dcce..3b7974d459 100644 --- a/temporal-sdk/src/test/java/io/temporal/workerFactory/WorkerFactoryTests.java +++ b/temporal-sdk/src/test/java/io/temporal/workerFactory/WorkerFactoryTests.java @@ -21,13 +21,13 @@ public class WorkerFactoryTests { - private static final boolean useDockerService = - Boolean.parseBoolean(System.getenv("USE_DOCKER_SERVICE")); + private static final boolean useExternalService = + Boolean.parseBoolean(System.getenv("USE_EXTERNAL_SERVICE")); private static final String serviceAddress = System.getenv("TEMPORAL_SERVICE_ADDRESS"); @BeforeClass public static void beforeClass() { - Assume.assumeTrue(useDockerService); + Assume.assumeTrue(useExternalService); } private WorkflowServiceStubs service; diff --git a/temporal-spring-boot-autoconfigure/src/test/java/io/temporal/spring/boot/autoconfigure/WorkerVersioningTest.java b/temporal-spring-boot-autoconfigure/src/test/java/io/temporal/spring/boot/autoconfigure/WorkerVersioningTest.java index 5c0481b4ab..70cc4076bd 100644 --- a/temporal-spring-boot-autoconfigure/src/test/java/io/temporal/spring/boot/autoconfigure/WorkerVersioningTest.java +++ b/temporal-spring-boot-autoconfigure/src/test/java/io/temporal/spring/boot/autoconfigure/WorkerVersioningTest.java @@ -36,11 +36,11 @@ public class WorkerVersioningTest { @Autowired WorkflowClient workflowClient; @BeforeAll - static void checkDockerService() { - String useDocker = System.getenv("USE_DOCKER_SERVICE"); + static void checkExternalService() { + String useExternal = System.getenv("USE_EXTERNAL_SERVICE"); Assumptions.assumeTrue( - useDocker != null && useDocker.equalsIgnoreCase("true"), - "Skipping tests because USE_DOCKER_SERVICE is not set"); + useExternal != null && useExternal.equalsIgnoreCase("true"), + "Skipping tests because USE_EXTERNAL_SERVICE is not set"); } @BeforeEach diff --git a/temporal-testing/src/main/java/io/temporal/internal/docker/RegisterTestNamespace.java b/temporal-testing/src/main/java/io/temporal/internal/docker/RegisterTestNamespace.java index c58f2e35bd..c840adf55c 100644 --- a/temporal-testing/src/main/java/io/temporal/internal/docker/RegisterTestNamespace.java +++ b/temporal-testing/src/main/java/io/temporal/internal/docker/RegisterTestNamespace.java @@ -13,12 +13,12 @@ /** Waits for local service to become available and registers UnitTest namespace. */ public class RegisterTestNamespace { public static final String NAMESPACE = "UnitTest"; - private static final boolean useDockerService = - Boolean.parseBoolean(System.getenv("USE_DOCKER_SERVICE")); + private static final boolean useExternalService = + Boolean.parseBoolean(System.getenv("USE_EXTERNAL_SERVICE")); private static final String serviceAddress = System.getenv("TEMPORAL_SERVICE_ADDRESS"); public static void main(String[] args) throws InterruptedException { - if (!useDockerService) { + if (!useExternalService) { return; } diff --git a/temporal-testing/src/main/java/io/temporal/testing/internal/ExternalServiceTestConfigurator.java b/temporal-testing/src/main/java/io/temporal/testing/internal/ExternalServiceTestConfigurator.java index fdcc322355..b81a9d363c 100644 --- a/temporal-testing/src/main/java/io/temporal/testing/internal/ExternalServiceTestConfigurator.java +++ b/temporal-testing/src/main/java/io/temporal/testing/internal/ExternalServiceTestConfigurator.java @@ -5,15 +5,15 @@ import io.temporal.testing.TestWorkflowRule; public class ExternalServiceTestConfigurator { - private static boolean USE_DOCKER_SERVICE = - EnvironmentVariableUtils.readBooleanFlag("USE_DOCKER_SERVICE"); + private static boolean USE_EXTERNAL_SERVICE = + EnvironmentVariableUtils.readBooleanFlag("USE_EXTERNAL_SERVICE"); private static String TEMPORAL_SERVICE_ADDRESS = EnvironmentVariableUtils.readString("TEMPORAL_SERVICE_ADDRESS"); private static boolean USE_VIRTUAL_THREADS = EnvironmentVariableUtils.readBooleanFlag("USE_VIRTUAL_THREADS"); public static boolean isUseExternalService() { - return USE_DOCKER_SERVICE; + return USE_EXTERNAL_SERVICE; } public static boolean isUseVirtualThreads() { @@ -21,13 +21,13 @@ public static boolean isUseVirtualThreads() { } public static String getTemporalServiceAddress() { - return USE_DOCKER_SERVICE + return USE_EXTERNAL_SERVICE ? (TEMPORAL_SERVICE_ADDRESS != null ? TEMPORAL_SERVICE_ADDRESS : "127.0.0.1:7233") : null; } public static TestWorkflowRule.Builder configure(TestWorkflowRule.Builder testWorkflowRule) { - if (USE_DOCKER_SERVICE) { + if (USE_EXTERNAL_SERVICE) { testWorkflowRule.setUseExternalService(true); if (TEMPORAL_SERVICE_ADDRESS != null) { testWorkflowRule.setTarget(TEMPORAL_SERVICE_ADDRESS); @@ -38,7 +38,7 @@ public static TestWorkflowRule.Builder configure(TestWorkflowRule.Builder testWo public static TestEnvironmentOptions.Builder configure( TestEnvironmentOptions.Builder testEnvironmentOptions) { - if (USE_DOCKER_SERVICE) { + if (USE_EXTERNAL_SERVICE) { testEnvironmentOptions.setUseExternalService(true); if (TEMPORAL_SERVICE_ADDRESS != null) { testEnvironmentOptions.setTarget(TEMPORAL_SERVICE_ADDRESS); diff --git a/temporal-testing/src/main/java/io/temporal/testing/internal/SDKTestWorkflowRule.java b/temporal-testing/src/main/java/io/temporal/testing/internal/SDKTestWorkflowRule.java index 48a00afc45..e88a7ec3d2 100644 --- a/temporal-testing/src/main/java/io/temporal/testing/internal/SDKTestWorkflowRule.java +++ b/temporal-testing/src/main/java/io/temporal/testing/internal/SDKTestWorkflowRule.java @@ -64,7 +64,7 @@ public class SDKTestWorkflowRule implements TestRule { "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; // Enable to regenerate JsonFiles used for replay testing. public static final boolean REGENERATE_JSON_FILES = false; - // Only enable when USE_DOCKER_SERVICE is true + // Only enable when USE_EXTERNAL_SERVICE is true public static final boolean useExternalService = ExternalServiceTestConfigurator.isUseExternalService(); public static final boolean USE_VIRTUAL_THREADS =