Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thsmi/sieve.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/gulp
diff options
context:
space:
mode:
authorThomas Schmid <schmid-thomas@gmx.net>2020-05-21 21:04:30 +0300
committerThomas Schmid <schmid-thomas@gmx.net>2020-05-21 21:04:30 +0300
commit06cde679c47ead7e010391c6afd1e4ae96fd5abc (patch)
tree9e7b6b4779ff8ea13e6ddc03e2c83ea9b62389e2 /gulp
parentdd67a979a936253b5ae1f3b94060b2d7f871fa8b (diff)
Package Linux Binary as appimage.
Experiments to package the linux binaries as an appimage. #268
Diffstat (limited to 'gulp')
-rw-r--r--gulp/gulpfile.app.js71
-rw-r--r--gulp/gulpfile.common.https.js160
-rw-r--r--gulp/gulpfile.common.js52
3 files changed, 227 insertions, 56 deletions
diff --git a/gulp/gulpfile.app.js b/gulp/gulpfile.app.js
index 9f71b23a..b906caf0 100644
--- a/gulp/gulpfile.app.js
+++ b/gulp/gulpfile.app.js
@@ -11,11 +11,15 @@
const { src, dest, watch, parallel, series } = require('gulp');
const { existsSync } = require('fs');
-const { readFile } = require('fs').promises;
+const { readFile, chmod } = require('fs').promises;
+
+const util = require('util');
+const exec = util.promisify(require('child_process').exec);
const logger = require('gulplog');
const common = require("./gulpfile.common.js");
+const https = require("./gulpfile.common.https.js");
const path = require('path');
const tar = require('tar');
@@ -42,6 +46,9 @@ const MAC_PLATFORM = "mas";
const RUNTIME_ELECTRON = "electron";
+const APP_IMAGE_RELEASE_URL = "https://api.github.com/repos/AppImage/AppImageKit/releases/latest";
+const APP_IMAGE_TOOL_NAME = "appimagetool-x86_64.AppImage";
+
/**
* Extracts a tar or tar.gz file to the given destination.
*
@@ -245,8 +252,6 @@ function packageKeytar() {
* @param {string} prebuiltDest
* the location (inside the electron application) where the prebuilt
* binaries should be stored.
- * @param {string} pkgSrc
- * the directory to the source node package, which should be repackaged.
* @param {string} pkgName
* the the package name
* @param {string} platform
@@ -288,7 +293,7 @@ async function deployPrebuilt(electronDest, prebuiltDest, pkgName, platform, arc
if (!existsSync(prebuiltSrc)) {
const url = `${PREBUILT_URL_KEYTAR}/v${pkg.version}/${filename}`;
- await common.download(url, prebuiltSrc);
+ await https.download(url, prebuiltSrc);
}
// Step four, deploy the prebuilt.
@@ -457,6 +462,61 @@ async function zipLinux() {
await common.compress(source, destination, options);
}
+/**
+ * Creates a linux appImage Container
+ */
+async function appImageLinux() {
+ "use strict";
+
+ const latest = await https.fetch(APP_IMAGE_RELEASE_URL);
+
+ let url = null;
+ for (const asset of latest.assets) {
+ if (asset.name === APP_IMAGE_TOOL_NAME)
+ url = asset.browser_download_url;
+ }
+
+ if (!url)
+ throw new Error("Could not download app image tool.");
+
+ const tool = path.join(CACHE_DIR_APP, `appimagetool-v${latest.name}.AppImage`);
+
+ if (!existsSync(tool))
+ await https.download(url, tool);
+
+ const RWX_RWX_RX = 0o775;
+ await chmod(tool, RWX_RWX_RX);
+
+ const version = (await common.getPackageVersion()).join(".");
+
+ const source = path.resolve(path.join(OUTPUT_DIR_APP, `sieve-${LINUX_PLATFORM}-${LINUX_ARCH}`));
+ const destination = path.resolve(path.join(common.BASE_DIR_BUILD, `sieve-${version}-${LINUX_PLATFORM}-${LINUX_ARCH}.AppImage`));
+
+ exec(`${tool} "${source}" "${destination}" 2>&1`);
+}
+
+
+/**
+ * Zip the macOS electron app.
+ */
+async function zipMacOs() {
+ "use strict";
+
+ const version = (await common.getPackageVersion()).join(".");
+
+ const source = path.resolve(path.join(OUTPUT_DIR_APP, `sieve-${MAC_PLATFORM}-${MAC_ARCH}`));
+ const destination = path.join(common.BASE_DIR_BUILD, `sieve-${version}-${MAC_PLATFORM}-${MAC_ARCH}.zip`);
+
+ const options = {
+ permissions: {
+ "sieve": 0o100770,
+ "*": 0o100660
+ }
+ };
+
+ await common.compress(source, destination, options);
+}
+
exports["watch"] = watchSrc;
exports["updateVersion"] = updateVersion;
@@ -487,6 +547,9 @@ exports["packageMacOS"] = series(
exports["zipWin32"] = zipWin32;
exports["zipLinux"] = zipLinux;
+exports["zipMacOs"] = zipMacOs;
+
+exports["appImageLinux"] = appImageLinux;
exports['package'] = parallel(
packageDefinition,
diff --git a/gulp/gulpfile.common.https.js b/gulp/gulpfile.common.https.js
new file mode 100644
index 00000000..88debbb3
--- /dev/null
+++ b/gulp/gulpfile.common.https.js
@@ -0,0 +1,160 @@
+/*
+ * The content of this file is licensed. You may obtain a copy of
+ * the license at https://github.com/thsmi/sieve/ or request it via
+ * email from the author.
+ *
+ * Do not remove or change this comment.
+ *
+ * The initial author of the code is:
+ * Thomas Schmid <schmid-thomas@gmx.net>
+ */
+
+const logger = require('gulplog');
+
+const https = require('https');
+const fs = require('fs');
+
+const HTTP_SUCCESS_MIN = 200;
+const HTTP_SUCCESS_MAX = 299;
+
+const HTTP_REDIRECT_MIN = 300;
+const HTTP_REDIRECT_MAX = 399;
+
+/**
+ * Checks if the http status code indicates a redirection.
+ *
+ * @param {int} status
+ * the status to be checked,
+ *
+ * @returns {boolean}
+ * the true in case the server requested a redirection otherwise false.
+ */
+function isRedirection(status) {
+ "use strict";
+
+ return (status >= HTTP_REDIRECT_MIN) && (status <= HTTP_REDIRECT_MAX);
+}
+
+/**
+ * Checks if the http status code indicates a success.
+ *
+ * @param {int} status
+ * the status to be checked,
+ *
+ * @returns {boolean}
+ * the true in case the server signaled a success otherwise false.
+ */
+function isSuccess(status) {
+ "use strict";
+
+ return (status >= HTTP_SUCCESS_MIN) && (status <= HTTP_SUCCESS_MAX);
+}
+
+/**
+ * Fetches a json file from a https url.
+ * E.g. used to download github releases via the api.
+ *
+ * @param {string} url
+ * the json file to be loaded.
+ */
+async function fetch(url) {
+
+ "use strict";
+
+ logger.debug(`Fetching ${url}`);
+
+ return await new Promise((resolve, reject) => {
+
+ // Github requires to have a user agents set.
+ // It should be the username plus the application name.
+ //
+ // https://developer.github.com/v3/#user-agent-required
+
+ const options = {headers: { 'User-Agent': 'thsmi-sieve' }};
+ https.get(url, options, async function (response) {
+
+ try {
+
+ if (isRedirection(response.statusCode)) {
+ logger.debug(`Following redirect to ${response.headers.location}`);
+ resolve(await fetch(response.headers.location));
+ return;
+ }
+
+ if (!isSuccess(response.statusCode))
+ throw Error(`Response failed with status code ${response.statusCode}.`);
+
+ let data = "";
+
+ response.on("data", (bytes) => {
+ data += bytes;
+ });
+
+ response.on('end', () => {
+ resolve(JSON.parse(data));
+ });
+
+ } catch (ex) {
+ reject(new Error(ex));
+ }
+ });
+ });
+}
+
+/**
+ * Downloads a file from an https url and stores the data into the given file.
+ * It follows redirects. Upon a non 200 status code an error is thrown.
+ *
+ * @param {string} url
+ * the download url.
+ * @param {string} destination
+ * the file into which the downloaded data should be stored.
+ * In case the file exists it will be silently overwritten.
+ */
+async function download(url, destination) {
+
+ "use strict";
+
+ logger.debug(`Downloading ${url} to ${destination}`);
+
+ return await new Promise((resolve, reject) => {
+ // Github requires to have a user agents set.
+ // It should be the username plus the application name.
+ //
+ // https://developer.github.com/v3/#user-agent-required
+
+ const options = {headers: { 'User-Agent': 'thsmi-sieve' }};
+
+ https.get(url, options, async function (response) {
+
+ try {
+ if (isRedirection(response.statusCode)) {
+ logger.debug(`Following redirect to ${response.headers.location}`);
+ await download(response.headers.location, destination);
+
+ resolve();
+ return;
+ }
+
+ if (!isSuccess(response.statusCode))
+ throw Error(`Response failed with status code ${response.statusCode}.`);
+
+ const file = fs.createWriteStream(destination);
+
+ response.pipe(file);
+
+ file.on('finish', function () {
+ file.close(function () {
+ resolve();
+ });
+ });
+ } catch (ex) {
+ reject(new Error(ex));
+ }
+ });
+ });
+}
+
+
+exports["download"] = download;
+exports["fetch"] = fetch;
diff --git a/gulp/gulpfile.common.js b/gulp/gulpfile.common.js
index 73b718e2..031f4e5f 100644
--- a/gulp/gulpfile.common.js
+++ b/gulp/gulpfile.common.js
@@ -352,60 +352,8 @@ async function compress(source, destination, options) {
});
}
-/**
- * Downloads a file from an https url and stores the data into the given file.
- * It follows redirects. Upon a non 200 status code an error is thrown.
- *
- * @param {string} url
- * the download url.
- * @param {string} destination
- * the file into which the downloaded data should be stored.
- * In case the file exists it will be silently overwritten.
- */
-async function download(url, destination) {
-
- "use strict";
-
- const https = require('https');
- const fs = require('fs');
-
- logger.debug(`Downloading ${url} to ${destination}`);
-
- return await new Promise((resolve, reject) => {
- https.get(url, async function (response) {
-
- try {
- if (response.statusCode >= 300 && response.statusCode <= 308) {
- logger.debug(`Following redirect to ${response.headers.location}`);
- await download(response.headers.location, destination);
-
- resolve();
- return;
- }
-
- if (response.statusCode !== 200)
- throw Error(`Response failed with status code ${response.statusCode}.`);
-
- const file = fs.createWriteStream(destination);
-
- response.pipe(file);
-
- file.on('finish', function () {
- file.close(function () {
- resolve();
- });
- });
- } catch (ex) {
- reject(new Error(ex));
- }
- });
- });
-}
-
-
exports["clean"] = clean;
exports["compress"] = compress;
-exports["download"] = download;
exports["packageJQuery"] = packageJQuery;
exports["packageCodeMirror"] = packageCodeMirror;