Skip to content

Commit 23d2606

Browse files
authored
[Components] jenkins - New Jenkins Job Status Notification (Instant) (#16096)
1 parent 0d52798 commit 23d2606

File tree

7 files changed

+366
-64
lines changed

7 files changed

+366
-64
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const PLUGIN_VERSION = "pluginVersion";
2+
3+
export default {
4+
PLUGIN_VERSION,
5+
};

components/jenkins/jenkins.app.mjs

+75-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,82 @@
1+
import {
2+
XMLParser, XMLBuilder,
3+
} from "fast-xml-parser";
4+
import { axios } from "@pipedream/platform";
5+
6+
const parser = new XMLParser({
7+
ignoreAttributes: false,
8+
});
9+
10+
const builder = new XMLBuilder({
11+
ignoreAttributes: false,
12+
suppressUnpairedNode: true,
13+
});
14+
115
export default {
216
type: "app",
317
app: "jenkins",
4-
propDefinitions: {},
18+
propDefinitions: {
19+
jobName: {
20+
type: "string",
21+
label: "Job Name",
22+
description: "The name of the Jenkins job to monitor for status updates.",
23+
async options() {
24+
const { jobs } = await this.getApiInfo();
25+
return jobs.map(({ name }) => name);
26+
},
27+
},
28+
},
529
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
30+
getUrl(path) {
31+
return `${this.$auth.api_url}${path}`;
32+
},
33+
getAuth() {
34+
const {
35+
api_token: password,
36+
username,
37+
} = this.$auth;
38+
return {
39+
username,
40+
password,
41+
};
42+
},
43+
async _makeRequest({
44+
$ = this, path, data, headers, ...args
45+
} = {}) {
46+
const hasXmlHeader = headers?.["Content-Type"]?.includes("xml");
47+
let response;
48+
49+
try {
50+
response = await axios($, {
51+
...args,
52+
headers,
53+
url: this.getUrl(path),
54+
auth: this.getAuth(),
55+
data: hasXmlHeader
56+
? data && builder.build(data) || undefined
57+
: data,
58+
});
59+
60+
} catch (error) {
61+
console.log("Error:", error);
62+
throw error;
63+
}
64+
65+
return hasXmlHeader
66+
? parser.parse(response)
67+
: response;
68+
},
69+
post(args = {}) {
70+
return this._makeRequest({
71+
method: "POST",
72+
...args,
73+
});
74+
},
75+
getApiInfo(args = {}) {
76+
return this._makeRequest({
77+
path: "/api/json",
78+
...args,
79+
});
980
},
1081
},
1182
};

components/jenkins/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/jenkins",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream Jenkins Components",
55
"main": "jenkins.app.mjs",
66
"keywords": [
@@ -11,5 +11,9 @@
1111
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
1212
"publishConfig": {
1313
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.0.3",
17+
"fast-xml-parser": "^4.3.2"
1418
}
15-
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export default {
2+
ALL: {
3+
value: "all",
4+
label: "All Events",
5+
},
6+
QUEUED: {
7+
value: "queued",
8+
label: "Job Queued",
9+
},
10+
STARTED: {
11+
value: "started",
12+
label: "Job Started",
13+
},
14+
COMPLETED: {
15+
value: "completed",
16+
label: "Job Completed",
17+
},
18+
FINALIZED: {
19+
value: "finalized",
20+
label: "Job Finalized",
21+
},
22+
FAILED: {
23+
value: "failed",
24+
label: "Job Failed",
25+
},
26+
FAILED_AND_FIRST_SUCCESS: {
27+
value: "failedAndFirstSuccess",
28+
label: "Job Failed and First Success",
29+
},
30+
MANUAL: {
31+
value: "manual",
32+
label: "No Events - Call manually",
33+
},
34+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { ConfigurationError } from "@pipedream/platform";
2+
import app from "../../jenkins.app.mjs";
3+
import constants from "../../common/constants.mjs";
4+
5+
export default {
6+
props: {
7+
app,
8+
db: "$.service.db",
9+
http: "$.interface.http",
10+
// eslint-disable-next-line pipedream/props-label, pipedream/props-description
11+
info: {
12+
type: "alert",
13+
alertType: "info",
14+
content: "Rmember to install the Jenkins Notification Plugin to use this source. Also make sure to activate and enable it in the job configuration.",
15+
},
16+
jobName: {
17+
propDefinition: [
18+
app,
19+
"jobName",
20+
],
21+
},
22+
},
23+
hooks: {
24+
async deploy() {
25+
const {
26+
listPlugins,
27+
setPluginVersion,
28+
} = this;
29+
30+
const { plugins } = await listPlugins({
31+
params: {
32+
depth: 1,
33+
tree: "plugins[active,enabled,shortName,longName,version]",
34+
},
35+
});
36+
const plugin = plugins.find(({ shortName }) => shortName === "notification");
37+
if (!plugin) {
38+
throw new ConfigurationError("The Jenkins Notification Plugin is not installed. Please install it to use this source.");
39+
}
40+
if (!plugin.active) {
41+
throw new ConfigurationError("The Jenkins Notification Plugin is not active. Please activate it to use this source.");
42+
}
43+
if (!plugin.enabled) {
44+
throw new ConfigurationError("The Jenkins Notification Plugin is not enabled. Please enable it to use this source.");
45+
}
46+
47+
setPluginVersion(plugin.version);
48+
},
49+
async activate() {
50+
const {
51+
http: { endpoint: url },
52+
jobName,
53+
getConfig,
54+
updateConfig,
55+
getEventName,
56+
getPluginVersion,
57+
} = this;
58+
59+
const { project } = await getConfig({
60+
jobName,
61+
});
62+
63+
const { properties } = project;
64+
65+
await updateConfig({
66+
jobName,
67+
data: {
68+
project: {
69+
...project,
70+
properties: {
71+
...properties,
72+
"com.tikal.hudson.plugins.notification.HudsonNotificationProperty": {
73+
"@_plugin": `notification@${getPluginVersion()}`,
74+
"endpoints": {
75+
"com.tikal.hudson.plugins.notification.Endpoint": {
76+
"protocol": "HTTP",
77+
"format": "JSON",
78+
"urlInfo": {
79+
"urlOrId": url,
80+
"urlType": "PUBLIC",
81+
},
82+
"event": getEventName(),
83+
"timeout": 30000,
84+
"loglines": 0,
85+
"buildNotes": "",
86+
"retries": 0,
87+
"branch": ".*",
88+
},
89+
},
90+
},
91+
},
92+
},
93+
},
94+
});
95+
},
96+
async deactivate() {
97+
const {
98+
jobName,
99+
getConfig,
100+
updateConfig,
101+
} = this;
102+
103+
const { project } = await getConfig({
104+
jobName,
105+
});
106+
107+
const {
108+
// eslint-disable-next-line no-unused-vars
109+
"com.tikal.hudson.plugins.notification.HudsonNotificationProperty": notificationProperty,
110+
...properties
111+
} = project.properties;
112+
113+
await updateConfig({
114+
jobName,
115+
data: {
116+
project: {
117+
...project,
118+
properties,
119+
},
120+
},
121+
});
122+
},
123+
},
124+
methods: {
125+
setPluginVersion(value) {
126+
this.db.set(constants.PLUGIN_VERSION, value);
127+
},
128+
getPluginVersion() {
129+
return this.db.get(constants.PLUGIN_VERSION);
130+
},
131+
generateMeta() {
132+
throw new ConfigurationError("generateMeta is not implemented");
133+
},
134+
getEventName() {
135+
throw new ConfigurationError("getEventName is not implemented");
136+
},
137+
processResource(resource) {
138+
this.$emit(resource, this.generateMeta(resource));
139+
},
140+
listPlugins(args = {}) {
141+
return this.app._makeRequest({
142+
debug: true,
143+
path: "/pluginManager/api/json",
144+
...args,
145+
});
146+
},
147+
getConfig({
148+
jobName, ...args
149+
} = {}) {
150+
return this.app._makeRequest({
151+
...args,
152+
debug: true,
153+
path: `/job/${encodeURIComponent(jobName)}/config.xml`,
154+
headers: {
155+
"Content-Type": "text/xml",
156+
},
157+
});
158+
},
159+
updateConfig({
160+
jobName, ...args
161+
} = {}) {
162+
return this.app.post({
163+
...args,
164+
debug: true,
165+
path: `/job/${encodeURIComponent(jobName)}/config.xml`,
166+
headers: {
167+
"Content-Type": "text/xml",
168+
},
169+
});
170+
},
171+
},
172+
async run({ body }) {
173+
this.processResource(body);
174+
},
175+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import common from "../common/webhook.mjs";
2+
import events from "../common/events.mjs";
3+
4+
export default {
5+
...common,
6+
key: "jenkins-new-job-status-notification-instant",
7+
name: "New Jenkins Job Status Notification (Instant)",
8+
description: "Emit new event when a Jenkins job sends a status notification via the notification plugin. [See the documentation](https://github.com/jenkinsci/notification-plugin).",
9+
version: "0.0.1",
10+
type: "source",
11+
dedupe: "unique",
12+
methods: {
13+
...common.methods,
14+
getEventName() {
15+
return events.ALL.value;
16+
},
17+
generateMeta(resource) {
18+
const {
19+
timestamp: ts,
20+
name,
21+
phase,
22+
} = resource.build;
23+
return {
24+
id: `${name}-${ts}`,
25+
summary: `New Status ${phase}`,
26+
ts,
27+
};
28+
},
29+
},
30+
};

0 commit comments

Comments
 (0)