mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c756c74ca | ||
|
|
241c70d10d | ||
|
|
abcc00f051 | ||
|
|
4051221b95 | ||
|
|
eff4d2a658 | ||
|
|
4e7fcd1807 | ||
|
|
8554de9e13 | ||
|
|
b3d207a835 | ||
|
|
136426bcdd | ||
|
|
86ed0e4aac | ||
|
|
b9ee6f987b | ||
|
|
44ec074b93 | ||
|
|
3b0de1e0ec | ||
|
|
82fe2253ff | ||
|
|
d392f3def0 | ||
|
|
a73df6edd1 | ||
|
|
e2150b12fd | ||
|
|
9fdbf390b3 | ||
|
|
1875200269 | ||
|
|
7b4e6ef9be | ||
|
|
b6970fb247 | ||
|
|
061d672774 | ||
|
|
4220b1130f | ||
|
|
3e753b6adc | ||
|
|
682620965c | ||
|
|
13d9281484 | ||
|
|
d54de0ec27 | ||
|
|
c6a74dc008 | ||
|
|
706b2dbdba | ||
|
|
a62db8265f | ||
|
|
1eb8bda97e | ||
|
|
b465a1fd78 | ||
|
|
2b9237b8b1 | ||
|
|
7e77167833 | ||
|
|
1157f4e8ba | ||
|
|
9104c8eb9a | ||
|
|
cb86f2087e | ||
|
|
8a45bb03f7 | ||
|
|
3c44f81687 | ||
|
|
7400902735 | ||
|
|
5f5c114cdd | ||
|
|
ecace0afe3 | ||
|
|
c40ed5b998 | ||
|
|
573cf4ebf2 | ||
|
|
64e83d995b | ||
|
|
db28406eeb | ||
|
|
e0d5a6682f | ||
|
|
59315b3f81 | ||
|
|
0a5860d153 | ||
|
|
25e3991ba9 | ||
|
|
618dbaf297 | ||
|
|
b8a4d7cdc2 | ||
|
|
16a4178fef | ||
|
|
2f0311fe8a | ||
|
|
963bdaa0fa | ||
|
|
c0c8c585c1 | ||
|
|
d8cdd0e327 | ||
|
|
6b597c6c5b | ||
|
|
a32ff3f759 | ||
|
|
4fd8bc3bf9 | ||
|
|
b84c56da53 | ||
|
|
1ccdde6087 | ||
|
|
0c85caedfa | ||
|
|
7eee7de067 | ||
|
|
d0c7a68be9 | ||
|
|
b5c65ccb48 | ||
|
|
e3b23bd5ba | ||
|
|
a68f9784b0 | ||
|
|
ab13f659e3 | ||
|
|
d3e227d591 | ||
|
|
f6a2273471 | ||
|
|
aeb94bc272 | ||
|
|
0defe8b62a | ||
|
|
a77172ef43 | ||
|
|
6158adefe2 | ||
|
|
3e16c2fe66 | ||
|
|
207fcb65e8 | ||
|
|
77cf1da58c | ||
|
|
a6fb15d7a9 | ||
|
|
e8acd1f16c | ||
|
|
aecc79fa11 | ||
|
|
146633f2d0 | ||
|
|
9b1db1c604 | ||
|
|
3939404717 | ||
|
|
66a6315e37 | ||
|
|
6358860df2 | ||
|
|
8bb5dce066 | ||
|
|
2e187d3cc5 | ||
|
|
53e91f8520 | ||
|
|
f87ceb0d13 | ||
|
|
2cb6b6b7fa | ||
|
|
2a1a2a5a43 | ||
|
|
67c4a5c334 | ||
|
|
af6cf4ad81 | ||
|
|
81d14f1274 | ||
|
|
18a69b8b25 | ||
|
|
3f024b687b | ||
|
|
78b31191cc | ||
|
|
9c1373442b | ||
|
|
f717f5ecd8 | ||
|
|
75578c4c41 | ||
|
|
9f3ad0bc11 | ||
|
|
1e477e2347 | ||
|
|
5df04de721 | ||
|
|
4c626f4f88 | ||
|
|
b19eedb4b4 | ||
|
|
afddedc308 | ||
|
|
7b8e9f7cba | ||
|
|
0004fd0ab6 | ||
|
|
f8bd75fa16 | ||
|
|
f6c8d8ba7f | ||
|
|
ccda03e517 | ||
|
|
845f20e53c | ||
|
|
de59055c84 | ||
|
|
2479d74b13 | ||
|
|
63fe24a8f4 | ||
|
|
b4ad529e68 | ||
|
|
d9f9fa03e6 | ||
|
|
dc4af70ff1 | ||
|
|
ada4da245b | ||
|
|
e4143f75b1 | ||
|
|
116231f8a5 | ||
|
|
f60d2db271 | ||
|
|
249d1784e7 | ||
|
|
7b0defc133 | ||
|
|
27c0204bb0 | ||
|
|
1347345d61 | ||
|
|
b46dfb8637 | ||
|
|
af58b47205 | ||
|
|
4c0f2c96db | ||
|
|
c01570f4c0 | ||
|
|
634279171b | ||
|
|
593db97cd3 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
server-product/docker/build/
|
||||
server-product/docker/onedev-*/
|
||||
**/target/
|
||||
target/
|
||||
bin/
|
||||
**/.classpath
|
||||
**/.gitignore
|
||||
**/.settings
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "server-ee"]
|
||||
path = server-ee
|
||||
url = https://code.onedev.io/onedev/server-ee
|
||||
url = https://code.onedev.io/onedev/server-ee.git
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
CVE-2024-53299
|
||||
CVE-2024-57699
|
||||
CVE-2024-57699
|
||||
|
||||
175
CLAUDE.md
Normal file
175
CLAUDE.md
Normal file
@ -0,0 +1,175 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Build Commands
|
||||
|
||||
OneDev uses Maven as its build system with a multi-module structure.
|
||||
|
||||
### Essential Commands
|
||||
- **Build the project**: `mvn clean compile`
|
||||
- **Run tests**: `mvn test`
|
||||
- **Package the application**: `mvn clean package`
|
||||
- **Build without tests**: `mvn clean package -DskipTests`
|
||||
- **Build specific module**: `mvn clean package -pl server-core`
|
||||
- **Install to local repository**: `mvn clean install`
|
||||
|
||||
### Profiles
|
||||
- **Community Edition**: `mvn clean package -Pce` (excludes enterprise features)
|
||||
- **Default/Enterprise**: `mvn clean package` (includes all features)
|
||||
|
||||
### Testing
|
||||
- **Run all tests**: `mvn test`
|
||||
- **Run specific test class**: `mvn test -Dtest=ClassName`
|
||||
- **Run tests for specific module**: `mvn test -pl server-core`
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
OneDev is a comprehensive DevOps platform built with a sophisticated multi-module Maven architecture:
|
||||
|
||||
### Core Technology Stack
|
||||
- **Web Framework**: Apache Wicket 7.18.0 (component-based UI)
|
||||
- **REST API**: Jersey 2.38 (JAX-RS implementation)
|
||||
- **Database/ORM**: Hibernate 5.4.24.Final with HikariCP connection pooling
|
||||
- **Web Server**: Embedded Jetty 9.4.57
|
||||
- **Dependency Injection**: Google Guice with custom plugin loading
|
||||
- **Security**: Apache Shiro for authentication/authorization
|
||||
- **Search**: Apache Lucene 8.7.0
|
||||
- **Git**: JGit 5.13.3 for Git operations
|
||||
- **Clustering**: Hazelcast 5.3.5 for distributed coordination
|
||||
|
||||
### Module Structure
|
||||
- **server-core**: Core application logic, entities, and services
|
||||
- **server-ee**: Enterprise edition features
|
||||
- **server-plugin**: Plugin framework and all plugin implementations
|
||||
- **server-product**: Final packaging and deployment artifacts
|
||||
|
||||
### Key Subsystems
|
||||
|
||||
#### 1. Application Bootstrap
|
||||
- Main entry point: `server-core/src/main/java/io/onedev/server/OneDev.java`
|
||||
- Module configuration: `server-core/src/main/java/io/onedev/server/CoreModule.java`
|
||||
- Handles server lifecycle, clustering, and graceful shutdown
|
||||
|
||||
#### 2. Entity Management
|
||||
Key domain entities and managers in `server-core/src/main/java/io/onedev/server/model/`:
|
||||
- Project, User, Group, Role management
|
||||
- Issue tracking with customizable workflows
|
||||
- Pull request lifecycle and code review
|
||||
- Build and CI/CD pipeline management
|
||||
- Package registry operations
|
||||
|
||||
#### 3. Git Integration
|
||||
- Full Git repository management via JGit
|
||||
- Git hooks for policy enforcement in `server-core/src/main/java/io/onedev/server/git/`
|
||||
- Code browsing, diff visualization, and blame tracking
|
||||
- SSH server for Git operations
|
||||
|
||||
#### 4. Web Layer (Wicket)
|
||||
- Component-based UI in `server-core/src/main/java/io/onedev/server/web/`
|
||||
- AJAX-heavy interface with WebSocket support
|
||||
- Project browsing, issue boards, pull request review interface
|
||||
|
||||
#### 5. REST API (Jersey)
|
||||
- RESTful services in `server-core/src/main/java/io/onedev/server/rest/`
|
||||
- Project, User, Build, Issue resources
|
||||
- WebHook endpoints and package registry APIs
|
||||
|
||||
#### 6. CI/CD System
|
||||
- YAML-based build specifications
|
||||
- Multi-executor support (Kubernetes, Docker, Shell)
|
||||
- Real-time log streaming and artifact management
|
||||
|
||||
#### 7. Plugin Architecture
|
||||
- Extensible plugin system in `server-plugin/`
|
||||
- Categories: build specs, executors, authenticators, importers, notifications, package registries, report processors
|
||||
- Plugin contributions via Guice modules
|
||||
|
||||
## Development Patterns
|
||||
|
||||
### Code Organization
|
||||
- **Package-by-feature**: Organized around business capabilities
|
||||
- **Dependency Injection**: Guice-based DI throughout the application
|
||||
- **Interface-based design**: For testability and modularity
|
||||
- **Custom annotations**: Extensive use for validation and metadata
|
||||
|
||||
### Design Patterns Used
|
||||
- Repository Pattern for data access
|
||||
- Observer Pattern for event handling
|
||||
- Command Pattern for Git operations
|
||||
- Strategy Pattern for pluggable components
|
||||
- Template Method for build processing
|
||||
|
||||
### Testing Strategy
|
||||
- Unit tests in `src/test/java` directories
|
||||
- Git operation tests with test repositories
|
||||
- Component and integration tests
|
||||
- Utility method tests
|
||||
- Focus on testing business logic and Git operations
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Working with Entities
|
||||
- Entities are in `server-core/src/main/java/io/onedev/server/model/`
|
||||
- Use corresponding managers for database operations
|
||||
- Follow JPA/Hibernate patterns for persistence
|
||||
|
||||
### Adding REST Endpoints
|
||||
- Create resources in `server-core/src/main/java/io/onedev/server/rest/resource/`
|
||||
- Follow Jersey/JAX-RS patterns
|
||||
- Use existing security annotations for authentication
|
||||
|
||||
### Creating Plugins
|
||||
- Extend `AbstractPlugin` class
|
||||
- Implement appropriate interfaces for the plugin category
|
||||
- Add Guice module configuration
|
||||
- Place in appropriate `server-plugin/server-plugin-*` module
|
||||
|
||||
### Working with Git
|
||||
- Use JGit APIs through OneDev's Git service layer
|
||||
- Follow patterns in `server-core/src/main/java/io/onedev/server/git/`
|
||||
- Handle Git operations asynchronously when possible
|
||||
|
||||
### Adding Web Components
|
||||
- Create Wicket components in `server-core/src/main/java/io/onedev/server/web/`
|
||||
- Follow existing component patterns and CSS frameworks
|
||||
- Use AJAX for dynamic behavior
|
||||
|
||||
## Configuration and Deployment
|
||||
|
||||
### Key Configuration Files
|
||||
- `server-product/system/conf/server.properties`: HTTP/SSH ports, clustering
|
||||
- `server-product/system/conf/hibernate.properties`: Database configuration
|
||||
- `server-product/system/conf/logback.xml`: Logging configuration
|
||||
|
||||
### Deployment Options
|
||||
- Standalone JAR with embedded Jetty
|
||||
- Docker containers (see `server-product/docker/`)
|
||||
- Kubernetes via Helm charts (see `server-product/helm/`)
|
||||
|
||||
### Database Support
|
||||
- PostgreSQL (recommended for production)
|
||||
- MySQL/MariaDB
|
||||
- HSQLDB (development/testing)
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching
|
||||
- Hibernate second-level cache with Hazelcast
|
||||
- Build artifact caching
|
||||
- Git object caching
|
||||
- Web resource bundling
|
||||
|
||||
### Clustering
|
||||
- Hazelcast-based clustering for high availability
|
||||
- Distributed session management
|
||||
- Leader election for coordinated operations
|
||||
|
||||
## Important Notes
|
||||
|
||||
- OneDev uses a custom plugin loading framework
|
||||
- Git operations are central to the application architecture
|
||||
- The system supports both community (CE) and enterprise (EE) editions
|
||||
- Extensive use of Guice for dependency injection and plugin management
|
||||
- Focus on performance and resource efficiency
|
||||
- Battle-tested in production environments for 5+ years
|
||||
7
development.md
Normal file
7
development.md
Normal file
@ -0,0 +1,7 @@
|
||||
# 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
|
||||
BIN
doc/images/mcp.png
Normal file
BIN
doc/images/mcp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 386 KiB |
@ -43,4 +43,5 @@ OD-2248
|
||||
OD-2257
|
||||
OD-2358
|
||||
OD-2403
|
||||
OD-2467
|
||||
OD-2467
|
||||
OD-2552
|
||||
34
pom.xml
34
pom.xml
@ -6,10 +6,10 @@
|
||||
<parent>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<version>1.3.0</version>
|
||||
</parent>
|
||||
<artifactId>server</artifactId>
|
||||
<version>12.0.2</version>
|
||||
<version>13.1.3</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.6.9</version>
|
||||
<version>2.7.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<?m2e execute onConfiguration,onIncremental?>
|
||||
@ -227,6 +227,11 @@
|
||||
<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>
|
||||
@ -275,7 +280,7 @@
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>oauth2-oidc-sdk</artifactId>
|
||||
<version>11.9.1</version>
|
||||
<version>11.28</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
@ -315,7 +320,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.0.1-jre</version>
|
||||
<version>33.5.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
@ -622,6 +627,16 @@
|
||||
<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>
|
||||
@ -641,8 +656,8 @@
|
||||
</repository>
|
||||
</repositories>
|
||||
<properties>
|
||||
<commons.version>3.0.13</commons.version>
|
||||
<agent.version>2.2.17</agent.version>
|
||||
<commons.version>3.1.1</commons.version>
|
||||
<agent.version>2.3.3</agent.version>
|
||||
<slf4j.version>2.0.9</slf4j.version>
|
||||
<logback.version>1.4.14</logback.version>
|
||||
<antlr.version>4.7.2</antlr.version>
|
||||
@ -654,9 +669,10 @@
|
||||
<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.19</groovy.version>
|
||||
<groovy.version>3.0.25</groovy.version>
|
||||
<servlet.version>3.1.0</servlet.version>
|
||||
<jackson.version>2.15.0</jackson.version>
|
||||
<tika.version>1.28.3</tika.version>
|
||||
<tika.version>3.2.2</tika.version>
|
||||
<langchain4j.version>1.8.0</langchain4j.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
@ -148,6 +148,14 @@ query to get notified of interesting events.
|
||||
|
||||

|
||||
|
||||
## 🤖 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)
|
||||
|
||||

|
||||
|
||||
## 🎛️ Dashboard for teams and users
|
||||
|
||||
Arrange gadgets in custom dashboard to get important information
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>io.onedev</groupId>
|
||||
<artifactId>server</artifactId>
|
||||
<version>12.0.2</version>
|
||||
<version>13.1.3</version>
|
||||
</parent>
|
||||
<build>
|
||||
<plugins>
|
||||
@ -274,6 +274,10 @@
|
||||
<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>
|
||||
@ -371,20 +375,18 @@
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-util</artifactId>
|
||||
<version>9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib-jdk7</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-open-ai</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<kotlin.version>1.9.23</kotlin.version>
|
||||
|
||||
@ -0,0 +1,327 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ 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;
|
||||
@ -23,6 +24,9 @@ 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;
|
||||
@ -71,8 +75,11 @@ import io.onedev.commons.utils.ExceptionUtils;
|
||||
import io.onedev.commons.utils.StringUtils;
|
||||
import io.onedev.k8shelper.KubernetesHelper;
|
||||
import io.onedev.k8shelper.OsInfo;
|
||||
import io.onedev.server.attachment.AttachmentManager;
|
||||
import io.onedev.server.attachment.DefaultAttachmentManager;
|
||||
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.buildspec.job.log.instruction.LogInstruction;
|
||||
import io.onedev.server.cluster.ClusterResource;
|
||||
import io.onedev.server.codequality.CodeProblemContribution;
|
||||
@ -85,182 +92,10 @@ 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.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.data.DataService;
|
||||
import io.onedev.server.data.DefaultDataService;
|
||||
import io.onedev.server.entityreference.DefaultReferenceChangeService;
|
||||
import io.onedev.server.entityreference.ReferenceChangeService;
|
||||
import io.onedev.server.event.DefaultListenerRegistry;
|
||||
import io.onedev.server.event.ListenerRegistry;
|
||||
import io.onedev.server.exception.handler.ExceptionHandler;
|
||||
@ -275,23 +110,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.DefaultSignatureVerificationManager;
|
||||
import io.onedev.server.git.signatureverification.SignatureVerificationManager;
|
||||
import io.onedev.server.git.signatureverification.DefaultSignatureVerificationService;
|
||||
import io.onedev.server.git.signatureverification.SignatureVerificationService;
|
||||
import io.onedev.server.git.signatureverification.SignatureVerifier;
|
||||
import io.onedev.server.jetty.DefaultJettyManager;
|
||||
import io.onedev.server.jetty.DefaultJettyService;
|
||||
import io.onedev.server.jetty.DefaultSessionDataStoreFactory;
|
||||
import io.onedev.server.jetty.JettyManager;
|
||||
import io.onedev.server.job.DefaultJobManager;
|
||||
import io.onedev.server.jetty.JettyService;
|
||||
import io.onedev.server.job.DefaultJobService;
|
||||
import io.onedev.server.job.DefaultResourceAllocator;
|
||||
import io.onedev.server.job.JobManager;
|
||||
import io.onedev.server.job.JobService;
|
||||
import io.onedev.server.job.ResourceAllocator;
|
||||
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.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.markdown.HtmlProcessor;
|
||||
import io.onedev.server.markdown.MarkdownManager;
|
||||
import io.onedev.server.markdown.MarkdownService;
|
||||
import io.onedev.server.model.support.administration.GroovyScript;
|
||||
import io.onedev.server.model.support.administration.authenticator.Authenticator;
|
||||
import io.onedev.server.notification.BuildNotificationManager;
|
||||
@ -302,21 +137,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.DefaultIdManager;
|
||||
import io.onedev.server.persistence.DefaultSessionFactoryManager;
|
||||
import io.onedev.server.persistence.DefaultSessionManager;
|
||||
import io.onedev.server.persistence.DefaultTransactionManager;
|
||||
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.HibernateInterceptor;
|
||||
import io.onedev.server.persistence.IdManager;
|
||||
import io.onedev.server.persistence.IdService;
|
||||
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.TransactionManager;
|
||||
import io.onedev.server.persistence.TransactionService;
|
||||
import io.onedev.server.persistence.annotation.Sessional;
|
||||
import io.onedev.server.persistence.annotation.Transactional;
|
||||
import io.onedev.server.persistence.dao.Dao;
|
||||
@ -327,16 +162,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.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.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.security.BasicAuthenticationFilter;
|
||||
import io.onedev.server.security.BearerAuthenticationFilter;
|
||||
import io.onedev.server.security.CodePullAuthorizationSource;
|
||||
@ -348,26 +183,208 @@ 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.DefaultSshManager;
|
||||
import io.onedev.server.ssh.DefaultSshService;
|
||||
import io.onedev.server.ssh.SshAuthenticator;
|
||||
import io.onedev.server.ssh.SshManager;
|
||||
import io.onedev.server.ssh.SshService;
|
||||
import io.onedev.server.taskschedule.DefaultTaskScheduler;
|
||||
import io.onedev.server.taskschedule.TaskScheduler;
|
||||
import io.onedev.server.updatecheck.DefaultUpdateCheckManager;
|
||||
import io.onedev.server.updatecheck.UpdateCheckManager;
|
||||
import io.onedev.server.updatecheck.DefaultUpdateCheckService;
|
||||
import io.onedev.server.updatecheck.UpdateCheckService;
|
||||
import io.onedev.server.util.ScriptContribution;
|
||||
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.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.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.DefaultOAuthTokenManager;
|
||||
import io.onedev.server.util.oauth.OAuthTokenManager;
|
||||
import io.onedev.server.util.oauth.DefaultOAuthTokenService;
|
||||
import io.onedev.server.util.oauth.OAuthTokenService;
|
||||
import io.onedev.server.util.xstream.CollectionConverter;
|
||||
import io.onedev.server.util.xstream.HibernateProxyConverter;
|
||||
import io.onedev.server.util.xstream.MapConverter;
|
||||
@ -376,15 +393,17 @@ 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.DefaultUrlManager;
|
||||
import io.onedev.server.web.DefaultUrlService;
|
||||
import io.onedev.server.web.DefaultWicketFilter;
|
||||
import io.onedev.server.web.DefaultWicketServlet;
|
||||
import io.onedev.server.web.ResourcePackScopeContribution;
|
||||
import io.onedev.server.web.UrlManager;
|
||||
import io.onedev.server.web.SessionListener;
|
||||
import io.onedev.server.web.UrlService;
|
||||
import io.onedev.server.web.WebApplication;
|
||||
import io.onedev.server.web.avatar.AvatarManager;
|
||||
import io.onedev.server.web.avatar.DefaultAvatarManager;
|
||||
import io.onedev.server.web.avatar.AvatarService;
|
||||
import io.onedev.server.web.avatar.DefaultAvatarService;
|
||||
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;
|
||||
@ -397,24 +416,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.DefaultUploadManager;
|
||||
import io.onedev.server.web.upload.UploadManager;
|
||||
import io.onedev.server.web.upload.DefaultUploadService;
|
||||
import io.onedev.server.web.upload.UploadService;
|
||||
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.DefaultWebSocketManager;
|
||||
import io.onedev.server.web.websocket.DefaultWebSocketService;
|
||||
import io.onedev.server.web.websocket.IssueEventBroadcaster;
|
||||
import io.onedev.server.web.websocket.PullRequestEventBroadcaster;
|
||||
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 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 nl.altindag.ssl.SSLFactory;
|
||||
|
||||
/**
|
||||
@ -428,8 +447,8 @@ public class CoreModule extends AbstractPluginModule {
|
||||
super.configure();
|
||||
|
||||
bind(ListenerRegistry.class).to(DefaultListenerRegistry.class);
|
||||
bind(JettyManager.class).to(DefaultJettyManager.class);
|
||||
bind(ServletContextHandler.class).toProvider(DefaultJettyManager.class);
|
||||
bind(JettyService.class).to(DefaultJettyService.class);
|
||||
bind(ServletContextHandler.class).toProvider(DefaultJettyService.class);
|
||||
|
||||
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class).in(Singleton.class);
|
||||
|
||||
@ -440,8 +459,31 @@ 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();
|
||||
@ -455,122 +497,127 @@ public class CoreModule extends AbstractPluginModule {
|
||||
* HK2 to guice bridge can only search in explicit bindings in Guice
|
||||
*/
|
||||
bind(SshAuthenticator.class).to(DefaultSshAuthenticator.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(SshService.class).to(DefaultSshService.class);
|
||||
bind(MarkdownService.class).to(DefaultMarkdownService.class);
|
||||
bind(SettingService.class).to(DefaultSettingService.class);
|
||||
bind(DataService.class).to(DefaultDataService.class);
|
||||
bind(TaskScheduler.class).to(DefaultTaskScheduler.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(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(PullRequestNotificationManager.class);
|
||||
bind(CommitNotificationManager.class);
|
||||
bind(BuildNotificationManager.class);
|
||||
bind(PackNotificationManager.class);
|
||||
bind(IssueNotificationManager.class);
|
||||
bind(CodeCommentNotificationManager.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(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(WebHookManager.class);
|
||||
|
||||
contribute(CodePullAuthorizationSource.class, DefaultJobManager.class);
|
||||
contribute(CodePullAuthorizationSource.class, DefaultJobService.class);
|
||||
|
||||
bind(CodeIndexManager.class).to(DefaultCodeIndexManager.class);
|
||||
bind(CodeSearchManager.class).to(DefaultCodeSearchManager.class);
|
||||
bind(CodeIndexService.class).to(DefaultCodeIndexService.class);
|
||||
bind(CodeSearchService.class).to(DefaultCodeSearchService.class);
|
||||
|
||||
Bootstrap.executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>()) {
|
||||
@ -591,8 +638,7 @@ 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());
|
||||
|
||||
@ -635,7 +681,7 @@ public class CoreModule extends AbstractPluginModule {
|
||||
bind(GitLfsFilter.class);
|
||||
bind(GitPreReceiveCallback.class);
|
||||
bind(GitPostReceiveCallback.class);
|
||||
bind(SignatureVerificationManager.class).to(DefaultSignatureVerificationManager.class);
|
||||
bind(SignatureVerificationService.class).to(DefaultSignatureVerificationService.class);
|
||||
contribute(CommandCreator.class, SshCommandCreator.class);
|
||||
contributeFromPackage(SignatureVerifier.class, SignatureVerifier.class);
|
||||
}
|
||||
@ -647,21 +693,23 @@ public class CoreModule extends AbstractPluginModule {
|
||||
contribute(FilterChainConfigurator.class, filterChainManager -> filterChainManager.createChain("/~api/**", "noSessionCreation, authcBasic, authcBearer"));
|
||||
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(WebSocketManager.class).to(DefaultWebSocketManager.class);
|
||||
bind(WebSocketService.class).to(DefaultWebSocketService.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(AvatarManager.class).to(DefaultAvatarManager.class);
|
||||
bind(WebSocketManager.class).to(DefaultWebSocketManager.class);
|
||||
bind(AvatarService.class).to(DefaultAvatarService.class);
|
||||
bind(WebSocketService.class).to(DefaultWebSocketService.class);
|
||||
|
||||
contributeFromPackage(EditSupport.class, EditSupportLocator.class);
|
||||
|
||||
@ -681,24 +729,26 @@ 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(UrlManager.class).to(DefaultUrlManager.class);
|
||||
bind(UrlService.class).to(DefaultUrlService.class);
|
||||
bind(CodeCommentEventBroadcaster.class);
|
||||
bind(PullRequestEventBroadcaster.class);
|
||||
bind(IssueEventBroadcaster.class);
|
||||
bind(BuildEventBroadcaster.class);
|
||||
bind(AlertEventBroadcaster.class);
|
||||
bind(UploadManager.class).to(DefaultUploadManager.class);
|
||||
bind(UploadService.class).to(DefaultUploadService.class);
|
||||
|
||||
bind(TaskButton.TaskFutureManager.class);
|
||||
}
|
||||
|
||||
private void configureBuild() {
|
||||
bind(ResourceAllocator.class).to(DefaultResourceAllocator.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);
|
||||
bind(AgentService.class).to(DefaultAgentService.class);
|
||||
bind(AgentTokenService.class).to(DefaultAgentTokenService.class);
|
||||
bind(AgentAttributeService.class).to(DefaultAgentAttributeService.class);
|
||||
bind(AgentLastUsedDateService.class).to(DefaultAgentLastUsedDateService.class);
|
||||
|
||||
contribute(ScriptContribution.class, new ScriptContribution() {
|
||||
|
||||
@ -736,22 +786,22 @@ public class CoreModule extends AbstractPluginModule {
|
||||
}
|
||||
|
||||
private void configurePersistence() {
|
||||
bind(DataManager.class).to(DefaultDataManager.class);
|
||||
bind(DataService.class).to(DefaultDataService.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(SessionFactoryManager.class).to(DefaultSessionFactoryManager.class);
|
||||
bind(SessionFactoryService.class).to(DefaultSessionFactoryService.class);
|
||||
|
||||
contribute(ObjectMapperConfigurator.class, HibernateObjectMapperConfigurator.class);
|
||||
|
||||
bind(Interceptor.class).to(HibernateInterceptor.class);
|
||||
bind(PhysicalNamingStrategy.class).toInstance(new PrefixedNamingStrategy("o_"));
|
||||
|
||||
bind(SessionManager.class).to(DefaultSessionManager.class);
|
||||
bind(TransactionManager.class).to(DefaultTransactionManager.class);
|
||||
bind(IdManager.class).to(DefaultIdManager.class);
|
||||
bind(SessionService.class).to(DefaultSessionService.class);
|
||||
bind(TransactionService.class).to(DefaultTransactionService.class);
|
||||
bind(IdService.class).to(DefaultIdService.class);
|
||||
bind(Dao.class).to(DefaultDao.class);
|
||||
|
||||
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
|
||||
|
||||
@ -10,6 +10,7 @@ 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;
|
||||
@ -21,7 +22,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
@ -43,20 +44,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.ClusterManager;
|
||||
import io.onedev.server.data.DataManager;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.cluster.ClusterService;
|
||||
import io.onedev.server.data.DataService;
|
||||
import io.onedev.server.service.SettingService;
|
||||
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.JettyManager;
|
||||
import io.onedev.server.jetty.JettyService;
|
||||
import io.onedev.server.model.support.administration.SystemSetting;
|
||||
import io.onedev.server.persistence.IdManager;
|
||||
import io.onedev.server.persistence.SessionFactoryManager;
|
||||
import io.onedev.server.persistence.SessionManager;
|
||||
import io.onedev.server.persistence.IdService;
|
||||
import io.onedev.server.persistence.SessionFactoryService;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
import io.onedev.server.persistence.annotation.Sessional;
|
||||
import io.onedev.server.security.SecurityUtils;
|
||||
import io.onedev.server.taskschedule.TaskScheduler;
|
||||
@ -65,59 +66,60 @@ 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<JettyManager> jettyLauncherProvider;
|
||||
|
||||
private final SessionManager sessionManager;
|
||||
|
||||
private final DataManager dataManager;
|
||||
|
||||
|
||||
private final Provider<JettyService> jettyLauncherProvider;
|
||||
|
||||
private final SessionService sessionService;
|
||||
|
||||
private final DataService dataService;
|
||||
|
||||
private final Provider<ServerConfig> serverConfigProvider;
|
||||
|
||||
|
||||
private final ListenerRegistry listenerRegistry;
|
||||
|
||||
|
||||
private final TaskScheduler taskScheduler;
|
||||
|
||||
|
||||
private final ExecutorService executorService;
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final SettingManager settingManager;
|
||||
|
||||
private final IdManager idManager;
|
||||
|
||||
private final SessionFactoryManager sessionFactoryManager;
|
||||
|
||||
|
||||
private final ClusterService clusterService;
|
||||
|
||||
private final SettingService settingService;
|
||||
|
||||
private final IdService idService;
|
||||
|
||||
private final SessionFactoryService sessionFactoryService;
|
||||
|
||||
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<JettyManager> jettyLauncherProvider, TaskScheduler taskScheduler,
|
||||
SessionManager sessionManager, Provider<ServerConfig> serverConfigProvider,
|
||||
DataManager dataManager, ExecutorService executorService,
|
||||
ListenerRegistry listenerRegistry, ClusterManager clusterManager,
|
||||
IdManager idManager, SessionFactoryManager sessionFactoryManager,
|
||||
SettingManager settingManager) {
|
||||
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) {
|
||||
this.jettyLauncherProvider = jettyLauncherProvider;
|
||||
this.taskScheduler = taskScheduler;
|
||||
this.sessionManager = sessionManager;
|
||||
this.dataManager = dataManager;
|
||||
this.sessionService = sessionService;
|
||||
this.dataService = dataService;
|
||||
this.serverConfigProvider = serverConfigProvider;
|
||||
this.executorService = executorService;
|
||||
this.listenerRegistry = listenerRegistry;
|
||||
this.clusterManager = clusterManager;
|
||||
this.idManager = idManager;
|
||||
this.sessionFactoryManager = sessionFactoryManager;
|
||||
this.settingManager = settingManager;
|
||||
|
||||
this.clusterService = clusterService;
|
||||
this.idService = idService;
|
||||
this.sessionFactoryService = sessionFactoryService;
|
||||
this.settingService = settingService;
|
||||
|
||||
try {
|
||||
wrapperManagerClass = Class.forName("org.tanukisoftware.wrapper.WrapperManager");
|
||||
} catch (ClassNotFoundException e) {
|
||||
@ -126,7 +128,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
|
||||
initStage = new InitStage("Server is Starting...");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
var maintenanceFile = getMaintenanceFile(Bootstrap.installDir);
|
||||
@ -138,33 +140,34 @@ 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");
|
||||
|
||||
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()) {
|
||||
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()) {
|
||||
callWithTransaction(conn, () -> {
|
||||
dataManager.populateDatabase(conn);
|
||||
dataService.populateDatabase(conn);
|
||||
return null;
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
};
|
||||
}
|
||||
return 1L;
|
||||
});
|
||||
|
||||
idManager.init();
|
||||
|
||||
sessionManager.run(() -> listenerRegistry.post(new SystemStarting()));
|
||||
idService.init();
|
||||
|
||||
sessionService.run(() -> listenerRegistry.post(new SystemStarting()));
|
||||
jettyLauncherProvider.get().start();
|
||||
|
||||
var manualConfigs = checkData();
|
||||
@ -174,16 +177,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 = clusterManager.getLocalServerAddress();
|
||||
var localServer = clusterService.getLocalServerAddress();
|
||||
while (true) {
|
||||
if (maintenanceFile.exists()) {
|
||||
logger.info("Maintenance requested, trying to stop all servers...");
|
||||
clusterManager.submitToAllServers(() -> {
|
||||
if (!localServer.equals(clusterManager.getLocalServerAddress()))
|
||||
clusterService.submitToAllServers(() -> {
|
||||
if (!localServer.equals(clusterService.getLocalServerAddress()))
|
||||
restart();
|
||||
return null;
|
||||
});
|
||||
while (thread != null && clusterManager.getServerAddresses().size() != 1) {
|
||||
while (thread != null && clusterService.getServerAddresses().size() != 1) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
@ -199,7 +202,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
}
|
||||
if (thread == null)
|
||||
return;
|
||||
|
||||
|
||||
manualConfigs = checkData();
|
||||
if (manualConfigs.isEmpty()) {
|
||||
initStage = new InitStage("Please wait...");
|
||||
@ -209,21 +212,21 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var leadServer = clusterManager.getLeaderServerAddress();
|
||||
if (!leadServer.equals(clusterManager.getLocalServerAddress())) {
|
||||
|
||||
var leadServer = clusterService.getLeaderServerAddress();
|
||||
if (!leadServer.equals(clusterService.getLocalServerAddress())) {
|
||||
logger.info("Syncing assets...");
|
||||
Client client = ClientBuilder.newClient();
|
||||
try {
|
||||
String fromServerUrl = clusterManager.getServerUrl(leadServer);
|
||||
String fromServerUrl = clusterService.getServerUrl(leadServer);
|
||||
WebTarget target = client.target(fromServerUrl).path("/~api/cluster/assets");
|
||||
Invocation.Builder builder = target.request();
|
||||
builder.header(AUTHORIZATION,
|
||||
BEARER + " " + clusterManager.getCredential());
|
||||
BEARER + " " + clusterService.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);
|
||||
@ -233,44 +236,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());
|
||||
clusterManager.postStart();
|
||||
clusterService.postStart();
|
||||
thread.start();
|
||||
|
||||
SystemSetting systemSetting = settingManager.getSystemSetting();
|
||||
SystemSetting systemSetting = settingService.getSystemSetting();
|
||||
logger.info("Server is ready at " + systemSetting.getServerUrl() + ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preStop() {
|
||||
thread = null;
|
||||
clusterManager.preStop();
|
||||
clusterService.preStop();
|
||||
SecurityUtils.bindAsSystem();
|
||||
try {
|
||||
sessionManager.run(() -> listenerRegistry.post(new SystemStopping()));
|
||||
sessionService.run(() -> listenerRegistry.post(new SystemStopping()));
|
||||
} catch (ServerNotReadyException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<ManualConfig> checkData() {
|
||||
HazelcastInstance hazelcastInstance = clusterManager.getHazelcastInstance();
|
||||
HazelcastInstance hazelcastInstance = clusterService.getHazelcastInstance();
|
||||
var lock = hazelcastInstance.getCPSubsystem().getLock("checkData");
|
||||
lock.lock();
|
||||
try {
|
||||
return dataManager.checkData();
|
||||
return dataService.checkData();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -284,10 +287,10 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
taskScheduler.stop();
|
||||
|
||||
jettyLauncherProvider.get().stop();
|
||||
sessionManager.run(() -> listenerRegistry.post(new SystemStopped()));
|
||||
sessionService.run(() -> listenerRegistry.post(new SystemStopped()));
|
||||
|
||||
sessionFactoryManager.stop();
|
||||
clusterManager.stop();
|
||||
sessionFactoryService.stop();
|
||||
clusterService.stop();
|
||||
executorService.shutdown();
|
||||
} catch (ServerNotReadyException ignore) {
|
||||
}
|
||||
@ -306,11 +309,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) {
|
||||
@ -331,40 +334,46 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -375,8 +384,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())) {
|
||||
@ -386,7 +395,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
return true;
|
||||
else
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static File getIndexDir() {
|
||||
@ -394,15 +403,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 {
|
||||
@ -418,17 +427,17 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
var localServer = clusterManager.getLocalServerAddress();
|
||||
var localServer = clusterService.getLocalServerAddress();
|
||||
var maintenanceFile = getMaintenanceFile(Bootstrap.installDir);
|
||||
while (thread != null) {
|
||||
if (maintenanceFile.exists()) {
|
||||
logger.info("Maintenance requested, trying to stop all servers...");
|
||||
clusterManager.submitToAllServers(() -> {
|
||||
if (!localServer.equals(clusterManager.getLocalServerAddress()))
|
||||
clusterService.submitToAllServers(() -> {
|
||||
if (!localServer.equals(clusterService.getLocalServerAddress()))
|
||||
restart();
|
||||
return null;
|
||||
});
|
||||
while (thread != null && clusterManager.getServerAddresses().size() != 1) {
|
||||
while (thread != null && clusterService.getServerAddresses().size() != 1) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
@ -436,7 +445,7 @@ public class OneDev extends AbstractPlugin implements Serializable, Runnable {
|
||||
}
|
||||
restart();
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
package io.onedev.server;
|
||||
|
||||
import io.onedev.server.annotation.NoDBAccess;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface StorageManager {
|
||||
public interface StorageService {
|
||||
|
||||
File initLfsDir(Long projectId);
|
||||
|
||||
File initArtifactsDir(Long projectId, Long buildNumber);
|
||||
|
||||
|
||||
@NoDBAccess
|
||||
File initPacksDir(Long projectId);
|
||||
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
package io.onedev.server;
|
||||
|
||||
import io.onedev.server.annotation.NoDBAccess;
|
||||
import org.apache.wicket.Component;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public interface SubscriptionManager {
|
||||
|
||||
public interface SubscriptionService {
|
||||
|
||||
@NoDBAccess
|
||||
boolean isSubscriptionActive();
|
||||
|
||||
@Nullable
|
||||
@ -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.entitymanager.AgentManager;
|
||||
import io.onedev.server.service.AgentService;
|
||||
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.JobManager;
|
||||
import io.onedev.server.job.JobService;
|
||||
import io.onedev.server.job.ResourceAllocator;
|
||||
import io.onedev.server.job.log.LogManager;
|
||||
import io.onedev.server.job.log.LogService;
|
||||
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)
|
||||
getAgentManager().agentDisconnected(agentId);
|
||||
getAgentService().agentDisconnected(agentId);
|
||||
|
||||
StringBuilder builder = new StringBuilder("Websocket closed (");
|
||||
if (session != null && session.getRemoteAddress() != null)
|
||||
@ -69,15 +69,15 @@ public class ServerSocket {
|
||||
}
|
||||
}
|
||||
|
||||
private AgentManager getAgentManager() {
|
||||
return OneDev.getInstance(AgentManager.class);
|
||||
private AgentService getAgentService() {
|
||||
return OneDev.getInstance(AgentService.class);
|
||||
}
|
||||
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session) {
|
||||
this.session = session;
|
||||
try {
|
||||
new Message(MessageTypes.UPDATE, getAgentManager().getAgentVersion()).sendBy(session);
|
||||
new Message(MessageTypes.UPDATE, getAgentService().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 = getAgentManager().agentConnected(data, session);
|
||||
agentId = getAgentService().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(LogManager.class).getJobLogger(jobToken);
|
||||
TaskLogger logger = OneDev.getInstance(LogService.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 = getJobManager().getJobContext(jobToken, false);
|
||||
JobContext jobContext = getJobService().getJobContext(jobToken, false);
|
||||
if (jobContext != null)
|
||||
getJobManager().reportJobWorkspace(jobContext, jobWorkspace);
|
||||
getJobService().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) getJobManager().getShell(sessionId);
|
||||
AgentShell shell = (AgentShell) getJobService().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) getJobManager().getShell(sessionId);
|
||||
shell = (AgentShell) getJobService().getShell(sessionId);
|
||||
if (shell != null)
|
||||
shell.getTerminal().sendError(error);
|
||||
break;
|
||||
case SHELL_CLOSED:
|
||||
sessionId = new String(messageData, StandardCharsets.UTF_8);
|
||||
shell = (AgentShell) getJobManager().getShell(sessionId);
|
||||
shell = (AgentShell) getJobService().getShell(sessionId);
|
||||
if (shell != null)
|
||||
shell.getTerminal().close();
|
||||
break;
|
||||
@ -180,8 +180,8 @@ public class ServerSocket {
|
||||
}
|
||||
}
|
||||
|
||||
private JobManager getJobManager() {
|
||||
return OneDev.getInstance(JobManager.class);
|
||||
private JobService getJobService() {
|
||||
return OneDev.getInstance(JobService.class);
|
||||
}
|
||||
|
||||
private Serializable service(Serializable request) {
|
||||
|
||||
@ -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.entitymanager.AgentTokenManager;
|
||||
import io.onedev.server.service.AgentTokenService;
|
||||
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 AgentTokenManager tokenManager;
|
||||
private final AgentTokenService tokenService;
|
||||
|
||||
@Inject
|
||||
public ServerSocketServlet(AgentTokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
public ServerSocketServlet(AgentTokenService tokenService) {
|
||||
this.tokenService = tokenService;
|
||||
}
|
||||
|
||||
@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 && tokenManager.find(tokenValue) != null)
|
||||
if (tokenValue != null && tokenService.find(tokenValue) != null)
|
||||
super.service(request, response);
|
||||
else
|
||||
response.sendError(SC_FORBIDDEN, "A valid agent token is expected");
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
1899
server-core/src/main/java/io/onedev/server/ai/McpHelperResource.java
Normal file
1899
server-core/src/main/java/io/onedev/server/ai/McpHelperResource.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,102 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,639 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package io.onedev.server.annotation;
|
||||
|
||||
public @interface NoDBAccess {
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
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 {
|
||||
|
||||
}
|
||||
@ -6,7 +6,7 @@ import java.util.List;
|
||||
|
||||
import io.onedev.server.util.artifact.FileInfo;
|
||||
|
||||
public interface AttachmentManager {
|
||||
public interface AttachmentService {
|
||||
|
||||
File getAttachmentGroupDir(Long projectId, String attachmentGroup);
|
||||
|
||||
@ -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.ClusterManager;
|
||||
import io.onedev.server.cluster.ClusterService;
|
||||
import io.onedev.server.cluster.ClusterRunnable;
|
||||
import io.onedev.server.cluster.ClusterTask;
|
||||
import io.onedev.server.entitymanager.IssueManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.service.IssueService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.service.SettingService;
|
||||
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.TransactionManager;
|
||||
import io.onedev.server.persistence.TransactionService;
|
||||
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.BatchWorkManager;
|
||||
import io.onedev.server.util.concurrent.BatchWorkExecutionService;
|
||||
import io.onedev.server.util.concurrent.BatchWorker;
|
||||
import io.onedev.server.util.concurrent.Prioritized;
|
||||
|
||||
@Singleton
|
||||
public class DefaultAttachmentManager implements AttachmentManager, SchedulableTask, Serializable {
|
||||
public class DefaultAttachmentService implements AttachmentService, SchedulableTask, Serializable {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultAttachmentManager.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultAttachmentService.class);
|
||||
|
||||
private static final long TEMP_PRESERVE_PERIOD = 24*3600*1000L;
|
||||
|
||||
@ -98,47 +98,40 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
private static final String PERMANENT = "permanent";
|
||||
|
||||
private static final String TEMP = "temp";
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
public Object writeReplace() throws ObjectStreamException {
|
||||
return new ManagedSerializedForm(AttachmentManager.class);
|
||||
return new ManagedSerializedForm(AttachmentService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getAttachmentGroupDir(Long projectId, String attachmentGroup) {
|
||||
File baseDir = projectManager.getAttachmentDir(projectId);
|
||||
File baseDir = projectService.getAttachmentDir(projectId);
|
||||
File groupDir = getPermanentAttachmentGroupDir(baseDir, attachmentGroup);
|
||||
if (groupDir.exists())
|
||||
return groupDir;
|
||||
@ -151,11 +144,11 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
public void on(IssuesMoved event) {
|
||||
Long sourceProjectId = event.getSourceProject().getId();
|
||||
Long targetProjectId = event.getProject().getId();
|
||||
File targetBaseDir = projectManager.getAttachmentDir(targetProjectId);
|
||||
File targetBaseDir = projectService.getAttachmentDir(targetProjectId);
|
||||
|
||||
String sourceActiveServer = projectManager.getActiveServer(sourceProjectId, true);
|
||||
if (sourceActiveServer.equals(clusterManager.getLocalServerAddress())) {
|
||||
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
|
||||
String sourceActiveServer = projectService.getActiveServer(sourceProjectId, true);
|
||||
if (sourceActiveServer.equals(clusterService.getLocalServerAddress())) {
|
||||
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
|
||||
for (Long issueId: event.getIssueIds()) {
|
||||
Issue issue = dao.load(Issue.class, issueId);
|
||||
String attachmentGroup = issue.getAttachmentGroup();
|
||||
@ -184,8 +177,8 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
} finally {
|
||||
FileUtils.deleteDir(tempGroupDir);
|
||||
}
|
||||
projectManager.directoryModified(targetProjectId, sourceGroupDir.getParentFile());
|
||||
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
projectService.directoryModified(targetProjectId, sourceGroupDir.getParentFile());
|
||||
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
}
|
||||
} else {
|
||||
Collection<String> attachmentGroups = new HashSet<>();
|
||||
@ -211,22 +204,22 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
} finally {
|
||||
FileUtils.deleteDir(tempGroupDir);
|
||||
}
|
||||
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
}
|
||||
projectManager.runOnActiveServer(sourceProjectId, new ClusterTask<Void>() {
|
||||
projectService.runOnActiveServer(sourceProjectId, new ClusterTask<Void>() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
|
||||
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
|
||||
for (var attachmentGroup: attachmentGroups) {
|
||||
var sourceGroupDir = getPermanentAttachmentGroupDir(sourceBaseDir, attachmentGroup);
|
||||
write(getAttachmentLockName(sourceProjectId, attachmentGroup), () -> {
|
||||
FileUtils.deleteDir(sourceGroupDir);
|
||||
return null;
|
||||
});
|
||||
projectManager.directoryModified(sourceProjectId, sourceGroupDir.getParentFile());
|
||||
projectService.directoryModified(sourceProjectId, sourceGroupDir.getParentFile());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -241,11 +234,11 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
Long sourceProjectId = event.getSourceProject().getId();
|
||||
Long targetProjectId = event.getProject().getId();
|
||||
|
||||
File targetBaseDir = projectManager.getAttachmentDir(targetProjectId);
|
||||
File targetBaseDir = projectService.getAttachmentDir(targetProjectId);
|
||||
|
||||
String sourceActiveServer = projectManager.getActiveServer(sourceProjectId, true);
|
||||
if (sourceActiveServer.equals(clusterManager.getLocalServerAddress())) {
|
||||
File sourceBaseDir = projectManager.getAttachmentDir(sourceProjectId);
|
||||
String sourceActiveServer = projectService.getActiveServer(sourceProjectId, true);
|
||||
if (sourceActiveServer.equals(clusterService.getLocalServerAddress())) {
|
||||
File sourceBaseDir = projectService.getAttachmentDir(sourceProjectId);
|
||||
for (var entry: event.getIssueIdMapping().entrySet()) {
|
||||
Issue sourceIssue = dao.load(Issue.class, entry.getKey());
|
||||
Issue targetIssue = dao.load(Issue.class, entry.getValue());
|
||||
@ -273,7 +266,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
} finally {
|
||||
FileUtils.deleteDir(tempGroupDir);
|
||||
}
|
||||
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
}
|
||||
} else {
|
||||
for (var entry: event.getIssueIdMapping().entrySet()) {
|
||||
@ -296,7 +289,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
} finally {
|
||||
FileUtils.deleteDir(tempGroupDir);
|
||||
}
|
||||
projectManager.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
projectService.directoryModified(targetProjectId, targetGroupDir.getParentFile());
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,13 +299,13 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
Long sourceProjectId, String sourceAttachmentGroup) {
|
||||
Client client = ClientBuilder.newClient();
|
||||
try {
|
||||
String fromServerUrl = clusterManager.getServerUrl(sourceActiveServer);
|
||||
String fromServerUrl = clusterService.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 + " " + clusterManager.getCredential());
|
||||
BEARER + " " + clusterService.getCredential());
|
||||
|
||||
try (Response response = builder.get()) {
|
||||
KubernetesHelper.checkStatus(response);
|
||||
@ -333,7 +326,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
}
|
||||
|
||||
private void permanentizeAttachmentGroup(Long projectId, String attachmentGroup) {
|
||||
var baseAttachmentDir = projectManager.getAttachmentDir(projectId);
|
||||
var baseAttachmentDir = projectService.getAttachmentDir(projectId);
|
||||
write(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
File permanentStorage = getPermanentAttachmentGroupDir(baseAttachmentDir, attachmentGroup);
|
||||
if (!permanentStorage.exists()) {
|
||||
@ -347,7 +340,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
} else {
|
||||
FileUtils.createDir(permanentStorage);
|
||||
}
|
||||
projectManager.directoryModified(projectId, permanentStorage);
|
||||
projectService.directoryModified(projectId, permanentStorage);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@ -366,13 +359,13 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
batchWorkManager.submit(new BatchWorker("attachment-manager-house-keeping") {
|
||||
batchWorkExecutionService.submit(new BatchWorker("attachment-manager-house-keeping") {
|
||||
|
||||
@Override
|
||||
public void doWorks(List<Prioritized> works) {
|
||||
for (var projectId: projectManager.getActiveIds()) {
|
||||
for (var projectId: projectService.getActiveIds()) {
|
||||
try {
|
||||
File tempAttachmentBase = new File(projectManager.getAttachmentDir(projectId), TEMP);
|
||||
File tempAttachmentBase = new File(projectService.getAttachmentDir(projectId), TEMP);
|
||||
if (tempAttachmentBase.exists()) {
|
||||
for (File attachmentGroupDir: tempAttachmentBase.listFiles()) {
|
||||
if (System.currentTimeMillis() - attachmentGroupDir.lastModified() > TEMP_PRESERVE_PERIOD) {
|
||||
@ -398,7 +391,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
@Sessional
|
||||
public void on(IssuesImported event) {
|
||||
for (var issueId: event.getIssueIds()) {
|
||||
var issue = issueManager.load(issueId);
|
||||
var issue = issueService.load(issueId);
|
||||
var attachmentGroup = issue.getAttachmentGroup();
|
||||
permanentizeAttachmentGroup(issue.getProject().getId(), attachmentGroup);
|
||||
}
|
||||
@ -505,15 +498,15 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
if (event.getEntity() instanceof AttachmentStorageSupport) {
|
||||
AttachmentStorageSupport storageSupport = (AttachmentStorageSupport) event.getEntity();
|
||||
Long projectId = storageSupport.getAttachmentProject().getId();
|
||||
String activeServer = projectManager.getActiveServer(projectId, false);
|
||||
String activeServer = projectService.getActiveServer(projectId, false);
|
||||
if (activeServer != null) {
|
||||
transactionManager.runAfterCommit(new ClusterRunnable() {
|
||||
transactionService.runAfterCommit(new ClusterRunnable() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
clusterManager.runOnServer(activeServer, new ClusterTask<Void>() {
|
||||
clusterService.runOnServer(activeServer, new ClusterTask<Void>() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -522,10 +515,10 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
var attachmentGroup = storageSupport.getAttachmentGroup();
|
||||
return write(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
File attachmentDir = getPermanentAttachmentGroupDir(
|
||||
projectManager.getAttachmentDir(storageSupport.getAttachmentProject().getId()),
|
||||
projectService.getAttachmentDir(storageSupport.getAttachmentProject().getId()),
|
||||
attachmentGroup);
|
||||
FileUtils.deleteDir(attachmentDir);
|
||||
projectManager.directoryModified(projectId, attachmentDir.getParentFile());
|
||||
projectService.directoryModified(projectId, attachmentDir.getParentFile());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
@ -541,21 +534,21 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
@Override
|
||||
public String saveAttachment(Long projectId, String attachmentGroup, String preferredAttachmentName,
|
||||
InputStream attachmentStream) {
|
||||
String activeServer = projectManager.getActiveServer(projectId, true);
|
||||
if (activeServer.equals(clusterManager.getLocalServerAddress())) {
|
||||
String activeServer = projectService.getActiveServer(projectId, true);
|
||||
if (activeServer.equals(clusterService.getLocalServerAddress())) {
|
||||
return saveAttachmentLocal(projectId, attachmentGroup, preferredAttachmentName, attachmentStream);
|
||||
} else {
|
||||
Client client = ClientBuilder.newClient();
|
||||
client.property(ClientProperties.REQUEST_ENTITY_PROCESSING, "CHUNKED");
|
||||
try {
|
||||
String serverUrl = clusterManager.getServerUrl(activeServer);
|
||||
String serverUrl = clusterService.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 + " " + clusterManager.getCredential());
|
||||
builder.header(AUTHORIZATION, BEARER + " " + clusterService.getCredential());
|
||||
|
||||
StreamingOutput os = output -> {
|
||||
try {
|
||||
@ -598,7 +591,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
index++;
|
||||
}
|
||||
|
||||
long maxUploadFileSize = settingManager.getPerformanceSetting().getMaxUploadFileSize() * 1024L * 1024L;
|
||||
long maxUploadFileSize = settingService.getPerformanceSetting().getMaxUploadFileSize() * 1024L * 1024L;
|
||||
|
||||
Exception ex = null;
|
||||
File file = new File(attachmentDir, attachmentName);
|
||||
@ -623,7 +616,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
throw ExceptionUtils.unchecked(ex);
|
||||
} else {
|
||||
if (!attachmentDir.getParentFile().getName().equals(TEMP))
|
||||
projectManager.directoryModified(projectId, attachmentDir);
|
||||
projectService.directoryModified(projectId, attachmentDir);
|
||||
return file.getName();
|
||||
}
|
||||
});
|
||||
@ -636,7 +629,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
|
||||
@Override
|
||||
public FileInfo getAttachmentInfo(Long projectId, String attachmentGroup, String attachment) {
|
||||
return projectManager.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
return projectService.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
File attachmentFile = new File(getAttachmentGroupDir(projectId, attachmentGroup), attachment);
|
||||
if (!attachmentFile.exists())
|
||||
throw new FileNotFoundException("Attachment not found: " + attachment);
|
||||
@ -647,12 +640,12 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
|
||||
@Override
|
||||
public void deleteAttachment(Long projectId, String attachmentGroup, String attachment) {
|
||||
projectManager.runOnActiveServer(projectId, () -> write(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
projectService.runOnActiveServer(projectId, () -> write(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
var attachmentGroupDir = getAttachmentGroupDir(projectId, attachmentGroup);
|
||||
File attachmentFile = new File(attachmentGroupDir, attachment);
|
||||
if (attachmentFile.exists()) {
|
||||
FileUtils.deleteFile(attachmentFile);
|
||||
projectManager.directoryModified(projectId, attachmentGroupDir);
|
||||
projectService.directoryModified(projectId, attachmentGroupDir);
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
@ -660,7 +653,7 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
|
||||
@Override
|
||||
public List<FileInfo> listAttachments(Long projectId, String attachmentGroup) {
|
||||
return projectManager.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
return projectService.runOnActiveServer(projectId, () -> read(getAttachmentLockName(projectId, attachmentGroup), () -> {
|
||||
List<FileInfo> attachments = new ArrayList<>();
|
||||
File attachmentGroupDir = getAttachmentGroupDir(projectId, attachmentGroup);
|
||||
if (attachmentGroupDir.exists()) {
|
||||
@ -676,12 +669,12 @@ public class DefaultAttachmentManager implements AttachmentManager, SchedulableT
|
||||
@Override
|
||||
public void syncAttachments(Long projectId, String activeServer) {
|
||||
var permanent = ATTACHMENT_DIR + "/" + PERMANENT;
|
||||
projectManager.syncDirectory(projectId, permanent, prefix -> {
|
||||
projectService.syncDirectory(projectId, permanent, prefix -> {
|
||||
var prefixPath = permanent + "/" + prefix;
|
||||
projectManager.syncDirectory(projectId, prefixPath, attachmentGroup -> {
|
||||
projectService.syncDirectory(projectId, prefixPath, attachmentGroup -> {
|
||||
var attachmentGroupPath = permanent + "/" + prefix + "/" + attachmentGroup;
|
||||
var lockName = getAttachmentLockName(projectId, attachmentGroup);
|
||||
projectManager.syncDirectory(projectId, attachmentGroupPath, lockName, activeServer);
|
||||
projectService.syncDirectory(projectId, attachmentGroupPath, lockName, activeServer);
|
||||
}, activeServer);
|
||||
}, activeServer);
|
||||
}
|
||||
@ -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.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.model.Project;
|
||||
import io.onedev.server.persistence.SessionManager;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
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 getAttachmentManager().listAttachments(projectId, attachmentGroup).stream()
|
||||
return getAttachmentService().listAttachments(projectId, attachmentGroup).stream()
|
||||
.map(it->it.getPath()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private ProjectManager getProjectManager() {
|
||||
return OneDev.getInstance(ProjectManager.class);
|
||||
private ProjectService getProjectService() {
|
||||
return OneDev.getInstance(ProjectService.class);
|
||||
}
|
||||
|
||||
private AttachmentManager getAttachmentManager() {
|
||||
return OneDev.getInstance(AttachmentManager.class);
|
||||
private AttachmentService getAttachmentService() {
|
||||
return OneDev.getInstance(AttachmentService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAttachemnt(String attachment) {
|
||||
getAttachmentManager().deleteAttachment(projectId, attachmentGroup, attachment);
|
||||
getAttachmentService().deleteAttachment(projectId, attachmentGroup, attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,18 +67,18 @@ public class ProjectAttachmentSupport implements AttachmentSupport {
|
||||
}
|
||||
|
||||
protected Project getProject() {
|
||||
SessionManager sessionManager = OneDev.getInstance(SessionManager.class);
|
||||
sessionManager.openSession();
|
||||
SessionService sessionService = OneDev.getInstance(SessionService.class);
|
||||
sessionService.openSession();
|
||||
try {
|
||||
return getProjectManager().load(projectId);
|
||||
return getProjectService().load(projectId);
|
||||
} finally {
|
||||
sessionManager.closeSession();
|
||||
sessionService.closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveAttachment(String suggestedAttachmentName, InputStream attachmentStream) {
|
||||
return getAttachmentManager().saveAttachment(
|
||||
return getAttachmentService().saveAttachment(
|
||||
projectId, attachmentGroup, suggestedAttachmentName, attachmentStream);
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,42 @@
|
||||
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;
|
||||
@ -27,27 +59,11 @@ 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
|
||||
@ -105,6 +121,7 @@ public class BuildSpec implements Serializable, Validatable {
|
||||
private transient Map<String, JobProperty> propertyMap;
|
||||
|
||||
@Editable
|
||||
@Valid
|
||||
public List<Job> getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
@ -115,6 +132,7 @@ public class BuildSpec implements Serializable, Validatable {
|
||||
}
|
||||
|
||||
@Editable
|
||||
@Valid
|
||||
public List<StepTemplate> getStepTemplates() {
|
||||
return stepTemplates;
|
||||
}
|
||||
@ -125,6 +143,7 @@ public class BuildSpec implements Serializable, Validatable {
|
||||
}
|
||||
|
||||
@Editable
|
||||
@Valid
|
||||
public List<Service> getServices() {
|
||||
return services;
|
||||
}
|
||||
@ -135,6 +154,7 @@ public class BuildSpec implements Serializable, Validatable {
|
||||
}
|
||||
|
||||
@Editable
|
||||
@Valid
|
||||
public List<JobProperty> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
@ -145,6 +165,7 @@ public class BuildSpec implements Serializable, Validatable {
|
||||
}
|
||||
|
||||
@Editable
|
||||
@Valid
|
||||
public List<Import> getImports() {
|
||||
return imports;
|
||||
}
|
||||
@ -164,8 +185,7 @@ 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, SecurityUtils.getUser(), null));
|
||||
JobAuthorizationContext.push(new JobAuthorizationContext(aImport.getProject(), importCommit, null));
|
||||
try {
|
||||
importedBuildSpecs.addAll(importedBuildSpec.getImportedBuildSpecs(newCommitChain));
|
||||
} finally {
|
||||
@ -271,27 +291,10 @@ 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())) {
|
||||
@ -300,19 +303,6 @@ 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) {
|
||||
@ -322,19 +312,6 @@ 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) {
|
||||
@ -344,19 +321,6 @@ 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) {
|
||||
@ -366,20 +330,6 @@ 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) {
|
||||
@ -2312,4 +2262,136 @@ 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")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public interface BuildSpecAware {
|
||||
|
||||
|
||||
@ -0,0 +1,487 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,7 +10,7 @@ import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
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>> importChain = ThreadLocal.withInitial(Stack::new);
|
||||
private static ThreadLocal<Stack<String>> IMPORT_CHAIN = 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() {
|
||||
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
|
||||
ProjectService projectService = OneDev.getInstance(ProjectService.class);
|
||||
Project project = ((ProjectPage)WicketUtils.getPage()).getProject();
|
||||
|
||||
Collection<Project> projects = SecurityUtils.getAuthorizedProjects(new AccessProject());
|
||||
projects.remove(project);
|
||||
|
||||
ProjectCache cache = projectManager.cloneCache();
|
||||
ProjectCache cache = projectService.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(ProjectManager.class).findByPath(projectPath);
|
||||
Project project = OneDev.getInstance(ProjectService.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 (importChain.get().contains(commit.name())) {
|
||||
List<String> circular = new ArrayList<>(importChain.get());
|
||||
if (IMPORT_CHAIN.get().contains(commit.name())) {
|
||||
List<String> circular = new ArrayList<>(IMPORT_CHAIN.get());
|
||||
circular.add(commit.name());
|
||||
String errorMessage = MessageFormat.format(
|
||||
_T("Circular build spec imports ({0})"), circular);
|
||||
@ -203,12 +203,11 @@ public class Import implements Serializable, Validatable {
|
||||
context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
|
||||
return false;
|
||||
} else {
|
||||
importChain.get().push(commit.name());
|
||||
IMPORT_CHAIN.get().push(commit.name());
|
||||
try {
|
||||
Validator validator = OneDev.getInstance(Validator.class);
|
||||
BuildSpec buildSpec = getBuildSpec();
|
||||
JobAuthorizationContext.push(new JobAuthorizationContext(
|
||||
getProject(), getCommit(), SecurityUtils.getUser(), null));
|
||||
JobAuthorizationContext.push(new JobAuthorizationContext(getProject(), getCommit(), null));
|
||||
try {
|
||||
for (int i = 0; i < buildSpec.getImports().size(); i++) {
|
||||
Import aImport = buildSpec.getImports().get(i);
|
||||
@ -226,7 +225,7 @@ public class Import implements Serializable, Validatable {
|
||||
JobAuthorizationContext.pop();
|
||||
}
|
||||
} finally {
|
||||
importChain.get().pop();
|
||||
IMPORT_CHAIN.get().pop();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -243,7 +242,7 @@ public class Import implements Serializable, Validatable {
|
||||
|
||||
public Project getProject() {
|
||||
if (project == null) {
|
||||
project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
|
||||
project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
|
||||
if (project == null)
|
||||
throw new ExplicitException(MessageFormat.format( _T("Unable to find project to import build spec: {0}"), projectPath));
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ 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;
|
||||
@ -87,6 +88,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Min;
|
||||
@ -32,6 +32,7 @@ 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;
|
||||
@ -45,14 +46,13 @@ 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.security.SecurityUtils;
|
||||
import io.onedev.server.service.SettingService;
|
||||
import io.onedev.server.util.ComponentContext;
|
||||
import io.onedev.server.util.EditContext;
|
||||
import io.onedev.server.util.criteria.Criteria;
|
||||
@ -82,6 +82,8 @@ 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;
|
||||
|
||||
@ -148,7 +150,7 @@ public class Job implements NamedElement, Validatable {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static String getJobExecutorPlaceholder() {
|
||||
if (OneDev.getInstance(SettingManager.class).getJobExecutors().isEmpty())
|
||||
if (OneDev.getInstance(SettingService.class).getJobExecutors().isEmpty())
|
||||
return _T("Auto-discovered executor");
|
||||
else
|
||||
return _T("First applicable executor");
|
||||
@ -156,7 +158,7 @@ public class Job implements NamedElement, Validatable {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static String getJobExecutorDescription() {
|
||||
if (OneDev.getInstance(SettingManager.class).getJobExecutors().isEmpty())
|
||||
if (OneDev.getInstance(SettingService.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");
|
||||
@ -171,8 +173,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, SecurityUtils.getAuthUser(), jobName);
|
||||
for (JobExecutor executor: OneDev.getInstance(SettingManager.class).getJobExecutors()) {
|
||||
JobMatchContext context = new JobMatchContext(page.getProject(), branch, null, jobName);
|
||||
for (JobExecutor executor: OneDev.getInstance(SettingService.class).getJobExecutors()) {
|
||||
if (executor.isEnabled()) {
|
||||
if (executor.getJobMatch() == null) {
|
||||
applicableJobExecutors.add(executor.getName());
|
||||
@ -188,6 +190,7 @@ 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;
|
||||
}
|
||||
@ -280,8 +283,8 @@ public class Job implements NamedElement, Validatable {
|
||||
}
|
||||
|
||||
@Editable(order=9400, group="More Settings", description="Specify condition to retry build upon failure")
|
||||
@NotEmpty
|
||||
@RetryCondition
|
||||
@NotEmpty
|
||||
public String getRetryCondition() {
|
||||
return retryCondition;
|
||||
}
|
||||
@ -292,6 +295,7 @@ 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;
|
||||
}
|
||||
@ -304,6 +308,7 @@ 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;
|
||||
}
|
||||
@ -346,6 +351,14 @@ 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())) {
|
||||
@ -364,18 +377,16 @@ public class Job implements NamedElement, Validatable {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import io.onedev.server.buildspec.ParamSpecAware;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job;
|
||||
|
||||
import io.onedev.k8shelper.KubernetesHelper;
|
||||
import io.onedev.server.OneDev;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.service.SettingService;
|
||||
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(SettingManager.class).getSystemSetting().getServerUrl();
|
||||
var serverUrl = OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
|
||||
return UrlUtils.getServer(serverUrl);
|
||||
}
|
||||
},
|
||||
SERVER_HOST {
|
||||
@Override
|
||||
public String getValue(Build build) {
|
||||
var serverUrl = OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
|
||||
var serverUrl = OneDev.getInstance(SettingService.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(SettingManager.class).getSystemSetting().getServerUrl();
|
||||
return OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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.entitymanager.IssueManager;
|
||||
import io.onedev.server.entitymanager.PullRequestManager;
|
||||
import io.onedev.server.service.IssueService;
|
||||
import io.onedev.server.service.PullRequestService;
|
||||
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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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(PullRequestManager.class).load(requestId);
|
||||
return OneDev.getInstance(PullRequestService.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(IssueManager.class).load(issueId);
|
||||
return OneDev.getInstance(IssueService.class).load(issueId);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1,15 +1,34 @@
|
||||
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.*;
|
||||
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.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.job.Job;
|
||||
import io.onedev.server.entitymanager.IssueManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.service.IssueService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.service.SettingService;
|
||||
import io.onedev.server.job.JobAuthorizationContext;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.model.Issue;
|
||||
@ -17,21 +36,12 @@ 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.TransactionManager;
|
||||
import io.onedev.server.persistence.TransactionService;
|
||||
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 {
|
||||
@ -63,13 +73,13 @@ public class CreateIssueAction extends PostBuildAction {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static List<String> getProjectChoices() {
|
||||
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
|
||||
ProjectService projectService = OneDev.getInstance(ProjectService.class);
|
||||
Project project = ((ProjectPage) WicketUtils.getPage()).getProject();
|
||||
|
||||
Collection<Project> projects = SecurityUtils.getAuthorizedProjects(new AccessProject());
|
||||
projects.remove(project);
|
||||
|
||||
ProjectCache cache = projectManager.cloneCache();
|
||||
ProjectCache cache = projectService.cloneCache();
|
||||
|
||||
List<String> choices = projects.stream().map(it->cache.get(it.getId()).getPath()).collect(Collectors.toList());
|
||||
Collections.sort(choices);
|
||||
@ -80,7 +90,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")
|
||||
@ShowCondition("isProjectSpecified")
|
||||
@DependsOn(property="projectPath")
|
||||
@Nullable
|
||||
public String getAccessTokenSecret() {
|
||||
return accessTokenSecret;
|
||||
@ -89,11 +99,6 @@ 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() {
|
||||
@ -150,15 +155,15 @@ public class CreateIssueAction extends PostBuildAction {
|
||||
}
|
||||
|
||||
private static Collection<String> getFieldNames() {
|
||||
return OneDev.getInstance(SettingManager.class).getIssueSetting().getFieldNames();
|
||||
return OneDev.getInstance(SettingService.class).getIssueSetting().getFieldNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Build build) {
|
||||
OneDev.getInstance(TransactionManager.class).run(() -> {
|
||||
OneDev.getInstance(TransactionService.class).run(() -> {
|
||||
Project project;
|
||||
if (getProjectPath() != null) {
|
||||
project = OneDev.getInstance(ProjectManager.class).findByPath(getProjectPath());
|
||||
project = OneDev.getInstance(ProjectService.class).findByPath(getProjectPath());
|
||||
if (project == null)
|
||||
throw new ExplicitException("Unable to find project: " + projectPath);
|
||||
Subject subject = JobAuthorizationContext.get().getSubject(getAccessTokenSecret());
|
||||
@ -172,8 +177,8 @@ public class CreateIssueAction extends PostBuildAction {
|
||||
issue.setTitle(getIssueTitle());
|
||||
issue.setSubmitter(SecurityUtils.getUser());
|
||||
issue.setSubmitDate(new Date());
|
||||
SettingManager settingManager = OneDev.getInstance(SettingManager.class);
|
||||
GlobalIssueSetting issueSetting = settingManager.getIssueSetting();
|
||||
SettingService settingService = OneDev.getInstance(SettingService.class);
|
||||
GlobalIssueSetting issueSetting = settingService.getIssueSetting();
|
||||
issue.setState(issueSetting.getInitialStateSpec().getName());
|
||||
|
||||
issue.setDescription(getIssueDescription());
|
||||
@ -183,7 +188,7 @@ public class CreateIssueAction extends PostBuildAction {
|
||||
.convertToObject(instance.getValueProvider().getValue());
|
||||
issue.setFieldValue(instance.getName(), fieldValue);
|
||||
}
|
||||
OneDev.getInstance(IssueManager.class).open(issue);
|
||||
OneDev.getInstance(IssueService.class).open(issue);
|
||||
});
|
||||
|
||||
}
|
||||
@ -197,7 +202,7 @@ public class CreateIssueAction extends PostBuildAction {
|
||||
public void validateWith(BuildSpec buildSpec, Job job) {
|
||||
super.validateWith(buildSpec, job);
|
||||
|
||||
GlobalIssueSetting issueSetting = OneDev.getInstance(SettingManager.class).getIssueSetting();
|
||||
GlobalIssueSetting issueSetting = OneDev.getInstance(SettingService.class).getIssueSetting();
|
||||
try {
|
||||
FieldUtils.validateFields(issueSetting.getFieldSpecMap(getFieldNames()), issueFields);
|
||||
} catch (ValidationException e) {
|
||||
|
||||
@ -1,7 +1,23 @@
|
||||
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.*;
|
||||
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.buildspec.BuildSpec;
|
||||
import io.onedev.server.buildspec.BuildSpecAware;
|
||||
import io.onedev.server.buildspec.job.Job;
|
||||
@ -9,21 +25,13 @@ 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.JobManager;
|
||||
import io.onedev.server.job.JobService;
|
||||
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 {
|
||||
@ -106,11 +114,11 @@ public class RunJobAction extends PostBuildAction {
|
||||
@Override
|
||||
public void execute(Build build) {
|
||||
for (var paramMap: resolveParams(build, build.getParamCombination(), getParamMatrix(), getExcludeParamMaps())) {
|
||||
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() + "'");
|
||||
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() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,308 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,7 +14,7 @@ import static io.onedev.server.model.Build.NAME_TAG;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,14 +2,14 @@ package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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.LogManager;
|
||||
import io.onedev.server.job.log.LogService;
|
||||
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(LogManager.class).matches(build, pattern);
|
||||
return OneDev.getInstance(LogService.class).matches(build, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.action.condition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -4,7 +4,7 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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.entitymanager.GroupManager;
|
||||
import io.onedev.server.entitymanager.UserManager;
|
||||
import io.onedev.server.service.GroupService;
|
||||
import io.onedev.server.service.UserService;
|
||||
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(UserManager.class).findByName(userName);
|
||||
User user = OneDev.getInstance(UserService.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(GroupManager.class).find(groupName);
|
||||
Group group = OneDev.getInstance(GroupService.class).find(groupName);
|
||||
if (group != null) {
|
||||
emailAddresses.addAll(group.getMembers().stream()
|
||||
.map(it->it.getPrimaryEmailAddress())
|
||||
|
||||
@ -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.UrlManager;
|
||||
import io.onedev.server.web.UrlService;
|
||||
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(UrlManager.class).cloneUrlFor(build.getProject(), false), jobToken);
|
||||
return new DefaultCloneInfo(OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), false), jobToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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.UrlManager;
|
||||
import io.onedev.server.web.UrlService;
|
||||
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(UrlManager.class).cloneUrlFor(build.getProject(), false),
|
||||
return new HttpCloneInfo(OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), false),
|
||||
build.getJobAuthorizationContext().getSecretValue(accessTokenSecret));
|
||||
}
|
||||
|
||||
|
||||
@ -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.entitymanager.SettingManager;
|
||||
import io.onedev.server.web.UrlManager;
|
||||
import io.onedev.server.service.SettingService;
|
||||
import io.onedev.server.web.UrlService;
|
||||
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(UrlManager.class).cloneUrlFor(build.getProject(), true);
|
||||
SettingManager settingManager = OneDev.getInstance(SettingManager.class);
|
||||
SystemSetting systemSetting = settingManager.getSystemSetting();
|
||||
SshSetting sshSetting = settingManager.getSshSetting();
|
||||
String cloneUrl = OneDev.getInstance(UrlService.class).cloneUrlFor(build.getProject(), true);
|
||||
SettingService settingService = OneDev.getInstance(SettingService.class);
|
||||
SystemSetting systemSetting = settingService.getSystemSetting();
|
||||
SshSetting sshSetting = settingService.getSshSetting();
|
||||
StringBuilder knownHosts = new StringBuilder(systemSetting.getSshServerName()).append(" ");
|
||||
try {
|
||||
PublicKeyEntry.appendPublicKeyEntry(knownHosts,
|
||||
|
||||
@ -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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.projectdependency;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.model.Project;
|
||||
|
||||
@ -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.entitymanager.BuildManager;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.model.Project;
|
||||
import io.onedev.server.util.EditContext;
|
||||
import io.onedev.server.annotation.ChoiceProvider;
|
||||
import io.onedev.server.annotation.Editable;
|
||||
import io.onedev.server.annotation.OmitName;
|
||||
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;
|
||||
|
||||
@Editable(order=100, name="Last Finished of Specified Job")
|
||||
public class LastFinishedBuild implements BuildProvider {
|
||||
@ -25,7 +25,6 @@ public class LastFinishedBuild implements BuildProvider {
|
||||
private String refName;
|
||||
|
||||
@Editable(order=100)
|
||||
@OmitName
|
||||
@ChoiceProvider("getJobChoices")
|
||||
@NotEmpty
|
||||
public String getJobName() {
|
||||
@ -51,7 +50,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(BuildManager.class).getAccessibleJobNames(project));
|
||||
jobNames.addAll(OneDev.getInstance(BuildService.class).getAccessibleJobNames(SecurityUtils.getSubject(), project));
|
||||
Collections.sort(jobNames);
|
||||
}
|
||||
return jobNames;
|
||||
@ -59,7 +58,7 @@ public class LastFinishedBuild implements BuildProvider {
|
||||
|
||||
@Override
|
||||
public Build getBuild(Project project) {
|
||||
return OneDev.getInstance(BuildManager.class).findLastFinished(project, jobName, refName);
|
||||
return OneDev.getInstance(BuildService.class).findLastFinished(project, jobName, refName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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();
|
||||
|
||||
ProjectManager projectManager = OneDev.getInstance(ProjectManager.class);
|
||||
ProjectCache cache = projectManager.cloneCache();
|
||||
ProjectService projectService = OneDev.getInstance(ProjectService.class);
|
||||
ProjectCache cache = projectService.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(ProjectManager.class).findByPath(projectPath);
|
||||
Project project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
|
||||
if (project != null && SecurityUtils.canReadCode(project))
|
||||
return project;
|
||||
}
|
||||
|
||||
@ -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.entitymanager.BuildManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
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(BuildManager.class).find(project, buildNumber);
|
||||
return OneDev.getInstance(BuildService.class).find(project, buildNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,14 +2,14 @@ package io.onedev.server.buildspec.job.retrycondition;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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.LogManager;
|
||||
import io.onedev.server.job.log.LogService;
|
||||
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(LogManager.class).matches(context.getBuild(), pattern);
|
||||
|| OneDev.getInstance(LogService.class).matches(context.getBuild(), pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package io.onedev.server.buildspec.job.retrycondition;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -10,7 +10,7 @@ import static io.onedev.server.model.Build.NAME_LOG;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.From;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.job.retrycondition;
|
||||
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class RetryContext {
|
||||
|
||||
|
||||
@ -1,25 +1,30 @@
|
||||
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.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
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 "
|
||||
@ -33,7 +38,9 @@ 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")
|
||||
@ -63,6 +70,17 @@ 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);
|
||||
@ -75,7 +93,7 @@ public class BranchUpdateTrigger extends JobTrigger {
|
||||
} else if (refUpdated.getNewCommitId().equals(ObjectId.zeroId())) {
|
||||
return false;
|
||||
} else {
|
||||
Repository repository = OneDev.getInstance(ProjectManager.class)
|
||||
Repository repository = OneDev.getInstance(ProjectService.class)
|
||||
.getRepository(refUpdated.getProject().getId());
|
||||
Collection<String> changedFiles = GitUtils.getChangedFiles(
|
||||
repository,
|
||||
@ -92,6 +110,14 @@ 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) {
|
||||
@ -102,7 +128,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)) {
|
||||
&& touchedFile(refUpdated) && pushedBy(refUpdated)) {
|
||||
return new TriggerMatch(refUpdated.getRefName(), null, null,
|
||||
getParamMatrix(), getExcludeParamMaps(), "Branch '" + updatedBranch + "' is updated");
|
||||
}
|
||||
@ -113,14 +139,26 @@ public class BranchUpdateTrigger extends JobTrigger {
|
||||
@Override
|
||||
public String getTriggerDescription() {
|
||||
String description;
|
||||
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";
|
||||
|
||||
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() + "'";
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
@ -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.entitymanager.SettingManager;
|
||||
import io.onedev.server.service.SettingService;
|
||||
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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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(SettingManager.class).getIssueSetting()
|
||||
return OneDev.getInstance(SettingService.class).getIssueSetting()
|
||||
.getStateSpecs().stream().map(StateSpec::getName).collect(toList());
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import io.onedev.server.web.util.WicketUtils;
|
||||
import org.apache.wicket.Component;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.validation.Valid;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -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.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
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 javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.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(ProjectManager.class)
|
||||
Repository repository = OneDev.getInstance(ProjectService.class)
|
||||
.getRepository(request.getTargetProject().getId());
|
||||
Collection<String> changedFiles = GitUtils.getChangedFiles(repository,
|
||||
request.getBaseCommit(), request.getLatestUpdate().getHeadCommit());
|
||||
|
||||
@ -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.util.Input;
|
||||
import io.onedev.server.buildspecmodel.inputspec.Input;
|
||||
|
||||
public class ParamCombination implements Serializable {
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ import org.apache.commons.lang.SerializationUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.validation.ValidationException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
@ -6,7 +6,8 @@ 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.util.Input;
|
||||
import io.onedev.server.buildspecmodel.inputspec.Input;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
|
||||
@ -4,17 +4,18 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import io.onedev.commons.utils.ExplicitException;
|
||||
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.util.Input;
|
||||
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;
|
||||
|
||||
@Editable(name="Use value of specified parameter/secret")
|
||||
public class PassthroughValues implements ValuesProvider {
|
||||
|
||||
@ -4,7 +4,7 @@ import io.onedev.server.annotation.Editable;
|
||||
import io.onedev.server.buildspec.param.ParamCombination;
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ package io.onedev.server.buildspec.param.instance;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import io.onedev.server.buildspec.param.ParamCombination;
|
||||
import io.onedev.server.model.Build;
|
||||
|
||||
@ -2,7 +2,7 @@ package io.onedev.server.buildspec.param.spec;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import io.onedev.server.annotation.Multiline;
|
||||
|
||||
@ -7,15 +7,14 @@ 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 {
|
||||
@ -39,8 +38,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;
|
||||
@ -50,13 +49,8 @@ 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;
|
||||
@ -66,11 +60,6 @@ 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);
|
||||
|
||||
@ -6,15 +6,14 @@ 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 {
|
||||
@ -39,7 +38,7 @@ public class UserChoiceParam extends ParamSpec {
|
||||
}
|
||||
|
||||
@Editable(order=1100, name="Default Value", placeholder="No default value")
|
||||
@ShowCondition("isDefaultValueProviderVisible")
|
||||
@DependsOn(property="allowMultiple", value="false")
|
||||
@Valid
|
||||
public DefaultValueProvider getDefaultValueProvider() {
|
||||
return defaultValueProvider;
|
||||
@ -49,13 +48,8 @@ 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;
|
||||
@ -65,11 +59,6 @@ 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();
|
||||
|
||||
@ -7,6 +7,7 @@ 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;
|
||||
|
||||
@ -82,6 +83,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -119,6 +119,10 @@ 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() {
|
||||
|
||||
@ -2,6 +2,7 @@ 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;
|
||||
@ -35,6 +36,7 @@ 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;
|
||||
|
||||
@ -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.entitymanager.BuildManager;
|
||||
import io.onedev.server.entitymanager.IterationManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
import io.onedev.server.service.IterationService;
|
||||
import io.onedev.server.model.Iteration;
|
||||
import io.onedev.server.model.Project;
|
||||
import io.onedev.server.persistence.TransactionManager;
|
||||
import io.onedev.server.persistence.TransactionService;
|
||||
|
||||
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(TransactionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
return OneDev.getInstance(TransactionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
Project project = build.getProject();
|
||||
String iterationName = getIterationName();
|
||||
IterationManager iterationManager = OneDev.getInstance(IterationManager.class);
|
||||
Iteration iteration = iterationManager.findInHierarchy(project, iterationName);
|
||||
IterationService iterationService = OneDev.getInstance(IterationService.class);
|
||||
Iteration iteration = iterationService.findInHierarchy(project, iterationName);
|
||||
if (iteration != null) {
|
||||
if (build.canCloseIteration(getAccessTokenSecret())) {
|
||||
iteration.setClosed(true);
|
||||
iterationManager.createOrUpdate(iteration);
|
||||
iterationService.createOrUpdate(iteration);
|
||||
} else {
|
||||
logger.error("This build is not authorized to close iteration '" + iterationName + "'");
|
||||
return new ServerStepResult(false);
|
||||
|
||||
@ -6,15 +6,16 @@ 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;
|
||||
@ -23,7 +24,6 @@ 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,14 +57,9 @@ 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")
|
||||
@ShowCondition("isRunInContainerEnabled")
|
||||
@DependsOn(property="runInContainer")
|
||||
@Interpolative(variableSuggester="suggestVariables")
|
||||
@NotEmpty
|
||||
public String getImage() {
|
||||
@ -76,10 +71,17 @@ 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;
|
||||
@ -92,7 +94,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")
|
||||
@ShowCondition("isRunInContainerEnabled")
|
||||
@DependsOn(property="runInContainer")
|
||||
@RegEx(pattern="\\d+:\\d+", message = "Should be specified in form of <uid>:<gid>")
|
||||
public String getRunAs() {
|
||||
return runAs;
|
||||
@ -105,7 +107,8 @@ 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")
|
||||
@ShowCondition("isRunInContainerEnabled")
|
||||
@DependsOn(property="runInContainer")
|
||||
@Valid
|
||||
public List<RegistryLogin> getRegistryLogins() {
|
||||
return registryLogins;
|
||||
}
|
||||
@ -116,6 +119,7 @@ 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;
|
||||
}
|
||||
@ -125,7 +129,7 @@ public class CommandStep extends Step {
|
||||
}
|
||||
|
||||
@Editable(order=10000, name="Enable TTY Mode", group = "More Settings", description=USE_TTY_HELP)
|
||||
@ShowCondition("isRunInContainerEnabled")
|
||||
@DependsOn(property="runInContainer")
|
||||
public boolean isUseTTY() {
|
||||
return useTTY;
|
||||
}
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
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.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;
|
||||
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
|
||||
|
||||
public abstract class CraneStep extends CommandStep {
|
||||
|
||||
@ -70,6 +72,10 @@ 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() {
|
||||
|
||||
@ -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.entitymanager.BuildManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
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.SessionManager;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
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(SessionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
return OneDev.getInstance(SessionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
Project project = build.getProject();
|
||||
String branchName = getBranchName();
|
||||
|
||||
|
||||
@ -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.entitymanager.BuildManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.entitymanager.UserManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.service.UserService;
|
||||
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.SessionManager;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
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(SessionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
PersonIdent taggerIdent = OneDev.getInstance(UserManager.class).getSystem().asPerson();
|
||||
return OneDev.getInstance(SessionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
PersonIdent taggerIdent = OneDev.getInstance(UserService.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(ProjectManager.class).deleteTag(project, tagName);
|
||||
OneDev.getInstance(ProjectService.class).deleteTag(project, tagName);
|
||||
OneDev.getInstance(GitService.class).createTag(project, tagName, build.getCommitHash(),
|
||||
taggerIdent, getTagMessage(), false);
|
||||
} else {
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
package io.onedev.server.buildspec.step;
|
||||
|
||||
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 static io.onedev.server.buildspec.step.StepGroup.UTILITIES;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static io.onedev.server.buildspec.step.StepGroup.UTILITIES;
|
||||
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;
|
||||
|
||||
@Editable(order=1110, group = UTILITIES, name="Generate File Checksum", description = "" +
|
||||
"This step can only be executed by a docker aware executor")
|
||||
@ -45,6 +48,10 @@ 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;
|
||||
|
||||
@ -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.StorageManager;
|
||||
import io.onedev.server.StorageService;
|
||||
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.entitymanager.BuildManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.persistence.SessionManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
import io.onedev.server.util.patternset.PatternSet;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
@ -23,7 +23,8 @@ import java.util.List;
|
||||
|
||||
import static io.onedev.server.buildspec.step.StepGroup.PUBLISH;
|
||||
|
||||
@Editable(order=1050, group= PUBLISH, name="Artifacts")
|
||||
@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")
|
||||
public class PublishArtifactStep extends ServerSideStep {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ -46,8 +47,7 @@ public class PublishArtifactStep extends ServerSideStep {
|
||||
this.sourcePath = sourcePath;
|
||||
}
|
||||
|
||||
@Editable(order=100, description="Specify files under above directory to be published. "
|
||||
+ "Use * or ? for pattern match")
|
||||
@Editable(order=100, description="Specify files under above directory to be published")
|
||||
@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(SessionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
return OneDev.getInstance(SessionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
return LockUtils.write(build.getArtifactsLockName(), () -> {
|
||||
var projectId = build.getProject().getId();
|
||||
var artifactsDir = OneDev.getInstance(StorageManager.class).initArtifactsDir(projectId, build.getNumber());
|
||||
var artifactsDir = OneDev.getInstance(StorageService.class).initArtifactsDir(projectId, build.getNumber());
|
||||
FileUtils.copyDirectory(inputDir, artifactsDir);
|
||||
OneDev.getInstance(ProjectManager.class).directoryModified(projectId, artifactsDir);
|
||||
OneDev.getInstance(ProjectService.class).directoryModified(projectId, artifactsDir);
|
||||
return new ServerStepResult(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -20,15 +20,13 @@ 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.entitymanager.BuildManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.service.SettingService;
|
||||
import io.onedev.server.job.JobContext;
|
||||
import io.onedev.server.job.JobManager;
|
||||
import io.onedev.server.model.Build;
|
||||
import io.onedev.server.job.JobService;
|
||||
import io.onedev.server.model.Project;
|
||||
import io.onedev.server.model.support.administration.jobexecutor.JobExecutor;
|
||||
import io.onedev.server.persistence.SessionManager;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
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. "
|
||||
@ -94,13 +92,13 @@ public class PublishSiteStep extends ServerSideStep {
|
||||
|
||||
@Override
|
||||
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
|
||||
return OneDev.getInstance(SessionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
JobContext jobContext = OneDev.getInstance(JobManager.class).getJobContext(build.getId());
|
||||
return OneDev.getInstance(SessionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
JobContext jobContext = OneDev.getInstance(JobService.class).getJobContext(build.getId());
|
||||
if (jobContext.getJobExecutor().isSitePublishEnabled()) {
|
||||
Project project;
|
||||
if (projectPath != null) {
|
||||
project = OneDev.getInstance(ProjectManager.class).findByPath(projectPath);
|
||||
project = OneDev.getInstance(ProjectService.class).findByPath(projectPath);
|
||||
if (project == null) {
|
||||
logger.error("Unable to find project: " + projectPath);
|
||||
return new ServerStepResult(false);
|
||||
@ -110,13 +108,13 @@ public class PublishSiteStep extends ServerSideStep {
|
||||
}
|
||||
var projectId = project.getId();
|
||||
LockUtils.write(project.getSiteLockName(), () -> {
|
||||
File projectSiteDir = OneDev.getInstance(ProjectManager.class).getSiteDir(projectId);
|
||||
File projectSiteDir = OneDev.getInstance(ProjectService.class).getSiteDir(projectId);
|
||||
FileUtils.cleanDir(projectSiteDir);
|
||||
FileUtils.copyDirectory(inputDir, projectSiteDir);
|
||||
OneDev.getInstance(ProjectManager.class).directoryModified(projectId, projectSiteDir);
|
||||
OneDev.getInstance(ProjectService.class).directoryModified(projectId, projectSiteDir);
|
||||
return null;
|
||||
});
|
||||
String serverUrl = OneDev.getInstance(SettingManager.class).getSystemSetting().getServerUrl();
|
||||
String serverUrl = OneDev.getInstance(SettingService.class).getSystemSetting().getServerUrl();
|
||||
logger.log("Site published as "
|
||||
+ StringUtils.stripEnd(serverUrl, "/") + "/" + project.getPath() + "/~site");
|
||||
} else {
|
||||
@ -127,9 +125,4 @@ public class PublishSiteStep extends ServerSideStep {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Build build, JobExecutor executor) {
|
||||
return executor.isSitePublishEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ 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;
|
||||
@ -13,7 +14,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
@ -44,8 +45,9 @@ 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.entitymanager.BuildManager;
|
||||
import io.onedev.server.entitymanager.ProjectManager;
|
||||
import io.onedev.server.service.BuildService;
|
||||
import io.onedev.server.service.ProjectService;
|
||||
import io.onedev.server.service.UserService;
|
||||
import io.onedev.server.event.ListenerRegistry;
|
||||
import io.onedev.server.event.project.RefUpdated;
|
||||
import io.onedev.server.git.CommandUtils;
|
||||
@ -54,7 +56,8 @@ 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.persistence.SessionManager;
|
||||
import io.onedev.server.model.User;
|
||||
import io.onedev.server.persistence.SessionService;
|
||||
import io.onedev.server.security.SecurityUtils;
|
||||
|
||||
@Editable(order=1070, name="Pull from Remote", group=StepGroup.REPOSITORY_SYNC, description=""
|
||||
@ -136,12 +139,12 @@ public class PullRepository extends SyncRepository {
|
||||
|
||||
@Override
|
||||
public ServerStepResult run(Long buildId, File inputDir, TaskLogger logger) {
|
||||
return OneDev.getInstance(SessionManager.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildManager.class).load(buildId);
|
||||
return OneDev.getInstance(SessionService.class).call(() -> {
|
||||
var build = OneDev.getInstance(BuildService.class).load(buildId);
|
||||
Project project = build.getProject();
|
||||
Project targetProject;
|
||||
if (getTargetProject() != null) {
|
||||
targetProject = getProjectManager().findByPath(getTargetProject());
|
||||
targetProject = getProjectService().findByPath(getTargetProject());
|
||||
if (targetProject == null)
|
||||
throw new ExplicitException("Target project not found: " + getTargetProject());
|
||||
} else {
|
||||
@ -158,21 +161,34 @@ 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, remoteUrl, getCertificate(), getRefs(), isForce(), isWithLfs(), getProxy(), build.getSecretMasker());
|
||||
getProjectManager().runOnActiveServer(targetProjectId, task);
|
||||
var task = new PullTask(targetProjectId, userId, remoteUrl, getCertificate(), getRefs(), isForce(), isWithLfs(), getProxy(), build.getSecretMasker());
|
||||
getProjectService().runOnActiveServer(targetProjectId, task);
|
||||
return new ServerStepResult(true);
|
||||
});
|
||||
}
|
||||
|
||||
private static ProjectManager getProjectManager() {
|
||||
return OneDev.getInstance(ProjectManager.class);
|
||||
private static ProjectService getProjectService() {
|
||||
return OneDev.getInstance(ProjectService.class);
|
||||
}
|
||||
|
||||
private static UserService getUserService() {
|
||||
return OneDev.getInstance(UserService.class);
|
||||
}
|
||||
|
||||
private static class PullTask implements ClusterTask<Void> {
|
||||
|
||||
private final Long projectId;
|
||||
|
||||
private final Long userId;
|
||||
|
||||
private final String remoteUrl;
|
||||
|
||||
@ -188,10 +204,11 @@ public class PullRepository extends SyncRepository {
|
||||
|
||||
private final SecretMasker secretMasker;
|
||||
|
||||
PullTask(Long projectId, String remoteUrl, @Nullable String certificate,
|
||||
PullTask(Long projectId, Long userId, 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;
|
||||
@ -225,7 +242,7 @@ public class PullRepository extends SyncRepository {
|
||||
var certificateFile = writeCertificate(certificate);
|
||||
SecretMasker.push(secretMasker);
|
||||
try {
|
||||
Repository repository = getProjectManager().getRepository(projectId);
|
||||
Repository repository = getProjectService().getRepository(projectId);
|
||||
|
||||
String defaultBranch = GitUtils.getDefaultBranch(repository);
|
||||
Map<String, ObjectId> oldCommitIds = getRefCommits(repository);
|
||||
@ -344,7 +361,7 @@ public class PullRepository extends SyncRepository {
|
||||
git.clearArgs();
|
||||
configureProxy(git, proxy);
|
||||
configureCertificate(git, certificateFile);
|
||||
var sinceCommitIds = getProjectManager().readLfsSinceCommits(projectId);
|
||||
var sinceCommitIds = getProjectService().readLfsSinceCommits(projectId);
|
||||
|
||||
if (sinceCommitIds.isEmpty()) {
|
||||
new LfsFetchAllCommand(git.workingDir(), remoteUrl) {
|
||||
@ -362,27 +379,28 @@ public class PullRepository extends SyncRepository {
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
getProjectManager().writeLfsSinceCommits(projectId, newCommitIds.values());
|
||||
getProjectService().writeLfsSinceCommits(projectId, newCommitIds.values());
|
||||
}
|
||||
|
||||
OneDev.getInstance(SessionManager.class).runAsync(() -> {
|
||||
OneDev.getInstance(SessionService.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 = getProjectManager().load(projectId);
|
||||
var project = getProjectService().load(projectId);
|
||||
var user = getUserService().load(userId);
|
||||
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(project, entry.getKey(), entry.getValue(), ObjectId.zeroId()));
|
||||
registry.post(new RefUpdated(user, 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(project, entry.getKey(), ObjectId.zeroId(), entry.getValue()));
|
||||
registry.post(new RefUpdated(user, 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(project, entry.getKey(),
|
||||
registry.post(new RefUpdated(user, project, entry.getKey(),
|
||||
entry.getValue().leftValue(), entry.getValue().rightValue()));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user