Merge pull request #24 from desktop/package-release

Package release builds
This commit is contained in:
Markus Olsson 2016-05-27 16:28:01 +02:00
commit 61a90f55b8
12 changed files with 273 additions and 123 deletions

View file

@ -29,7 +29,7 @@ before_script:
script:
- npm run lint
- npm run build
- npm run build:prod
- npm test
cache:

View file

@ -15,7 +15,7 @@ install:
build_script:
- npm run lint
- npm run build
- npm run build:prod
test_script:
- npm test

View file

@ -1,10 +1,12 @@
var express = require('express')
var webpack = require('webpack')
var config = require('./webpack.config')
'use strict'
var app = express()
var compiler = webpack(config)
var port = process.env.PORT || 3000
const express = require('express')
const webpack = require('webpack')
const config = require('./webpack.development')
const app = express()
const compiler = webpack(config)
const port = process.env.PORT || 3000
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath

View file

@ -14,12 +14,16 @@
"test": "electron-mocha --renderer --require ts-node/register test/*.ts test/*.tsx",
"postinstall": "typings install",
"start-server": "node dev_server.js",
"start": "npm run build && npm-run-all --parallel dev start-server",
"dev": "env NODE_ENV=development node script/run",
"compile": "tsc && webpack",
"build": "npm run compile && node script/package",
"start": "npm run build:dev && npm-run-all --parallel run start-server",
"run": "env NODE_ENV=development node script/run",
"compile:dev": "tsc && env NODE_ENV=development webpack --config webpack.development.js",
"compile:prod": "tsc && env NODE_ENV=production webpack --config webpack.production.js",
"build:dev": "npm run compile:dev && env NODE_ENV=development node script/build",
"build:prod": "npm run compile:prod && env NODE_ENV=production node script/build",
"package": "node script/package",
"clean": "rm -rf build",
"rebuild": "npm run clean && npm run build",
"rebuild:dev": "npm run clean && npm run build:dev",
"rebuild:prod": "npm run clean && npm run build:prod",
"lint": "tslint ./src/**/*.ts ./src/**/*.tsx ./test/**/*.ts ./test/**/*.tsx"
},
"author": "",
@ -28,7 +32,9 @@
"babel-runtime": "^6.6.1",
"octokat": "^0.5.0-beta.0",
"react": "^15.0.2",
"react-dom": "^15.0.2",
"react-dom": "^15.0.2"
},
"debugDependencies": {
"react-transform-hmr": "^1.0.4",
"webpack-hot-middleware": "^2.10.0"
},
@ -45,6 +51,7 @@
"electron-mocha": "2.1.0",
"electron-packager": "^7.0.1",
"electron-prebuilt": "^1.1.2",
"electron-winstaller": "^2.3.0",
"express": "^4.13.4",
"fs-extra": "^0.30.0",
"mocha": "^2.4.5",

93
script/build Executable file
View file

@ -0,0 +1,93 @@
#!/usr/bin/env node
'use strict'
const path = require('path')
const cp = require('child_process')
const fs = require('fs-extra')
const packager = require('electron-packager')
const projectRoot = path.join(__dirname, '..')
const buildRoot = path.join(projectRoot, 'build')
const appPackage = require(path.join(projectRoot, 'package.json'))
console.log(`Building for ${process.env.NODE_ENV}…`)
console.log('Removing old distribution…')
fs.removeSync(path.join(projectRoot, 'dist'))
console.log('Installing dependencies…')
installDependencies()
console.log('Copying `static`…')
fs.copySync(path.join(projectRoot, 'static'), path.join(buildRoot, 'static'), {clobber: true})
const options = {
platform: process.platform,
arch: 'x64',
'app-version': appPackage.version,
'build-version': appPackage.version,
asar: false, // TODO: Probably wanna enable this down the road.
out: path.join(projectRoot, 'dist'),
icon: path.join(buildRoot, 'static', 'icon'),
dir: path.join(projectRoot, 'build'),
overwrite: true,
prune: false, // We only install production dependencies above.
// OS X
// TODO: We'll need to sign this shit.
'app-bundle-id': appPackage.bundleID,
'app-category-type': 'public.app-category.developer-tools',
// Windows
'version-string': {
'CompanyName': appPackage.companyName,
'FileDescription': '',
'OriginalFilename': '',
'ProductName': appPackage.productName,
'InternalName': appPackage.productName
}
}
packager(options, (error, appPaths) => {
if (error) {
console.error(error)
process.exit(1)
} else {
console.log(`Built to ${appPaths}`)
process.exit(0)
}
})
function installDependencies () {
let packageJson = appPackage
if (process.env.NODE_ENV === 'development') {
packageJson = debugPackageJson(packageJson)
} else {
packageJson = releasePackageJson(packageJson)
}
fs.removeSync(path.join(buildRoot, 'package.json'))
fs.writeJsonSync(path.join(buildRoot, 'package.json'), packageJson)
cp.execSync('npm install', {cwd: buildRoot, env: process.env})
}
function distPackageJson (appPackage) {
const releasePackage = Object.assign({}, appPackage)
delete releasePackage['scripts']
delete releasePackage['devDependencies']
return releasePackage
}
function releasePackageJson (appPackage) {
const releasePackage = Object.assign({}, distPackageJson(appPackage))
delete releasePackage['debugDependencies']
return releasePackage
}
function debugPackageJson (appPackage) {
const releasePackage = Object.assign({}, distPackageJson(appPackage))
releasePackage.dependencies = Object.assign({}, releasePackage.dependencies, releasePackage.debugDependencies)
delete releasePackage['debugDependencies']
return releasePackage
}

18
script/dist-info.js Normal file
View file

@ -0,0 +1,18 @@
'use strict'
const path = require('path')
const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'package.json'))
module.exports.getDistPath = function () {
return path.join(projectRoot, 'dist', `${appPackage.productName}-${process.platform}-x64`)
}
module.exports.getProductName = function () {
return appPackage.productName
}
module.exports.getCompanyName = function () {
return appPackage.companyName
}

87
script/package Executable file → Normal file
View file

@ -2,58 +2,45 @@
'use strict'
const path = require('path')
const cp = require('child_process')
const fs = require('fs-extra')
const packager = require('electron-packager')
const cp = require('child_process')
const path = require('path')
const distInfo = require('./dist-info')
const projectRoot = path.join(__dirname, '..')
const buildRoot = path.join(projectRoot, 'build')
const appPackage = require(path.join(projectRoot, 'package.json'))
const distPath = distInfo.getDistPath()
const productName = distInfo.getProductName()
console.log('Removing old distribution…')
fs.removeSync(path.join(projectRoot, 'dist'))
console.log('Installing dependencies…')
fs.copySync(path.join(projectRoot, 'package.json'), path.join(buildRoot, 'package.json'), {clobber: true})
cp.execSync('npm install --only=production', {cwd: buildRoot})
console.log('Copying `static`…')
fs.copySync(path.join(projectRoot, 'static'), path.join(buildRoot, 'static'), {clobber: true})
const options = {
platform: process.platform,
arch: 'x64',
'app-version': appPackage.version,
'build-version': appPackage.version,
asar: false, // TODO: Probably wanna enable this down the road.
out: path.join(projectRoot, 'dist'),
icon: path.join(buildRoot, 'static', 'icon'),
dir: path.join(projectRoot, 'build'),
overwrite: true,
prune: false, // We only install production dependencies above.
// OS X
'app-bundle-id': appPackage.bundleID,
'app-category-type': 'public.app-category.developer-tools',
// Windows
'version-string': {
'CompanyName': appPackage.companyName,
'FileDescription': '',
'OriginalFilename': '',
'ProductName': appPackage.productName,
'InternalName': appPackage.productName
}
if (process.platform === 'darwin') {
packageOSX()
} else if (process.platform === 'win32') {
packageWindows()
} else {
console.error(`I dunno how to package for ${process.platform} :(`)
process.exit(1)
}
console.log('Packaging…')
packager(options, (error, appPaths) => {
if (error) {
console.error(error)
process.exit(1)
} else {
console.log(`Built to ${appPaths}`)
process.exit(0)
}
})
function packageOSX () {
const dest = path.join(distPath, '..', `${productName}.zip`)
fs.removeSync(dest)
cp.execSync(`ditto -ck --keepParent ${distPath}/${productName}.app ${dest}`)
console.log(`Zipped to ${dest}`)
}
function packageWindows () {
const electronInstaller = require('electron-winstaller')
const outputDir = path.join(distPath, '..', 'installer')
// TODO: We'll need to sign this shit.
electronInstaller
.createWindowsInstaller({
appDirectory: distPath,
outputDirectory: outputDir,
authors: distInfo.getCompanyName(),
exe: `${productName}.exe`
})
.then(() => console.log(`Installers created in ${outputDir}`))
.catch(e => {
console.error(`Error packaging: ${e}`)
process.exit(1)
})
}

View file

@ -4,10 +4,9 @@
const path = require('path')
const cp = require('child_process')
const distInfo = require('./dist-info')
const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'package.json'))
const distPath = path.join(projectRoot, 'dist', `${appPackage.productName}-${process.platform}-x64`)
const distPath = distInfo.getDistPath()
let binaryPath = ''
if (process.platform === 'darwin') {

38
webpack.common.js Normal file
View file

@ -0,0 +1,38 @@
'use strict'
const path = require('path')
module.exports = {
entry: [
'./src/index'
],
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'build'),
libraryTarget: 'commonjs2'
},
module: {
loaders: [
{
test: /\.tsx?$/,
loaders: ['babel', 'ts'],
include: path.join(__dirname, 'src')
}
]
},
resolve: {
extensions: ['', '.js', '.ts', '.tsx'],
packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
},
target: 'electron',
externals: function (context, request, callback) {
try {
// Attempt to resolve the module via Node
require.resolve(request)
callback(null, request)
} catch (e) {
// Node couldn't find it, so it must be user-aliased
callback()
}
}
}

View file

@ -1,56 +0,0 @@
var path = require('path')
var webpack = require('webpack')
var webpackTargetElectronRenderer = require('webpack-target-electron-renderer')
var config = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr',
'./src/index'
],
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'build'),
libraryTarget: 'commonjs2',
publicPath: 'http://localhost:3000/build/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
// TODO: This is obviously wrong for production builds.
__DEV__: true,
'process.env': {
NODE_ENV: JSON.stringify('development')
}
})
],
module: {
loaders: [
{
test: /\.tsx?$/,
loaders: ['babel', 'ts'],
include: path.join(__dirname, 'src')
}
]
},
resolve: {
extensions: ['', '.js', '.ts', '.tsx'],
packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
},
target: 'electron',
externals: function (context, request, callback) {
try {
// Attempt to resolve the module via Node
require.resolve(request)
callback(null, request)
} catch (e) {
// Node couldn't find it, so it must be user-aliased
callback()
}
}
}
config.target = webpackTargetElectronRenderer(config)
module.exports = config

35
webpack.development.js Normal file
View file

@ -0,0 +1,35 @@
'use strict'
const common = require('./webpack.common')
const webpack = require('webpack')
const webpackTargetElectronRenderer = require('webpack-target-electron-renderer')
const config = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr',
...common.entry
],
output: {
filename: common.output.filename,
path: common.output.path,
libraryTarget: common.output.libraryTarget,
publicPath: 'http://localhost:3000/build/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
__DEV__: true
})
],
module: common.module,
resolve: common.resolve,
target: 'electron',
externals: common.externals
}
config.target = webpackTargetElectronRenderer(config)
module.exports = config

27
webpack.production.js Normal file
View file

@ -0,0 +1,27 @@
'use strict'
const common = require('./webpack.common')
const webpack = require('webpack')
const webpackTargetElectronRenderer = require('webpack-target-electron-renderer')
const config = {
devtool: 'cheap-module-source-map',
entry: common.entry,
output: common.output,
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(true),
new webpack.DefinePlugin({
__DEV__: false
})
],
module: common.module,
resolve: common.resolve,
target: common.target,
externals: common.externals
}
config.target = webpackTargetElectronRenderer(config)
module.exports = config