Skip to content

Commit

Permalink
feat: validate config using JSON schema
Browse files Browse the repository at this point in the history
Close #1292, Close #1290
  • Loading branch information
develar committed Feb 22, 2017
1 parent 580eeaa commit d65f8c3
Show file tree
Hide file tree
Showing 34 changed files with 881 additions and 217 deletions.
3 changes: 1 addition & 2 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ dependencies:
- sudo apt-get install git-lfs
- ssh [email protected] git-lfs-authenticate $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME.git download
- git lfs pull
- docker run --rm --env-file ./test/docker-env.list -v ${PWD}:/project -v ~/.electron:/root/.electron -v ~/.cache/electron-builder:/root/.cache/electron-builder electronuserland/electron-builder:wine /bin/bash -c "node ./test/vendor/yarn.js --link-duplicates --pure-lockfile && node ./test/vendor/yarn.js test"
- mkdir -p $CIRCLE_TEST_REPORTS/reports
- mv -f test/test-report.xml $CIRCLE_TEST_REPORTS/reports/test-report.xml
- docker run --rm --env-file ./test/docker-env.list -v ${PWD}:/project -v ~/.electron:/root/.electron -v ~/.cache/electron-builder:/root/.cache/electron-builder electronuserland/electron-builder:wine /bin/bash -c "node ./test/vendor/yarn.js --link-duplicates --pure-lockfile && node ./test/vendor/yarn.js test" && mv -f test/test-report.xml $CIRCLE_TEST_REPORTS/reports/test-report.xml

test:
override:
Expand Down
2 changes: 1 addition & 1 deletion docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ On Windows works only if [nsis.perMachine](https://github.com/electron-userland/
| category | <a name="LinuxBuildOptions-category"></a>The [application category](https://specifications.freedesktop.org/menu-spec/latest/apa.html#main-category-registry).
| packageCategory | <a name="LinuxBuildOptions-packageCategory"></a>The [package category](https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Section). Not applicable for AppImage.
| description | <a name="LinuxBuildOptions-description"></a>As [description](#AppMetadata-description) from application package.json, but allows you to specify different for Linux.
| target | <a name="LinuxBuildOptions-target"></a><p>Target package type: list of <code>AppImage</code>, <code>snap</code>, <code>deb</code>, <code>rpm</code>, <code>freebsd</code>, <code>pacman</code>, <code>p5p</code>, <code>apk</code>, <code>7z</code>, <code>zip</code>, <code>tar.xz</code>, <code>tar.lz</code>, <code>tar.gz</code>, <code>tar.bz2</code>, <code>dir</code>. Defaults to <code>AppImage</code>.</p> <p>The most effective [xz](https://en.wikipedia.org/wiki/Xz) compression format used by default.</p>
| target | <a name="LinuxBuildOptions-target"></a><p>Target package type: list of <code>AppImage</code>, <code>snap</code>, <code>deb</code>, <code>rpm</code>, <code>freebsd</code>, <code>pacman</code>, <code>p5p</code>, <code>apk</code>, <code>7z</code>, <code>zip</code>, <code>tar.xz</code>, <code>tar.lz</code>, <code>tar.gz</code>, <code>tar.bz2</code>, <code>dir</code>. Defaults to <code>AppImage</code>.</p> <p>The most effective [xz](https://en.wikipedia.org/wiki/Xz) compression format used by default.</p> <p>electron-builder [docker image](https://github.com/electron-userland/electron-builder/wiki/Docker) can be used to build Linux targets on any platform. See [Multi platform build](https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build).</p>
| maintainer | <a name="LinuxBuildOptions-maintainer"></a>The maintainer. Defaults to [author](#AppMetadata-author).
| vendor | <a name="LinuxBuildOptions-vendor"></a>The vendor. Defaults to [author](#AppMetadata-author).
| desktop | <a name="LinuxBuildOptions-desktop"></a>The [Desktop file](https://developer.gnome.org/integration-guide/stable/desktop-files.html.en) entries (name to value).
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"license": "MIT",
"scripts": {
"compile": "ts-babel packages/electron-builder-http packages/electron-builder-core packages/electron-builder-util packages/electron-publish packages/electron-builder packages/electron-builder-squirrel-windows packages/electron-updater packages/electron-publisher-s3 test && node ./test/vendor/yarn.js scheme",
"compile": "ts-babel packages/electron-builder-http packages/electron-builder-core packages/electron-builder-util packages/electron-publish packages/electron-builder packages/electron-builder-squirrel-windows packages/electron-updater packages/electron-publisher-s3 test && node ./test/vendor/yarn.js schema",
"lint": "node test/out/helpers/lint.js",
"pretest": "node ./test/vendor/yarn.js compile && node ./test/vendor/yarn.js lint && node ./test/vendor/yarn.js lint-deps",
"lint-deps": "node ./test/out/helpers/checkDeps.js",
Expand All @@ -18,13 +18,15 @@
"update-deps": "lerna exec -- npm-check-updates --reject 'electron-builder-http,electron-builder-util,electron-builder-core,electron-publish' -a",
"set-versions": "node test/out/helpers/setVersions.js",
"npm-publish": "yarn compile && ./packages/npm-publish.sh && conventional-changelog -p angular -i CHANGELOG.md -s",
"scheme": "typescript-json-schema packages/electron-builder/tsconfig.json Config --out packages/electron-builder/scheme.json",
"schema": "typescript-json-schema packages/electron-builder/tsconfig.json Config --out packages/electron-builder/scheme.json --noExtraProps",
"docs": "jsdoc -R jsdoc/readme.md -c jsdoc/jsdoc.json -d jsdoc/out -P packages/electron-updater/package.json jsdoc/out/electron-updater"
},
"//": "repository must be specified otherwise conventional-changelog will use forked repo (currently cloned)",
"repository": "electron-userland/electron-builder",
"dependencies": {
"7zip-bin": "^2.0.4",
"ajv": "^5.0.2-beta",
"ajv-keywords": "^1.5.1",
"archiver": "^1.3.0",
"asar-electron-builder": "^0.13.5",
"aws-sdk": "^2.17.0",
Expand Down Expand Up @@ -58,6 +60,7 @@
"yargs": "^6.6.0"
},
"devDependencies": {
"@develar/typescript-json-schema": "0.9.1",
"@types/electron": "^1.4.32",
"@types/ini": "^1.3.29",
"@types/jest": "^18.1.1",
Expand All @@ -76,8 +79,8 @@
"depcheck": "^0.6.7",
"docdash": "https://github.com/develar/docdash.git",
"electron-download-tf": "3.2.0",
"jest-cli": "^19.0.0",
"jest-environment-node-debug": "^1.0.0",
"jest-cli": "^19.0.1",
"jest-environment-node-debug": "^2.0.0",
"jest-junit-reporter": "^1.0.1",
"jsdoc": "^3.4.3",
"lerna": "2.0.0-beta.37",
Expand Down
9 changes: 6 additions & 3 deletions packages/electron-builder-http/src/publishOptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export type PublishProvider = "github" | "bintray" | "s3" | "generic"

export type Publish = string | Array<string> | PublishConfiguration | GithubOptions | S3Options | BintrayOptions | GenericServerOptions | Array<PublishConfiguration> | Array<GithubOptions> | Array<S3Options> | Array<GenericServerOptions> | Array<BintrayOptions> | null

/**
### `publish`
Expand Down Expand Up @@ -149,4 +147,9 @@ export interface BintrayOptions extends PublishConfiguration {
The Bintray user account. Used in cases where the owner is an organization.
*/
user?: string | null
}
}

// typescript-json-schema generates only PublishConfiguration if it is specified in the list, so, it is not added here
export type AllPublishOptions = string | GithubOptions | S3Options | GenericServerOptions | BintrayOptions
// https://github.com/YousefED/typescript-json-schema/issues/80
export type Publish = AllPublishOptions | Array<AllPublishOptions> | null
2 changes: 2 additions & 0 deletions packages/electron-builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"bugs": "https://github.com/electron-userland/electron-builder/issues",
"homepage": "https://github.com/electron-userland/electron-builder",
"dependencies": {
"ajv": "^5.0.2-beta",
"ajv-keywords": "^1.5.1",
"7zip-bin": "^2.0.4",
"asar-electron-builder": "^0.13.5",
"bluebird-lst": "^1.0.1",
Expand Down
32 changes: 0 additions & 32 deletions packages/electron-builder/src/fileMatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,36 +108,4 @@ export function copyFiles(patterns: Array<FileMatcher> | null): Promise<any> {
}
return await copyDir(pattern.from, pattern.to, pattern.createFilter())
})
}


export function deprecatedUserIgnoreFilter(ignore: Array<RegExp> | ((file: string) => boolean), appDir: string) {
let ignoreFunc: any
if (typeof ignore === "function") {
ignoreFunc = function (file: string) { return !(<any>ignore)(file) }
}
else {
if (!Array.isArray(ignore)) {
ignore = [ignore]
}

ignoreFunc = function (file: string) {
for (const i of <Array<RegExp>>ignore) {
if (file.match(i)) {
return false
}
}

return true
}
}

return function filter(file: string) {
let name = file.split(path.resolve(appDir))[1]
if (path.sep === "\\") {
// convert slashes so unix-format ignores work
name = name.replace(/\\/g, "/")
}
return ignoreFunc(name)
}
}
2 changes: 2 additions & 0 deletions packages/electron-builder/src/options/linuxOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export interface LinuxBuildOptions extends PlatformSpecificBuildOptions {
Target package type: list of `AppImage`, `snap`, `deb`, `rpm`, `freebsd`, `pacman`, `p5p`, `apk`, `7z`, `zip`, `tar.xz`, `tar.lz`, `tar.gz`, `tar.bz2`, `dir`. Defaults to `AppImage`.
The most effective [xz](https://en.wikipedia.org/wiki/Xz) compression format used by default.
electron-builder [docker image](https://github.com/electron-userland/electron-builder/wiki/Docker) can be used to build Linux targets on any platform. See [Multi platform build](https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build).
*/
readonly target?: Array<string> | null

Expand Down
13 changes: 12 additions & 1 deletion packages/electron-builder/src/packager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ajv from "ajv"
import { extractFile } from "asar-electron-builder"
import BluebirdPromise from "bluebird-lst"
import { Arch, Platform, Target } from "electron-builder-core"
Expand All @@ -8,6 +9,7 @@ import { log, warn } from "electron-builder-util/out/log"
import { all, executeFinally } from "electron-builder-util/out/promise"
import { TmpDir } from "electron-builder-util/out/tmp"
import { EventEmitter } from "events"
import { readJson } from "fs-extra-p"
import * as path from "path"
import { lt as isVersionLessThan } from "semver"
import { AppInfo } from "./appInfo"
Expand All @@ -17,7 +19,7 @@ import { ArtifactCreated, BuildInfo, PackagerOptions, SourceRepositoryInfo } fro
import { PlatformPackager } from "./platformPackager"
import { getRepositoryInfo } from "./repositoryInfo"
import { createTargets } from "./targets/targetFactory"
import { doLoadConfig, getElectronVersion, loadConfig, readPackageJson } from "./util/readPackageJson"
import { doLoadConfig, getElectronVersion, loadConfig, normaliseErrorMessages, readPackageJson } from "./util/readPackageJson"
import { WinPackager } from "./winPackager"
import { getGypEnv, installOrRebuild } from "./yarn"

Expand Down Expand Up @@ -124,6 +126,15 @@ export class Packager implements BuildInfo {
}
}

const ajv = new Ajv({allErrors: true})
ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-04.json"))
require("ajv-keywords")(ajv, ["typeof"])
const schema = await readJson(path.join(__dirname, "..", "scheme.json"))
const validator = ajv.compile(schema)
if (!validator(config)) {
throw new Error("Config is invalid:\n" + JSON.stringify(normaliseErrorMessages(validator.errors!), null, 2) + "\n\nRaw validation errors: " + JSON.stringify(validator.errors, null, 2))
}

this._config = config
this.appDir = await computeDefaultAppDirectory(projectDir, use(config.directories, it => it!.app))

Expand Down
13 changes: 1 addition & 12 deletions packages/electron-builder/src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Minimatch } from "minimatch"
import * as path from "path"
import { AppInfo } from "./appInfo"
import { checkFileInArchive, createAsarArchive } from "./asarUtil"
import { copyFiles, deprecatedUserIgnoreFilter, FileMatcher } from "./fileMatcher"
import { copyFiles, FileMatcher } from "./fileMatcher"
import { AsarOptions, Config, FileAssociation, FilePattern, Macros, PlatformSpecificBuildOptions } from "./metadata"
import { unpackElectron } from "./packager/dirPackager"
import { BuildInfo, PackagerOptions } from "./packagerApi"
Expand Down Expand Up @@ -172,17 +172,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
".nyc_output}")

let rawFilter: any = null
const deprecatedIgnore = (<any>this.config).ignore
if (deprecatedIgnore != null) {
if (typeof deprecatedIgnore === "function") {
warn(`"ignore" is specified as function, may be new "files" option will be suit your needs? Please see https://github.com/electron-userland/electron-builder/wiki/Options#Config-files`)
}
else {
warn(`"ignore" is deprecated, please use "files", see https://github.com/electron-userland/electron-builder/wiki/Options#Config-files`)
}
rawFilter = deprecatedUserIgnoreFilter(deprecatedIgnore, appDir)
}

const excludePatterns: Array<Minimatch> = []
if (extraResourceMatchers != null) {
for (const matcher of extraResourceMatchers) {
Expand Down
76 changes: 68 additions & 8 deletions packages/electron-builder/src/util/readPackageJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { readFile, readJson } from "fs-extra-p"
import { safeLoad } from "js-yaml"
import * as path from "path"
import { Config } from "../metadata"
import AdditionalPropertiesParams = ajv.AdditionalPropertiesParams
import ErrorObject = ajv.ErrorObject
import TypeParams = ajv.TypeParams

const normalizeData = require("normalize-package-data")

Expand Down Expand Up @@ -34,14 +37,7 @@ async function authors(file: string, data: any) {

function getConfigFromPackageData(metadata: any) {
if (metadata.directories != null) {
warn(`"directories" in the root is deprecated, please specify in the "build"`)
if (metadata.build == null) {
metadata.build = {directories: metadata.directories}
}
else if (metadata.build.directories == null) {
metadata.build.directories = metadata.directories
}
delete metadata.directories
throw new Error(`"directories" in the root is deprecated, please specify in the "build"`)
}
return metadata.build
}
Expand Down Expand Up @@ -132,4 +128,68 @@ function findFromElectronPrebuilt(packageData: any): any {
}
}
return null
}

export function normaliseErrorMessages(errors: Array<ErrorObject>) {
const result: any = Object.create(null)
for (const e of errors) {
if (e.keyword === "type" && (<TypeParams>e.params).type === "null") {
// ignore - no sense to report that type accepts null
continue
}

const dataPath = e.dataPath.length === 0 ? [] : e.dataPath.substring(1).split(".")
if (e.keyword === "additionalProperties") {
dataPath.push((<AdditionalPropertiesParams>e.params).additionalProperty)
}

let o = result
let lastName: string | null = null
for (const p of dataPath) {
if (p === dataPath[dataPath.length - 1]) {
lastName = p
break
}
else {
if (o[p] == null) {
o[p] = Object.create(null)
}
else if (typeof o[p] === "string") {
o[p] = [o[p]]
}
o = o[p]
}
}

if (lastName == null) {
lastName = "unknown"
}

let message = e.message!.toUpperCase()[0] + e.message!.substring(1)
switch (e.keyword) {
case "additionalProperties":
message = "Unknown option"
break

case "required":
message = "Required option"
break

case "anyOf":
message = "Invalid option object"
break
}

if (o[lastName] != null && !Array.isArray(o[lastName])) {
o[lastName] = [o[lastName]]
}

if (Array.isArray(o[lastName])) {
o[lastName].push(message)
}
else {
o[lastName] = message
}
}
return result
}
4 changes: 2 additions & 2 deletions packages/electron-builder/templates/linux/AppRun.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ if [ -z $APPDIR ] ; then
fi

export PATH="${APPDIR}/usr/bin:${APPDIR}/usr/sbin:${PATH}"
export XDG_DATA_DIRS="./share/:${XDG_DATA_DIRS}"
export XDG_DATA_DIRS="./share/:/usr/share/gnome:/usr/local/share/:/usr/share/:${XDG_DATA_DIRS}"
export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}"
export XDG_DATA_DIRS="${APPDIR}/usr/share:${XDG_DATA_DIRS}"
export XDG_DATA_DIRS="${APPDIR}"/usr/share/:"${XDG_DATA_DIRS}":/usr/share/gnome/:/usr/local/share/:/usr/share/
export GSETTINGS_SCHEMA_DIR="${APPDIR}/usr/share/glib-2.0/schemas:${GSETTINGS_SCHEMA_DIR}"

DESKTOP_FILE=$(find "$APPDIR" -maxdepth 1 -name "*.desktop" | head -n 1)
Expand Down
10 changes: 5 additions & 5 deletions packages/electron-builder/templates/nsis/common.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ Name "${PRODUCT_NAME}"
!define UNINSTALL_FILENAME "Uninstall ${PRODUCT_FILENAME}.exe"

!macro check64BitAndSetRegView
!ifdef APP_64
${IfNot} ${AtLeastWin7}
MessageBox MB_OK "Windows 7 and above is required"
Quit
${EndIf}
${IfNot} ${AtLeastWin7}
MessageBox MB_OK "Windows 7 and above is required"
Quit
${EndIf}

!ifdef APP_64
${If} ${RunningX64}
SetRegView 64
${Else}
Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
"build": {
"electronVersion": "1.6.0",
"appId": "org.electron-builder.testApp",
"category": "your.app.category.type",
"iconUrl": "https://raw.githubusercontent.com/szwacz/electron-boilerplate/master/resources/windows/icon.ico",
"compression": "store",
"npmRebuild": false
"npmRebuild": false,
"mac": {
"category": "your.app.category.type"
}
}
}
Loading

0 comments on commit d65f8c3

Please sign in to comment.