diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 0e742b94c..f743081a7 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -23,7 +23,7 @@ jobs: GRADLE_CLI_OPTS: "" run: "chmod +x ./gradlew && ./gradlew ${GRADLE_CLI_OPTS} -Pversion=${API_VERSION} build jacocoTestReport" - name: Build and push Docker images - if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') + if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/cds' || startsWith(github.ref, 'refs/tags') uses: docker/build-push-action@v1.1.1 with: username: ${{ secrets.DOCKER_USERNAME }} diff --git a/Dockerfile b/Dockerfile index 6ce248419..2d3613d5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,17 +2,23 @@ FROM eclipse-temurin:21-jdk-alpine as builder WORKDIR /application ARG JAR_FILE=build/libs/faf-java-api-*.jar COPY ${JAR_FILE} application.jar -RUN java -Djarmode=layertools -jar application.jar extract +COPY test-pki-private.key /pki/secret.key +COPY test-pki-public.key /pki/public.key +COPY test-account-activation.html /config/mail/account-activation.html +COPY test-password-reset.html /config/mail/password-reset.html +COPY test-welcome-to-faf.html /config/mail/welcome-to-faf.html +ENV FAF_DOMAIN=faforever.com +ENV CHALLONGE_KEY=test +RUN java -Djarmode=tools -jar application.jar extract +RUN java -Dspring.context.exit=onRefresh -Dspring.profiles.active=training -XX:ArchiveClassesAtExit=application.jsa -jar application/application.jar FROM eclipse-temurin:21-jdk-alpine VOLUME /tmp WORKDIR /application -COPY --from=builder /application/dependencies/ ./ +COPY --from=builder /application/application/lib ./application/lib RUN true -COPY --from=builder /application/spring-boot-loader/ ./ +COPY --from=builder /application/application/application.jar ./application RUN true -COPY --from=builder /application/snapshot-dependencies/ ./ +COPY --from=builder /application/application.jsa ./ RUN true -COPY --from=builder /application/application/ ./ -RUN true -ENTRYPOINT ["java", "-server", "-Djava.security.egd=file:/dev/./urandom", "org.springframework.boot.loader.launch.JarLauncher"] +ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "-Djava.security.egd=file:/dev/./urandom", "-jar", "application/application.jar"] diff --git a/build.gradle b/build.gradle index 199b4d4b0..e8cefde1d 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { plugins { id "java" - id "org.springframework.boot" version "3.3.0" + id "org.springframework.boot" version "3.3.1" id "idea" id "com.adarshr.test-logger" version "4.0.0" } @@ -31,7 +31,10 @@ repositories { maven { url "https://jitpack.io" } } -compileJava.dependsOn(processResources) +compileJava { + dependsOn(processResources) + options.compilerArgs.add("-parameters") +} configurations { compile.exclude module: "assertj-core" @@ -39,7 +42,7 @@ configurations { idea { module { - testSourceDirs += file('src/inttest/java') + testSources = files(file("src/test/java"), file("src/inttest/java")) } } @@ -66,7 +69,7 @@ configurations { } -task inttest(type: Test) { +tasks.register('inttest', Test) { group = LifecycleBasePlugin.VERIFICATION_GROUP description = "Runs the integration tests." @@ -105,13 +108,14 @@ configurations { codacy } -task sendCoverageToCodacy(type: JavaExec, dependsOn: jacocoTestReport) { +tasks.register('sendCoverageToCodacy', JavaExec) { + dependsOn jacocoTestReport mainClass = "com.codacy.CodacyCoverageReporter" classpath = configurations.codacy args = ["report", "-l", "Java", "-r", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"] } -configurations.all { +configurations.configureEach { // Cache -SNAPSHOT for 60 seconds only resolutionStrategy.cacheChangingModulesFor 60, 'seconds' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3fa8f862f..b82aa23a4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/faforever/api/challonge/ChallongeController.java b/src/main/java/com/faforever/api/challonge/ChallongeController.java index fe3119703..bc892061d 100644 --- a/src/main/java/com/faforever/api/challonge/ChallongeController.java +++ b/src/main/java/com/faforever/api/challonge/ChallongeController.java @@ -2,12 +2,11 @@ import com.faforever.api.config.FafApiProperties; import com.faforever.api.config.FafApiProperties.Challonge; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -22,7 +21,6 @@ import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.UriBuilder; -import jakarta.servlet.http.HttpServletRequest; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -37,7 +35,6 @@ * only loaded if a Challonge API key is specified.

*/ @RestController -@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) @RequestMapping(path = ChallongeController.CHALLONGE_ROUTE) @ConditionalOnProperty("faf-api.challonge.key") public class ChallongeController { diff --git a/src/main/java/com/faforever/api/config/ApplicationProfile.java b/src/main/java/com/faforever/api/config/ApplicationProfile.java index 5d692e1b1..a37702cbb 100644 --- a/src/main/java/com/faforever/api/config/ApplicationProfile.java +++ b/src/main/java/com/faforever/api/config/ApplicationProfile.java @@ -5,6 +5,7 @@ public final class ApplicationProfile { public static final String PRODUCTION = "prod"; public static final String DEVELOPMENT = "dev"; public static final String INTEGRATION_TEST = "int"; + public static final String TRAINING = "training"; private ApplicationProfile() { // Utility class diff --git a/src/main/java/com/faforever/api/config/CacheConfig.java b/src/main/java/com/faforever/api/config/CacheConfig.java index 9140741a0..84595051d 100644 --- a/src/main/java/com/faforever/api/config/CacheConfig.java +++ b/src/main/java/com/faforever/api/config/CacheConfig.java @@ -16,6 +16,7 @@ import com.faforever.api.data.domain.MapVersion; import com.faforever.api.data.domain.Mod; import com.faforever.api.data.domain.ModVersion; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.caffeine.CaffeineCache; @@ -28,7 +29,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.web.servlet.HandlerMapping; -import jakarta.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.List; import java.util.concurrent.TimeUnit; @@ -40,7 +40,7 @@ @EnableCaching(proxyTargetClass = true) @Configuration -@Profile(ApplicationProfile.PRODUCTION) +@Profile({ApplicationProfile.PRODUCTION, ApplicationProfile.TRAINING}) public class CacheConfig { /** diff --git a/src/main/java/com/faforever/api/config/LocalizationConfig.java b/src/main/java/com/faforever/api/config/LocalizationConfig.java index 8d8747885..784a2b180 100644 --- a/src/main/java/com/faforever/api/config/LocalizationConfig.java +++ b/src/main/java/com/faforever/api/config/LocalizationConfig.java @@ -1,24 +1,15 @@ package com.faforever.api.config; import com.faforever.api.i18n.RepositoryMessageSource; -import org.springframework.context.HierarchicalMessageSource; -import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.MessageSourceAccessor; -import jakarta.inject.Inject; - @Configuration public class LocalizationConfig { @Bean - public MessageSourceAccessor messageSourceAccessor(MessageSource messageSource) { + public MessageSourceAccessor messageSourceAccessor(RepositoryMessageSource messageSource) { return new MessageSourceAccessor(messageSource); } - - @Inject - public void configureMessageSource(HierarchicalMessageSource messageSource, RepositoryMessageSource repositoryMessageSource) { - messageSource.setParentMessageSource(repositoryMessageSource); - } } diff --git a/src/main/java/com/faforever/api/config/elide/ElideConfig.java b/src/main/java/com/faforever/api/config/elide/ElideConfig.java index 87969b1d1..422115a9d 100644 --- a/src/main/java/com/faforever/api/config/elide/ElideConfig.java +++ b/src/main/java/com/faforever/api/config/elide/ElideConfig.java @@ -18,6 +18,7 @@ import com.yahoo.elide.jsonapi.JsonApiSettings; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.Converter; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,8 +36,8 @@ public class ElideConfig { @Bean MultiplexManager multiplexDataStore( - DataStore fafDataStore, - DataStore leagueDataStore + @Qualifier("fafDataStore") DataStore fafDataStore, + @Qualifier("leagueDataStore")DataStore leagueDataStore ) { return new MultiplexManager(fafDataStore, leagueDataStore); } diff --git a/src/main/java/com/faforever/api/db/SchemaVersionVerifier.java b/src/main/java/com/faforever/api/db/SchemaVersionVerifier.java index 514235372..dac349f1c 100644 --- a/src/main/java/com/faforever/api/db/SchemaVersionVerifier.java +++ b/src/main/java/com/faforever/api/db/SchemaVersionVerifier.java @@ -11,7 +11,7 @@ import java.util.Objects; @Component -@Profile("!" + ApplicationProfile.INTEGRATION_TEST) +@Profile(ApplicationProfile.PRODUCTION) public class SchemaVersionVerifier implements PriorityOrdered, InitializingBean { private final SchemaVersionRepository schemaVersionRepository; diff --git a/src/main/java/com/faforever/api/i18n/RepositoryMessageSource.java b/src/main/java/com/faforever/api/i18n/RepositoryMessageSource.java index c358dd6b1..a4f1ccc97 100644 --- a/src/main/java/com/faforever/api/i18n/RepositoryMessageSource.java +++ b/src/main/java/com/faforever/api/i18n/RepositoryMessageSource.java @@ -1,8 +1,10 @@ package com.faforever.api.i18n; +import com.faforever.api.config.ApplicationProfile; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.support.AbstractResourceBasedMessageSource; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import java.text.MessageFormat; @@ -10,6 +12,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; @Component @RequiredArgsConstructor @@ -18,6 +21,7 @@ public class RepositoryMessageSource extends AbstractResourceBasedMessageSource private static final Locale FALLBACK_LOCALE = Locale.US; private final MessageRepository messageRepository; + private final Environment environment; /** * Language -> Region -> Key -> Value. @@ -76,6 +80,6 @@ private String getText(String key, Locale locale) { @Override public void afterPropertiesSet() { - messagesByLanguage = loadMessages(); + messagesByLanguage = Set.of(environment.getActiveProfiles()).contains(ApplicationProfile.TRAINING) ? Map.of() : loadMessages(); } } diff --git a/src/main/resources/config/application-local.yml b/src/main/resources/config/application-local.yml index bb9fe52f2..5e8475105 100644 --- a/src/main/resources/config/application-local.yml +++ b/src/main/resources/config/application-local.yml @@ -71,7 +71,7 @@ spring: rabbitmq: host: ${RABBIT_HOST:127.0.0.1} port: ${RABBIT_PORT:5672} - username: ${RABBIT_USERNAME:faf-java-api} + username: ${RABBIT_USERNAME:faf-api} password: ${RABBIT_PASSWORD:banana} virtual-host: ${RABBIT_VHOST:/faf-core} jpa: @@ -80,8 +80,8 @@ spring: oauth2: resourceserver: jwt: - jwk-set-uri: https://hydra.faforever.com/.well-known/jwks.json - issuer-uri: https://hydra.faforever.com/ + jwk-set-uri: http://localhost:4444/.well-known/jwks.json + issuer-uri: http://ory-hydra:4444/ logging: level: - com.faforever.api: debug + com.faforever.api: debug \ No newline at end of file diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index 390db4cd7..11def3a3a 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -148,6 +148,8 @@ spring: resourceserver: jwt: issuer-uri: ${JWT_FAF_HYDRA_ISSUER:https://hydra.${FAF_DOMAIN}/} + aot: + enabled: true server: # Mind that this is configured in the docker compose file as well (that is, in the gradle script that generates it)