Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions components/jenkins/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const PLUGIN_VERSION = "pluginVersion";

export default {
PLUGIN_VERSION,
};
79 changes: 75 additions & 4 deletions components/jenkins/jenkins.app.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,82 @@
import {
XMLParser, XMLBuilder,
} from "fast-xml-parser";
import { axios } from "@pipedream/platform";

const parser = new XMLParser({
ignoreAttributes: false,
});

const builder = new XMLBuilder({
ignoreAttributes: false,
suppressUnpairedNode: true,
});

export default {
type: "app",
app: "jenkins",
propDefinitions: {},
propDefinitions: {
jobName: {
type: "string",
label: "Job Name",
description: "The name of the Jenkins job to monitor for status updates.",
async options() {
const { jobs } = await this.getApiInfo();
return jobs.map(({ name }) => name);
},
},
},
methods: {
// this.$auth contains connected account data
authKeys() {
console.log(Object.keys(this.$auth));
getUrl(path) {
return `${this.$auth.api_url}${path}`;
},
getAuth() {
const {
api_token: password,
username,
} = this.$auth;
return {
username,
password,
};
},
async _makeRequest({
$ = this, path, data, headers, ...args
} = {}) {
const hasXmlHeader = headers?.["Content-Type"]?.includes("xml");
let response;

try {
response = await axios($, {
...args,
headers,
url: this.getUrl(path),
auth: this.getAuth(),
data: hasXmlHeader
? data && builder.build(data) || undefined
: data,
});

} catch (error) {
console.log("Error:", error);
throw error;
}

return hasXmlHeader
? parser.parse(response)
: response;
},
post(args = {}) {
return this._makeRequest({
method: "POST",
...args,
});
},
getApiInfo(args = {}) {
return this._makeRequest({
path: "/api/json",
...args,
});
},
},
};
8 changes: 6 additions & 2 deletions components/jenkins/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/jenkins",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream Jenkins Components",
"main": "jenkins.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,9 @@
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3",
"fast-xml-parser": "^4.3.2"
}
}
}
34 changes: 34 additions & 0 deletions components/jenkins/sources/common/events.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export default {
ALL: {
value: "all",
label: "All Events",
},
QUEUED: {
value: "queued",
label: "Job Queued",
},
STARTED: {
value: "started",
label: "Job Started",
},
COMPLETED: {
value: "completed",
label: "Job Completed",
},
FINALIZED: {
value: "finalized",
label: "Job Finalized",
},
FAILED: {
value: "failed",
label: "Job Failed",
},
FAILED_AND_FIRST_SUCCESS: {
value: "failedAndFirstSuccess",
label: "Job Failed and First Success",
},
MANUAL: {
value: "manual",
label: "No Events - Call manually",
},
};
175 changes: 175 additions & 0 deletions components/jenkins/sources/common/webhook.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import { ConfigurationError } from "@pipedream/platform";
import app from "../../jenkins.app.mjs";
import constants from "../../common/constants.mjs";

export default {
props: {
app,
db: "$.service.db",
http: "$.interface.http",
// eslint-disable-next-line pipedream/props-label, pipedream/props-description
info: {
type: "alert",
alertType: "info",
content: "Rmember to install the Jenkins Notification Plugin to use this source. Also make sure to activate and enable it in the job configuration.",
},
jobName: {
propDefinition: [
app,
"jobName",
],
},
},
hooks: {
async deploy() {
const {
listPlugins,
setPluginVersion,
} = this;

const { plugins } = await listPlugins({
params: {
depth: 1,
tree: "plugins[active,enabled,shortName,longName,version]",
},
});
const plugin = plugins.find(({ shortName }) => shortName === "notification");
if (!plugin) {
throw new ConfigurationError("The Jenkins Notification Plugin is not installed. Please install it to use this source.");
}
if (!plugin.active) {
throw new ConfigurationError("The Jenkins Notification Plugin is not active. Please activate it to use this source.");
}
if (!plugin.enabled) {
throw new ConfigurationError("The Jenkins Notification Plugin is not enabled. Please enable it to use this source.");
}

setPluginVersion(plugin.version);
},
async activate() {
const {
http: { endpoint: url },
jobName,
getConfig,
updateConfig,
getEventName,
getPluginVersion,
} = this;

const { project } = await getConfig({
jobName,
});

const { properties } = project;

await updateConfig({
jobName,
data: {
project: {
...project,
properties: {
...properties,
"com.tikal.hudson.plugins.notification.HudsonNotificationProperty": {
"@_plugin": `notification@${getPluginVersion()}`,
"endpoints": {
"com.tikal.hudson.plugins.notification.Endpoint": {
"protocol": "HTTP",
"format": "JSON",
"urlInfo": {
"urlOrId": url,
"urlType": "PUBLIC",
},
"event": getEventName(),
"timeout": 30000,
"loglines": 0,
"buildNotes": "",
"retries": 0,
"branch": ".*",
},
},
},
},
},
},
});
},
async deactivate() {
const {
jobName,
getConfig,
updateConfig,
} = this;

const { project } = await getConfig({
jobName,
});

const {
// eslint-disable-next-line no-unused-vars
"com.tikal.hudson.plugins.notification.HudsonNotificationProperty": notificationProperty,
...properties
} = project.properties;

await updateConfig({
jobName,
data: {
project: {
...project,
properties,
},
},
});
},
},
methods: {
setPluginVersion(value) {
this.db.set(constants.PLUGIN_VERSION, value);
},
getPluginVersion() {
return this.db.get(constants.PLUGIN_VERSION);
},
generateMeta() {
throw new ConfigurationError("generateMeta is not implemented");
},
getEventName() {
throw new ConfigurationError("getEventName is not implemented");
},
processResource(resource) {
this.$emit(resource, this.generateMeta(resource));
},
listPlugins(args = {}) {
return this.app._makeRequest({
debug: true,
path: "/pluginManager/api/json",
...args,
});
},
getConfig({
jobName, ...args
} = {}) {
return this.app._makeRequest({
...args,
debug: true,
path: `/job/${encodeURIComponent(jobName)}/config.xml`,
headers: {
"Content-Type": "text/xml",
},
});
},
updateConfig({
jobName, ...args
} = {}) {
return this.app.post({
...args,
debug: true,
path: `/job/${encodeURIComponent(jobName)}/config.xml`,
headers: {
"Content-Type": "text/xml",
},
});
},
},
async run({ body }) {
this.processResource(body);
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import common from "../common/webhook.mjs";
import events from "../common/events.mjs";

export default {
...common,
key: "jenkins-new-job-status-notification-instant",
name: "New Jenkins Job Status Notification (Instant)",
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).",
version: "0.0.1",
type: "source",
dedupe: "unique",
methods: {
...common.methods,
getEventName() {
return events.ALL.value;
},
generateMeta(resource) {
const {
timestamp: ts,
name,
phase,
} = resource.build;
return {
id: `${name}-${ts}`,
summary: `New Status ${phase}`,
ts,
};
},
},
};
Loading
Loading