feat: npm install execute OS specific install script
This commit is contained in:
parent
23e0d473e9
commit
61fe3d3d8b
@ -1,154 +0,0 @@
|
|||||||
#######################################################################
|
|
||||||
# Wiki.js - CONFIGURATION #
|
|
||||||
#######################################################################
|
|
||||||
# Full explanation + examples in the documentation:
|
|
||||||
# https://docs.requarks.io/wiki/install
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Title of this site
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
title: $(WIKI_TITLE)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Full public path to the site, without the trailing slash
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
host: $(WIKI_HOST)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Port the main server should listen to (80 by default)
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
port: $(PORT)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Data Directories
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
paths:
|
|
||||||
repo: ./repo
|
|
||||||
data: ./data
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Upload Limits
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# In megabytes (MB)
|
|
||||||
|
|
||||||
uploads:
|
|
||||||
maxImageFileSize: 3
|
|
||||||
maxOtherFileSize: 100
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Site Language
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Possible values: en, es, fr, ko, ru or zh
|
|
||||||
|
|
||||||
lang: $(WIKI_LANG)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Site Authentication
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
public: $(WIKI_PUBLIC)
|
|
||||||
|
|
||||||
auth:
|
|
||||||
defaultReadAccess: false
|
|
||||||
local:
|
|
||||||
enabled: true
|
|
||||||
google:
|
|
||||||
enabled: false
|
|
||||||
clientId: GOOGLE_CLIENT_ID
|
|
||||||
clientSecret: GOOGLE_CLIENT_SECRET
|
|
||||||
microsoft:
|
|
||||||
enabled: false
|
|
||||||
clientId: MS_APP_ID
|
|
||||||
clientSecret: MS_APP_SECRET
|
|
||||||
facebook:
|
|
||||||
enabled: false
|
|
||||||
clientId: FACEBOOK_APP_ID
|
|
||||||
clientSecret: FACEBOOK_APP_SECRET
|
|
||||||
github:
|
|
||||||
enabled: false
|
|
||||||
clientId: GITHUB_CLIENT_ID
|
|
||||||
clientSecret: GITHUB_CLIENT_SECRET
|
|
||||||
slack:
|
|
||||||
enabled: false
|
|
||||||
clientId: SLACK_CLIENT_ID
|
|
||||||
clientSecret: SLACK_CLIENT_SECRET
|
|
||||||
ldap:
|
|
||||||
enabled: false
|
|
||||||
url: ldap://serverhost:389
|
|
||||||
bindDn: cn='root'
|
|
||||||
bindCredentials: BIND_PASSWORD
|
|
||||||
searchBase: o=users,o=example.com
|
|
||||||
searchFilter: (uid={{username}})
|
|
||||||
tlsEnabled: false
|
|
||||||
tlsCertPath: C:\example\root_ca_cert.crt
|
|
||||||
azure:
|
|
||||||
enabled: false
|
|
||||||
clientID: APP_ID
|
|
||||||
clientSecret: APP_SECRET_KEY
|
|
||||||
resource: '00000002-0000-0000-c000-000000000000'
|
|
||||||
tenant: 'YOUR_TENANT.onmicrosoft.com'
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Secret key to use when encrypting sessions
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Use a long and unique random string (256-bit keys are perfect!)
|
|
||||||
|
|
||||||
sessionSecret: $(WIKI_SESSION_KEY)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Database Connection String
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
db: $(MONGODB_URI)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Git Connection Info
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
git:
|
|
||||||
url: $(WIKI_GIT_URL)
|
|
||||||
branch: $(WIKI_GIT_BRANCH)
|
|
||||||
auth:
|
|
||||||
|
|
||||||
# Type: basic or ssh
|
|
||||||
type: basic
|
|
||||||
|
|
||||||
# Only for Basic authentication:
|
|
||||||
username: $(WIKI_GIT_USERNAME)
|
|
||||||
password: $(WIKI_GIT_PASSWORD)
|
|
||||||
|
|
||||||
# Only for SSH authentication:
|
|
||||||
privateKey: /etc/wiki/keys/git.pem
|
|
||||||
|
|
||||||
sslVerify: true
|
|
||||||
|
|
||||||
# Default email to use as commit author
|
|
||||||
serverEmail: $(WIKI_SERVER_EMAIL)
|
|
||||||
|
|
||||||
# Whether to use user email as author in commits
|
|
||||||
showUserEmail: $(WIKI_SHOW_USER_EMAIL)
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# Features
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# You can enable / disable specific features below
|
|
||||||
|
|
||||||
features:
|
|
||||||
linebreaks: true
|
|
||||||
mathjax: true
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
# External Logging
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
externalLogging:
|
|
||||||
bugsnag: false
|
|
||||||
loggly: false
|
|
||||||
papertrail: false
|
|
||||||
rollbar: false
|
|
||||||
sentry: false
|
|
||||||
|
|
279
npm/install.js
279
npm/install.js
@ -5,274 +5,21 @@
|
|||||||
// Installation Script
|
// Installation Script
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
const Promise = require('bluebird')
|
|
||||||
const _ = require('lodash')
|
|
||||||
const colors = require('colors/safe')
|
|
||||||
const exec = require('execa')
|
|
||||||
const fs = Promise.promisifyAll(require('fs-extra'))
|
|
||||||
const https = require('follow-redirects').https
|
|
||||||
const inquirer = require('inquirer')
|
|
||||||
const os = require('os')
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const pm2 = Promise.promisifyAll(require('pm2'))
|
const spawn = require('child_process').spawn
|
||||||
const tar = require('tar')
|
|
||||||
const zlib = require('zlib')
|
|
||||||
|
|
||||||
const installDir = path.resolve(__dirname, '../..')
|
const installDir = path.resolve(__dirname, '../..')
|
||||||
const isContainerBased = (process.env.WIKI_JS_HEROKU || process.env.WIKI_JS_DOCKER)
|
const cmd = (process.platform !== 'win32')
|
||||||
let installMode = 'new'
|
? 'curl -s -S -o- https://wiki.js.org/install.sh | bash'
|
||||||
|
: `PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://wiki.js.org/install.ps1'))"`
|
||||||
|
|
||||||
// =====================================================
|
console.info(`Executing installation script for ${process.platform} platform...`)
|
||||||
// INSTALLATION TASKS
|
|
||||||
// =====================================================
|
|
||||||
|
|
||||||
const tasks = {
|
let inst = spawn(cmd, [], {
|
||||||
/**
|
cwd: installDir,
|
||||||
* Stop and delete existing instances
|
env: process.env,
|
||||||
*/
|
shell: true,
|
||||||
stopAndDeleteInstances() {
|
stdio: 'inherit',
|
||||||
ora.text = 'Looking for running instances...'
|
detached: true
|
||||||
return pm2.connectAsync().then(() => {
|
|
||||||
return pm2.describeAsync('wiki').then(() => {
|
|
||||||
ora.text = 'Stopping and deleting process from pm2...'
|
|
||||||
return pm2.deleteAsync('wiki')
|
|
||||||
}).catch(err => { // eslint-disable-line handle-callback-err
|
|
||||||
return true
|
|
||||||
}).finally(() => {
|
|
||||||
pm2.disconnect()
|
|
||||||
})
|
|
||||||
}).catch(err => { // eslint-disable-line handle-callback-err
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Check for sufficient memory
|
|
||||||
*/
|
|
||||||
checkRequirements() {
|
|
||||||
ora.text = 'Checking system requirements...'
|
|
||||||
if (os.totalmem() < 1000 * 1000 * 768) {
|
|
||||||
return Promise.reject(new Error('Not enough memory to install dependencies. Minimum is 768 MB.'))
|
|
||||||
} else {
|
|
||||||
return Promise.resolve(true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Install via local tarball if present
|
|
||||||
*/
|
|
||||||
installFromLocal() {
|
|
||||||
let hasTarball = true
|
|
||||||
let tbPath = path.join(installDir, 'wiki-js.tar.gz')
|
|
||||||
return fs.accessAsync(tbPath)
|
|
||||||
.catch(err => { // eslint-disable-line handle-callback-err
|
|
||||||
hasTarball = false
|
|
||||||
}).then(() => {
|
|
||||||
if (hasTarball) {
|
|
||||||
ora.text = 'Local tarball found. Extracting...'
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fs.createReadStream(tbPath).pipe(zlib.createGunzip())
|
|
||||||
.pipe(tar.extract({ cwd: installDir }))
|
|
||||||
.on('error', err => reject(err))
|
|
||||||
.on('end', () => {
|
|
||||||
ora.text = 'Tarball extracted successfully.'
|
|
||||||
resolve(tasks.installDependencies())
|
|
||||||
isContainerBased && console.info('>> Installing dependencies...')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Install from GitHub release download
|
|
||||||
*/
|
|
||||||
installFromRemote() {
|
|
||||||
// Fetch version from npm package
|
|
||||||
return fs.readJsonAsync('package.json').then((packageObj) => {
|
|
||||||
let versionGet = _.chain(packageObj.version).split('.').take(4).join('.')
|
|
||||||
let remoteURLApp = _.replace('https://github.com/Requarks/wiki/releases/download/v{0}/wiki-js.tar.gz', '{0}', versionGet)
|
|
||||||
let remoteURLDeps = _.replace('https://github.com/Requarks/wiki/releases/download/v{0}/node_modules.tar.gz', '{0}', versionGet)
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Fetch app tarball
|
|
||||||
ora.text = 'Looking for app package...'
|
|
||||||
https.get(remoteURLApp, resp => {
|
|
||||||
if (resp.statusCode !== 200) {
|
|
||||||
return reject(new Error('Remote file not found'))
|
|
||||||
}
|
|
||||||
ora.text = 'Remote app tarball found. Downloading...'
|
|
||||||
isContainerBased && console.info('>> Extracting app to ' + installDir)
|
|
||||||
|
|
||||||
// Extract app tarball
|
|
||||||
resp.pipe(zlib.createGunzip())
|
|
||||||
.pipe(tar.extract({ cwd: installDir }))
|
|
||||||
.on('error', err => reject(err))
|
|
||||||
.on('end', () => {
|
|
||||||
ora.text = 'App tarball extracted successfully.'
|
|
||||||
resolve(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).then(() => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Fetch deps tarball
|
|
||||||
ora.text = 'Looking for dependencies package...'
|
|
||||||
https.get(remoteURLDeps, resp => {
|
|
||||||
if (resp.statusCode !== 200) {
|
|
||||||
return reject(new Error('Remote file not found'))
|
|
||||||
}
|
|
||||||
ora.text = 'Remote dependencies tarball found. Downloading...'
|
|
||||||
isContainerBased && console.info('>> Extracting dependencies to ' + installDir)
|
|
||||||
|
|
||||||
// Extract deps tarball
|
|
||||||
resp.pipe(zlib.createGunzip())
|
|
||||||
.pipe(tar.extract({ cwd: path.join(installDir, 'node_modules') }))
|
|
||||||
.on('error', err => reject(err))
|
|
||||||
.on('end', () => {
|
|
||||||
ora.text = 'Dependencies tarball extracted successfully.'
|
|
||||||
resolve(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Create default config.yml file if new installation
|
|
||||||
*/
|
|
||||||
ensureConfigFile() {
|
|
||||||
return fs.accessAsync(path.join(installDir, 'config.yml')).then(() => {
|
|
||||||
// Is Upgrade
|
|
||||||
ora.text = 'Existing config.yml found. Upgrade mode.'
|
|
||||||
installMode = 'upgrade'
|
|
||||||
return true
|
|
||||||
}).catch(err => {
|
|
||||||
// Is New Install
|
|
||||||
if (err.code === 'ENOENT') {
|
|
||||||
ora.text = 'First-time install, creating a new config.yml...'
|
|
||||||
installMode = 'new'
|
|
||||||
let sourceConfigFile = path.join(installDir, 'config.sample.yml')
|
|
||||||
if (process.env.WIKI_JS_HEROKU || process.env.WIKI_JS_DOCKER) {
|
|
||||||
sourceConfigFile = path.join(__dirname, 'configs/config.passive.yml')
|
|
||||||
}
|
|
||||||
return fs.copyAsync(sourceConfigFile, path.join(installDir, 'config.yml'))
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Install npm dependencies
|
|
||||||
*/
|
|
||||||
installDependencies() {
|
|
||||||
ora.text = 'Installing Wiki.js npm dependencies...'
|
|
||||||
return exec.stdout('npm', ['install', '--only=production', '--no-optional'], {
|
|
||||||
cwd: installDir
|
|
||||||
}).then(results => {
|
|
||||||
ora.text = 'Wiki.js npm dependencies installed successfully.'
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
startConfigurationWizard() {
|
|
||||||
ora.succeed('Installation succeeded.')
|
|
||||||
if (process.env.WIKI_JS_HEROKU) {
|
|
||||||
console.info('> Wiki.js has been installed and is configured to use Heroku configuration.')
|
|
||||||
return true
|
|
||||||
} else if (process.env.WIKI_JS_DOCKER) {
|
|
||||||
console.info('Docker environment detected. Skipping setup wizard auto-start.')
|
|
||||||
return true
|
|
||||||
} else if (process.stdout.isTTY) {
|
|
||||||
if (installMode === 'upgrade') {
|
|
||||||
console.info(colors.yellow('\n!!! IMPORTANT !!!'))
|
|
||||||
console.info(colors.yellow('Running the configuration wizard is optional but recommended after an upgrade to ensure your config file is using the latest available settings.'))
|
|
||||||
console.info(colors.yellow('Note that the contents of your config file will be displayed during the configuration wizard. It is therefor highly recommended to run the wizard on a non-publicly accessible port or skip this step completely.\n'))
|
|
||||||
}
|
|
||||||
inquirer.prompt([{
|
|
||||||
type: 'list',
|
|
||||||
name: 'action',
|
|
||||||
message: 'Continue with configuration wizard?',
|
|
||||||
default: 'default',
|
|
||||||
choices: [
|
|
||||||
{ name: 'Yes, run configuration wizard on port 3000 (recommended)', value: 'default', short: 'Yes' },
|
|
||||||
{ name: 'Yes, run configuration wizard on a custom port...', value: 'custom', short: 'Yes' },
|
|
||||||
{ name: 'No, I\'ll configure the config file manually', value: 'exit', short: 'No' }
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
type: 'input',
|
|
||||||
name: 'customport',
|
|
||||||
message: 'Custom port to use:',
|
|
||||||
default: 3000,
|
|
||||||
validate: (val) => {
|
|
||||||
val = _.toNumber(val)
|
|
||||||
return (_.isNumber(val) && val > 0) ? true : 'Invalid Port!'
|
|
||||||
},
|
|
||||||
when: (ans) => {
|
|
||||||
return ans.action === 'custom'
|
|
||||||
}
|
|
||||||
}]).then((ans) => {
|
|
||||||
switch (ans.action) {
|
|
||||||
case 'default':
|
|
||||||
console.info(colors.bold.cyan('> Browse to http://your-server:3000/ to configure your wiki! (Replaced your-server with the hostname or IP of your server!)'))
|
|
||||||
ora = require('ora')({ text: 'I\'ll wait until you\'re done ;)', color: 'yellow', spinner: 'pong' }).start()
|
|
||||||
return exec.stdout('node', ['wiki', 'configure'], {
|
|
||||||
cwd: installDir
|
|
||||||
})
|
|
||||||
case 'custom':
|
|
||||||
console.info(colors.bold.cyan('> Browse to http://your-server:' + ans.customport + '/ to configure your wiki! (Replaced your-server with the hostname or IP of your server!)'))
|
|
||||||
ora = require('ora')({ text: 'I\'ll wait until you\'re done ;)', color: 'yellow', spinner: 'pong' }).start()
|
|
||||||
return exec.stdout('node', ['wiki', 'configure', ans.customport], {
|
|
||||||
cwd: installDir
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
console.info(colors.bold.cyan('\n> You can run the configuration wizard using command:') + colors.bold.white(' node wiki configure') + colors.bold.cyan('.\n> Then start Wiki.js using command: ') + colors.bold.white('node wiki start'))
|
|
||||||
return Promise.delay(7000).then(() => {
|
|
||||||
process.exit(0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).then(() => {
|
|
||||||
ora.succeed(colors.bold.green('Wiki.js has been configured successfully. It is now starting up and should be accessible very soon!'))
|
|
||||||
return Promise.delay(3000).then(() => {
|
|
||||||
console.info('npm is finishing... please wait...')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.info(colors.cyan('[WARNING] Non-interactive terminal detected. You must manually start the configuration wizard using the command: node wiki configure'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// INSTALL SEQUENCE
|
|
||||||
// =====================================================
|
|
||||||
|
|
||||||
if (!isContainerBased) {
|
|
||||||
console.info(colors.yellow(
|
|
||||||
' __ __ _ _ _ _ \n' +
|
|
||||||
'/ / /\\ \\ (_) | _(_) (_)___ \n' +
|
|
||||||
'\\ \\/ \\/ / | |/ / | | / __| \n' +
|
|
||||||
' \\ /\\ /| | <| |_ | \\__ \\ \n' +
|
|
||||||
' \\/ \\/ |_|_|\\_\\_(_)/ |___/ \n' +
|
|
||||||
' |__/\n'))
|
|
||||||
} else {
|
|
||||||
console.info('> WIKI.JS [Installing...]')
|
|
||||||
}
|
|
||||||
|
|
||||||
let ora = require('ora')({ text: 'Initializing...', spinner: 'dots12' }).start()
|
|
||||||
|
|
||||||
Promise.join(
|
|
||||||
tasks.stopAndDeleteInstances(),
|
|
||||||
tasks.checkRequirements()
|
|
||||||
).then(() => {
|
|
||||||
isContainerBased && console.info('>> Fetching tarball...')
|
|
||||||
return tasks.installFromLocal().then(succeeded => {
|
|
||||||
return (!succeeded) ? tasks.installFromRemote() : true
|
|
||||||
})
|
|
||||||
}).then(() => {
|
|
||||||
isContainerBased && console.info('>> Creating config file...')
|
|
||||||
return tasks.ensureConfigFile()
|
|
||||||
}).then(() => {
|
|
||||||
return tasks.startConfigurationWizard()
|
|
||||||
}).catch(err => {
|
|
||||||
isContainerBased && console.error(err)
|
|
||||||
ora.fail(err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
inst.unref()
|
||||||
|
1328
npm/package-lock.json
generated
1328
npm/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wiki.js",
|
"name": "wiki.js",
|
||||||
"version": "1.0.5",
|
"version": "1.0.5-rev.1",
|
||||||
"description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
|
"description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
|
||||||
"main": "install.js",
|
"main": "install.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -28,16 +28,5 @@
|
|||||||
"url": "https://github.com/Requarks/wiki/issues"
|
"url": "https://github.com/Requarks/wiki/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Requarks/wiki#readme",
|
"homepage": "https://github.com/Requarks/wiki#readme",
|
||||||
"dependencies": {
|
"dependencies": {}
|
||||||
"bluebird": "~3.5.0",
|
|
||||||
"colors": "~1.1.2",
|
|
||||||
"execa": "~0.7.0",
|
|
||||||
"follow-redirects": "~1.2.4",
|
|
||||||
"fs-extra": "~3.0.1",
|
|
||||||
"inquirer": "~3.1.1",
|
|
||||||
"lodash": "~4.17.4",
|
|
||||||
"ora": "~1.3.0",
|
|
||||||
"pm2": "~2.5.0",
|
|
||||||
"tar": "~3.1.5"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user