Unverified Commit ccbb5062 authored by Johan's avatar Johan
Browse files

SGP-1: Test dockerized dind build.

parent 35206a72
image: docker:dind
stages:
- build
- test
- qa
- artifact
build:
stage: build
script: "mvn -B compile test-compile"
quicktests:
stage: test
script: "mvn -B test --fail-at-end"
artifacts:
expire_in: 1 week
paths:
- "**/target/jacoco.exec"
integration-SQ-LTS-GitLab-8-14:
image: maven-3.3.3
tags: [ "docker" ]
stage: test
script: "mvn -B verify"
[submodule "it-sources"]
path = it-sources
url = gitlab@git.johnnei.org:Johnnei/sonar-gitlab-plugin-it-sources.git
Subproject commit 5aa1219c40a736f4ab91b5c19cd3d7fa4746cf60
......@@ -16,10 +16,11 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Deployment -->
<sonar.pluginName>GitLab Integration</sonar.pluginName>
<sonar.pluginClass>org.johnnei.sonar.GitLabPlugin</sonar.pluginClass>
<sonar.pluginClass>org.johnnei.sgp.sonar.GitLabPlugin</sonar.pluginClass>
<!-- Dependency Versions -->
<dependency.sonar-plugin-api.version>5.6</dependency.sonar-plugin-api.version>
......@@ -60,14 +61,120 @@
<url>https://jira.johnnei.org/projects/SGP/issues/</url>
</issueManagement>
<profiles>
<profile>
<id>it-environment-windows</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<properties>
<os.command>/C</os.command>
<os.shell>cmd</os.shell>
</properties>
</profile>
</profiles>
<build>
<plugins>
<!-- Plugin to build SonarQube plugin artifact -->
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
<version>1.17</version>
<extensions>true</extensions>
</plugin>
<!-- Add Docker Container Ports to environment -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<systemProperties>
<sonarqube.host>http://${docker.containers.sonarqube.ports.9000/tcp.host}:${docker.containers.sonarqube.ports.9000/tcp.port}
</sonarqube.host>
<gitlab.host>http://${docker.containers.gitlab.ports.80/tcp.host}:${docker.containers.gitlab.ports.80/tcp.port}</gitlab.host>
<os.shell>${os.shell}</os.shell>
<os.command>${os.command}</os.command>
</systemProperties>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Plugin to run Docker Container based ITs -->
<plugin>
<groupId>net.wouterdanes.docker</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>5.0.0</version>
<executions>
<execution>
<id>package</id>
<goals>
<goal>build-images</goal>
</goals>
<configuration>
<images>
<image>
<id>gitlab-plugin</id>
<dockerFile>${project.basedir}/src/test/resources/docker/Dockerfile</dockerFile>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
</artifact>
</artifacts>
</image>
</images>
</configuration>
</execution>
<execution>
<id>start</id>
<goals>
<goal>start-containers</goal>
</goals>
<configuration>
<!-- You can set forceCleanup to true to stop and remove started containers
at the end of the build even if the stop-containers goal is not executed
(useful for preventing Ctrl+C causing dangling containers) -->
<forceCleanup>false</forceCleanup>
<containers>
<container>
<id>sonarqube</id>
<image>gitlab-plugin</image>
<waitForStartup>Process\[web\] is up</waitForStartup>
</container>
<container>
<id>gitlab</id>
<image>gitlab/gitlab-ce</image>
<waitForStartup>master process ready</waitForStartup>
</container>
</containers>
</configuration>
</execution>
<execution>
<id>stop</id>
<goals>
<goal>stop-containers</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
......@@ -99,12 +206,48 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Improved Assertions -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
</dependency>
<!-- Mocking -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<!-- Interaction with GitLab / SonarQube -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
<!-- Logging during Unit Tests -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.6.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package org.johnnei.internal.gitlab;
package org.johnnei.sgp.internal.gitlab;
import javax.annotation.Nonnull;
import java.io.IOException;
......@@ -9,7 +9,7 @@ import org.sonar.api.batch.postjob.issue.PostJobIssue;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.johnnei.internal.sonar.SonarReport;
import org.johnnei.sgp.internal.sonar.SonarReport;
/**
* Created by Johnnei on 2016-11-12.
......
package org.johnnei.internal.gitlab;
package org.johnnei.sgp.internal.gitlab;
/**
* Created by Johnnei on 2016-12-03.
......
package org.johnnei.internal.sonar;
package org.johnnei.sgp.internal.sonar;
import java.io.IOException;
......
package org.johnnei.internal.sonar;
package org.johnnei.sgp.internal.sonar;
import javax.annotation.Nonnull;
import java.util.Collection;
......@@ -13,8 +13,8 @@ import org.sonar.api.batch.postjob.issue.PostJobIssue;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.johnnei.internal.gitlab.CommitCommenter;
import org.johnnei.sonar.GitLabPlugin;
import org.johnnei.sgp.internal.gitlab.CommitCommenter;
import org.johnnei.sgp.sonar.GitLabPlugin;
/**
* Created by Johnnei on 2016-11-12.
......
package org.johnnei.internal.sonar;
package org.johnnei.sgp.internal.sonar;
import javax.annotation.CheckForNull;
......@@ -11,7 +11,7 @@ import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.config.Settings;
import org.johnnei.sonar.GitLabPlugin;
import org.johnnei.sgp.sonar.GitLabPlugin;
/**
* Class to create a domain orientated facade of the SonarQube settings.
......@@ -56,7 +56,10 @@ public class GitLabPluginConfiguration {
project = gitlabApi.getAllProjects().stream()
.filter(p -> projectName.equals(p.getNameWithNamespace()))
.findAny()
.orElseThrow(() -> new IllegalArgumentException("Failed to find project '%s'. Is the user authorized to access the project?"));
.orElseThrow(() -> new IllegalArgumentException(String.format(
"Failed to find project '%s'. Is the user authorized to access the project?",
projectName
)));
}
public void setBaseDir(File baseDir) {
......
package org.johnnei.internal.sonar;
package org.johnnei.sgp.internal.sonar;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
......
package org.johnnei.sonar;
package org.johnnei.sgp.sonar;
import org.sonar.api.Plugin;
import org.sonar.api.Properties;
import org.sonar.api.Property;
import org.johnnei.internal.sonar.CommitAnalysisBuilder;
import org.johnnei.internal.sonar.CommitIssueJob;
import org.johnnei.internal.sonar.GitLabPluginConfiguration;
import org.johnnei.sgp.internal.sonar.CommitAnalysisBuilder;
import org.johnnei.sgp.internal.sonar.CommitIssueJob;
import org.johnnei.sgp.internal.sonar.GitLabPluginConfiguration;
/**
* Class which configures the GitLab plugin within the SonarQube instance.
......
package org.johnnei.sgp;
import java.io.IOException;
import org.junit.Test;
import org.johnnei.sgp.it.IntegrationTest;
/**
* Created by Johnnei on 2016-12-04.
*/
public class CommentOnCommitIT extends IntegrationTest {
@Test
public void testCommentsAreCreated() throws IOException {
sonarAnalysis("5aa1219c40a736f4ab91b5c19cd3d7fa4746cf60");
}
}
package org.johnnei.sgp.it;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.gitlab.api.GitlabAPI;
import org.gitlab.api.models.GitlabProject;
import org.gitlab.api.models.GitlabSession;
import org.hamcrest.collection.IsEmptyCollection;
import org.junit.After;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeThat;
/**
* Created by Johnnei on 2016-12-04.
*/
public abstract class IntegrationTest {
private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationTest.class);
private static final String ADMIN_PASSWORD = "Test1234@!";
private static final Pattern INPUT_FIELD = Pattern.compile("<input(.*?)>");
private static final Pattern NAME_ATTRIBUTE = Pattern.compile("name=\"(.*?)\"");
private static final Pattern VALUE_ATTRIBUTE = Pattern.compile("value=\"(.*?)\"");
private static final String GITLAB_HOST = getProperty("gitlab.host", "http://localhost:80");
private static final String SONARQUBE_HOST = getProperty("sonarqube.host", "http://localhost:9000");
private static final String OS_SHELL = getProperty("os.shell", "/bin/bash");
private static final String OS_COMMAND = getProperty("os.command", "-c");
protected GitlabAPI gitlabApi;
protected GitlabProject project;
private String gitLabAuthToken;
private static String getProperty(String key, String defaultValue) {
String value = System.getProperty(key);
if (value == null || value.contains("$")) {
value = defaultValue;
}
return value;
}
@Before
public void setUp() throws Exception {
LOGGER.debug("GitLab Host: {}", GITLAB_HOST);
LOGGER.debug("SonarQube Host: {}", SONARQUBE_HOST);
ensureAdminCreated();
createProject();
}
@After
public void tearDown() throws Exception {
deleteProject();
}
protected void checkout(String ref) throws IOException {
LOGGER.info("Checking out {}");
Process process = new ProcessBuilder()
.directory(new File("it-sources"))
.command("git", "checkout", ref)
.start();
try {
process.waitFor();
} catch (InterruptedException e) {
process.destroy();
}
}
protected void sonarAnalysis(String commitHash) throws IOException {
LOGGER.info("Starting SonarQube Analysis.");
String argument = OS_COMMAND + " \"" +
"mvn" +
" clean" +
" compile " +
" sonar:sonar" +
" -Dsonar.analysis.mode=issues" +
" -Dsonar.host.url=" + SONARQUBE_HOST +
" -Dsonar.gitlab.uri=" + GITLAB_HOST +
" -Dsonar.gitlab.auth.token=" + gitLabAuthToken +
" -Dsonar.gitlab.analyse.project=root/sgp-it" +
" -Dsonar.gitlab.analyse.commit=" + commitHash +
"\"";
LOGGER.debug("Running: " + OS_SHELL + " " + argument);
Process process = new ProcessBuilder()
.directory(new File("it-sources"))
.command(
OS_SHELL,
argument
)
.inheritIO()
.start();
try {
int returnCode = process.waitFor();
if (returnCode != 0) {
throw new RuntimeException("Process failed: " + returnCode);
}
} catch (InterruptedException e) {
process.destroy();
}
}
private void ensureAdminCreated() throws Exception {
LOGGER.info("Verifying that GitLab Admin account exists.");
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private List<Cookie> cookies = Collections.emptyList();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
this.cookies = cookies;
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
return cookies;
}
})
.build();
Request homeRequest = new Request.Builder()
.url(GITLAB_HOST)
.build();
Response response = client.newCall(homeRequest).execute();
if (isRedirectedToResetPassword(response)) {
Request postRequest = createRegisterAdminRequest(response);
LOGGER.info("Registering admin account: {}", postRequest.body());
Response createResponse = client.newCall(postRequest).execute();
if (!createResponse.isSuccessful()) {
throw new IllegalStateException(String.format("Submit of reset password failed: %s", createResponse.message()));
}
}
GitlabSession session = GitlabAPI.connect(GITLAB_HOST, "root", ADMIN_PASSWORD);
gitLabAuthToken = session.getPrivateToken();
gitlabApi = GitlabAPI.connect(GITLAB_HOST, gitLabAuthToken);
LOGGER.info("GitLab API Initialized.");
}
private static Request createRegisterAdminRequest(Response response) throws IOException {
String body = response.body().string();
FormBody.Builder formBodyBuilder = new FormBody.Builder()
.add("user[password]", ADMIN_PASSWORD)
.add("user[password_confirmation]", ADMIN_PASSWORD);
Matcher inputFields = INPUT_FIELD.matcher(body);
while (inputFields.find()) {
String inputField = inputFields.group();
Matcher nameMatcher = NAME_ATTRIBUTE.matcher(inputField);
Matcher valueMatcher = VALUE_ATTRIBUTE.matcher(inputField);
if (!nameMatcher.find()) {
throw new IllegalStateException("Failed to extract name attribute from: " + inputField);
}
if (valueMatcher.find() && !"commit".equalsIgnoreCase(nameMatcher.group(1))) {
LOGGER.debug("Adding {} = {} to form body.", nameMatcher.group(1), valueMatcher.group(1));
formBodyBuilder.add(nameMatcher.group(1), valueMatcher.group(1));
} else {
LOGGER.debug("Ignoring valueless input: {}", nameMatcher.group(1));
}
}
return new Request.Builder()
.url(GITLAB_HOST + "/users/password")
.post(formBodyBuilder.build())
.build();
}
private static boolean isRedirectedToResetPassword(Response response) {
if (response.priorResponse() == null) {
return false;
}
if (!response.priorResponse().isRedirect()) {
return false;
}
return response.priorResponse().header("location").contains("/users/password/edit");
}
private void createProject() throws IOException {
LOGGER.info("Ensuring that there is no left over project.");
List<GitlabProject> projects = gitlabApi.getAllProjects();
assumeThat(projects, IsEmptyCollection.empty());
LOGGER.info("Creating Project");
project = gitlabApi.createProject("sgp-it");
assertNotNull("Failed to create project in GitLab", project);
}
private void deleteProject() throws IOException {
LOGGER.debug("Removing project from GitLab.");
if (project != null) {
gitlabApi.deleteProject(project.getId());
}
LOGGER.debug("Removing project from SonarQube.");
}
}
FROM sonarqube:lts
MAINTAINER Johnnei
COPY sonar-gitlab-plugin-*\.jar" /opt/sonarqube/extensions/plugins/sonar-gitlab-plugin.jar
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss,SSS} %-5level %c{1.} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" level="debug"/>
</Root>
</Loggers>
</Configuration>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment