Skip to content

Commit

Permalink
Merge pull request #385 from cosmos/fabo/342-deterministic-zip
Browse files Browse the repository at this point in the history
Deterministic zip/tar
  • Loading branch information
nylira authored Jan 26, 2018
2 parents 39b4cd6 + bfa6246 commit a1e2070
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 586 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:8.9.3-browsers
- image: circleci/node:9.4.0-browsers

working_directory: ~/repo

Expand Down
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest Tests",
"program": "${workspaceRoot}\\node_modules\\jest\\bin\\jest.js",
"args": [
"-i"
],
"internalConsoleOptions": "openOnSessionStart"
}
]
}
7 changes: 0 additions & 7 deletions app/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,6 @@ async function reconnect (seeds) {
}

async function main () {
// the windows installer opens the app once when installing
// the package recommends, that we exit if this happens
// we can also react to installer events, but currently don't need to
if (require('electron-squirrel-startup')) {
return
}

if (JSON.parse(process.env.COSMOS_UI_ONLY || 'false')) {
return
}
Expand Down
Empty file removed builds/.gitkeep
Empty file.
2 changes: 1 addition & 1 deletion config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let config = {
ignore: /^\/(src|index\.ejs|icons)/,
out: path.join(__dirname, 'builds'),
overwrite: true,
platform: process.env.PLATFORM_TARGET || 'darwin,linux,windows',
platform: process.env.PLATFORM_TARGET || 'darwin,linux,win32',
packageManager: 'yarn'
}
}
Expand Down
15 changes: 5 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"url": "git+https://github.com/cosmos/cosmos-ui.git"
},
"engines": {
"node": ">=8.0.0"
"node": ">=9.4.0"
},
"scripts": {
"build": "node tasks/release.js",
Expand All @@ -20,9 +20,6 @@
"build:linux": "cross-env PLATFORM_TARGET=linux node tasks/release.js",
"build:mas": "cross-env PLATFORM_TARGET=mas node tasks/release.js",
"build:win32": "cross-env PLATFORM_TARGET=win32 node tasks/release.js",
"release:darwin": "electron-installer-dmg --overwrite builds/Cosmos-darwin-x64/Cosmos.app builds/cosmos",
"release:linux": "electron-installer-debian --src builds/Cosmos-linux-x64/ --dest builds/cosmos --arch amd64",
"release:win32": "node tasks/windows-installer.js",
"uionly": "cross-env COSMOS_UI_ONLY='true' yarn run testnet",
"local": "npm run testnet local",
"testnet": "node tasks/testnet.js",
Expand Down Expand Up @@ -106,12 +103,16 @@
"casual": "^1.5.19",
"chart.js": "^2.6.0",
"cosmos-sdk": "^1.5.1",
"deterministic-tar": "^0.1.2",
"deterministic-zip": "^1.0.5",
"electron": "^1.7.5",
"event-to-promise": "^0.8.0",
"express": "^4.16.2",
"express-http-proxy": "^1.1.0",
"flatpickr": "^4.1.2",
"fs-extra": "^5.0.0",
"glob": "^7.1.2",
"jszip": "^3.1.5",
"interactjs": "^1.3.3",
"kill-port": "^1.0.0",
"moment": "^2.17.1",
Expand Down Expand Up @@ -187,11 +188,5 @@
"./test/unit/helpers/console_error_throw.js",
"./test/unit/helpers/genesis_mock.js"
]
},
"optionalDependencies": {
"electron-installer-debian": "^0.7.1",
"electron-installer-dmg": "^0.2.1",
"electron-squirrel-startup": "^1.0.0",
"electron-winstaller": "^2.6.3"
}
}
104 changes: 97 additions & 7 deletions tasks/release.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
'use strict'

const { exec } = require('child_process')
const { join } = require('path')
const { createHash } = require('crypto')
const path = require('path')
const packager = require('electron-packager')
const mkdirp = require('mkdirp').sync
const fs = require('fs-extra')
const { promisify } = require('util')
var glob = require('glob')
var JSZip = require('jszip')
const zlib = require('zlib')
var deterministic = require('deterministic-tar')
var tar = require('tar-stream')
const packageJson = require('../package.json')

let skipPack = false
let binaryPath = null
Expand All @@ -32,7 +37,7 @@ if (process.env.PLATFORM_TARGET === 'clean') {
console.log('\x1b[33m`builds` directory cleaned.\n\x1b[0m')
} else {
if (skipPack) {
build()
build(process.env.PLATFORM_TARGET)
} else {
pack()
}
Expand All @@ -57,21 +62,30 @@ function pack () {
/**
* Use electron-packager to build electron app
*/
function build () {
function build (platform) {
let options = require('../config').building

options.afterCopy = [
copyBinary('gaia', binaryPath)
]

console.log('\x1b[34mBuilding electron app(s)...\n\x1b[0m')
packager(options, (err, appPaths) => {
packager(options, async (err, appPaths) => {
if (err) {
console.error('\x1b[31mError from `electron-packager` when building app...\x1b[0m')
console.error(err)
} else {
console.log('Build(s) successful!')
console.log(appPaths)
console.log('\n\x1b[34mZipping files...\n\x1b[0m')
await Promise.all(appPaths.map(async appPath => {
if (platform === 'win32') {
await zipFolder(appPath, options.out, packageJson.version)
} else {
await tarFolder(appPath, options.out, packageJson.version)
.catch(err => console.error(err))
}
}))

console.log('\n\x1b[34mDONE\n\x1b[0m')
}
Expand All @@ -80,11 +94,87 @@ function build () {

function copyBinary (name, binaryLocation) {
return function (buildPath, electronVersion, platform, arch, cb) {
let binPath = join(buildPath, 'bin', name)
let binPath = path.join(buildPath, 'bin', name)
if (platform === 'win32') {
binPath = binPath + '.exe'
}
fs.copySync(binaryLocation, binPath)
cb()
}
}

function sha256File (path) {
let hash = createHash('sha256')
fs.createReadStream(path).pipe(hash)
return new Promise((resolve, reject) => {
hash.on('data', (hash) =>
resolve(hash.toString('hex')))
})
}

function zipFolder (inDir, outDir, version) {
return new Promise(async (resolve, reject) => {
let name = path.parse(inDir).name
let outFile = path.join(outDir, `${name}_${version}.zip`)
var zip = new JSZip()
await new Promise((resolve) => {
glob(inDir + '/**/*', (err, files) => {
if (err) {
return reject(err)
}
files
.filter(file => !fs.lstatSync(file).isDirectory())
.forEach(file => {
zip.file(path.relative(inDir, file), fs.readFileSync(file), {date: new Date('1987-08-16')}) // make the zip deterministic by changing all file times
})
resolve()
})
})
zip.generateNodeStream({type: 'nodebuffer', streamFiles: true})
.pipe(fs.createWriteStream(outFile))
.on('finish', function () {
sha256File(outFile).then((hash) => {
console.log('Zip successful!', outFile, 'SHA256:', hash)
resolve()
})
})
})
}

function tarFolder (inDir, outDir, version) {
return new Promise(async (resolve, reject) => {
let name = path.parse(inDir).name
let outFile = path.join(outDir, `${name}_${version}.tar.gz`)
var pack = tar.pack()

await new Promise((resolve) => {
glob(inDir + '/**/*', (err, files) => {
if (err) {
return reject(err)
}
// add files to tar
files
.filter(file => !fs.lstatSync(file).isDirectory())
.forEach(file => {
pack.entry({ name: path.relative(inDir, file) }, fs.readFileSync(file))
})
pack.finalize()
resolve()
})
})

// make tar deterministic
pack
.pipe(deterministic())
.pipe(zlib.createGzip())
// save tar to disc
.pipe(fs.createWriteStream(outFile))
.on('finish', function () {
console.log('write finished')
sha256File(outFile).then((hash) => {
console.log('Zip successful!', outFile, 'SHA256:', hash)
resolve()
})
})
})
}
Loading

0 comments on commit a1e2070

Please sign in to comment.