Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deterministic zip/tar #385

Merged
merged 10 commits into from
Jan 26, 2018
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
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