Add Jenkins Integration (#1295)
* add jenkins changes * run prettier * update icons * update icons to use latest favicon
This commit is contained in:
parent
9be46bf8aa
commit
937cc3fde5
Binary file not shown.
Before Width: | Height: | Size: 788 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,6 @@
|
||||||
|
FROM electronuserland/builder:wine-03.18
|
||||||
|
|
||||||
|
RUN mkdir /hostHome
|
||||||
|
RUN apt-get update && apt-get install -y libusb-1.0 nasm graphicsmagick autoconf automake libtool python-pip
|
||||||
|
RUN pip install awscli --upgrade --user
|
||||||
|
ENV PATH "$PATH:/root/.local/bin"
|
|
@ -0,0 +1,26 @@
|
||||||
|
pipeline {
|
||||||
|
agent {
|
||||||
|
dockerfile {
|
||||||
|
filename 'Dockerfile'
|
||||||
|
dir 'jenkins/Docker'
|
||||||
|
args '--env ETH_SIGNING_KEY=$ETH_SIGNING_KEY --env S3_BUCKET_NAME=$S3_BUCKET_NAME'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Build') {
|
||||||
|
environment {
|
||||||
|
ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES = 1
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'rm -rf node_modules'
|
||||||
|
sh 'npm install'
|
||||||
|
sh 'npm run jenkins:build:linux'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Upload') {
|
||||||
|
steps {
|
||||||
|
sh 'npm run jenkins:upload'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
const VERSION = require('../package.json').version;
|
||||||
|
const GIT_COMMIT = process.env.GIT_COMMIT || 'commit-not-set';
|
||||||
|
const GIT_COMMIT_SHORT = GIT_COMMIT.substring(0, 7);
|
||||||
|
const JENKINS_BUILD_ID = process.env.BUILD_ID;
|
||||||
|
const LINUX_FILES = [`MyCrypto-${VERSION}-i386.AppImage`, `MyCrypto-${VERSION}-x86_64.AppImage`];
|
||||||
|
const WINDOWS_FILES = [`MyCrypto Setup ${VERSION}.exe`, `MyCrypto Setup ${VERSION}.exe.blockmap`];
|
||||||
|
const OSX_FILES = [];
|
||||||
|
const FLAVOR = (() => {
|
||||||
|
const { platform } = process;
|
||||||
|
|
||||||
|
if (platform === 'linux') {
|
||||||
|
return 'linux-windows';
|
||||||
|
} else if (platform === 'darwin') {
|
||||||
|
return 'mac';
|
||||||
|
} else {
|
||||||
|
throw new Error('Unsupported platform.');
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
const S3_BUCKET = process.env.S3_BUCKET_NAME;
|
||||||
|
const ETH_SIGNING_KEY = process.env.ETH_SIGNING_KEY;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
VERSION,
|
||||||
|
GIT_COMMIT,
|
||||||
|
GIT_COMMIT_SHORT,
|
||||||
|
JENKINS_BUILD_ID,
|
||||||
|
LINUX_FILES,
|
||||||
|
WINDOWS_FILES,
|
||||||
|
OSX_FILES,
|
||||||
|
FLAVOR,
|
||||||
|
S3_BUCKET,
|
||||||
|
ETH_SIGNING_KEY
|
||||||
|
};
|
|
@ -0,0 +1,112 @@
|
||||||
|
const path = require('path');
|
||||||
|
const { createHash } = require('crypto');
|
||||||
|
const { readFileSync } = require('fs');
|
||||||
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
|
const { hashPersonalMessage, ecsign, toBuffer, addHexPrefix } = require('ethereumjs-util');
|
||||||
|
|
||||||
|
const genCommitFilename = (name, version, commit, buildId) => {
|
||||||
|
const split = name.split(version);
|
||||||
|
return `${split[0]}${version}-${commit}-${buildId}${split[1]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const genFileList = (linux, windows, osx) => {
|
||||||
|
const { platform } = process;
|
||||||
|
if (platform === 'linux') {
|
||||||
|
return [...linux, ...windows];
|
||||||
|
} else if (platform === 'darwin') {
|
||||||
|
return [...osx];
|
||||||
|
} else {
|
||||||
|
throw new Error('Unrecognized host platform.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const genSha512 = filePath => {
|
||||||
|
const hash = createHash('sha512');
|
||||||
|
const data = readFileSync(filePath);
|
||||||
|
hash.update(data);
|
||||||
|
return hash.digest('hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
const runChildProcess = cmd =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const child = spawn('sh', ['-c', cmd]);
|
||||||
|
|
||||||
|
child.stdout.on('data', data => {
|
||||||
|
process.stdout.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on('data', data => {
|
||||||
|
process.stderr.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('close', code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
return reject(`Child process exited with code: ${code}`);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const uploadToS3 = (localFilePath, s3FilePath) =>
|
||||||
|
runChildProcess(`aws s3 cp "${localFilePath}" "${s3FilePath}"`);
|
||||||
|
|
||||||
|
const genS3Url = (filename, commit, bucket) => `s3://${bucket}/${commit}/${filename}`;
|
||||||
|
|
||||||
|
const genManifestFile = manifest =>
|
||||||
|
manifest.map(info => ({
|
||||||
|
Filename: info.commitFilename,
|
||||||
|
SHA512: info.fileHash
|
||||||
|
}));
|
||||||
|
|
||||||
|
const genManifestFilename = (flavor, version, commit, buildId) =>
|
||||||
|
`manifest.${flavor}.v${version}.${commit}.${buildId}.json`;
|
||||||
|
|
||||||
|
const genSignatureFile = (manifestHash, pKeyString) => {
|
||||||
|
const pKeyBuffer = Buffer.from(pKeyString, 'hex');
|
||||||
|
return signMessageWithPrivKeyV2(pKeyBuffer, manifestHash);
|
||||||
|
};
|
||||||
|
|
||||||
|
const genSignatureFilename = (flavor, version, commit, buildId) =>
|
||||||
|
`manifest.${flavor}.v${version}.${commit}.${buildId}.signature`;
|
||||||
|
|
||||||
|
const genManifest = (fileList, version, jenkinsBuildId, gitCommit, gitCommitShort, s3Bucket) =>
|
||||||
|
fileList.map(filename => {
|
||||||
|
const fullPath = path.resolve('dist/electron-builds/', filename);
|
||||||
|
const commitFilename = genCommitFilename(filename, version, gitCommitShort, jenkinsBuildId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
fullPath,
|
||||||
|
filename,
|
||||||
|
commitFilename,
|
||||||
|
fileHash: genSha512(fullPath),
|
||||||
|
s3Url: genS3Url(commitFilename, gitCommit, s3Bucket)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function signMessageWithPrivKeyV2(privKey, msg) {
|
||||||
|
const hash = hashPersonalMessage(toBuffer(msg));
|
||||||
|
const signed = ecsign(hash, privKey);
|
||||||
|
const combined = Buffer.concat([
|
||||||
|
Buffer.from(signed.r),
|
||||||
|
Buffer.from(signed.s),
|
||||||
|
Buffer.from([signed.v])
|
||||||
|
]);
|
||||||
|
const combinedHex = combined.toString('hex');
|
||||||
|
|
||||||
|
return addHexPrefix(combinedHex);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
genCommitFilename,
|
||||||
|
genManifestFile,
|
||||||
|
genFileList,
|
||||||
|
genSha512,
|
||||||
|
genS3Url,
|
||||||
|
uploadToS3,
|
||||||
|
signMessageWithPrivKeyV2,
|
||||||
|
genManifestFilename,
|
||||||
|
genManifest,
|
||||||
|
genSignatureFile,
|
||||||
|
genSignatureFilename
|
||||||
|
};
|
|
@ -0,0 +1,68 @@
|
||||||
|
const path = require('path');
|
||||||
|
const { writeFileSync } = require('fs');
|
||||||
|
|
||||||
|
const {
|
||||||
|
VERSION,
|
||||||
|
FLAVOR,
|
||||||
|
GIT_COMMIT,
|
||||||
|
GIT_COMMIT_SHORT,
|
||||||
|
LINUX_FILES,
|
||||||
|
WINDOWS_FILES,
|
||||||
|
OSX_FILES,
|
||||||
|
S3_BUCKET,
|
||||||
|
JENKINS_BUILD_ID,
|
||||||
|
ETH_SIGNING_KEY
|
||||||
|
} = require('./constants');
|
||||||
|
|
||||||
|
const {
|
||||||
|
genSha512,
|
||||||
|
genFileList,
|
||||||
|
genCommitFilename,
|
||||||
|
genS3Url,
|
||||||
|
genManifest,
|
||||||
|
genManifestFile,
|
||||||
|
genManifestFilename,
|
||||||
|
genSignatureFile,
|
||||||
|
genSignatureFilename,
|
||||||
|
uploadToS3
|
||||||
|
} = require('./lib');
|
||||||
|
|
||||||
|
const fileList = genFileList(WINDOWS_FILES, LINUX_FILES, OSX_FILES);
|
||||||
|
|
||||||
|
const manifest = genManifest(
|
||||||
|
fileList,
|
||||||
|
VERSION,
|
||||||
|
JENKINS_BUILD_ID,
|
||||||
|
GIT_COMMIT,
|
||||||
|
GIT_COMMIT_SHORT,
|
||||||
|
S3_BUCKET
|
||||||
|
);
|
||||||
|
|
||||||
|
const manifestFile = genManifestFile(manifest);
|
||||||
|
const manifestFilename = genManifestFilename(FLAVOR, VERSION, GIT_COMMIT_SHORT, JENKINS_BUILD_ID);
|
||||||
|
const manifestFilePath = path.resolve(`./${manifestFilename}`);
|
||||||
|
const manifestS3Url = genS3Url(manifestFilename, GIT_COMMIT, S3_BUCKET);
|
||||||
|
|
||||||
|
// write manifest file
|
||||||
|
writeFileSync(manifestFilename, JSON.stringify(manifestFile, null, 2), 'utf8');
|
||||||
|
|
||||||
|
const manifestHash = genSha512(manifestFilePath);
|
||||||
|
|
||||||
|
const signatureFile = genSignatureFile(manifestHash, ETH_SIGNING_KEY);
|
||||||
|
const signatureFilename = genSignatureFilename(FLAVOR, VERSION, GIT_COMMIT_SHORT, JENKINS_BUILD_ID);
|
||||||
|
const signatureFilePath = path.resolve(`./${signatureFilename}`);
|
||||||
|
const signatureS3Url = genS3Url(signatureFilename, GIT_COMMIT, S3_BUCKET);
|
||||||
|
|
||||||
|
// write signature file
|
||||||
|
writeFileSync(signatureFilePath, signatureFile, 'utf8');
|
||||||
|
|
||||||
|
// upload all the things to S3
|
||||||
|
(async () => {
|
||||||
|
for (let fileInfo of manifest) {
|
||||||
|
const { fullPath, s3Url } = fileInfo;
|
||||||
|
await uploadToS3(fullPath, s3Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
await uploadToS3(manifestFilePath, manifestS3Url);
|
||||||
|
await uploadToS3(signatureFilePath, signatureS3Url);
|
||||||
|
})();
|
|
@ -152,6 +152,9 @@
|
||||||
"build:electron:windows": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=windows node webpack_config/buildElectron.js",
|
"build:electron:windows": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=windows node webpack_config/buildElectron.js",
|
||||||
"build:electron:linux": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=linux node webpack_config/buildElectron.js",
|
"build:electron:linux": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=linux node webpack_config/buildElectron.js",
|
||||||
"prebuild:electron": "check-node-version --package",
|
"prebuild:electron": "check-node-version --package",
|
||||||
|
"jenkins:build:linux": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=JENKINS_LINUX node webpack_config/buildElectron.js",
|
||||||
|
"jenkins:build:mac": "webpack --config webpack_config/webpack.electron-prod.js && ELECTRON_OS=JENKINS_MAC node webpack_config/buildElectron.js",
|
||||||
|
"jenkins:upload": "node jenkins/upload",
|
||||||
"test:coverage": "jest --config=jest_config/jest.config.json --coverage",
|
"test:coverage": "jest --config=jest_config/jest.config.json --coverage",
|
||||||
"test": "jest --config=jest_config/jest.config.json",
|
"test": "jest --config=jest_config/jest.config.json",
|
||||||
"test:unit": "jest --config=jest_config/jest.config.json --coverage",
|
"test:unit": "jest --config=jest_config/jest.config.json --coverage",
|
||||||
|
|
|
@ -6,7 +6,15 @@ const builder = require('electron-builder');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
|
||||||
function shouldBuildOs(os) {
|
function shouldBuildOs(os) {
|
||||||
return !process.env.ELECTRON_OS || process.env.ELECTRON_OS === os;
|
const { ELECTRON_OS } = process.env;
|
||||||
|
|
||||||
|
if (ELECTRON_OS === 'JENKINS_LINUX') {
|
||||||
|
return os === 'linux' || os === 'windows';
|
||||||
|
} else if (ELECTRON_OS === 'JENKINS_MAC') {
|
||||||
|
return os === 'mac';
|
||||||
|
} else {
|
||||||
|
return !process.env.ELECTRON_OS || process.env.ELECTRON_OS === os;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function build() {
|
async function build() {
|
||||||
|
@ -36,7 +44,7 @@ async function build() {
|
||||||
productName: 'MyCrypto',
|
productName: 'MyCrypto',
|
||||||
directories: {
|
directories: {
|
||||||
app: jsBuildDir,
|
app: jsBuildDir,
|
||||||
output: electronBuildsDir,
|
output: electronBuildsDir
|
||||||
},
|
},
|
||||||
mac: {
|
mac: {
|
||||||
category: 'public.app-category.finance',
|
category: 'public.app-category.finance',
|
||||||
|
@ -49,14 +57,11 @@ async function build() {
|
||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
category: 'Finance',
|
category: 'Finance',
|
||||||
|
icon: path.join(config.path.electron, 'icons/icon.png'),
|
||||||
compression
|
compression
|
||||||
},
|
},
|
||||||
publish: {
|
// IMPORTANT: Prevents from auto publishing to GitHub in CI environments
|
||||||
provider: 'github',
|
publish: null,
|
||||||
owner: 'MyCryptoHQ',
|
|
||||||
repo: 'MyCrypto',
|
|
||||||
vPrefixedTagName: false
|
|
||||||
},
|
|
||||||
// IMPORTANT: Prevents extending configs in node_modules
|
// IMPORTANT: Prevents extending configs in node_modules
|
||||||
extends: null
|
extends: null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue