@hexonet/semantic-release-whmcs 4.0.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +7 -7
- package/.github/workflows/release.yml +29 -0
- package/.github/workflows/{pull-request.yml → test.yml} +13 -16
- package/.releaserc.json +1 -5
- package/CONTRIBUTING.md +1 -1
- package/HISTORY.md +81 -62
- package/README.md +5 -5
- package/index.js +36 -30
- package/lib/definitions/errors.js +26 -13
- package/lib/delete-marketplace-version.js +48 -48
- package/lib/get-error.js +6 -6
- package/lib/get-github-releases.js +17 -18
- package/lib/publish.js +10 -13
- package/lib/puppet.js +73 -74
- package/lib/resolve-config.js +5 -6
- package/lib/scrape-marketplace-versions.js +30 -28
- package/lib/set-compatible-versions.js +42 -41
- package/lib/verify.js +14 -11
- package/package.json +35 -31
- package/whmcs.js +81 -53
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -14
- package/.github/workflows/push.yml +0 -79
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/coverage-final.json +0 -11
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/lib/definitions/errors.js.html +0 -136
- package/coverage/lib/definitions/index.html +0 -116
- package/coverage/lib/delete-marketplace-version.js.html +0 -343
- package/coverage/lib/get-error.js.html +0 -106
- package/coverage/lib/get-github-releases.js.html +0 -184
- package/coverage/lib/index.html +0 -236
- package/coverage/lib/publish.js.html +0 -370
- package/coverage/lib/puppet.js.html +0 -424
- package/coverage/lib/resolve-config.js.html +0 -118
- package/coverage/lib/scrape-marketplace-versions.js.html +0 -220
- package/coverage/lib/set-compatible-versions.js.html +0 -298
- package/coverage/lib/verify.js.html +0 -148
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
@@ -1,40 +1,40 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
import puppet from "./puppet.js";
|
2
|
+
import debugConfig from "debug";
|
3
|
+
import { fileURLToPath } from "node:url";
|
4
|
+
const debug = debugConfig("semantic-release:whmcs");
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
5
6
|
/**
|
6
7
|
* A method to publish the module update on whmcs market place
|
7
8
|
*/
|
8
|
-
|
9
|
+
export default async (pluginConfig, context) => {
|
9
10
|
// if (!context.logger) {
|
10
11
|
// context.logger = console;
|
11
12
|
// }
|
12
13
|
|
13
|
-
const sep =
|
14
|
-
const out = `\n${sep}\n${
|
14
|
+
const sep = "+++++++++++++++++++++++++++++++++++++++++++++++++++";
|
15
|
+
const out = `\n${sep}\n${__filename}\n${sep}\n`;
|
15
16
|
|
16
|
-
const { version } = context
|
17
|
+
const { version } = context;
|
17
18
|
if (!version || !version.length) {
|
18
|
-
debug(`${out}Deleting product version failed. No input data available.`)
|
19
|
-
return false
|
19
|
+
debug(`${out}Deleting product version failed. No input data available.`);
|
20
|
+
return false;
|
20
21
|
}
|
21
22
|
|
22
|
-
debug(`${out}Delete Version: ${version}`)
|
23
|
+
debug(`${out}Delete Version: ${version}`);
|
23
24
|
|
24
|
-
const püppi = await puppet(context)
|
25
|
-
const result = await püppi.login()
|
25
|
+
const püppi = await puppet(context);
|
26
|
+
const result = await püppi.login();
|
26
27
|
if (!result) {
|
27
|
-
return result
|
28
|
+
return result;
|
28
29
|
}
|
29
|
-
const { page, navOpts, gotoOpts, selectorOpts, productid, urlbase } =
|
30
|
-
püppi.config
|
30
|
+
const { page, navOpts, gotoOpts, selectorOpts, productid, urlbase } = püppi.config;
|
31
31
|
|
32
32
|
// strip markdown links from notes as not allowed to keep
|
33
33
|
try {
|
34
34
|
// navigate to product administration
|
35
|
-
const url = `${urlbase}/product/${productid}/edit#versions
|
36
|
-
await page.goto(url, gotoOpts)
|
37
|
-
debug(
|
35
|
+
const url = `${urlbase}/product/${productid}/edit#versions`;
|
36
|
+
await page.goto(url, gotoOpts);
|
37
|
+
debug("product page loaded at %s", url);
|
38
38
|
// open versions tab (instead of doing it via url)
|
39
39
|
// let selector = '#nav-tabs li a[href="#versions"]';
|
40
40
|
// await page.waitForSelector(selector, selectorOpts);
|
@@ -44,43 +44,43 @@ module.exports = async (pluginConfig, context) => {
|
|
44
44
|
// xpath improvements / changes with v16.1.0
|
45
45
|
// -> https://github.com/puppeteer/puppeteer/pull/8730
|
46
46
|
// https://github.com/puppeteer/puppeteer/blob/d1681ec06b7c3db4b51c20b17b3339f852efbd4d/test/src/queryhandler.spec.ts
|
47
|
-
let elements = []
|
47
|
+
let elements = [];
|
48
48
|
do {
|
49
|
-
const xpath = `xpath/.//td[contains(., "Version ${version}")]/following-sibling::td/a[contains(@class, "btn-styled-red")]
|
50
|
-
await page.waitForSelector(xpath, selectorOpts)
|
51
|
-
debug(
|
52
|
-
const nav = page.waitForNavigation(navOpts)
|
53
|
-
elements = await page.$$(xpath)
|
49
|
+
const xpath = `xpath/.//td[contains(., "Version ${version}")]/following-sibling::td/a[contains(@class, "btn-styled-red")]`;
|
50
|
+
await page.waitForSelector(xpath, selectorOpts);
|
51
|
+
debug("XPath found.");
|
52
|
+
const nav = page.waitForNavigation(navOpts);
|
53
|
+
elements = await page.$$(xpath);
|
54
54
|
if (elements.length) {
|
55
|
-
debug(
|
56
|
-
await elements[0].hover()
|
57
|
-
await elements[0].click()
|
58
|
-
debug(
|
59
|
-
await nav
|
60
|
-
debug(
|
55
|
+
debug("Delete Button - click.");
|
56
|
+
await elements[0].hover();
|
57
|
+
await elements[0].click();
|
58
|
+
debug("Delete Button - clicked.");
|
59
|
+
await nav;
|
60
|
+
debug("Navigation finished.");
|
61
61
|
// confirm deletion
|
62
|
-
const selector =
|
63
|
-
await page.waitForSelector(selector, selectorOpts)
|
64
|
-
debug(
|
65
|
-
debug(
|
66
|
-
await page.clickAndNavigate(selector)
|
67
|
-
debug(
|
68
|
-
await nav
|
69
|
-
debug(
|
62
|
+
const selector = "button.btn-styled-red";
|
63
|
+
await page.waitForSelector(selector, selectorOpts);
|
64
|
+
debug("deletion confirmation button available");
|
65
|
+
debug("click confirmation button");
|
66
|
+
await page.clickAndNavigate(selector);
|
67
|
+
debug("clicked confirmation button");
|
68
|
+
await nav;
|
69
|
+
debug("WHMCS Marketplace deleting product version succeeded.");
|
70
70
|
}
|
71
|
-
} while (elements.length)
|
71
|
+
} while (elements.length);
|
72
72
|
} catch (error) {
|
73
73
|
// while loop and having all versions deleted
|
74
74
|
if (!/waiting for selector `.\/\//i.test(error.message)) {
|
75
|
-
debug(
|
76
|
-
await page.browser().close()
|
77
|
-
return false
|
75
|
+
debug("Deleting product version failed.", error.message);
|
76
|
+
await page.browser().close();
|
77
|
+
return false;
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
-
await page.browser().close()
|
81
|
+
await page.browser().close();
|
82
82
|
return {
|
83
|
-
name:
|
84
|
-
url: `${urlbase}/product/${productid}
|
85
|
-
}
|
86
|
-
}
|
83
|
+
name: "WHMCS Marketplace Product Version",
|
84
|
+
url: `${urlbase}/product/${productid}`,
|
85
|
+
};
|
86
|
+
};
|
package/lib/get-error.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
import SemanticReleaseError from "@semantic-release/error";
|
2
|
+
import * as ERROR_DEFINITIONS from "./definitions/errors.js";
|
3
3
|
|
4
|
-
|
5
|
-
const { message, details } = ERROR_DEFINITIONS[code]()
|
6
|
-
return new SemanticReleaseError(message, code, details)
|
7
|
-
}
|
4
|
+
export default (code) => {
|
5
|
+
const { message, details } = ERROR_DEFINITIONS[code]();
|
6
|
+
return new SemanticReleaseError(message, code, details);
|
7
|
+
};
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import resolveConfig from "./resolve-config.js";
|
2
|
+
import GitHub from "github-api";
|
3
|
+
import debugConfig from "debug";
|
4
|
+
const debug = debugConfig("semantic-release:whmcs");
|
4
5
|
|
5
6
|
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
6
7
|
// Rate limits to 60 requests/hour per IP for anonymous requests, 5000/hour with authentication
|
@@ -8,26 +9,24 @@ const GitHub = require('github-api')
|
|
8
9
|
/**
|
9
10
|
* A method to get releases from github repository
|
10
11
|
*/
|
11
|
-
|
12
|
-
debug(
|
12
|
+
export default async (pluginConfig, context) => {
|
13
|
+
debug("Getting releases from GitHub");
|
13
14
|
|
14
|
-
const { ghrepo, ghtoken } = resolveConfig(context)
|
15
|
+
const { ghrepo, ghtoken } = resolveConfig(context);
|
15
16
|
|
16
17
|
const gh = new GitHub({
|
17
|
-
token: ghtoken
|
18
|
-
})
|
18
|
+
token: ghtoken,
|
19
|
+
});
|
19
20
|
if (ghrepo) {
|
20
21
|
// optional by default false
|
21
|
-
const repo = ghrepo.split(
|
22
|
-
const githubReleases = await gh.getRepo(repo[0], repo[1]).listReleases()
|
22
|
+
const repo = ghrepo.split("/");
|
23
|
+
const githubReleases = await gh.getRepo(repo[0], repo[1]).listReleases();
|
23
24
|
if (githubReleases.status === 200) {
|
24
|
-
githubReleases.data.forEach((r) =>
|
25
|
-
|
26
|
-
|
27
|
-
githubReleases.data.reverse()
|
28
|
-
return githubReleases.data
|
25
|
+
githubReleases.data.forEach((r) => debug(`Detected GitHub release ${r.name.substring(1)}`));
|
26
|
+
githubReleases.data.reverse();
|
27
|
+
return githubReleases.data;
|
29
28
|
}
|
30
|
-
debug(
|
29
|
+
debug("Failed to get releases from GitHub");
|
31
30
|
}
|
32
|
-
return false
|
33
|
-
}
|
31
|
+
return false;
|
32
|
+
};
|
package/lib/publish.js
CHANGED
@@ -1,22 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
import puppet from "./puppet.js";
|
2
|
+
import setCompatibleVersions from "./set-compatible-versions.js";
|
3
|
+
import debugConfig from "debug";
|
4
|
+
import { fileURLToPath } from "node:url";
|
5
|
+
const debug = debugConfig("semantic-release:whmcs");
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
5
7
|
|
6
8
|
/**
|
7
9
|
* A method to publish the module update on whmcs market place
|
8
10
|
*/
|
9
|
-
|
11
|
+
export default async (pluginConfig, context) => {
|
10
12
|
const sep = "+++++++++++++++++++++++++++++++++++++++++++++++++++";
|
11
|
-
const out = `\n${sep}\n${
|
12
|
-
|
13
|
+
const out = `\n${sep}\n${__filename}\n${sep}\n`;
|
13
14
|
const {
|
14
15
|
nextRelease: { notes, version, releaseDate },
|
15
16
|
} = context;
|
16
17
|
if (!notes || !notes.length || !version || !version.length) {
|
17
|
-
debug(
|
18
|
-
`${out}Publishing new product version failed. No input data available.`
|
19
|
-
);
|
18
|
+
debug(`${out}Publishing new product version failed. No input data available.`);
|
20
19
|
return false;
|
21
20
|
}
|
22
21
|
// strip markdown links from notes as not allowed to keep (taken from remove-markdown and cleaned up)
|
@@ -76,9 +75,7 @@ module.exports = async (pluginConfig, context) => {
|
|
76
75
|
);
|
77
76
|
debug("form input for description finished.");
|
78
77
|
|
79
|
-
await page.clickAndNavigate(
|
80
|
-
'div.listing-edit-container form button[type="submit"]'
|
81
|
-
);
|
78
|
+
await page.clickAndNavigate('div.listing-edit-container form button[type="submit"]');
|
82
79
|
await setCompatibleVersions(pluginConfig, context);
|
83
80
|
} catch (error) {
|
84
81
|
debug("Publishing new product version failed.", error.message);
|
package/lib/puppet.js
CHANGED
@@ -1,113 +1,112 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
import puppeteer from "puppeteer";
|
2
|
+
import resolveConfig from "./resolve-config.js";
|
3
|
+
import debugConfig from "debug";
|
4
|
+
const debug = debugConfig("semantic-release:whmcs");
|
5
|
+
export default async (context) => {
|
6
|
+
let config;
|
6
7
|
const cfg = {
|
7
|
-
urlbase:
|
8
|
+
urlbase: "https://marketplace.whmcs.com",
|
8
9
|
...resolveConfig(context),
|
9
10
|
// logger: logger,
|
10
11
|
gotoOpts: {
|
11
|
-
waitUntil: [
|
12
|
-
timeout: 240000
|
12
|
+
waitUntil: ["load", "domcontentloaded"],
|
13
|
+
timeout: 240000,
|
13
14
|
},
|
14
15
|
navOpts: {
|
15
|
-
waitUntil: [
|
16
|
-
timeout: 240000
|
16
|
+
waitUntil: ["networkidle0"],
|
17
|
+
timeout: 240000,
|
17
18
|
},
|
18
19
|
selectorOpts: {
|
19
|
-
timeout:
|
20
|
+
timeout: 20000,
|
20
21
|
},
|
21
|
-
logger: context.logger
|
22
|
-
}
|
22
|
+
logger: context.logger,
|
23
|
+
};
|
23
24
|
|
24
25
|
const browser = await puppeteer.launch({
|
25
|
-
headless: cfg.headless ===
|
26
|
+
headless: cfg.headless === "1",
|
26
27
|
defaultViewport: null, // automatically full-sized
|
27
28
|
args: [
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
]
|
38
|
-
})
|
39
|
-
const { logger } = cfg
|
40
|
-
const [page] = await browser.pages()
|
29
|
+
"--disable-gpu",
|
30
|
+
"--incognito",
|
31
|
+
"--start-maximized",
|
32
|
+
"--no-sandbox",
|
33
|
+
"--disable-setuid-sandbox",
|
34
|
+
"--disable-infobars",
|
35
|
+
"--ignore-certifcate-errors",
|
36
|
+
"--ignore-certifcate-errors-spki-list",
|
37
|
+
"--ignoreHTTPSErrors=true",
|
38
|
+
],
|
39
|
+
});
|
40
|
+
const { logger } = cfg;
|
41
|
+
const [page] = await browser.pages();
|
41
42
|
await page.setExtraHTTPHeaders({
|
42
|
-
|
43
|
-
})
|
43
|
+
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
|
44
|
+
});
|
44
45
|
await page.setUserAgent(
|
45
|
-
|
46
|
-
)
|
47
|
-
await page.setJavaScriptEnabled(true)
|
46
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
|
47
|
+
);
|
48
|
+
await page.setJavaScriptEnabled(true);
|
48
49
|
|
49
50
|
if (cfg.debug) {
|
50
|
-
page.on(
|
51
|
+
page.on("console", (msg) => {
|
51
52
|
for (let i = 0; i < msg.args().length; i++) {
|
52
|
-
logger.log(`${i}: ${msg.args()[i]}`)
|
53
|
+
logger.log(`${i}: ${msg.args()[i]}`);
|
53
54
|
}
|
54
|
-
})
|
55
|
+
});
|
55
56
|
}
|
56
57
|
|
57
58
|
page.clickAndNavigate = async (selector) => {
|
58
|
-
const { page, navOpts } =
|
59
|
-
const nav = page.waitForNavigation(navOpts)
|
60
|
-
await page.hover(selector)
|
61
|
-
await page.click(selector)
|
62
|
-
await nav
|
63
|
-
}
|
59
|
+
const { page, navOpts } = config;
|
60
|
+
const nav = page.waitForNavigation(navOpts);
|
61
|
+
await page.hover(selector);
|
62
|
+
await page.click(selector);
|
63
|
+
await nav;
|
64
|
+
};
|
64
65
|
|
65
66
|
page.enterAndType = async (selector, value) => {
|
66
|
-
const { page, selectorOpts } =
|
67
|
-
await page.waitForSelector(selector, selectorOpts)
|
68
|
-
await page.type(selector, value)
|
69
|
-
}
|
67
|
+
const { page, selectorOpts } = config;
|
68
|
+
await page.waitForSelector(selector, selectorOpts);
|
69
|
+
await page.type(selector, value);
|
70
|
+
};
|
70
71
|
|
71
|
-
|
72
|
-
const { page, login, password, productid, gotoOpts, urlbase } =
|
73
|
-
const selector = 'div.login-leftcol form button[type="submit"]'
|
72
|
+
async function login() {
|
73
|
+
const { page, login, password, productid, gotoOpts, urlbase } = config;
|
74
|
+
const selector = 'div.login-leftcol form button[type="submit"]';
|
74
75
|
// do login
|
75
76
|
try {
|
76
|
-
await page.goto(`${urlbase}/user/login`, gotoOpts)
|
77
|
-
debug(
|
78
|
-
await page.enterAndType(
|
79
|
-
await page.enterAndType(
|
80
|
-
debug(
|
81
|
-
await page.clickAndNavigate(selector)
|
82
|
-
debug(
|
77
|
+
await page.goto(`${urlbase}/user/login`, gotoOpts);
|
78
|
+
debug("login form loaded at %s", `${urlbase}/user/login`);
|
79
|
+
await page.enterAndType("#email", login);
|
80
|
+
await page.enterAndType("#password", password);
|
81
|
+
debug("WHMCS Marketplace credentials entered");
|
82
|
+
await page.clickAndNavigate(selector);
|
83
|
+
debug("WHMCS Marketplace login form submitted.");
|
83
84
|
} catch (error) {
|
84
|
-
debug(
|
85
|
-
|
86
|
-
|
87
|
-
)
|
88
|
-
await page.browser().close()
|
89
|
-
return false
|
85
|
+
debug("WHMCS Marketplace login failed or Product ID missing", error.message);
|
86
|
+
await page.browser().close();
|
87
|
+
return false;
|
90
88
|
}
|
91
|
-
|
89
|
+
|
90
|
+
debug("WHMCS Marketplace login succeeded.");
|
92
91
|
|
93
92
|
// access MP Product ID
|
94
|
-
let tmp = productid
|
93
|
+
let tmp = productid;
|
95
94
|
if (!tmp || !/^[0-9]+$/.test(productid) || !parseInt(productid, 10)) {
|
96
|
-
debug(
|
97
|
-
await page.browser().close()
|
98
|
-
return false
|
95
|
+
debug("No or invalid WHMCS Marketplace Product ID provided.");
|
96
|
+
await page.browser().close();
|
97
|
+
return false;
|
99
98
|
}
|
100
99
|
|
101
|
-
tmp = tmp.replace(/(.)/g,
|
102
|
-
debug(`WHMCS Marketplace Product ID: ${tmp}`)
|
100
|
+
tmp = tmp.replace(/(.)/g, "$&\u200E");
|
101
|
+
debug(`WHMCS Marketplace Product ID: ${tmp}`);
|
103
102
|
|
104
|
-
return true
|
103
|
+
return true;
|
105
104
|
}
|
106
105
|
|
107
|
-
|
106
|
+
config = {
|
108
107
|
...cfg,
|
109
|
-
page
|
110
|
-
}
|
108
|
+
page,
|
109
|
+
};
|
111
110
|
|
112
|
-
return
|
113
|
-
}
|
111
|
+
return { config, login };
|
112
|
+
};
|
package/lib/resolve-config.js
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
|
1
|
+
export default ({ env }) => ({
|
2
2
|
login: env.WHMCSMP_LOGIN || false,
|
3
3
|
password: env.WHMCSMP_PASSWORD || false,
|
4
4
|
productid: env.WHMCSMP_PRODUCTID || false,
|
5
|
-
minversion: env.WHMCSMP_MINVERSION ||
|
5
|
+
minversion: env.WHMCSMP_MINVERSION || "7.10",
|
6
6
|
ghtoken: env.GH_TOKEN || env.GITHUB_TOKEN || false,
|
7
7
|
ghrepo: env.GH_REPO || env.GITHUB_REPO || false,
|
8
|
-
headless: env.PUPPETEER_HEADLESS ||
|
9
|
-
debug:
|
10
|
-
|
11
|
-
})
|
8
|
+
headless: env.PUPPETEER_HEADLESS || "1",
|
9
|
+
debug: (env.DEBUG && /^semantic-release:(\*|whmcs)$/.test(env.DEBUG)) || false,
|
10
|
+
});
|
@@ -1,45 +1,47 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import puppet from "./puppet.js";
|
2
|
+
import debugConfig from "debug";
|
3
|
+
import { fileURLToPath } from "node:url";
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
5
|
+
const debug = debugConfig("semantic-release:whmcs");
|
4
6
|
|
5
7
|
/**
|
6
8
|
* A method to publish the module update on whmcs market place
|
7
9
|
*/
|
8
|
-
|
9
|
-
const sep =
|
10
|
-
const out = `\n${sep}\n${
|
10
|
+
export default async (pluginConfig, context) => {
|
11
|
+
const sep = "+++++++++++++++++++++++++++++++++++++++++++++++++++";
|
12
|
+
const out = `\n${sep}\n${__filename}\n${sep}\n`;
|
11
13
|
|
12
|
-
const püppi = await puppet(context)
|
13
|
-
const result = await püppi.login()
|
14
|
+
const püppi = await puppet(context);
|
15
|
+
const result = await püppi.login();
|
14
16
|
if (!result) {
|
15
|
-
return result
|
17
|
+
return result;
|
16
18
|
}
|
17
|
-
const { page, gotoOpts, selectorOpts, productid, urlbase } = püppi.config
|
19
|
+
const { page, gotoOpts, selectorOpts, productid, urlbase } = püppi.config;
|
18
20
|
|
19
|
-
let marketplaceVersions = []
|
21
|
+
let marketplaceVersions = [];
|
20
22
|
try {
|
21
23
|
// scrap versions from WHMCS marketplace
|
22
|
-
const url = `${urlbase}/product/${productid}/edit#versions
|
23
|
-
await page.goto(url, gotoOpts)
|
24
|
-
debug(`${out}product page loaded at %s`, url)
|
25
|
-
const selector =
|
26
|
-
await page.waitForSelector(selector, selectorOpts)
|
27
|
-
debug(
|
24
|
+
const url = `${urlbase}/product/${productid}/edit#versions`;
|
25
|
+
await page.goto(url, gotoOpts);
|
26
|
+
debug(`${out}product page loaded at %s`, url);
|
27
|
+
const selector = "div#versions tr strong";
|
28
|
+
await page.waitForSelector(selector, selectorOpts);
|
29
|
+
debug("product version table found");
|
28
30
|
/* istanbul ignore next */
|
29
31
|
marketplaceVersions = await page.$$eval(selector, (tds) =>
|
30
32
|
tds.map((td) => {
|
31
|
-
return td.innerText.substring(8)
|
33
|
+
return td.innerText.substring(8);
|
32
34
|
})
|
33
|
-
)
|
34
|
-
marketplaceVersions.reverse()
|
35
|
-
marketplaceVersions.forEach((v) => debug(`Detected WHMCS version ${v}`))
|
35
|
+
);
|
36
|
+
marketplaceVersions.reverse();
|
37
|
+
marketplaceVersions.forEach((v) => debug(`Detected WHMCS version ${v}`));
|
36
38
|
} catch (error) {
|
37
|
-
debug(
|
38
|
-
await page.browser().close()
|
39
|
-
return false
|
39
|
+
debug("Publishing new product version failed.", error.message);
|
40
|
+
await page.browser().close();
|
41
|
+
return false;
|
40
42
|
}
|
41
43
|
|
42
|
-
debug(
|
43
|
-
await page.browser().close()
|
44
|
-
return marketplaceVersions
|
45
|
-
}
|
44
|
+
debug("Publishing new product version succeeded.");
|
45
|
+
await page.browser().close();
|
46
|
+
return marketplaceVersions;
|
47
|
+
};
|
@@ -1,71 +1,72 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import puppet from "./puppet.js";
|
2
|
+
import debugConfig from "debug";
|
3
|
+
import { fileURLToPath } from "node:url";
|
4
|
+
const debug = debugConfig("semantic-release:whmcs");
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
4
6
|
|
5
7
|
/**
|
6
8
|
* A method to publish the module update on whmcs market place
|
7
9
|
*/
|
8
|
-
|
9
|
-
const sep =
|
10
|
-
const out = `\n${sep}\n${
|
10
|
+
export default async (pluginConfig, context) => {
|
11
|
+
const sep = "+++++++++++++++++++++++++++++++++++++++++++++++++++";
|
12
|
+
const out = `\n${sep}\n${__filename}\n${sep}\n`;
|
11
13
|
|
12
|
-
const püppi = await puppet(context)
|
13
|
-
const result = await püppi.login()
|
14
|
+
const püppi = await puppet(context);
|
15
|
+
const result = await püppi.login();
|
14
16
|
if (!result) {
|
15
|
-
return result
|
17
|
+
return result;
|
16
18
|
}
|
17
|
-
const { page, gotoOpts, selectorOpts, productid, urlbase, minversion } =
|
18
|
-
püppi.config
|
19
|
+
const { page, gotoOpts, selectorOpts, productid, urlbase, minversion } = püppi.config;
|
19
20
|
|
20
|
-
debug(out)
|
21
|
+
debug(out);
|
21
22
|
try {
|
22
23
|
// scrap versions from WHMCS marketplace
|
23
|
-
const url = `${urlbase}/product/${productid}/edit#compatibility
|
24
|
-
await page.goto(url, gotoOpts)
|
25
|
-
debug(
|
24
|
+
const url = `${urlbase}/product/${productid}/edit#compatibility`;
|
25
|
+
await page.goto(url, gotoOpts);
|
26
|
+
debug("product page loaded at %s", url);
|
26
27
|
|
27
|
-
const selector = 'input[name="versionIds[]"]'
|
28
|
-
const submitSelector = 'div#compatibility button[type="submit"]'
|
29
|
-
await page.waitForSelector(selector, selectorOpts)
|
30
|
-
await page.waitForSelector(submitSelector, selectorOpts)
|
31
|
-
debug(
|
28
|
+
const selector = 'input[name="versionIds[]"]';
|
29
|
+
const submitSelector = 'div#compatibility button[type="submit"]';
|
30
|
+
await page.waitForSelector(selector, selectorOpts);
|
31
|
+
await page.waitForSelector(submitSelector, selectorOpts);
|
32
|
+
debug("compatibility version table found");
|
32
33
|
|
33
|
-
let tmp = minversion
|
34
|
+
let tmp = minversion;
|
34
35
|
if (tmp) {
|
35
|
-
tmp = tmp.replace(/(.)/g,
|
36
|
+
tmp = tmp.replace(/(.)/g, "$&\u200E");
|
36
37
|
}
|
37
|
-
debug(`Minimum required WHMCS version: ${tmp}`)
|
38
|
+
debug(`Minimum required WHMCS version: ${tmp}`);
|
38
39
|
/* istanbul ignore next */
|
39
40
|
await page.$$eval(
|
40
41
|
selector,
|
41
42
|
(checkboxes, minversion) =>
|
42
43
|
checkboxes.forEach(function (c) {
|
43
|
-
const checkParts = c.className.split(
|
44
|
-
const minParts = minversion.split(
|
45
|
-
let check = true
|
44
|
+
const checkParts = c.className.split("-")[0].split("_");
|
45
|
+
const minParts = minversion.split(".");
|
46
|
+
let check = true;
|
46
47
|
for (let i = 0; i < 2; i++) {
|
47
|
-
const a = ~~checkParts[i]
|
48
|
-
const b = ~~minParts[i]
|
48
|
+
const a = ~~checkParts[i];
|
49
|
+
const b = ~~minParts[i];
|
49
50
|
if (a > b) {
|
50
|
-
break
|
51
|
+
break;
|
51
52
|
}
|
52
53
|
if (a < b) {
|
53
|
-
check = false
|
54
|
-
break
|
54
|
+
check = false;
|
55
|
+
break;
|
55
56
|
}
|
56
57
|
}
|
57
|
-
c.checked = check
|
58
|
+
c.checked = check;
|
58
59
|
}),
|
59
60
|
minversion
|
60
|
-
)
|
61
|
-
await page.clickAndNavigate(submitSelector)
|
61
|
+
);
|
62
|
+
await page.clickAndNavigate(submitSelector);
|
62
63
|
} catch (error) {
|
63
|
-
debug(
|
64
|
-
await page.browser().close()
|
65
|
-
return false
|
64
|
+
debug("Updating whmcs compatibility list failed.", error.message);
|
65
|
+
await page.browser().close();
|
66
|
+
return false;
|
66
67
|
}
|
67
68
|
|
68
|
-
debug(
|
69
|
-
await page.browser().close()
|
70
|
-
return true
|
71
|
-
}
|
69
|
+
debug("Updating whmcs compatibility list succeeded.");
|
70
|
+
await page.browser().close();
|
71
|
+
return true;
|
72
|
+
};
|