Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuelBoerlin committed Oct 21, 2024
0 parents commit c05dccd
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
target

# mvn hpi:run
work

# IntelliJ IDEA project files
*.iml
*.iws
*.ipr
.idea

# Eclipse project files
.settings
.classpath
.project
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Jenkins JCasC Queue Job Plugin

This Jenkins plugin enables queueing jobs from the [JCasC](https://www.jenkins.io/projects/jcasc/) config using [Job DSL](https://plugins.jenkins.io/job-dsl/).
Job DSL on its own can already queue jobs, but since JCasC runs before the Jenkins Queue is initialized any jobs queued during this initialization phase are discarded.
This plugin defers jobs queued by Job DSL during initialization until after Jenkins has fully loaded.

### Usage

To queue a job via JCasC simply use the following example snippet:
```yaml
jobs:
- script: |
queue("my_job")
```
### Development
Starting a development Jenkins instance with this plugin: `mvn hpi:run`

Building the plugin: `mvn package`
70 changes: 70 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.41</version>
<relativePath />
</parent>

<groupId>swiss.dasch.plugins</groupId>
<artifactId>jcasc-queue-job</artifactId>
<version>${revision}</version>
<name>JCasC Queue Job Plugin</name>

<packaging>hpi</packaging>

<properties>
<revision>1.0</revision>

<jenkins.version>2.332.4</jenkins.version>

<java.level>8</java.level>
</properties>

<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>

<dependencyManagement>
<dependencies>
<dependency>
<!-- Pick up common dependencies for the selected LTS line: https://github.com/jenkinsci/bom#usage -->
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.332.x</artifactId>
<version>1451.v15f1fdb_772a_f</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>job-dsl</artifactId>
<version>1.79</version>
</dependency>
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package swiss.dasch.plugins.jcascqueuejob;

import java.util.LinkedHashMap;
import java.util.Map.Entry;

import hudson.Extension;
import hudson.model.BuildableItem;
import hudson.model.Cause;
import hudson.model.Item;
import hudson.model.Queue.QueueDecisionHandler;
import hudson.model.listeners.ItemListener;

@Extension
public class StartupItemListener extends ItemListener {

@Override
public void onLoaded() {
StartupQueueDecisionHandler instance = QueueDecisionHandler.all().get(StartupQueueDecisionHandler.class);

if (instance != null) {
LinkedHashMap<BuildableItem, Cause> items = instance.getAndClearQueuedItems();

for (Entry<BuildableItem, Cause> entry : items.entrySet()) {
BuildableItem item = entry.getKey();
Cause cause = entry.getValue();

item.checkPermission(Item.BUILD);

item.scheduleBuild(cause);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package swiss.dasch.plugins.jcascqueuejob;

import java.util.LinkedHashMap;
import java.util.List;

import javax.annotation.Nullable;

import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

import hudson.Extension;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.Action;
import hudson.model.BuildableItem;
import hudson.model.Cause;
import hudson.model.CauseAction;
import hudson.model.Queue.QueueDecisionHandler;
import hudson.model.Queue.Task;
import hudson.security.ACL;
import jenkins.model.Jenkins;

@Extension
public class StartupQueueDecisionHandler extends QueueDecisionHandler {

private static final String JOB_DSL_CAUSE_CLASS = "javaposse.jobdsl.plugin.JenkinsJobManagement$JobDslCause";

private static boolean isLoading;

@Restricted(NoExternalUse.class)
@Initializer(before = InitMilestone.SYSTEM_CONFIG_LOADED)
public static void onBeforeSystemConfigLoaded() {
isLoading = true;
}

@Restricted(NoExternalUse.class)
@Initializer(after = InitMilestone.JOB_CONFIG_ADAPTED)
public static void onAfterJobConfigAdapted() {
isLoading = false;
}

private LinkedHashMap<BuildableItem, Cause> queuedItems = new LinkedHashMap<>();

public LinkedHashMap<BuildableItem, Cause> getAndClearQueuedItems() {
LinkedHashMap<BuildableItem, Cause> items;

synchronized (this) {
items = this.queuedItems;
this.queuedItems = new LinkedHashMap<>();
}

return items;
}

@Override
public boolean shouldSchedule(Task task, List<Action> actions) {
if (isLoading && Jenkins.getAuthentication2() == ACL.SYSTEM2 && task instanceof BuildableItem) {
Cause cause = getJobDSLCause(actions);
if (cause != null) {
// Task was queued by JobDSL during initialization. Cancel scheduling for
// now and schedule it again later once Jenkins Queue has finished loading.
synchronized (this) {
this.queuedItems.put((BuildableItem) task, cause);
}
return false;
}
}
return true;
}

@Nullable
private Cause getJobDSLCause(List<Action> actions) {
for (Action action : actions) {
if (action instanceof CauseAction) {
CauseAction causeAction = (CauseAction) action;
for (Cause cause : causeAction.getCauses()) {
if (JOB_DSL_CAUSE_CLASS.equals(cause.getClass().getName())) {
return cause;
}
}
}
}
return null;
}

}
4 changes: 4 additions & 0 deletions src/main/resources/index.jelly
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?jelly escape-by-default='true'?>
<div>
JCasC Queue Job Plugin
</div>

0 comments on commit c05dccd

Please sign in to comment.