├── .bowerrc
├── .editorconfig
├── .ember-cli
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── .watchmanconfig
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── addon
├── .gitkeep
└── services
│ └── raven.js
├── app
├── .gitkeep
└── services
│ └── raven.js
├── bower.json
├── circle.yml
├── config
├── ember-try.js
└── environment.js
├── index.js
├── package-lock.json
├── package.json
├── testem.json
├── tests
├── .jshintrc
├── dummy
│ ├── app
│ │ ├── app.js
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── index.html
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── router.js
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── styles
│ │ │ └── app.css
│ │ └── templates
│ │ │ ├── application.hbs
│ │ │ └── components
│ │ │ └── .gitkeep
│ ├── config
│ │ └── environment.js
│ └── public
│ │ ├── crossdomain.xml
│ │ └── robots.txt
├── helpers
│ ├── resolver.js
│ └── start-app.js
├── index.html
├── runner.js
├── test-helper.js
└── unit
│ ├── .gitkeep
│ └── index-nodetest.js
└── vendor
└── .gitkeep
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.js]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.hbs]
21 | insert_final_newline = false
22 | indent_style = space
23 | indent_size = 2
24 |
25 | [*.css]
26 | indent_style = space
27 | indent_size = 2
28 |
29 | [*.html]
30 | indent_style = space
31 | indent_size = 2
32 |
33 | [*.{diff,md}]
34 | trim_trailing_whitespace = false
35 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log
17 | testem.log
18 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "-Promise"
6 | ],
7 | "browser": true,
8 | "boss": true,
9 | "curly": true,
10 | "debug": false,
11 | "devel": true,
12 | "eqeqeq": true,
13 | "evil": true,
14 | "forin": false,
15 | "immed": false,
16 | "laxbreak": false,
17 | "newcap": true,
18 | "noarg": true,
19 | "noempty": false,
20 | "nonew": false,
21 | "nomen": false,
22 | "onevar": false,
23 | "plusplus": false,
24 | "regexp": false,
25 | "undef": true,
26 | "sub": true,
27 | "strict": false,
28 | "white": false,
29 | "eqnull": true,
30 | "esnext": true,
31 | "unused": true
32 | }
33 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components/
2 | tests/
3 | tmp/
4 | dist/
5 |
6 | .bowerrc
7 | .editorconfig
8 | .ember-cli
9 | .travis.yml
10 | .npmignore
11 | **/.gitkeep
12 | bower.json
13 | ember-cli-build.js
14 | Brocfile.js
15 | testem.json
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - "0.12"
5 |
6 | sudo: false
7 |
8 | cache:
9 | directories:
10 | - node_modules
11 |
12 | env:
13 | - EMBER_TRY_SCENARIO=default
14 | - EMBER_TRY_SCENARIO=ember-release
15 | - EMBER_TRY_SCENARIO=ember-beta
16 | - EMBER_TRY_SCENARIO=ember-canary
17 |
18 | matrix:
19 | fast_finish: true
20 | allow_failures:
21 | - env: EMBER_TRY_SCENARIO=ember-canary
22 |
23 | before_install:
24 | - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
25 | - "npm config set spin false"
26 | - "npm install -g npm@^2"
27 |
28 | install:
29 | - npm install -g bower
30 | - npm install
31 | - bower install
32 |
33 | script:
34 | - ember try $EMBER_TRY_SCENARIO test
35 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp"]
3 | }
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ember-cli-deploy-sentry Changelog
2 |
3 | ### 0.7.0
4 | - Add ability to associate a commit with a release [#62]
5 | - Make it obvious where to get the keys for hosted accounts [#59]
6 | - Update mock-fs to use more recent versions of Node.js [#55]
7 | - Upload on didPrepare hook to fix gzip issues [#52]
8 |
9 | ### 0.5.5
10 | - Remove jQuery usages [#45]
11 |
12 | ### 0.5.4
13 | - Remove sentryApiKey from required config params [#43]
14 | - Add strictSSL option for request [#43]
15 |
16 | ### 0.5.3
17 | - Remove to prevent IE10 from breaking [#40]
18 |
19 | ### 0.5.2
20 | - Fix deprecation warning for ember-cli/lib/ext/promise [#35]
21 | - Add config documentation [#33]
22 |
23 | ### 0.5.1
24 | - Remove documentation for `didDeployMessage` config option as its gone
25 |
26 | ### 0.5.0
27 | Thanks to @kmiyashiro, @Turbo87 and especially @duizendnegen for making this release happen!
28 |
29 | - Add bearer token authentication [#21]
30 | - Support ember-cli-deploy-plugin 0.2.9 [#27]
31 |
32 | ### 0.4.0
33 |
34 | - Gracefully handle reuploading sourcemaps for releases with assigned issues
35 | - Several logging improvements
36 | - Fix releaseMetaName not being respected by raven service
37 | - Several Documentation fixes
38 |
39 | ### 0.3.1
40 |
41 | - Fix possibly broken tarball
42 |
43 | ### 0.3.0
44 |
45 | - Rate limit uploaded sourcemaps
46 | - Update mock-fs dependency to support newer versions of node
47 | - Use prepare hook instead of didBuild hook to catch revision data
48 | - Fix windows issues by using form-data library directly
49 |
50 | ### 0.2.1
51 |
52 | - Fix logging
53 |
54 | ### 0.2.0
55 |
56 | - Add service for usage with ember-cli-sentry
57 |
58 | ### 0.1.0
59 |
60 | - Initial release.
61 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ember-cli-deploy-sentry [](https://circleci.com/gh/dschmidt/ember-cli-deploy-sentry/tree/master)
2 |
3 | > An ember-cli-deploy-plugin to upload javascript sourcemaps to [Sentry][1].
4 |
5 | [](http://ember-cli-deploy.github.io/ember-cli-deploy-version-badges/)
6 |
7 | ## What is an ember-cli-deploy plugin?
8 |
9 | A plugin is an addon that can be executed as a part of the ember-cli-deploy pipeline. A plugin will implement one or more of the ember-cli-deploy's pipeline hooks.
10 |
11 | For more information on what plugins are and how they work, please refer to the [Plugin Documentation][10].
12 |
13 | ## Quick Start
14 | To get up and running quickly, do the following:
15 |
16 | - Ensure [ember-cli-deploy-build][11] is installed and configured.
17 |
18 | - Install this plugin
19 |
20 | ```bash
21 | $ ember install ember-cli-deploy-sentry
22 | ```
23 |
24 | - For hosted accounts, generate your bearer/api key here: https://sentry.io/api/
25 | - Place the following configuration into `config/deploy.js`
26 |
27 | ```javascript
28 | ENV.sentry = {
29 | // the URL or CDN your js assets are served from
30 | publicUrl: 'https://your.awesome.site',
31 | // the sentry install you're using, https://sentry.io for hosted accounts
32 | sentryUrl: 'https://sentry.your.awesome.site',
33 | sentryOrganizationSlug: 'AwesomeOrg',
34 | sentryProjectSlug: 'AwesomeProject',
35 |
36 | // One of:
37 | sentryApiKey: 'awesomeApiKey',
38 | // or
39 | sentryBearerApiKey: 'awesomeApiKey'
40 | }
41 | ```
42 | - Integrate [raven-js][2] in your page
43 |
44 | Install [ember-cli-sentry](https://github.com/damiencaselli/ember-cli-sentry) but import the raven service from `ember-cli-deploy-sentry/services/raven`,
45 | which will automatically handle setting up the release version for you. Sentry needs this to find the correct sourcemap for an error that occurs.
46 |
47 | If you don't want to use `ember-cli-sentry` but set [raven-js][2] up manually see [Manual integration with raven-js](#manual-integration-with-raven-js).
48 |
49 |
50 | - Build sourcemaps in production environment
51 |
52 | `ember-cli` builds sourcemaps only in development environment by default. In order to build them always,
53 | just add the following to your `EmberApp` options.
54 | ```
55 | sourcemaps: {
56 | enabled: true,
57 | extensions: ['js']
58 | }
59 | ```
60 |
61 | See also: [ember-cli documentation](http://www.ember-cli.com/user-guide/#source-map)
62 |
63 |
64 | - Run the pipeline
65 |
66 | ```bash
67 | $ ember deploy
68 | ```
69 |
70 | ## Installation
71 | Run the following command in your terminal:
72 |
73 | ```bash
74 | ember install ember-cli-deploy-sentry
75 | ```
76 |
77 | For general information on how to setup [Sentry][1] and [raven-js][2] you probably want to check out the official [Sentry Documentation][3] especially on [Sourcemaps][4].
78 |
79 | ## ember-cli-deploy Hooks Implemented
80 |
81 | For detailed information on what plugin hooks are and how they work, please refer to the [Plugin Documentation][10].
82 |
83 | - `configure`
84 | - `upload`
85 | - `didDeploy`
86 |
87 | ## Configuration Options
88 |
89 | For detailed information on how configuration of plugins works, please refer to the [Plugin Documentation][10].
90 |
91 | ### publicUrl
92 |
93 | The public url to the root of where your assets are stored. For instance, if your assets are stored on Cloudfront, it would be `https://xxxx.cloudfront.net`.
94 |
95 | *Required*
96 |
97 | ### sentryUrl
98 |
99 | The url of the sentry installation that `ember-cli-deploy-sentry` shall upload sourcemaps and javascript files to.
100 | If you are deploying in your local network, keep in mind you might need to use the local hostname/IP address.
101 |
102 | *Required*
103 |
104 | ### sentryOrganizationSlug
105 |
106 | The slug of the organization you want to upload sourcemaps for.
107 | You can specify this in organization settings in sentry.
108 |
109 | *Required*
110 |
111 | ### sentryProjectSlug
112 |
113 | The slug of the project you want to upload sourcemaps for.
114 | You can specify this in project settings in sentry.
115 |
116 | *Required*
117 |
118 | ### sentryApiKey _or_ sentryBearerApiKey
119 |
120 | Either an HTTP Basic Auth username, or a bearer token. If you are uploading to the current Sentry API, use the latter. Use the former if you are using an older API.
121 |
122 | You can create the api key in your organization settings. Make sure it has the `project:write` privilege.
123 |
124 | *Required*
125 |
126 | ### distDir
127 |
128 | The root directory that all files matching the `filePattern` will be uploaded from. By default, this option will use the `distDir` property of the deployment context.
129 |
130 | *Default:* `context.distDir`
131 |
132 | ### filePattern
133 |
134 | `minimatch` expression that is used to determine which files should be uploaded from the `distDir`.
135 |
136 | *Default:* `/**/*.{js,map}`
137 |
138 | ### revisionKey
139 |
140 | The revision string that is used to create releases in sentry.
141 |
142 | *Default:*
143 | ```javascript
144 | revisionKey: function(context) {
145 | return context.revisionData && context.revisionData.revisionKey;
146 | }
147 | ```
148 |
149 | ### revisionCommits
150 |
151 | An array of revision commits allows us to associate commits with this Sentry release. See the [Sentry docs here](https://docs.sentry.io/workflow/releases/?platform=browser#using-the-api).
152 |
153 | *Default:*
154 | ```javascript
155 | revisionCommits: undefined
156 | ```
157 |
158 | *Examples:*
159 | ```javascript
160 | revisionCommits: function(context) {
161 | return [{
162 | repository:"owner-name/repo-name", // required
163 | id:"2da95dfb052f477380608d59d32b4ab9" // required
164 | }]
165 | }
166 | ```
167 |
168 | ### enableRevisionTagging
169 |
170 | Enable adding a meta tag with the current revisionKey into the head of your `index.html`.
171 |
172 | *Default* true
173 |
174 | ### replaceFiles
175 |
176 | At deploy-time, the plugin will check your Sentry instance for an existing release under the current `revisionKey`. If a release is found and this is set to `true`, all existing files for the matching release will be deleted before the current build's files are uploaded to Sentry. If this is set to `false`, the files on Sentry will remain untouched and the just-built files will not be uploaded.
177 |
178 | *Default* true
179 |
180 | ## Prerequisites
181 |
182 | The following properties are expected to be present on the deployment `context` object:
183 |
184 | - `distDir` (provided by [ember-cli-deploy-build][11])
185 | - `revisionData.revisionKey` (provided by [ember-cli-deploy-revision-data][12])
186 |
187 |
188 | ## Manual integration with raven-js
189 |
190 | By default a meta tag with the key name `sentry:revision` is inserted in your index.html:
191 | ```html
192 |
193 |
194 | ```
195 |
196 | When you setup [raven-js][2] you can retrieve it like this:
197 |
198 | ```javascript
199 | Raven.config({
200 | release: document.querySelector("meta[name='sentry:revision']").content
201 | });
202 | ```
203 |
204 | If you only want to use the sourcemap upload functionality of `ember-cli-deploy-sentry`, you can disable automatic meta tag insertion completely by setting [enableRevisionTagging](#enableRevisionTagging) to `false`.
205 |
206 |
207 | Last but not least make sure to setup proper exception catching like [this](https://github.com/getsentry/raven-js/blob/master/plugins/ember.js).
208 |
209 | ## Running Tests
210 |
211 | - `npm test`
212 |
213 | ## TODO
214 |
215 | - use `context.distFiles` from [ember-cli-deploy-build][11] instead globbing distDir again?
216 | - automatically setup raven-js? If you want this, let me know.
217 | - add revision tagging file pattern
218 | - make meta name configurable and document `service.releaseMetaName`
219 |
220 | ### State
221 |
222 | It works. We use it in production at [Hatchet](https://hatchet.is).
223 |
224 |
225 | [1]: https://getsentry.com "Sentry"
226 | [2]: https://github.com/getsentry/raven-js "raven-js"
227 | [3]: https://docs.getsentry.com/on-premise/clients/javascript/ "Sentry Documentation for Javascript clients"
228 | [4]: https://docs.getsentry.com/on-premise/clients/javascript/sourcemaps/ "Sentry Documentation for Javascript Sourcemaps"
229 |
230 | [10]: http://ember-cli.github.io/ember-cli-deploy/plugins "Plugin Documentation"
231 | [11]: https://github.com/zapnito/ember-cli-deploy-build "ember-cli-deploy-build"
232 | [12]: https://github.com/zapnito/ember-cli-deploy-revision-data "ember-cli-deploy-revision-data"
233 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/addon/.gitkeep
--------------------------------------------------------------------------------
/addon/services/raven.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import RavenService from 'ember-cli-sentry/services/raven';
3 |
4 | export default RavenService.extend({
5 | releaseMetaName: 'sentry:revision',
6 | release: Ember.computed('releaseMetaName', {
7 | get: function() {
8 | return document.querySelector(`meta[name='${this.get('releaseMetaName')}']`).content;
9 | }
10 | })
11 | });
12 |
13 |
--------------------------------------------------------------------------------
/app/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/app/.gitkeep
--------------------------------------------------------------------------------
/app/services/raven.js:
--------------------------------------------------------------------------------
1 | import RavenService from 'ember-cli-deply-sentry/services/raven';
2 |
3 | export default RavenService;
4 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-deploy-sentry",
3 | "dependencies": {
4 | "ember": "1.13.3",
5 | "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
6 | "ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
7 | "ember-data": "1.13.5",
8 | "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
9 | "ember-qunit": "0.4.1",
10 | "ember-qunit-notifications": "0.0.7",
11 | "ember-resolver": "~0.1.18",
12 | "jquery": "^1.11.1",
13 | "loader.js": "ember-cli/loader.js#3.2.0",
14 | "qunit": "~1.17.1"
15 | }
16 | }
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | node:
3 | version: 0.12.0
4 |
5 | dependencies:
6 | pre:
7 | - npm install -g bower
8 | override:
9 | - npm i
10 | - bower i
11 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | scenarios: [
3 | {
4 | name: 'default',
5 | dependencies: { }
6 | },
7 | {
8 | name: 'ember-release',
9 | dependencies: {
10 | 'ember': 'components/ember#release'
11 | },
12 | resolutions: {
13 | 'ember': 'release'
14 | }
15 | },
16 | {
17 | name: 'ember-beta',
18 | dependencies: {
19 | 'ember': 'components/ember#beta'
20 | },
21 | resolutions: {
22 | 'ember': 'beta'
23 | }
24 | },
25 | {
26 | name: 'ember-canary',
27 | dependencies: {
28 | 'ember': 'components/ember#canary'
29 | },
30 | resolutions: {
31 | 'ember': 'canary'
32 | }
33 | }
34 | ]
35 | };
36 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(/* environment, appConfig */) {
4 | return { };
5 | };
6 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 | 'use strict';
3 |
4 | var RSVP = require('rsvp');
5 | var DeployPluginBase = require('ember-cli-deploy-plugin');
6 | var SilentError = require('silent-error');
7 | var glob = require("glob");
8 | var urljoin_ = require("url-join");
9 | var request = require('request-promise');
10 | var path = require('path');
11 | var fs = require('fs');
12 | var throat = require('throat');
13 | var parse = require('parse-link-header');
14 |
15 | var urljoin = function(...args) {
16 | return urljoin_(...args).split('\\').join('/');
17 | }
18 |
19 | module.exports = {
20 | name: 'ember-cli-deploy-sentry',
21 |
22 | contentFor: function(type/*, config*/) {
23 | if (type === 'head-footer') {
24 | return '';
25 | }
26 | },
27 |
28 | createDeployPlugin: function(options) {
29 | var DeployPlugin = DeployPluginBase.extend({
30 | name: options.name,
31 | defaultConfig: {
32 | distDir: function(context) {
33 | return context.distDir;
34 | },
35 | filePattern: '/**/*.{js,map}',
36 | revisionKey: function(context) {
37 | return context.revisionData && context.revisionData.revisionKey;
38 | },
39 | revisionCommits: undefined,
40 | enableRevisionTagging: true,
41 | replaceFiles: true,
42 | strictSSL: true,
43 | },
44 | requiredConfig: ['publicUrl', 'sentryUrl', 'sentryOrganizationSlug', 'sentryProjectSlug', 'revisionKey'],
45 |
46 | prepare: function(context) {
47 | var isEnabled = this.readConfig('enableRevisionTagging');
48 | if(!isEnabled) {
49 | return;
50 | }
51 |
52 | var revisionKey = this.readConfig('revisionKey');
53 | if(!revisionKey) {
54 | return new SilentError("Could not find revision key to fingerprint Sentry revision with.");
55 | }
56 |
57 | // TODO instead of plainly reading index.html, minimatch
58 | // getConfig('revision patterns') on context.distFiles
59 | var indexPath = path.join(context.distDir, "index.html");
60 | var index = fs.readFileSync(indexPath, 'utf8');
61 | index = index.replace('',
62 | '');
63 | fs.writeFileSync(indexPath, index);
64 | },
65 |
66 | /**
67 | * Upload the sourcemaps to Sentry
68 | *
69 | * We intentionally use the semantically not quite correct `didPrepare` hook instead of `upload` to work around
70 | * an issue with ember-cli-deploy-gzip (and other compression plugins like -brotli or -compress), where gzipped
71 | * sourcemaps are uploaded that Sentry is not able to decompress automatically. By using a hook before `willUpload`
72 | * we will upload the still uncompressed files.
73 | *
74 | * See https://github.com/dschmidt/ember-cli-deploy-sentry/issues/26 and https://github.com/getsentry/sentry/issues/4566
75 | */
76 | didPrepare: function(/* context */) {
77 | this.sentrySettings = {
78 | url: this.readConfig('sentryUrl'),
79 | publicUrl: this.readConfig('publicUrl'),
80 | organizationSlug: this.readConfig('sentryOrganizationSlug'),
81 | projectSlug: this.readConfig('sentryProjectSlug'),
82 | apiKey: this.readConfig('sentryApiKey'),
83 | bearerApiKey: this.readConfig('sentryBearerApiKey'),
84 | release: this.readConfig('revisionKey'),
85 | commits: this.readConfig('revisionCommits'),
86 | };
87 | this.baseUrl = urljoin(this.sentrySettings.url, '/api/0/projects/', this.sentrySettings.organizationSlug, this.sentrySettings.projectSlug, '/releases/');
88 | this.releaseUrl = urljoin(this.baseUrl, this.sentrySettings.release, '/');
89 |
90 | if(!this.sentrySettings.release) {
91 | throw new SilentError('revisionKey setting is not available, either provide it manually or make sure the ember-cli-deploy-revision-data plugin is loaded');
92 | }
93 |
94 | return this.doesReleaseExist(this.releaseUrl)
95 | .then(this.handleExistingRelease.bind(this))
96 | .catch(this.createRelease.bind(this));
97 | },
98 |
99 | generateAuth: function() {
100 | var apiKey = this.sentrySettings.apiKey;
101 | var bearerApiKey = this.sentrySettings.bearerApiKey;
102 | if (bearerApiKey !== undefined) {
103 | return { bearer: bearerApiKey };
104 | }
105 | return { user: apiKey };
106 | },
107 |
108 | doesReleaseExist: function(releaseUrl) {
109 | return request({
110 | uri: releaseUrl,
111 | auth: this.generateAuth(),
112 | json: true,
113 | strictSSL: this.readConfig('strictSSL'),
114 | });
115 | },
116 | handleExistingRelease: function handleExistingRelease(response) {
117 | this.log('Release ' + response.version + ' exists.', {verbose: true});
118 | this.log('Retrieving release files.', {verbose: true});
119 | return this._getReleaseFiles().then(function(response) {
120 | if (this.readConfig('replaceFiles')) {
121 | this.log('Replacing files.', {verbose: true});
122 | return RSVP.all(response.map(this._deleteFile, this))
123 | .then(this._doUpload.bind(this))
124 | .then(this._logFiles.bind(this, response));
125 | } else {
126 | this.log('Leaving files alone.', {verbose: true});
127 | return this._logFiles(response);
128 | }
129 | }.bind(this));
130 | },
131 | createRelease: function createRelease(error) {
132 | if (error.statusCode === 404) {
133 | this.log('Release does not exist. Creating.', {verbose: true});
134 | } else if (error.statusCode === 400) {
135 | this.log('Bad Request. Not Continuing');
136 | return RSVP.resolve(error.message);
137 | }
138 |
139 | var body = {
140 | version: this.sentrySettings.release
141 | };
142 | if (this.sentrySettings.commits) {
143 | body.commits = this.sentrySettings.commits;
144 | }
145 |
146 | return request({
147 | uri: this.baseUrl,
148 | method: 'POST',
149 | auth: this.generateAuth(),
150 | json: true,
151 | body: body,
152 | resolveWithFullResponse: true,
153 | strictSSL: this.readConfig('strictSSL'),
154 | })
155 | .then(this._doUpload.bind(this))
156 | .then(this._logFiles.bind(this))
157 | .catch(function(err){
158 | console.error(err);
159 | throw new SilentError('Creating release failed');
160 | });
161 | },
162 | _doUpload: function doUpload() {
163 | return this._getFilesToUpload()
164 | .then(this._uploadFileList.bind(this));
165 | },
166 | _getFilesToUpload: function getFilesToUpload() {
167 | this.log('Generating file list for upload', {verbose: true});
168 | var dir = this.readConfig('distDir');
169 | var filePattern = this.readConfig('filePattern');
170 | var pattern = path.join(dir, filePattern);
171 | return new RSVP.Promise(function(resolve, reject) {
172 | // options is optional
173 | glob(pattern, function (err, files) {
174 | if(err) {
175 | reject(err);
176 | } else {
177 | resolve(files);
178 | }
179 | });
180 | }).then(function(files) {
181 | return files.map(function(file) {
182 | return path.relative(dir, file);
183 | });
184 | });
185 | },
186 | _uploadFileList: function uploadFileList(files) {
187 | this.log('Beginning upload.', {verbose: true});
188 | return RSVP.all(files.map(throat(5, this._uploadFile.bind(this))))
189 | .then(this._getReleaseFiles.bind(this));
190 | },
191 | _uploadFile: function uploadFile(filePath) {
192 | var distDir = this.readConfig('distDir');
193 | var fileName = path.join(distDir, filePath);
194 |
195 | var formData = {
196 | name: urljoin(this.sentrySettings.publicUrl, filePath),
197 | file: fs.createReadStream(fileName),
198 | };
199 |
200 | return request({
201 | uri: urljoin(this.releaseUrl, 'files/'),
202 | method: 'POST',
203 | auth: this.generateAuth(),
204 | formData: formData,
205 | strictSSL: this.readConfig('strictSSL'),
206 | });
207 | },
208 | _getReleaseFiles: function getReleaseFiles(options = {}) {
209 | return request({
210 | uri: options.url || urljoin(this.releaseUrl, 'files/'),
211 | auth: this.generateAuth(),
212 | json: true,
213 | resolveWithFullResponse: true,
214 | strictSSL: this.readConfig('strictSSL'),
215 | }).then((response) => {
216 | var links = parse(response.headers.link);
217 |
218 | if (!links.next || links.next.results === 'false') {
219 | return response.body;
220 | }
221 |
222 | return this._getReleaseFiles({url: links.next.url}).then((results) => {
223 | return results.concat(response.body);
224 | });
225 | });
226 | },
227 | _deleteFile: function deleteFile(file) {
228 | this.log('Deleting ' + file.name, {verbose: true});
229 | return request({
230 | uri: urljoin(this.releaseUrl, 'files/', file.id, '/'),
231 | method: 'DELETE',
232 | auth: this.generateAuth(),
233 | strictSSL: this.readConfig('strictSSL'),
234 | });
235 | },
236 | _logFiles: function logFiles(response) {
237 | this.log('Files known to sentry for this release', { verbose: true });
238 | response.forEach(function(file) { this.log('✔ ' + file.name, { verbose: true }); }, this);
239 | },
240 |
241 | didDeploy: function(/* context */){
242 | var deployMessage = "Uploaded sourcemaps to sentry release: "
243 | + this.readConfig('sentryUrl')
244 | + '/'
245 | + this.readConfig('sentryOrganizationSlug')
246 | + '/'
247 | + this.readConfig('sentryProjectSlug')
248 | + '/releases/'
249 | + this.readConfig('revisionKey')
250 | + '/';
251 |
252 | if (this.readConfig('revisionCommits')) {
253 | deployMessage += '\n\t' + 'Commits ' + this.readConfig('revisionCommits').map(commit => commit.id).join(', ') + ' associated with this release';
254 | }
255 |
256 | this.log(deployMessage);
257 | }
258 | });
259 | return new DeployPlugin();
260 | }
261 | };
262 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-deploy-sentry",
3 | "version": "0.7.0",
4 | "description": "Ember CLI Deploy plugin to upload javascript sourcemaps to sentry.",
5 | "directories": {
6 | "doc": "doc",
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "start": "ember server",
11 | "build": "ember build",
12 | "test": "node tests/runner.js"
13 | },
14 | "repository": "dschmidt/ember-cli-deploy-sentry",
15 | "engines": {
16 | "node": ">= 10.20.1"
17 | },
18 | "author": "Dominik Schmidt ",
19 | "contributors": [
20 | "Pepijn Schoen "
21 | ],
22 | "license": "MIT",
23 | "devDependencies": {
24 | "broccoli-asset-rev": "^2.0.2",
25 | "chai": "^2.2.0",
26 | "chai-as-promised": "^5.0.0",
27 | "ember-cli": "1.13.1",
28 | "ember-cli-app-version": "0.4.0",
29 | "ember-cli-content-security-policy": "0.4.0",
30 | "ember-cli-dependency-checker": "^1.0.0",
31 | "ember-cli-htmlbars": "0.7.9",
32 | "ember-cli-htmlbars-inline-precompile": "^0.1.1",
33 | "ember-cli-ic-ajax": "0.2.1",
34 | "ember-cli-inject-live-reload": "^1.3.0",
35 | "ember-cli-qunit": "0.3.15",
36 | "ember-cli-release": "0.2.3",
37 | "ember-cli-uglify": "^1.0.1",
38 | "ember-data": "1.13.5",
39 | "ember-disable-prototype-extensions": "^1.0.0",
40 | "ember-disable-proxy-controllers": "^1.0.0",
41 | "ember-export-application-global": "^1.0.2",
42 | "ember-try": "0.0.6",
43 | "mocha": "^2.2.4",
44 | "mock-fs": "^4.7.0",
45 | "rsvp": "^3.1.0"
46 | },
47 | "keywords": [
48 | "ember-addon",
49 | "ember-cli-deploy-plugin"
50 | ],
51 | "dependencies": {
52 | "ember-cli-babel": "^6.6.0",
53 | "ember-cli-deploy-plugin": "^0.2.0",
54 | "glob": "^5.0.14",
55 | "parse-link-header": "^1.0.1",
56 | "request-promise": "^4.2.5",
57 | "silent-error": "^1.0.0",
58 | "throat": "^2.0.0",
59 | "url-join": "0.0.1"
60 | },
61 | "ember-addon": {
62 | "configPath": "tests/dummy/config",
63 | "after": [
64 | "ember-cli-deploy-revision-data",
65 | "ember-cli-sentry"
66 | ]
67 | },
68 | "volta": {
69 | "node": "10.20.1"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/testem.json:
--------------------------------------------------------------------------------
1 | {
2 | "framework": "qunit",
3 | "test_page": "tests/index.html?hidepassed",
4 | "disable_watching": true,
5 | "launch_in_ci": [
6 | "PhantomJS"
7 | ],
8 | "launch_in_dev": [
9 | "PhantomJS",
10 | "Chrome"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "DS",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName"
25 | ],
26 | "node": false,
27 | "browser": false,
28 | "boss": true,
29 | "curly": true,
30 | "debug": false,
31 | "devel": false,
32 | "eqeqeq": true,
33 | "evil": true,
34 | "forin": false,
35 | "immed": false,
36 | "laxbreak": false,
37 | "newcap": true,
38 | "noarg": true,
39 | "noempty": false,
40 | "nonew": false,
41 | "nomen": false,
42 | "onevar": false,
43 | "plusplus": false,
44 | "regexp": false,
45 | "undef": true,
46 | "sub": true,
47 | "strict": false,
48 | "white": false,
49 | "eqnull": true,
50 | "esnext": true,
51 | "unused": true
52 | }
53 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from 'ember/resolver';
3 | import loadInitializers from 'ember/load-initializers';
4 | import config from './config/environment';
5 |
6 | var App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver: Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/helpers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for 'head'}}
11 |
12 |
13 |
14 |
15 | {{content-for 'head-footer'}}
16 |
17 |
18 | {{content-for 'body'}}
19 |
20 |
21 |
22 |
23 | {{content-for 'body-footer'}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | var Router = Ember.Router.extend({
5 | location: config.locationType
6 | });
7 |
8 | Router.map(function() {
9 | });
10 |
11 | export default Router;
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/routes/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/styles/app.css
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | Welcome to Ember.js
2 |
3 | {{outlet}}
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/dummy/app/templates/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: 'dummy',
6 | environment: environment,
7 | baseURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | }
14 | },
15 |
16 | APP: {
17 | // Here you can pass flags/options to your application instance
18 | // when it is created
19 | }
20 | };
21 |
22 | if (environment === 'development') {
23 | // ENV.APP.LOG_RESOLVER = true;
24 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
25 | // ENV.APP.LOG_TRANSITIONS = true;
26 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
27 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
28 | }
29 |
30 | if (environment === 'test') {
31 | // Testem prefers this...
32 | ENV.baseURL = '/';
33 | ENV.locationType = 'none';
34 |
35 | // keep test console output quieter
36 | ENV.APP.LOG_ACTIVE_GENERATION = false;
37 | ENV.APP.LOG_VIEW_LOOKUPS = false;
38 |
39 | ENV.APP.rootElement = '#ember-testing';
40 | }
41 |
42 | if (environment === 'production') {
43 |
44 | }
45 |
46 | return ENV;
47 | };
48 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember/resolver';
2 | import config from '../../config/environment';
3 |
4 | var resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | var application;
7 |
8 | var attributes = Ember.merge({}, config.APP);
9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | Ember.run(function() {
12 | application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | });
16 |
17 | return application;
18 | }
19 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for 'head'}}
11 | {{content-for 'test-head'}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for 'head-footer'}}
18 | {{content-for 'test-head-footer'}}
19 |
20 |
21 |
22 | {{content-for 'body'}}
23 | {{content-for 'test-body'}}
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{content-for 'body-footer'}}
31 | {{content-for 'test-body-footer'}}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/tests/runner.js:
--------------------------------------------------------------------------------
1 | /*jshint globalstrict: true*/
2 | 'use strict';
3 |
4 | var glob = require('glob');
5 | var Mocha = require('mocha');
6 |
7 | var mocha = new Mocha({
8 | reporter: 'spec'
9 | });
10 |
11 | var arg = process.argv[2];
12 | var root = 'tests/';
13 |
14 | function addFiles(mocha, files) {
15 | glob.sync(root + files).forEach(mocha.addFile.bind(mocha));
16 | }
17 |
18 | addFiles(mocha, '/**/*-nodetest.js');
19 |
20 | if (arg === 'all') {
21 | addFiles(mocha, '/**/*-nodetest-slow.js');
22 | }
23 |
24 | mocha.run(function(failures) {
25 | process.on('exit', function() {
26 | process.exit(failures);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/tests/unit/.gitkeep
--------------------------------------------------------------------------------
/tests/unit/index-nodetest.js:
--------------------------------------------------------------------------------
1 | /*jshint globalstrict: true*/
2 | 'use strict';
3 |
4 | var RSVP = require('ember-cli/lib/ext/promise');
5 |
6 | var assert = require('ember-cli/tests/helpers/assert');
7 |
8 | var mockFs = require('mock-fs');
9 | var fs = require('fs');
10 |
11 | describe('deploySentry plugin', function() {
12 | var subject, mockUi, context;
13 |
14 | before(function() {
15 | subject = require('../../index');
16 | });
17 |
18 | beforeEach(function() {
19 | mockUi = {
20 | verbose: true,
21 | messages: [],
22 | write: function() { },
23 | writeLine: function(message) {
24 | this.messages.push(message);
25 | }
26 | };
27 |
28 | context = {
29 | distFiles: ['app.css', 'app.js'],
30 | ui: mockUi,
31 | config: {
32 | deploySentry: {
33 | publicUrl: 'http://example.org',
34 | sentryUrl: 'http://example.org',
35 | sentryOrganizationSlug: 'slug',
36 | sentryProjectSlug: 'slug',
37 | sentryApiKey: 'api-key',
38 | revisionKey: 'abcdef'
39 | }
40 | }
41 | };
42 | });
43 |
44 | it('has a name', function() {
45 | var plugin = subject.createDeployPlugin({
46 | name: 'test-plugin'
47 | });
48 |
49 | assert.equal(plugin.name, 'test-plugin');
50 | });
51 |
52 | it('implements the correct deployment hooks', function() {
53 | var plugin = subject.createDeployPlugin({
54 | name: 'test-plugin'
55 | });
56 |
57 | assert.equal(typeof plugin.configure, 'function');
58 | assert.equal(typeof plugin.prepare, 'function');
59 | assert.equal(typeof plugin.didPrepare, 'function');
60 | assert.equal(typeof plugin.didDeploy, 'function');
61 | });
62 |
63 | describe('configure hook', function() {
64 | it('does not throw if config is ok', function() {
65 | var plugin = subject.createDeployPlugin({
66 | name: 'deploySentry'
67 | });
68 | plugin.beforeHook(context);
69 | plugin.configure(context);
70 | assert.ok(true); // it didn't throw
71 | });
72 |
73 | it('throws if config is not valid', function() {
74 | var plugin = subject.createDeployPlugin({
75 | name: 'deploySentry'
76 | });
77 |
78 | context.config = { deploySentry: {} };
79 |
80 | plugin.beforeHook(context);
81 | assert.throws(function(){
82 | plugin.configure(context);
83 | });
84 | });
85 |
86 | describe('without providing config', function () {
87 | var plugin;
88 |
89 | beforeEach(function() {
90 | plugin = subject.createDeployPlugin({
91 | name: 'deploySentry'
92 | });
93 | });
94 |
95 | it('warns about missing required config', function() {
96 | context.config = { deploySentry: {} };
97 |
98 | plugin.beforeHook(context);
99 | assert.throws(function(error){
100 | plugin.configure(context);
101 | });
102 | var messages = mockUi.messages.reduce(function(previous, current) {
103 | if (/- Missing required config:\s.*/.test(current)) {
104 | previous.push(current);
105 | }
106 |
107 | return previous;
108 | }, []);
109 |
110 | assert.equal(messages.length, 1); // doesn't log all failures, just first one
111 | });
112 |
113 | it('warns about missing optional config', function() {
114 | plugin.beforeHook(context);
115 | plugin.configure(context);
116 | var messages = mockUi.messages.reduce(function(previous, current) {
117 | if (/- Missing config:\s.*, using default:\s/.test(current)) {
118 | previous.push(current);
119 | }
120 |
121 | return previous;
122 | }, []);
123 |
124 | assert.equal(messages.length, 6);
125 | });
126 |
127 | it('adds default config to the config object', function() {
128 | plugin.beforeHook(context);
129 | plugin.configure(context);
130 | assert.isDefined(context.config.deploySentry.distDir);
131 | assert.isDefined(context.config.deploySentry.filePattern);
132 | assert.isDefined(context.config.deploySentry.enableRevisionTagging);
133 | });
134 | });
135 |
136 | describe('with optional config supplied', function () {
137 | var plugin;
138 |
139 | beforeEach(function() {
140 | plugin = subject.createDeployPlugin({
141 | name: 'deploySentry'
142 | });
143 | context.config.deploySentry["distDir"] = "dist/dir";
144 | context.config.deploySentry["filePattern"] = "/**/*.{js,map}";
145 | context.config.deploySentry["enableRevisionTagging"] = false;
146 | context.config.deploySentry["replaceFiles"] = true;
147 | context.config.deploySentry["strictSSL"] = true;
148 | context.config.deploySentry["revisionCommits"] = [{
149 | "repository":"owner-org/repo-name",
150 | "id":"4c9c05d912292cb1b3e63c7947505cf19366c078"
151 | }];
152 | });
153 |
154 | it('does not warn about missing optional config', function() {
155 | plugin.beforeHook(context);
156 | plugin.configure(context);
157 | var messages = mockUi.messages.reduce(function(previous, current) {
158 | if (/- Missing config:\s.*, using default:\s/.test(current)) {
159 | previous.push(current);
160 | }
161 |
162 | return previous;
163 | }, []);
164 |
165 | assert.equal(messages.length, 0);
166 | });
167 | });
168 | });
169 |
170 | describe('contentFor hook', function() {
171 | it('is defined', function() {
172 | assert.equal(typeof subject.contentFor, 'function');
173 | });
174 | it('returns content for head-footer', function() {
175 | assert.equal(subject.contentFor('head-footer'), '');
176 | });
177 | it('does not return content for other types', function() {
178 | assert.notEqual(subject.contentFor('head-barter'), '');
179 | })
180 | });
181 |
182 | describe('prepare hook', function() {
183 | var plugin, fileSystem, indexFile;
184 | beforeEach(function() {
185 | plugin = subject.createDeployPlugin({
186 | name: 'deploySentry'
187 | });
188 | indexFile = mockFs.file({
189 | content: ''
190 | });
191 | fileSystem = {
192 | '/path/to/fake/dir': {
193 | 'index.html': indexFile
194 | }
195 | };
196 | mockFs(fileSystem);
197 | context.distDir = '/path/to/fake/dir';
198 | context.revisionKey = 'abc123';
199 | });
200 | afterEach(function() {
201 | mockFs.restore();
202 | });
203 |
204 | it('does not fill in revision data when disabled', function() {
205 | context.config.deploySentry.enableRevisionTagging = false;
206 |
207 | plugin.beforeHook(context);
208 | plugin.configure(context);
209 | plugin.prepare(context);
210 | var result = fs.readFileSync('/path/to/fake/dir/index.html', 'utf8');
211 | assert.notEqual(result.indexOf(''), -1);
212 | });
213 |
214 | it('fills in revision data in the meta-tag', function() {
215 | plugin.beforeHook(context);
216 | plugin.configure(context);
217 | plugin.prepare(context);
218 | var result = fs.readFileSync('/path/to/fake/dir/index.html', 'utf8');
219 | assert.notEqual(result.indexOf(''), -1);
220 | });
221 | });
222 |
223 | describe('upload hook', function() {
224 | // possibly mock Sentry out here
225 | });
226 | });
227 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschmidt/ember-cli-deploy-sentry/13de676f015ca727166d6ba1e6de92950ba5f015/vendor/.gitkeep
--------------------------------------------------------------------------------