Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into avoid_lock
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Westberg committed Dec 2, 2019
2 parents 8ae453d + f54b027 commit 275dc4c
Show file tree
Hide file tree
Showing 165 changed files with 7,569 additions and 1,440 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Expand Up @@ -25,3 +25,4 @@ jobs:
- uses: actions/checkout@v1
- name: Build and test
run: gradlew.bat test --info --stacktrace
shell: cmd
42 changes: 39 additions & 3 deletions README.md
Expand Up @@ -39,14 +39,14 @@ external Git source code hosting providers are available:
## Building

[JDK 12](http://jdk.java.net/12/) or later and [Gradle](https://gradle.org/)
5.2.1 or later is required for building. To build the project on macOS or
GNU/Linux, just run the following command from the source tree root:
5.6.2 or later is required for building. To build the project on macOS or
GNU/Linux x64, just run the following command from the source tree root:

```bash
$ sh gradlew
```

To build the project on Windows, run the following command from the source tree root:
To build the project on Windows x64, run the following command from the source tree root:

```bat
> gradlew
Expand All @@ -55,6 +55,42 @@ To build the project on Windows, run the following command from the source tree
The extracted jlinked image will end up in the `build` directory in the source
tree root.

### Other operating systems and CPU architectures

If you want to build on an operating system other than GNU/Linux, macOS or
Windows _or_ if you want to build on a CPU architecture other than x64, then
ensure that you have JDK 12 or later installed locally. You can then run the
following command from the source tree root:

```bash
$ sh gradlew
```

The extracted jlinked image will end up in the `build` directory in the source
tree root.

### Offline builds

If you don't want the build to automatically download any dependencies, then
you must ensure that you have installed the following software locally:

- JDK 12 or later
- Gradle 5.6.2 or later

To create a build then run the command:

```bash
$ gradle offline
```

_Please note_ that the above command does _not_ make use of `gradlew` to avoid
downloading Gradle.

The extracted jlinked image will end up in the `build` directory in the source
tree root.

### Cross-linking

It is also supported to cross-jlink jimages to GNU/Linux, macOS and/or Windows from
any of the aforementioned operating systems. To build all applicable jimages
(including the server-side tooling), run the following command from the
Expand Down
1 change: 1 addition & 0 deletions bot/build.gradle
Expand Up @@ -30,6 +30,7 @@ module {
}

dependencies {
implementation project(':ci')
implementation project(':host')
implementation project(':network')
implementation project(':issuetracker')
Expand Down
1 change: 1 addition & 0 deletions bot/src/main/java/module-info.java
Expand Up @@ -21,6 +21,7 @@
* questions.
*/
module org.openjdk.skara.bot {
requires transitive org.openjdk.skara.ci;
requires transitive org.openjdk.skara.host;
requires transitive org.openjdk.skara.issuetracker;
requires transitive org.openjdk.skara.forge;
Expand Down
8 changes: 8 additions & 0 deletions bot/src/main/java/org/openjdk/skara/bot/BotConfiguration.java
Expand Up @@ -22,6 +22,7 @@
*/
package org.openjdk.skara.bot;

import org.openjdk.skara.ci.ContinuousIntegration;
import org.openjdk.skara.forge.HostedRepository;
import org.openjdk.skara.issuetracker.IssueProject;
import org.openjdk.skara.json.JSONObject;
Expand Down Expand Up @@ -49,6 +50,13 @@ public interface BotConfiguration {
*/
IssueProject issueProject(String name);

/**
* Configuration-specific name mapped to a ContinuousIntegration.
* @param name
* @return
*/
ContinuousIntegration continuousIntegration(String name);

/**
* Retrieves the ref name that optionally follows the configuration-specific repository name.
* If not configured, returns the name of the VCS default branch.
Expand Down
8 changes: 5 additions & 3 deletions bot/src/main/java/org/openjdk/skara/bot/BotRunner.java
Expand Up @@ -177,7 +177,6 @@ private void drain(Duration timeout) throws TimeoutException {
}
try {
Thread.sleep(1);
watchdog();
} catch (InterruptedException e) {
log.warning("Exception during queue drain");
log.throwing("BotRunner", "drain", e);
Expand Down Expand Up @@ -259,7 +258,10 @@ private void processRestRequest(JSONValue request) {
}

public void run() {
log.info("Starting BotRunner execution, will run forever.");
run(Duration.ofDays(10 * 365));
}

public void run(Duration timeout) {
log.info("Periodic task interval: " + config.scheduledExecutionPeriod());
log.info("Concurrency: " + config.concurrency());

Expand All @@ -280,7 +282,7 @@ public void run() {
config.scheduledExecutionPeriod().toMillis(), TimeUnit.MILLISECONDS);

try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
executor.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
Expand Down
77 changes: 58 additions & 19 deletions bot/src/main/java/org/openjdk/skara/bot/BotRunnerConfiguration.java
Expand Up @@ -22,26 +22,28 @@
*/
package org.openjdk.skara.bot;

import org.openjdk.skara.ci.ContinuousIntegration;
import org.openjdk.skara.forge.*;
import org.openjdk.skara.host.*;
import org.openjdk.skara.host.Credential;
import org.openjdk.skara.issuetracker.*;
import org.openjdk.skara.network.URIBuilder;
import org.openjdk.skara.json.JSONObject;
import org.openjdk.skara.network.URIBuilder;
import org.openjdk.skara.vcs.VCS;

import java.io.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.time.Duration;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Pattern;

public class BotRunnerConfiguration {
private final Logger log;
private final JSONObject config;
private final Map<String, Forge> repositoryHosts;
private final Map<String, IssueTracker> issueHosts;
private final Map<String, ContinuousIntegration> continuousIntegrations;
private final Map<String, HostedRepository> repositories;

private BotRunnerConfiguration(JSONObject config, Path cwd) throws ConfigurationError {
Expand All @@ -50,6 +52,7 @@ private BotRunnerConfiguration(JSONObject config, Path cwd) throws Configuration

repositoryHosts = parseRepositoryHosts(config, cwd);
issueHosts = parseIssueHosts(config, cwd);
continuousIntegrations = parseContinuousIntegrations(config, cwd);
repositories = parseRepositories(config);
}

Expand All @@ -64,8 +67,8 @@ private Map<String, Forge> parseRepositoryHosts(JSONObject config, Path cwd) thr
if (entry.value().contains("gitlab")) {
var gitlab = entry.value().get("gitlab");
var uri = URIBuilder.base(gitlab.get("url").asString()).build();
var pat = new PersonalAccessToken(gitlab.get("username").asString(), gitlab.get("pat").asString());
ret.put(entry.name(), ForgeFactory.createGitLabHost(uri, pat));
var pat = new Credential(gitlab.get("username").asString(), gitlab.get("pat").asString());
ret.put(entry.name(), Forge.from("gitlab", uri, pat, gitlab.asObject()));
} else if (entry.value().contains("github")) {
var github = entry.value().get("github");
URI uri;
Expand All @@ -74,21 +77,21 @@ private Map<String, Forge> parseRepositoryHosts(JSONObject config, Path cwd) thr
} else {
uri = URIBuilder.base("https://github.com/").build();
}
Pattern webUriPattern = null;
String webUriReplacement = null;
if (github.contains("weburl")) {
webUriPattern = Pattern.compile(github.get("weburl").get("pattern").asString());
webUriReplacement = github.get("weburl").get("replacement").asString();
}

if (github.contains("app")) {
var keyFile = cwd.resolve(github.get("app").get("key").asString());
ret.put(entry.name(), ForgeFactory.createGitHubHost(uri, webUriPattern, webUriReplacement, keyFile.toString(),
github.get("app").get("id").asString(),
github.get("app").get("installation").asString()));
try {
var keyContents = Files.readString(keyFile, StandardCharsets.UTF_8);
var pat = new Credential(github.get("app").get("id").asString() + ";" +
github.get("app").get("installation").asString(),
keyContents);
ret.put(entry.name(), Forge.from("github", uri, pat, github.asObject()));
} catch (IOException e) {
throw new ConfigurationError("Cannot find key file: " + keyFile);
}
} else {
var pat = new PersonalAccessToken(github.get("username").asString(), github.get("pat").asString());
ret.put(entry.name(), ForgeFactory.createGitHubHost(uri, pat));
var pat = new Credential(github.get("username").asString(), github.get("pat").asString());
ret.put(entry.name(), Forge.from("github", uri, pat, github.asObject()));
}
} else {
throw new ConfigurationError("Host " + entry.name());
Expand All @@ -109,7 +112,11 @@ private Map<String, IssueTracker> parseIssueHosts(JSONObject config, Path cwd) t
if (entry.value().contains("jira")) {
var jira = entry.value().get("jira");
var uri = URIBuilder.base(jira.get("url").asString()).build();
ret.put(entry.name(), IssueTrackerFactory.createJiraHost(uri, null));
Credential credential = null;
if (jira.contains("username")) {
credential = new Credential(jira.get("username").asString(), jira.get("password").asString());
}
ret.put(entry.name(), IssueTracker.from("jira", uri, credential, jira.asObject()));
} else {
throw new ConfigurationError("Host " + entry.name());
}
Expand All @@ -118,6 +125,26 @@ private Map<String, IssueTracker> parseIssueHosts(JSONObject config, Path cwd) t
return ret;
}

private Map<String, ContinuousIntegration> parseContinuousIntegrations(JSONObject config, Path cwd) throws ConfigurationError {
Map<String, ContinuousIntegration> ret = new HashMap<>();

if (!config.contains("ci")) {
return ret;
}

for (var entry : config.get("ci").fields()) {
var url = entry.value().get("url").asString();
var ci = ContinuousIntegration.from(URI.create(url), entry.value().asObject());
if (ci.isPresent()) {
ret.put(entry.name(), ci.get());
} else {
throw new ConfigurationError("No continuous integration named with url: " + url);
}
}

return ret;
}

private Map<String, HostedRepository> parseRepositories(JSONObject config) throws ConfigurationError {
Map<String, HostedRepository> ret = new HashMap<>();

Expand All @@ -131,7 +158,9 @@ private Map<String, HostedRepository> parseRepositories(JSONObject config) throw
throw new ConfigurationError("Repository " + entry.name() + " uses undefined host '" + hostName + "'");
}
var host = repositoryHosts.get(hostName);
var repo = host.repository(entry.value().get("repository").asString());
var repo = host.repository(entry.value().get("repository").asString()).orElseThrow(() ->
new ConfigurationError("Repository " + entry.value().get("repository").asString() + " is not available at " + hostName)
);
ret.put(entry.name(), repo);
}

Expand All @@ -158,7 +187,9 @@ private RepositoryEntry parseRepositoryEntry(String entry) throws ConfigurationE
throw new ConfigurationError("Repository entry " + entry + " uses undefined host '" + hostName + "'");
}
var repositoryName = entry.substring(hostSeparatorIndex + 1);
ret.repository = host.repository(repositoryName);
ret.repository = host.repository(repositoryName).orElseThrow(() ->
new ConfigurationError("Repository " + repositoryName + " is not available at " + hostName)
);
} else {
if (!repositories.containsKey(entry)) {
throw new ConfigurationError("Repository " + entry + " is not defined!");
Expand Down Expand Up @@ -233,6 +264,14 @@ public IssueProject issueProject(String name) {
}
}

@Override
public ContinuousIntegration continuousIntegration(String name) {
if (continuousIntegrations.containsKey(name)) {
return continuousIntegrations.get(name);
}
throw new RuntimeException("Couldn't find continuous integration with name: " + name);
}

@Override
public String repositoryRef(String name) {
try {
Expand Down
7 changes: 3 additions & 4 deletions bot/src/test/java/org/openjdk/skara/bot/BotRunnerTests.java
Expand Up @@ -276,12 +276,11 @@ void dontDiscardDifferentBlockedItems() throws TimeoutException {
}

@Test
@DisabledOnOs(OS.WINDOWS)
void watchdogTrigger() throws TimeoutException {
var countdownLatch = new CountDownLatch(1);
var item = new TestBlockedWorkItem(countdownLatch);
var bot = new TestBot(item);
var runner = new BotRunner(config("{ \"runner\": { \"watchdog\": \"PT0.01S\" } }"), List.of(bot));
var runner = new BotRunner(config("{ \"runner\": { \"watchdog\": \"PT0.01S\", \"interval\": \"PT0.001S\" } }"), List.of(bot));

var errors = new ArrayList<String>();
var log = Logger.getLogger("org.openjdk.skara.bot");
Expand All @@ -302,9 +301,9 @@ public void close() throws SecurityException {
}
});

assertThrows(TimeoutException.class, () -> runner.runOnce(Duration.ofMillis(100)));
runner.run(Duration.ofMillis(100));
assertTrue(errors.size() > 0);
assertTrue(errors.size() <= 10);
assertTrue(errors.size() <= 100);
countdownLatch.countDown();
}
}
45 changes: 45 additions & 0 deletions bots/bridgekeeper/build.gradle
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

module {
name = 'org.openjdk.skara.bots.bridgekeeper'
test {
requires 'org.junit.jupiter.api'
requires 'org.openjdk.skara.vcs'
requires 'org.openjdk.skara.test'
opens 'org.openjdk.skara.bots.bridgekeeper' to 'org.junit.platform.commons'
}
}

dependencies {
implementation project(':ci')
implementation project(':host')
implementation project(':forge')
implementation project(':issuetracker')
implementation project(':bot')
implementation project(':census')
implementation project(':json')
implementation project(':vcs')

testImplementation project(':test')
}
30 changes: 30 additions & 0 deletions bots/bridgekeeper/src/main/java/module-info.java
@@ -0,0 +1,30 @@
import org.openjdk.skara.bots.bridgekeeper.BridgekeeperBotFactory;

/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module org.openjdk.skara.bots.bridgekeeper {
requires org.openjdk.skara.bot;
requires java.logging;

provides org.openjdk.skara.bot.BotFactory with BridgekeeperBotFactory;
}

0 comments on commit 275dc4c

Please sign in to comment.