Compare commits

..

No commits in common. "main" and "v12.0.7" have entirely different histories.

1927 changed files with 21416 additions and 30833 deletions

3
.gitignore vendored
View File

@ -1,7 +1,6 @@
server-product/docker/build/
server-product/docker/onedev-*/
target/
bin/
**/target/
**/.classpath
**/.gitignore
**/.settings

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "server-ee"]
path = server-ee
url = https://code.onedev.io/onedev/server-ee.git
url = https://code.onedev.io/onedev/server-ee

View File

@ -1,2 +1,2 @@
CVE-2024-53299
CVE-2024-57699
CVE-2024-57699

View File

@ -1,7 +0,0 @@
# Conventions
## Service Methods
1. Various service methods will not check permissions, except for those with subject param
1. User param of service methods are used to indicate who performs the action, instead of requiring permission check
1. Service methods will not audit changes, unless stated explicitly

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

View File

@ -43,5 +43,4 @@ OD-2248
OD-2257
OD-2358
OD-2403
OD-2467
OD-2552
OD-2467

34
pom.xml
View File

@ -6,10 +6,10 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>parent</artifactId>
<version>1.3.0</version>
<version>1.2.3</version>
</parent>
<artifactId>server</artifactId>
<version>13.1.3</version>
<version>12.0.7</version>
<packaging>pom</packaging>
<build>
<finalName>${project.groupId}.${project.artifactId}-${project.version}</finalName>
@ -38,7 +38,7 @@
<plugin>
<groupId>io.onedev</groupId>
<artifactId>plugin-maven</artifactId>
<version>2.7.0</version>
<version>2.6.9</version>
<executions>
<execution>
<?m2e execute onConfiguration,onIncremental?>
@ -227,11 +227,6 @@
<artifactId>wicket-native-websocket-core</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-guice</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
@ -280,7 +275,7 @@
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>11.28</version>
<version>11.9.1</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
@ -320,7 +315,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.5.0-jre</version>
<version>32.0.1-jre</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
@ -627,16 +622,6 @@
<artifactId>fastexcel</artifactId>
<version>0.15.7</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
@ -656,8 +641,8 @@
</repository>
</repositories>
<properties>
<commons.version>3.1.1</commons.version>
<agent.version>2.3.3</agent.version>
<commons.version>3.0.13</commons.version>
<agent.version>2.2.17</agent.version>
<slf4j.version>2.0.9</slf4j.version>
<logback.version>1.4.14</logback.version>
<antlr.version>4.7.2</antlr.version>
@ -669,10 +654,9 @@
<shiro.version>1.13.0</shiro.version>
<jgit.version>5.13.3.202401111512-r</jgit.version>
<flexmark.version>0.64.8</flexmark.version>
<groovy.version>3.0.25</groovy.version>
<groovy.version>3.0.19</groovy.version>
<servlet.version>3.1.0</servlet.version>
<jackson.version>2.15.0</jackson.version>
<tika.version>3.2.2</tika.version>
<langchain4j.version>1.8.0</langchain4j.version>
<tika.version>1.28.3</tika.version>
</properties>
</project>

View File

@ -148,14 +148,6 @@ query to get notified of interesting events.
![issue query](./doc/images/issue-query.gif)
## 🤖 MCP server to interact with OneDev via AI agents
MCP server for managing issues, pull requests, and builds. Streamline DevOps workflows, configure CI/CD jobs,
and investigate build failures through conversations.
[**Tutorial**](https://docs.onedev.io/tutorials/misc/working-with-mcp)
![mcp](./doc/images/mcp.png)
## 🎛️ Dashboard for teams and users
Arrange gadgets in custom dashboard to get important information

View File

@ -7,7 +7,7 @@
<parent>
<groupId>io.onedev</groupId>
<artifactId>server</artifactId>
<version>13.1.3</version>
<version>12.0.7</version>
</parent>
<build>
<plugins>
@ -274,10 +274,6 @@
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-native-websocket-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-guice</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
@ -375,18 +371,20 @@
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>9.2</version>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk7</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<properties>
<kotlin.version>1.9.23</kotlin.version>

View File

@ -1,327 +0,0 @@
package dev.langchain4j.internal;
import java.util.Random;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dev.langchain4j.Internal;
import dev.langchain4j.exception.LangChain4jException;
import dev.langchain4j.exception.NonRetriableException;
import io.onedev.server.exception.ExceptionUtils;
/**
* Utility class for retrying actions.
*/
@Internal
public final class RetryUtils {
private static final Random RANDOM = new Random();
private RetryUtils() {}
private static final Logger log = LoggerFactory.getLogger(RetryUtils.class);
/**
* This method returns a RetryPolicy.Builder.
*
* @return A RetryPolicy.Builder.
*/
public static RetryPolicy.Builder retryPolicyBuilder() {
return new RetryPolicy.Builder();
}
/**
* This class encapsulates a retry policy.
*/
public static final class RetryPolicy {
/**
* This class encapsulates a retry policy builder.
*/
public static final class Builder {
private int maxRetries = 2;
private int delayMillis = 1000;
private double jitterScale = 0.2;
private double backoffExp = 1.5;
/**
* Construct a RetryPolicy.Builder.
*/
public Builder() {}
/**
* Sets the default maximum number of retries.
*
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @return {@code this}
*/
public Builder maxRetries(int maxRetries) {
this.maxRetries = maxRetries;
return this;
}
/**
* Sets the base delay in milliseconds.
*
* <p>The delay is calculated as follows:
* <ol>
* <li>Calculate the raw delay in milliseconds as
* {@code delayMillis * Math.pow(backoffExp, retry)}.</li>
* <li>Calculate the jitter delay in milliseconds as
* {@code rawDelayMs + rand.nextInt((int) (rawDelayMs * jitterScale))}.</li>
* <li>Sleep for the jitter delay in milliseconds.</li>
* </ol>
*
* @param delayMillis The delay in milliseconds.
* @return {@code this}
*/
public Builder delayMillis(int delayMillis) {
this.delayMillis = delayMillis;
return this;
}
/**
* Sets the jitter scale.
*
* <p>The jitter delay in milliseconds is calculated as
* {@code rawDelayMs + rand.nextInt((int) (rawDelayMs * jitterScale))}.
*
* @param jitterScale The jitter scale.
* @return {@code this}
*/
public Builder jitterScale(double jitterScale) {
this.jitterScale = jitterScale;
return this;
}
/**
* Sets the backoff exponent.
*
* @param backoffExp The backoff exponent.
* @return {@code this}
*/
public Builder backoffExp(double backoffExp) {
this.backoffExp = backoffExp;
return this;
}
/**
* Builds a RetryPolicy.
*
* @return A RetryPolicy.
*/
public RetryPolicy build() {
return new RetryPolicy(maxRetries, delayMillis, jitterScale, backoffExp);
}
}
private final int maxRetries;
private final int delayMillis;
private final double jitterScale;
private final double backoffExp;
/**
* Construct a RetryPolicy.
*
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @param delayMillis The delay in milliseconds.
* @param jitterScale The jitter scale.
* @param backoffExp The backoff exponent.
*/
public RetryPolicy(int maxRetries, int delayMillis, double jitterScale, double backoffExp) {
this.maxRetries = maxRetries;
this.delayMillis = delayMillis;
this.jitterScale = jitterScale;
this.backoffExp = backoffExp;
}
/**
* This method returns the raw delay in milliseconds after a given retry.
*
* @param retry The retry number.
* @return The raw delay in milliseconds.
*/
public double rawDelayMs(int retry) {
return delayMillis * Math.pow(backoffExp, retry);
}
/**
* This method returns the jitter delay in milliseconds after a given retry.
*
* @param retry The retry number.
* @return The jitter delay in milliseconds.
*/
public int jitterDelayMillis(int retry) {
double delay = rawDelayMs(retry);
double jitter = delay * jitterScale;
return (int) (delay + RANDOM.nextInt((int) jitter));
}
/**
* This method sleeps after a given retry.
*
* @param retry The retry number.
*/
@JacocoIgnoreCoverageGenerated
public void sleep(int retry) {
try {
Thread.sleep(jitterDelayMillis(retry));
} catch (InterruptedException ignored) {
// pass
}
}
/**
* This method attempts to execute a given action up to 3 times with an exponential backoff.
* If the action fails on all attempts, it throws a RuntimeException.
*
* @param action The action to be executed.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public <T> T withRetry(Callable<T> action) {
return withRetry(action, maxRetries);
}
/**
* This method attempts to execute a given action up to a specified number of times with an exponential backoff.
* If the action fails on all attempts, it throws a RuntimeException.
*
* @param action The action to be executed.
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public <T> T withRetry(Callable<T> action, int maxRetries) {
int retry = 0;
while (true) {
try {
return action.call();
} catch (NonRetriableException e) {
throw e;
} catch (Exception e) {
if (retry >= maxRetries || ExceptionUtils.find(e, InterruptedException.class) != null) {
throw e instanceof RuntimeException re ? re : new LangChain4jException(e);
}
log.warn(
"A retriable exception occurred. Remaining retries: %s of %s"
.formatted(maxRetries - retry, maxRetries),
e);
sleep(retry);
}
retry++;
}
}
}
/**
* Default retry policy used by {@link #withRetry(Callable)}.
*/
public static final RetryPolicy DEFAULT_RETRY_POLICY = retryPolicyBuilder()
.maxRetries(2)
.delayMillis(500)
.jitterScale(0.2)
.backoffExp(1.5)
.build();
/**
* This method attempts to execute a given action up to 3 times with an exponential backoff.
* If the action fails on all attempts, it throws a RuntimeException.
*
* @param action The action to be executed.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public static <T> T withRetry(Callable<T> action) {
return DEFAULT_RETRY_POLICY.withRetry(action);
}
/**
* This method attempts to execute a given action up to a specified number of times with an exponential backoff.
* If the action fails on all attempts, it throws a RuntimeException.
*
* @param action The action to be executed.
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public static <T> T withRetry(Callable<T> action, int maxRetries) {
return DEFAULT_RETRY_POLICY.withRetry(action, maxRetries);
}
/**
* This method attempts to execute a given action up to a specified number of times with an exponential backoff.
* If the action fails on all attempts, it throws a RuntimeException.
*
* @param action The action to be executed.
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @throws RuntimeException if the action fails on all attempts.
*/
public static void withRetry(Runnable action, int maxRetries) {
DEFAULT_RETRY_POLICY.withRetry(
() -> {
action.run();
return null;
},
maxRetries);
}
/**
* This method attempts to execute a given action up to 3 times with an exponential backoff.
* If the action fails, the Exception causing the failure will be mapped with the default {@link ExceptionMapper}.
*
* @param action The action to be executed.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public static <T> T withRetryMappingExceptions(Callable<T> action) {
return withRetry(() -> ExceptionMapper.DEFAULT.withExceptionMapper(action));
}
/**
* This method attempts to execute a given action up to a specified number of times with an exponential backoff.
* If the action fails, the Exception causing the failure will be mapped with the default {@link ExceptionMapper}.
*
* @param action The action to be executed.
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public static <T> T withRetryMappingExceptions(Callable<T> action, int maxRetries) {
return withRetryMappingExceptions(action, maxRetries, ExceptionMapper.DEFAULT);
}
/**
* This method attempts to execute a given action up to a specified number of times with an exponential backoff.
* If the action fails, the Exception causing the failure will be mapped with the provided {@link ExceptionMapper}.
*
* @param action The action to be executed.
* @param maxRetries The maximum number of retries.
* The action can be executed up to {@code maxRetries + 1} times.
* @param exceptionMapper The ExceptionMapper used to translate the exception that caused the failure of the action invocation.
* @param <T> The type of the result of the action.
* @return The result of the action if it is successful.
* @throws RuntimeException if the action fails on all attempts.
*/
public static <T> T withRetryMappingExceptions(
Callable<T> action, int maxRetries, ExceptionMapper exceptionMapper) {
return withRetry(() -> exceptionMapper.withExceptionMapper(action), maxRetries);
}
}

View File

@ -3,7 +3,6 @@ package io.onedev.server;
import static com.google.common.collect.Lists.newArrayList;
import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@ -24,9 +23,6 @@ import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.Configuration;
import javax.validation.Path;
import javax.validation.Path.Node;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
@ -76,10 +72,8 @@ import io.onedev.commons.utils.StringUtils;
import io.onedev.k8shelper.KubernetesHelper;
import io.onedev.k8shelper.OsInfo;
import io.onedev.server.ai.McpHelperResource;
import io.onedev.server.annotation.Shallow;
import io.onedev.server.attachment.AttachmentService;
import io.onedev.server.attachment.DefaultAttachmentService;
import io.onedev.server.buildspec.BuildSpecSchemaResource;
import io.onedev.server.attachment.AttachmentManager;
import io.onedev.server.attachment.DefaultAttachmentManager;
import io.onedev.server.buildspec.job.log.instruction.LogInstruction;
import io.onedev.server.cluster.ClusterResource;
import io.onedev.server.codequality.CodeProblemContribution;
@ -92,10 +86,182 @@ import io.onedev.server.commandhandler.ResetAdminPassword;
import io.onedev.server.commandhandler.RestoreDatabase;
import io.onedev.server.commandhandler.Translate;
import io.onedev.server.commandhandler.Upgrade;
import io.onedev.server.data.DataService;
import io.onedev.server.data.DefaultDataService;
import io.onedev.server.entityreference.DefaultReferenceChangeService;
import io.onedev.server.entityreference.ReferenceChangeService;
import io.onedev.server.data.DataManager;
import io.onedev.server.data.DefaultDataManager;
import io.onedev.server.entitymanager.AccessTokenAuthorizationManager;
import io.onedev.server.entitymanager.AccessTokenManager;
import io.onedev.server.entitymanager.AgentAttributeManager;
import io.onedev.server.entitymanager.AgentLastUsedDateManager;
import io.onedev.server.entitymanager.AgentManager;
import io.onedev.server.entitymanager.AgentTokenManager;
import io.onedev.server.entitymanager.AlertManager;
import io.onedev.server.entitymanager.BaseAuthorizationManager;
import io.onedev.server.entitymanager.BuildDependenceManager;
import io.onedev.server.entitymanager.BuildLabelManager;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.BuildMetricManager;
import io.onedev.server.entitymanager.BuildParamManager;
import io.onedev.server.entitymanager.BuildQueryPersonalizationManager;
import io.onedev.server.entitymanager.CodeCommentManager;
import io.onedev.server.entitymanager.CodeCommentMentionManager;
import io.onedev.server.entitymanager.CodeCommentQueryPersonalizationManager;
import io.onedev.server.entitymanager.CodeCommentReplyManager;
import io.onedev.server.entitymanager.CodeCommentStatusChangeManager;
import io.onedev.server.entitymanager.CodeCommentTouchManager;
import io.onedev.server.entitymanager.CommitQueryPersonalizationManager;
import io.onedev.server.entitymanager.DashboardGroupShareManager;
import io.onedev.server.entitymanager.DashboardManager;
import io.onedev.server.entitymanager.DashboardUserShareManager;
import io.onedev.server.entitymanager.DashboardVisitManager;
import io.onedev.server.entitymanager.EmailAddressManager;
import io.onedev.server.entitymanager.GitLfsLockManager;
import io.onedev.server.entitymanager.GpgKeyManager;
import io.onedev.server.entitymanager.GroupAuthorizationManager;
import io.onedev.server.entitymanager.GroupManager;
import io.onedev.server.entitymanager.IssueAuthorizationManager;
import io.onedev.server.entitymanager.IssueChangeManager;
import io.onedev.server.entitymanager.IssueCommentManager;
import io.onedev.server.entitymanager.IssueCommentReactionManager;
import io.onedev.server.entitymanager.IssueCommentRevisionManager;
import io.onedev.server.entitymanager.IssueDescriptionRevisionManager;
import io.onedev.server.entitymanager.IssueFieldManager;
import io.onedev.server.entitymanager.IssueLinkManager;
import io.onedev.server.entitymanager.IssueManager;
import io.onedev.server.entitymanager.IssueMentionManager;
import io.onedev.server.entitymanager.IssueQueryPersonalizationManager;
import io.onedev.server.entitymanager.IssueReactionManager;
import io.onedev.server.entitymanager.IssueScheduleManager;
import io.onedev.server.entitymanager.IssueStateHistoryManager;
import io.onedev.server.entitymanager.IssueTouchManager;
import io.onedev.server.entitymanager.IssueVoteManager;
import io.onedev.server.entitymanager.IssueWatchManager;
import io.onedev.server.entitymanager.IssueWorkManager;
import io.onedev.server.entitymanager.IterationManager;
import io.onedev.server.entitymanager.JobCacheManager;
import io.onedev.server.entitymanager.LabelSpecManager;
import io.onedev.server.entitymanager.LinkAuthorizationManager;
import io.onedev.server.entitymanager.LinkSpecManager;
import io.onedev.server.entitymanager.MembershipManager;
import io.onedev.server.entitymanager.PackBlobManager;
import io.onedev.server.entitymanager.PackBlobReferenceManager;
import io.onedev.server.entitymanager.PackLabelManager;
import io.onedev.server.entitymanager.PackManager;
import io.onedev.server.entitymanager.PackQueryPersonalizationManager;
import io.onedev.server.entitymanager.PendingSuggestionApplyManager;
import io.onedev.server.entitymanager.ProjectLabelManager;
import io.onedev.server.entitymanager.ProjectLastEventDateManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.PullRequestAssignmentManager;
import io.onedev.server.entitymanager.PullRequestChangeManager;
import io.onedev.server.entitymanager.PullRequestCommentManager;
import io.onedev.server.entitymanager.PullRequestCommentReactionManager;
import io.onedev.server.entitymanager.PullRequestCommentRevisionManager;
import io.onedev.server.entitymanager.PullRequestDescriptionRevisionManager;
import io.onedev.server.entitymanager.PullRequestLabelManager;
import io.onedev.server.entitymanager.PullRequestManager;
import io.onedev.server.entitymanager.PullRequestMentionManager;
import io.onedev.server.entitymanager.PullRequestQueryPersonalizationManager;
import io.onedev.server.entitymanager.PullRequestReactionManager;
import io.onedev.server.entitymanager.PullRequestReviewManager;
import io.onedev.server.entitymanager.PullRequestTouchManager;
import io.onedev.server.entitymanager.PullRequestUpdateManager;
import io.onedev.server.entitymanager.PullRequestWatchManager;
import io.onedev.server.entitymanager.ReviewedDiffManager;
import io.onedev.server.entitymanager.RoleManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.entitymanager.SshKeyManager;
import io.onedev.server.entitymanager.StopwatchManager;
import io.onedev.server.entitymanager.UserAuthorizationManager;
import io.onedev.server.entitymanager.UserInvitationManager;
import io.onedev.server.entitymanager.UserManager;
import io.onedev.server.entitymanager.impl.DefaultAccessTokenAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultAccessTokenManager;
import io.onedev.server.entitymanager.impl.DefaultAgentAttributeManager;
import io.onedev.server.entitymanager.impl.DefaultAgentLastUsedDateManager;
import io.onedev.server.entitymanager.impl.DefaultAgentManager;
import io.onedev.server.entitymanager.impl.DefaultAgentTokenManager;
import io.onedev.server.entitymanager.impl.DefaultAlertManager;
import io.onedev.server.entitymanager.impl.DefaultBaseAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultBuildDependenceManager;
import io.onedev.server.entitymanager.impl.DefaultBuildLabelManager;
import io.onedev.server.entitymanager.impl.DefaultBuildManager;
import io.onedev.server.entitymanager.impl.DefaultBuildMetricManager;
import io.onedev.server.entitymanager.impl.DefaultBuildParamManager;
import io.onedev.server.entitymanager.impl.DefaultBuildQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentMentionManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentReplyManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentStatusChangeManager;
import io.onedev.server.entitymanager.impl.DefaultCodeCommentTouchManager;
import io.onedev.server.entitymanager.impl.DefaultCommitQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultDashboardGroupShareManager;
import io.onedev.server.entitymanager.impl.DefaultDashboardManager;
import io.onedev.server.entitymanager.impl.DefaultDashboardUserShareManager;
import io.onedev.server.entitymanager.impl.DefaultDashboardVisitManager;
import io.onedev.server.entitymanager.impl.DefaultEmailAddressManager;
import io.onedev.server.entitymanager.impl.DefaultGitLfsLockManager;
import io.onedev.server.entitymanager.impl.DefaultGpgKeyManager;
import io.onedev.server.entitymanager.impl.DefaultGroupAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultGroupManager;
import io.onedev.server.entitymanager.impl.DefaultIssueAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultIssueChangeManager;
import io.onedev.server.entitymanager.impl.DefaultIssueCommentManager;
import io.onedev.server.entitymanager.impl.DefaultIssueCommentReactionManager;
import io.onedev.server.entitymanager.impl.DefaultIssueCommentRevisionManager;
import io.onedev.server.entitymanager.impl.DefaultIssueDescriptionRevisionManager;
import io.onedev.server.entitymanager.impl.DefaultIssueFieldManager;
import io.onedev.server.entitymanager.impl.DefaultIssueLinkManager;
import io.onedev.server.entitymanager.impl.DefaultIssueManager;
import io.onedev.server.entitymanager.impl.DefaultIssueMentionManager;
import io.onedev.server.entitymanager.impl.DefaultIssueQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultIssueReactionManager;
import io.onedev.server.entitymanager.impl.DefaultIssueScheduleManager;
import io.onedev.server.entitymanager.impl.DefaultIssueStateHistoryManager;
import io.onedev.server.entitymanager.impl.DefaultIssueTouchManager;
import io.onedev.server.entitymanager.impl.DefaultIssueVoteManager;
import io.onedev.server.entitymanager.impl.DefaultIssueWatchManager;
import io.onedev.server.entitymanager.impl.DefaultIssueWorkManager;
import io.onedev.server.entitymanager.impl.DefaultIterationManager;
import io.onedev.server.entitymanager.impl.DefaultJobCacheManager;
import io.onedev.server.entitymanager.impl.DefaultLabelSpecManager;
import io.onedev.server.entitymanager.impl.DefaultLinkAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultLinkSpecManager;
import io.onedev.server.entitymanager.impl.DefaultMembershipManager;
import io.onedev.server.entitymanager.impl.DefaultPackBlobManager;
import io.onedev.server.entitymanager.impl.DefaultPackBlobReferenceManager;
import io.onedev.server.entitymanager.impl.DefaultPackLabelManager;
import io.onedev.server.entitymanager.impl.DefaultPackManager;
import io.onedev.server.entitymanager.impl.DefaultPackQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultPendingSuggestionApplyManager;
import io.onedev.server.entitymanager.impl.DefaultProjectLabelManager;
import io.onedev.server.entitymanager.impl.DefaultProjectLastEventDateManager;
import io.onedev.server.entitymanager.impl.DefaultProjectManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestAssignmentManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestChangeManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestCommentManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestCommentReactionManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestCommentRevisionManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestDescriptionRevisionManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestLabelManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestMentionManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestQueryPersonalizationManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestReactionManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestReviewManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestTouchManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestUpdateManager;
import io.onedev.server.entitymanager.impl.DefaultPullRequestWatchManager;
import io.onedev.server.entitymanager.impl.DefaultReviewedDiffManager;
import io.onedev.server.entitymanager.impl.DefaultRoleManager;
import io.onedev.server.entitymanager.impl.DefaultSettingManager;
import io.onedev.server.entitymanager.impl.DefaultSshKeyManager;
import io.onedev.server.entitymanager.impl.DefaultStopwatchManager;
import io.onedev.server.entitymanager.impl.DefaultUserAuthorizationManager;
import io.onedev.server.entitymanager.impl.DefaultUserInvitationManager;
import io.onedev.server.entitymanager.impl.DefaultUserManager;
import io.onedev.server.entityreference.DefaultReferenceChangeManager;
import io.onedev.server.entityreference.ReferenceChangeManager;
import io.onedev.server.event.DefaultListenerRegistry;
import io.onedev.server.event.ListenerRegistry;
import io.onedev.server.exception.handler.ExceptionHandler;
@ -110,23 +276,23 @@ import io.onedev.server.git.hook.GitPreReceiveChecker;
import io.onedev.server.git.location.GitLocation;
import io.onedev.server.git.service.DefaultGitService;
import io.onedev.server.git.service.GitService;
import io.onedev.server.git.signatureverification.DefaultSignatureVerificationService;
import io.onedev.server.git.signatureverification.SignatureVerificationService;
import io.onedev.server.git.signatureverification.DefaultSignatureVerificationManager;
import io.onedev.server.git.signatureverification.SignatureVerificationManager;
import io.onedev.server.git.signatureverification.SignatureVerifier;
import io.onedev.server.jetty.DefaultJettyService;
import io.onedev.server.jetty.DefaultJettyManager;
import io.onedev.server.jetty.DefaultSessionDataStoreFactory;
import io.onedev.server.jetty.JettyService;
import io.onedev.server.job.DefaultJobService;
import io.onedev.server.jetty.JettyManager;
import io.onedev.server.job.DefaultJobManager;
import io.onedev.server.job.DefaultResourceAllocator;
import io.onedev.server.job.JobService;
import io.onedev.server.job.JobManager;
import io.onedev.server.job.ResourceAllocator;
import io.onedev.server.job.log.DefaultLogService;
import io.onedev.server.job.log.LogService;
import io.onedev.server.mail.DefaultMailService;
import io.onedev.server.mail.MailService;
import io.onedev.server.markdown.DefaultMarkdownService;
import io.onedev.server.job.log.DefaultLogManager;
import io.onedev.server.job.log.LogManager;
import io.onedev.server.mail.DefaultMailManager;
import io.onedev.server.mail.MailManager;
import io.onedev.server.markdown.DefaultMarkdownManager;
import io.onedev.server.markdown.HtmlProcessor;
import io.onedev.server.markdown.MarkdownService;
import io.onedev.server.markdown.MarkdownManager;
import io.onedev.server.model.support.administration.GroovyScript;
import io.onedev.server.model.support.administration.authenticator.Authenticator;
import io.onedev.server.notification.BuildNotificationManager;
@ -137,21 +303,21 @@ import io.onedev.server.notification.PackNotificationManager;
import io.onedev.server.notification.PullRequestNotificationManager;
import io.onedev.server.notification.WebHookManager;
import io.onedev.server.pack.PackFilter;
import io.onedev.server.persistence.DefaultIdService;
import io.onedev.server.persistence.DefaultSessionFactoryService;
import io.onedev.server.persistence.DefaultSessionService;
import io.onedev.server.persistence.DefaultTransactionService;
import io.onedev.server.persistence.DefaultIdManager;
import io.onedev.server.persistence.DefaultSessionFactoryManager;
import io.onedev.server.persistence.DefaultSessionManager;
import io.onedev.server.persistence.DefaultTransactionManager;
import io.onedev.server.persistence.HibernateInterceptor;
import io.onedev.server.persistence.IdService;
import io.onedev.server.persistence.IdManager;
import io.onedev.server.persistence.PersistListener;
import io.onedev.server.persistence.PrefixedNamingStrategy;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.persistence.SessionFactoryProvider;
import io.onedev.server.persistence.SessionFactoryService;
import io.onedev.server.persistence.SessionInterceptor;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.persistence.SessionProvider;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.TransactionInterceptor;
import io.onedev.server.persistence.TransactionService;
import io.onedev.server.persistence.TransactionManager;
import io.onedev.server.persistence.annotation.Sessional;
import io.onedev.server.persistence.annotation.Transactional;
import io.onedev.server.persistence.dao.Dao;
@ -162,16 +328,16 @@ import io.onedev.server.rest.JerseyConfigurator;
import io.onedev.server.rest.ResourceConfigProvider;
import io.onedev.server.rest.WebApplicationExceptionHandler;
import io.onedev.server.rest.resource.ProjectResource;
import io.onedev.server.search.code.CodeIndexService;
import io.onedev.server.search.code.CodeSearchService;
import io.onedev.server.search.code.DefaultCodeIndexService;
import io.onedev.server.search.code.DefaultCodeSearchService;
import io.onedev.server.search.entitytext.CodeCommentTextService;
import io.onedev.server.search.entitytext.DefaultCodeCommentTextService;
import io.onedev.server.search.entitytext.DefaultIssueTextService;
import io.onedev.server.search.entitytext.DefaultPullRequestTextService;
import io.onedev.server.search.entitytext.IssueTextService;
import io.onedev.server.search.entitytext.PullRequestTextService;
import io.onedev.server.search.code.CodeIndexManager;
import io.onedev.server.search.code.CodeSearchManager;
import io.onedev.server.search.code.DefaultCodeIndexManager;
import io.onedev.server.search.code.DefaultCodeSearchManager;
import io.onedev.server.search.entitytext.CodeCommentTextManager;
import io.onedev.server.search.entitytext.DefaultCodeCommentTextManager;
import io.onedev.server.search.entitytext.DefaultIssueTextManager;
import io.onedev.server.search.entitytext.DefaultPullRequestTextManager;
import io.onedev.server.search.entitytext.IssueTextManager;
import io.onedev.server.search.entitytext.PullRequestTextManager;
import io.onedev.server.security.BasicAuthenticationFilter;
import io.onedev.server.security.BearerAuthenticationFilter;
import io.onedev.server.security.CodePullAuthorizationSource;
@ -183,208 +349,26 @@ import io.onedev.server.security.DefaultWebSecurityManager;
import io.onedev.server.security.FilterChainConfigurator;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.security.realm.GeneralAuthorizingRealm;
import io.onedev.server.service.AccessTokenAuthorizationService;
import io.onedev.server.service.AccessTokenService;
import io.onedev.server.service.AgentAttributeService;
import io.onedev.server.service.AgentLastUsedDateService;
import io.onedev.server.service.AgentService;
import io.onedev.server.service.AgentTokenService;
import io.onedev.server.service.AlertService;
import io.onedev.server.service.BaseAuthorizationService;
import io.onedev.server.service.BuildDependenceService;
import io.onedev.server.service.BuildLabelService;
import io.onedev.server.service.BuildMetricService;
import io.onedev.server.service.BuildParamService;
import io.onedev.server.service.BuildQueryPersonalizationService;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.CodeCommentMentionService;
import io.onedev.server.service.CodeCommentQueryPersonalizationService;
import io.onedev.server.service.CodeCommentReplyService;
import io.onedev.server.service.CodeCommentService;
import io.onedev.server.service.CodeCommentStatusChangeService;
import io.onedev.server.service.CodeCommentTouchService;
import io.onedev.server.service.CommitQueryPersonalizationService;
import io.onedev.server.service.DashboardGroupShareService;
import io.onedev.server.service.DashboardService;
import io.onedev.server.service.DashboardUserShareService;
import io.onedev.server.service.DashboardVisitService;
import io.onedev.server.service.EmailAddressService;
import io.onedev.server.service.GitLfsLockService;
import io.onedev.server.service.GpgKeyService;
import io.onedev.server.service.GroupAuthorizationService;
import io.onedev.server.service.GroupEntitlementService;
import io.onedev.server.service.GroupService;
import io.onedev.server.service.IssueAuthorizationService;
import io.onedev.server.service.IssueChangeService;
import io.onedev.server.service.IssueCommentReactionService;
import io.onedev.server.service.IssueCommentRevisionService;
import io.onedev.server.service.IssueCommentService;
import io.onedev.server.service.IssueDescriptionRevisionService;
import io.onedev.server.service.IssueFieldService;
import io.onedev.server.service.IssueLinkService;
import io.onedev.server.service.IssueMentionService;
import io.onedev.server.service.IssueQueryPersonalizationService;
import io.onedev.server.service.IssueReactionService;
import io.onedev.server.service.IssueScheduleService;
import io.onedev.server.service.IssueService;
import io.onedev.server.service.IssueStateHistoryService;
import io.onedev.server.service.IssueTouchService;
import io.onedev.server.service.IssueVoteService;
import io.onedev.server.service.IssueWatchService;
import io.onedev.server.service.IssueWorkService;
import io.onedev.server.service.IterationService;
import io.onedev.server.service.JobCacheService;
import io.onedev.server.service.LabelSpecService;
import io.onedev.server.service.LinkAuthorizationService;
import io.onedev.server.service.LinkSpecService;
import io.onedev.server.service.MembershipService;
import io.onedev.server.service.PackBlobReferenceService;
import io.onedev.server.service.PackBlobService;
import io.onedev.server.service.PackLabelService;
import io.onedev.server.service.PackQueryPersonalizationService;
import io.onedev.server.service.PackService;
import io.onedev.server.service.PendingSuggestionApplyService;
import io.onedev.server.service.ProjectEntitlementService;
import io.onedev.server.service.ProjectLabelService;
import io.onedev.server.service.ProjectLastEventDateService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.PullRequestAssignmentService;
import io.onedev.server.service.PullRequestChangeService;
import io.onedev.server.service.PullRequestCommentReactionService;
import io.onedev.server.service.PullRequestCommentRevisionService;
import io.onedev.server.service.PullRequestCommentService;
import io.onedev.server.service.PullRequestDescriptionRevisionService;
import io.onedev.server.service.PullRequestLabelService;
import io.onedev.server.service.PullRequestMentionService;
import io.onedev.server.service.PullRequestQueryPersonalizationService;
import io.onedev.server.service.PullRequestReactionService;
import io.onedev.server.service.PullRequestReviewService;
import io.onedev.server.service.PullRequestService;
import io.onedev.server.service.PullRequestTouchService;
import io.onedev.server.service.PullRequestUpdateService;
import io.onedev.server.service.PullRequestWatchService;
import io.onedev.server.service.ReviewedDiffService;
import io.onedev.server.service.RoleService;
import io.onedev.server.service.SettingService;
import io.onedev.server.service.SshKeyService;
import io.onedev.server.service.SsoAccountService;
import io.onedev.server.service.SsoProviderService;
import io.onedev.server.service.StopwatchService;
import io.onedev.server.service.UserAuthorizationService;
import io.onedev.server.service.UserEntitlementService;
import io.onedev.server.service.UserInvitationService;
import io.onedev.server.service.UserService;
import io.onedev.server.service.impl.DefaultAccessTokenAuthorizationService;
import io.onedev.server.service.impl.DefaultAccessTokenService;
import io.onedev.server.service.impl.DefaultAgentAttributeService;
import io.onedev.server.service.impl.DefaultAgentLastUsedDateService;
import io.onedev.server.service.impl.DefaultAgentService;
import io.onedev.server.service.impl.DefaultAgentTokenService;
import io.onedev.server.service.impl.DefaultAlertService;
import io.onedev.server.service.impl.DefaultBaseAuthorizationService;
import io.onedev.server.service.impl.DefaultBuildDependenceService;
import io.onedev.server.service.impl.DefaultBuildLabelService;
import io.onedev.server.service.impl.DefaultBuildMetricService;
import io.onedev.server.service.impl.DefaultBuildParamService;
import io.onedev.server.service.impl.DefaultBuildQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultBuildService;
import io.onedev.server.service.impl.DefaultCodeCommentMentionService;
import io.onedev.server.service.impl.DefaultCodeCommentQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultCodeCommentReplyService;
import io.onedev.server.service.impl.DefaultCodeCommentService;
import io.onedev.server.service.impl.DefaultCodeCommentStatusChangeService;
import io.onedev.server.service.impl.DefaultCodeCommentTouchService;
import io.onedev.server.service.impl.DefaultCommitQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultDashboardGroupShareService;
import io.onedev.server.service.impl.DefaultDashboardService;
import io.onedev.server.service.impl.DefaultDashboardUserShareService;
import io.onedev.server.service.impl.DefaultDashboardVisitService;
import io.onedev.server.service.impl.DefaultEmailAddressService;
import io.onedev.server.service.impl.DefaultGitLfsLockService;
import io.onedev.server.service.impl.DefaultGpgKeyService;
import io.onedev.server.service.impl.DefaultGroupAuthorizationService;
import io.onedev.server.service.impl.DefaultGroupEntitlementService;
import io.onedev.server.service.impl.DefaultGroupService;
import io.onedev.server.service.impl.DefaultIssueAuthorizationService;
import io.onedev.server.service.impl.DefaultIssueChangeService;
import io.onedev.server.service.impl.DefaultIssueCommentReactionService;
import io.onedev.server.service.impl.DefaultIssueCommentRevisionService;
import io.onedev.server.service.impl.DefaultIssueCommentService;
import io.onedev.server.service.impl.DefaultIssueDescriptionRevisionService;
import io.onedev.server.service.impl.DefaultIssueFieldService;
import io.onedev.server.service.impl.DefaultIssueLinkService;
import io.onedev.server.service.impl.DefaultIssueMentionService;
import io.onedev.server.service.impl.DefaultIssueQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultIssueReactionService;
import io.onedev.server.service.impl.DefaultIssueScheduleService;
import io.onedev.server.service.impl.DefaultIssueService;
import io.onedev.server.service.impl.DefaultIssueStateHistoryService;
import io.onedev.server.service.impl.DefaultIssueTouchService;
import io.onedev.server.service.impl.DefaultIssueVoteService;
import io.onedev.server.service.impl.DefaultIssueWatchService;
import io.onedev.server.service.impl.DefaultIssueWorkService;
import io.onedev.server.service.impl.DefaultIterationService;
import io.onedev.server.service.impl.DefaultJobCacheService;
import io.onedev.server.service.impl.DefaultLabelSpecService;
import io.onedev.server.service.impl.DefaultLinkAuthorizationService;
import io.onedev.server.service.impl.DefaultLinkSpecService;
import io.onedev.server.service.impl.DefaultMembershipService;
import io.onedev.server.service.impl.DefaultPackBlobReferenceService;
import io.onedev.server.service.impl.DefaultPackBlobService;
import io.onedev.server.service.impl.DefaultPackLabelService;
import io.onedev.server.service.impl.DefaultPackQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultPackService;
import io.onedev.server.service.impl.DefaultPendingSuggestionApplyService;
import io.onedev.server.service.impl.DefaultProjectEntitlementService;
import io.onedev.server.service.impl.DefaultProjectLabelService;
import io.onedev.server.service.impl.DefaultProjectLastEventDateService;
import io.onedev.server.service.impl.DefaultProjectService;
import io.onedev.server.service.impl.DefaultPullRequestAssignmentService;
import io.onedev.server.service.impl.DefaultPullRequestChangeService;
import io.onedev.server.service.impl.DefaultPullRequestCommentReactionService;
import io.onedev.server.service.impl.DefaultPullRequestCommentRevisionService;
import io.onedev.server.service.impl.DefaultPullRequestCommentService;
import io.onedev.server.service.impl.DefaultPullRequestDescriptionRevisionService;
import io.onedev.server.service.impl.DefaultPullRequestLabelService;
import io.onedev.server.service.impl.DefaultPullRequestMentionService;
import io.onedev.server.service.impl.DefaultPullRequestQueryPersonalizationService;
import io.onedev.server.service.impl.DefaultPullRequestReactionService;
import io.onedev.server.service.impl.DefaultPullRequestReviewService;
import io.onedev.server.service.impl.DefaultPullRequestService;
import io.onedev.server.service.impl.DefaultPullRequestTouchService;
import io.onedev.server.service.impl.DefaultPullRequestUpdateService;
import io.onedev.server.service.impl.DefaultPullRequestWatchService;
import io.onedev.server.service.impl.DefaultReviewedDiffService;
import io.onedev.server.service.impl.DefaultRoleService;
import io.onedev.server.service.impl.DefaultSettingService;
import io.onedev.server.service.impl.DefaultSshKeyService;
import io.onedev.server.service.impl.DefaultSsoAccountService;
import io.onedev.server.service.impl.DefaultSsoProviderService;
import io.onedev.server.service.impl.DefaultStopwatchService;
import io.onedev.server.service.impl.DefaultUserAuthorizationService;
import io.onedev.server.service.impl.DefaultUserEntitlementService;
import io.onedev.server.service.impl.DefaultUserInvitationService;
import io.onedev.server.service.impl.DefaultUserService;
import io.onedev.server.ssh.CommandCreator;
import io.onedev.server.ssh.DefaultSshAuthenticator;
import io.onedev.server.ssh.DefaultSshService;
import io.onedev.server.ssh.DefaultSshManager;
import io.onedev.server.ssh.SshAuthenticator;
import io.onedev.server.ssh.SshService;
import io.onedev.server.ssh.SshManager;
import io.onedev.server.taskschedule.DefaultTaskScheduler;
import io.onedev.server.taskschedule.TaskScheduler;
import io.onedev.server.updatecheck.DefaultUpdateCheckService;
import io.onedev.server.updatecheck.UpdateCheckService;
import io.onedev.server.updatecheck.DefaultUpdateCheckManager;
import io.onedev.server.updatecheck.UpdateCheckManager;
import io.onedev.server.util.ScriptContribution;
import io.onedev.server.util.concurrent.BatchWorkExecutionService;
import io.onedev.server.util.concurrent.DefaultBatchWorkExecutionService;
import io.onedev.server.util.concurrent.DefaultWorkExecutionService;
import io.onedev.server.util.concurrent.WorkExecutionService;
import io.onedev.server.util.concurrent.BatchWorkManager;
import io.onedev.server.util.concurrent.DefaultBatchWorkManager;
import io.onedev.server.util.concurrent.DefaultWorkExecutor;
import io.onedev.server.util.concurrent.WorkExecutor;
import io.onedev.server.util.jackson.ObjectMapperConfigurator;
import io.onedev.server.util.jackson.ObjectMapperProvider;
import io.onedev.server.util.jackson.git.GitObjectMapperConfigurator;
import io.onedev.server.util.jackson.hibernate.HibernateObjectMapperConfigurator;
import io.onedev.server.util.oauth.DefaultOAuthTokenService;
import io.onedev.server.util.oauth.OAuthTokenService;
import io.onedev.server.util.oauth.DefaultOAuthTokenManager;
import io.onedev.server.util.oauth.OAuthTokenManager;
import io.onedev.server.util.xstream.CollectionConverter;
import io.onedev.server.util.xstream.HibernateProxyConverter;
import io.onedev.server.util.xstream.MapConverter;
@ -393,17 +377,15 @@ import io.onedev.server.util.xstream.ReflectionConverter;
import io.onedev.server.util.xstream.StringConverter;
import io.onedev.server.util.xstream.VersionedDocumentConverter;
import io.onedev.server.validation.MessageInterpolator;
import io.onedev.server.validation.ShallowValidatorProvider;
import io.onedev.server.validation.ValidatorProvider;
import io.onedev.server.web.DefaultUrlService;
import io.onedev.server.web.DefaultUrlManager;
import io.onedev.server.web.DefaultWicketFilter;
import io.onedev.server.web.DefaultWicketServlet;
import io.onedev.server.web.ResourcePackScopeContribution;
import io.onedev.server.web.SessionListener;
import io.onedev.server.web.UrlService;
import io.onedev.server.web.UrlManager;
import io.onedev.server.web.WebApplication;
import io.onedev.server.web.avatar.AvatarService;
import io.onedev.server.web.avatar.DefaultAvatarService;
import io.onedev.server.web.avatar.AvatarManager;
import io.onedev.server.web.avatar.DefaultAvatarManager;
import io.onedev.server.web.component.diff.DiffRenderer;
import io.onedev.server.web.component.markdown.SourcePositionTrackExtension;
import io.onedev.server.web.component.markdown.emoji.EmojiExtension;
@ -416,24 +398,24 @@ import io.onedev.server.web.exceptionhandler.PageExpiredExceptionHandler;
import io.onedev.server.web.page.layout.AdministrationSettingContribution;
import io.onedev.server.web.page.project.blob.render.BlobRenderer;
import io.onedev.server.web.page.project.setting.ProjectSettingContribution;
import io.onedev.server.web.upload.DefaultUploadService;
import io.onedev.server.web.upload.UploadService;
import io.onedev.server.web.upload.DefaultUploadManager;
import io.onedev.server.web.upload.UploadManager;
import io.onedev.server.web.websocket.AlertEventBroadcaster;
import io.onedev.server.web.websocket.BuildEventBroadcaster;
import io.onedev.server.web.websocket.CodeCommentEventBroadcaster;
import io.onedev.server.web.websocket.CommitIndexedBroadcaster;
import io.onedev.server.web.websocket.DefaultWebSocketService;
import io.onedev.server.web.websocket.DefaultWebSocketManager;
import io.onedev.server.web.websocket.IssueEventBroadcaster;
import io.onedev.server.web.websocket.PullRequestEventBroadcaster;
import io.onedev.server.web.websocket.WebSocketService;
import io.onedev.server.xodus.CommitInfoService;
import io.onedev.server.xodus.DefaultCommitInfoService;
import io.onedev.server.xodus.DefaultIssueInfoService;
import io.onedev.server.xodus.DefaultPullRequestInfoService;
import io.onedev.server.xodus.DefaultVisitInfoService;
import io.onedev.server.xodus.IssueInfoService;
import io.onedev.server.xodus.PullRequestInfoService;
import io.onedev.server.xodus.VisitInfoService;
import io.onedev.server.web.websocket.WebSocketManager;
import io.onedev.server.xodus.CommitInfoManager;
import io.onedev.server.xodus.DefaultCommitInfoManager;
import io.onedev.server.xodus.DefaultIssueInfoManager;
import io.onedev.server.xodus.DefaultPullRequestInfoManager;
import io.onedev.server.xodus.DefaultVisitInfoManager;
import io.onedev.server.xodus.IssueInfoManager;
import io.onedev.server.xodus.PullRequestInfoManager;
import io.onedev.server.xodus.VisitInfoManager;
import nl.altindag.ssl.SSLFactory;
/**
@ -447,8 +429,8 @@ public class CoreModule extends AbstractPluginModule {
super.configure();
bind(ListenerRegistry.class).to(DefaultListenerRegistry.class);
bind(JettyService.class).to(DefaultJettyService.class);
bind(ServletContextHandler.class).toProvider(DefaultJettyService.class);
bind(JettyManager.class).to(DefaultJettyManager.class);
bind(ServletContextHandler.class).toProvider(DefaultJettyManager.class);
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);
@ -459,31 +441,8 @@ public class CoreModule extends AbstractPluginModule {
.messageInterpolator(new MessageInterpolator());
return configuration.buildValidatorFactory();
}).in(Singleton.class);
bind(ValidatorFactory.class).annotatedWith(Shallow.class).toProvider(() -> {
Configuration<?> configuration = Validation
.byDefaultProvider()
.configure()
.traversableResolver(new TraversableResolver() {
@Override
public boolean isReachable(Object traversableObject, Node traversableProperty,
Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
return true;
}
@Override
public boolean isCascadable(Object traversableObject, Node traversableProperty,
Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
return false;
}
})
.messageInterpolator(new MessageInterpolator());
return configuration.buildValidatorFactory();
}).in(Singleton.class);
bind(Validator.class).toProvider(ValidatorProvider.class).in(Singleton.class);
bind(Validator.class).annotatedWith(Shallow.class).toProvider(ShallowValidatorProvider.class).in(Singleton.class);
configurePersistence();
configureSecurity();
@ -497,127 +456,122 @@ public class CoreModule extends AbstractPluginModule {
* HK2 to guice bridge can only search in explicit bindings in Guice
*/
bind(SshAuthenticator.class).to(DefaultSshAuthenticator.class);
bind(SshService.class).to(DefaultSshService.class);
bind(MarkdownService.class).to(DefaultMarkdownService.class);
bind(SettingService.class).to(DefaultSettingService.class);
bind(DataService.class).to(DefaultDataService.class);
bind(SshManager.class).to(DefaultSshManager.class);
bind(MarkdownManager.class).to(DefaultMarkdownManager.class);
bind(SettingManager.class).to(DefaultSettingManager.class);
bind(DataManager.class).to(DefaultDataManager.class);
bind(TaskScheduler.class).to(DefaultTaskScheduler.class);
bind(PullRequestCommentService.class).to(DefaultPullRequestCommentService.class);
bind(CodeCommentService.class).to(DefaultCodeCommentService.class);
bind(PullRequestService.class).to(DefaultPullRequestService.class);
bind(PullRequestUpdateService.class).to(DefaultPullRequestUpdateService.class);
bind(ProjectService.class).to(DefaultProjectService.class);
bind(ProjectLastEventDateService.class).to(DefaultProjectLastEventDateService.class);
bind(UserInvitationService.class).to(DefaultUserInvitationService.class);
bind(PullRequestReviewService.class).to(DefaultPullRequestReviewService.class);
bind(BuildService.class).to(DefaultBuildService.class);
bind(BuildDependenceService.class).to(DefaultBuildDependenceService.class);
bind(JobService.class).to(DefaultJobService.class);
bind(JobCacheService.class).to(DefaultJobCacheService.class);
bind(LogService.class).to(DefaultLogService.class);
bind(MailService.class).to(DefaultMailService.class);
bind(IssueService.class).to(DefaultIssueService.class);
bind(IssueFieldService.class).to(DefaultIssueFieldService.class);
bind(BuildParamService.class).to(DefaultBuildParamService.class);
bind(UserAuthorizationService.class).to(DefaultUserAuthorizationService.class);
bind(GroupAuthorizationService.class).to(DefaultGroupAuthorizationService.class);
bind(PullRequestWatchService.class).to(DefaultPullRequestWatchService.class);
bind(RoleService.class).to(DefaultRoleService.class);
bind(CommitInfoService.class).to(DefaultCommitInfoService.class);
bind(IssueInfoService.class).to(DefaultIssueInfoService.class);
bind(VisitInfoService.class).to(DefaultVisitInfoService.class);
bind(BatchWorkExecutionService.class).to(DefaultBatchWorkExecutionService.class);
bind(WorkExecutionService.class).to(DefaultWorkExecutionService.class);
bind(GroupService.class).to(DefaultGroupService.class);
bind(IssueMentionService.class).to(DefaultIssueMentionService.class);
bind(PullRequestMentionService.class).to(DefaultPullRequestMentionService.class);
bind(CodeCommentMentionService.class).to(DefaultCodeCommentMentionService.class);
bind(MembershipService.class).to(DefaultMembershipService.class);
bind(PullRequestChangeService.class).to(DefaultPullRequestChangeService.class);
bind(CodeCommentReplyService.class).to(DefaultCodeCommentReplyService.class);
bind(CodeCommentStatusChangeService.class).to(DefaultCodeCommentStatusChangeService.class);
bind(AttachmentService.class).to(DefaultAttachmentService.class);
bind(PullRequestInfoService.class).to(DefaultPullRequestInfoService.class);
bind(PullRequestCommentManager.class).to(DefaultPullRequestCommentManager.class);
bind(CodeCommentManager.class).to(DefaultCodeCommentManager.class);
bind(PullRequestManager.class).to(DefaultPullRequestManager.class);
bind(PullRequestUpdateManager.class).to(DefaultPullRequestUpdateManager.class);
bind(ProjectManager.class).to(DefaultProjectManager.class);
bind(ProjectLastEventDateManager.class).to(DefaultProjectLastEventDateManager.class);
bind(UserInvitationManager.class).to(DefaultUserInvitationManager.class);
bind(PullRequestReviewManager.class).to(DefaultPullRequestReviewManager.class);
bind(BuildManager.class).to(DefaultBuildManager.class);
bind(BuildDependenceManager.class).to(DefaultBuildDependenceManager.class);
bind(JobManager.class).to(DefaultJobManager.class);
bind(JobCacheManager.class).to(DefaultJobCacheManager.class);
bind(LogManager.class).to(DefaultLogManager.class);
bind(MailManager.class).to(DefaultMailManager.class);
bind(IssueManager.class).to(DefaultIssueManager.class);
bind(IssueFieldManager.class).to(DefaultIssueFieldManager.class);
bind(BuildParamManager.class).to(DefaultBuildParamManager.class);
bind(UserAuthorizationManager.class).to(DefaultUserAuthorizationManager.class);
bind(GroupAuthorizationManager.class).to(DefaultGroupAuthorizationManager.class);
bind(PullRequestWatchManager.class).to(DefaultPullRequestWatchManager.class);
bind(RoleManager.class).to(DefaultRoleManager.class);
bind(CommitInfoManager.class).to(DefaultCommitInfoManager.class);
bind(IssueInfoManager.class).to(DefaultIssueInfoManager.class);
bind(VisitInfoManager.class).to(DefaultVisitInfoManager.class);
bind(BatchWorkManager.class).to(DefaultBatchWorkManager.class);
bind(WorkExecutor.class).to(DefaultWorkExecutor.class);
bind(GroupManager.class).to(DefaultGroupManager.class);
bind(IssueMentionManager.class).to(DefaultIssueMentionManager.class);
bind(PullRequestMentionManager.class).to(DefaultPullRequestMentionManager.class);
bind(CodeCommentMentionManager.class).to(DefaultCodeCommentMentionManager.class);
bind(MembershipManager.class).to(DefaultMembershipManager.class);
bind(PullRequestChangeManager.class).to(DefaultPullRequestChangeManager.class);
bind(CodeCommentReplyManager.class).to(DefaultCodeCommentReplyManager.class);
bind(CodeCommentStatusChangeManager.class).to(DefaultCodeCommentStatusChangeManager.class);
bind(AttachmentManager.class).to(DefaultAttachmentManager.class);
bind(PullRequestInfoManager.class).to(DefaultPullRequestInfoManager.class);
bind(PullRequestNotificationManager.class);
bind(CommitNotificationManager.class);
bind(BuildNotificationManager.class);
bind(PackNotificationManager.class);
bind(IssueNotificationManager.class);
bind(CodeCommentNotificationManager.class);
bind(CodeCommentService.class).to(DefaultCodeCommentService.class);
bind(AccessTokenService.class).to(DefaultAccessTokenService.class);
bind(UserService.class).to(DefaultUserService.class);
bind(IssueWatchService.class).to(DefaultIssueWatchService.class);
bind(IssueChangeService.class).to(DefaultIssueChangeService.class);
bind(IssueVoteService.class).to(DefaultIssueVoteService.class);
bind(IssueWorkService.class).to(DefaultIssueWorkService.class);
bind(IterationService.class).to(DefaultIterationService.class);
bind(IssueCommentService.class).to(DefaultIssueCommentService.class);
bind(IssueQueryPersonalizationService.class).to(DefaultIssueQueryPersonalizationService.class);
bind(PullRequestQueryPersonalizationService.class).to(DefaultPullRequestQueryPersonalizationService.class);
bind(CodeCommentQueryPersonalizationService.class).to(DefaultCodeCommentQueryPersonalizationService.class);
bind(CommitQueryPersonalizationService.class).to(DefaultCommitQueryPersonalizationService.class);
bind(BuildQueryPersonalizationService.class).to(DefaultBuildQueryPersonalizationService.class);
bind(PackQueryPersonalizationService.class).to(DefaultPackQueryPersonalizationService.class);
bind(PullRequestAssignmentService.class).to(DefaultPullRequestAssignmentService.class);
bind(SshKeyService.class).to(DefaultSshKeyService.class);
bind(BuildMetricService.class).to(DefaultBuildMetricService.class);
bind(ReferenceChangeService.class).to(DefaultReferenceChangeService.class);
bind(GitLfsLockService.class).to(DefaultGitLfsLockService.class);
bind(IssueScheduleService.class).to(DefaultIssueScheduleService.class);
bind(LinkSpecService.class).to(DefaultLinkSpecService.class);
bind(IssueLinkService.class).to(DefaultIssueLinkService.class);
bind(IssueStateHistoryService.class).to(DefaultIssueStateHistoryService.class);
bind(LinkAuthorizationService.class).to(DefaultLinkAuthorizationService.class);
bind(EmailAddressService.class).to(DefaultEmailAddressService.class);
bind(GpgKeyService.class).to(DefaultGpgKeyService.class);
bind(IssueTextService.class).to(DefaultIssueTextService.class);
bind(PullRequestTextService.class).to(DefaultPullRequestTextService.class);
bind(CodeCommentTextService.class).to(DefaultCodeCommentTextService.class);
bind(PendingSuggestionApplyService.class).to(DefaultPendingSuggestionApplyService.class);
bind(IssueAuthorizationService.class).to(DefaultIssueAuthorizationService.class);
bind(DashboardService.class).to(DefaultDashboardService.class);
bind(DashboardUserShareService.class).to(DefaultDashboardUserShareService.class);
bind(DashboardGroupShareService.class).to(DefaultDashboardGroupShareService.class);
bind(DashboardVisitService.class).to(DefaultDashboardVisitService.class);
bind(LabelSpecService.class).to(DefaultLabelSpecService.class);
bind(ProjectLabelService.class).to(DefaultProjectLabelService.class);
bind(BuildLabelService.class).to(DefaultBuildLabelService.class);
bind(PackLabelService.class).to(DefaultPackLabelService.class);
bind(PullRequestLabelService.class).to(DefaultPullRequestLabelService.class);
bind(IssueTouchService.class).to(DefaultIssueTouchService.class);
bind(PullRequestTouchService.class).to(DefaultPullRequestTouchService.class);
bind(CodeCommentTouchService.class).to(DefaultCodeCommentTouchService.class);
bind(AlertService.class).to(DefaultAlertService.class);
bind(UpdateCheckService.class).to(DefaultUpdateCheckService.class);
bind(StopwatchService.class).to(DefaultStopwatchService.class);
bind(PackService.class).to(DefaultPackService.class);
bind(PackBlobService.class).to(DefaultPackBlobService.class);
bind(PackBlobReferenceService.class).to(DefaultPackBlobReferenceService.class);
bind(AccessTokenAuthorizationService.class).to(DefaultAccessTokenAuthorizationService.class);
bind(ReviewedDiffService.class).to(DefaultReviewedDiffService.class);
bind(OAuthTokenService.class).to(DefaultOAuthTokenService.class);
bind(IssueReactionService.class).to(DefaultIssueReactionService.class);
bind(IssueCommentReactionService.class).to(DefaultIssueCommentReactionService.class);
bind(PullRequestReactionService.class).to(DefaultPullRequestReactionService.class);
bind(PullRequestCommentReactionService.class).to(DefaultPullRequestCommentReactionService.class);
bind(IssueCommentRevisionService.class).to(DefaultIssueCommentRevisionService.class);
bind(PullRequestCommentRevisionService.class).to(DefaultPullRequestCommentRevisionService.class);
bind(IssueDescriptionRevisionService.class).to(DefaultIssueDescriptionRevisionService.class);
bind(PullRequestDescriptionRevisionService.class).to(DefaultPullRequestDescriptionRevisionService.class);
bind(SsoProviderService.class).to(DefaultSsoProviderService.class);
bind(SsoAccountService.class).to(DefaultSsoAccountService.class);
bind(BaseAuthorizationService.class).to(DefaultBaseAuthorizationService.class);
bind(GroupEntitlementService.class).to(DefaultGroupEntitlementService.class);
bind(UserEntitlementService.class).to(DefaultUserEntitlementService.class);
bind(ProjectEntitlementService.class).to(DefaultProjectEntitlementService.class);
bind(CodeCommentManager.class).to(DefaultCodeCommentManager.class);
bind(AccessTokenManager.class).to(DefaultAccessTokenManager.class);
bind(UserManager.class).to(DefaultUserManager.class);
bind(IssueWatchManager.class).to(DefaultIssueWatchManager.class);
bind(IssueChangeManager.class).to(DefaultIssueChangeManager.class);
bind(IssueVoteManager.class).to(DefaultIssueVoteManager.class);
bind(IssueWorkManager.class).to(DefaultIssueWorkManager.class);
bind(IterationManager.class).to(DefaultIterationManager.class);
bind(IssueCommentManager.class).to(DefaultIssueCommentManager.class);
bind(IssueQueryPersonalizationManager.class).to(DefaultIssueQueryPersonalizationManager.class);
bind(PullRequestQueryPersonalizationManager.class).to(DefaultPullRequestQueryPersonalizationManager.class);
bind(CodeCommentQueryPersonalizationManager.class).to(DefaultCodeCommentQueryPersonalizationManager.class);
bind(CommitQueryPersonalizationManager.class).to(DefaultCommitQueryPersonalizationManager.class);
bind(BuildQueryPersonalizationManager.class).to(DefaultBuildQueryPersonalizationManager.class);
bind(PackQueryPersonalizationManager.class).to(DefaultPackQueryPersonalizationManager.class);
bind(PullRequestAssignmentManager.class).to(DefaultPullRequestAssignmentManager.class);
bind(SshKeyManager.class).to(DefaultSshKeyManager.class);
bind(BuildMetricManager.class).to(DefaultBuildMetricManager.class);
bind(ReferenceChangeManager.class).to(DefaultReferenceChangeManager.class);
bind(GitLfsLockManager.class).to(DefaultGitLfsLockManager.class);
bind(IssueScheduleManager.class).to(DefaultIssueScheduleManager.class);
bind(LinkSpecManager.class).to(DefaultLinkSpecManager.class);
bind(IssueLinkManager.class).to(DefaultIssueLinkManager.class);
bind(IssueStateHistoryManager.class).to(DefaultIssueStateHistoryManager.class);
bind(LinkAuthorizationManager.class).to(DefaultLinkAuthorizationManager.class);
bind(EmailAddressManager.class).to(DefaultEmailAddressManager.class);
bind(GpgKeyManager.class).to(DefaultGpgKeyManager.class);
bind(IssueTextManager.class).to(DefaultIssueTextManager.class);
bind(PullRequestTextManager.class).to(DefaultPullRequestTextManager.class);
bind(CodeCommentTextManager.class).to(DefaultCodeCommentTextManager.class);
bind(PendingSuggestionApplyManager.class).to(DefaultPendingSuggestionApplyManager.class);
bind(IssueAuthorizationManager.class).to(DefaultIssueAuthorizationManager.class);
bind(DashboardManager.class).to(DefaultDashboardManager.class);
bind(DashboardUserShareManager.class).to(DefaultDashboardUserShareManager.class);
bind(DashboardGroupShareManager.class).to(DefaultDashboardGroupShareManager.class);
bind(DashboardVisitManager.class).to(DefaultDashboardVisitManager.class);
bind(LabelSpecManager.class).to(DefaultLabelSpecManager.class);
bind(ProjectLabelManager.class).to(DefaultProjectLabelManager.class);
bind(BuildLabelManager.class).to(DefaultBuildLabelManager.class);
bind(PackLabelManager.class).to(DefaultPackLabelManager.class);
bind(PullRequestLabelManager.class).to(DefaultPullRequestLabelManager.class);
bind(IssueTouchManager.class).to(DefaultIssueTouchManager.class);
bind(PullRequestTouchManager.class).to(DefaultPullRequestTouchManager.class);
bind(CodeCommentTouchManager.class).to(DefaultCodeCommentTouchManager.class);
bind(AlertManager.class).to(DefaultAlertManager.class);
bind(UpdateCheckManager.class).to(DefaultUpdateCheckManager.class);
bind(StopwatchManager.class).to(DefaultStopwatchManager.class);
bind(PackManager.class).to(DefaultPackManager.class);
bind(PackBlobManager.class).to(DefaultPackBlobManager.class);
bind(PackBlobReferenceManager.class).to(DefaultPackBlobReferenceManager.class);
bind(AccessTokenAuthorizationManager.class).to(DefaultAccessTokenAuthorizationManager.class);
bind(ReviewedDiffManager.class).to(DefaultReviewedDiffManager.class);
bind(OAuthTokenManager.class).to(DefaultOAuthTokenManager.class);
bind(IssueReactionManager.class).to(DefaultIssueReactionManager.class);
bind(IssueCommentReactionManager.class).to(DefaultIssueCommentReactionManager.class);
bind(PullRequestReactionManager.class).to(DefaultPullRequestReactionManager.class);
bind(PullRequestCommentReactionManager.class).to(DefaultPullRequestCommentReactionManager.class);
bind(IssueCommentRevisionManager.class).to(DefaultIssueCommentRevisionManager.class);
bind(PullRequestCommentRevisionManager.class).to(DefaultPullRequestCommentRevisionManager.class);
bind(IssueDescriptionRevisionManager.class).to(DefaultIssueDescriptionRevisionManager.class);
bind(PullRequestDescriptionRevisionManager.class).to(DefaultPullRequestDescriptionRevisionManager.class);
bind(BaseAuthorizationManager.class).to(DefaultBaseAuthorizationManager.class);
bind(WebHookManager.class);
contribute(CodePullAuthorizationSource.class, DefaultJobService.class);
contribute(CodePullAuthorizationSource.class, DefaultJobManager.class);
bind(CodeIndexService.class).to(DefaultCodeIndexService.class);
bind(CodeSearchService.class).to(DefaultCodeSearchService.class);
bind(CodeIndexManager.class).to(DefaultCodeIndexManager.class);
bind(CodeSearchManager.class).to(DefaultCodeSearchManager.class);
Bootstrap.executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue<>()) {
@ -638,7 +592,8 @@ public class CoreModule extends AbstractPluginModule {
bind(OsInfo.class).toProvider(() -> ExecutorUtils.getOsInfo()).in(Singleton.class);
contributeFromPackage(LogInstruction.class, LogInstruction.class);
contributeFromPackage(LogInstruction.class, LogInstruction.class);
contribute(CodeProblemContribution.class, (build, blobPath, reportName) -> newArrayList());
@ -681,7 +636,7 @@ public class CoreModule extends AbstractPluginModule {
bind(GitLfsFilter.class);
bind(GitPreReceiveCallback.class);
bind(GitPostReceiveCallback.class);
bind(SignatureVerificationService.class).to(DefaultSignatureVerificationService.class);
bind(SignatureVerificationManager.class).to(DefaultSignatureVerificationManager.class);
contribute(CommandCreator.class, SshCommandCreator.class);
contributeFromPackage(SignatureVerifier.class, SignatureVerifier.class);
}
@ -694,22 +649,21 @@ public class CoreModule extends AbstractPluginModule {
contribute(JerseyConfigurator.class, resourceConfig -> resourceConfig.packages(ProjectResource.class.getPackage().getName()));
contribute(JerseyConfigurator.class, resourceConfig -> resourceConfig.register(ClusterResource.class));
contribute(JerseyConfigurator.class, resourceConfig -> resourceConfig.register(McpHelperResource.class));
contribute(JerseyConfigurator.class, resourceConfig -> resourceConfig.register(BuildSpecSchemaResource.class));
}
private void configureWeb() {
bind(WicketServlet.class).to(DefaultWicketServlet.class);
bind(WicketFilter.class).to(DefaultWicketFilter.class);
bind(EditSupportRegistry.class).to(DefaultEditSupportRegistry.class);
bind(WebSocketService.class).to(DefaultWebSocketService.class);
bind(WebSocketManager.class).to(DefaultWebSocketManager.class);
bind(SessionDataStoreFactory.class).to(DefaultSessionDataStoreFactory.class);
contributeFromPackage(EditSupport.class, EditSupport.class);
bind(org.apache.wicket.protocol.http.WebApplication.class).to(WebApplication.class);
bind(Application.class).to(WebApplication.class);
bind(AvatarService.class).to(DefaultAvatarService.class);
bind(WebSocketService.class).to(DefaultWebSocketService.class);
bind(AvatarManager.class).to(DefaultAvatarManager.class);
bind(WebSocketManager.class).to(DefaultWebSocketManager.class);
contributeFromPackage(EditSupport.class, EditSupportLocator.class);
@ -729,26 +683,24 @@ public class CoreModule extends AbstractPluginModule {
contributeFromPackage(ExceptionHandler.class, ConstraintViolationExceptionHandler.class);
contributeFromPackage(ExceptionHandler.class, PageExpiredExceptionHandler.class);
contributeFromPackage(ExceptionHandler.class, WebApplicationExceptionHandler.class);
contribute(SessionListener.class, DefaultWebSocketService.class);
bind(UrlService.class).to(DefaultUrlService.class);
bind(UrlManager.class).to(DefaultUrlManager.class);
bind(CodeCommentEventBroadcaster.class);
bind(PullRequestEventBroadcaster.class);
bind(IssueEventBroadcaster.class);
bind(BuildEventBroadcaster.class);
bind(AlertEventBroadcaster.class);
bind(UploadService.class).to(DefaultUploadService.class);
bind(UploadManager.class).to(DefaultUploadManager.class);
bind(TaskButton.TaskFutureManager.class);
}
private void configureBuild() {
bind(ResourceAllocator.class).to(DefaultResourceAllocator.class);
bind(AgentService.class).to(DefaultAgentService.class);
bind(AgentTokenService.class).to(DefaultAgentTokenService.class);
bind(AgentAttributeService.class).to(DefaultAgentAttributeService.class);
bind(AgentLastUsedDateService.class).to(DefaultAgentLastUsedDateService.class);
bind(AgentManager.class).to(DefaultAgentManager.class);
bind(AgentTokenManager.class).to(DefaultAgentTokenManager.class);
bind(AgentAttributeManager.class).to(DefaultAgentAttributeManager.class);
bind(AgentLastUsedDateManager.class).to(DefaultAgentLastUsedDateManager.class);
contribute(ScriptContribution.class, new ScriptContribution() {
@ -786,22 +738,22 @@ public class CoreModule extends AbstractPluginModule {
}
private void configurePersistence() {
bind(DataService.class).to(DefaultDataService.class);
bind(DataManager.class).to(DefaultDataManager.class);
bind(Session.class).toProvider(SessionProvider.class);
bind(EntityManager.class).toProvider(SessionProvider.class);
bind(SessionFactory.class).toProvider(SessionFactoryProvider.class);
bind(EntityManagerFactory.class).toProvider(SessionFactoryProvider.class);
bind(SessionFactoryService.class).to(DefaultSessionFactoryService.class);
bind(SessionFactoryManager.class).to(DefaultSessionFactoryManager.class);
contribute(ObjectMapperConfigurator.class, HibernateObjectMapperConfigurator.class);
bind(Interceptor.class).to(HibernateInterceptor.class);
bind(PhysicalNamingStrategy.class).toInstance(new PrefixedNamingStrategy("o_"));
bind(SessionService.class).to(DefaultSessionService.class);
bind(TransactionService.class).to(DefaultTransactionService.class);
bind(IdService.class).to(DefaultIdService.class);
bind(SessionManager.class).to(DefaultSessionManager.class);
bind(TransactionManager.class).to(DefaultTransactionManager.class);
bind(IdManager.class).to(DefaultIdManager.class);
bind(Dao.class).to(DefaultDao.class);
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

View File

@ -10,7 +10,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
@ -22,7 +21,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
@ -44,20 +43,20 @@ import io.onedev.commons.loader.AppLoader;
import io.onedev.commons.loader.ManagedSerializedForm;
import io.onedev.commons.utils.FileUtils;
import io.onedev.commons.utils.TarUtils;
import io.onedev.server.cluster.ClusterService;
import io.onedev.server.data.DataService;
import io.onedev.server.service.SettingService;
import io.onedev.server.cluster.ClusterManager;
import io.onedev.server.data.DataManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.event.ListenerRegistry;
import io.onedev.server.event.system.SystemStarted;
import io.onedev.server.event.system.SystemStarting;
import io.onedev.server.event.system.SystemStopped;
import io.onedev.server.event.system.SystemStopping;
import io.onedev.server.exception.ServerNotReadyException;
import io.onedev.server.jetty.JettyService;
import io.onedev.server.jetty.JettyManager;
import io.onedev.server.model.support.administration.SystemSetting;
import io.onedev.server.persistence.IdService;
import io.onedev.server.persistence.SessionFactoryService;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.IdManager;
import io.onedev.server.persistence.SessionFactoryManager;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.persistence.annotation.Sessional;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.taskschedule.TaskScheduler;
@ -66,60 +65,59 @@ import io.onedev.server.util.init.InitStage;
import io.onedev.server.util.init.ManualConfig;
public class OneDev extends AbstractPlugin implements Serializable, Runnable {
private static final Logger logger = LoggerFactory.getLogger(OneDev.class);
private final Provider<JettyService> jettyLauncherProvider;
private final SessionService sessionService;
private final DataService dataService;
private final Provider<JettyManager> jettyLauncherProvider;
private final SessionManager sessionManager;
private final DataManager dataManager;
private final Provider<ServerConfig> serverConfigProvider;
private final ListenerRegistry listenerRegistry;
private final TaskScheduler taskScheduler;
private final ExecutorService executorService;
private final ClusterService clusterService;
private final SettingService settingService;
private final IdService idService;
private final SessionFactoryService sessionFactoryService;
private final ClusterManager clusterManager;
private final SettingManager settingManager;
private final IdManager idManager;
private final SessionFactoryManager sessionFactoryManager;
private final Date bootDate = new Date();
private volatile InitStage initStage;
private Class<?> wrapperManagerClass;
private Class<?> wrapperManagerClass;
private volatile Thread thread;
// Some are injected via provider as instantiation might encounter problem
// during upgrade
// Some are injected via provider as instantiation might encounter problem during upgrade
@Inject
public OneDev(Provider<JettyService> jettyLauncherProvider, TaskScheduler taskScheduler,
SessionService sessionService, Provider<ServerConfig> serverConfigProvider,
DataService dataService, ExecutorService executorService,
ListenerRegistry listenerRegistry, ClusterService clusterService,
IdService idService, SessionFactoryService sessionFactoryService,
SettingService settingService) {
public OneDev(Provider<JettyManager> jettyLauncherProvider, TaskScheduler taskScheduler,
SessionManager sessionManager, Provider<ServerConfig> serverConfigProvider,
DataManager dataManager, ExecutorService executorService,
ListenerRegistry listenerRegistry, ClusterManager clusterManager,
IdManager idManager, SessionFactoryManager sessionFactoryManager,
SettingManager settingManager) {
this.jettyLauncherProvider = jettyLauncherProvider;
this.taskScheduler = taskScheduler;
this.sessionService = sessionService;
this.dataService = dataService;
this.sessionManager = sessionManager;
this.dataManager = dataManager;
this.serverConfigProvider = serverConfigProvider;
this.executorService = executorService;
this.listenerRegistry = listenerRegistry;
this.clusterService = clusterService;
this.idService = idService;
this.sessionFactoryService = sessionFactoryService;
this.settingService = settingService;
this.clusterManager = clusterManager;
this.idManager = idManager;
this.sessionFactoryManager = sessionFactoryManager;
this.settingManager = settingManager;
try {
wrapperManagerClass = Class.forName("org.tanukisoftware.wrapper.WrapperManager");
} catch (ClassNotFoundException e) {
@ -128,7 +126,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
initStage = new InitStage("Server is Starting...");
}
@Override
public void start() {
var maintenanceFile = getMaintenanceFile(Bootstrap.installDir);
@ -140,34 +138,33 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
throw new RuntimeException(e);
}
}
SecurityUtils.bindAsSystem();
System.setProperty("hsqldb.reconfig_logging", "false");
System.setProperty("hsqldb.method_class_names", "java.lang.Math");
clusterService.start();
sessionFactoryService.start();
var databasePopulated = clusterService.getHazelcastInstance().getCPSubsystem()
.getAtomicLong("databasePopulated");
// Do not use database lock as schema update will commit transaction immediately
// in MySQL
clusterService.initWithLead(databasePopulated, () -> {
try (var conn = dataService.openConnection()) {
clusterManager.start();
sessionFactoryManager.start();
var databasePopulated = clusterManager.getHazelcastInstance().getCPSubsystem().getAtomicLong("databasePopulated");
// Do not use database lock as schema update will commit transaction immediately
// in MySQL
clusterManager.initWithLead(databasePopulated, () -> {
try (var conn = dataManager.openConnection()) {
callWithTransaction(conn, () -> {
dataService.populateDatabase(conn);
dataManager.populateDatabase(conn);
return null;
});
} catch (SQLException e) {
throw new RuntimeException(e);
}
};
return 1L;
});
idManager.init();
idService.init();
sessionService.run(() -> listenerRegistry.post(new SystemStarting()));
sessionManager.run(() -> listenerRegistry.post(new SystemStarting()));
jettyLauncherProvider.get().start();
var manualConfigs = checkData();
@ -177,16 +174,16 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
else
logger.warn("Please set up the server at " + guessServerUrl());
initStage = new InitStage("Server Setup", manualConfigs);
var localServer = clusterService.getLocalServerAddress();
var localServer = clusterManager.getLocalServerAddress();
while (true) {
if (maintenanceFile.exists()) {
logger.info("Maintenance requested, trying to stop all servers...");
clusterService.submitToAllServers(() -> {
if (!localServer.equals(clusterService.getLocalServerAddress()))
clusterManager.submitToAllServers(() -> {
if (!localServer.equals(clusterManager.getLocalServerAddress()))
restart();
return null;
});
while (thread != null && clusterService.getServerAddresses().size() != 1) {
while (thread != null && clusterManager.getServerAddresses().size() != 1) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
@ -202,7 +199,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
}
if (thread == null)
return;
manualConfigs = checkData();
if (manualConfigs.isEmpty()) {
initStage = new InitStage("Please wait...");
@ -212,21 +209,21 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
}
}
}
var leadServer = clusterService.getLeaderServerAddress();
if (!leadServer.equals(clusterService.getLocalServerAddress())) {
var leadServer = clusterManager.getLeaderServerAddress();
if (!leadServer.equals(clusterManager.getLocalServerAddress())) {
logger.info("Syncing assets...");
Client client = ClientBuilder.newClient();
try {
String fromServerUrl = clusterService.getServerUrl(leadServer);
String fromServerUrl = clusterManager.getServerUrl(leadServer);
WebTarget target = client.target(fromServerUrl).path("/~api/cluster/assets");
Invocation.Builder builder = target.request();
builder.header(AUTHORIZATION,
BEARER + " " + clusterService.getCredential());
BEARER + " " + clusterManager.getCredential());
try (Response response = builder.get()) {
checkStatus(response);
try (InputStream is = response.readEntity(InputStream.class)) {
try (InputStream is = response.readEntity(InputStream.class)) {
TarUtils.untar(is, getAssetsDir(), false);
} catch (IOException e) {
throw new RuntimeException(e);
@ -236,44 +233,44 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
client.close();
}
}
// workaround for issue https://bugs.eclipse.org/bugs/show_bug.cgi?id=566170
FileStoreAttributes.setBackground(true);
taskScheduler.start();
}
@Sessional
@Override
public void postStart() {
if (thread == null)
if (thread == null)
return;
SecurityUtils.bindAsSystem();
initStage = null;
listenerRegistry.post(new SystemStarted());
clusterService.postStart();
clusterManager.postStart();
thread.start();
SystemSetting systemSetting = settingService.getSystemSetting();
SystemSetting systemSetting = settingManager.getSystemSetting();
logger.info("Server is ready at " + systemSetting.getServerUrl() + ".");
}
@Override
public void preStop() {
thread = null;
clusterService.preStop();
clusterManager.preStop();
SecurityUtils.bindAsSystem();
try {
sessionService.run(() -> listenerRegistry.post(new SystemStopping()));
sessionManager.run(() -> listenerRegistry.post(new SystemStopping()));
} catch (ServerNotReadyException ignore) {
}
}
private List<ManualConfig> checkData() {
HazelcastInstance hazelcastInstance = clusterService.getHazelcastInstance();
HazelcastInstance hazelcastInstance = clusterManager.getHazelcastInstance();
var lock = hazelcastInstance.getCPSubsystem().getLock("checkData");
lock.lock();
try {
return dataService.checkData();
return dataManager.checkData();
} finally {
lock.unlock();
}
@ -287,10 +284,10 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
taskScheduler.stop();
jettyLauncherProvider.get().stop();
sessionService.run(() -> listenerRegistry.post(new SystemStopped()));
sessionManager.run(() -> listenerRegistry.post(new SystemStopped()));
sessionFactoryService.stop();
clusterService.stop();
sessionFactoryManager.stop();
clusterManager.stop();
executorService.shutdown();
} catch (ServerNotReadyException ignore) {
}
@ -309,11 +306,11 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
return null;
}
}
public static String getK8sService() {
return System.getenv("k8s_service");
}
public String guessServerUrl() {
String serviceHost = System.getenv("ONEDEV_SERVICE_HOST");
if (serviceHost != null) {
@ -334,46 +331,40 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
return UrlUtils.toString(serverUrl);
}
}
private Url buildServerUrl(String host, String protocol, int port) {
Url serverUrl = new Url(StandardCharsets.UTF_8);
serverUrl.setHost(host);
serverUrl.setProtocol(protocol);
serverUrl.setPort(port);
Url serverUrl = new Url(StandardCharsets.UTF_8);
serverUrl.setHost(host);
serverUrl.setProtocol(protocol);
serverUrl.setPort(port);
return serverUrl;
}
/**
* This method can be called from different UI threads, so we clone initStage to
* This method can be called from different UI threads, so we clone initStage to
* make it thread-safe.
* <p>
*
* @return
* cloned initStage, or <tt>null</tt> if system initialization is
* completed
* cloned initStage, or <tt>null</tt> if system initialization is completed
*/
public @Nullable InitStage getInitStage() {
return initStage;
}
public boolean isReady() {
return initStage == null;
}
public static OneDev getInstance() {
return AppLoader.getInstance(OneDev.class);
}
public static <T> T getInstance(Class<T> type) {
return AppLoader.getInstance(type);
}
public static <T> T getInstance(Class<T> type, Class<? extends Annotation> annotationClass) {
return AppLoader.getInstance(type, annotationClass);
}
public static <T> Set<T> getExtensions(Class<T> extensionPoint) {
return AppLoader.getExtensions(extensionPoint);
}
@ -384,8 +375,8 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
public Object writeReplace() throws ObjectStreamException {
return new ManagedSerializedForm(OneDev.class);
}
}
public static boolean isServerRunning(File installDir) {
var serverConfig = new ServerConfig(installDir);
try (ServerSocket ignored = new ServerSocket(serverConfig.getClusterPort())) {
@ -395,7 +386,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
return true;
else
throw new RuntimeException(e);
}
}
}
public static File getIndexDir() {
@ -403,15 +394,15 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
FileUtils.createDir(indexDir);
return indexDir;
}
public static File getAssetsDir() {
return new File(Bootstrap.getSiteDir(), "assets");
}
public static File getMaintenanceFile(File installDir) {
return new File(installDir, "maintenance");
}
private void restart() {
if (wrapperManagerClass != null) {
try {
@ -427,17 +418,17 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
@Override
public void run() {
var localServer = clusterService.getLocalServerAddress();
var localServer = clusterManager.getLocalServerAddress();
var maintenanceFile = getMaintenanceFile(Bootstrap.installDir);
while (thread != null) {
if (maintenanceFile.exists()) {
logger.info("Maintenance requested, trying to stop all servers...");
clusterService.submitToAllServers(() -> {
if (!localServer.equals(clusterService.getLocalServerAddress()))
clusterManager.submitToAllServers(() -> {
if (!localServer.equals(clusterManager.getLocalServerAddress()))
restart();
return null;
});
while (thread != null && clusterService.getServerAddresses().size() != 1) {
while (thread != null && clusterManager.getServerAddresses().size() != 1) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
@ -445,7 +436,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
}
restart();
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {

View File

@ -1,16 +1,13 @@
package io.onedev.server;
import io.onedev.server.annotation.NoDBAccess;
import java.io.File;
public interface StorageService {
public interface StorageManager {
File initLfsDir(Long projectId);
File initArtifactsDir(Long projectId, Long buildNumber);
@NoDBAccess
File initPacksDir(Long projectId);
}

View File

@ -1,13 +1,11 @@
package io.onedev.server;
import io.onedev.server.annotation.NoDBAccess;
import org.apache.wicket.Component;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
public interface SubscriptionService {
@NoDBAccess
public interface SubscriptionManager {
boolean isSubscriptionActive();
@Nullable

View File

@ -8,7 +8,7 @@ import java.util.concurrent.ExecutorService;
import io.onedev.agent.*;
import io.onedev.commons.utils.ExceptionUtils;
import io.onedev.server.OneDev;
import io.onedev.server.service.AgentService;
import io.onedev.server.entitymanager.AgentManager;
import org.apache.commons.lang3.SerializationUtils;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
@ -24,9 +24,9 @@ import io.onedev.commons.utils.StringUtils;
import io.onedev.commons.utils.TaskLogger;
import io.onedev.server.exception.ServerNotReadyException;
import io.onedev.server.job.JobContext;
import io.onedev.server.job.JobService;
import io.onedev.server.job.JobManager;
import io.onedev.server.job.ResourceAllocator;
import io.onedev.server.job.log.LogService;
import io.onedev.server.job.log.LogManager;
import io.onedev.server.terminal.AgentShell;
@WebSocket
@ -42,7 +42,7 @@ public class ServerSocket {
public void onClose(int statusCode, String reason) {
try {
if (agentId != null)
getAgentService().agentDisconnected(agentId);
getAgentManager().agentDisconnected(agentId);
StringBuilder builder = new StringBuilder("Websocket closed (");
if (session != null && session.getRemoteAddress() != null)
@ -69,15 +69,15 @@ public class ServerSocket {
}
}
private AgentService getAgentService() {
return OneDev.getInstance(AgentService.class);
private AgentManager getAgentManager() {
return OneDev.getInstance(AgentManager.class);
}
@OnWebSocketConnect
public void onConnect(Session session) {
this.session = session;
try {
new Message(MessageTypes.UPDATE, getAgentService().getAgentVersion()).sendBy(session);
new Message(MessageTypes.UPDATE, getAgentManager().getAgentVersion()).sendBy(session);
} catch (Exception e) {
logger.error("Error sending websocket message", e);
try {
@ -98,7 +98,7 @@ public class ServerSocket {
// be assigned via Administrator
AgentData data = SerializationUtils.deserialize(message.getData());
try {
agentId = getAgentService().agentConnected(data, session);
agentId = getAgentManager().agentConnected(data, session);
} catch (Exception e) {
var explicitException = ExceptionUtils.find(e, ExplicitException.class);
if (explicitException != null) {
@ -132,7 +132,7 @@ public class ServerSocket {
if (sessionId.length() == 0)
sessionId = null;
String logMessage = StringUtils.substringAfter(remaining, ":");
TaskLogger logger = OneDev.getInstance(LogService.class).getJobLogger(jobToken);
TaskLogger logger = OneDev.getInstance(LogManager.class).getJobLogger(jobToken);
if (logger != null)
logger.log(logMessage, sessionId);
} catch (Exception e) {
@ -143,15 +143,15 @@ public class ServerSocket {
String dataString = new String(messageData, StandardCharsets.UTF_8);
String jobToken = StringUtils.substringBefore(dataString, ":");
String jobWorkspace = StringUtils.substringAfter(dataString, ":");
JobContext jobContext = getJobService().getJobContext(jobToken, false);
JobContext jobContext = getJobManager().getJobContext(jobToken, false);
if (jobContext != null)
getJobService().reportJobWorkspace(jobContext, jobWorkspace);
getJobManager().reportJobWorkspace(jobContext, jobWorkspace);
break;
case SHELL_OUTPUT:
dataString = new String(messageData, StandardCharsets.UTF_8);
String sessionId = StringUtils.substringBefore(dataString, ":");
String output = StringUtils.substringAfter(dataString, ":");
AgentShell shell = (AgentShell) getJobService().getShell(sessionId);
AgentShell shell = (AgentShell) getJobManager().getShell(sessionId);
if (shell != null)
shell.getTerminal().sendOutput(output);
break;
@ -159,13 +159,13 @@ public class ServerSocket {
dataString = new String(messageData, StandardCharsets.UTF_8);
sessionId = StringUtils.substringBefore(dataString, ":");
String error = StringUtils.substringAfter(dataString, ":");
shell = (AgentShell) getJobService().getShell(sessionId);
shell = (AgentShell) getJobManager().getShell(sessionId);
if (shell != null)
shell.getTerminal().sendError(error);
break;
case SHELL_CLOSED:
sessionId = new String(messageData, StandardCharsets.UTF_8);
shell = (AgentShell) getJobService().getShell(sessionId);
shell = (AgentShell) getJobManager().getShell(sessionId);
if (shell != null)
shell.getTerminal().close();
break;
@ -180,8 +180,8 @@ public class ServerSocket {
}
}
private JobService getJobService() {
return OneDev.getInstance(JobService.class);
private JobManager getJobManager() {
return OneDev.getInstance(JobManager.class);
}
private Serializable service(Serializable request) {

View File

@ -3,7 +3,7 @@ package io.onedev.server.agent;
import io.onedev.agent.Agent;
import io.onedev.server.OneDev;
import io.onedev.server.exception.ServerNotReadyException;
import io.onedev.server.service.AgentTokenService;
import io.onedev.server.entitymanager.AgentTokenManager;
import io.onedev.server.security.SecurityUtils;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
@ -22,11 +22,11 @@ public class ServerSocketServlet extends WebSocketServlet {
private static final long serialVersionUID = 1L;
private final AgentTokenService tokenService;
private final AgentTokenManager tokenManager;
@Inject
public ServerSocketServlet(AgentTokenService tokenService) {
this.tokenService = tokenService;
public ServerSocketServlet(AgentTokenManager tokenManager) {
this.tokenManager = tokenManager;
}
@Override
@ -43,7 +43,7 @@ public class ServerSocketServlet extends WebSocketServlet {
if (!OneDev.getInstance().isReady())
throw new ServerNotReadyException();
String tokenValue = SecurityUtils.getBearerToken(request);
if (tokenValue != null && tokenService.find(tokenValue) != null)
if (tokenValue != null && tokenManager.find(tokenValue) != null)
super.service(request, response);
else
response.sendError(SC_FORBIDDEN, "A valid agent token is expected");

View File

@ -1,90 +0,0 @@
package io.onedev.server.ai;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.onedev.server.OneDev;
import io.onedev.server.model.Issue;
import io.onedev.server.model.IssueComment;
import io.onedev.server.model.Project;
import io.onedev.server.web.UrlService;
public class IssueHelper {
private static ObjectMapper getObjectMapper() {
return OneDev.getInstance(ObjectMapper.class);
}
private static UrlService getUrlService() {
return OneDev.getInstance(UrlService.class);
}
public static Map<String, Object> getSummary(Project currentProject, Issue issue) {
var typeReference = new TypeReference<LinkedHashMap<String, Object>>() {};
var summary = getObjectMapper().convertValue(issue, typeReference);
summary.remove("id");
summary.remove("stateOrdinal");
summary.remove("uuid");
summary.remove("messageId");
summary.remove("pinDate");
summary.remove("boardPosition");
summary.remove("numberScopeId");
summary.put("reference", issue.getReference().toString(currentProject));
summary.remove("submitterId");
summary.put("submitter", issue.getSubmitter().getName());
summary.put("Project", issue.getProject().getPath());
summary.remove("lastActivity");
for (var it = summary.entrySet().iterator(); it.hasNext();) {
var entry = it.next();
if (entry.getKey().endsWith("Count"))
it.remove();
}
return summary;
}
public static List<Map<String, Object>> getComments(Issue issue) {
var comments = new ArrayList<Map<String, Object>>();
issue.getComments().stream().sorted(Comparator.comparing(IssueComment::getId)).forEach(comment -> {
var commentMap = new HashMap<String, Object>();
commentMap.put("user", comment.getUser().getName());
commentMap.put("date", comment.getDate());
commentMap.put("content", comment.getContent());
comments.add(commentMap);
});
return comments;
}
public static Map<String, Object> getDetail(Project currentProject, Issue issue) {
var detail = getSummary(currentProject, issue);
for (var entry : issue.getFieldInputs().entrySet()) {
detail.put(entry.getKey(), entry.getValue().getValues());
}
Map<String, Collection<String>> linkedIssues = new HashMap<>();
for (var link: issue.getTargetLinks()) {
linkedIssues.computeIfAbsent(link.getSpec().getName(), k -> new ArrayList<>())
.add(link.getTarget().getReference().toString(currentProject));
}
for (var link : issue.getSourceLinks()) {
if (link.getSpec().getOpposite() != null) {
linkedIssues.computeIfAbsent(link.getSpec().getOpposite().getName(), k -> new ArrayList<>())
.add(link.getSource().getReference().toString(currentProject));
} else {
linkedIssues.computeIfAbsent(link.getSpec().getName(), k -> new ArrayList<>())
.add(link.getSource().getReference().toString(currentProject));
}
}
detail.putAll(linkedIssues);
detail.put("link", getUrlService().urlFor(issue, true));
return detail;
}
}

View File

@ -1,102 +0,0 @@
package io.onedev.server.ai;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.onedev.server.OneDev;
import io.onedev.server.model.Project;
import io.onedev.server.model.PullRequest;
import io.onedev.server.model.PullRequestComment;
import io.onedev.server.model.PullRequestReview;
import io.onedev.server.web.UrlService;
public class PullRequestHelper {
private static ObjectMapper getObjectMapper() {
return OneDev.getInstance(ObjectMapper.class);
}
private static UrlService getUrlService() {
return OneDev.getInstance(UrlService.class);
}
public static Map<String, Object> getSummary(Project currentProject,
PullRequest pullRequest, boolean checkMergeConditionIfOpen) {
var typeReference = new TypeReference<LinkedHashMap<String, Object>>() {};
var summary = getObjectMapper().convertValue(pullRequest, typeReference);
summary.remove("id");
if (pullRequest.isOpen() && checkMergeConditionIfOpen) {
var errorMessage = pullRequest.checkMergeCondition();
if (errorMessage != null)
summary.put("status", PullRequest.Status.OPEN.name() + " (" + errorMessage + ")");
else
summary.put("status", PullRequest.Status.OPEN.name() + " (ready to merge)");
}
summary.remove("uuid");
summary.remove("buildCommitHash");
summary.remove("submitTimeGroups");
summary.remove("closeTimeGroups");
summary.remove("checkError");
summary.remove("numberScopeId");
summary.put("reference", pullRequest.getReference().toString(currentProject));
summary.remove("submitterId");
summary.put("submitter", pullRequest.getSubmitter().getName());
summary.put("targetProject", pullRequest.getTarget().getProject().getPath());
if (pullRequest.getSourceProject() != null)
summary.put("sourceProject", pullRequest.getSourceProject().getPath());
summary.remove("codeCommentsUpdateDate");
summary.remove("lastActivity");
for (var it = summary.entrySet().iterator(); it.hasNext();) {
var entry = it.next();
if (entry.getKey().endsWith("Count"))
it.remove();
}
return summary;
}
public static Map<String, Object> getDetail(Project currentProject, PullRequest pullRequest) {
var detail = getSummary(currentProject, pullRequest, true);
detail.put("headCommitHash", pullRequest.getLatestUpdate().getHeadCommitHash());
detail.put("assignees", pullRequest.getAssignees().stream().map(it->it.getName()).collect(Collectors.toList()));
var reviews = new ArrayList<Map<String, Object>>();
for (var review : pullRequest.getReviews()) {
if (review.getStatus() == PullRequestReview.Status.EXCLUDED)
continue;
var reviewMap = new HashMap<String, Object>();
reviewMap.put("reviewer", review.getUser().getName());
reviewMap.put("status", review.getStatus());
reviews.add(reviewMap);
}
detail.put("reviews", reviews);
var builds = new ArrayList<String>();
for (var build : pullRequest.getBuilds()) {
builds.add(build.getReference().toString(currentProject) + " (job: " + build.getJobName() + ", status: " + build.getStatus() + ")");
}
detail.put("builds", builds);
detail.put("labels", pullRequest.getLabels().stream().map(it->it.getSpec().getName()).collect(Collectors.toList()));
detail.put("link", getUrlService().urlFor(pullRequest, true));
return detail;
}
public static List<Map<String, Object>> getComments(PullRequest pullRequest) {
var comments = new ArrayList<Map<String, Object>>();
pullRequest.getComments().stream().sorted(Comparator.comparing(PullRequestComment::getId)).forEach(comment -> {
var commentMap = new HashMap<String, Object>();
commentMap.put("user", comment.getUser().getName());
commentMap.put("date", comment.getDate());
commentMap.put("content", comment.getContent());
comments.add(commentMap);
});
return comments;
}
}

View File

@ -1,639 +0,0 @@
package io.onedev.server.ai;
import static java.util.stream.Collectors.joining;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import io.onedev.server.OneDev;
import io.onedev.server.model.Agent;
import io.onedev.server.model.Build;
import io.onedev.server.model.Issue;
import io.onedev.server.model.LabelSpec;
import io.onedev.server.model.Pack;
import io.onedev.server.model.Project;
import io.onedev.server.model.PullRequest;
import io.onedev.server.model.support.issue.field.spec.BooleanField;
import io.onedev.server.model.support.issue.field.spec.BuildChoiceField;
import io.onedev.server.model.support.issue.field.spec.CommitField;
import io.onedev.server.model.support.issue.field.spec.DateField;
import io.onedev.server.model.support.issue.field.spec.DateTimeField;
import io.onedev.server.model.support.issue.field.spec.FloatField;
import io.onedev.server.model.support.issue.field.spec.GroupChoiceField;
import io.onedev.server.model.support.issue.field.spec.IntegerField;
import io.onedev.server.model.support.issue.field.spec.IssueChoiceField;
import io.onedev.server.model.support.issue.field.spec.IterationChoiceField;
import io.onedev.server.model.support.issue.field.spec.PullRequestChoiceField;
import io.onedev.server.model.support.issue.field.spec.TextField;
import io.onedev.server.model.support.issue.field.spec.choicefield.ChoiceField;
import io.onedev.server.model.support.issue.field.spec.userchoicefield.UserChoiceField;
import io.onedev.server.model.support.pullrequest.MergeStrategy;
import io.onedev.server.pack.PackSupport;
import io.onedev.server.service.AgentAttributeService;
import io.onedev.server.service.AgentService;
import io.onedev.server.service.LabelSpecService;
import io.onedev.server.service.LinkSpecService;
import io.onedev.server.service.SettingService;
public class QueryDescriptions {
private static String REACTION_CRITERIAS = """
| '"Reaction: Thumbs Up Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Thumbs Up Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Thumbs Down Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Thumbs Down Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Smile Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Smile Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Tada Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Tada Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Confused Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Confused Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Heart Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Heart Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Rocket Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Rocket Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Reaction: Eyes Count"' 'is' ('not')? '"'Number'"'
| '"Reaction: Eyes Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
""".trim();
private static SettingService getSettingService() {
return OneDev.getInstance(SettingService.class);
}
private static LinkSpecService getLinkSpecService() {
return OneDev.getInstance(LinkSpecService.class);
}
public static String getIssueQueryDescription() {
var settingService = getSettingService();
var linkSpecService = getLinkSpecService();
var fieldCriterias = new ArrayList<String>();
var choiceFieldValueRules = new ArrayList<String>();
int choiceFieldValueRuleIndex = 0;
for (var field: settingService.getIssueSetting().getFieldSpecs()) {
if (field instanceof ChoiceField) {
var choiceField = (ChoiceField) field;
var fieldValueRuleName = "ChoiceFieldValue" + (choiceFieldValueRuleIndex++);
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'" + fieldValueRuleName + "'\"'");
choiceFieldValueRules.add(choiceField.getPossibleValues().stream().map(it->"'" + it.replace("'", "\\'") + "'").collect(joining("\n | ")));
} else if (field instanceof UserChoiceField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'LoginNameOfUser'\"'");
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? 'me'");
} else if (field instanceof GroupChoiceField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'GroupName'\"'");
} else if (field instanceof BooleanField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'('true'|'false')'\"'");
} else if (field instanceof DateField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('before'|'after') '\"'DateDescription'\"'");
} else if (field instanceof DateTimeField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('before'|'after') '\"'DateTimeDescription'\"'");
} else if (field instanceof IntegerField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'Integer'\"'");
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('greater'|'less') 'than' '\"'Integer'\"'");
} else if (field instanceof FloatField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('greater'|'less') 'than' '\"'Float'\"'");
} else if (field instanceof TextField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'Text'\"'");
fieldCriterias.add("'\"" + field.getName() + "\"' 'contains' '\"'Text'\"'");
} else if (field instanceof PullRequestChoiceField || field instanceof BuildChoiceField || field instanceof IssueChoiceField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'EntityReference'\"'");
} else if (field instanceof CommitField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'CommitReference'\"'");
} else if (field instanceof IterationChoiceField) {
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? '\"'IterationNameOrPattern'\"'");
}
fieldCriterias.add("'\"" + field.getName() + "\"' 'is' ('not')? 'empty'");
}
var linkCriterias = new ArrayList<String>();
for (var linkSpec: linkSpecService.query()) {
linkCriterias.add("'any' '\"" + linkSpec.getName() + "\"' 'matching' '('criteria')'");
linkCriterias.add("'all' '\"" + linkSpec.getName() + "\"' 'matching' '('criteria')'");
linkCriterias.add("'has any' '\"" + linkSpec.getName() + "\"'");
if (linkSpec.getOpposite() != null) {
linkCriterias.add("'any' '\"" + linkSpec.getOpposite().getName() + "\"' 'matching' '('criteria')'");
linkCriterias.add("'all' '\"" + linkSpec.getOpposite().getName() + "\"' 'matching' '('criteria')'");
linkCriterias.add("'has any' '\"" + linkSpec.getOpposite().getName() + "\"'");
}
}
var description = String.format("""
A structured query should conform to below ANTLR grammar:
issueQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: '"Number"' 'is' ('not')? '"'EntityReference'"'
| '"Number"' 'is' ('greater'|'less') 'than' '"'EntityReference'"'
| '"State"' 'is' ('not')? '"'StateName'"'
| '"State"' 'is' ('after'|'before') '"'StateName'"'
%s
%s
| 'submitted by' '"'LoginNameOfUser'"'
| 'submitted by me'
| 'watched by' '"'LoginNameOfUser'"'
| 'watched by me'
| 'ignored by' '"'LoginNameOfUser'"'
| 'ignored by me'
| 'commented by' '"'LoginNameOfUser'"'
| 'commented by me'
| 'mentioned' '"'LoginNameOfUser'"'
| 'mentioned me'
| 'fixed in commit' '"'CommitReference'"'
| 'fixed in current commit'
| 'fixed in build' '"'EntityReference'"'
| 'fixed in current build'
| 'fixed in pull request' '"'EntityReference'"'
| 'fixed in current pull request'
| 'fixed between' revision 'and' revision
| '"Submit Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Last Activity Date"' 'is' ('until'|'since') '"'DateDescription'"'
| 'confidential'
| '"Spent Time"' 'is' ('greater'|'less') 'than' '"'TimePeriodDescription'"'
| '"Spent Time"' 'is' ('not')? '"'TimePeriodDescription'"'
| '"Estimated Time"' 'is' ('greater'|'less') 'than' '"'TimePeriodDescription'"'
| '"Estimated Time"' 'is' ('not')? '"'TimePeriodDescription'"'
| '"Progress"' 'is' ('greater'|'less') 'than' '"'Float'"'
| '"Iteration"' 'is' ('not')? '"'IterationNameOrPattern'"'
| '"Iteration"' 'is' ('not')? 'empty'
| '"Title"' 'contains' '"'Text'"'
| '"Description"' 'contains' '"'Text'"'
| '"Comment"' 'contains' '"'Text'"'
| '"Comment Count"' 'is' ('not')? '"'Number'"'
| '"Comment Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Vote Count"' 'is' ('not')? '"'Number'"'
| '"Vote Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
%s
| '"Project"' 'is current'
| '"Project"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
StateName
: %s
;
%s
revision
: 'commit' '"'CommitReference'"'
| 'build' '"'EntityReference'"'
| 'branch' '"'BranchReference'"'
| 'tag' '"'TagReference'"'
;
EntityReference
: '#'Number
| ProjectPath'#'Number
| ProjectKey'-'Number
;
CommitReference
: (ProjectPath':')?CommitHash
;
BranchReference
: (ProjectPath':')?BranchName
;
TagReference
: (ProjectPath':')?TagName
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible issues""",
fieldCriterias.stream().map(it->" | " + it + "\n").collect(joining("")).trim(),
linkCriterias.stream().map(it->" | " + it + "\n").collect(joining("")).trim(),
REACTION_CRITERIAS,
settingService.getIssueSetting().getStateSpecs().stream().map(it->"'" + it.getName() + "'").collect(joining("\n | ")).trim(),
IntStream.range(0, choiceFieldValueRules.size()).mapToObj(i -> "ChoiceFieldValue" + i + "\n : " + choiceFieldValueRules.get(i) + "\n ;\n\n").collect(joining("")).trim(),
Issue.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
public static String getPullRequestQueryDescription() {
var description = String.format("""
A structured query should conform to below ANTLR grammar:
pullRequestQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: '"Number"' 'is' ('not')? '"'EntityReference'"'
| '"Number"' 'is' ('greater'|'less') 'than' '"'EntityReference'"'
| 'open'
| 'merged'
| 'discarded'
| '"Source Branch"' 'is' ('not')? '"'BranchNameOrPattern'"'
| '"Souce Project"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| '"Target Branch"' 'is' ('not')? '"'BranchNameOrPattern'"'
| '"Merge Strategy"' 'is' ('not')? '"'MergeStrategy'"'
| '"Label"' 'is' ('not')? '"'LabelName'"'
| 'ready to merge'
| 'has pending reviews'
| 'has unsuccessful builds'
| 'has unfinished builds'
| 'has merge conflicts'
| 'assigned to' '"'LoginNameOfUser'"'
| 'approved by' '"'LoginNameOfUser'"'
| 'to be reviewed by' '"'LoginNameOfUser'"'
| 'to be changed by' '"'LoginNameOfUser'"'
| 'to be merged by' '"'LoginNameOfUser'"'
| 'requested for changes by' '"'LoginNameOfUser'"'
| 'need action of' '"'LoginNameOfUser'"'
| 'assigned to me'
| 'approved by me'
| 'to be reviewed by me'
| 'to be changed by me'
| 'to be merged by me'
| 'requested for changes by me'
| 'someone requested for changes'
| 'mentioned' '"'LoginNameOfUser'"'
| 'mentioned me'
| 'need action of' '"'LoginNameOfUser'"'
| 'need my action'
| 'submitted by' '"'LoginNameOfUser'"'
| 'submitted by me'
| '"Submit Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Last Activity Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Close Date"' 'is' ('until'|'since') '"'DateDescription'"'
| 'includes issue' '"'EntityReference'"'
| 'includes commit' '"'CommitReference'"'
| '"Title"' 'contains' '"'Text'"'
| '"Description"' 'contains' '"'Text'"'
| '"Comment"' 'contains' '"'Text'"'
| '"Comment Count"' 'is' ('not')? '"'Number'"'
| '"Comment Count"' 'is' ('greater'|'less') 'than' '"'Number'"'
%s
| '"Project"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| 'watched by' '"'LoginNameOfUser'"'
| 'watched by me'
| 'ignored by' '"'LoginNameOfUser'"'
| 'ignored by me'
| 'commented by' '"'LoginNameOfUser'"'
| 'commented by me'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
EntityReference
: '#'Number
| ProjectPath'#'Number
| ProjectKey'-'Number
;
CommitReference
: (ProjectPath':')?CommitHash
;
BranchReference
: (ProjectPath':')?BranchName
;
TagReference
: (ProjectPath':')?TagName
;
MergeStrategy
: %s
;
LabelName
: %s
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible pull requests""",
REACTION_CRITERIAS,
Arrays.stream(MergeStrategy.values()).map(it->"'" + it.name() + "'").collect(joining("\n | ")).trim(),
getLabelSpecs().stream().map(it->"'" + it.getName() + "'").collect(joining("\n | ")).trim(),
PullRequest.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
public static String getBuildQueryDescription() {
var description = String.format("""
A structured query should conform to below ANTLR grammar:
buildQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: '"Number"' 'is' ('not')? '"'EntityReference'"'
| '"Number"' 'is' ('greater'|'less') 'than' '"'EntityReference'"'
| 'sucessful'
| 'failed'
| 'cancelled'
| 'timed out'
| 'finished'
| 'running'
| 'waiting'
| 'pending'
| 'submitted by' '"'LoginNameOfUser'"'
| 'submitted by me'
| 'cancelled by' '"'LoginNameOfUser'"'
| 'cancelled by me'
| 'depends on' '"'EntityReference'"'
| 'dependencies of' '"'EntityReference'"'
| 'ran on' '"'AgentName'"'
| 'fixed issue' '"'EntityReference'"'
| '"Project"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| '"Job"' 'is' ('not')? '"'JobNameOrPattern'"'
| '"Version"' 'is' ('not')? '"'VersionNameOrPattern'"'
| '"Branch"' 'is' ('not')? '"'BranchNameOrPattern'"'
| '"Tag"' 'is' ('not')? '"'TagNameOrPattern'"'
| '"Param"' 'is' ('not')? '"'ParamName'"'
| '"Label"' 'is' ('not')? '"'LabelName'"'
| '"Pull Request"' 'is' ('not')? '"'EntityReference'"'
| '"Commit"' 'is' ('not')? '"'CommitReference'"'
| '"Submit Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Pending Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Running Date"' 'is' ('until'|'since') '"'DateDescription'"'
| '"Finish Date"' 'is' ('until'|'since') '"'DateDescription'"'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
EntityReference
: '#'Number
| ProjectPath'#'Number
| ProjectKey'-'Number
;
CommitReference
: (ProjectPath':')?CommitHash
;
LabelName
: %s
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible builds""",
getLabelSpecs().stream().map(it->"'" + it.getName() + "'").collect(joining("\n | ")).trim(),
Build.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
private static List<LabelSpec> getLabelSpecs() {
return OneDev.getInstance(LabelSpecService.class).query();
}
public static String getPackQueryDescription() {
var packSupports = new ArrayList<>(OneDev.getExtensions(PackSupport.class));
var description = String.format("""
A structured query should conform to below ANTLR grammar:
packQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: 'published by me'
| 'published by user' '"'LoginNameOfUser'"'
| 'published by build' '"'EntityReference'"'
| 'published by project' '"'ProjectPathOrPattern'"'
| '"Project"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| '"Type"' 'is' ('not')? '"'PackType'"'
| '"Name"' 'is' ('not')? '"'PackName'"'
| '"Version"' 'is' ('not')? '"'PackVersion'"'
| '"Label"' 'is' ('not')? '"'LabelName'"'
| '"Publish Date"' 'is' ('until'|'since') '"'DateDescription'"'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
EntityReference
: '#'Number
| ProjectPath'#'Number
| ProjectKey'-'Number
;
PackType
: %s
;
LabelName
: %s
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible packages""",
packSupports.stream().map(it->"'" + it.getPackType() + "'").collect(joining("\n | ")).trim(),
getLabelSpecs().stream().map(it->"'" + it.getName() + "'").collect(joining("\n | ")).trim(),
Pack.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
public static String getCommitQueryDescription() {
var description = """
A structured query should conform to below ANTLR grammar:
commitQuery
: criteria+
;
criteria
: ('before('|'after(') DateDescription ')'
| 'committer(' CommitterNameAndEmail ')' // committer is specified user
| 'author(' AuthorNameAndEmail ')' // author is specified user
| 'message(' Text ')' // commit message contains specified text
| 'path(' FilePath ')' // commit touches specified file
| 'authored-by-me'
| 'committed-by-me'
| ('until')? revision // until specified revision
| 'since' revision // since specified revision
;
revision
: 'commit(' CommitHash ')'
| 'build(' '#'Number ')'
| 'branch(' BranchName ')'
| 'tag(' TagName ')'
| 'default-branch'
;
WS
: [ ]+ -> skip
;
""";
return description;
}
public static String getProjectQueryDescription() {
var description = String.format("""
A structured query should conform to below ANTLR grammar:
projectQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: 'owned by' '"'LoginNameOfUser'"'
| 'owned by me'
| 'owned by none'
| 'has outdated replicas'
| 'without enough replicas'
| 'missing storage'
| 'children of' '"'ProjectPathOrPattern'"'
| 'forks of' '"'ProjectPathOrPattern'"'
| 'roots'
| 'leafs'
| 'fork roots'
| '"Name"' 'is' ('not')? '"'ProjectNameOrPattern'"'
| '"Key"' 'is' ('not')? '"'ProjectKeyOrPattern'"'
| '"Path"' 'is' ('not')? '"'ProjectPathOrPattern'"'
| '"Label"' 'is' ('not')? '"'LabelName'"'
| '"Description"' 'contains' '"'Text'"'
| '"Id"' 'is' ('not')? '"'Number'"'
| '"Id"' 'is' ('greater'|'less') 'than' '"'Number'"'
| '"Service Desk Email Address"' 'is' ('not')? '"'EmailAddressOrPattern'"'
| '"Last Activity Date"' 'is' ('until'|'since') '"'DateDescription'"'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
LabelName
: %s
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible projects""",
getLabelSpecs().stream().map(it->"'" + it.getName() + "'").collect(joining("\n | ")).trim(),
Project.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
public static String getAgentQueryDescription() {
var agentService = OneDev.getInstance(AgentService.class);
var attributeService = OneDev.getInstance(AgentAttributeService.class);
var description = String.format("""
A structured query should conform to below ANTLR grammar:
agentQuery
: criteria ('order by' '"'OrderField'"' ('asc'|'desc') (',' '"'OrderField'"' ('asc'|'desc'))*)?
;
criteria
: 'online'
| 'offline'
| 'paused'
| 'has running builds'
| 'has attribute' '"'AttributeName'"'
| 'not used since' '"'DateDescription'"'
| 'ever used since' '"'DateDescription'"'
| 'ran build' '"'EntityReference'"'
| '"Name"' 'is' ('not')? '"'AgentNameOrPattern'"'
| '"Ip Address"' 'is' ('not')? '"'IPAddressOrPattern'"'
| '"Os"' 'is' ('not')? '"'(OsName|OsNamePattern)'"'
| '"Os Arch"' 'is' ('not')? '"'(OsArch|OsArchPattern)'"'
| '"Os Version"' 'is' ('not')? '"'OsVersionOrPattern'"'
| '"'AttributeName'"' 'is' ('not')? '"'AttributeValue'"'
| criteria 'and' criteria
| criteria 'or' criteria
| 'not('criteria')'
| '('criteria')'
;
OsName
: %s
;
OsArch
: %s
;
AttributeName
: %s
;
OrderField
: %s
;
WS
: [ ]+ -> skip
;
Please note:
1. "LoginNameOfUser" should be retrieved via tool 'getLoginName' if available, with parameter set to user name
2. Use an empty query to list all accessible agents""",
agentService.getOsNames().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim(),
agentService.getOsArchs().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim(),
attributeService.getAttributeNames().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim(),
Agent.SORT_FIELDS.keySet().stream().map(it->"'" + it + "'").collect(joining("\n | ")).trim());
return description;
}
}

View File

@ -1,18 +0,0 @@
package io.onedev.server.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface DependsOn {
String property();
String value() default "";
boolean inverse() default false;
}

View File

@ -1,4 +0,0 @@
package io.onedev.server.annotation;
public @interface NoDBAccess {
}

View File

@ -1,12 +0,0 @@
package io.onedev.server.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.google.inject.BindingAnnotation;
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface Shallow {
}

View File

@ -6,7 +6,7 @@ import java.util.List;
import io.onedev.server.util.artifact.FileInfo;
public interface AttachmentService {
public interface AttachmentManager {
File getAttachmentGroupDir(Long projectId, String attachmentGroup);

View File

@ -45,12 +45,12 @@ import io.onedev.commons.utils.FileUtils;
import io.onedev.commons.utils.StringUtils;
import io.onedev.commons.utils.TarUtils;
import io.onedev.k8shelper.KubernetesHelper;
import io.onedev.server.cluster.ClusterService;
import io.onedev.server.cluster.ClusterManager;
import io.onedev.server.cluster.ClusterRunnable;
import io.onedev.server.cluster.ClusterTask;
import io.onedev.server.service.IssueService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.SettingService;
import io.onedev.server.entitymanager.IssueManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.event.Listen;
import io.onedev.server.event.entity.EntityRemoved;
import io.onedev.server.event.project.build.BuildSubmitted;
@ -74,7 +74,7 @@ import io.onedev.server.event.system.SystemStopping;
import io.onedev.server.model.Issue;
import io.onedev.server.model.support.issue.changedata.IssueDescriptionChangeData;
import io.onedev.server.model.support.pullrequest.changedata.PullRequestDescriptionChangeData;
import io.onedev.server.persistence.TransactionService;
import io.onedev.server.persistence.TransactionManager;
import io.onedev.server.persistence.annotation.Sessional;
import io.onedev.server.persistence.annotation.Transactional;
import io.onedev.server.persistence.dao.Dao;
@ -82,14 +82,14 @@ import io.onedev.server.taskschedule.SchedulableTask;
import io.onedev.server.taskschedule.TaskScheduler;
import io.onedev.server.util.IOUtils;
import io.onedev.server.util.artifact.FileInfo;
import io.onedev.server.util.concurrent.BatchWorkExecutionService;
import io.onedev.server.util.concurrent.BatchWorkManager;
import io.onedev.server.util.concurrent.BatchWorker;
import io.onedev.server.util.concurrent.Prioritized;
@Singleton
public class DefaultAttachmentService implements AttachmentService, SchedulableTask, Serializable {
public class DefaultAttachmentManager implements AttachmentManager, SchedulableTask, Serializable {
private static final Logger logger = LoggerFactory.getLogger(DefaultAttachmentService.class);
private static final Logger logger = LoggerFactory.getLogger(DefaultAttachmentManager.class);
private static final long TEMP_PRESERVE_PERIOD = 24*3600*1000L;
@ -98,40 +98,47 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
private static final String PERMANENT = "permanent";
private static final String TEMP = "temp";
@Inject
private Dao dao;
@Inject
private TransactionService transactionService;
@Inject
private TaskScheduler taskScheduler;
@Inject
private ProjectService projectService;
@Inject
private ClusterService clusterService;
@Inject
private SettingService settingService;
@Inject
private IssueService issueService;
@Inject
private BatchWorkExecutionService batchWorkExecutionService;
private volatile String taskId;
private final Dao dao;
private final TransactionManager transactionManager;
private final TaskScheduler taskScheduler;
private final ProjectManager projectManager;
private final ClusterManager clusterManager;
private final SettingManager settingManager;
private final IssueManager issueManager;
private final BatchWorkManager batchWorkManager;
private String taskId;
@Inject
public DefaultAttachmentManager(Dao dao, TransactionManager transactionManager,
TaskScheduler taskScheduler, SettingManager settingManager,
ProjectManager projectManager, ClusterManager clusterManager,
IssueManager issueManager, BatchWorkManager batchWorkManager) {
this.dao = dao;
this.transactionManager = transactionManager;
this.taskScheduler = taskScheduler;
this.settingManager = settingManager;
this.projectManager = projectManager;
this.clusterManager = clusterManager;
this.issueManager = issueManager;
this.batchWorkManager = batchWorkManager;
}
public Object writeReplace() throws ObjectStreamException {
return new ManagedSerializedForm(AttachmentService.class);
return new ManagedSerializedForm(AttachmentManager.class);
}
@Override
public File getAttachmentGroupDir(Long projectId, String attachmentGroup) {
File baseDir = projectService.getAttachmentDir(projectId);
File baseDir = projectManager.getAttachmentDir(projectId);
File groupDir = getPermanentAttachmentGroupDir(baseDir, attachmentGroup);
if (groupDir.exists())
return groupDir;
@ -144,11 +151,11 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
public void on(IssuesMoved event) {
Long sourceProjectId = event.getSourceProject().getId();
Long targetProjectId = event.getProject().getId();
File targetBaseDir = projectService.getAttachmentDir(targetProjectId);
File targetBaseDir = projectManager.getAttachmentDir(targetProjectId);
String sourceActiveServer = projectService.getActiveServer(sourceProjectId, true);
if (sourceActiveServer.equals(clusterService.getLocalServerAddress())) {
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
String sourceActiveServer = projectManager.getActiveServer(sourceProjectId, true);
if (sourceActiveServer.equals(clusterManager.getLocalServerAddress())) {
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
for (Long issueId: event.getIssueIds()) {
Issue issue = dao.load(Issue.class, issueId);
String attachmentGroup = issue.getAttachmentGroup();
@ -177,8 +184,8 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
} finally {
FileUtils.deleteDir(tempGroupDir);
}
projectService.directoryModified(targetProjectId, sourceGroupDir.getParentFile());
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
projectManager.directoryModified(targetProjectId, sourceGroupDir.getParentFile());
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
}
} else {
Collection<String> attachmentGroups = new HashSet<>();
@ -204,22 +211,22 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
} finally {
FileUtils.deleteDir(tempGroupDir);
}
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
}
projectService.runOnActiveServer(sourceProjectId, new ClusterTask<Void>() {
projectManager.runOnActiveServer(sourceProjectId, new ClusterTask<Void>() {
private static final long serialVersionUID = 1L;
@Override
public Void call() {
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
for (var attachmentGroup: attachmentGroups) {
var sourceGroupDir = getPermanentAttachmentGroupDir(sourceBaseDir, attachmentGroup);
write(getAttachmentLockName(sourceProjectId, attachmentGroup), () -> {
FileUtils.deleteDir(sourceGroupDir);
return null;
});
projectService.directoryModified(sourceProjectId, sourceGroupDir.getParentFile());
projectManager.directoryModified(sourceProjectId, sourceGroupDir.getParentFile());
}
return null;
}
@ -234,11 +241,11 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
Long sourceProjectId = event.getSourceProject().getId();
Long targetProjectId = event.getProject().getId();
File targetBaseDir = projectService.getAttachmentDir(targetProjectId);
File targetBaseDir = projectManager.getAttachmentDir(targetProjectId);
String sourceActiveServer = projectService.getActiveServer(sourceProjectId, true);
if (sourceActiveServer.equals(clusterService.getLocalServerAddress())) {
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
String sourceActiveServer = projectManager.getActiveServer(sourceProjectId, true);
if (sourceActiveServer.equals(clusterManager.getLocalServerAddress())) {
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
for (var entry: event.getIssueIdMapping().entrySet()) {
Issue sourceIssue = dao.load(Issue.class, entry.getKey());
Issue targetIssue = dao.load(Issue.class, entry.getValue());
@ -266,7 +273,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
} finally {
FileUtils.deleteDir(tempGroupDir);
}
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
}
} else {
for (var entry: event.getIssueIdMapping().entrySet()) {
@ -289,7 +296,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
} finally {
FileUtils.deleteDir(tempGroupDir);
}
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
}
}
@ -299,13 +306,13 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
Long sourceProjectId, String sourceAttachmentGroup) {
Client client = ClientBuilder.newClient();
try {
String fromServerUrl = clusterService.getServerUrl(sourceActiveServer);
String fromServerUrl = clusterManager.getServerUrl(sourceActiveServer);
WebTarget target = client.target(fromServerUrl).path("/~api/cluster/attachments")
.queryParam("projectId", sourceProjectId)
.queryParam("attachmentGroup", sourceAttachmentGroup);
Invocation.Builder builder = target.request();
builder.header(AUTHORIZATION,
BEARER + " " + clusterService.getCredential());
BEARER + " " + clusterManager.getCredential());
try (Response response = builder.get()) {
KubernetesHelper.checkStatus(response);
@ -326,7 +333,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
}
private void permanentizeAttachmentGroup(Long projectId, String attachmentGroup) {
var baseAttachmentDir = projectService.getAttachmentDir(projectId);
var baseAttachmentDir = projectManager.getAttachmentDir(projectId);
write(getAttachmentLockName(projectId, attachmentGroup), () -> {
File permanentStorage = getPermanentAttachmentGroupDir(baseAttachmentDir, attachmentGroup);
if (!permanentStorage.exists()) {
@ -340,7 +347,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
} else {
FileUtils.createDir(permanentStorage);
}
projectService.directoryModified(projectId, permanentStorage);
projectManager.directoryModified(projectId, permanentStorage);
}
return null;
});
@ -359,13 +366,13 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public void execute() {
batchWorkExecutionService.submit(new BatchWorker("attachment-manager-house-keeping") {
batchWorkManager.submit(new BatchWorker("attachment-manager-house-keeping") {
@Override
public void doWorks(List<Prioritized> works) {
for (var projectId: projectService.getActiveIds()) {
for (var projectId: projectManager.getActiveIds()) {
try {
File tempAttachmentBase = new File(projectService.getAttachmentDir(projectId), TEMP);
File tempAttachmentBase = new File(projectManager.getAttachmentDir(projectId), TEMP);
if (tempAttachmentBase.exists()) {
for (File attachmentGroupDir: tempAttachmentBase.listFiles()) {
if (System.currentTimeMillis() - attachmentGroupDir.lastModified() > TEMP_PRESERVE_PERIOD) {
@ -391,7 +398,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Sessional
public void on(IssuesImported event) {
for (var issueId: event.getIssueIds()) {
var issue = issueService.load(issueId);
var issue = issueManager.load(issueId);
var attachmentGroup = issue.getAttachmentGroup();
permanentizeAttachmentGroup(issue.getProject().getId(), attachmentGroup);
}
@ -498,15 +505,15 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
if (event.getEntity() instanceof AttachmentStorageSupport) {
AttachmentStorageSupport storageSupport = (AttachmentStorageSupport) event.getEntity();
Long projectId = storageSupport.getAttachmentProject().getId();
String activeServer = projectService.getActiveServer(projectId, false);
String activeServer = projectManager.getActiveServer(projectId, false);
if (activeServer != null) {
transactionService.runAfterCommit(new ClusterRunnable() {
transactionManager.runAfterCommit(new ClusterRunnable() {
private static final long serialVersionUID = 1L;
@Override
public void run() {
clusterService.runOnServer(activeServer, new ClusterTask<Void>() {
clusterManager.runOnServer(activeServer, new ClusterTask<Void>() {
private static final long serialVersionUID = 1L;
@ -515,10 +522,10 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
var attachmentGroup = storageSupport.getAttachmentGroup();
return write(getAttachmentLockName(projectId, attachmentGroup), () -> {
File attachmentDir = getPermanentAttachmentGroupDir(
projectService.getAttachmentDir(storageSupport.getAttachmentProject().getId()),
projectManager.getAttachmentDir(storageSupport.getAttachmentProject().getId()),
attachmentGroup);
FileUtils.deleteDir(attachmentDir);
projectService.directoryModified(projectId, attachmentDir.getParentFile());
projectManager.directoryModified(projectId, attachmentDir.getParentFile());
return null;
});
}
@ -534,21 +541,21 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public String saveAttachment(Long projectId, String attachmentGroup, String preferredAttachmentName,
InputStream attachmentStream) {
String activeServer = projectService.getActiveServer(projectId, true);
if (activeServer.equals(clusterService.getLocalServerAddress())) {
String activeServer = projectManager.getActiveServer(projectId, true);
if (activeServer.equals(clusterManager.getLocalServerAddress())) {
return saveAttachmentLocal(projectId, attachmentGroup, preferredAttachmentName, attachmentStream);
} else {
Client client = ClientBuilder.newClient();
client.property(ClientProperties.REQUEST_ENTITY_PROCESSING, "CHUNKED");
try {
String serverUrl = clusterService.getServerUrl(activeServer);
String serverUrl = clusterManager.getServerUrl(activeServer);
WebTarget target = client.target(serverUrl)
.path("~api/cluster/attachment")
.queryParam("projectId", projectId)
.queryParam("attachmentGroup", attachmentGroup)
.queryParam("suggestedAttachmentName", preferredAttachmentName);
var builder = target.request();
builder.header(AUTHORIZATION, BEARER + " " + clusterService.getCredential());
builder.header(AUTHORIZATION, BEARER + " " + clusterManager.getCredential());
StreamingOutput os = output -> {
try {
@ -591,7 +598,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
index++;
}
long maxUploadFileSize = settingService.getPerformanceSetting().getMaxUploadFileSize() * 1024L * 1024L;
long maxUploadFileSize = settingManager.getPerformanceSetting().getMaxUploadFileSize() * 1024L * 1024L;
Exception ex = null;
File file = new File(attachmentDir, attachmentName);
@ -616,7 +623,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
throw ExceptionUtils.unchecked(ex);
} else {
if (!attachmentDir.getParentFile().getName().equals(TEMP))
projectService.directoryModified(projectId, attachmentDir);
projectManager.directoryModified(projectId, attachmentDir);
return file.getName();
}
});
@ -629,7 +636,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public FileInfo getAttachmentInfo(Long projectId, String attachmentGroup, String attachment) {
return projectService.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
return projectManager.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
File attachmentFile = new File(getAttachmentGroupDir(projectId, attachmentGroup), attachment);
if (!attachmentFile.exists())
throw new FileNotFoundException("Attachment not found: " + attachment);
@ -640,12 +647,12 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public void deleteAttachment(Long projectId, String attachmentGroup, String attachment) {
projectService.runOnActiveServer(projectId, () -> write(getAttachmentLockName(projectId, attachmentGroup), () -> {
projectManager.runOnActiveServer(projectId, () -> write(getAttachmentLockName(projectId, attachmentGroup), () -> {
var attachmentGroupDir = getAttachmentGroupDir(projectId, attachmentGroup);
File attachmentFile = new File(attachmentGroupDir, attachment);
if (attachmentFile.exists()) {
FileUtils.deleteFile(attachmentFile);
projectService.directoryModified(projectId, attachmentGroupDir);
projectManager.directoryModified(projectId, attachmentGroupDir);
}
return null;
}));
@ -653,7 +660,7 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public List<FileInfo> listAttachments(Long projectId, String attachmentGroup) {
return projectService.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
return projectManager.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
List<FileInfo> attachments = new ArrayList<>();
File attachmentGroupDir = getAttachmentGroupDir(projectId, attachmentGroup);
if (attachmentGroupDir.exists()) {
@ -669,12 +676,12 @@ public class DefaultAttachmentService implements AttachmentService, SchedulableT
@Override
public void syncAttachments(Long projectId, String activeServer) {
var permanent = ATTACHMENT_DIR + "/" + PERMANENT;
projectService.syncDirectory(projectId, permanent, prefix -> {
projectManager.syncDirectory(projectId, permanent, prefix -> {
var prefixPath = permanent + "/" + prefix;
projectService.syncDirectory(projectId, prefixPath, attachmentGroup -> {
projectManager.syncDirectory(projectId, prefixPath, attachmentGroup -> {
var attachmentGroupPath = permanent + "/" + prefix + "/" + attachmentGroup;
var lockName = getAttachmentLockName(projectId, attachmentGroup);
projectService.syncDirectory(projectId, attachmentGroupPath, lockName, activeServer);
projectManager.syncDirectory(projectId, attachmentGroupPath, lockName, activeServer);
}, activeServer);
}, activeServer);
}

View File

@ -11,9 +11,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import io.onedev.server.OneDev;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.web.resource.AttachmentResource;
import io.onedev.server.web.resource.AttachmentResourceReference;
@ -44,21 +44,21 @@ public class ProjectAttachmentSupport implements AttachmentSupport {
@Override
public List<String> getAttachments() {
return getAttachmentService().listAttachments(projectId, attachmentGroup).stream()
return getAttachmentManager().listAttachments(projectId, attachmentGroup).stream()
.map(it->it.getPath()).collect(Collectors.toList());
}
private ProjectService getProjectService() {
return OneDev.getInstance(ProjectService.class);
private ProjectManager getProjectManager() {
return OneDev.getInstance(ProjectManager.class);
}
private AttachmentService getAttachmentService() {
return OneDev.getInstance(AttachmentService.class);
private AttachmentManager getAttachmentManager() {
return OneDev.getInstance(AttachmentManager.class);
}
@Override
public void deleteAttachemnt(String attachment) {
getAttachmentService().deleteAttachment(projectId, attachmentGroup, attachment);
getAttachmentManager().deleteAttachment(projectId, attachmentGroup, attachment);
}
@Override
@ -67,18 +67,18 @@ public class ProjectAttachmentSupport implements AttachmentSupport {
}
protected Project getProject() {
SessionService sessionService = OneDev.getInstance(SessionService.class);
sessionService.openSession();
SessionManager sessionManager = OneDev.getInstance(SessionManager.class);
sessionManager.openSession();
try {
return getProjectService().load(projectId);
return getProjectManager().load(projectId);
} finally {
sessionService.closeSession();
sessionManager.closeSession();
}
}
@Override
public String saveAttachment(String suggestedAttachmentName, InputStream attachmentStream) {
return getAttachmentService().saveAttachment(
return getAttachmentManager().saveAttachment(
projectId, attachmentGroup, suggestedAttachmentName, attachmentStream);
}

View File

@ -1,42 +1,10 @@
package io.onedev.server.buildspec;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.Validator;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.wicket.Component;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import io.onedev.commons.codeassist.InputCompletion;
import io.onedev.commons.codeassist.InputStatus;
import io.onedev.commons.codeassist.InputSuggestion;
@ -59,11 +27,27 @@ import io.onedev.server.data.migration.XmlBuildSpecMigrator;
import io.onedev.server.job.JobAuthorizationContext;
import io.onedev.server.model.Project;
import io.onedev.server.model.support.build.JobProperty;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.util.ComponentContext;
import io.onedev.server.validation.Validatable;
import io.onedev.server.web.page.project.blob.ProjectBlobPage;
import io.onedev.server.web.util.SuggestionUtils;
import io.onedev.server.web.util.WicketUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.wicket.Component;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.nodes.*;
import javax.annotation.Nullable;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
@Editable
@ClassValidating
@ -121,7 +105,6 @@ public class BuildSpec implements Serializable, Validatable {
private transient Map<String, JobProperty> propertyMap;
@Editable
@Valid
public List<Job> getJobs() {
return jobs;
}
@ -132,7 +115,6 @@ public class BuildSpec implements Serializable, Validatable {
}
@Editable
@Valid
public List<StepTemplate> getStepTemplates() {
return stepTemplates;
}
@ -143,7 +125,6 @@ public class BuildSpec implements Serializable, Validatable {
}
@Editable
@Valid
public List<Service> getServices() {
return services;
}
@ -154,7 +135,6 @@ public class BuildSpec implements Serializable, Validatable {
}
@Editable
@Valid
public List<JobProperty> getProperties() {
return properties;
}
@ -165,7 +145,6 @@ public class BuildSpec implements Serializable, Validatable {
}
@Editable
@Valid
public List<Import> getImports() {
return imports;
}
@ -185,7 +164,8 @@ public class BuildSpec implements Serializable, Validatable {
Collection<String> newCommitChain = new HashSet<>(commitChain);
newCommitChain.add(importCommit.name());
BuildSpec importedBuildSpec = aImport.getBuildSpec();
JobAuthorizationContext.push(new JobAuthorizationContext(aImport.getProject(), importCommit, null));
JobAuthorizationContext.push(new JobAuthorizationContext(
aImport.getProject(), importCommit, SecurityUtils.getUser(), null));
try {
importedBuildSpecs.addAll(importedBuildSpec.getImportedBuildSpecs(newCommitChain));
} finally {
@ -291,10 +271,27 @@ public class BuildSpec implements Serializable, Validatable {
return isValid;
}
private Validator getValidator() {
return OneDev.getInstance(Validator.class);
}
@Override
public boolean isValid(ConstraintValidatorContext context) {
boolean isValid = true;
int index = 0;
for (Job job: jobs) {
for (ConstraintViolation<Job> violation: getValidator().validate(job)) {
context.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(PROP_JOBS)
.addBeanNode()
.inIterable().atIndex(index)
.addConstraintViolation();
isValid = false;
}
index++;
}
Set<String> jobNames = new HashSet<>();
for (Job job: jobs) {
if (!jobNames.add(job.getName())) {
@ -303,6 +300,19 @@ public class BuildSpec implements Serializable, Validatable {
isValid = false;
}
}
index = 0;
for (Service service: services) {
for (ConstraintViolation<Service> violation: getValidator().validate(service)) {
context.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(PROP_SERVICES)
.addBeanNode()
.inIterable().atIndex(index)
.addConstraintViolation();
isValid = false;
}
index++;
}
Set<String> serviceNames = new HashSet<>();
for (Service service: services) {
@ -312,6 +322,19 @@ public class BuildSpec implements Serializable, Validatable {
isValid = false;
}
}
index = 0;
for (StepTemplate stepTemplate: stepTemplates) {
for (ConstraintViolation<StepTemplate> violation: getValidator().validate(stepTemplate)) {
context.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(PROP_STEP_TEMPLATES)
.addBeanNode()
.inIterable().atIndex(index)
.addConstraintViolation();
isValid = false;
}
index++;
}
Set<String> stepTemplateNames = new HashSet<>();
for (StepTemplate template: stepTemplates) {
@ -321,6 +344,19 @@ public class BuildSpec implements Serializable, Validatable {
isValid = false;
}
}
index = 0;
for (JobProperty property: properties) {
for (ConstraintViolation<JobProperty> violation: getValidator().validate(property)) {
context.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(PROP_PROPERTIES)
.addBeanNode()
.inIterable().atIndex(index)
.addConstraintViolation();
isValid = false;
}
index++;
}
Set<String> propertyNames = new HashSet<>();
for (JobProperty property : properties) {
@ -330,6 +366,20 @@ public class BuildSpec implements Serializable, Validatable {
isValid = false;
}
}
index = 0;
for (Import aImport: getImports()) {
Validator validator = OneDev.getInstance(Validator.class);
for (ConstraintViolation<Import> violation: validator.validate(aImport)) {
context.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(PROP_IMPORTS)
.addBeanNode()
.inIterable().atIndex(index)
.addConstraintViolation();
isValid = false;
}
index++;
}
Set<String> importProjectAndRevisions = new HashSet<>();
for (Import aImport: imports) {
@ -2262,136 +2312,4 @@ public class BuildSpec implements Serializable, Validatable {
});
}
@SuppressWarnings("unused")
private void migrate41(VersionedYamlDoc doc, Stack<Integer> versions) {
for (NodeTuple specTuple: doc.getValue()) {
String specKey = ((ScalarNode)specTuple.getKeyNode()).getValue();
if (specKey.equals("jobs")) {
SequenceNode jobsNode = (SequenceNode) specTuple.getValueNode();
for (Node jobsNodeItem: jobsNode.getValue()) {
MappingNode jobNode = (MappingNode) jobsNodeItem;
for (var itJobTuple = jobNode.getValue().iterator(); itJobTuple.hasNext();) {
var jobTuple = itJobTuple.next();
var keyNode = (ScalarNode) jobTuple.getKeyNode();
if (keyNode.getValue().equals("retryCondition")) {
var valueNode = (ScalarNode) jobTuple.getValueNode();
if (valueNode.getValue().equals("never")) {
itJobTuple.remove();
}
}
}
}
}
}
}
@SuppressWarnings("unused")
private void migrate42(VersionedYamlDoc doc, Stack<Integer> versions) {
migrate42_processNode(doc);
}
private void migrate42_processNode(Node node) {
if (node instanceof MappingNode) {
MappingNode mappingNode = (MappingNode) node;
if (mappingNode.getTag() != null && !mappingNode.getTag().equals(Tag.MAP)
&& mappingNode.getTag().getValue().startsWith("!")) {
var tagValue = mappingNode.getTag().getValue().substring(1);
boolean hasTypeTuple = false;
for (NodeTuple tuple : mappingNode.getValue()) {
if (tuple.getKeyNode() instanceof ScalarNode) {
ScalarNode keyNode = (ScalarNode) tuple.getKeyNode();
if ("type".equals(keyNode.getValue())) {
hasTypeTuple = true;
break;
}
}
}
if (!hasTypeTuple) {
mappingNode.getValue().add(0, new NodeTuple(
new ScalarNode(Tag.STR, "type"),
new ScalarNode(Tag.STR, tagValue)));
}
mappingNode.setTag(Tag.MAP);
}
for (NodeTuple tuple : mappingNode.getValue()) {
migrate42_processNode(tuple.getKeyNode());
migrate42_processNode(tuple.getValueNode());
}
} else if (node instanceof SequenceNode) {
SequenceNode sequenceNode = (SequenceNode) node;
for (Node item : sequenceNode.getValue()) {
migrate42_processNode(item);
}
}
}
@SuppressWarnings("unused")
private void migrate43(VersionedYamlDoc doc, Stack<Integer> versions) {
for (NodeTuple specTuple: doc.getValue()) {
String specKey = ((ScalarNode)specTuple.getKeyNode()).getValue();
if (specKey.equals("jobs")) {
SequenceNode jobsNode = (SequenceNode) specTuple.getValueNode();
for (Node jobsNodeItem: jobsNode.getValue()) {
MappingNode jobNode = (MappingNode) jobsNodeItem;
boolean hasRetryCondition = false;
for (var itJobTuple = jobNode.getValue().iterator(); itJobTuple.hasNext();) {
var jobTuple = itJobTuple.next();
var keyNode = (ScalarNode) jobTuple.getKeyNode();
if (keyNode.getValue().equals("retryCondition")) {
var valueNode = (ScalarNode) jobTuple.getValueNode();
if (StringUtils.isBlank(valueNode.getValue())) {
itJobTuple.remove();
} else {
hasRetryCondition = true;
}
break;
} else if (keyNode.getValue().equals("triggers")) {
SequenceNode triggersNode = (SequenceNode) jobTuple.getValueNode();
for (Node triggerNode: triggersNode.getValue()) {
MappingNode triggerMappingNode = (MappingNode) triggerNode;
boolean hasUserMatch = false;
String triggerType = null;
for (var triggerTuple: triggerMappingNode.getValue()) {
String triggerTupleKey = ((ScalarNode)triggerTuple.getKeyNode()).getValue();
if (triggerTupleKey.equals("type")) {
triggerType = ((ScalarNode)triggerTuple.getValueNode()).getValue();
break;
}
}
if ("BranchUpdateTrigger".equals(triggerType)) {
for (var itTriggerTuple = triggerMappingNode.getValue().iterator(); itTriggerTuple.hasNext();) {
var triggerTuple = itTriggerTuple.next();
String triggerTupleKey = ((ScalarNode)triggerTuple.getKeyNode()).getValue();
if (triggerTupleKey.equals("userMatch")) {
var valueNode = (ScalarNode) triggerTuple.getValueNode();
if (StringUtils.isBlank(valueNode.getValue())) {
itTriggerTuple.remove();
} else {
hasUserMatch = true;
}
break;
}
}
if (!hasUserMatch) {
triggerMappingNode.getValue().add(new NodeTuple(
new ScalarNode(Tag.STR, "userMatch"),
new ScalarNode(Tag.STR, "anyone")));
}
}
}
}
}
if (!hasRetryCondition) {
jobNode.getValue().add(new NodeTuple(
new ScalarNode(Tag.STR, "retryCondition"),
new ScalarNode(Tag.STR, "never")));
}
}
}
}
}
}

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
public interface BuildSpecAware {

View File

@ -1,487 +0,0 @@
package io.onedev.server.buildspec;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import io.onedev.commons.loader.ImplementationRegistry;
import io.onedev.commons.utils.ClassUtils;
import io.onedev.commons.utils.ExplicitException;
import io.onedev.commons.utils.StringUtils;
import io.onedev.server.annotation.Code;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.ImplementationProvider;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.Multiline;
import io.onedev.server.annotation.Patterns;
import io.onedev.server.annotation.RetryCondition;
import io.onedev.server.annotation.UserMatch;
import io.onedev.server.buildspec.job.Job;
import io.onedev.server.data.migration.MigrationHelper;
import io.onedev.server.model.support.build.JobProperty;
import io.onedev.server.rest.annotation.Api;
import io.onedev.server.util.Pair;
import io.onedev.server.util.ReflectionUtils;
import io.onedev.server.util.patternset.PatternSet;
import io.onedev.server.web.editable.BeanDescriptor;
import io.onedev.server.web.editable.EditableUtils;
import io.onedev.server.web.editable.PropertyDescriptor;
@Api(internal = true)
@Path("/build-spec-schema.yml")
@Consumes(MediaType.APPLICATION_JSON)
@Produces("application/x-yaml")
@Singleton
public class BuildSpecSchemaResource {
private final ImplementationRegistry implementationRegistry;
private volatile String schema;
@Inject
public BuildSpecSchemaResource(ImplementationRegistry implementationRegistry) {
this.implementationRegistry = implementationRegistry;
}
private void processProperty(Map<String, Object> currentNode, Object bean, PropertyDescriptor property) {
var descriptionSections = new ArrayList<String>();
var descriptionSection = property.getDescription();
if (descriptionSection != null)
descriptionSections.add(descriptionSection);
var getter = property.getPropertyGetter();
var returnType = property.getPropertyClass();
if (returnType == String.class) {
if (getter.getAnnotation(Code.class) == null && getter.getAnnotation(Multiline.class) == null) {
descriptionSections.add("NOTE: If set, the value can only contain one line");
}
InputStream grammarStream = null;
try {
if (getter.getAnnotation(Patterns.class) != null) {
if (getter.getAnnotation(Interpolative.class) != null) {
grammarStream = PatternSet.class.getResourceAsStream("InterpolativePatternSet.g4");
} else {
grammarStream = PatternSet.class.getResourceAsStream("PatternSet.g4");
}
} else if (getter.getAnnotation(RetryCondition.class) != null) {
grammarStream = io.onedev.server.buildspec.job.retrycondition.RetryCondition.class.getResourceAsStream("RetryCondition.g4");
} else if (getter.getAnnotation(UserMatch.class) != null) {
grammarStream = io.onedev.server.util.usermatch.UserMatch.class.getResourceAsStream("UserMatch.g4");
}
if (grammarStream != null) {
try {
var grammar = IOUtils.toString(grammarStream, StandardCharsets.UTF_8);
descriptionSections.add("NOTE: If set, the value should conform with below ANTLR v4 grammar:\n\n" + grammar);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} finally {
IOUtils.closeQuietly(grammarStream);
}
}
if (descriptionSections.size() != 0)
currentNode.put("description", StringUtils.join(descriptionSections, "\n\n"));
Class<?> elementClass = null;
if (Collection.class.isAssignableFrom(returnType)) {
elementClass = ReflectionUtils.getCollectionElementClass(property.getPropertyGetter().getGenericReturnType());
if (elementClass == null)
throw new ExplicitException("Unknown collection element class (bean: " + property.getBeanClass() + ", property: " + property.getPropertyName() + ")");
processCollectionProperty(currentNode, elementClass);
} else {
processType(currentNode, returnType);
}
Object defaultValue;
var value = property.getPropertyValue(bean);
if (value instanceof Integer) {
var intValue = (Integer) value;
if (intValue == 0)
defaultValue = null;
else
defaultValue = intValue;
} else if (value instanceof Long) {
var longValue = (Long) value;
if (longValue == 0)
defaultValue = null;
else
defaultValue = longValue;
} else if (value instanceof Double) {
var doubleValue = (Double) value;
if (doubleValue == 0)
defaultValue = null;
else
defaultValue = doubleValue;
} else if (value instanceof Float) {
var floatValue = (Float) value;
if (floatValue == 0)
defaultValue = null;
else
defaultValue = floatValue;
} else if (value instanceof Boolean) {
var booleanValue = (Boolean) value;
if (!booleanValue)
defaultValue = null;
else
defaultValue = booleanValue;
} else if (value instanceof Enum) {
var enumValue = (Enum<?>) value;
defaultValue = enumValue.name();
} else if (value instanceof String || value instanceof Date) {
defaultValue = value;
} else {
defaultValue = null;
}
if (defaultValue != null) {
currentNode.put("default", defaultValue);
}
}
private Object newBean(Class<?> beanClass) {
try {
return beanClass.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private void processBean(Map<String, Object> currentNode, Class<?> beanClass,
Collection<Class<?>> implementations, Set<String> processedProperties) {
var propsNode = (Map<String, Object>) currentNode.get("properties");
if (propsNode == null) {
propsNode = new HashMap<>();
}
var requiredNode = (List<String>) currentNode.get("required");
if (requiredNode == null) {
requiredNode = new ArrayList<>();
}
var beanDescriptor = new BeanDescriptor(beanClass);
var propertyMap = new HashMap<String, PropertyDescriptor>();
for (var groupProperties: beanDescriptor.getProperties().values()) {
for (var property: groupProperties) {
propertyMap.put(property.getPropertyName(), property);
}
}
/*
* As long as one implementation overrides a property in base class, we will exclude the property from
* common property section, and add it individually to each implementation's property section to avoid
* defining same property both in common section and oneOf section
*/
var excludedProperties = new HashSet<String>();
Map<String, byte[]> valueBytesMap = new HashMap<>();
Object bean = null;
for (var implementation: implementations) {
bean = newBean(implementation);
for (var groupProperties: new BeanDescriptor(implementation).getProperties().values()) {
for (var property: groupProperties) {
if (!excludedProperties.contains(property.getPropertyName())
&& propertyMap.containsKey(property.getPropertyName())
&& property.getBeanClass() != beanClass) {
excludedProperties.add(property.getPropertyName());
}
if (!excludedProperties.contains(property.getPropertyName())) {
var value = property.getPropertyValue(bean);
var lastValueBytes = valueBytesMap.get(property.getPropertyName());
if (lastValueBytes == null) {
lastValueBytes = SerializationUtils.serialize((Serializable) value);
valueBytesMap.put(property.getPropertyName(), lastValueBytes);
} else if (!Arrays.equals(lastValueBytes, SerializationUtils.serialize((Serializable) value))) {
excludedProperties.add(property.getPropertyName());
}
}
}
}
}
if (bean == null) {
bean = newBean(beanClass);
}
var dependents = new ArrayList<Pair<PropertyDescriptor, DependsOn>>();
for (var groupProperties: beanDescriptor.getProperties().values()) {
for (var property: groupProperties) {
if (!excludedProperties.contains(property.getPropertyName()) && processedProperties.add(property.getPropertyName())) {
if (property.getPropertyName().equals("type"))
throw new ExplicitException("Property 'type' is reserved (class: " + beanClass.getName() + ")");
var dependsOn = property.getPropertyGetter().getAnnotation(DependsOn.class);
if (dependsOn != null) {
dependents.add(new Pair<>(property, dependsOn));
} else {
if (property.isPropertyRequired())
requiredNode.add(property.getPropertyName());
var propNode = new HashMap<String, Object>();
propsNode.put(property.getPropertyName(), propNode);
processProperty(propNode, bean, property);
}
}
}
}
if (!dependents.isEmpty()) {
var allOfNode = new ArrayList<Map<String, Object>>();
currentNode.put("allOf", allOfNode);
for (var dependent: dependents) {
var allOfItemNode = new HashMap<String, Object>();
allOfNode.add(allOfItemNode);
var dependsOn = dependent.getRight();
var dependencyProperty = propertyMap.get(dependsOn.property());
if (dependencyProperty == null)
throw new ExplicitException("Dependency property not found: " + dependsOn.property());
var ifNode = new HashMap<String, Object>();
allOfItemNode.put("if", ifNode);
var ifPropsNode = new HashMap<String, Object>();
ifNode.put("properties", ifPropsNode);
var dependencyPropertyNode = new HashMap<String, Object>();
ifPropsNode.put(dependencyProperty.getPropertyName(), dependencyPropertyNode);
var inverse = dependsOn.inverse();
var dependencyPropertyClass = dependencyProperty.getPropertyClass();
if (dependencyPropertyClass == boolean.class) {
if (dependsOn.value().length() != 0) {
dependencyPropertyNode.put("const", Boolean.parseBoolean(dependsOn.value()));
} else {
dependencyPropertyNode.put("const", true);
}
} else if (dependencyPropertyClass == int.class || dependencyPropertyClass == long.class
|| dependencyPropertyClass == double.class || dependencyPropertyClass == float.class) {
if (dependsOn.value().length() != 0) {
dependencyPropertyNode.put("const", Integer.parseInt(dependsOn.value()));
} else {
dependencyPropertyNode.put("const", 0);
inverse = !inverse;
}
} else {
if (dependsOn.value().length() != 0) {
if (dependencyPropertyClass == Boolean.class)
dependencyPropertyNode.put("const", Boolean.parseBoolean(dependsOn.value()));
else if (dependencyPropertyClass == Integer.class || dependencyPropertyClass == Long.class || dependencyPropertyClass == Double.class || dependencyPropertyClass == Float.class)
dependencyPropertyNode.put("const", Integer.parseInt(dependsOn.value()));
else
dependencyPropertyNode.put("const", dependsOn.value());
} else {
var typeList = new ArrayList<String>();
typeList.add("object");
typeList.add("string");
typeList.add("integer");
typeList.add("number");
typeList.add("boolean");
dependencyPropertyNode.put("type", typeList);
}
}
Map<String, Object> branchNode;
if (!inverse) {
branchNode = new HashMap<>();
allOfItemNode.put("then", branchNode);
} else {
branchNode = new HashMap<>();
allOfItemNode.put("else", branchNode);
}
var property = dependent.getLeft();
var branchPropsNode = new HashMap<String, Object>();
branchNode.put("properties", branchPropsNode);
var propNode = new HashMap<String, Object>();
branchPropsNode.put(property.getPropertyName(), propNode);
processProperty(propNode, bean, property);
if (property.isPropertyRequired()) {
var requiredList = new ArrayList<String>();
requiredList.add(property.getPropertyName());
branchNode.put("required", requiredList);
}
}
}
if (!propsNode.isEmpty())
currentNode.put("properties", propsNode);
if (!requiredNode.isEmpty())
currentNode.put("required", requiredNode);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void processType(Map<String, Object> currentNode, Class<?> type) {
if (type == String.class) {
currentNode.put("type", "string");
} else if (type == Boolean.class || type == boolean.class) {
currentNode.put("type", "boolean");
} else if (type == Integer.class || type == int.class || type == Long.class || type == long.class) {
currentNode.put("type", "integer");
} else if (type == Float.class || type == float.class || type == Double.class || type == double.class) {
currentNode.put("type", "number");
} else if (Enum.class.isAssignableFrom(type)) {
currentNode.put("type", "string");
var enumList = new ArrayList<String>();
var enumClass = (Class<Enum>) type;
for (var enumValue: EnumSet.allOf(enumClass)) {
enumList.add(((Enum) enumValue).name());
}
currentNode.put("enum", enumList);
} else if (type == Date.class) {
currentNode.put("type", "string");
currentNode.put("format", "date-time");
} else if (type.getAnnotation(Editable.class) != null) {
if (ClassUtils.isConcrete(type)) {
currentNode.put("type", "object");
processBean(currentNode, type, new ArrayList<>(), new HashSet<>());
currentNode.put("additionalProperties", false);
} else {
processPolymorphic(currentNode, type);
}
} else {
throw new ExplicitException("Unsupported type: " + type);
}
}
@SuppressWarnings("unchecked")
private void processPolymorphic(Map<String, Object> currentNode, Class<?> baseClass) {
Collection<Class<?>> implementations = new ArrayList<>();
var implementationProvider = baseClass.getAnnotation(ImplementationProvider.class);
if (implementationProvider != null)
implementations.addAll((Collection<? extends Class<? extends Serializable>>) ReflectionUtils.invokeStaticMethod(baseClass, implementationProvider.value()));
else
implementations.addAll(implementationRegistry.getImplementations(baseClass));
currentNode.put("type", "object");
var propsNode = new HashMap<String, Object>();
var typeNode = new HashMap<String, Object>();
typeNode.put("type", "string");
propsNode.put("type", typeNode);
currentNode.put("properties", propsNode);
var enumList = new ArrayList<String>();
typeNode.put("enum", enumList);
var requiredList = new ArrayList<String>();
requiredList.add("type");
currentNode.put("required", requiredList);
var processedProperties = new HashSet<String>();
processBean(currentNode, baseClass, implementations, processedProperties);
var oneOfList = new ArrayList<Map<String, Object>>();
currentNode.put("oneOf", oneOfList);
for (var implementation: implementations) {
enumList.add(implementation.getSimpleName());
var oneOfItemNode = new HashMap<String, Object>();
var oneOfItemPropsNode = new HashMap<String, Object>();
var typeConstNode = new HashMap<String, Object>();
typeConstNode.put("const", implementation.getSimpleName());
oneOfItemPropsNode.put("type", typeConstNode);
oneOfItemNode.put("properties", oneOfItemPropsNode);
var description = EditableUtils.getDescription(implementation);
if (description != null)
oneOfItemNode.put("description", description);
processBean(oneOfItemNode, implementation, new ArrayList<>(), new HashSet<>(processedProperties));
oneOfList.add(oneOfItemNode);
}
}
private void processCollectionProperty(Map<String, Object> currentNode, Class<?> collectionElementClass) {
currentNode.put("type", "array");
var itemsNode = new HashMap<String, Object>();
currentNode.put("items", itemsNode);
if (Collection.class.isAssignableFrom(collectionElementClass)) {
itemsNode.put("type", "array");
var nestedItemsNode = new HashMap<String, Object>();
nestedItemsNode.put("type", "string");
itemsNode.put("items", nestedItemsNode);
} else {
processType(itemsNode, collectionElementClass);
}
}
@GET
@SuppressWarnings("unchecked")
public String getBuildSpecSchema() {
if (schema == null) {
var rootNode = new HashMap<String, Object>();
rootNode.put("$schema", "https://json-schema.org/draft/2020-12/schema");
rootNode.put("title", "YAML schema of build spec file");
rootNode.put("type", "object");
var propsNode = new HashMap<String, Object>();
rootNode.put("properties", propsNode);
var versionNode = new HashMap<String, Object>();
propsNode.put("version", versionNode);
versionNode.put("type", "integer");
versionNode.put("const", Integer.parseInt(MigrationHelper.getVersion(BuildSpec.class)));
var jobsNode = new HashMap<String, Object>();
propsNode.put("jobs", jobsNode);
processCollectionProperty(jobsNode, Job.class);
var servicesNode = new HashMap<String, Object>();
propsNode.put("services", servicesNode);
processCollectionProperty(servicesNode, Service.class);
var propertiesNode = new HashMap<String, Object>();
propsNode.put("properties", propertiesNode);
processCollectionProperty(propertiesNode, JobProperty.class);
var importsNode = new HashMap<String, Object>();
propsNode.put("imports", importsNode);
processCollectionProperty(importsNode, Import.class);
var jobPropsNode = (Map<String, Object>) ((Map<String, Object>) jobsNode.get("items")).get("properties");
var stepTemplatesNode = new HashMap<String, Object>();
propsNode.put("stepTemplates", stepTemplatesNode);
stepTemplatesNode.put("type", "array");
var stepTemplateNode = new HashMap<String, Object>();
stepTemplatesNode.put("items", stepTemplateNode);
stepTemplateNode.put("type", "object");
var stepTemplatePropsNode = new HashMap<String, Object>();
stepTemplateNode.put("properties", stepTemplatePropsNode);
stepTemplatePropsNode.put("steps", jobPropsNode.get("steps"));
stepTemplatePropsNode.put("paramSpecs", jobPropsNode.get("paramSpecs"));
var requiredList = new ArrayList<String>();
requiredList.add("version");
rootNode.put("required", requiredList);
rootNode.put("additionalProperties", false);
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(true);
schema = new Yaml(options).dump(rootNode);
}
return schema;
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
import java.util.Stack;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
@ -30,7 +30,7 @@ import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.ClassValidating;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.job.JobAuthorizationContext;
import io.onedev.server.model.Project;
import io.onedev.server.security.SecurityUtils;
@ -64,7 +64,7 @@ public class Import implements Serializable, Validatable {
private transient BuildSpec buildSpec;
private static ThreadLocal<Stack<String>> IMPORT_CHAIN = ThreadLocal.withInitial(Stack::new);
private static ThreadLocal<Stack<String>> importChain = ThreadLocal.withInitial(Stack::new);
// change Named("projectPath") also if change name of this property
@Editable(order=100, name="Project", description="Specify project to import build spec from")
@ -80,13 +80,13 @@ public class Import implements Serializable, Validatable {
@SuppressWarnings("unused")
private static List<String> getProjectChoices() {
ProjectService projectService = OneDev.getInstance(ProjectService.class);
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
Project project = ((ProjectPage)WicketUtils.getPage()).getProject();
Collection<Project> projects = SecurityUtils.getAuthorizedProjects(new AccessProject());
projects.remove(project);
ProjectCache cache = projectService.cloneCache();
ProjectCache cache = projectManager.cloneCache();
List<String> choices = projects.stream().map(it->cache.get(it.getId()).getPath()).collect(Collectors.toList());
Collections.sort(choices);
@ -98,7 +98,7 @@ public class Import implements Serializable, Validatable {
private static Project getInputProject() {
String projectPath = (String) EditContext.get().getInputValue("projectPath");
if (projectPath != null) {
Project project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
Project project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
if (project != null && SecurityUtils.canReadCode(project))
return project;
}
@ -194,8 +194,8 @@ public class Import implements Serializable, Validatable {
public boolean isValid(ConstraintValidatorContext context) {
try {
var commit = getCommit();
if (IMPORT_CHAIN.get().contains(commit.name())) {
List<String> circular = new ArrayList<>(IMPORT_CHAIN.get());
if (importChain.get().contains(commit.name())) {
List<String> circular = new ArrayList<>(importChain.get());
circular.add(commit.name());
String errorMessage = MessageFormat.format(
_T("Circular build spec imports ({0})"), circular);
@ -203,11 +203,12 @@ public class Import implements Serializable, Validatable {
context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
return false;
} else {
IMPORT_CHAIN.get().push(commit.name());
importChain.get().push(commit.name());
try {
Validator validator = OneDev.getInstance(Validator.class);
BuildSpec buildSpec = getBuildSpec();
JobAuthorizationContext.push(new JobAuthorizationContext(getProject(), getCommit(), null));
JobAuthorizationContext.push(new JobAuthorizationContext(
getProject(), getCommit(), SecurityUtils.getUser(), null));
try {
for (int i = 0; i < buildSpec.getImports().size(); i++) {
Import aImport = buildSpec.getImports().get(i);
@ -225,7 +226,7 @@ public class Import implements Serializable, Validatable {
JobAuthorizationContext.pop();
}
} finally {
IMPORT_CHAIN.get().pop();
importChain.get().pop();
}
}
} catch (Exception e) {
@ -242,7 +243,7 @@ public class Import implements Serializable, Validatable {
public Project getProject() {
if (project == null) {
project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
if (project == null)
throw new ExplicitException(MessageFormat.format( _T("Unable to find project to import build spec: {0}"), projectPath));
}

View File

@ -6,7 +6,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import io.onedev.commons.codeassist.InputCompletion;
@ -88,7 +87,6 @@ public class Service implements NamedElement {
@Editable(order=300, name="Environment Variables", description="Optionally specify environment variables of "
+ "the service")
@Valid
public List<EnvVar> getEnvVars() {
return envVars;
}

View File

@ -17,7 +17,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Valid;
import javax.validation.constraints.Min;
@ -32,7 +32,6 @@ import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.ClassValidating;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.RetryCondition;
@ -46,13 +45,14 @@ import io.onedev.server.buildspec.job.trigger.JobTrigger;
import io.onedev.server.buildspec.param.ParamUtils;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.buildspec.step.Step;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.event.project.ProjectEvent;
import io.onedev.server.git.GitUtils;
import io.onedev.server.job.match.JobMatch;
import io.onedev.server.job.match.JobMatchContext;
import io.onedev.server.model.PullRequest;
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
import io.onedev.server.service.SettingService;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.util.ComponentContext;
import io.onedev.server.util.EditContext;
import io.onedev.server.util.criteria.Criteria;
@ -82,8 +82,6 @@ public class Job implements NamedElement, Validatable {
public static final String PROP_RETRY_CONDITION = "retryCondition";
public static final String PROP_POST_BUILD_ACTIONS = "postBuildActions";
public static final String PROP_JOB_EXECUTOR = "jobExecutor";
private String name;
@ -150,7 +148,7 @@ public class Job implements NamedElement, Validatable {
@SuppressWarnings("unused")
private static String getJobExecutorPlaceholder() {
if (OneDev.getInstance(SettingService.class).getJobExecutors().isEmpty())
if (OneDev.getInstance(SettingManager.class).getJobExecutors().isEmpty())
return _T("Auto-discovered executor");
else
return _T("First applicable executor");
@ -158,7 +156,7 @@ public class Job implements NamedElement, Validatable {
@SuppressWarnings("unused")
private static String getJobExecutorDescription() {
if (OneDev.getInstance(SettingService.class).getJobExecutors().isEmpty())
if (OneDev.getInstance(SettingManager.class).getJobExecutors().isEmpty())
return _T("Optionally specify executor for this job. Leave empty to use auto-discover executor");
else
return _T("Optionally specify executor for this job. Leave empty to use first applicable executor");
@ -173,8 +171,8 @@ public class Job implements NamedElement, Validatable {
String branch = page.getBlobIdent().revision;
if (branch == null)
branch = "main";
JobMatchContext context = new JobMatchContext(page.getProject(), branch, null, jobName);
for (JobExecutor executor: OneDev.getInstance(SettingService.class).getJobExecutors()) {
JobMatchContext context = new JobMatchContext(page.getProject(), branch, null, SecurityUtils.getAuthUser(), jobName);
for (JobExecutor executor: OneDev.getInstance(SettingManager.class).getJobExecutors()) {
if (executor.isEnabled()) {
if (executor.getJobMatch() == null) {
applicableJobExecutors.add(executor.getName());
@ -190,7 +188,6 @@ public class Job implements NamedElement, Validatable {
}
@Editable(order=200, description="Steps will be executed serially on same node, sharing the same <a href='https://docs.onedev.io/concepts#job-workspace'>job workspace</a>")
@Valid
public List<Step> getSteps() {
return steps;
}
@ -283,8 +280,8 @@ public class Job implements NamedElement, Validatable {
}
@Editable(order=9400, group="More Settings", description="Specify condition to retry build upon failure")
@RetryCondition
@NotEmpty
@RetryCondition
public String getRetryCondition() {
return retryCondition;
}
@ -295,7 +292,6 @@ public class Job implements NamedElement, Validatable {
@Editable(order=9410, group="More Settings", description="Maximum of retries before giving up")
@Min(value=1, message="This value should not be less than 1")
@DependsOn(property="retryCondition", value = "never", inverse = true)
public int getMaxRetries() {
return maxRetries;
}
@ -308,7 +304,6 @@ public class Job implements NamedElement, Validatable {
"Delay of subsequent retries will be calculated using an exponential back-off based on " +
"this value")
@Min(value=1, message="This value should not be less than 1")
@DependsOn(property="retryCondition", value = "never", inverse = true)
public int getRetryDelay() {
return retryDelay;
}
@ -351,14 +346,6 @@ public class Job implements NamedElement, Validatable {
public boolean isValid(ConstraintValidatorContext context) {
boolean isValid = true;
var jobExecutors = OneDev.getInstance(SettingService.class).getJobExecutors();
if (jobExecutor != null && !jobExecutor.contains("@")
&& jobExecutors.stream().noneMatch(it->it.getName().equals(jobExecutor))) {
isValid = false;
context.buildConstraintViolationWithTemplate("Job executor not found: " + jobExecutor)
.addPropertyNode(PROP_JOB_EXECUTOR).addConstraintViolation();
}
Set<String> dependencyJobNames = new HashSet<>();
for (JobDependency dependency: jobDependencies) {
if (!dependencyJobNames.add(dependency.getJobName())) {
@ -377,16 +364,18 @@ public class Job implements NamedElement, Validatable {
}
}
try {
io.onedev.server.buildspec.job.retrycondition.RetryCondition.parse(this, getRetryCondition());
} catch (Exception e) {
String message = e.getMessage();
if (message == null)
message = "Malformed retry condition";
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(PROP_RETRY_CONDITION)
.addConstraintViolation();
isValid = false;
if (getRetryCondition() != null) {
try {
io.onedev.server.buildspec.job.retrycondition.RetryCondition.parse(this, getRetryCondition());
} catch (Exception e) {
String message = e.getMessage();
if (message == null)
message = "Malformed retry condition";
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(PROP_RETRY_CONDITION)
.addConstraintViolation();
isValid = false;
}
}
if (isValid) {

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import io.onedev.server.buildspec.ParamSpecAware;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job;
import io.onedev.k8shelper.KubernetesHelper;
import io.onedev.server.OneDev;
import io.onedev.server.service.SettingService;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.model.Build;
import io.onedev.server.util.UrlUtils;
@ -118,14 +118,14 @@ public enum JobVariable {
SERVER {
@Override
public String getValue(Build build) {
var serverUrl = OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
var serverUrl = OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
return UrlUtils.getServer(serverUrl);
}
},
SERVER_HOST {
@Override
public String getValue(Build build) {
var serverUrl = OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
var serverUrl = OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
try {
return new URL(serverUrl).getHost();
} catch (MalformedURLException e) {
@ -136,7 +136,7 @@ public enum JobVariable {
SERVER_URL {
@Override
public String getValue(Build build) {
return OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
return OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
}
};

View File

@ -3,14 +3,14 @@ package io.onedev.server.buildspec.job;
import io.onedev.server.OneDev;
import io.onedev.server.buildspec.param.instance.ParamInstances;
import io.onedev.server.buildspec.param.instance.ParamMap;
import io.onedev.server.service.IssueService;
import io.onedev.server.service.PullRequestService;
import io.onedev.server.entitymanager.IssueManager;
import io.onedev.server.entitymanager.PullRequestManager;
import io.onedev.server.model.Issue;
import io.onedev.server.model.PullRequest;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.List;
@ -48,7 +48,7 @@ public class TriggerMatch implements Serializable {
@Nullable
public PullRequest getRequest() {
if (requestId != null)
return OneDev.getInstance(PullRequestService.class).load(requestId);
return OneDev.getInstance(PullRequestManager.class).load(requestId);
else
return null;
}
@ -56,7 +56,7 @@ public class TriggerMatch implements Serializable {
@Nullable
public Issue getIssue() {
if (issueId != null)
return OneDev.getInstance(IssueService.class).load(issueId);
return OneDev.getInstance(IssueManager.class).load(issueId);
else
return null;
}

View File

@ -1,34 +1,15 @@
package io.onedev.server.buildspec.job.action;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotEmpty;
import org.apache.shiro.subject.Subject;
import edu.emory.mathcs.backport.java.util.Collections;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.commons.utils.ExplicitException;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.FieldNamesProvider;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.Multiline;
import io.onedev.server.annotation.OmitName;
import io.onedev.server.annotation.*;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.buildspec.job.Job;
import io.onedev.server.service.IssueService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.SettingService;
import io.onedev.server.entitymanager.IssueManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.job.JobAuthorizationContext;
import io.onedev.server.model.Build;
import io.onedev.server.model.Issue;
@ -36,12 +17,21 @@ import io.onedev.server.model.Project;
import io.onedev.server.model.support.administration.GlobalIssueSetting;
import io.onedev.server.model.support.issue.field.FieldUtils;
import io.onedev.server.model.support.issue.field.instance.FieldInstance;
import io.onedev.server.persistence.TransactionService;
import io.onedev.server.persistence.TransactionManager;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.security.permission.AccessProject;
import io.onedev.server.util.EditContext;
import io.onedev.server.util.facade.ProjectCache;
import io.onedev.server.web.page.project.ProjectPage;
import io.onedev.server.web.util.WicketUtils;
import org.apache.shiro.subject.Subject;
import javax.annotation.Nullable;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotEmpty;
import java.util.*;
import java.util.stream.Collectors;
@Editable(name="Create issue", order=300)
public class CreateIssueAction extends PostBuildAction {
@ -73,13 +63,13 @@ public class CreateIssueAction extends PostBuildAction {
@SuppressWarnings("unused")
private static List<String> getProjectChoices() {
ProjectService projectService = OneDev.getInstance(ProjectService.class);
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
Project project = ((ProjectPage) WicketUtils.getPage()).getProject();
Collection<Project> projects = SecurityUtils.getAuthorizedProjects(new AccessProject());
projects.remove(project);
ProjectCache cache = projectService.cloneCache();
ProjectCache cache = projectManager.cloneCache();
List<String> choices = projects.stream().map(it->cache.get(it.getId()).getPath()).collect(Collectors.toList());
Collections.sort(choices);
@ -90,7 +80,7 @@ public class CreateIssueAction extends PostBuildAction {
@Editable(order=910, description="Specify a secret to be used as access token to create issue in " +
"above project if it is not publicly accessible")
@ChoiceProvider("getAccessTokenSecretChoices")
@DependsOn(property="projectPath")
@ShowCondition("isProjectSpecified")
@Nullable
public String getAccessTokenSecret() {
return accessTokenSecret;
@ -99,6 +89,11 @@ public class CreateIssueAction extends PostBuildAction {
public void setAccessTokenSecret(String accessTokenSecret) {
this.accessTokenSecret = accessTokenSecret;
}
@SuppressWarnings("unused")
private static boolean isProjectSpecified() {
return EditContext.get().getInputValue("projectPath") != null;
}
@SuppressWarnings("unused")
private static List<String> getAccessTokenSecretChoices() {
@ -155,15 +150,15 @@ public class CreateIssueAction extends PostBuildAction {
}
private static Collection<String> getFieldNames() {
return OneDev.getInstance(SettingService.class).getIssueSetting().getFieldNames();
return OneDev.getInstance(SettingManager.class).getIssueSetting().getFieldNames();
}
@Override
public void execute(Build build) {
OneDev.getInstance(TransactionService.class).run(() -> {
OneDev.getInstance(TransactionManager.class).run(() -> {
Project project;
if (getProjectPath() != null) {
project = OneDev.getInstance(ProjectService.class).findByPath(getProjectPath());
project = OneDev.getInstance(ProjectManager.class).findByPath(getProjectPath());
if (project == null)
throw new ExplicitException("Unable to find project: " + projectPath);
Subject subject = JobAuthorizationContext.get().getSubject(getAccessTokenSecret());
@ -177,8 +172,8 @@ public class CreateIssueAction extends PostBuildAction {
issue.setTitle(getIssueTitle());
issue.setSubmitter(SecurityUtils.getUser());
issue.setSubmitDate(new Date());
SettingService settingService = OneDev.getInstance(SettingService.class);
GlobalIssueSetting issueSetting = settingService.getIssueSetting();
SettingManager settingManager = OneDev.getInstance(SettingManager.class);
GlobalIssueSetting issueSetting = settingManager.getIssueSetting();
issue.setState(issueSetting.getInitialStateSpec().getName());
issue.setDescription(getIssueDescription());
@ -188,7 +183,7 @@ public class CreateIssueAction extends PostBuildAction {
.convertToObject(instance.getValueProvider().getValue());
issue.setFieldValue(instance.getName(), fieldValue);
}
OneDev.getInstance(IssueService.class).open(issue);
OneDev.getInstance(IssueManager.class).open(issue);
});
}
@ -202,7 +197,7 @@ public class CreateIssueAction extends PostBuildAction {
public void validateWith(BuildSpec buildSpec, Job job) {
super.validateWith(buildSpec, job);
GlobalIssueSetting issueSetting = OneDev.getInstance(SettingService.class).getIssueSetting();
GlobalIssueSetting issueSetting = OneDev.getInstance(SettingManager.class).getIssueSetting();
try {
FieldUtils.validateFields(issueSetting.getFieldSpecMap(getFieldNames()), issueFields);
} catch (ValidationException e) {

View File

@ -1,23 +1,7 @@
package io.onedev.server.buildspec.job.action;
import static io.onedev.server.buildspec.param.ParamUtils.resolveParams;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotEmpty;
import org.apache.wicket.Component;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.OmitName;
import io.onedev.server.annotation.ParamSpecProvider;
import io.onedev.server.annotation.ShowCondition;
import io.onedev.server.annotation.VariableOption;
import io.onedev.server.annotation.*;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.buildspec.BuildSpecAware;
import io.onedev.server.buildspec.job.Job;
@ -25,13 +9,21 @@ import io.onedev.server.buildspec.param.ParamUtils;
import io.onedev.server.buildspec.param.instance.ParamInstances;
import io.onedev.server.buildspec.param.instance.ParamMap;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.job.JobService;
import io.onedev.server.job.JobManager;
import io.onedev.server.model.Build;
import io.onedev.server.service.UserService;
import io.onedev.server.util.ComponentContext;
import io.onedev.server.util.EditContext;
import io.onedev.server.web.editable.BeanEditor;
import io.onedev.server.web.util.WicketUtils;
import org.apache.wicket.Component;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
import static io.onedev.server.buildspec.param.ParamUtils.resolveParams;
@Editable(name="Run job", order=100)
public class RunJobAction extends PostBuildAction {
@ -114,11 +106,11 @@ public class RunJobAction extends PostBuildAction {
@Override
public void execute(Build build) {
for (var paramMap: resolveParams(build, build.getParamCombination(), getParamMatrix(), getExcludeParamMaps())) {
JobService jobService = OneDev.getInstance(JobService.class);
var userService = OneDev.getInstance(UserService.class);
jobService.submit(userService.getSystem(), build.getProject(), build.getCommitId(),
getJobName(), paramMap, build.getRefName(), build.getRequest(), build.getIssue(),
"Triggered via post build action of job '" + build.getJobName() + "'");
JobManager jobManager = OneDev.getInstance(JobManager.class);
jobManager.submit(build.getProject(), build.getCommitId(),
getJobName(), paramMap, build.getRefName(),
build.getSubmitter(), build.getRequest(), build.getIssue(),
"Post build action of job '" + build.getJobName() + "'");
}
}

View File

@ -1,308 +0,0 @@
package io.onedev.server.buildspec.job.action;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraints.NotEmpty;
import javax.ws.rs.NotAcceptableException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.util.ThreadContext;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.ClassValidating;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.git.GitUtils;
import io.onedev.server.job.JobService;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.security.permission.AccessProject;
import io.onedev.server.service.AccessTokenService;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.util.EditContext;
import io.onedev.server.util.facade.ProjectCache;
import io.onedev.server.validation.Validatable;
import io.onedev.server.web.page.project.ProjectPage;
import io.onedev.server.web.util.SuggestionUtils;
import io.onedev.server.web.util.WicketUtils;
@Editable(name="Run job in another project", order=150)
@ClassValidating
public class RunProjectJobAction extends PostBuildAction implements Validatable {
private static final long serialVersionUID = 1L;
private String projectPath;
private String branch;
private String tag;
private String jobName;
private List<JobParam> jobParams = new ArrayList<>();
private String accessTokenSecret;
@Editable(order=100, name="Project", description="Specify project to run job in")
@ChoiceProvider("getProjectChoices")
@NotEmpty
public String getProjectPath() {
return projectPath;
}
public void setProjectPath(String projectPath) {
this.projectPath = projectPath;
}
@SuppressWarnings("unused")
private static List<String> getProjectChoices() {
List<String> choices = new ArrayList<>();
Project currentProject = ((ProjectPage)WicketUtils.getPage()).getProject();
ProjectCache cache = getProjectService().cloneCache();
for (Project project: SecurityUtils.getAuthorizedProjects(new AccessProject())) {
if (!project.equals(currentProject))
choices.add(cache.get(project.getId()).getPath());
}
Collections.sort(choices);
return choices;
}
@Editable(order=200, description="Specify branch to run the job against. Either branch or tag can be specified, but not both. Default branch will be used if both not specified")
@Interpolative(variableSuggester="suggestVariables", literalSuggester="suggestBranches")
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
@Editable(order=200, description="Specify tag to run the job against. Either branch or tag can be specified, but not both. Default branch will be used if both not specified")
@Interpolative(variableSuggester="suggestVariables", literalSuggester="suggestTags")
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
@SuppressWarnings("unused")
private static List<InputSuggestion> suggestVariables(String matchWith) {
return BuildSpec.suggestVariables(matchWith, false, false, false);
}
@SuppressWarnings("unused")
private static List<InputSuggestion> suggestBranches(String matchWith) {
Project project = getInputProject();
if (project != null)
return SuggestionUtils.suggestBranches(project, matchWith);
else
return new ArrayList<>();
}
@SuppressWarnings("unused")
private static List<InputSuggestion> suggestTags(String matchWith) {
Project project = getInputProject();
if (project != null)
return SuggestionUtils.suggestTags(project, matchWith);
else
return new ArrayList<>();
}
@Editable(order=300, name="Job")
@ChoiceProvider("getJobChoices")
@NotEmpty
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
@Nullable
private static Project getInputProject() {
String projectPath = (String) EditContext.get().getInputValue("projectPath");
if (projectPath != null) {
Project project = getProjectService().findByPath(projectPath);
if (project != null && SecurityUtils.canReadCode(project))
return project;
}
return null;
}
@SuppressWarnings("unused")
private static List<String> getJobChoices() {
Project project = getInputProject();
List<String> jobNames = new ArrayList<>();
if (project != null) {
jobNames.addAll(getBuildService().getAccessibleJobNames(SecurityUtils.getSubject(), project));
Collections.sort(jobNames);
}
return jobNames;
}
@Editable(order=400, name="Job Parameters")
public List<JobParam> getJobParams() {
return jobParams;
}
public void setJobParams(List<JobParam> jobParams) {
this.jobParams = jobParams;
}
@Editable(order=500, placeholder="Access Anonymously", description="Specify a secret to be used as "
+ "access token to trigger job in above project")
@ChoiceProvider("getAccessTokenSecretChoices")
@NotEmpty
public String getAccessTokenSecret() {
return accessTokenSecret;
}
public void setAccessTokenSecret(String accessTokenSecret) {
this.accessTokenSecret = accessTokenSecret;
}
@SuppressWarnings("unused")
private static List<String> getAccessTokenSecretChoices() {
return Project.get().getHierarchyJobSecrets()
.stream().map(it->it.getName()).collect(Collectors.toList());
}
@Override
public void execute(Build build) {
Project project = getProjectService().findByPath(projectPath);
if (project == null)
throw new NotAcceptableException("Project not found: " + projectPath);
String secretValue = build.getJobAuthorizationContext().getSecretValue(accessTokenSecret);
var accessToken = getAccessTokenService().findByValue(secretValue);
if (accessToken == null)
throw new NotAcceptableException("Invalid access token");
var subject = accessToken.asSubject();
if (!SecurityUtils.canRunJob(subject, project, jobName))
throw new UnauthorizedException();
var user = SecurityUtils.getUser(subject);
ThreadContext.bind(subject);
try {
String refName;
if (branch != null) {
refName = GitUtils.branch2ref(branch);
} else if (tag != null) {
refName = GitUtils.tag2ref(tag);
} else {
var defaultBranch = project.getDefaultBranch();
if (defaultBranch == null)
throw new NotAcceptableException("No default branch in project: " + project.getPath());
refName = GitUtils.branch2ref(defaultBranch);
}
var commit = project.getRevCommit(refName, false);
if (commit == null)
throw new NotAcceptableException("Ref not found (project: " + project.getPath() + ", ref: " + refName + ")");
Map<String, List<String>> jobParamMap = new HashMap<>();
for (var jobParam: jobParams) {
jobParamMap.computeIfAbsent(jobParam.getName(), k -> new ArrayList<>()).add(jobParam.getValue());
}
getJobService().submit(user, project, commit.copy(), jobName, jobParamMap, refName, null, null,
"Triggered via post build action of job '" + build.getJobName() + "' in project '" + build.getProject().getPath() + "'");
} finally {
ThreadContext.unbindSubject();
}
}
@Override
public boolean isValid(ConstraintValidatorContext context) {
if (branch != null && tag != null) {
var errorMessage = "Either branch or tag can be specified, but not both";
context.buildConstraintViolationWithTemplate(errorMessage)
.addPropertyNode("branch").addConstraintViolation();
context.buildConstraintViolationWithTemplate(errorMessage)
.addPropertyNode("tag").addConstraintViolation();
return false;
} else {
return true;
}
}
@Override
public String getDescription() {
return "Run job '" + jobName + "' in project '" + projectPath + "'";
}
private static ProjectService getProjectService() {
return OneDev.getInstance(ProjectService.class);
}
private static AccessTokenService getAccessTokenService() {
return OneDev.getInstance(AccessTokenService.class);
}
private static JobService getJobService() {
return OneDev.getInstance(JobService.class);
}
private static BuildService getBuildService() {
return OneDev.getInstance(BuildService.class);
}
@Editable
public static class JobParam implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String value;
@Editable(order=100)
@Interpolative(variableSuggester="suggestVariables")
@NotEmpty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Editable(order=200)
@Interpolative(variableSuggester="suggestVariables")
@NotEmpty
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@SuppressWarnings("unused")
private static List<InputSuggestion> suggestVariables(String matchWith) {
return BuildSpec.suggestVariables(matchWith, false, false, false);
}
}
}

View File

@ -14,7 +14,7 @@ import static io.onedev.server.model.Build.NAME_TAG;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.action.condition;
import static io.onedev.server.buildspec.job.action.condition.ActionCondition.getRuleName;
import static io.onedev.server.model.Build.NAME_BRANCH;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.action.condition;
import static io.onedev.server.buildspec.job.action.condition.ActionCondition.getRuleName;
import static io.onedev.server.model.Build.NAME_BRANCH;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,14 +2,14 @@ package io.onedev.server.buildspec.job.action.condition;
import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;
import io.onedev.server.OneDev;
import io.onedev.server.job.log.LogService;
import io.onedev.server.job.log.LogManager;
import io.onedev.server.model.Build;
import io.onedev.server.util.ProjectScope;
import io.onedev.server.util.criteria.Criteria;
@ -32,7 +32,7 @@ public class LogCriteria extends Criteria<Build> {
@Override
public boolean matches(Build build) {
Pattern pattern = Pattern.compile(value);
return OneDev.getInstance(LogService.class).matches(build, pattern);
return OneDev.getInstance(LogManager.class).matches(build, pattern);
}
@Override

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.action.condition;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.action.condition;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.action.condition;
import static io.onedev.server.buildspec.job.action.condition.ActionCondition.getRuleName;
import static io.onedev.server.model.Build.NAME_PROJECT;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.action.condition;
import static io.onedev.server.buildspec.job.action.condition.ActionCondition.getRuleName;
import static io.onedev.server.model.Build.NAME_TAG;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.action.condition;
import static io.onedev.server.buildspec.job.action.condition.ActionCondition.getRuleName;
import static io.onedev.server.model.Build.NAME_TAG;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.action.condition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -4,7 +4,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.BaseErrorListener;
@ -22,8 +22,8 @@ import io.onedev.commons.utils.ExplicitException;
import io.onedev.commons.utils.StringUtils;
import io.onedev.server.OneDev;
import io.onedev.server.buildspec.job.action.notificationreceiver.NotificationReceiverParser.CriteriaContext;
import io.onedev.server.service.GroupService;
import io.onedev.server.service.UserService;
import io.onedev.server.entitymanager.GroupManager;
import io.onedev.server.entitymanager.UserManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.EmailAddress;
import io.onedev.server.model.Group;
@ -60,14 +60,14 @@ public class NotificationReceiver {
for (CriteriaContext criteria: parser.receiver().criteria()) {
if (criteria.userCriteria() != null) {
String userName = getValue(criteria.userCriteria().Value());
User user = OneDev.getInstance(UserService.class).findByName(userName);
User user = OneDev.getInstance(UserManager.class).findByName(userName);
if (user != null)
addEmailAddress(emailAddresses, user);
else
throw new ExplicitException("Unable to find user '" + userName + "'");
} else if (criteria.groupCriteria() != null) {
String groupName = getValue(criteria.groupCriteria().Value());
Group group = OneDev.getInstance(GroupService.class).find(groupName);
Group group = OneDev.getInstance(GroupManager.class).find(groupName);
if (group != null) {
emailAddresses.addAll(group.getMembers().stream()
.map(it->it.getPrimaryEmailAddress())

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.job.gitcredential;
import io.onedev.k8shelper.CloneInfo;
import io.onedev.k8shelper.DefaultCloneInfo;
import io.onedev.server.OneDev;
import io.onedev.server.web.UrlService;
import io.onedev.server.web.UrlManager;
import io.onedev.server.model.Build;
import io.onedev.server.annotation.Editable;
@ -14,7 +14,7 @@ public class DefaultCredential implements GitCredential {
@Override
public CloneInfo newCloneInfo(Build build, String jobToken) {
return new DefaultCloneInfo(OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), false), jobToken);
return new DefaultCloneInfo(OneDev.getInstance(UrlManager.class).cloneUrlFor(build.getProject(), false), jobToken);
}
}

View File

@ -10,7 +10,7 @@ import javax.validation.constraints.NotEmpty;
import io.onedev.k8shelper.CloneInfo;
import io.onedev.k8shelper.HttpCloneInfo;
import io.onedev.server.OneDev;
import io.onedev.server.web.UrlService;
import io.onedev.server.web.UrlManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.validation.Validatable;
@ -45,7 +45,7 @@ public class HttpCredential implements GitCredential, Validatable {
@Override
public CloneInfo newCloneInfo(Build build, String jobToken) {
return new HttpCloneInfo(OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), false),
return new HttpCloneInfo(OneDev.getInstance(UrlManager.class).cloneUrlFor(build.getProject(), false),
build.getJobAuthorizationContext().getSecretValue(accessTokenSecret));
}

View File

@ -14,8 +14,8 @@ import javax.validation.constraints.NotEmpty;
import io.onedev.k8shelper.CloneInfo;
import io.onedev.k8shelper.SshCloneInfo;
import io.onedev.server.OneDev;
import io.onedev.server.service.SettingService;
import io.onedev.server.web.UrlService;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.web.UrlManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.model.support.administration.SshSetting;
@ -52,10 +52,10 @@ public class SshCredential implements GitCredential, Validatable {
@Override
public CloneInfo newCloneInfo(Build build, String jobToken) {
String cloneUrl = OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), true);
SettingService settingService = OneDev.getInstance(SettingService.class);
SystemSetting systemSetting = settingService.getSystemSetting();
SshSetting sshSetting = settingService.getSshSetting();
String cloneUrl = OneDev.getInstance(UrlManager.class).cloneUrlFor(build.getProject(), true);
SettingManager settingManager = OneDev.getInstance(SettingManager.class);
SystemSetting systemSetting = settingManager.getSystemSetting();
SshSetting sshSetting = settingManager.getSshSetting();
StringBuilder knownHosts = new StringBuilder(systemSetting.getSshServerName()).append(" ");
try {
PublicKeyEntry.appendPublicKeyEntry(knownHosts,

View File

@ -5,7 +5,7 @@ import com.google.common.collect.Lists;
import io.onedev.server.job.log.StyleBuilder;
import io.onedev.server.web.asset.emoji.Emojis;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.projectdependency;
import java.io.Serializable;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;

View File

@ -7,13 +7,13 @@ import javax.validation.constraints.NotEmpty;
import edu.emory.mathcs.backport.java.util.Collections;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.service.BuildService;
import io.onedev.server.util.EditContext;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.OmitName;
@Editable(order=100, name="Last Finished of Specified Job")
public class LastFinishedBuild implements BuildProvider {
@ -25,6 +25,7 @@ public class LastFinishedBuild implements BuildProvider {
private String refName;
@Editable(order=100)
@OmitName
@ChoiceProvider("getJobChoices")
@NotEmpty
public String getJobName() {
@ -50,7 +51,7 @@ public class LastFinishedBuild implements BuildProvider {
Project project = ProjectDependency.getInputProject(EditContext.get(1));
List<String> jobNames = new ArrayList<>();
if (project != null) {
jobNames.addAll(OneDev.getInstance(BuildService.class).getAccessibleJobNames(SecurityUtils.getSubject(), project));
jobNames.addAll(OneDev.getInstance(BuildManager.class).getAccessibleJobNames(project));
Collections.sort(jobNames);
}
return jobNames;
@ -58,7 +59,7 @@ public class LastFinishedBuild implements BuildProvider {
@Override
public Build getBuild(Project project) {
return OneDev.getInstance(BuildService.class).findLastFinished(project, jobName, refName);
return OneDev.getInstance(BuildManager.class).findLastFinished(project, jobName, refName);
}
@Override

View File

@ -8,7 +8,7 @@ import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.Patterns;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.model.Project;
import io.onedev.server.security.SecurityUtils;
import io.onedev.server.security.permission.AccessProject;
@ -17,7 +17,7 @@ import io.onedev.server.util.facade.ProjectCache;
import io.onedev.server.web.page.project.ProjectPage;
import io.onedev.server.web.util.WicketUtils;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@ -57,8 +57,8 @@ public class ProjectDependency implements Serializable {
List<String> choices = new ArrayList<>();
Project currentProject = ((ProjectPage)WicketUtils.getPage()).getProject();
ProjectService projectService = OneDev.getInstance(ProjectService.class);
ProjectCache cache = projectService.cloneCache();
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
ProjectCache cache = projectManager.cloneCache();
for (Project project: SecurityUtils.getAuthorizedProjects(new AccessProject())) {
if (!project.equals(currentProject))
choices.add(cache.get(project.getId()).getPath());
@ -83,7 +83,7 @@ public class ProjectDependency implements Serializable {
static Project getInputProject(EditContext editContext) {
String projectPath = (String) editContext.getInputValue("projectPath");
if (projectPath != null) {
Project project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
Project project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
if (project != null && SecurityUtils.canReadCode(project))
return project;
}

View File

@ -8,7 +8,7 @@ import javax.validation.constraints.NotEmpty;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.server.OneDev;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.util.EditContext;
@ -59,7 +59,7 @@ public class SpecifiedBuild implements BuildProvider {
else
buildNumber = Long.parseLong(this.buildNumber);
return OneDev.getInstance(BuildService.class).find(project, buildNumber);
return OneDev.getInstance(BuildManager.class).find(project, buildNumber);
}
@Override

View File

@ -2,14 +2,14 @@ package io.onedev.server.buildspec.job.retrycondition;
import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;
import io.onedev.server.OneDev;
import io.onedev.server.job.log.LogService;
import io.onedev.server.job.log.LogManager;
import io.onedev.server.model.Build;
import io.onedev.server.util.ProjectScope;
import io.onedev.server.util.criteria.Criteria;
@ -33,7 +33,7 @@ public class LogCriteria extends Criteria<RetryContext> {
public boolean matches(RetryContext context) {
Pattern pattern = Pattern.compile(value);
return context.getErrorMessage() != null && pattern.matcher(context.getErrorMessage()).find()
|| OneDev.getInstance(LogService.class).matches(context.getBuild(), pattern);
|| OneDev.getInstance(LogManager.class).matches(context.getBuild(), pattern);
}
@Override

View File

@ -1,6 +1,6 @@
package io.onedev.server.buildspec.job.retrycondition;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -10,7 +10,7 @@ import static io.onedev.server.model.Build.NAME_LOG;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
import io.onedev.server.model.Build;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
public class RetryContext {

View File

@ -1,30 +1,25 @@
package io.onedev.server.buildspec.job.trigger;
import java.util.Collection;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.commons.utils.match.Matcher;
import io.onedev.commons.utils.match.PathMatcher;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Patterns;
import io.onedev.server.annotation.UserMatch;
import io.onedev.server.buildspec.job.Job;
import io.onedev.server.buildspec.job.TriggerMatch;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.event.project.ProjectEvent;
import io.onedev.server.event.project.RefUpdated;
import io.onedev.server.git.GitUtils;
import io.onedev.server.model.Project;
import io.onedev.commons.utils.match.Matcher;
import io.onedev.commons.utils.match.PathMatcher;
import io.onedev.server.util.patternset.PatternSet;
import io.onedev.server.util.usermatch.Anyone;
import io.onedev.server.web.util.SuggestionUtils;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import java.util.Collection;
import java.util.List;
@Editable(order=100, name="Branch update", description=""
+ "Job will run when code is committed. <b class='text-info'>NOTE:</b> This trigger will ignore commits "
@ -38,9 +33,7 @@ public class BranchUpdateTrigger extends JobTrigger {
private String branches;
private String paths;
private String userMatch = new Anyone().toString();
@Editable(name="Branches", order=100, placeholder="Any branch", description="Optionally specify space-separated branches "
+ "to check. Use '**' or '*' or '?' for <a href='https://docs.onedev.io/appendix/path-wildcard' target='_blank'>path wildcard match</a>. "
+ "Prefix with '-' to exclude. Leave empty to match all branches")
@ -70,17 +63,6 @@ public class BranchUpdateTrigger extends JobTrigger {
this.paths = paths;
}
@Editable(order=300, name="Applicable Users", description="Optionally specify applicable users who pushed the change")
@UserMatch
@NotEmpty
public String getUserMatch() {
return userMatch;
}
public void setUserMatch(String userMatch) {
this.userMatch = userMatch;
}
@SuppressWarnings("unused")
private static List<InputSuggestion> getPathSuggestions(String matchWith) {
return SuggestionUtils.suggestBlobs(Project.get(), matchWith);
@ -93,7 +75,7 @@ public class BranchUpdateTrigger extends JobTrigger {
} else if (refUpdated.getNewCommitId().equals(ObjectId.zeroId())) {
return false;
} else {
Repository repository = OneDev.getInstance(ProjectService.class)
Repository repository = OneDev.getInstance(ProjectManager.class)
.getRepository(refUpdated.getProject().getId());
Collection<String> changedFiles = GitUtils.getChangedFiles(
repository,
@ -110,14 +92,6 @@ public class BranchUpdateTrigger extends JobTrigger {
return true;
}
}
private boolean pushedBy(RefUpdated refUpdated) {
if (refUpdated.getUser() != null) {
return io.onedev.server.util.usermatch.UserMatch.parse(getUserMatch()).matches(refUpdated.getUser());
} else {
return true;
}
}
@Override
protected TriggerMatch triggerMatches(ProjectEvent event, Job job) {
@ -128,7 +102,7 @@ public class BranchUpdateTrigger extends JobTrigger {
if (updatedBranch != null
&& !SKIP_COMMIT.apply(event.getProject().getRevCommit(refUpdated.getNewCommitId(), true))
&& (branches == null || PatternSet.parse(branches).matches(matcher, updatedBranch))
&& touchedFile(refUpdated) && pushedBy(refUpdated)) {
&& touchedFile(refUpdated)) {
return new TriggerMatch(refUpdated.getRefName(), null, null,
getParamMatrix(), getExcludeParamMaps(), "Branch '" + updatedBranch + "' is updated");
}
@ -139,26 +113,14 @@ public class BranchUpdateTrigger extends JobTrigger {
@Override
public String getTriggerDescription() {
String description;
if (getUserMatch() == null || getUserMatch().equals(new Anyone().toString())) {
if (getBranches() != null && getPaths() != null)
description = String.format("When update branches '%s' and touch files '%s'", getBranches(), getPaths());
else if (getBranches() != null)
description = String.format("When update branches '%s'", getBranches());
else if (getPaths() != null)
description = String.format("When touch files '%s'", getPaths());
else
description = "When update branches";
} else {
if (getBranches() != null && getPaths() != null)
description = String.format("When update branches '%s' and touch files '%s' and pushed by '%s'", getBranches(), getPaths(), getUserMatch());
else if (getBranches() != null)
description = String.format("When update branches '%s' and pushed by '%s'", getBranches(), getUserMatch());
else if (getPaths() != null)
description = String.format("When touch files '%s' and pushed by '%s'", getPaths(), getUserMatch());
else
description = "When pushed by '" + getUserMatch() + "'";
}
if (getBranches() != null && getPaths() != null)
description = String.format("When update branches '%s' and touch files '%s'", getBranches(), getPaths());
else if (getBranches() != null)
description = String.format("When update branches '%s'", getBranches());
else if (getPaths() != null)
description = String.format("When touch files '%s'", getPaths());
else
description = "When update branches";
return description;
}

View File

@ -5,7 +5,7 @@ import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.job.Job;
import io.onedev.server.buildspec.job.TriggerMatch;
import io.onedev.server.service.SettingService;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.event.project.ProjectEvent;
import io.onedev.server.event.project.issue.IssueChanged;
import io.onedev.server.event.project.issue.IssueOpened;
@ -16,7 +16,7 @@ import io.onedev.server.model.support.issue.changedata.IssueStateChangeData;
import io.onedev.server.search.entity.issue.IssueQuery;
import io.onedev.server.search.entity.issue.IssueQueryParseOption;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@ -42,7 +42,7 @@ public class IssueInStateTrigger extends JobTrigger {
@SuppressWarnings("unused")
private static List<String> getStateChoices() {
return OneDev.getInstance(SettingService.class).getIssueSetting()
return OneDev.getInstance(SettingManager.class).getIssueSetting()
.getStateSpecs().stream().map(StateSpec::getName).collect(toList());
}

View File

@ -20,7 +20,7 @@ import io.onedev.server.web.util.WicketUtils;
import org.apache.wicket.Component;
import org.eclipse.jgit.revwalk.RevCommit;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.ArrayList;

View File

@ -5,7 +5,7 @@ import io.onedev.server.OneDev;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Patterns;
import io.onedev.server.buildspec.job.TriggerMatch;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.git.GitUtils;
import io.onedev.server.model.Project;
import io.onedev.server.model.PullRequest;
@ -15,7 +15,7 @@ import io.onedev.server.util.patternset.PatternSet;
import io.onedev.server.web.util.SuggestionUtils;
import org.eclipse.jgit.lib.Repository;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
@ -65,7 +65,7 @@ public abstract class PullRequestTrigger extends JobTrigger {
private boolean touchedFile(PullRequest request) {
if (getPaths() != null) {
Repository repository = OneDev.getInstance(ProjectService.class)
Repository repository = OneDev.getInstance(ProjectManager.class)
.getRepository(request.getTargetProject().getId());
Collection<String> changedFiles = GitUtils.getChangedFiles(repository,
request.getBaseCommit(), request.getLatestUpdate().getHeadCommit());

View File

@ -14,7 +14,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.buildspecmodel.inputspec.Input;
import io.onedev.server.util.Input;
public class ParamCombination implements Serializable {

View File

@ -17,7 +17,7 @@ import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.ValidationException;
import java.io.Serializable;
import java.util.*;

View File

@ -6,7 +6,7 @@ import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.param.ParamCombination;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.model.Build;
import io.onedev.server.buildspecmodel.inputspec.Input;
import io.onedev.server.util.Input;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

View File

@ -4,18 +4,17 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.constraints.NotEmpty;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import javax.validation.constraints.NotEmpty;
import io.onedev.commons.utils.ExplicitException;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.param.ParamCombination;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.buildspecmodel.inputspec.Input;
import io.onedev.server.model.Build;
import io.onedev.server.util.Input;
import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
@Editable(name="Use value of specified parameter/secret")
public class PassthroughValues implements ValuesProvider {

View File

@ -4,7 +4,7 @@ import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.param.ParamCombination;
import io.onedev.server.model.Build;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.List;

View File

@ -3,7 +3,7 @@ package io.onedev.server.buildspec.param.instance;
import java.io.Serializable;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import io.onedev.server.buildspec.param.ParamCombination;
import io.onedev.server.model.Build;

View File

@ -2,7 +2,7 @@ package io.onedev.server.buildspec.param.spec;
import java.util.List;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.Valid;
import io.onedev.server.annotation.Multiline;

View File

@ -7,14 +7,15 @@ import java.util.Map;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.buildspec.param.spec.choiceparam.defaultmultivalueprovider.DefaultMultiValueProvider;
import io.onedev.server.buildspec.param.spec.choiceparam.defaultvalueprovider.DefaultValueProvider;
import io.onedev.server.buildspecmodel.inputspec.choiceinput.ChoiceInput;
import io.onedev.server.buildspecmodel.inputspec.choiceinput.choiceprovider.ChoiceProvider;
import io.onedev.server.buildspecmodel.inputspec.choiceinput.choiceprovider.SpecifiedChoices;
import io.onedev.server.util.EditContext;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.ShowCondition;
@Editable(order=145, name= ParamSpec.ENUMERATION)
public class ChoiceParam extends ParamSpec {
@ -38,8 +39,8 @@ public class ChoiceParam extends ParamSpec {
this.choiceProvider = choiceProvider;
}
@ShowCondition("isDefaultValueProviderVisible")
@Editable(order=1100, name="Default Value", placeholder="No default value")
@DependsOn(property="allowMultiple", value="false")
@Valid
public DefaultValueProvider getDefaultValueProvider() {
return defaultValueProvider;
@ -49,8 +50,13 @@ public class ChoiceParam extends ParamSpec {
this.defaultValueProvider = defaultValueProvider;
}
@SuppressWarnings("unused")
private static boolean isDefaultValueProviderVisible() {
return EditContext.get().getInputValue("allowMultiple").equals(false);
}
@ShowCondition("isDefaultMultiValueProviderVisible")
@Editable(order=1100, name="Default Value", placeholder="No default value")
@DependsOn(property="allowMultiple")
@Valid
public DefaultMultiValueProvider getDefaultMultiValueProvider() {
return defaultMultiValueProvider;
@ -60,6 +66,11 @@ public class ChoiceParam extends ParamSpec {
this.defaultMultiValueProvider = defaultMultiValueProvider;
}
@SuppressWarnings("unused")
private static boolean isDefaultMultiValueProviderVisible() {
return EditContext.get().getInputValue("allowMultiple").equals(true);
}
@Override
public List<String> getPossibleValues() {
return ChoiceInput.getPossibleValues(choiceProvider);

View File

@ -6,14 +6,15 @@ import java.util.Map;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.buildspec.param.spec.ParamSpec;
import io.onedev.server.buildspec.param.spec.userchoiceparam.defaultmultivalueprovider.DefaultMultiValueProvider;
import io.onedev.server.buildspec.param.spec.userchoiceparam.defaultvalueprovider.DefaultValueProvider;
import io.onedev.server.buildspecmodel.inputspec.userchoiceinput.UserChoiceInput;
import io.onedev.server.buildspecmodel.inputspec.userchoiceinput.choiceprovider.AllUsers;
import io.onedev.server.buildspecmodel.inputspec.userchoiceinput.choiceprovider.ChoiceProvider;
import io.onedev.server.util.EditContext;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.ShowCondition;
@Editable(order=150, name= ParamSpec.USER)
public class UserChoiceParam extends ParamSpec {
@ -38,7 +39,7 @@ public class UserChoiceParam extends ParamSpec {
}
@Editable(order=1100, name="Default Value", placeholder="No default value")
@DependsOn(property="allowMultiple", value="false")
@ShowCondition("isDefaultValueProviderVisible")
@Valid
public DefaultValueProvider getDefaultValueProvider() {
return defaultValueProvider;
@ -48,8 +49,13 @@ public class UserChoiceParam extends ParamSpec {
this.defaultValueProvider = defaultValueProvider;
}
@SuppressWarnings("unused")
private static boolean isDefaultValueProviderVisible() {
return EditContext.get().getInputValue("allowMultiple").equals(false);
}
@ShowCondition("isDefaultMultiValueProviderVisible")
@Editable(order=1100, name="Default Value", placeholder="No default value")
@DependsOn(property="allowMultiple")
@Valid
public DefaultMultiValueProvider getDefaultMultiValueProvider() {
return defaultMultiValueProvider;
@ -59,6 +65,11 @@ public class UserChoiceParam extends ParamSpec {
this.defaultMultiValueProvider = defaultMultiValueProvider;
}
@SuppressWarnings("unused")
private static boolean isDefaultMultiValueProviderVisible() {
return EditContext.get().getInputValue("allowMultiple").equals(true);
}
@Override
public List<String> getPossibleValues() {
return UserChoiceInput.getPossibleValues();

View File

@ -7,7 +7,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ -83,7 +82,6 @@ public class BuildImageStep extends Step {
@Editable(order=1000, group="More Settings", description="Optionally specify registry logins to override " +
"those defined in job executor. For built-in registry, use <code>@server_url@</code> for registry url, " +
"<code>@job_token@</code> for user name, and access token secret for password secret")
@Valid
public List<RegistryLogin> getRegistryLogins() {
return registryLogins;
}

View File

@ -119,10 +119,6 @@ public class BuildImageWithKanikoStep extends CommandStep {
this.moreOptions = moreOptions;
}
static List<InputSuggestion> suggestVariables(String matchWith) {
return BuildSpec.suggestVariables(matchWith, true, true, false);
}
@Override
public Interpreter getInterpreter() {
return new DefaultInterpreter() {

View File

@ -2,7 +2,6 @@ package io.onedev.server.buildspec.step;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import io.onedev.commons.codeassist.InputSuggestion;
@ -36,7 +35,6 @@ public class CheckoutStep extends Step {
@Editable(order=100, description="By default code is cloned via an auto-generated credential, " +
"which only has read permission over current project. In case the job needs to <a href='https://docs.onedev.io/tutorials/cicd/commit-and-push' target='_blank'>push code to server</a>, " +
"you should supply custom credential with appropriate permissions here")
@Valid
@NotNull
public GitCredential getCloneCredential() {
return cloneCredential;

View File

@ -8,11 +8,11 @@ import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.IterationService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.IterationManager;
import io.onedev.server.model.Iteration;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.TransactionService;
import io.onedev.server.persistence.TransactionManager;
import javax.validation.constraints.NotEmpty;
import java.io.File;
@ -63,16 +63,16 @@ public class CloseIterationStep extends ServerSideStep {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(TransactionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
return OneDev.getInstance(TransactionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
Project project = build.getProject();
String iterationName = getIterationName();
IterationService iterationService = OneDev.getInstance(IterationService.class);
Iteration iteration = iterationService.findInHierarchy(project, iterationName);
IterationManager iterationManager = OneDev.getInstance(IterationManager.class);
Iteration iteration = iterationManager.findInHierarchy(project, iterationName);
if (iteration != null) {
if (build.canCloseIteration(getAccessTokenSecret())) {
iteration.setClosed(true);
iterationService.createOrUpdate(iteration);
iterationManager.createOrUpdate(iteration);
} else {
logger.error("This build is not authorized to close iteration '" + iterationName + "'");
return new ServerStepResult(false);

View File

@ -6,16 +6,15 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.k8shelper.StepFacade;
import io.onedev.server.annotation.DependsOn;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.RegEx;
import io.onedev.server.annotation.ShowCondition;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.buildspec.job.EnvVar;
import io.onedev.server.buildspec.param.ParamCombination;
@ -24,6 +23,7 @@ import io.onedev.server.buildspec.step.commandinterpreter.Interpreter;
import io.onedev.server.model.Build;
import io.onedev.server.model.support.administration.jobexecutor.DockerAware;
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
import io.onedev.server.util.EditContext;
@Editable(order=100, name="Execute Commands")
public class CommandStep extends Step {
@ -57,9 +57,14 @@ public class CommandStep extends Step {
public void setRunInContainer(boolean runInContainer) {
this.runInContainer = runInContainer;
}
@SuppressWarnings("unused")
private static boolean isRunInContainerEnabled() {
return (boolean) EditContext.get().getInputValue("runInContainer");
}
@Editable(order=100, name="container:image", description="Specify container image to execute commands inside")
@DependsOn(property="runInContainer")
@ShowCondition("isRunInContainerEnabled")
@Interpolative(variableSuggester="suggestVariables")
@NotEmpty
public String getImage() {
@ -71,17 +76,10 @@ public class CommandStep extends Step {
}
static List<InputSuggestion> suggestVariables(String matchWith) {
/*
* We do not support dynamic variable here as:
* 1. @file:@ notion will not work for workspace files generated in current step
* 2. It is very easy to use file content in shell script via shell utilities
* in regardless the file is generated in current or previous steps
*/
return BuildSpec.suggestVariables(matchWith, false, false, false);
}
@Editable(order=110)
@Valid
@NotNull
public Interpreter getInterpreter() {
return interpreter;
@ -94,7 +92,7 @@ public class CommandStep extends Step {
@Editable(order=8000, name="Run As", group = "More Settings", placeholder = "root", description = "Optionally specify uid:gid to run container as. " +
"<b class='text-warning'>Note:</b> This setting should be left empty if container runtime is rootless or " +
"using user namespace remapping")
@DependsOn(property="runInContainer")
@ShowCondition("isRunInContainerEnabled")
@RegEx(pattern="\\d+:\\d+", message = "Should be specified in form of <uid>:<gid>")
public String getRunAs() {
return runAs;
@ -107,8 +105,7 @@ public class CommandStep extends Step {
@Editable(order=8500, group="More Settings", description="Optionally specify registry logins to override " +
"those defined in job executor. For built-in registry, use <code>@server_url@</code> for registry url, " +
"<code>@job_token@</code> for user name, and access token secret for password secret")
@DependsOn(property="runInContainer")
@Valid
@ShowCondition("isRunInContainerEnabled")
public List<RegistryLogin> getRegistryLogins() {
return registryLogins;
}
@ -119,7 +116,6 @@ public class CommandStep extends Step {
@Editable(order=9900, name="Environment Variables", group="More Settings", description="Optionally specify environment "
+ "variables for this step")
@Valid
public List<EnvVar> getEnvVars() {
return envVars;
}
@ -129,7 +125,7 @@ public class CommandStep extends Step {
}
@Editable(order=10000, name="Enable TTY Mode", group = "More Settings", description=USE_TTY_HELP)
@DependsOn(property="runInContainer")
@ShowCondition("isRunInContainerEnabled")
public boolean isUseTTY() {
return useTTY;
}

View File

@ -1,22 +1,20 @@
package io.onedev.server.buildspec.step;
import static io.onedev.agent.DockerExecutorUtils.buildDockerConfig;
import static io.onedev.k8shelper.RegistryLoginFacade.merge;
import java.util.List;
import java.util.Map;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.k8shelper.CommandFacade;
import io.onedev.k8shelper.RegistryLoginFacade;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.Multiline;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.buildspec.step.commandinterpreter.DefaultInterpreter;
import io.onedev.server.buildspec.step.commandinterpreter.Interpreter;
import io.onedev.server.model.support.administration.jobexecutor.DockerAware;
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
import io.onedev.server.model.support.administration.jobexecutor.DockerAware;
import java.util.List;
import java.util.Map;
import static io.onedev.agent.DockerExecutorUtils.buildDockerConfig;
import static io.onedev.k8shelper.RegistryLoginFacade.merge;
public abstract class CraneStep extends CommandStep {
@ -72,10 +70,6 @@ public abstract class CraneStep extends CommandStep {
super.setRegistryLogins(registryLogins);
}
static List<InputSuggestion> suggestVariables(String matchWith) {
return BuildSpec.suggestVariables(matchWith, true, true, false);
}
@Override
public Interpreter getInterpreter() {
return new DefaultInterpreter() {

View File

@ -10,12 +10,12 @@ import io.onedev.server.annotation.ChoiceProvider;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.git.GitUtils;
import io.onedev.server.git.service.GitService;
import io.onedev.server.git.service.RefFacade;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.web.util.SuggestionUtils;
import org.eclipse.jgit.lib.Repository;
@ -93,8 +93,8 @@ public class CreateBranchStep extends ServerSideStep {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
Project project = build.getProject();
String branchName = getBranchName();

View File

@ -7,14 +7,14 @@ import io.onedev.k8shelper.ServerStepResult;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.*;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.UserService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.UserManager;
import io.onedev.server.git.GitUtils;
import io.onedev.server.git.service.GitService;
import io.onedev.server.git.service.RefFacade;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.SessionManager;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
@ -81,9 +81,9 @@ public class CreateTagStep extends ServerSideStep {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
PersonIdent taggerIdent = OneDev.getInstance(UserService.class).getSystem().asPerson();
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
PersonIdent taggerIdent = OneDev.getInstance(UserManager.class).getSystem().asPerson();
Project project = build.getProject();
String tagName = getTagName();
@ -95,7 +95,7 @@ public class CreateTagStep extends ServerSideStep {
if (build.canCreateTag(getAccessTokenSecret(), tagName)) {
RefFacade tagRef = project.getTagRef(tagName);
if (tagRef != null)
OneDev.getInstance(ProjectService.class).deleteTag(project, tagName);
OneDev.getInstance(ProjectManager.class).deleteTag(project, tagName);
OneDev.getInstance(GitService.class).createTag(project, tagName, build.getCommitHash(),
taggerIdent, getTagMessage(), false);
} else {

View File

@ -1,18 +1,15 @@
package io.onedev.server.buildspec.step;
import static io.onedev.server.buildspec.step.StepGroup.UTILITIES;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.buildspec.step.commandinterpreter.Interpreter;
import io.onedev.server.buildspec.step.commandinterpreter.ShellInterpreter;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import io.onedev.commons.codeassist.InputSuggestion;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.buildspec.step.commandinterpreter.Interpreter;
import io.onedev.server.buildspec.step.commandinterpreter.ShellInterpreter;
import static io.onedev.server.buildspec.step.StepGroup.UTILITIES;
@Editable(order=1110, group = UTILITIES, name="Generate File Checksum", description = "" +
"This step can only be executed by a docker aware executor")
@ -48,10 +45,6 @@ public class GenerateChecksumStep extends CommandStep {
this.targetFile = targetFile;
}
static List<InputSuggestion> suggestVariables(String matchWith) {
return BuildSpec.suggestVariables(matchWith, true, true, false);
}
@Override
public boolean isRunInContainer() {
return true;

View File

@ -6,15 +6,15 @@ import io.onedev.commons.utils.LockUtils;
import io.onedev.commons.utils.TaskLogger;
import io.onedev.k8shelper.ServerStepResult;
import io.onedev.server.OneDev;
import io.onedev.server.StorageService;
import io.onedev.server.StorageManager;
import io.onedev.server.annotation.Editable;
import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.Patterns;
import io.onedev.server.annotation.SubPath;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.util.patternset.PatternSet;
import javax.validation.constraints.NotEmpty;
@ -23,8 +23,7 @@ import java.util.List;
import static io.onedev.server.buildspec.step.StepGroup.PUBLISH;
@Editable(order=1050, group= PUBLISH, name="Artifacts", description="This step copies files from job workspace " +
"to build artifacts directory, so that they can be accessed after job is completed")
@Editable(order=1050, group= PUBLISH, name="Artifacts")
public class PublishArtifactStep extends ServerSideStep {
private static final long serialVersionUID = 1L;
@ -47,7 +46,8 @@ public class PublishArtifactStep extends ServerSideStep {
this.sourcePath = sourcePath;
}
@Editable(order=100, description="Specify files under above directory to be published")
@Editable(order=100, description="Specify files under above directory to be published. "
+ "Use * or ? for pattern match")
@Interpolative(variableSuggester="suggestVariables")
@Patterns(path=true)
@NotEmpty
@ -71,13 +71,13 @@ public class PublishArtifactStep extends ServerSideStep {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger jobLogger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
return LockUtils.write(build.getArtifactsLockName(), () -> {
var projectId = build.getProject().getId();
var artifactsDir = OneDev.getInstance(StorageService.class).initArtifactsDir(projectId, build.getNumber());
var artifactsDir = OneDev.getInstance(StorageManager.class).initArtifactsDir(projectId, build.getNumber());
FileUtils.copyDirectory(inputDir, artifactsDir);
OneDev.getInstance(ProjectService.class).directoryModified(projectId, artifactsDir);
OneDev.getInstance(ProjectManager.class).directoryModified(projectId, artifactsDir);
return new ServerStepResult(true);
});
});

View File

@ -20,13 +20,15 @@ import io.onedev.server.annotation.Patterns;
import io.onedev.server.annotation.ProjectChoice;
import io.onedev.server.annotation.SubPath;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.SettingService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.job.JobContext;
import io.onedev.server.job.JobService;
import io.onedev.server.job.JobManager;
import io.onedev.server.model.Build;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.util.patternset.PatternSet;
@Editable(order=1060, name="Site", group = PUBLISH, description="This step publishes specified files to be served as project web site. "
@ -92,13 +94,13 @@ public class PublishSiteStep extends ServerSideStep {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
JobContext jobContext = OneDev.getInstance(JobService.class).getJobContext(build.getId());
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
JobContext jobContext = OneDev.getInstance(JobManager.class).getJobContext(build.getId());
if (jobContext.getJobExecutor().isSitePublishEnabled()) {
Project project;
if (projectPath != null) {
project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
if (project == null) {
logger.error("Unable to find project: " + projectPath);
return new ServerStepResult(false);
@ -108,13 +110,13 @@ public class PublishSiteStep extends ServerSideStep {
}
var projectId = project.getId();
LockUtils.write(project.getSiteLockName(), () -> {
File projectSiteDir = OneDev.getInstance(ProjectService.class).getSiteDir(projectId);
File projectSiteDir = OneDev.getInstance(ProjectManager.class).getSiteDir(projectId);
FileUtils.cleanDir(projectSiteDir);
FileUtils.copyDirectory(inputDir, projectSiteDir);
OneDev.getInstance(ProjectService.class).directoryModified(projectId, projectSiteDir);
OneDev.getInstance(ProjectManager.class).directoryModified(projectId, projectSiteDir);
return null;
});
String serverUrl = OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
String serverUrl = OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
logger.log("Site published as "
+ StringUtils.stripEnd(serverUrl, "/") + "/" + project.getPath() + "/~site");
} else {
@ -125,4 +127,9 @@ public class PublishSiteStep extends ServerSideStep {
});
}
@Override
public boolean isApplicable(Build build, JobExecutor executor) {
return executor.isSitePublishEnabled();
}
}

View File

@ -6,7 +6,6 @@ import static io.onedev.server.web.translation.Translation._T;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@ -14,7 +13,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.jspecify.annotations.Nullable;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import org.eclipse.jgit.lib.AnyObjectId;
@ -45,9 +44,8 @@ import io.onedev.server.annotation.Interpolative;
import io.onedev.server.annotation.ProjectChoice;
import io.onedev.server.buildspec.BuildSpec;
import io.onedev.server.cluster.ClusterTask;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.service.UserService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.event.ListenerRegistry;
import io.onedev.server.event.project.RefUpdated;
import io.onedev.server.git.CommandUtils;
@ -56,8 +54,7 @@ import io.onedev.server.git.command.LfsFetchAllCommand;
import io.onedev.server.git.command.LfsFetchCommand;
import io.onedev.server.git.service.RefFacade;
import io.onedev.server.model.Project;
import io.onedev.server.model.User;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.SessionManager;
import io.onedev.server.security.SecurityUtils;
@Editable(order=1070, name="Pull from Remote", group=StepGroup.REPOSITORY_SYNC, description=""
@ -139,12 +136,12 @@ public class PullRepository extends SyncRepository {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
Project project = build.getProject();
Project targetProject;
if (getTargetProject() != null) {
targetProject = getProjectService().findByPath(getTargetProject());
targetProject = getProjectManager().findByPath(getTargetProject());
if (targetProject == null)
throw new ExplicitException("Target project not found: " + getTargetProject());
} else {
@ -161,34 +158,21 @@ public class PullRepository extends SyncRepository {
if (!authorized)
throw new ExplicitException("This build is not authorized to sync to project: " + targetProject.getPath());
Long userId;
if (getAccessTokenSecret() != null) {
userId = build.getAccessToken(getAccessTokenSecret()).getOwner().getId();
} else {
userId = User.SYSTEM_ID;
}
String remoteUrl = getRemoteUrlWithCredential(build);
Long targetProjectId = targetProject.getId();
var task = new PullTask(targetProjectId, userId, remoteUrl, getCertificate(), getRefs(), isForce(), isWithLfs(), getProxy(), build.getSecretMasker());
getProjectService().runOnActiveServer(targetProjectId, task);
var task = new PullTask(targetProjectId, remoteUrl, getCertificate(), getRefs(), isForce(), isWithLfs(), getProxy(), build.getSecretMasker());
getProjectManager().runOnActiveServer(targetProjectId, task);
return new ServerStepResult(true);
});
}
private static ProjectService getProjectService() {
return OneDev.getInstance(ProjectService.class);
}
private static UserService getUserService() {
return OneDev.getInstance(UserService.class);
private static ProjectManager getProjectManager() {
return OneDev.getInstance(ProjectManager.class);
}
private static class PullTask implements ClusterTask<Void> {
private final Long projectId;
private final Long userId;
private final String remoteUrl;
@ -204,11 +188,10 @@ public class PullRepository extends SyncRepository {
private final SecretMasker secretMasker;
PullTask(Long projectId, Long userId, String remoteUrl, @Nullable String certificate,
PullTask(Long projectId, String remoteUrl, @Nullable String certificate,
String refs, boolean force, boolean withLfs, @Nullable String proxy,
SecretMasker secretMasker) {
this.projectId = projectId;
this.userId = userId;
this.remoteUrl = remoteUrl;
this.certificate = certificate;
this.refs = refs;
@ -242,7 +225,7 @@ public class PullRepository extends SyncRepository {
var certificateFile = writeCertificate(certificate);
SecretMasker.push(secretMasker);
try {
Repository repository = getProjectService().getRepository(projectId);
Repository repository = getProjectManager().getRepository(projectId);
String defaultBranch = GitUtils.getDefaultBranch(repository);
Map<String, ObjectId> oldCommitIds = getRefCommits(repository);
@ -361,7 +344,7 @@ public class PullRepository extends SyncRepository {
git.clearArgs();
configureProxy(git, proxy);
configureCertificate(git, certificateFile);
var sinceCommitIds = getProjectService().readLfsSinceCommits(projectId);
var sinceCommitIds = getProjectManager().readLfsSinceCommits(projectId);
if (sinceCommitIds.isEmpty()) {
new LfsFetchAllCommand(git.workingDir(), remoteUrl) {
@ -379,28 +362,27 @@ public class PullRepository extends SyncRepository {
}
}.run();
}
getProjectService().writeLfsSinceCommits(projectId, newCommitIds.values());
getProjectManager().writeLfsSinceCommits(projectId, newCommitIds.values());
}
OneDev.getInstance(SessionService.class).runAsync(() -> {
OneDev.getInstance(SessionManager.class).runAsync(() -> {
try {
// Access db connection in a separate thread to avoid possible deadlock, as
// the parent thread is blocking another thread holding database connections
var project = getProjectService().load(projectId);
var user = getUserService().load(userId);
var project = getProjectManager().load(projectId);
MapDifference<String, ObjectId> difference = difference(oldCommitIds, newCommitIds);
ListenerRegistry registry = OneDev.getInstance(ListenerRegistry.class);
for (Map.Entry<String, ObjectId> entry : difference.entriesOnlyOnLeft().entrySet()) {
if (RefUpdated.isValidRef(entry.getKey()))
registry.post(new RefUpdated(user, project, entry.getKey(), entry.getValue(), ObjectId.zeroId()));
registry.post(new RefUpdated(project, entry.getKey(), entry.getValue(), ObjectId.zeroId()));
}
for (Map.Entry<String, ObjectId> entry : difference.entriesOnlyOnRight().entrySet()) {
if (RefUpdated.isValidRef(entry.getKey()))
registry.post(new RefUpdated(user, project, entry.getKey(), ObjectId.zeroId(), entry.getValue()));
registry.post(new RefUpdated(project, entry.getKey(), ObjectId.zeroId(), entry.getValue()));
}
for (Map.Entry<String, ValueDifference<ObjectId>> entry : difference.entriesDiffering().entrySet()) {
if (RefUpdated.isValidRef(entry.getKey())) {
registry.post(new RefUpdated(user, project, entry.getKey(),
registry.post(new RefUpdated(project, entry.getKey(),
entry.getValue().leftValue(), entry.getValue().rightValue()));
}
}

View File

@ -16,12 +16,12 @@ import io.onedev.commons.utils.command.LineConsumer;
import io.onedev.k8shelper.ServerStepResult;
import io.onedev.server.OneDev;
import io.onedev.server.annotation.Editable;
import io.onedev.server.service.BuildService;
import io.onedev.server.service.ProjectService;
import io.onedev.server.entitymanager.BuildManager;
import io.onedev.server.entitymanager.ProjectManager;
import io.onedev.server.git.CommandUtils;
import io.onedev.server.git.GitUtils;
import io.onedev.server.model.Project;
import io.onedev.server.persistence.SessionService;
import io.onedev.server.persistence.SessionManager;
@Editable(order=1080, name="Push to Remote", group=StepGroup.REPOSITORY_SYNC,
description="This step pushes current commit to same ref on remote")
@ -31,15 +31,15 @@ public class PushRepository extends SyncRepository {
@Override
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
return OneDev.getInstance(SessionService.class).call(() -> {
var build = OneDev.getInstance(BuildService.class).load(buildId);
return OneDev.getInstance(SessionManager.class).call(() -> {
var build = OneDev.getInstance(BuildManager.class).load(buildId);
var certificateFile = writeCertificate(getCertificate());
SecretMasker.push(build.getSecretMasker());
try {
if (OneDev.getInstance(ProjectService.class).hasLfsObjects(build.getProject().getId())) {
if (OneDev.getInstance(ProjectManager.class).hasLfsObjects(build.getProject().getId())) {
Project project = build.getProject();
Commandline git = CommandUtils.newGit();
git.workingDir(OneDev.getInstance(ProjectService.class).getGitDir(project.getId()));
git.workingDir(OneDev.getInstance(ProjectManager.class).getGitDir(project.getId()));
configureProxy(git, getProxy());
configureCertificate(git, certificateFile);
@ -89,7 +89,7 @@ public class PushRepository extends SyncRepository {
}).checkReturnCode();
Repository repository = OneDev.getInstance(ProjectService.class)
Repository repository = OneDev.getInstance(ProjectManager.class)
.getRepository(project.getId());
String mergeBaseId = GitUtils.getMergeBase(repository,
ObjectId.fromString(remoteCommitId.get()), build.getCommitId()).name();
@ -143,7 +143,7 @@ public class PushRepository extends SyncRepository {
Commandline git = CommandUtils.newGit();
configureProxy(git, getProxy());
configureCertificate(git, certificateFile);
git.workingDir(OneDev.getInstance(ProjectService.class).getGitDir(build.getProject().getId()));
git.workingDir(OneDev.getInstance(ProjectManager.class).getGitDir(build.getProject().getId()));
git.addArgs("push");
if (isForce())
git.addArgs("--force");

Some files were not shown because too many files have changed in this diff Show More