mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Build is initially set to pending when execute by job executors
This commit is contained in:
parent
8a0c9d0060
commit
ded705cc5c
@ -37,6 +37,7 @@ import io.onedev.commons.launcher.loader.ListenerRegistry;
|
|||||||
import io.onedev.commons.utils.ExceptionUtils;
|
import io.onedev.commons.utils.ExceptionUtils;
|
||||||
import io.onedev.commons.utils.FileUtils;
|
import io.onedev.commons.utils.FileUtils;
|
||||||
import io.onedev.commons.utils.LockUtils;
|
import io.onedev.commons.utils.LockUtils;
|
||||||
|
import io.onedev.commons.utils.MatrixRunner;
|
||||||
import io.onedev.commons.utils.schedule.SchedulableTask;
|
import io.onedev.commons.utils.schedule.SchedulableTask;
|
||||||
import io.onedev.commons.utils.schedule.TaskScheduler;
|
import io.onedev.commons.utils.schedule.TaskScheduler;
|
||||||
import io.onedev.server.OneException;
|
import io.onedev.server.OneException;
|
||||||
@ -53,7 +54,7 @@ import io.onedev.server.entitymanager.UserManager;
|
|||||||
import io.onedev.server.event.BuildCommitAware;
|
import io.onedev.server.event.BuildCommitAware;
|
||||||
import io.onedev.server.event.ProjectEvent;
|
import io.onedev.server.event.ProjectEvent;
|
||||||
import io.onedev.server.event.build.BuildFinished;
|
import io.onedev.server.event.build.BuildFinished;
|
||||||
import io.onedev.server.event.build.BuildQueueing;
|
import io.onedev.server.event.build.BuildPending;
|
||||||
import io.onedev.server.event.build.BuildRunning;
|
import io.onedev.server.event.build.BuildRunning;
|
||||||
import io.onedev.server.event.build.BuildSubmitted;
|
import io.onedev.server.event.build.BuildSubmitted;
|
||||||
import io.onedev.server.event.entity.EntityPersisted;
|
import io.onedev.server.event.entity.EntityPersisted;
|
||||||
@ -65,15 +66,15 @@ import io.onedev.server.model.BuildParam;
|
|||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.Setting;
|
import io.onedev.server.model.Setting;
|
||||||
import io.onedev.server.model.Setting.Key;
|
import io.onedev.server.model.Setting.Key;
|
||||||
|
import io.onedev.server.model.User;
|
||||||
|
import io.onedev.server.model.support.JobExecutionContext;
|
||||||
import io.onedev.server.model.support.JobExecutor;
|
import io.onedev.server.model.support.JobExecutor;
|
||||||
import io.onedev.server.model.support.SourceSnapshot;
|
import io.onedev.server.model.support.SourceSnapshot;
|
||||||
import io.onedev.server.model.User;
|
|
||||||
import io.onedev.server.persistence.SessionManager;
|
import io.onedev.server.persistence.SessionManager;
|
||||||
import io.onedev.server.persistence.TransactionManager;
|
import io.onedev.server.persistence.TransactionManager;
|
||||||
import io.onedev.server.persistence.annotation.Sessional;
|
import io.onedev.server.persistence.annotation.Sessional;
|
||||||
import io.onedev.server.persistence.annotation.Transactional;
|
import io.onedev.server.persistence.annotation.Transactional;
|
||||||
import io.onedev.server.util.Input;
|
import io.onedev.server.util.Input;
|
||||||
import io.onedev.server.util.MatrixRunner;
|
|
||||||
import io.onedev.server.util.inputspec.InputSpec;
|
import io.onedev.server.util.inputspec.InputSpec;
|
||||||
import io.onedev.server.util.inputspec.SecretInput;
|
import io.onedev.server.util.inputspec.SecretInput;
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
import io.onedev.server.util.patternset.PatternSet;
|
||||||
@ -150,9 +151,7 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
// Lock to guarantee uniqueness of build (by project, commit, job and parameters)
|
||||||
* Lock to guarantee uniqueness of build (by project, commit, job and parameters)
|
|
||||||
*/
|
|
||||||
try {
|
try {
|
||||||
lock.lockInterruptibly();
|
lock.lockInterruptibly();
|
||||||
return submit(project, commitId, jobName, paramMap, submitter, new LinkedHashSet<>());
|
return submit(project, commitId, jobName, paramMap, submitter, new LinkedHashSet<>());
|
||||||
@ -241,18 +240,12 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(Build build) {
|
private void execute(Build build) {
|
||||||
try {
|
try {
|
||||||
Job job = build.getJob();
|
Job job = build.getJob();
|
||||||
ObjectId commitId = ObjectId.fromString(build.getCommitHash());
|
ObjectId commitId = ObjectId.fromString(build.getCommitHash());
|
||||||
JobExecutor executor = getJobExecutor(build.getProject(), commitId, job.getName(), job.getEnvironment());
|
JobExecutor executor = getJobExecutor(build.getProject(), commitId, job.getName(), job.getEnvironment());
|
||||||
if (executor != null) {
|
if (executor != null) {
|
||||||
if (executor.hasCapacity()) {
|
|
||||||
build.setStatus(Build.Status.RUNNING);
|
|
||||||
build.setRunningDate(new Date());
|
|
||||||
buildManager.save(build);
|
|
||||||
listenerRegistry.post(new BuildRunning(build));
|
|
||||||
|
|
||||||
SourceSnapshot snapshot;
|
SourceSnapshot snapshot;
|
||||||
if (job.isCloneSource())
|
if (job.isCloneSource())
|
||||||
snapshot = new SourceSnapshot(build.getProject(), commitId);
|
snapshot = new SourceSnapshot(build.getProject(), commitId);
|
||||||
@ -320,8 +313,27 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
logger.info("Executing job with executor '" + executor.getName() + "'...");
|
logger.info("Executing job with executor '" + executor.getName() + "'...");
|
||||||
|
|
||||||
List<String> commands = Splitter.on("\n").trimResults(CharMatcher.is('\r')).splitToList(job.getCommands());
|
List<String> commands = Splitter.on("\n").trimResults(CharMatcher.is('\r')).splitToList(job.getCommands());
|
||||||
executor.execute(job.getEnvironment(), workspace, envVars, commands, snapshot,
|
executor.execute(new JobExecutionContext(job.getEnvironment(), workspace, envVars, commands,
|
||||||
job.getCaches(), new PatternSet(includeFiles, excludeFiles), logger);
|
snapshot, job.getCaches(), new PatternSet(includeFiles, excludeFiles), logger) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyJobRunning() {
|
||||||
|
transactionManager.run(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
logger.info("Collecting job outcomes...");
|
||||||
|
Build build = buildManager.load(buildId);
|
||||||
|
build.setStatus(Build.Status.RUNNING);
|
||||||
|
build.setRunningDate(new Date());
|
||||||
|
buildManager.save(build);
|
||||||
|
listenerRegistry.post(new BuildRunning(build));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
sessionManager.run(new Runnable() {
|
sessionManager.run(new Runnable() {
|
||||||
|
|
||||||
@ -352,7 +364,6 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
|
|
||||||
if (prevExecution != null)
|
if (prevExecution != null)
|
||||||
prevExecution.cancel(null);
|
prevExecution.cancel(null);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
markBuildError(build, "No applicable job executor");
|
markBuildError(build, "No applicable job executor");
|
||||||
}
|
}
|
||||||
@ -405,7 +416,7 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
if (build.isFinished()) {
|
if (build.isFinished()) {
|
||||||
build.setStatus(Build.Status.WAITING);
|
build.setStatus(Build.Status.WAITING);
|
||||||
build.setFinishDate(null);
|
build.setFinishDate(null);
|
||||||
build.setQueueingDate(null);
|
build.setPendingDate(null);
|
||||||
build.setRunningDate(null);
|
build.setRunningDate(null);
|
||||||
build.setSubmitDate(new Date());
|
build.setSubmitDate(new Date());
|
||||||
build.setSubmitter(submitter);
|
build.setSubmitter(submitter);
|
||||||
@ -497,10 +508,7 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
@Override
|
@Override
|
||||||
public Boolean call() {
|
public Boolean call() {
|
||||||
for (Build build: buildManager.queryUnfinished()) {
|
for (Build build: buildManager.queryUnfinished()) {
|
||||||
if (build.getStatus() == Build.Status.QUEUEING) {
|
if (build.getStatus() == Build.Status.PENDING || build.getStatus() == Build.Status.RUNNING) {
|
||||||
if (status == Status.STARTED)
|
|
||||||
run(build);
|
|
||||||
} else if (build.getStatus() == Build.Status.RUNNING) {
|
|
||||||
JobExecution execution = jobExecutions.get(build.getId());
|
JobExecution execution = jobExecutions.get(build.getId());
|
||||||
if (execution != null) {
|
if (execution != null) {
|
||||||
if (execution.isTimedout())
|
if (execution.isTimedout())
|
||||||
@ -526,9 +534,12 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
if (hasUnsuccessful) {
|
if (hasUnsuccessful) {
|
||||||
markBuildError(build, "There are failed dependency jobs");
|
markBuildError(build, "There are failed dependency jobs");
|
||||||
} else if (!hasUnfinished) {
|
} else if (!hasUnfinished) {
|
||||||
build.setStatus(Build.Status.QUEUEING);
|
build.setStatus(Build.Status.PENDING);
|
||||||
build.setQueueingDate(new Date());
|
build.setPendingDate(new Date());
|
||||||
listenerRegistry.post(new BuildQueueing(build));
|
listenerRegistry.post(new BuildPending(build));
|
||||||
|
|
||||||
|
if (status == Status.STARTED)
|
||||||
|
execute(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -536,7 +547,7 @@ public class DefaultJobManager implements JobManager, Runnable, SchedulableTask
|
|||||||
Map.Entry<Long, JobExecution> entry = it.next();
|
Map.Entry<Long, JobExecution> entry = it.next();
|
||||||
Build build = buildManager.get(entry.getKey());
|
Build build = buildManager.get(entry.getKey());
|
||||||
JobExecution execution = entry.getValue();
|
JobExecution execution = entry.getValue();
|
||||||
if (build == null || build.getStatus() != Build.Status.RUNNING) {
|
if (build == null || build.getStatus() != Build.Status.PENDING && build.getStatus() != Build.Status.RUNNING) {
|
||||||
it.remove();
|
it.remove();
|
||||||
execution.cancel(null);
|
execution.cancel(null);
|
||||||
} else if (execution.isDone()) {
|
} else if (execution.isDone()) {
|
||||||
|
|||||||
@ -161,7 +161,7 @@ public class DefaultBuildManager extends AbstractEntityManager<Build> implements
|
|||||||
public Collection<Build> queryUnfinished() {
|
public Collection<Build> queryUnfinished() {
|
||||||
EntityCriteria<Build> criteria = newCriteria();
|
EntityCriteria<Build> criteria = newCriteria();
|
||||||
criteria.add(Restrictions.or(
|
criteria.add(Restrictions.or(
|
||||||
Restrictions.eq("status", Status.QUEUEING),
|
Restrictions.eq("status", Status.PENDING),
|
||||||
Restrictions.eq("status", Status.RUNNING),
|
Restrictions.eq("status", Status.RUNNING),
|
||||||
Restrictions.eq("status", Status.WAITING)));
|
Restrictions.eq("status", Status.WAITING)));
|
||||||
criteria.setCacheable(true);
|
criteria.setCacheable(true);
|
||||||
|
|||||||
@ -56,6 +56,7 @@ import com.google.common.base.Preconditions;
|
|||||||
import io.onedev.commons.launcher.loader.Listen;
|
import io.onedev.commons.launcher.loader.Listen;
|
||||||
import io.onedev.commons.launcher.loader.ListenerRegistry;
|
import io.onedev.commons.launcher.loader.ListenerRegistry;
|
||||||
import io.onedev.commons.utils.ExceptionUtils;
|
import io.onedev.commons.utils.ExceptionUtils;
|
||||||
|
import io.onedev.commons.utils.MatrixRunner;
|
||||||
import io.onedev.commons.utils.concurrent.Prioritized;
|
import io.onedev.commons.utils.concurrent.Prioritized;
|
||||||
import io.onedev.server.OneDev;
|
import io.onedev.server.OneDev;
|
||||||
import io.onedev.server.OneException;
|
import io.onedev.server.OneException;
|
||||||
@ -123,7 +124,6 @@ import io.onedev.server.search.entity.pullrequest.PullRequestQuery;
|
|||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.security.permission.ProjectPermission;
|
import io.onedev.server.security.permission.ProjectPermission;
|
||||||
import io.onedev.server.security.permission.ProjectPrivilege;
|
import io.onedev.server.security.permission.ProjectPrivilege;
|
||||||
import io.onedev.server.util.MatrixRunner;
|
|
||||||
import io.onedev.server.util.PullRequestConstants;
|
import io.onedev.server.util.PullRequestConstants;
|
||||||
import io.onedev.server.util.facade.ProjectFacade;
|
import io.onedev.server.util.facade.ProjectFacade;
|
||||||
import io.onedev.server.util.facade.UserFacade;
|
import io.onedev.server.util.facade.UserFacade;
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
package io.onedev.server.event.build;
|
||||||
|
|
||||||
|
import io.onedev.server.model.Build;
|
||||||
|
|
||||||
|
public class BuildPending extends BuildEvent {
|
||||||
|
|
||||||
|
public BuildPending(Build build) {
|
||||||
|
super(null, build.getPendingDate(), build);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package io.onedev.server.event.build;
|
|
||||||
|
|
||||||
import io.onedev.server.model.Build;
|
|
||||||
|
|
||||||
public class BuildQueueing extends BuildEvent {
|
|
||||||
|
|
||||||
public BuildQueueing(Build build) {
|
|
||||||
super(null, build.getQueueingDate(), build);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -61,7 +61,7 @@ import io.onedev.server.web.editable.PropertyDescriptor;
|
|||||||
indexes={@Index(columnList="o_project_id"), @Index(columnList="o_submitter_id"), @Index(columnList="o_canceller_id"),
|
indexes={@Index(columnList="o_project_id"), @Index(columnList="o_submitter_id"), @Index(columnList="o_canceller_id"),
|
||||||
@Index(columnList="submitterName"), @Index(columnList="cancellerName"), @Index(columnList="commitHash"),
|
@Index(columnList="submitterName"), @Index(columnList="cancellerName"), @Index(columnList="commitHash"),
|
||||||
@Index(columnList="number"), @Index(columnList="jobName"), @Index(columnList="status"),
|
@Index(columnList="number"), @Index(columnList="jobName"), @Index(columnList="status"),
|
||||||
@Index(columnList="submitDate"), @Index(columnList="queueingDate"), @Index(columnList="runningDate"),
|
@Index(columnList="submitDate"), @Index(columnList="pendingDate"), @Index(columnList="runningDate"),
|
||||||
@Index(columnList="finishDate"), @Index(columnList="version"),
|
@Index(columnList="finishDate"), @Index(columnList="version"),
|
||||||
@Index(columnList="o_project_id, commitHash")},
|
@Index(columnList="o_project_id, commitHash")},
|
||||||
uniqueConstraints={@UniqueConstraint(columnNames={"o_project_id", "number"})}
|
uniqueConstraints={@UniqueConstraint(columnNames={"o_project_id", "number"})}
|
||||||
@ -79,7 +79,7 @@ public class Build extends AbstractEntity implements Referenceable {
|
|||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
// Most significant status comes first, refer to getOverallStatus
|
// Most significant status comes first, refer to getOverallStatus
|
||||||
WAITING, QUEUEING, RUNNING, IN_ERROR, FAILED, CANCELLED, TIMED_OUT, SUCCESSFUL;
|
WAITING, PENDING, RUNNING, IN_ERROR, FAILED, CANCELLED, TIMED_OUT, SUCCESSFUL;
|
||||||
|
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
return StringUtils.capitalize(name().replace('_', ' ').toLowerCase());
|
return StringUtils.capitalize(name().replace('_', ' ').toLowerCase());
|
||||||
@ -126,7 +126,7 @@ public class Build extends AbstractEntity implements Referenceable {
|
|||||||
@Column(nullable=false)
|
@Column(nullable=false)
|
||||||
private Date submitDate;
|
private Date submitDate;
|
||||||
|
|
||||||
private Date queueingDate;
|
private Date pendingDate;
|
||||||
|
|
||||||
private Date runningDate;
|
private Date runningDate;
|
||||||
|
|
||||||
@ -266,12 +266,12 @@ public class Build extends AbstractEntity implements Referenceable {
|
|||||||
this.submitDate = submitDate;
|
this.submitDate = submitDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getQueueingDate() {
|
public Date getPendingDate() {
|
||||||
return queueingDate;
|
return pendingDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setQueueingDate(Date queueingDate) {
|
public void setPendingDate(Date pendingDate) {
|
||||||
this.queueingDate = queueingDate;
|
this.pendingDate = pendingDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getRunningDate() {
|
public Date getRunningDate() {
|
||||||
|
|||||||
@ -71,6 +71,7 @@ import io.onedev.commons.launcher.loader.ListenerRegistry;
|
|||||||
import io.onedev.commons.utils.FileUtils;
|
import io.onedev.commons.utils.FileUtils;
|
||||||
import io.onedev.commons.utils.LinearRange;
|
import io.onedev.commons.utils.LinearRange;
|
||||||
import io.onedev.commons.utils.LockUtils;
|
import io.onedev.commons.utils.LockUtils;
|
||||||
|
import io.onedev.commons.utils.MatrixRunner;
|
||||||
import io.onedev.commons.utils.StringUtils;
|
import io.onedev.commons.utils.StringUtils;
|
||||||
import io.onedev.commons.utils.stringmatch.ChildAwareMatcher;
|
import io.onedev.commons.utils.stringmatch.ChildAwareMatcher;
|
||||||
import io.onedev.commons.utils.stringmatch.Matcher;
|
import io.onedev.commons.utils.stringmatch.Matcher;
|
||||||
@ -120,7 +121,6 @@ import io.onedev.server.persistence.TransactionManager;
|
|||||||
import io.onedev.server.security.SecurityUtils;
|
import io.onedev.server.security.SecurityUtils;
|
||||||
import io.onedev.server.security.permission.DefaultPrivilege;
|
import io.onedev.server.security.permission.DefaultPrivilege;
|
||||||
import io.onedev.server.storage.StorageManager;
|
import io.onedev.server.storage.StorageManager;
|
||||||
import io.onedev.server.util.MatrixRunner;
|
|
||||||
import io.onedev.server.util.facade.ProjectFacade;
|
import io.onedev.server.util.facade.ProjectFacade;
|
||||||
import io.onedev.server.util.jackson.DefaultView;
|
import io.onedev.server.util.jackson.DefaultView;
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
import io.onedev.server.util.patternset.PatternSet;
|
||||||
|
|||||||
@ -0,0 +1,81 @@
|
|||||||
|
package io.onedev.server.model.support;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import io.onedev.server.ci.job.cache.JobCache;
|
||||||
|
import io.onedev.server.util.patternset.PatternSet;
|
||||||
|
|
||||||
|
public abstract class JobExecutionContext {
|
||||||
|
|
||||||
|
private final String environment;
|
||||||
|
|
||||||
|
private final File workspace;
|
||||||
|
|
||||||
|
private final Map<String, String> envVars;
|
||||||
|
|
||||||
|
private final List<String> commands;
|
||||||
|
|
||||||
|
private final @Nullable SourceSnapshot snapshot;
|
||||||
|
|
||||||
|
private final Collection<JobCache> caches;
|
||||||
|
|
||||||
|
private final PatternSet collectFiles;
|
||||||
|
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public JobExecutionContext(String environment, File workspace, Map<String, String> envVars,
|
||||||
|
List<String> commands, @Nullable SourceSnapshot snapshot, Collection<JobCache> caches,
|
||||||
|
PatternSet collectFiles, Logger logger) {
|
||||||
|
this.environment = environment;
|
||||||
|
this.workspace = workspace;
|
||||||
|
this.envVars = envVars;
|
||||||
|
this.commands = commands;
|
||||||
|
this.snapshot = snapshot;
|
||||||
|
this.caches = caches;
|
||||||
|
this.collectFiles = collectFiles;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnvironment() {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWorkspace() {
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getEnvVars() {
|
||||||
|
return envVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getCommands() {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SourceSnapshot getSnapshot() {
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<JobCache> getCaches() {
|
||||||
|
return caches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PatternSet getCollectFiles() {
|
||||||
|
return collectFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void notifyJobRunning();
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,20 +2,13 @@ package io.onedev.server.model.support;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import io.onedev.commons.launcher.loader.ExtensionPoint;
|
import io.onedev.commons.launcher.loader.ExtensionPoint;
|
||||||
import io.onedev.commons.utils.stringmatch.ChildAwareMatcher;
|
import io.onedev.commons.utils.stringmatch.ChildAwareMatcher;
|
||||||
import io.onedev.commons.utils.stringmatch.Matcher;
|
import io.onedev.commons.utils.stringmatch.Matcher;
|
||||||
import io.onedev.server.ci.job.cache.JobCache;
|
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.util.Usage;
|
import io.onedev.server.util.Usage;
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
import io.onedev.server.util.patternset.PatternSet;
|
||||||
@ -127,9 +120,7 @@ public abstract class JobExecutor implements Serializable {
|
|||||||
this.cacheTTL = cacheTTL;
|
this.cacheTTL = cacheTTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void execute(String environment, File workspace, Map<String, String> envVars,
|
public abstract void execute(JobExecutionContext context);
|
||||||
List<String> commands, @Nullable SourceSnapshot snapshot, Collection<JobCache> caches,
|
|
||||||
PatternSet collectFiles, Logger logger);
|
|
||||||
|
|
||||||
public final boolean isApplicable(Project project, ObjectId commitId, String jobName, String environment) {
|
public final boolean isApplicable(Project project, ObjectId commitId, String jobName, String environment) {
|
||||||
Matcher matcher = new ChildAwareMatcher();
|
Matcher matcher = new ChildAwareMatcher();
|
||||||
@ -160,10 +151,6 @@ public abstract class JobExecutor implements Serializable {
|
|||||||
setProjects(patternSet.toString());
|
setProjects(patternSet.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasCapacity() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void checkCaches();
|
public abstract void checkCaches();
|
||||||
|
|
||||||
public abstract void cleanDir(File dir);
|
public abstract void cleanDir(File dir);
|
||||||
|
|||||||
@ -11,10 +11,10 @@ import javax.persistence.criteria.Predicate;
|
|||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
import edu.emory.mathcs.backport.java.util.Collections;
|
import edu.emory.mathcs.backport.java.util.Collections;
|
||||||
|
import io.onedev.commons.utils.RangeBuilder;
|
||||||
import io.onedev.server.model.AbstractEntity;
|
import io.onedev.server.model.AbstractEntity;
|
||||||
import io.onedev.server.model.Project;
|
import io.onedev.server.model.Project;
|
||||||
import io.onedev.server.model.User;
|
import io.onedev.server.model.User;
|
||||||
import io.onedev.server.util.RangeBuilder;
|
|
||||||
|
|
||||||
public abstract class EntityCriteria<T extends AbstractEntity> implements Serializable {
|
public abstract class EntityCriteria<T extends AbstractEntity> implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ query
|
|||||||
;
|
;
|
||||||
|
|
||||||
criteria
|
criteria
|
||||||
: operator=(Successful|Failed|InError|Cancelled|Running|Waiting|Queueing|TimedOut|SubmittedByMe|CancelledByMe) #OperatorCriteria
|
: operator=(Successful|Failed|InError|Cancelled|Running|Waiting|Pending|TimedOut|SubmittedByMe|CancelledByMe) #OperatorCriteria
|
||||||
| operator=(FixedIssue|SubmittedBy|CancelledBy|DependsOn|DependenciesOf|RequiredByPullRequest) WS+ criteriaValue=Quoted #OperatorValueCriteria
|
| operator=(FixedIssue|SubmittedBy|CancelledBy|DependsOn|DependenciesOf|RequiredByPullRequest) WS+ criteriaValue=Quoted #OperatorValueCriteria
|
||||||
| criteriaField=Quoted WS+ operator=(Is|IsGreaterThan|IsLessThan|IsBefore|IsAfter) WS+ criteriaValue=Quoted #FieldOperatorValueCriteria
|
| criteriaField=Quoted WS+ operator=(Is|IsGreaterThan|IsLessThan|IsBefore|IsAfter) WS+ criteriaValue=Quoted #FieldOperatorValueCriteria
|
||||||
| criteria WS+ And WS+ criteria #AndCriteria
|
| criteria WS+ And WS+ criteria #AndCriteria
|
||||||
@ -52,8 +52,8 @@ Waiting
|
|||||||
: 'waiting'
|
: 'waiting'
|
||||||
;
|
;
|
||||||
|
|
||||||
Queueing
|
Pending
|
||||||
: 'queueing'
|
: 'pending'
|
||||||
;
|
;
|
||||||
|
|
||||||
SubmittedByMe
|
SubmittedByMe
|
||||||
|
|||||||
@ -112,8 +112,8 @@ public class BuildQuery extends EntityQuery<Build> {
|
|||||||
return new InErrorCriteria();
|
return new InErrorCriteria();
|
||||||
case BuildQueryLexer.Waiting:
|
case BuildQueryLexer.Waiting:
|
||||||
return new WaitingCriteria();
|
return new WaitingCriteria();
|
||||||
case BuildQueryLexer.Queueing:
|
case BuildQueryLexer.Pending:
|
||||||
return new QueueingCriteria();
|
return new PendingCriteria();
|
||||||
case BuildQueryLexer.Running:
|
case BuildQueryLexer.Running:
|
||||||
return new RunningCriteria();
|
return new RunningCriteria();
|
||||||
case BuildQueryLexer.SubmittedByMe:
|
case BuildQueryLexer.SubmittedByMe:
|
||||||
|
|||||||
@ -11,19 +11,19 @@ import io.onedev.server.model.User;
|
|||||||
import io.onedev.server.search.entity.EntityCriteria;
|
import io.onedev.server.search.entity.EntityCriteria;
|
||||||
import io.onedev.server.util.BuildConstants;
|
import io.onedev.server.util.BuildConstants;
|
||||||
|
|
||||||
public class QueueingCriteria extends EntityCriteria<Build> {
|
public class PendingCriteria extends EntityCriteria<Build> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Predicate getPredicate(Project project, Root<Build> root, CriteriaBuilder builder, User user) {
|
public Predicate getPredicate(Project project, Root<Build> root, CriteriaBuilder builder, User user) {
|
||||||
Path<?> attribute = root.get(BuildConstants.ATTR_STATUS);
|
Path<?> attribute = root.get(BuildConstants.ATTR_STATUS);
|
||||||
return builder.equal(attribute, Build.Status.QUEUEING);
|
return builder.equal(attribute, Build.Status.PENDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(Build build, User user) {
|
public boolean matches(Build build, User user) {
|
||||||
return build.getStatus() == Build.Status.QUEUEING;
|
return build.getStatus() == Build.Status.PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -33,7 +33,7 @@ public class QueueingCriteria extends EntityCriteria<Build> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return BuildQuery.getRuleName(BuildQueryLexer.Queueing);
|
return BuildQuery.getRuleName(BuildQueryLexer.Pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -41,9 +41,9 @@ public class QueueingDateCriteria extends EntityCriteria<Build> {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(Build build, User user) {
|
public boolean matches(Build build, User user) {
|
||||||
if (operator == BuildQueryLexer.IsBefore)
|
if (operator == BuildQueryLexer.IsBefore)
|
||||||
return build.getQueueingDate().before(value);
|
return build.getPendingDate().before(value);
|
||||||
else
|
else
|
||||||
return build.getQueueingDate().after(value);
|
return build.getPendingDate().after(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -7,7 +7,7 @@ query
|
|||||||
;
|
;
|
||||||
|
|
||||||
criteria
|
criteria
|
||||||
: operator=(Open|Merged|Discarded|SubmittedByMe|ToBeReviewedByMe|RequestedForChangesByMe|ApprovedByMe|DiscardedByMe|SomeoneRequestedForChanges|HasPendingReviews|HasFailedBuilds|HasPendingBuilds|HasMergeConflicts) #OperatorCriteria
|
: operator=(Open|Merged|Discarded|SubmittedByMe|ToBeReviewedByMe|RequestedForChangesByMe|ApprovedByMe|DiscardedByMe|SomeoneRequestedForChanges|HasPendingReviews|HasFailedBuilds|ToBeVerifiedByBuilds|HasMergeConflicts) #OperatorCriteria
|
||||||
| operator=(ToBeReviewedBy|ApprovedBy|RequestedForChangesBy|SubmittedBy|DiscardedBy|IncludesCommit|IncludesIssue) WS+ criteriaValue=Quoted #OperatorValueCriteria
|
| operator=(ToBeReviewedBy|ApprovedBy|RequestedForChangesBy|SubmittedBy|DiscardedBy|IncludesCommit|IncludesIssue) WS+ criteriaValue=Quoted #OperatorValueCriteria
|
||||||
| criteriaField=Quoted WS+ operator=(Is|IsGreaterThan|IsLessThan|IsBefore|IsAfter|Contains) WS+ criteriaValue=Quoted #FieldOperatorValueCriteria
|
| criteriaField=Quoted WS+ operator=(Is|IsGreaterThan|IsLessThan|IsBefore|IsAfter|Contains) WS+ criteriaValue=Quoted #FieldOperatorValueCriteria
|
||||||
| criteria WS+ And WS+ criteria #AndCriteria
|
| criteria WS+ And WS+ criteria #AndCriteria
|
||||||
@ -68,8 +68,8 @@ HasFailedBuilds
|
|||||||
: 'has' WS+ 'failed' WS+ 'builds'
|
: 'has' WS+ 'failed' WS+ 'builds'
|
||||||
;
|
;
|
||||||
|
|
||||||
HasPendingBuilds
|
ToBeVerifiedByBuilds
|
||||||
: 'has' WS+ 'pending' WS+ 'builds'
|
: 'to' WS+ 'be' WS+ 'verified' WS+ 'by' WS+ 'builds'
|
||||||
;
|
;
|
||||||
|
|
||||||
HasMergeConflicts
|
HasMergeConflicts
|
||||||
|
|||||||
@ -109,8 +109,8 @@ public class PullRequestQuery extends EntityQuery<PullRequest> {
|
|||||||
return new HasFailedBuildsCriteria();
|
return new HasFailedBuildsCriteria();
|
||||||
case PullRequestQueryLexer.HasMergeConflicts:
|
case PullRequestQueryLexer.HasMergeConflicts:
|
||||||
return new HasMergeConflictsCriteria();
|
return new HasMergeConflictsCriteria();
|
||||||
case PullRequestQueryLexer.HasPendingBuilds:
|
case PullRequestQueryLexer.ToBeVerifiedByBuilds:
|
||||||
return new HasPendingBuildsCriteria();
|
return new ToBeVerifiedByBuildsCriteria();
|
||||||
case PullRequestQueryLexer.HasPendingReviews:
|
case PullRequestQueryLexer.HasPendingReviews:
|
||||||
return new HasPendingReviewsCriteria();
|
return new HasPendingReviewsCriteria();
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import io.onedev.server.model.PullRequest;
|
|||||||
import io.onedev.server.model.User;
|
import io.onedev.server.model.User;
|
||||||
import io.onedev.server.util.PullRequestConstants;
|
import io.onedev.server.util.PullRequestConstants;
|
||||||
|
|
||||||
public class HasPendingBuildsCriteria extends PullRequestCriteria {
|
public class ToBeVerifiedByBuildsCriteria extends PullRequestCriteria {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ public class HasPendingBuildsCriteria extends PullRequestCriteria {
|
|||||||
|
|
||||||
return builder.or(
|
return builder.or(
|
||||||
builder.equal(status, Build.Status.RUNNING),
|
builder.equal(status, Build.Status.RUNNING),
|
||||||
builder.equal(status, Build.Status.QUEUEING),
|
builder.equal(status, Build.Status.PENDING),
|
||||||
builder.equal(status, Build.Status.WAITING));
|
builder.equal(status, Build.Status.WAITING));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public class HasPendingBuildsCriteria extends PullRequestCriteria {
|
|||||||
public boolean matches(PullRequest request, User user) {
|
public boolean matches(PullRequest request, User user) {
|
||||||
for (PullRequestBuild build: request.getPullRequestBuilds()) {
|
for (PullRequestBuild build: request.getPullRequestBuilds()) {
|
||||||
if (build.getBuild().getStatus() == Build.Status.RUNNING
|
if (build.getBuild().getStatus() == Build.Status.RUNNING
|
||||||
|| build.getBuild().getStatus() == Build.Status.QUEUEING
|
|| build.getBuild().getStatus() == Build.Status.PENDING
|
||||||
|| build.getBuild().getStatus() == Build.Status.WAITING) {
|
|| build.getBuild().getStatus() == Build.Status.WAITING) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ public class HasPendingBuildsCriteria extends PullRequestCriteria {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return PullRequestQuery.getRuleName(PullRequestQueryLexer.HasPendingBuilds);
|
return PullRequestQuery.getRuleName(PullRequestQueryLexer.ToBeVerifiedByBuilds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,29 +0,0 @@
|
|||||||
package io.onedev.server.util;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
public class Maps {
|
|
||||||
|
|
||||||
public static <T> Map<T, T> newLinkedHashMap(@SuppressWarnings("unchecked") T...args) {
|
|
||||||
Map<T, T> map = new LinkedHashMap<>();
|
|
||||||
initMap(map, args);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Map<T, T> newHashMap(@SuppressWarnings("unchecked") T...args) {
|
|
||||||
Map<T, T> map = new HashMap<>();
|
|
||||||
initMap(map, args);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> void initMap(Map<T, T> map, @SuppressWarnings("unchecked") T...args) {
|
|
||||||
Preconditions.checkArgument(args.length % 2 == 0, "Arguments should be key/value pairs");
|
|
||||||
for (int i=0; i<args.length/2; i++)
|
|
||||||
map.put(args[i*2], args[i*2+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
package io.onedev.server.util;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public abstract class MatrixRunner<T> {
|
|
||||||
|
|
||||||
private final Map<String, T> paramMap;
|
|
||||||
|
|
||||||
private final Map<String, List<T>> paramMatrix;
|
|
||||||
|
|
||||||
public MatrixRunner(Map<String, List<T>> paramMatrix) {
|
|
||||||
this(new LinkedHashMap<>(), paramMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MatrixRunner(Map<String, T> paramMap, Map<String, List<T>> paramMatrix) {
|
|
||||||
this.paramMap = paramMap;
|
|
||||||
this.paramMatrix = paramMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
if (!paramMatrix.isEmpty()) {
|
|
||||||
Map.Entry<String, List<T>> entry = paramMatrix.entrySet().iterator().next();
|
|
||||||
for (T value: entry.getValue()) {
|
|
||||||
Map<String, T> paramsCopy = new LinkedHashMap<>(paramMap);
|
|
||||||
paramsCopy.put(entry.getKey(), value);
|
|
||||||
Map<String, List<T>> matrixCopy = new LinkedHashMap<>(paramMatrix);
|
|
||||||
matrixCopy.remove(entry.getKey());
|
|
||||||
new MatrixRunner<T>(paramsCopy, matrixCopy) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void run(Map<String, T> paramMap) {
|
|
||||||
MatrixRunner.this.run(paramMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
}.run();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
run(paramMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void run(Map<String, T> paramMap);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
package io.onedev.server.util;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class RangeBuilder {
|
|
||||||
|
|
||||||
private final List<List<Long>> ranges = new ArrayList<>();
|
|
||||||
|
|
||||||
public RangeBuilder(List<Long> discreteValues, List<Long> allValues) {
|
|
||||||
Map<Long, Integer> indexes = new HashMap<>();
|
|
||||||
for (int i=0; i<allValues.size(); i++)
|
|
||||||
indexes.put(allValues.get(i), i);
|
|
||||||
List<Long> continuousValues = new ArrayList<>();
|
|
||||||
int lastIndex = -1;
|
|
||||||
for (Long value: discreteValues) {
|
|
||||||
Integer index = indexes.get(value);
|
|
||||||
if (index != null) {
|
|
||||||
if (lastIndex != -1 && index - lastIndex > 1) {
|
|
||||||
ranges.add(continuousValues);
|
|
||||||
continuousValues = new ArrayList<>();
|
|
||||||
}
|
|
||||||
continuousValues.add(value);
|
|
||||||
lastIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!continuousValues.isEmpty())
|
|
||||||
ranges.add(continuousValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<List<Long>> getRanges() {
|
|
||||||
return ranges;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -143,9 +143,9 @@ public abstract class BuildSidePanel extends Panel {
|
|||||||
protected String load() {
|
protected String load() {
|
||||||
long duration;
|
long duration;
|
||||||
if (getBuild().getRunningDate() != null)
|
if (getBuild().getRunningDate() != null)
|
||||||
duration = getBuild().getRunningDate().getTime() - getBuild().getQueueingDate().getTime();
|
duration = getBuild().getRunningDate().getTime() - getBuild().getPendingDate().getTime();
|
||||||
else
|
else
|
||||||
duration = System.currentTimeMillis() - getBuild().getQueueingDate().getTime();
|
duration = System.currentTimeMillis() - getBuild().getPendingDate().getTime();
|
||||||
if (duration < 0)
|
if (duration < 0)
|
||||||
duration = 0;
|
duration = 0;
|
||||||
return DateUtils.formatDuration(duration);
|
return DateUtils.formatDuration(duration);
|
||||||
@ -156,7 +156,7 @@ public abstract class BuildSidePanel extends Panel {
|
|||||||
@Override
|
@Override
|
||||||
protected void onConfigure() {
|
protected void onConfigure() {
|
||||||
super.onConfigure();
|
super.onConfigure();
|
||||||
setVisible(getBuild().getQueueingDate() != null
|
setVisible(getBuild().getPendingDate() != null
|
||||||
&& (!getBuild().isFinished() || getBuild().getRunningDate() != null));
|
&& (!getBuild().isFinished() || getBuild().getRunningDate() != null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ public class BuildStatusIcon extends GenericPanel<Status> {
|
|||||||
super.onComponentTag(tag);
|
super.onComponentTag(tag);
|
||||||
|
|
||||||
Status status = getModelObject();
|
Status status = getModelObject();
|
||||||
String cssClass = "fa fa-fw build-status build-status-";
|
String cssClass = "fa build-status build-status-";
|
||||||
if (status != null)
|
if (status != null)
|
||||||
cssClass += status.name().toLowerCase();
|
cssClass += status.name().toLowerCase();
|
||||||
else
|
else
|
||||||
@ -87,8 +87,8 @@ public class BuildStatusIcon extends GenericPanel<Status> {
|
|||||||
String title;
|
String title;
|
||||||
if (status == Status.WAITING)
|
if (status == Status.WAITING)
|
||||||
title = "Waiting for completion of dependency builds";
|
title = "Waiting for completion of dependency builds";
|
||||||
else if (status == Status.QUEUEING)
|
else if (status == Status.PENDING)
|
||||||
title = "Queued due to limited capacity";
|
title = "Pending (preparing environments and/or waiting for resources)";
|
||||||
else if (status != null)
|
else if (status != null)
|
||||||
title = StringUtils.capitalize(status.getDisplayName().toLowerCase());
|
title = StringUtils.capitalize(status.getDisplayName().toLowerCase());
|
||||||
else
|
else
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
.build-status-waiting:before {
|
.build-status-waiting:before {
|
||||||
content: "\f28c";
|
content: "\f28c";
|
||||||
}
|
}
|
||||||
.build-status-queueing:before {
|
.build-status-pending:before {
|
||||||
content: "\f192";
|
content: "\f192";
|
||||||
}
|
}
|
||||||
.build-status-none:before {
|
.build-status-none:before {
|
||||||
@ -37,7 +37,7 @@
|
|||||||
.build-status-failed, .build-status-in_error, .build-status-cancelled, .build-status-timed_out {
|
.build-status-failed, .build-status-in_error, .build-status-cancelled, .build-status-timed_out {
|
||||||
color: red !important;
|
color: red !important;
|
||||||
}
|
}
|
||||||
.build-status-running, .build-status-waiting, .build-status-queueing {
|
.build-status-running, .build-status-waiting, .build-status-pending {
|
||||||
color: #D2A906 !important;
|
color: #D2A906 !important;
|
||||||
}
|
}
|
||||||
.build-status-none {
|
.build-status-none {
|
||||||
|
|||||||
@ -76,7 +76,7 @@ public abstract class TaskButton extends AjaxButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
})));
|
})));
|
||||||
if (future != null)
|
if (future != null && !future.isDone())
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
|
|
||||||
new ModalPanel(target) {
|
new ModalPanel(target) {
|
||||||
@ -127,7 +127,7 @@ public abstract class TaskButton extends AjaxButton {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCancel(AjaxRequestTarget target) {
|
protected void onCancel(AjaxRequestTarget target) {
|
||||||
Future<?> future = getTaskFutures().remove(path);
|
Future<?> future = getTaskFutures().remove(path);
|
||||||
if (future != null)
|
if (future != null && !future.isDone())
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,10 +180,14 @@ public abstract class TaskButton extends AjaxButton {
|
|||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
for (Iterator<Map.Entry<String, TaskFuture>> it = taskFutures.entrySet().iterator(); it.hasNext();) {
|
for (Iterator<Map.Entry<String, TaskFuture>> it = taskFutures.entrySet().iterator(); it.hasNext();) {
|
||||||
if (it.next().getValue().isExpired())
|
TaskFuture taskFuture = it.next().getValue();
|
||||||
|
if (taskFuture.isTimedout()) {
|
||||||
|
if (!taskFuture.isDone())
|
||||||
|
taskFuture.cancel(true);
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduleBuilder<?> getScheduleBuilder() {
|
public ScheduleBuilder<?> getScheduleBuilder() {
|
||||||
@ -217,7 +221,7 @@ public abstract class TaskButton extends AjaxButton {
|
|||||||
return wrapped.isDone();
|
return wrapped.isDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExpired() {
|
public boolean isTimedout() {
|
||||||
return timestamp.before(new DateTime().minusHours(1).toDate());
|
return timestamp.before(new DateTime().minusHours(1).toDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -306,7 +306,7 @@ public abstract class BuildDetailPage extends ProjectPage implements InputContex
|
|||||||
case SUCCESSFUL:
|
case SUCCESSFUL:
|
||||||
return "alert-success";
|
return "alert-success";
|
||||||
case WAITING:
|
case WAITING:
|
||||||
case QUEUEING:
|
case PENDING:
|
||||||
case RUNNING:
|
case RUNNING:
|
||||||
return "alert-warning";
|
return "alert-warning";
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -13,6 +13,8 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import io.onedev.commons.utils.MatrixRunner;
|
||||||
|
|
||||||
public class MatrixRunnerTest {
|
public class MatrixRunnerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import io.onedev.commons.utils.RangeBuilder;
|
||||||
|
|
||||||
public class RangeBuilderTest {
|
public class RangeBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import java.io.Serializable;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -24,18 +23,17 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import io.onedev.commons.utils.ExceptionUtils;
|
||||||
import io.onedev.commons.utils.FileUtils;
|
import io.onedev.commons.utils.FileUtils;
|
||||||
|
import io.onedev.commons.utils.Maps;
|
||||||
import io.onedev.commons.utils.StringUtils;
|
import io.onedev.commons.utils.StringUtils;
|
||||||
import io.onedev.commons.utils.command.Commandline;
|
import io.onedev.commons.utils.command.Commandline;
|
||||||
import io.onedev.commons.utils.command.ExecuteResult;
|
import io.onedev.commons.utils.command.ExecuteResult;
|
||||||
import io.onedev.commons.utils.command.LineConsumer;
|
import io.onedev.commons.utils.command.LineConsumer;
|
||||||
import io.onedev.server.OneException;
|
import io.onedev.server.OneException;
|
||||||
import io.onedev.server.ci.job.cache.JobCache;
|
import io.onedev.server.model.support.JobExecutionContext;
|
||||||
import io.onedev.server.model.support.JobExecutor;
|
import io.onedev.server.model.support.JobExecutor;
|
||||||
import io.onedev.server.model.support.SourceSnapshot;
|
|
||||||
import io.onedev.server.plugin.kubernetes.KubernetesExecutor.TestData;
|
import io.onedev.server.plugin.kubernetes.KubernetesExecutor.TestData;
|
||||||
import io.onedev.server.util.Maps;
|
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
|
||||||
import io.onedev.server.web.editable.annotation.Editable;
|
import io.onedev.server.web.editable.annotation.Editable;
|
||||||
import io.onedev.server.web.editable.annotation.OmitName;
|
import io.onedev.server.web.editable.annotation.OmitName;
|
||||||
import io.onedev.server.web.util.Testable;
|
import io.onedev.server.web.util.Testable;
|
||||||
@ -127,9 +125,7 @@ public class KubernetesExecutor extends JobExecutor implements Testable<TestData
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String environment, File workspace, Map<String, String> envVars,
|
public void execute(JobExecutionContext context) {
|
||||||
List<String> commands, SourceSnapshot snapshot, Collection<JobCache> caches,
|
|
||||||
PatternSet collectFiles, Logger logger) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -392,7 +388,7 @@ public class KubernetesExecutor extends JobExecutor implements Testable<TestData
|
|||||||
|
|
||||||
throw new OneException("Unexpected end of pod event watching");
|
throw new OneException("Unexpected end of pod event watching");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (e.getCause() instanceof InterruptedException) {
|
if (ExceptionUtils.find(e, InterruptedException.class) != null) {
|
||||||
if (podStartedRef.get()) {
|
if (podStartedRef.get()) {
|
||||||
kubectl = newKubeCtl();
|
kubectl = newKubeCtl();
|
||||||
kubectl.addArgs("logs", podName, "-n", getNamespace(), "--follow");
|
kubectl.addArgs("logs", podName, "-n", getNamespace(), "--follow");
|
||||||
@ -420,6 +416,7 @@ public class KubernetesExecutor extends JobExecutor implements Testable<TestData
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (InterruptedException e2) {
|
} catch (InterruptedException e2) {
|
||||||
|
throw new RuntimeException(e2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.checkReturnCode();
|
result.checkReturnCode();
|
||||||
|
|||||||
@ -32,16 +32,15 @@ import io.onedev.commons.utils.StringUtils;
|
|||||||
import io.onedev.commons.utils.command.Commandline;
|
import io.onedev.commons.utils.command.Commandline;
|
||||||
import io.onedev.commons.utils.command.LineConsumer;
|
import io.onedev.commons.utils.command.LineConsumer;
|
||||||
import io.onedev.commons.utils.command.ProcessKiller;
|
import io.onedev.commons.utils.command.ProcessKiller;
|
||||||
import io.onedev.commons.utils.concurrent.ConstrainedRunner;
|
import io.onedev.commons.utils.concurrent.CapacityRunner;
|
||||||
import io.onedev.server.ci.job.cache.CacheAllocation;
|
import io.onedev.server.ci.job.cache.CacheAllocation;
|
||||||
import io.onedev.server.ci.job.cache.CacheCallable;
|
import io.onedev.server.ci.job.cache.CacheCallable;
|
||||||
import io.onedev.server.ci.job.cache.CacheRunner;
|
import io.onedev.server.ci.job.cache.CacheRunner;
|
||||||
import io.onedev.server.ci.job.cache.JobCache;
|
import io.onedev.server.ci.job.cache.JobCache;
|
||||||
|
import io.onedev.server.model.support.JobExecutionContext;
|
||||||
import io.onedev.server.model.support.JobExecutor;
|
import io.onedev.server.model.support.JobExecutor;
|
||||||
import io.onedev.server.model.support.SourceSnapshot;
|
|
||||||
import io.onedev.server.plugin.serverdocker.ServerDockerExecutor.TestData;
|
import io.onedev.server.plugin.serverdocker.ServerDockerExecutor.TestData;
|
||||||
import io.onedev.server.util.OneContext;
|
import io.onedev.server.util.OneContext;
|
||||||
import io.onedev.server.util.patternset.PatternSet;
|
|
||||||
import io.onedev.server.util.validation.Validatable;
|
import io.onedev.server.util.validation.Validatable;
|
||||||
import io.onedev.server.util.validation.annotation.ClassValidating;
|
import io.onedev.server.util.validation.annotation.ClassValidating;
|
||||||
import io.onedev.server.web.editable.annotation.Editable;
|
import io.onedev.server.web.editable.annotation.Editable;
|
||||||
@ -70,7 +69,7 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
|
|
||||||
private List<RegistryLogin> registryLogins = new ArrayList<>();
|
private List<RegistryLogin> registryLogins = new ArrayList<>();
|
||||||
|
|
||||||
private transient ConstrainedRunner constrainedRunner;
|
private transient CapacityRunner capacityRunner;
|
||||||
|
|
||||||
@Editable(order=20000, group="More Settings", description="Optionally specify docker executable, for instance <i>/usr/local/bin/docker</i>. "
|
@Editable(order=20000, group="More Settings", description="Optionally specify docker executable, for instance <i>/usr/local/bin/docker</i>. "
|
||||||
+ "Leave empty to use docker executable in PATH")
|
+ "Leave empty to use docker executable in PATH")
|
||||||
@ -149,15 +148,10 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized ConstrainedRunner getConstrainedRunner() {
|
private synchronized CapacityRunner getCapacityRunner() {
|
||||||
if (constrainedRunner == null)
|
if (capacityRunner == null)
|
||||||
constrainedRunner = new ConstrainedRunner(capacity);
|
capacityRunner = new CapacityRunner(capacity);
|
||||||
return constrainedRunner;
|
return capacityRunner;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasCapacity() {
|
|
||||||
return getConstrainedRunner().hasCapacity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getCacheHome() {
|
private File getCacheHome() {
|
||||||
@ -165,33 +159,33 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String environment, File workspace, Map<String, String> envVars,
|
public void execute(JobExecutionContext context) {
|
||||||
List<String> commands, SourceSnapshot snapshot, Collection<JobCache> caches,
|
getCapacityRunner().call(new Callable<Void>() {
|
||||||
PatternSet collectFiles, Logger logger) {
|
|
||||||
getConstrainedRunner().call(new Callable<Void>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void call() {
|
public Void call() {
|
||||||
return new CacheRunner(getCacheHome(), caches).call(new CacheCallable<Void>() {
|
return new CacheRunner(getCacheHome(), context.getCaches()).call(new CacheCallable<Void>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void call(Collection<CacheAllocation> allocations) {
|
public Void call(Collection<CacheAllocation> allocations) {
|
||||||
|
context.notifyJobRunning();
|
||||||
|
|
||||||
login(logger);
|
login(logger);
|
||||||
|
|
||||||
logger.info("Pulling image...") ;
|
logger.info("Pulling image...") ;
|
||||||
Commandline docker = getDocker();
|
Commandline docker = getDocker();
|
||||||
docker.addArgs("pull", environment);
|
docker.addArgs("pull", context.getEnvironment());
|
||||||
docker.execute(newInfoLogger(logger), newErrorLogger(logger)).checkReturnCode();
|
docker.execute(newInfoLogger(logger), newErrorLogger(logger)).checkReturnCode();
|
||||||
|
|
||||||
docker.clearArgs();
|
docker.clearArgs();
|
||||||
String jobInstance = UUID.randomUUID().toString();
|
String jobInstance = UUID.randomUUID().toString();
|
||||||
docker.addArgs("run", "--rm", "--name", jobInstance);
|
docker.addArgs("run", "--rm", "--name", jobInstance);
|
||||||
for (Map.Entry<String, String> entry: envVars.entrySet())
|
for (Map.Entry<String, String> entry: context.getEnvVars().entrySet())
|
||||||
docker.addArgs("--env", entry.getKey() + "=" + entry.getValue());
|
docker.addArgs("--env", entry.getKey() + "=" + entry.getValue());
|
||||||
if (getRunOptions() != null)
|
if (getRunOptions() != null)
|
||||||
docker.addArgs(StringUtils.parseQuoteTokens(getRunOptions()));
|
docker.addArgs(StringUtils.parseQuoteTokens(getRunOptions()));
|
||||||
|
|
||||||
String imageOS = getImageOS(logger, environment);
|
String imageOS = getImageOS(logger, context.getEnvironment());
|
||||||
logger.info("Detected image OS: " + imageOS);
|
logger.info("Detected image OS: " + imageOS);
|
||||||
|
|
||||||
boolean windows = imageOS.equals("windows");
|
boolean windows = imageOS.equals("windows");
|
||||||
@ -210,16 +204,16 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File effectiveWorkspace = workspaceCache != null? workspaceCache: workspace;
|
File effectiveWorkspace = workspaceCache != null? workspaceCache: context.getWorkspace();
|
||||||
|
|
||||||
if (snapshot != null) {
|
if (context.getSnapshot() != null) {
|
||||||
logger.info("Cloning source code...");
|
logger.info("Cloning source code...");
|
||||||
snapshot.checkout(effectiveWorkspace);
|
context.getSnapshot().checkout(effectiveWorkspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workspaceCache != null) {
|
if (workspaceCache != null) {
|
||||||
try {
|
try {
|
||||||
FileUtils.copyDirectory(workspace, workspaceCache);
|
FileUtils.copyDirectory(context.getWorkspace(), workspaceCache);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@ -235,20 +229,20 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
if (windows) {
|
if (windows) {
|
||||||
File scriptFile = new File(effectiveWorkspace, "onedev-job-commands.bat");
|
File scriptFile = new File(effectiveWorkspace, "onedev-job-commands.bat");
|
||||||
try {
|
try {
|
||||||
FileUtils.writeLines(scriptFile, commands, "\r\n");
|
FileUtils.writeLines(scriptFile, context.getCommands(), "\r\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
docker.addArgs(environment);
|
docker.addArgs(context.getEnvironment());
|
||||||
docker.addArgs("cmd", "/c", dockerWorkspacePath + "\\onedev-job-commands.bat");
|
docker.addArgs("cmd", "/c", dockerWorkspacePath + "\\onedev-job-commands.bat");
|
||||||
} else {
|
} else {
|
||||||
File scriptFile = new File(effectiveWorkspace, "onedev-job-commands.sh");
|
File scriptFile = new File(effectiveWorkspace, "onedev-job-commands.sh");
|
||||||
try {
|
try {
|
||||||
FileUtils.writeLines(scriptFile, commands, "\n");
|
FileUtils.writeLines(scriptFile, context.getCommands(), "\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
docker.addArgs(environment);
|
docker.addArgs(context.getEnvironment());
|
||||||
docker.addArgs("sh", dockerWorkspacePath + "/onedev-job-commands.sh");
|
docker.addArgs("sh", dockerWorkspacePath + "/onedev-job-commands.sh");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,9 +265,9 @@ public class ServerDockerExecutor extends JobExecutor implements Testable<TestDa
|
|||||||
} finally {
|
} finally {
|
||||||
if (workspaceCache != null) {
|
if (workspaceCache != null) {
|
||||||
int baseLen = workspaceCache.getAbsolutePath().length()+1;
|
int baseLen = workspaceCache.getAbsolutePath().length()+1;
|
||||||
for (File file: collectFiles.listFiles(workspaceCache)) {
|
for (File file: context.getCollectFiles().listFiles(workspaceCache)) {
|
||||||
try {
|
try {
|
||||||
FileUtils.copyFile(file, new File(workspace, file.getAbsolutePath().substring(baseLen)));
|
FileUtils.copyFile(file, new File(context.getWorkspace(), file.getAbsolutePath().substring(baseLen)));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user