Skip to content

Commit

Permalink
Testing of Keycloak admin client with Keycloak 24, 25 and nightly. GH…
Browse files Browse the repository at this point in the history
… actions setup updates to allow caching

closes keycloak/keycloak#31868

Signed-off-by: mposolda <[email protected]>
  • Loading branch information
mposolda committed Aug 7, 2024
1 parent cec8cb3 commit b6a894d
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 19 deletions.
44 changes: 44 additions & 0 deletions .github/actions/build-keycloak/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Build Keycloak Client
description: Builds Keycloak client providing Maven repository with all artifacts

inputs:
upload-m2-repo:
description: Upload Maven repository for org.keycloak artifacts
required: false
default: "true"

runs:
using: composite
steps:
- id: setup-java
name: Setup Java
uses: ./.github/actions/java-setup

- id: maven-cache
name: Maven cache
uses: ./.github/actions/maven-cache
with:
create-cache-if-it-doesnt-exist: true

- id: build-keycloak-client
name: Build Keycloak Client libraries
shell: bash
run: mvn -B clean install dependency:resolve -Pnightly -DskipTests=true

- id: compress-keycloak-maven-repository
name: Compress Keycloak Maven artifacts
if: inputs.upload-m2-repo == 'true'
shell: bash
run: |
tar -C ~/ --use-compress-program zstd -cf m2-keycloak.tzts \
--exclude '*.tar.gz' \
.m2/repository/org/keycloak
- id: upload-keycloak-maven-repository
name: Upload Keycloak Maven artifacts
if: inputs.upload-m2-repo == 'true'
uses: actions/upload-artifact@v4
with:
name: m2-keycloak.tzts
path: m2-keycloak.tzts
retention-days: 1
22 changes: 22 additions & 0 deletions .github/actions/java-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Setup Java
description: Sets up Java.

inputs:
distribution:
description: Java distribution.
required: false
default: temurin
java-version:
description: The Java version that is going to be set up.
required: false
default: "21"

runs:
using: composite
steps:
- id: setup-java
name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ inputs.distribution }}
java-version: ${{ inputs.java-version }}
42 changes: 42 additions & 0 deletions .github/actions/maven-cache/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Maven Cache
description: Caches Maven artifacts

inputs:
create-cache-if-it-doesnt-exist:
description: >
Only those callers which fill the cache with the right contents should set this to true to avoid creating a cache
which contains too few or too many entries.
required: false
default: false

runs:
using: composite
steps:
- id: weekly-cache-key
name: Key for weekly rotation of cache
shell: bash
run: echo "key=mvn-`date -u "+%Y-%U"`" >> $GITHUB_OUTPUT

- id: cache-maven-repository
name: Maven cache
uses: actions/cache@v4
if: inputs.create-cache-if-it-doesnt-exist == 'true'
with:
# Two asterisks are needed to make the follow-up exclusion work
# see https://github.com/actions/toolkit/issues/713 for the upstream issue
path: |
~/.m2/repository/*/*
!~/.m2/repository/org/keycloak
key: ${{ steps.weekly-cache-key.outputs.key }}

- id: restore-maven-repository
name: Maven cache
uses: actions/cache/restore@v4
if: inputs.create-cache-if-it-doesnt-exist == 'false'
with:
# Two asterisks are needed to make the follow-up exclusion work
# see https://github.com/actions/toolkit/issues/713 for the upstream issue
path: |
~/.m2/repository/*/*
!~/.m2/repository/org/keycloak
key: ${{ steps.weekly-cache-key.outputs.key }}
27 changes: 27 additions & 0 deletions .github/actions/test-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Setup unit test
description: Download Maven caches needed for unit tests

runs:
using: composite
steps:
- name: Setup Java
uses: ./.github/actions/java-setup

- id: maven-cache
name: Maven cache
uses: ./.github/actions/maven-cache

- id: download-keycloak
name: Download Keycloak Maven artifacts
uses: actions/download-artifact@v4
with:
name: m2-keycloak.tzts

- id: extract-maven-artifacts
name: Extract Keycloak Maven artifacts
shell: bash
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
choco install zstandard
fi
tar -C ~/ --use-compress-program="zstd -d" -xf m2-keycloak.tzts
32 changes: 23 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,31 @@ on:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
check-latest: true
cache: maven
- name: Build Keycloak Client Libs
uses: ./.github/actions/build-keycloak

admin-client-tests:
name: Admin client tests (Jakarta, JEE)
runs-on: ubuntu-latest
needs: build
timeout-minutes: 30
strategy:
matrix:
keycloak_server_version: [ "24.0", "25.0", "nightly" ]
steps:
- uses: actions/checkout@v4

- id: test-setup
name: Test setup
uses: ./.github/actions/test-setup

- name: Run unit tests
run: |
mvn -B -f testsuite/admin-client-tests/pom.xml test -Dkeycloak.version.docker.image=${{ matrix.keycloak_server_version }}
mvn -B -f testsuite/admin-client-jee-tests/pom.xml test -Dkeycloak.version.docker.image=${{ matrix.keycloak_server_version }}
- name: Build with Keycloak Nightly
run: mvn -B package -Pnightly
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ mvn clean install -Dkeycloak.lifecycle=remote

The testsuite won't start the Keycloak server, but instead tests will try to use Keycloak server, which is already started on this laptop where testsuite is running.

It is also possible to use different version of Keycloak server. By default, it uses `nightly` docker image, but can be overriden by the parameter like this:

```
mvn clean install -Dkeycloak.version.docker.image=24.0
```

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.keycloak.admin.client.Keycloak;
import org.keycloak.client.testsuite.KeycloakContainersTestsuiteContext;
import org.keycloak.client.testsuite.RemoteTestsuiteContext;
import org.keycloak.client.testsuite.TestConstants;
import org.keycloak.client.testsuite.TestsuiteContext;

/**
Expand All @@ -17,7 +18,7 @@ public abstract class AbstractAdminClientTest {

@BeforeAll
public static void beforeAll() {
String keycloakLifecycle = System.getProperty("keycloak.lifecycle");
String keycloakLifecycle = System.getProperty(TestConstants.PROPERTY_KEYCLOAK_LIFECYCLE);
testsuiteContext = "remote".equalsIgnoreCase(keycloakLifecycle) ? new RemoteTestsuiteContext() : new KeycloakContainersTestsuiteContext();

testsuiteContext.startKeycloakServer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dasniko.testcontainers.keycloak.KeycloakContainer;
import org.jboss.logging.Logger;
import org.keycloak.admin.client.Keycloak;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;

/**
* Providing Keycloak server based on testcontainers
Expand All @@ -14,7 +15,6 @@
public class KeycloakContainersTestsuiteContext implements TestsuiteContext {

private static final String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak";
private static final String KEYCLOAK_VERSION = "nightly"; // "25.0"; // TODO: Retrive from the configuration to be able to test with more Keycloak versions

private volatile KeycloakContainer keycloakContainer;
private Keycloak adminClient;
Expand All @@ -27,10 +27,18 @@ public void startKeycloakServer() {
if (keycloakContainer == null) {
synchronized (this) {
if (keycloakContainer == null) {
String dockerImage = KEYCLOAK_IMAGE + ":" + KEYCLOAK_VERSION;
logger.infof("Starting Keycloak server based on testcontainers. Docker image %s", dockerImage);
String keycloakVersion = System.getProperty(TestConstants.PROPERTY_KEYCLOAK_VERSION, TestConstants.KEYCLOAK_VERSION_DEFAULT);
String dockerImage = KEYCLOAK_IMAGE + ":" + keycloakVersion;
logger.infof("Starting Keycloak server based on testcontainers. Docker image: %s", dockerImage);

keycloakContainer = new KeycloakContainer(dockerImage).useTls();

if (keycloakVersion.startsWith("24.0")) {
// Health probe like https://localhost:37267/health/started reset connections by default on Keycloak 24. So fallback to use the log message
keycloakContainer.waitingFor(new LogMessageWaitStrategy()
.withRegEx(".*Profile dev activated.*\\s"));
}

keycloakContainer.start();
logger.infof("Started Keycloak server on URL %s", keycloakContainer.getAuthServerUrl());

Expand All @@ -42,13 +50,14 @@ public void startKeycloakServer() {

@Override
public void stopKeycloakServer() {
if (keycloakContainer == null) {
throw new IllegalStateException("Incorrect usage. Calling stopKeycloakServer before Keycloak server started.");
if (adminClient != null) {
adminClient.close();
}
if (keycloakContainer != null) {
logger.info("Going to stop Keycloak server");
keycloakContainer.stop();
logger.info("Stopped Keycloak server");
}
logger.info("Going to stop Keycloak server");
adminClient.close();
keycloakContainer.stop();
logger.info("Stopped Keycloak server");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public void startKeycloakServer() {
@Override
public void stopKeycloakServer() {
logger.infof("Ignored stop of Keycloak server as it is externally managed");
if (adminClient != null) {
logger.infof("Closing adminClient");
adminClient.close();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
*/
public class TestConstants {

public static final String PROPERTY_KEYCLOAK_LIFECYCLE = "keycloak.lifecycle";
public static final String PROPERTY_KEYCLOAK_VERSION = "keycloak.version.docker.image";
public static final String KEYCLOAK_VERSION_DEFAULT = "nightly";

public static final String MASTER_REALM = "master";
public static final String ADMIN_CLI_CLIENT = "admin-cli";
}

0 comments on commit b6a894d

Please sign in to comment.