Merge pull request #10172 from electron/publish-prebuilt

publish to npm directly from electron repo
This commit is contained in:
Vanessa Yuen 2017-08-08 13:59:37 -04:00 committed by GitHub
commit aac9ea1371
9 changed files with 360 additions and 25 deletions

View file

@ -15,36 +15,71 @@ editor](https://github.com/atom/atom) and many other [apps](https://electron.ato
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
announcements.
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
This project adheres to the Contributor Covenant
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable
behavior to electron@github.com.
behavior to [electron@github.com](mailto:electron@github.com).
## Downloads
## Installation
To install prebuilt Electron binaries, use
[`npm`](https://docs.npmjs.com/):
To install prebuilt Electron binaries, use [`npm`](https://docs.npmjs.com/).
The preferred method is to install Electron as a development dependency in your
app:
```sh
# Install as a development dependency
npm install electron --save-dev
# Install the `electron` command globally in your $PATH
npm install electron -g
npm install electron --save-dev --save-exact
```
See the [releases page](https://github.com/electron/electron/releases) for
prebuilt binaries, debug symbols, and more.
The `--save-exact` flag is recommended as Electron does not follow semantic
versioning. For info on how to manage Electron versions in your apps, see
[Electron versioning](https://electron.atom.io/docs/tutorial/electron-versioning/).
For more installation options and troubleshooting tips, see
[installation](https://electron.atom.io/docs/tutorial/installation/).
## Quick Start
Clone and run the
[electron/electron-quick-start](https://github.com/electron/electron-quick-start)
repository to see a minimal Electron app in action:
```
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start
```
## Resources for Learning Electron
- [electron.atom.io/docs](http://electron.atom.io/docs) - all of Electron's documentation
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - a very basic starter Electron app
- [electron.atom.io/community/#boilerplates](http://electron.atom.io/community/#boilerplates) - sample starter apps created by the community
- [electron/simple-samples](https://github.com/electron/simple-samples) - small applications with ideas for taking them further
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - an Electron app that teaches you how to use Electron
- [hokein/electron-sample-apps](https://github.com/hokein/electron-sample-apps) - small demo apps for the various Electron APIs
## Programmatic usage
Most people use Electron from the command line, but if you require `electron` inside
your **Node app** (not your Electron app) it will return the file path to the
binary. Use this to spawn Electron from Node scripts:
```javascript
const electron = require('electron')
const proc = require('child_process')
// will print something similar to /Users/maf/.../Electron
console.log(electron)
// spawn Electron
const child = proc.spawn(electron)
```
### Mirrors
- [China](https://npm.taobao.org/mirrors/electron)
## Documentation
Guides and the API reference are located in the
[docs](https://github.com/electron/electron/tree/master/docs) directory. It also
contains documents describing how to build and contribute to Electron.
## Documentation Translations
- [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR)
@ -60,11 +95,6 @@ contains documents describing how to build and contribute to Electron.
- [French](https://github.com/electron/electron/tree/master/docs-translations/fr-FR)
- [Indonesian](https://github.com/electron/electron/tree/master/docs-translations/id)
## Quick Start
Clone and run the [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
repository to see a minimal Electron app in action.
## Community
You can ask questions and interact with the community in the following

View file

@ -0,0 +1,56 @@
# Installation
> Tips for installing Electron
To install prebuilt Electron binaries, use [`npm`](https://docs.npmjs.com/).
The preferred method is to install Electron as a development dependency in your
app:
```sh
npm install electron --save-dev --save-exact
```
The `--save-exact` flag is recommended as Electron does not follow semantic
versioning. See the
[versioning doc](https://electron.atom.io/docs/tutorial/electron-versioning/)
for info on how to manage Electron versions in your apps.
## Global Installation
You can also install the `electron` command globally in your `$PATH`:
```sh
npm install electron -g
```
## Customization
If you want to change the architecture that is downloaded (e.g., `ia32` on an
`x64` machine), you can use the `--arch` flag with npm install or set the
`npm_config_arch` environment variable:
```shell
npm install --arch=ia32 electron
```
## Proxies
If you need to use an HTTP proxy you can [set these environment variables](https://github.com/request/request/tree/f0c4ec061141051988d1216c24936ad2e7d5c45d#controlling-proxy-behaviour-using-environment-variables).
## Troubleshooting
When running `npm install electron`, some users occasionally encounter
installation errors.
In almost all cases, these errors are the result of network problems and not
actual issues with the `electron` npm package. Errors like `ELIFECYCLE`,
`EAI_AGAIN`, `ECONNRESET`, and `ETIMEDOUT` are all indications of such
network problems. The best resolution is to try switching networks, or
just wait a bit and try installing again.
You can also attempt to download Electron directly from
[electron/electron/releases](https://github.com/electron/electron/releases)
if installing via `npm` is failing.
If you need to force a re-download of the asset and the SHASUM file set the
`force_no_cache` enviroment variable to `true`.

10
npm/cli.js Executable file
View file

@ -0,0 +1,10 @@
#!/usr/bin/env node
var electron = require('./')
var proc = require('child_process')
var child = proc.spawn(electron, process.argv.slice(2), {stdio: 'inherit'})
child.on('close', function (code) {
process.exit(code)
})

10
npm/index.js Normal file
View file

@ -0,0 +1,10 @@
var fs = require('fs')
var path = require('path')
var pathFile = path.join(__dirname, 'path.txt')
if (fs.existsSync(pathFile)) {
module.exports = path.join(__dirname, fs.readFileSync(pathFile, 'utf-8'))
} else {
throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
}

65
npm/install.js Executable file
View file

@ -0,0 +1,65 @@
#!/usr/bin/env node
// maintainer note - x.y.z-ab version in package.json -> x.y.z
var version = require('./package').version.replace(/-.*/, '')
var fs = require('fs')
var os = require('os')
var path = require('path')
var extract = require('extract-zip')
var download = require('electron-download')
var installedVersion = null
try {
installedVersion = fs.readFileSync(path.join(__dirname, 'dist', 'version'), 'utf-8').replace(/^v/, '')
} catch (ignored) {
// do nothing
}
var platformPath = getPlatformPath()
if (installedVersion === version && fs.existsSync(path.join(__dirname, platformPath))) {
process.exit(0)
}
// downloads if not cached
download({
cache: process.env.electron_config_cache,
version: version,
platform: process.env.npm_config_platform,
arch: process.env.npm_config_arch,
strictSSL: process.env.npm_config_strict_ssl === 'true',
force: process.env.force_no_cache === 'true',
quiet: ['info', 'verbose', 'silly', 'http'].indexOf(process.env.npm_config_loglevel) === -1
}, extractFile)
// unzips and makes path.txt point at the correct executable
function extractFile (err, zipPath) {
if (err) return onerror(err)
extract(zipPath, {dir: path.join(__dirname, 'dist')}, function (err) {
if (err) return onerror(err)
fs.writeFile(path.join(__dirname, 'path.txt'), platformPath, function (err) {
if (err) return onerror(err)
})
})
}
function onerror (err) {
throw err
}
function getPlatformPath () {
var platform = process.env.npm_config_platform || os.platform()
switch (platform) {
case 'darwin':
return 'dist/Electron.app/Contents/MacOS/Electron'
case 'freebsd':
case 'linux':
return 'dist/electron'
case 'win32':
return 'dist/electron.exe'
default:
throw new Error('Electron builds are not available on platform: ' + platform)
}
}

26
npm/package.json Normal file
View file

@ -0,0 +1,26 @@
{
"scripts": {
"cache-clean": "rm -rf ~/.electron && rm -rf dist",
"postinstall": "node install.js",
"pretest": "npm run cache-clean",
"test": "standard"
},
"bin": {
"electron": "cli.js"
},
"main": "index.js",
"types": "electron.d.ts",
"dependencies": {
"@types/node": "^7.0.18",
"electron-download": "^3.0.1",
"extract-zip": "^1.0.3"
},
"devDependencies": {
"home-path": "^0.1.1",
"path-exists": "^2.0.0",
"standard": "^5.4.1"
},
"directories": {
"test": "test"
}
}

View file

@ -1,17 +1,22 @@
{
"name": "electron",
"version": "1.7.5",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"asar": "^0.11.0",
"browserify": "^13.1.0",
"check-for-leaks": "^1.0.2",
"dotenv-safe": "^4.0.4",
"electabul": "~0.0.4",
"electron-docs-linter": "^2.3.3",
"electron-typescript-definitions": "^1.2.7",
"github": "^9.2.0",
"husky": "^0.14.3",
"request": "^2.68.0",
"standard": "^8.4.0",
"standard-markdown": "^4.0.0"
"standard-markdown": "^4.0.0",
"temp": "^0.8.3"
},
"standard": {
"ignore": [
@ -43,11 +48,17 @@
"create-api-json": "electron-docs-linter docs --outfile=out/electron-api.json --version=$npm_package_version",
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --in=out/electron-api.json --out=out/electron.d.ts",
"preinstall": "node -e 'process.exit(0)'",
"publish-to-npm": "node ./script/publish-to-npm.js",
"prepack": "check-for-leaks",
"prepush": "check-for-leaks",
"release": "./script/upload.py -p",
"repl": "python ./script/start.py --interactive",
"start": "python ./script/start.py",
"test": "python ./script/test.py"
}
},
"license": "MIT",
"author": "Electron Community",
"keywords": [
"electron"
]
}

125
script/publish-to-npm.js Normal file
View file

@ -0,0 +1,125 @@
const temp = require('temp')
const fs = require('fs')
const path = require('path')
const childProcess = require('child_process')
const GitHubApi = require('github')
const request = require('request')
const assert = require('assert')
const rootPackageJson = require('../package.json')
const github = new GitHubApi({
// debug: true,
headers: { 'User-Agent': 'electron-npm-publisher' },
followRedirects: false
})
let tempDir
temp.track() // track and cleanup files at exit
const files = [
'cli.js',
'index.js',
'install.js',
'package.json',
'README.md'
]
const jsonFields = [
'name',
'version',
'repository',
'description',
'license',
'author',
'keywords'
]
let npmTag = ''
new Promise((resolve, reject) => {
temp.mkdir('electron-npm', (err, dirPath) => {
if (err) {
reject(err)
} else {
resolve(dirPath)
}
})
})
.then((dirPath) => {
tempDir = dirPath
// copy files from `/npm` to temp directory
files.forEach((name) => {
fs.writeFileSync(
path.join(tempDir, name),
fs.readFileSync(path.join(__dirname, '..', name === 'README.md' ? '' : 'npm', name))
)
})
// copy from root package.json to temp/package.json
const packageJson = require(path.join(tempDir, 'package.json'))
jsonFields.forEach((fieldName) => {
packageJson[fieldName] = rootPackageJson[fieldName]
})
fs.writeFileSync(
path.join(tempDir, 'package.json'),
JSON.stringify(packageJson, null, 2)
)
return github.repos.getReleases({
owner: 'electron',
repo: 'electron'
})
})
.then((releases) => {
// download electron.d.ts from release
const release = releases.data.find(
(release) => release.tag_name === `v${rootPackageJson.version}`
)
if (!release) {
throw new Error(`cannot find release with tag v${rootPackageJson.version}`)
}
return release
})
.then((release) => {
const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts')
if (!tsdAsset) {
throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`)
}
return new Promise((resolve, reject) => {
request.get({
url: tsdAsset.url,
headers: {
'accept': 'application/octet-stream',
'user-agent': 'electron-npm-publisher'
}
}, (err, response, body) => {
if (err || response.statusCode !== 200) {
reject(err || new Error('Cannot download electron.d.ts'))
} else {
fs.writeFileSync(path.join(tempDir, 'electron.d.ts'), body)
resolve(release)
}
})
})
})
.then((release) => {
npmTag = release.prerelease ? 'beta' : 'latest'
})
.then(() => childProcess.execSync('npm pack', { cwd: tempDir }))
.then(() => {
// test that the package can install electron prebuilt from github release
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`)
return new Promise((resolve, reject) => {
childProcess.execSync(`npm install ${tarballPath} --force --silent`, {
env: Object.assign({}, process.env, { electron_config_cache: tempDir }),
cwd: tempDir
})
const checkVersion = childProcess.execSync(`${path.join(tempDir, 'node_modules', '.bin', 'electron')} -v`)
assert.strictEqual(checkVersion.toString().trim(), `v${rootPackageJson.version}`)
resolve(tarballPath)
})
})
.then((tarballPath) => childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag}`))
.catch((err) => {
console.error(`Error: ${err}`)
process.exit(1)
})

View file

@ -72,6 +72,8 @@ def main():
# Press the publish button.
publish_release(github, release['id'])
# TODO: run publish-to-npm script here
# Do not upload other files when passed "-p".
return