Permalink
Browse files

Publish multiple versions of the inspector to support all Ember versions

This commit will allow us to drop support for old Ember versions on
master so we can move faster while at the same time not breaking the
inspector on old Ember apps.

  - Whenever we want to stop supporting an Ember version we take a
    snapshot of the current inspector and compress and upload it to S3.
Current master will only support the latest Ember versions (example:
Ember 2.0+).

  - Before publishing the extension, we fetch the uploaded snapshots and
    bundle them with the current inspector and publish all of them
together.

  - During runtime, we detect the Ember version and start the inspector
    version that matches this Ember version. This is all automatic and
does not require the user to do anything.

TL;DR the Ember Inspector published extension will contain several
bundled Ember Inspector versions and boot up the suitable one depending
on the app.

- One of the biggest challenges while working on the inspector has been
  supporting all Ember versions (since Ember 1.0-RC). This is becoming
harder with each released Ember version, especially after Ember 2.0 was
released. We need to drop support for the old Ember versions.

- As with everything in Ember, although we want to move fast, we don't
  want to leave developers behind. People who have not kept up with the
latest Ember version should still be able to inspect their apps. We need
to keep support for the old Ember versions.

- There's a very good chance that when a developer opens the Ember
  Inspector they are usually debugging some kind of problem, so even
adding one manual step could break their chain of thought or use up
time/energy they'd rather spend on their app. The process needs to be
automatic.
  • Loading branch information...
1 parent a903280 commit 80c8b20a6c6e0a2d53a5191c66c0a8bcb4398a54 @teddyzeenny teddyzeenny committed Apr 4, 2016
Showing with 674 additions and 102 deletions.
  1. +2 −0 .gitignore
  2. +2 −0 .npmignore
  3. +129 −35 Brocfile.js
  4. +30 −12 Gruntfile.js
  5. +15 −1 README.md
  6. +98 −0 app/adapters/basic.js
  7. +23 −3 app/adapters/bookmarklet.js
  8. +33 −10 app/adapters/chrome.js
  9. +25 −5 app/adapters/firefox.js
  10. +3 −4 app/app.js
  11. +3 −0 config/environment.js
  12. +4 −0 config/secrets.json.sample
  13. +92 −0 ember_debug/vendor/startup-wrapper.js
  14. +13 −4 package.json
  15. +85 −0 scripts/download-panes.js
  16. +37 −0 scripts/upload-panes.js
  17. +20 −4 {skeleton_bookmarklet → skeletons/bookmarklet}/load_inspector.js
  18. 0 {skeleton_chrome → skeletons/chrome}/background-script.js
  19. 0 {skeleton_chrome → skeletons/chrome}/chrome-bootstrap.css
  20. +1 −1 {skeleton_chrome → skeletons/chrome}/content-script.js
  21. 0 {skeleton_chrome → skeletons/chrome}/devtools.html
  22. +1 −1 {skeleton_chrome → skeletons/chrome}/devtools.js
  23. +7 −7 {skeleton_chrome → skeletons/chrome}/manifest.json
  24. +1 −1 {skeleton_chrome → skeletons/chrome}/options-dialog.html
  25. +2 −2 {skeleton_chrome → skeletons/chrome}/options.html
  26. 0 {skeleton_chrome → skeletons/chrome}/options.js
  27. +2 −3 {skeleton_firefox → skeletons/firefox}/data/content-script.js
  28. +1 −1 {skeleton_firefox → skeletons/firefox}/data/devtool-panel.html
  29. 0 {skeleton_firefox → skeletons/firefox}/data/toolbar-button-panel.html
  30. 0 {skeleton_firefox → skeletons/firefox}/lib/devtools-utils.js
  31. +10 −0 skeletons/firefox/lib/ember-versions.js
  32. 0 {skeleton_firefox → skeletons/firefox}/lib/main.js
  33. +17 −2 {skeleton_firefox → skeletons/firefox}/lib/tomster-devtool-panel.js
  34. +1 −1 {skeleton_firefox → skeletons/firefox}/lib/tomster-locationbar-button.js
  35. +16 −4 {skeleton_firefox → skeletons/firefox}/lib/tomster-tabs.js
  36. 0 {skeleton_firefox → skeletons/firefox}/lib/urlbarbutton.js
  37. +1 −1 {skeleton_firefox → skeletons/firefox}/package.json
View
@@ -3,6 +3,7 @@
# compiled output
/dist
/tmp
+/dist_prev
.DS_Store
@@ -17,5 +18,6 @@
/libpeerconnection.log
npm-debug.log
testem.log
+config/secrets.json
/.mozilla-addon-sdk
View
@@ -6,6 +6,8 @@ tmp/
dist/chrome/ember-inspector.zip
dist/testing
+dist_prev
+
*.xpi
.mozilla-addon-sdk
View
@@ -14,7 +14,7 @@ var mv = require('broccoli-stew').mv;
var writeFile = require('broccoli-file-creator');
var replace = require('broccoli-replace');
var esTranspiler = require('broccoli-babel-transpiler');
-
+var packageJson = require('./package.json');
/*global process */
@@ -80,6 +80,13 @@ emberDebug = removeFile(emberDebug, {
]
});
+emberDebug = removeFile(emberDebug, {
+ files: [
+ 'ember-debug/vendor/startup-wrapper.js',
+ 'ember-debug/vendor/loader.js'
+ ]
+});
+
if (env === 'test') {
var linted = eslint(emberDebug, {
testGenerator: eslintTestGenerator,
@@ -91,13 +98,6 @@ if (env === 'test') {
emberDebug = mergeTrees([emberDebug, linted]);
}
-emberDebug = removeFile(emberDebug, {
- files: [
- 'ember-debug/vendor/startup-wrapper.js',
- 'ember-debug/vendor/loader.js'
- ]
-});
-
emberDebug = new ES6Modules(emberDebug, {
esperantoOptions: {
absolutePaths: true,
@@ -106,12 +106,27 @@ emberDebug = new ES6Modules(emberDebug, {
});
emberDebug = esTranspiler(emberDebug);
+var previousEmberVersionsSupportedString = '[' + packageJson.previousEmberVersionsSupported.map(function(item) {
+ return "'" + item + "'";
+}).join(',') + ']';
+var emberVersionsSupportedString = '[' + packageJson.emberVersionsSupported.map(function(item) {
+ return "'" + item + "'";
+}).join(',') + ']';
+
var startupWrapper = pickFiles('ember_debug', {
srcDir: '/vendor',
files: ['startup-wrapper.js'],
destDir: '/'
});
+startupWrapper = replace(startupWrapper, {
+ files: ['startup-wrapper.js'],
+ patterns: [{
+ match: /{{EMBER_VERSIONS_SUPPORTED}}/,
+ replacement: emberVersionsSupportedString
+ }]
+});
+
var sourceMap = pickFiles('ember_debug', {
srcDir: '/vendor',
files: ['source-map.js'],
@@ -145,52 +160,131 @@ var emberDebugs = [];
var tree = app.toTree();
-var bookmarklet = mergeTrees([tree, emberDebugs.bookmarklet, 'skeleton_bookmarklet']);
+var emberInspectorVersionPattern = [{
+ match: /{{EMBER_INSPECTOR_VERSION}}/g,
+ replacement: packageJson.version
+}];
+
+tree = replace(tree, {
+ files: ['**/*.js'],
+ patterns: emberInspectorVersionPattern
+});
+
+var minimumVersion = packageJson.emberVersionsSupported[0].replace(/\./g, '-');
+var chromeRoot = 'panes-' + minimumVersion;
+var firefoxRoot = 'data/' + chromeRoot;
+var bookmarkletRoot = chromeRoot;
var firefoxAndChromeExtra = pickFiles('shared', {
srcDir: '/',
files: ['in-page-script.js'],
destDir: '/'
});
-var tabLabelPattern = [{
+var replacementPattern = [{
match: /{{env}}/,
replacement: env === 'development' ? ' [DEV]' : ''
+}, {
+ match: /{{PANE_ROOT}}/g,
+ replacement: 'panes-' + minimumVersion
+}, {
+ match: /{{PREVIOUS_EMBER_VERSIONS_SUPPORTED}}/g,
+ replacement: previousEmberVersionsSupportedString
+}, {
+ match: /{{EMBER_VERSIONS_SUPPORTED}}/g,
+ replacement: emberVersionsSupportedString
}];
-var skeleton_chrome = replace('skeleton_chrome', {
- files: ['devtools.js'],
- patterns: tabLabelPattern
+replacementPattern = replacementPattern.concat(emberInspectorVersionPattern);
+
+var skeletonChrome = replace('skeletons/chrome', {
+ files: ['*'],
+ patterns: replacementPattern
});
-var skeleton_firefox = replace('skeleton_firefox', {
- files: ['lib/tomster-devtool-panel.js'],
- patterns: tabLabelPattern
+var skeletonFirefox = replace('skeletons/firefox', {
+ files: ['*', '*/**'],
+ patterns: replacementPattern
+});
+
+var skeletonBookmarklet = replace('skeletons/bookmarklet', {
+ files: ['*'],
+ patterns: replacementPattern
});
var firefox = mergeTrees([
- mv(mergeTrees([tree, firefoxAndChromeExtra, emberDebugs.firefox]), 'data/panes'),
- skeleton_firefox
+ mv(mergeTrees([tree, emberDebugs.firefox]), firefoxRoot),
+ skeletonFirefox
]);
var chrome = mergeTrees([
- mv(mergeTrees([tree, firefoxAndChromeExtra, emberDebugs.chrome]), 'panes'),
- skeleton_chrome
+ mv(mergeTrees([tree, emberDebugs.chrome]), chromeRoot),
+ skeletonChrome
]);
-var websocket = mergeTrees([tree, emberDebugs.websocket]);
-var basic = mergeTrees([tree, emberDebugs.basic]);
+var bookmarklet = mergeTrees([
+ mv(mergeTrees([tree, emberDebugs.bookmarklet]), chromeRoot),
+ skeletonBookmarklet
+]);
+
+packageJson.previousEmberVersionsSupported.forEach(function(version) {
+ version = version.replace(/\./g, '-');
+ if (env === 'production') {
+ var prevDist = 'dist_prev/' + env;
+
+ bookmarklet = mergeTrees([
+ mv(prevDist + '/bookmarklet/panes-' + version, 'panes-' + version),
+ bookmarklet
+ ]);
+ firefox = mergeTrees([
+ mv(prevDist + '/firefox/panes-' + version, 'data/panes-' + version),
+ firefox
+ ]);
+ chrome = mergeTrees([
+ mv(prevDist + '/chrome/panes-' + version, 'panes-' + version),
+ chrome
+ ]);
+ } else {
+ var file = writeFile('index.html', "This Ember version is not supported in development environment.");
+ var emberDebugFile = writeFile('ember_debug.js', 'void(0);');
+ chrome = mergeTrees([mv(file, 'panes-' + version), chrome]);
+ firefox = mergeTrees([mv(file, 'data/panes-' + version), mv(emberDebugFile, 'data/panes-' + version), firefox]);
+ bookmarklet = mergeTrees([mv(file, 'panes-' + version), mv(emberDebugFile, 'panes-' + version), bookmarklet]);
+ }
+});
+
+firefox = mergeTrees([
+ mv(firefoxAndChromeExtra, 'data/scripts'),
+ firefox
+]);
+
+chrome = mergeTrees([
+ mv(firefoxAndChromeExtra, 'scripts'),
+ chrome
+]);
// Pass the current dist to the Ember Inspector app.
-chrome = mergeTrees([chrome, mv(writeFile('dist-config.js', "window.EMBER_DIST='chrome';"), 'panes/assets')]);
-firefox = mergeTrees([firefox, mv(writeFile('dist-config.js', "window.EMBER_DIST='firefox';"), 'data/panes/assets')]);
-bookmarklet = mergeTrees([bookmarklet, mv(writeFile('dist-config.js', "window.EMBER_DIST='bookmarklet';"), 'assets')]);
-websocket = mergeTrees([websocket, mv(writeFile('dist-config.js', "window.EMBER_DIST='websocket';"), 'assets')]);
-basic = mergeTrees([basic, mv(writeFile('dist-config.js', "window.EMBER_DIST='basic';"), 'assets')]);
+// EMBER DIST
+var dists = {
+ chrome: chrome,
+ firefox: firefox,
+ bookmarklet: bookmarklet,
+ websocket: mergeTrees([tree, emberDebugs.websocket]),
+ basic: mergeTrees([tree, emberDebugs.basic])
+};
+Object.keys(dists).forEach(function(key) {
+ dists[key] = replace(dists[key], {
+ files: ['**/*.js'],
+ patterns: [{
+ match: /{{EMBER_DIST}}/g,
+ replacement: key
+ }]
+ });
+});
// Add {{ remote-port }} to the head
// so that the websocket addon can replace it.
-websocket = replace(websocket, {
+dists.websocket = replace(dists.websocket, {
files: ['index.html'],
patterns: [{
match: /<head>/,
@@ -203,11 +297,11 @@ var output;
if (env === 'test') {
// `ember test` expects the index.html file to be in the
// output directory.
- output = basic;
+ output = dists.basic;
} else {
// Change base tag for running tests in development env.
- basic = replace(basic, {
+ dists.basic = replace(dists.basic, {
files: ['tests/index.html'],
patterns: [{
match: /<base.*\/>/,
@@ -216,11 +310,11 @@ if (env === 'test') {
});
output = mergeTrees([
- mv(bookmarklet, 'bookmarklet'),
- mv(firefox, 'firefox'),
- mv(chrome, 'chrome'),
- mv(websocket, 'websocket'),
- mv(basic, 'testing')
+ mv(dists.bookmarklet, 'bookmarklet'),
+ mv(dists.firefox, 'firefox'),
+ mv(dists.chrome, 'chrome'),
+ mv(dists.websocket, 'websocket'),
+ mv(dists.basic, 'testing')
]);
}
View
@@ -1,23 +1,15 @@
module.exports = function(grunt) {
-
+ var packageJson = grunt.file.readJSON('package.json');
+ var versionedPane = 'panes-' + packageJson.emberVersionsSupported[0].replace(/\./g, '-');
var config = {
- pkg: grunt.file.readJSON('package.json'),
+ pkg: packageJson,
env: process.env,
"jpm": {
options: {
src: "dist/firefox",
xpi: "tmp/xpi"
}
},
- "version": {
- app: {
- src: ['app/app.js']
- },
- dist: {
- prefix: '^"?version"?:\s*[\'"]?',
- src: ['skeleton_chrome/manifest.json', 'skeleton_firefox/package.json']
- }
- },
"s3": {
options: {
bucket: 'ember-extension',
@@ -44,14 +36,40 @@ module.exports = function(grunt) {
expand: true,
pretty: true,
src: 'dist/chrome/**/*'
+ },
+ "chrome-pane": {
+ options: {
+ archive: 'dist/chrome-pane.zip'
+ },
+ expand: true,
+ pretty: true,
+ cwd: 'dist/chrome/' + versionedPane,
+ src: ['**/*']
+ },
+ "firefox-pane": {
+ options: {
+ archive: 'dist/firefox-pane.zip'
+ },
+ expand: true,
+ pretty: true,
+ cwd: 'dist/firefox/data/' + versionedPane,
+ src: ['**/*']
+ },
+ "bookmarklet-pane": {
+ options: {
+ archive: 'dist/bookmarklet-pane.zip'
+ },
+ expand: true,
+ pretty: true,
+ cwd: 'dist/bookmarklet/' + versionedPane,
+ src: ['**/*']
}
}
};
grunt.initConfig(config);
grunt.loadNpmTasks('grunt-jpm');
- grunt.loadNpmTasks('grunt-version');
grunt.loadNpmTasks('grunt-s3');
grunt.loadNpmTasks('grunt-contrib-compress');
View
@@ -97,7 +97,7 @@ Patch versions are only committed to the stable branch. So we need to cherry-pic
- `git checkout master`
- Commit the change log entry to the master branch.
-#### Minor and Major versions
+#### Minor and major versions
When releasing a major/minor version, master would already have this version set, so what we need to do is to merge master into stable and release.
@@ -117,6 +117,20 @@ When releasing a major/minor version, master would already have this version set
- `npm publish ./`
- `git tag` the new version
+### Locking a version
+
+We can take a snapshot of the current inspector version to support a specific Ember version range. This allows us to stop supporting old Ember versions in master without breaking the published inspector for old Ember apps. It works by serving a different inspector version based on the current app's Ember version.
+
+The Ember versions supported by the current inspector are indicated in the `emberVersionsSupported` array in `package.json`.
+
+Here are the steps to lock an inspector version:
+
+- Update `package.json`'s `emberVersionsSupported`: add a second element that indicates the minimum Ember version this inspector *does not* support.
+- Release a new version (See "Minor and major versions"). Create a branch for this version.
+- Run `npm run lock-version`. This will build, compress, and upload this version to S3.
+- Update `package.json`'s `previousEmberVersionsSupported`: add the first Ember version supported by the recently locked version (the first element in the `emberVersionsSupported` array).
+- Update `package.json`'s `emberVersionsSupported`: Move the second element in the array to the first position. Add an empty string as the second element to indicate there's currently no maximum Ember version supported yet.
+- Commit.
### Window Messages
Oops, something went wrong.

0 comments on commit 80c8b20

Please sign in to comment.