Skip to content

Commit

Permalink
Merge pull request #386 from cqse/installer_windows
Browse files Browse the repository at this point in the history
Installer windows
  • Loading branch information
DreierF committed Mar 28, 2024
2 parents 22c9121 + 9c98428 commit c944a28
Show file tree
Hide file tree
Showing 45 changed files with 1,466 additions and 657 deletions.
37 changes: 29 additions & 8 deletions .github/workflows/actions.yml
Expand Up @@ -9,17 +9,14 @@ on:

jobs:
build:
name: Build & Deploy
name: Build on Linux & Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
- uses: actions/setup-java@v4
with:
java-version: '17.0.8'
distribution: 'graalvm-community'
github-token: ${{ secrets.GITHUB_TOKEN }}
set-java-home: true
distribution: 'temurin'
java-version: '17'
- name: Build with Gradle
run: ./gradlew build
- name: Upload Release Assets
Expand Down Expand Up @@ -71,7 +68,31 @@ jobs:
accesskey: ${{ secrets.CQSE_TEAMSCALE_IO_ACCESSKEY }}
partition: 'Coverage'
format: 'JACOCO'
message: 'Coverage'
message: 'Linux Coverage'
files: '**/jacocoTestReport.xml'

test-windows:
name: Test on Windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Build with Gradle
run: ./gradlew build
- name: Upload coverage to Teamscale
if: always() && github.event_name == 'push'
uses: cqse/teamscale-upload-action@v2.8.2
with:
server: 'https://cqse.teamscale.io'
project: 'teamscale-jacoco-agent'
user: ${{ secrets.CQSE_TEAMSCALE_IO_USER }}
accesskey: ${{ secrets.CQSE_TEAMSCALE_IO_ACCESSKEY }}
partition: 'Coverage Windows'
format: 'JACOCO'
message: 'Coverage Windows'
files: '**/jacocoTestReport.xml'

docker:
Expand Down
5 changes: 5 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@ We use [semantic versioning](http://semver.org/):
- PATCH version when you make backwards compatible bug fixes.

# Next Release
- [feature] add installer for Windows
- [feature] Docker: agent copies itself to `/transfer` if this is mounted into the container
- [fix] Disable warning about proxy port not being correct when no proxy port was set at all
- [fix] _agent_: `GET /commit` and `GET /revision` endpoints did return 500 error
Expand Down
4 changes: 2 additions & 2 deletions agent/build.gradle.kts
Expand Up @@ -84,8 +84,8 @@ distributions {
named("shadow") {
distributionBaseName.set("teamscale-jacoco-agent")
contents {
from(project(":installer").tasks["nativeCompile"]) {
include("installer")
from(project(":installer").tasks["jlink"]) {
into("installer")
}

from(tasks.readmeToPdf) {
Expand Down
9 changes: 9 additions & 0 deletions agent/src/dist/installer.bat
@@ -0,0 +1,9 @@
@echo off
set DIR="%~dp0"
set BAT_EXEC="%DIR:"=%\installer\installer-windows-x86_64\bin\installer.bat"

rem ensure that we don't accidentally profile the uninstaller
set JAVA_TOOL_OPTIONS=
set _JAVA_OPTIONS=

pushd %DIR% & %BAT_EXEC% %* & popd
8 changes: 8 additions & 0 deletions agent/src/dist/installer.sh
@@ -0,0 +1,8 @@
#!/bin/sh
DIR="${0%/*}"

# ensure that we don't accidentally profile the uninstaller
unset JAVA_TOOL_OPTIONS
unset _JAVA_OPTIONS

exec "$DIR/installer/installer-linux-x86_64/bin/installer" "$@"
4 changes: 3 additions & 1 deletion agent/src/docker/Dockerfile
@@ -1,6 +1,8 @@
# --- build image ---

FROM openjdk:8 as build
FROM openjdk:17 as build
# install xargs which is needed during the build
RUN microdnf install findutils
ADD . /src
WORKDIR /src
RUN ./gradlew :agent:shadowJar
Expand Down
Expand Up @@ -3,6 +3,8 @@
import okhttp3.HttpUrl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.TempDir;

import java.io.IOException;
Expand Down Expand Up @@ -45,36 +47,44 @@ void successfulParsing() throws AgentOptionParseException, IOException {
void missingUsername() throws IOException {
Files.write(teamscalePropertiesPath, "url=http://test\naccesskey=key".getBytes(StandardCharsets.UTF_8));
assertThatThrownBy(
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining("missing the username");
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining(
"missing the username");
}

@Test
void missingAccessKey() throws IOException {
Files.write(teamscalePropertiesPath, "url=http://test\nusername=user".getBytes(StandardCharsets.UTF_8));
assertThatThrownBy(
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining("missing the accesskey");
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining(
"missing the accesskey");
}

@Test
void missingUrl() throws IOException {
Files.write(teamscalePropertiesPath, "username=user\nusername=user".getBytes(StandardCharsets.UTF_8));
assertThatThrownBy(
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining("missing the url");
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining(
"missing the url");
}

@Test
void malformedUrl() throws IOException {
Files.write(teamscalePropertiesPath, "url=$$**\nusername=user\nusername=user".getBytes(StandardCharsets.UTF_8));
assertThatThrownBy(
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining("malformed URL");
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining(
"malformed URL");
}

/** This test doesn't work on Windows since {@link java.io.File#setReadable(boolean)} does not work there. */
@DisabledOnOs(OS.WINDOWS)
@Test
void fileNotReadable() throws IOException {
Files.write(teamscalePropertiesPath, "url=http://test\nusername=user\nusername=user".getBytes(StandardCharsets.UTF_8));
Files.write(teamscalePropertiesPath,
"url=http://test\nusername=user\nusername=user".getBytes(StandardCharsets.UTF_8));
assertThat(teamscalePropertiesPath.toFile().setReadable(false)).isTrue();
assertThatThrownBy(
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining("Failed to read");
() -> TeamscalePropertiesUtils.parseCredentials(teamscalePropertiesPath)).hasMessageContaining(
"Failed to read");
}

}
Expand Up @@ -3,6 +3,9 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Test Utilities
Expand All @@ -11,12 +14,15 @@ public class TestUtils {
/**
* Deletes all contents inside the coverage folder inside the agent directory
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static void cleanAgentCoverageDirectory() throws IOException {
Path coverageDir = AgentUtils.getAgentDirectory().resolve("coverage");
if (Files.exists(coverageDir)) {
Files.list(coverageDir).forEach(path -> path.toFile().delete());
try (Stream<Path> stream = Files.list(coverageDir)) {
stream.forEach(path ->
assertThat(path.toFile().delete()).withFailMessage("Failed to delete " + path).isTrue());
}
Files.delete(coverageDir);
}
}

}
@@ -1,8 +1,9 @@
package com.teamscale.test.commons;

import com.teamscale.report.testwise.model.TestInfo;
import org.apache.commons.lang3.SystemUtils;
import org.conqat.lib.commons.io.ProcessUtils;
import org.conqat.lib.commons.system.SystemUtils;
import org.jetbrains.annotations.NotNull;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.http.POST;
Expand All @@ -12,6 +13,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -50,20 +54,20 @@ public static String getCoverageString(TestInfo info) {
* @throws IOException if running Maven fails.
*/
public static void runMavenTests(String mavenProjectPath) throws IOException {
File workingDirectory = new File(mavenProjectPath);
runMaven(mavenProjectPath, "clean", "verify");
}

/**
* Runs Maven in the given Maven project path with the given arguments.
*
* @throws IOException if running Maven fails.
*/
public static void runMaven(String mavenProjectPath, String... mavenArguments) throws IOException {
ProcessUtils.ExecutionResult result;
try {
String executable = "./mvnw";
if (SystemUtils.isWindows()) {
executable = Paths.get(mavenProjectPath, "mvnw.cmd").toUri().getPath();
}
result = ProcessUtils.execute(
new ProcessBuilder(executable, "clean", "verify").directory(workingDirectory));
result = ProcessUtils.execute(buildMavenProcess(mavenProjectPath, mavenArguments));
} catch (IOException e) {
throw new IOException(
"Failed to run ./mvnw clean verify in directory " + workingDirectory.getAbsolutePath(),
e);
throw new IOException("Failed to run ./mvnw clean verify in directory " + mavenProjectPath, e);
}

// in case the process succeeded, we still log stdout and stderr in case later assertions fail. This helps
Expand All @@ -76,6 +80,25 @@ public static void runMavenTests(String mavenProjectPath) throws IOException {
}
}

/**
* Creates the command-line arguments that can be passed to {@link ProcessBuilder} to invoke Maven with the given
* arguments.
*/
@NotNull
public static ProcessBuilder buildMavenProcess(String mavenProjectDirectory, String... mavenArguments) {
List<String> arguments = new ArrayList<>();
if (SystemUtils.IS_OS_WINDOWS) {
Collections.addAll(arguments, "cmd", "/c", "mvnw.cmd");
} else {
arguments.add("./mvnw");
}

arguments.addAll(Arrays.asList(mavenArguments));


return new ProcessBuilder(arguments).directory(new File(mavenProjectDirectory));
}

/** Retrieve all files in the `tia/reports` folder sorted by name. */
public static List<Path> getReportFileNames(String mavenProjectPath) throws IOException {
try (Stream<Path> stream = Files.walk(Paths.get(mavenProjectPath, "target", "tia", "reports"))) {
Expand Down
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Expand Up @@ -50,12 +50,15 @@ spark = { module = "com.sparkjava:spark-core", version = "2.9.4" }
jcommander = { module = "com.beust:jcommander", version = "1.82" }
teamscaleLibCommons = { module = "com.teamscale:teamscale-lib-commons", version = "9.4.1" }
commonsCodec = { module = "commons-codec:commons-codec", version = "1.16.1" }
commonsLang = { module = "org.apache.commons:commons-lang3", version = "3.14.0" }
commonsIo = { module = "commons-io:commons-io", version = "2.15.1" }
slf4j-api = { module = "org.slf4j:slf4j-api", version = "2.0.12" }
jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version = "6.9.0.202403050737-r" }
okio = { module = "com.squareup.okio:okio", version = "3.9.0" }

picocli-core = { module = "info.picocli:picocli", version.ref = "picocli" }
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
jna-platform = { module = "net.java.dev.jna:jna-platform", version = "5.14.0" }

junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
Expand Down

0 comments on commit c944a28

Please sign in to comment.