diff --git a/.travis.yml b/.travis.yml index 64ecae6257..78f64f8e21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,6 @@ install: - npm install script: - - lerna run compile - - lerna run lint + - npm run compile + - npm run lint # - lerna run test --concurrency 1 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d7868da8d8..05c672855d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,28 +4,27 @@ "tasks": [ { "taskName": "Bootstrap", - "command": "lerna", + "command": "npm", "isShellCommand": true, "showOutput": "silent", - "args": ["bootstrap"], + "args": ["run", "bootstrap"], "isBackground": false }, { - "taskName": "Watch", - "command": "lerna", + "taskName": "Clean", + "command": "npm", "isShellCommand": true, "showOutput": "silent", - "args": ["run", "--parallel", "watch"], - "isBackground": true, - "problemMatcher": "$tsc-watch" + "args": ["run", "clean"], + "isBackground": false }, { "isBuildCommand": true, "taskName": "Compile", - "command": "lerna", + "command": "npm", "isShellCommand": true, "showOutput": "silent", - "args": ["run", "--stream", "compile"], + "args": ["run", "compile"], "isBackground": false, "problemMatcher": { "owner": "typescript", @@ -39,6 +38,32 @@ "message": 7 } } + }, + { + "taskName": "Lint", + "command": "npm", + "isShellCommand": true, + "showOutput": "silent", + "args": ["run", "lint"], + "isBackground": false + }, + { + "isTestCommand": true, + "taskName": "Test", + "command": "npm", + "isShellCommand": true, + "showOutput": "silent", + "args": ["run", "test"], + "isBackground": false + }, + { + "taskName": "Watch", + "command": "npm", + "isShellCommand": true, + "showOutput": "silent", + "args": ["run", "watch"], + "isBackground": true, + "problemMatcher": "$tsc-watch" } ] } diff --git a/README.md b/README.md index 0cdc41a7dd..72d27b3a24 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,26 @@ it will ask you to install them. **Please do so since this includes the linters and formatters**. +## Pre-requisites for Windows Development + +These are instructions for _developing_ the extensions on Windows since there +are some quirkiness with the way Windows behaves. This does not affect the +actual extensions that we distribute. + +1. Same as above. +1. You should use Bash Shell instead of Powershell or the Command Prompt. +1. If you want to use the integrated terminal in VS Code, you can see that + following the instructions + [here](https://code.visualstudio.com/docs/editor/integrated-terminal#_windows); +1. You should install VS Code Insiders from + [here](https://code.visualstudio.com/insiders). Without this, you won't be + able to run the end-to-end tests while VS Code is open. You will see an error + of the form "Running extension tests from the command line is currently only + supported if no other instance of Code is running." To circumvent that you + could close VS Code each time you run the tests. Or, you can install the + Insiders version so that it can run the tests in Code while you work in the + Insiders version. + ## Structure ### Packages @@ -39,7 +59,7 @@ You would only do this once after you cloned the repository. You would usually do the following each time you close/reopen VS Code: 1. [Optional] Open the Command Palette > Tasks: Run Task > Bootstrap (this - essentially runs `lerna bootstrap`). This is required if you change the + essentially runs `npm run bootstrap`). This is required if you change the dependencies in any of the package.json. 1. If you wish to build, you can invoke Command Palette > Build Task (Ctrl+Shift+B or Cmd+Shift+B on Mac). The errors will show in the Problems @@ -56,9 +76,9 @@ to run and debug extensions. When you are ready to commit -1. Run `lerna run lint` to run tslint in more thorough mode to identify any +1. Run `npm run lint` to run tslint in more thorough mode to identify any errors. -1. Some of the items can be fixed using `tstlint --project . fix`. Some you +1. Some of the items can be fixed using `tslint --project . fix`. Some you might need to fix them manually. This linting steps should be done later as part of the continuous integration @@ -66,7 +86,9 @@ runs but that is how you would check locally first. ## List of Useful commands -### `lerna bootstrap` +_These commands assume that they are executed from the top-level directory. Internally, they delegate to `lerna` to call them on each npm module in the packages directory._ + +### `npm run bootstrap` This bootstraps the packages by issuing an `npm install` on each package and also symlinking any package that are part of the packages folder. @@ -77,27 +99,27 @@ modules. If you change the dependencies in your package.json, you will also need to run this command. -### `lerna run compile` +### `npm run compile` This runs `npm run compile` on each of the package in packages. -### `lerna run clean` +### `npm run clean` This run `npm run clean` on each of the package in packages. -### `lerna run --parallel watch` +### `npm run watch` This runs `npm run watch` on each of the package in packages. The `--parallel` flag tell it to run each in a separate process so that it won't block the main thread. -### `lerna run test --concurrency 1` +### `npm run test` This runs `npm test` on each of the packages. The `--concurrency 1` is essential for VS Code extension tests since they require an instance of Code to run in. And, only one instance of that can be running at a single time. -### `lerna run lint` +### `npm run lint` This runs `npm lint` on each of the packages. If there are no errors/warnings from tslint, then you get a clean output. But, if they are errors from tslint, diff --git a/docs/publishing.md b/docs/publishing.md new file mode 100644 index 0000000000..86585ddf33 --- /dev/null +++ b/docs/publishing.md @@ -0,0 +1,89 @@ +# Introduction + +This is a guide for publishing to the Visual Studio Code Marketplace. Most +contributors will not need to worry about publishing. However, it might be +worthwhile familiarizing yourself with the steps in case you need to share the +extensions through the .vsix files. + +# Goal + +The goal of publishing is to take the extensions under /packages, bundle them as +.vsix files, and push them to the [Visual Studio Code +Marketplace](https://marketplace.visualstudio.com/vscode). + +For more information about publishing take a look at + +* [Publishing VS Code Extensions](https://code.visualstudio.com/docs/extensions/publish-extension) +* [Managing Extensions](https://code.visualstudio.com/docs/editor/extension-gallery) + +# Steps + +The scripts/publish.js contains the end-to-end flow. It is possible to run each step manually. + +The files under scripts use [shelljs/shx](https://github.com/shelljs/shx) and +[shelljs/shelljs](https://github.com/shelljs/shelljs) to write scripts in a +portable manner across platforms. + +## Packaging as .vsix + +### Prerequisite + +* Lerna is properly installed. + +### Steps + +1. `npm run bootstrap` to install all the dependencies and to symlink interdependent local modules. +1. `npm run compile` to compile all the TypeScript files. +1. `npm run test` to run all the tests. +1. `lerna publish ...` will increment the version in the individual package.json + to prepare for publication. **This also commits the changes to git and adds a + tag.** +1. `npm run vscode:package` packages _each_ extension as a .vsix. + +**At this stage, it is possible to share the .vsix directly for manual installation.** + +## Generating SHA256 + +Due to [vscode-vsce#191](https://github.com/Microsoft/vscode-vsce/issues/191) +the .vsix are neither signed nor verified. To ensure that they have not been +tampered with, we generate a SHA256 of the contents and publish that to +https://developer.salesforce.com/media/vscode/SHA256 + +### Prerequisite + +* You have access to our S3 bucket at s3://dfc-data-production/media/vscode +* You have the [AWS CLI](https://aws.amazon.com/cli/) installed and configured + via `aws configure` or have the `AWS_ACCESS_KEY_ID` and + `AWS_SECRET_ACCESS_KEY` exported as environment variables. + +### Steps + +1. `npm run vscode:sha256` will compute the SHA256 for the .vsix generated in + the previous stage. +1. The SHA256 are appended to the top-level SHA256 file. +1. This file is then copied over to our S3 bucket. +1. Finally the file is added to git so that it can be committed. + +## Pushing .vsix to Visual Studio Marketplace + +### Prerequisite + +* You have a personal access token that for the salesforce publisher id that is + exported as `VSCE_PERSONAL_ACCESS_TOKEN`. +* Or, you have vsce installed and configured with the salesforce publisher id. + +### Steps + +1. `npm run vscode:publish` takes the .vsix that you had _before_ and uploads + it to the Visual Studio Code Marketplace. + +It's **crucial** that you publish the .vsix that you had before so that the +SHA256 match. If you were to repackage, the SHA256 would be different. + +# Tips + +1. After publishing, you will need to run `npm run bootstrap` again to continue + development. This is because the `npm run vscode:package` step does a `npm + prune --production`. This is required due to the way Lerna does symlinking. + See [vscode-vsce#52](https://github.com/Microsoft/vscode-vsce/issues/52) for + more information. \ No newline at end of file diff --git a/lerna.json b/lerna.json index a0ad6632d6..d7a72ffb2f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,7 @@ { - "lerna": "2.0.0-rc.5", + "lerna": "2.0.0", "packages": [ "packages/*" ], - "version": "0.1.0" + "version": "0.2.0" } diff --git a/package.json b/package.json index ec20e461d1..12b31aa9db 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,23 @@ { "devDependencies": { - "lerna": "^2.0.0-rc.5", + "lerna": "2.0.0", + "shx": "^0.2.2", + "tslint": "5.5.0", "typescript": "2.4.0", - "tslint": "5.5.0" + "vsce": "1.29.0" }, "scripts": { - "postinstall": "lerna bootstrap" + "postinstall": "lerna bootstrap", + "bootstrap": "lerna bootstrap", + "clean": "lerna run clean", + "compile": "lerna run --stream compile", + "lint": "lerna run lint", + "publish": "node scripts/publish.js", + "test": "lerna run test --concurrency 1", + "vscode:package": "lerna run vscode:package --concurrency 1", + "vscode:sha256": "lerna run vscode:sha256 --concurrency 1", + "vscode:publish": "lerna run vscode:publish --concurrency 1", + "watch": "lerna run --parallel watch" }, "repository": { "type": "git", diff --git a/packages/salesforcedx-utils-vscode/package.json b/packages/salesforcedx-utils-vscode/package.json index 73442b601e..e269b48c3a 100644 --- a/packages/salesforcedx-utils-vscode/package.json +++ b/packages/salesforcedx-utils-vscode/package.json @@ -2,10 +2,12 @@ "name": "@salesforce/salesforcedx-utils-vscode", "displayName": "SFDX Utilities for VS Code", "description": "Provides utilies to interface the SFDX libraries with VS Code", - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", - "categories": ["Other"], + "categories": [ + "Other" + ], "dependencies": { "rxjs": "^5.4.1", "tree-kill": "^1.1.0" @@ -23,8 +25,8 @@ "compile": "tsc -p ./", "lint": "tslint --project .", "watch": "tsc -watch -p .", - "clean": "rm -rf node_modules && rm -rf out", - "test": "node ./node_modules/.bin/_mocha --recursive out/test", + "clean": "shx rm -rf node_modules && shx rm -rf out", + "test": "./node_modules/.bin/_mocha --recursive out/test", "coverage": "./node_modules/.bin/nyc npm test" }, "main": "./out/src/" diff --git a/packages/salesforcedx-vscode-apex-debugger/package.json b/packages/salesforcedx-vscode-apex-debugger/package.json index 2cbf60c557..42529b5635 100644 --- a/packages/salesforcedx-vscode-apex-debugger/package.json +++ b/packages/salesforcedx-vscode-apex-debugger/package.json @@ -8,11 +8,13 @@ "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Debuggers"] + "categories": [ + "Debuggers" + ] } diff --git a/packages/salesforcedx-vscode-apex/package.json b/packages/salesforcedx-vscode-apex/package.json index 061173fe57..7db8ba4a10 100644 --- a/packages/salesforcedx-vscode-apex/package.json +++ b/packages/salesforcedx-vscode-apex/package.json @@ -8,13 +8,15 @@ "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Languages"], + "categories": [ + "Languages" + ], "devDependencies": { "@types/chai": "^4.0.0", "@types/mocha": "2.2.38", @@ -28,14 +30,19 @@ }, "scripts": { "vscode:prepublish": "npm prune --production", + "vscode:package": "vsce package", + "vscode:sha256": "node ../../scripts/generate-sha256.js >> ../../SHA256", + "vscode:publish": "node ../../scripts/publish-vsix.js", "compile": "tsc -p ./", "lint": "tslint --project .", "watch": "tsc -watch -p .", - "clean": "rm -rf node_modules && (cd out && find . \\! -name 'apex-jorje-lsp.jar' -delete)", + "clean": "shx rm -rf node_modules && cd out && node ../../../scripts/clean-all-but-jar.js", "postinstall": "node ./node_modules/vscode/bin/install", "test": "node ./node_modules/vscode/bin/test" }, - "activationEvents": ["workspaceContains:sfdx-project.json"], + "activationEvents": [ + "workspaceContains:sfdx-project.json" + ], "main": "./out/src", "contributes": { "configuration": { @@ -43,7 +50,10 @@ "title": "%configuration_title%", "properties": { "salesforcedx-vscode-apex.java.home": { - "type": ["string", "null"], + "type": [ + "string", + "null" + ], "default": null, "description": "%java_home_description%" } @@ -52,8 +62,14 @@ "languages": [ { "id": "apex", - "aliases": ["Apex", "apex"], - "extensions": [".cls", ".trigger"], + "aliases": [ + "Apex", + "apex" + ], + "extensions": [ + ".cls", + ".trigger" + ], "configuration": "./syntaxes/apex.configuration.json" } ], @@ -66,7 +82,7 @@ ] }, "dependencies": { - "@salesforce/salesforcedx-utils-vscode": "0.1.0", + "@salesforce/salesforcedx-utils-vscode": "0.2.0", "expand-home-dir": "0.0.3", "find-java-home": "0.2.0", "path-exists": "3.0.0", diff --git a/packages/salesforcedx-vscode-core/package.json b/packages/salesforcedx-vscode-core/package.json index e6fcecafde..bd3a2f0a4e 100644 --- a/packages/salesforcedx-vscode-core/package.json +++ b/packages/salesforcedx-vscode-core/package.json @@ -8,15 +8,17 @@ "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Other"], + "categories": [ + "Other" + ], "dependencies": { - "@salesforce/salesforcedx-utils-vscode": "0.1.0", + "@salesforce/salesforcedx-utils-vscode": "0.2.0", "rxjs": "^5.4.1" }, "devDependencies": { @@ -33,11 +35,14 @@ "vscode": "1.1.2" }, "scripts": { - "vscode:prepublish": "tsc -p ./", + "vscode:prepublish": "npm prune --production", + "vscode:package": "vsce package", + "vscode:sha256": "node ../../scripts/generate-sha256.js >> ../../SHA256", + "vscode:publish": "node ../../scripts/publish-vsix.js", "compile": "tsc -p ./", "lint": "tslint --project .", "watch": "tsc -watch -p .", - "clean": "rm -rf node_modules && rm -rf out", + "clean": "shx rm -rf node_modules && shx rm -rf out", "postinstall": "node ./node_modules/vscode/bin/install", "test": "node ./node_modules/vscode/bin/test" }, diff --git a/packages/salesforcedx-vscode-lightning/package.json b/packages/salesforcedx-vscode-lightning/package.json index 866571612e..952815ecb7 100644 --- a/packages/salesforcedx-vscode-lightning/package.json +++ b/packages/salesforcedx-vscode-lightning/package.json @@ -8,13 +8,15 @@ "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Languages"], + "categories": [ + "Languages" + ], "devDependencies": { "@types/chai": "^4.0.0", "@types/mocha": "2.2.38", @@ -27,11 +29,14 @@ "vscode": "1.1.2" }, "scripts": { - "vscode:prepublish": "tsc -p ./", + "vscode:prepublish": "npm prune --production", + "vscode:package": "vsce package", + "vscode:sha256": "node ../../scripts/generate-sha256.js >> ../../SHA256", + "vscode:publish": "node ../../scripts/publish-vsix.js", "compile": "tsc -p ./", "lint": "tslint --project .", "watch": "tsc -watch -p .", - "clean": "rm -rf node_modules && rm -rf out", + "clean": "shx rm -rf node_modules && shx rm -rf out", "postinstall": "node ./node_modules/vscode/bin/install", "test": "node ./node_modules/vscode/bin/test" }, diff --git a/packages/salesforcedx-vscode-visualforce/package.json b/packages/salesforcedx-vscode-visualforce/package.json index 779f1a4a82..d558d4867c 100644 --- a/packages/salesforcedx-vscode-visualforce/package.json +++ b/packages/salesforcedx-vscode-visualforce/package.json @@ -8,13 +8,15 @@ "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Languages"], + "categories": [ + "Languages" + ], "devDependencies": { "@types/chai": "^4.0.0", "@types/mocha": "2.2.38", @@ -27,11 +29,14 @@ "vscode": "1.1.2" }, "scripts": { - "vscode:prepublish": "tsc -p ./", + "vscode:prepublish": "npm prune --production", + "vscode:package": "vsce package", + "vscode:sha256": "node ../../scripts/generate-sha256.js >> ../../SHA256", + "vscode:publish": "node ../../scripts/publish-vsix.js", "compile": "tsc -p ./", "lint": "tslint --project .", "watch": "tsc -watch -p .", - "clean": "rm -rf node_modules && rm -rf out", + "clean": "shx rm -rf node_modules && shx rm -rf out", "postinstall": "node ./node_modules/vscode/bin/install", "test": "node ./node_modules/vscode/bin/test" }, @@ -39,7 +44,10 @@ "languages": [ { "id": "html", - "extensions": [".page", ".component"] + "extensions": [ + ".page", + ".component" + ] } ] } diff --git a/packages/salesforcedx-vscode/package.json b/packages/salesforcedx-vscode/package.json index 85c497ca93..7c4c102b7c 100644 --- a/packages/salesforcedx-vscode/package.json +++ b/packages/salesforcedx-vscode/package.json @@ -2,19 +2,27 @@ "preview": true, "name": "salesforcedx-vscode", "displayName": "Visual Studio Code Extension Pack for Salesforce DX", - "description": "Collection of extension for Salesforce DX", + "description": "Collection of extensions for Salesforce DX", "icon": "images/icon.png", "galleryBanner": { "color": "#ECECEC", "theme": "light" }, - "version": "0.1.0", + "version": "0.2.0", "publisher": "salesforce", "license": "MIT", "engines": { "vscode": "^1.13.0" }, - "categories": ["Extension Packs"], + "scripts": { + "vscode:prepublish": "npm prune --production", + "vscode:package": "vsce package", + "vscode:sha256": "node ../../scripts/generate-sha256.js >> ../../SHA256", + "vscode:publish": "node ../../scripts/publish-vsix.js" + }, + "categories": [ + "Extension Packs" + ], "extensionDependencies": [ "salesforce.salesforcedx-vscode-apex", "salesforce.salesforcedx-vscode-core", diff --git a/scripts/clean-all-but-jar.js b/scripts/clean-all-but-jar.js new file mode 100755 index 0000000000..d904ea23bb --- /dev/null +++ b/scripts/clean-all-but-jar.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +const shell = require('shelljs'); + +// Removes all files but .jar files at the top-level + +shell.rm('-rf', shell.ls().filter(file => !file.match(/\.jar$/))); diff --git a/scripts/generate-sha256.js b/scripts/generate-sha256.js new file mode 100644 index 0000000000..532d2e0990 --- /dev/null +++ b/scripts/generate-sha256.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +const shell = require('shelljs'); + +// Generate the SHA256 for the .vsix that matches the version in package.json + +const packageVersion = JSON.parse(shell.cat('package.json')).version; +const vsix = shell.ls().filter(file => file.match(`-${packageVersion}.vsix`)); + +if (!vsix.length) { + shell.error('No VSIX found matching the requested version in package.json'); + shell.exit(1); +} + +if (/win32/.test(process.platform)) { + shell.exec(`CertUtil -hashfile ${vsix} SHA256`); +} else { + shell.exec(`shasum -a 256 ${vsix}`); +} diff --git a/scripts/publish-vsix.js b/scripts/publish-vsix.js new file mode 100644 index 0000000000..fa44d22bf7 --- /dev/null +++ b/scripts/publish-vsix.js @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const shell = require('shelljs'); + +// Publishes the .vsix that matches the version in package.json + +const packageVersion = JSON.parse(shell.cat('package.json')).version; +const vsix = shell.ls().filter(file => file.match(`-${packageVersion}.vsix`)); + +if (!vsix.length) { + shell.error('No VSIX found matching the requested version in package.json'); + shell.exit(1); +} + +const vsce = '../../node_modules/.bin/vsce'; +const VSCE_PERSONAL_ACCESS_TOKEN = process.env['VSCE_PERSONAL_ACCESS_TOKEN']; +if (VSCE_PERSONAL_ACCESS_TOKEN) { + shell.exec( + `${vsce} publish --pat ${VSCE_PERSONAL_ACCESS_TOKEN} --packagePath ${vsix}` + ); +} else { + // Assume that one has already been configured + shell.exec(`${vsce} publish --packagePath ${vsix}`); +} diff --git a/scripts/publish.js b/scripts/publish.js new file mode 100644 index 0000000000..dd5752e52d --- /dev/null +++ b/scripts/publish.js @@ -0,0 +1,58 @@ +#!/usr/bin/env node + +const shell = require('shelljs'); +shell.set('-e'); +shell.set('+v'); + +/* + * Assumptions: + * 0. The script is running locally - it's not optimized for Travis workflow + * yet. + * 1. The script is running in the right branch. + * 2. The script is running in a clean environment - all changes have been + * committed. + */ + +// Bootstrap +shell.exec('npm run bootstrap'); + +// Compile +shell.exec('npm run compile'); + +// Test +shell.exec('npm run test'); + +// lerna publish +// --skip-npm to increment the version number in all packages but not publish to npmjs +// This will still make a commit in Git with the tag of the version used +const nextVersion = process.env['VERSION_INCREMENT']; +if (nextVersion) { + shell.exec( + `lerna publish --force-publish --exact --repo-version ${nextVersion} --yes --skip-npm` + ); +} else { + shell.exec( + 'lerna publish --force-publish --exact --cd-version minor --yes --skip-npm' + ); +} + +// Generate the .vsix files +shell.exec(`npm run vscode:package`); + +// Generate the SHA256 and append to the file +shell.exec(`npm run vscode:sha256`); + +// Push the SHA256 to AWS +shell.exec('aws s3 cp SHA256 s3://dfc-data-production/media/vscode/SHA256'); + +// Add SHA256 to git +shell.exec(`git add SHA256`); + +// Publish to VS Code Marketplace +shell.exec(`npm run vscode:publish`); + +// Perform these steps manually for now +// Git commit +// shell.exec(`git commit -m "Updated SHA256"`); +// Push back to GitHub +//shell.exec(`git push`);