diff --git a/scm-test/src/main/java/sonia/scm/TempSCMContextProvider.java b/scm-test/src/main/java/sonia/scm/TempSCMContextProvider.java
new file mode 100644
index 0000000000..3c38bf6faf
--- /dev/null
+++ b/scm-test/src/main/java/sonia/scm/TempSCMContextProvider.java
@@ -0,0 +1,109 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import java.io.File;
+import java.nio.file.Path;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class TempSCMContextProvider implements SCMContextProvider
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public File getBaseDirectory()
+ {
+ return baseDirectory;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Stage getStage()
+ {
+ return Stage.DEVELOPMENT;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Throwable getStartupError()
+ {
+ return null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String getVersion()
+ {
+ return "900.0.1-SNAPSHOT";
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param baseDirectory
+ */
+ public void setBaseDirectory(File baseDirectory)
+ {
+ this.baseDirectory = baseDirectory;
+ }
+
+ @Override
+ public Path resolve(Path path) {
+ return baseDirectory.toPath().resolve(path);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private File baseDirectory;
+}
diff --git a/scm-test/src/main/resources/META-INF/services/sonia.scm.SCMContextProvider b/scm-test/src/main/resources/META-INF/services/sonia.scm.SCMContextProvider
new file mode 100644
index 0000000000..35e76607cf
--- /dev/null
+++ b/scm-test/src/main/resources/META-INF/services/sonia.scm.SCMContextProvider
@@ -0,0 +1 @@
+sonia.scm.TempSCMContextProvider
diff --git a/scm-ui/build.gradle b/scm-ui/build.gradle
new file mode 100644
index 0000000000..b2c5b8ad54
--- /dev/null
+++ b/scm-ui/build.gradle
@@ -0,0 +1,66 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+plugins {
+ id 'com.github.node-gradle.node' version '2.2.4'
+}
+
+node {
+ download = true
+ version = '14.15.1'
+ yarnVersion = '1.22.5'
+ nodeModulesDir = file("${project.rootProject.projectDir}")
+}
+
+// TODO define inputs and outputs
+
+task typecheck(type: YarnTask) {
+ args = ['run', 'typecheck']
+ dependsOn('yarn_install')
+}
+
+task test(type: YarnTask) {
+ args = ['run', 'test']
+ dependsOn('yarn_install')
+}
+
+
+task check(type: YarnTask) {
+ dependsOn('typecheck', 'test')
+}
+
+task build(type: YarnTask) {
+ args = ['run', 'build']
+ dependsOn('yarn_install')
+}
+
+task deploy(type: YarnTask) {
+ args = ['run', 'deploy', project.version]
+ dependsOn('yarn_install')
+}
+
+task setVersion(type: YarnTask) {
+ args = ['run', 'set-version', project.version]
+ dependsOn('yarn_install')
+}
diff --git a/scm-webapp/build.gradle b/scm-webapp/build.gradle
new file mode 100644
index 0000000000..4999fdc33a
--- /dev/null
+++ b/scm-webapp/build.gradle
@@ -0,0 +1,206 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+plugins {
+ id 'war'
+ id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.1.6'
+}
+
+dependencies {
+ implementation platform(project(':'))
+
+ implementation project(':scm-core')
+ implementation project(':scm-dao-xml')
+ testImplementation project(':scm-test')
+ annotationProcessor project(':scm-annotation-processor')
+
+ // servlet api TODO version
+ providedCompile 'javax.servlet:javax.servlet-api:3.0.1'
+ testImplementation 'javax.servlet:javax.servlet-api'
+
+ // security
+ implementation 'org.apache.shiro:shiro-web:1.7.0' // TODO
+ implementation 'org.apache.shiro:shiro-guice:1.7.0' // TODO
+
+ // jwt
+ implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
+ implementation 'io.jsonwebtoken:jjwt-impl:0.11.2'
+ implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2'
+
+ // gpg
+ implementation 'org.bouncycastle:bcpg-jdk15on:1.67'
+ implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
+ implementation 'org.bouncycastle:bcpkix-jdk15on:1.67'
+
+ // json TODO versions
+ implementation 'com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.11.3'
+ implementation 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.11.3'
+ implementation 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.11.3'
+ implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.3'
+ implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.3'
+
+ // rest api TODO versions
+ implementation 'org.jboss.resteasy:resteasy-jaxb-provider:4.5.8.Final'
+ implementation 'org.jboss.resteasy:resteasy-jackson2-provider:4.5.8.Final'
+ implementation 'org.jboss.resteasy:resteasy-multipart-provider:4.5.8.Final'
+ implementation 'org.jboss.resteasy:resteasy-guice:4.5.8.Final'
+ implementation 'org.jboss.resteasy:resteasy-servlet-initializer:4.5.8.Final'
+ implementation 'org.jboss.resteasy:resteasy-validator-provider:4.5.8.Final'
+
+ // openapi
+ compileOnly 'io.swagger.core.v3:swagger-jaxrs2:2.1.6'
+
+ // validation
+ implementation 'org.hibernate.validator:hibernate-validator:6.1.6.Final'
+ implementation 'javax.el:javax.el-api:3.0.0'
+ implementation 'org.glassfish:javax.el:3.0.1-b11'
+
+ // logging
+ implementation 'ch.qos.logback:logback-classic'
+ // api 'org.slf4j:jcl-over-slf4j' from core, but why?
+ implementation 'org.slf4j:log4j-over-slf4j:1.7.30'
+
+ // utils
+ implementation 'com.google.guava:guava'
+
+ // cron expression
+ implementation 'com.cronutils:cron-utils:9.1.3'
+
+ // templates
+ implementation 'com.github.spullara.mustache.java:compiler:0.9.7'
+
+ // static resources
+ implementation 'com.github.sdorra:web-resources:1.1.1'
+
+ // content type detection
+ implementation 'com.github.sdorra:spotter-core:3.0.1'
+ implementation 'org.apache.tika:tika-core:1.25'
+
+ // restart on unix
+ implementation 'org.kohsuke:akuma:1.10'
+
+ // native access
+ implementation 'net.java.dev.jna:jna:5.6.0'
+
+ // lombok
+ compileOnly 'org.projectlombok:lombok'
+ testCompileOnly 'org.projectlombok:lombok'
+ // TODO version from parent
+ annotationProcessor 'org.projectlombok:lombok:1.18.10'
+ testAnnotationProcessor 'org.projectlombok:lombok:1.18.10'
+
+ // dto mapping
+ annotationProcessor 'org.mapstruct:mapstruct-processor'
+
+ // selenium TODO do we need this?
+ // testImplementation 'org.seleniumhq.selenium:selenium-java:2.53.1'
+ // testImplementation 'org.seleniumhq.selenium:selenium-firefox-driver:2.53.1'
+ // testImplementation 'org.seleniumhq.selenium:htmlunit-driver:2.21'
+
+ // rest api client TODO do we need this?
+ testImplementation 'com.sun.jersey:jersey-client:1.19.4'
+ testImplementation 'com.sun.jersey.contribs:jersey-apache-client:1.19.4'
+
+ // async
+ testImplementation 'org.awaitility:awaitility:4.0.2'
+
+ // shiro unit
+ testImplementation 'com.github.sdorra:shiro-unit:1.0.1'
+}
+
+/**
+WTF???
+
+
+
+
+ javax.transaction
+ jta
+ 1.1
+ provided
+
+
+
+
+
+ xml-apis
+ xml-apis
+ 1.4.01
+
+
+
+
+
+ sonia.scm.plugins
+ scm-git-plugin
+ 2.13.0-SNAPSHOT
+ tests
+ test
+
+
+
+ sonia.scm.plugins
+ scm-git-plugin
+ 2.13.0-SNAPSHOT
+ test
+
+
+
+ sonia.scm.plugins
+ scm-hg-plugin
+ 2.13.0-SNAPSHOT
+ tests
+ test
+
+
+
+ sonia.scm.plugins
+ scm-hg-plugin
+ 2.13.0-SNAPSHOT
+ test
+
+
+
+ sonia.scm.plugins
+ scm-svn-plugin
+ 2.13.0-SNAPSHOT
+ tests
+ test
+
+
+
+ sonia.scm.plugins
+ scm-svn-plugin
+ 2.13.0-SNAPSHOT
+ test
+
+
+**/
+test {
+ useJUnitPlatform()
+ // TODO integration tests
+ exclude '**/*ITCase.class'
+}
diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
index 6cad96b2e6..d747a454be 100644
--- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java
@@ -90,6 +90,9 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
+import sonia.scm.TempSCMContextProvider;
+
//~--- JDK imports ------------------------------------------------------------
/**
diff --git a/settings.gradle b/settings.gradle
index 7a14f8f648..2ed6354bb3 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -31,3 +31,4 @@ include('scm-test')
// include('scm-ui')
// include('scm-plugins')
include('scm-dao-xml')
+include('scm-webapp')