diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4659722854e..71ddebef662 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -364,10 +364,11 @@ update-tests-metadata:
- rspec_flaky/
policy: push
script:
- - retry gem install fog-aws mime-types
+ - retry gem install fog-aws mime-types activesupport
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
+ - FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
@@ -735,16 +736,50 @@ codequality:
expire_in: 1 week
sast:
- <<: *except-docs
- image: registry.gitlab.com/gitlab-org/gl-sast:latest
+ <<: *dedicated-no-docs-no-db-pull-cache-job
+ image: docker:stable
variables:
- CONFIDENCE_LEVEL: 2
+ SAST_CONFIDENCE_LEVEL: 2
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ tags: []
before_script: []
+ cache: {}
+ dependencies: []
+ services:
+ - docker:stable-dind
script:
- - /app/bin/run .
+ - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ - docker run
+ --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}"
+ --volume "$PWD:/code"
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
artifacts:
paths: [gl-sast-report.json]
+dependency_scanning:
+ <<: *dedicated-no-docs-no-db-pull-cache-job
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ tags: []
+ before_script: []
+ cache: {}
+ dependencies: []
+ services:
+ - docker:stable-dind
+ script:
+ - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ - docker run
+ --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}"
+ --volume "$PWD:/code"
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
+ artifacts:
+ paths: [gl-dependency-scanning-report.json]
+
qa:internal:
<<: *dedicated-no-docs-no-db-pull-cache-job
services: []
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9109f04fb17..d56c86523f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,24 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 10.6.4 (2018-04-09)
+
+### Fixed (8 changes, 1 of them is from the community)
+
+- Correct copy text for the promote milestone and label modals. !17726
+- Avoid validation errors when running the Pages domain verification service. !17992
+- Fix autolinking URLs containing ampersands. !18045
+- Fix exceptions raised when migrating pipeline stages in the background. !18076
+- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
+- Don't show Jump to Discussion button on Issues.
+- Fix listing commit branch/tags that contain special characters.
+- Fix 404 in group boards when moving issue between lists.
+
+### Performance (1 change)
+
+- Free open file descriptors and libgit2 buffers in UpdatePagesService.
+
+
## 10.6.3 (2018-04-03)
### Security (2 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index c5c735103b2..5f8cbfdb7d7 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.94.0
+0.95.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index fcdb2e109f6..ee74734aa22 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-4.0.0
+4.1.0
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 03fe5f2ed26..c953b9708a0 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -321,6 +321,9 @@ GEM
rubyntlm (~> 0.5)
globalid (0.4.1)
activesupport (>= 4.2.0)
+ goldiloader (2.0.1)
+ activerecord (>= 4.2, < 5.2)
+ activesupport (>= 4.2, < 5.2)
gollum-grit_adapter (1.0.1)
gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.2.7)
@@ -878,7 +881,7 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
slack-notifier (1.5.1)
- spinach (0.10.1)
+ spinach (0.8.10)
colorize
gherkin-ruby (>= 0.3.2)
json
@@ -1072,6 +1075,7 @@ DEPENDENCIES
gitlab-markup (~> 1.6.2)
gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4)
+ goldiloader (~> 2.0)
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.4)
gon (~> 6.1.0)
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 466a5b5d635..24d63b99a29 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -55,22 +55,20 @@
},
methods: {
successCallback(resp) {
- return resp.json().then((response) => {
- // depending of the endpoint the response can either bring a `pipelines` key or not.
- const pipelines = response.pipelines || response;
- this.setCommonData(pipelines);
+ // depending of the endpoint the response can either bring a `pipelines` key or not.
+ const pipelines = resp.data.pipelines || resp.data;
+ this.setCommonData(pipelines);
- const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
- detail: {
- pipelines: response,
- },
- });
-
- // notifiy to update the count in tabs
- if (this.$el.parentElement) {
- this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
- }
+ const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
+ detail: {
+ pipelines: resp.data,
+ },
});
+
+ // notifiy to update the count in tabs
+ if (this.$el.parentElement) {
+ this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
+ }
},
},
};
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index a195162b7f2..e18972f4298 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -22,7 +22,7 @@ export default {
...mapState(['rightPanelCollapsed', 'viewer', 'delayViewerUpdated', 'panelResizing']),
...mapGetters(['currentMergeRequest']),
shouldHideEditor() {
- return this.file && this.file.binary && !this.file.raw;
+ return this.file && this.file.binary && !this.file.content;
},
editTabCSS() {
return {
@@ -212,7 +212,7 @@ export default {
+ {{ __('Quick actions can be used in the issues description and comment boxes.') }} +
++
++
+ + {{ __('Learn more') }} + +testing 123
', + }); + vm.$nextTick(done); }); + afterEach(() => { + mock.restore(); + }); + it('renders an Edit and a Preview Tab', done => { Vue.nextTick(() => { const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li'); @@ -99,6 +116,26 @@ describe('RepoEditor', () => { done(); }); }); + + it('renders markdown for tempFile', done => { + vm.file.tempFile = true; + vm.file.path = `${vm.file.path}.md`; + vm.$store.state.entries[vm.file.path] = vm.file; + + vm + .$nextTick() + .then(() => { + vm.$el.querySelectorAll('.ide-mode-tabs .nav-links a')[1].click(); + }) + .then(setTimeoutPromise) + .then(() => { + expect(vm.$el.querySelector('.preview-container').innerHTML).toContain( + 'testing 123
', + ); + }) + .then(done) + .catch(done.fail); + }); }); describe('when open file is binary and not raw', () => { diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js index ab81aabb992..1dfe890e05e 100644 --- a/spec/javascripts/notes/components/note_actions_spec.js +++ b/spec/javascripts/notes/components/note_actions_spec.js @@ -3,7 +3,7 @@ import store from '~/notes/stores'; import noteActions from '~/notes/components/note_actions.vue'; import { userDataMock } from '../mock_data'; -describe('issse_note_actions component', () => { +describe('issue_note_actions component', () => { let vm; let Component; @@ -24,6 +24,7 @@ describe('issse_note_actions component', () => { authorId: 26, canDelete: true, canEdit: true, + canAwardEmoji: true, canReportAsAbuse: true, noteId: 539, reportAbusePath: '/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26', @@ -70,6 +71,7 @@ describe('issse_note_actions component', () => { authorId: 26, canDelete: false, canEdit: false, + canAwardEmoji: false, canReportAsAbuse: false, noteId: 539, reportAbusePath: '/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26', diff --git a/spec/javascripts/notes/components/note_awards_list_spec.js b/spec/javascripts/notes/components/note_awards_list_spec.js index 15995ec5a05..1c30d8691b1 100644 --- a/spec/javascripts/notes/components/note_awards_list_spec.js +++ b/spec/javascripts/notes/components/note_awards_list_spec.js @@ -29,6 +29,7 @@ describe('note_awards_list component', () => { awards: awardsMock, noteAuthorId: 2, noteId: 545, + canAwardEmoji: true, toggleAwardPath: '/gitlab-org/gitlab-ce/notes/545/toggle_award_emoji', }, }).$mount(); @@ -43,14 +44,45 @@ describe('note_awards_list component', () => { expect(vm.$el.querySelector('.js-awards-block button [data-name="cartwheel_tone3"]')).toBeDefined(); }); - it('should be possible to remove awareded emoji', () => { + it('should be possible to remove awarded emoji', () => { spyOn(vm, 'handleAward').and.callThrough(); + spyOn(vm, 'toggleAwardRequest').and.callThrough(); vm.$el.querySelector('.js-awards-block button').click(); expect(vm.handleAward).toHaveBeenCalledWith('flag_tz'); + expect(vm.toggleAwardRequest).toHaveBeenCalled(); }); it('should be possible to add new emoji', () => { expect(vm.$el.querySelector('.js-add-award')).toBeDefined(); }); + + describe('when the user cannot award emoji', () => { + beforeEach(() => { + const Component = Vue.extend(awardsNote); + + vm = new Component({ + store, + propsData: { + awards: awardsMock, + noteAuthorId: 2, + noteId: 545, + canAwardEmoji: false, + toggleAwardPath: '/gitlab-org/gitlab-ce/notes/545/toggle_award_emoji', + }, + }).$mount(); + }); + + it('should not be possible to remove awarded emoji', () => { + spyOn(vm, 'toggleAwardRequest').and.callThrough(); + + vm.$el.querySelector('.js-awards-block button').click(); + + expect(vm.toggleAwardRequest).not.toHaveBeenCalled(); + }); + + it('should not be possible to add new emoji', () => { + expect(vm.$el.querySelector('.js-add-award')).toBeNull(); + }); + }); }); diff --git a/spec/javascripts/notes/components/note_body_spec.js b/spec/javascripts/notes/components/note_body_spec.js index 0ff804f0e55..4e551496ff0 100644 --- a/spec/javascripts/notes/components/note_body_spec.js +++ b/spec/javascripts/notes/components/note_body_spec.js @@ -18,6 +18,7 @@ describe('issue_note_body component', () => { propsData: { note, canEdit: true, + canAwardEmoji: true, }, }).$mount(); }); diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js index 24388fba219..bfe3a65feee 100644 --- a/spec/javascripts/notes/mock_data.js +++ b/spec/javascripts/notes/mock_data.js @@ -9,6 +9,7 @@ export const notesDataMock = { totalNotes: 1, closePath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=close', reopenPath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=reopen', + canAwardEmoji: true, }; export const userDataMock = { @@ -30,6 +31,7 @@ export const noteableDataMock = { current_user: { can_create_note: true, can_update: true, + can_award_emoji: true, }, description: '', due_date: null, @@ -86,7 +88,10 @@ export const individualNote = { human_access: 'Owner', note: 'sdfdsaf', note_html: "sdfdsaf
", - current_user: { can_edit: true }, + current_user: { + can_edit: true, + can_award_emoji: true, + }, discussion_id: '0fb4e0e3f9276e55ff32eb4195add694aece4edd', emoji_awardable: true, award_emoji: [ @@ -129,6 +134,7 @@ export const note = { note_html: 'Vel id placeat reprehenderit sit numquam.
', current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: 'd3842a451b7f3d9a5dfce329515127b2d29a4cd0', emoji_awardable: true, @@ -187,6 +193,7 @@ export const discussionMock = { note_html: "THIS IS A DICUSSSION!
", current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1', emoji_awardable: true, @@ -231,6 +238,7 @@ export const discussionMock = { }, current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1', emoji_awardable: true, @@ -275,6 +283,7 @@ export const discussionMock = { }, current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: '9e3bd2f71a01de45fd166e6719eb380ad9f270b1', emoji_awardable: true, @@ -365,6 +374,7 @@ export const INDIVIDUAL_NOTE_RESPONSE_MAP = { note_html: '\u003cp dir="auto"\u003esdfdsaf\u003c/p\u003e', current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: '0fb4e0e3f9276e55ff32eb4195add694aece4edd', emoji_awardable: true, @@ -425,6 +435,7 @@ export const INDIVIDUAL_NOTE_RESPONSE_MAP = { note_html: '\u003cp dir="auto"\u003eNew note!\u003c/p\u003e', current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: '70d5c92a4039a36c70100c6691c18c27e4b0a790', emoji_awardable: true, @@ -478,6 +489,7 @@ export const INDIVIDUAL_NOTE_RESPONSE_MAP = { }, current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: 'a3ed36e29b1957efb3b68c53e2d7a2b24b1df052', emoji_awardable: true, @@ -527,6 +539,7 @@ export const DISCUSSION_NOTE_RESPONSE_MAP = { note_html: '\u003cp dir="auto"\u003eAdding a comment\u003c/p\u003e', current_user: { can_edit: true, + can_award_emoji: true, }, discussion_id: 'a3ed36e29b1957efb3b68c53e2d7a2b24b1df052', emoji_awardable: true, diff --git a/spec/javascripts/pipelines/pipeline_details_mediator_spec.js b/spec/javascripts/pipelines/pipeline_details_mediator_spec.js index e58a8018ed5..61ee2dc13ca 100644 --- a/spec/javascripts/pipelines/pipeline_details_mediator_spec.js +++ b/spec/javascripts/pipelines/pipeline_details_mediator_spec.js @@ -1,42 +1,36 @@ -import _ from 'underscore'; -import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import PipelineMediator from '~/pipelines/pipeline_details_mediator'; describe('PipelineMdediator', () => { let mediator; + let mock; + beforeEach(() => { - mediator = new PipelineMediator({ endpoint: 'foo' }); + mock = new MockAdapter(axios); + mediator = new PipelineMediator({ endpoint: 'foo.json' }); + }); + + afterEach(() => { + mock.restore(); }); it('should set defaults', () => { - expect(mediator.options).toEqual({ endpoint: 'foo' }); + expect(mediator.options).toEqual({ endpoint: 'foo.json' }); expect(mediator.state.isLoading).toEqual(false); expect(mediator.store).toBeDefined(); expect(mediator.service).toBeDefined(); }); describe('request and store data', () => { - const interceptor = (request, next) => { - next(request.respondWith(JSON.stringify({ foo: 'bar' }), { - status: 200, - })); - }; - - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - }); - - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptor, interceptor); - }); - - it('should store received data', (done) => { + it('should store received data', done => { + mock.onGet('foo.json').reply(200, { id: '121123' }); mediator.fetchPipeline(); setTimeout(() => { - expect(mediator.store.state.pipeline).toEqual({ foo: 'bar' }); + expect(mediator.store.state.pipeline).toEqual({ id: '121123' }); done(); - }); + }, 0); }); }); }); diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js index 7e242eb45e1..d79544f83ad 100644 --- a/spec/javascripts/pipelines/pipelines_spec.js +++ b/spec/javascripts/pipelines/pipelines_spec.js @@ -1,5 +1,6 @@ -import _ from 'underscore'; import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import pipelinesComp from '~/pipelines/components/pipelines.vue'; import Store from '~/pipelines/stores/pipelines_store'; import mountComponent from 'spec/helpers/vue_mount_component_helper'; @@ -12,6 +13,8 @@ describe('Pipelines', () => { let PipelinesComponent; let pipelines; let vm; + let mock; + const paths = { endpoint: 'twitter/flight/pipelines.json', autoDevopsPath: '/help/topics/autodevops/index.md', @@ -34,6 +37,8 @@ describe('Pipelines', () => { }; beforeEach(() => { + mock = new MockAdapter(axios); + pipelines = getJSONFixture(jsonFixtureName); PipelinesComponent = Vue.extend(pipelinesComp); @@ -41,38 +46,14 @@ describe('Pipelines', () => { afterEach(() => { vm.$destroy(); + mock.restore(); }); - const pipelinesInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify(pipelines), { - status: 200, - })); - }; - - const emptyStateInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify({ - pipelines: [], - count: { - all: 0, - pending: 0, - running: 0, - finished: 0, - }, - }), { - status: 200, - })); - }; - - const errorInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify({}), { - status: 500, - })); - }; - describe('With permission', () => { describe('With pipelines in main tab', () => { beforeEach((done) => { - Vue.http.interceptors.push(pipelinesInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: true, @@ -85,12 +66,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, pipelinesInterceptor, - ); - }); - it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -116,7 +91,15 @@ describe('Pipelines', () => { describe('Without pipelines on main tab with CI', () => { beforeEach((done) => { - Vue.http.interceptors.push(emptyStateInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, { + pipelines: [], + count: { + all: 0, + pending: 0, + running: 0, + finished: 0, + }, + }); vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: true, @@ -129,12 +112,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, emptyStateInterceptor, - ); - }); - it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -158,7 +135,15 @@ describe('Pipelines', () => { describe('Without pipelines nor CI', () => { beforeEach((done) => { - Vue.http.interceptors.push(emptyStateInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, { + pipelines: [], + count: { + all: 0, + pending: 0, + running: 0, + finished: 0, + }, + }); vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: false, @@ -171,12 +156,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, emptyStateInterceptor, - ); - }); - it('renders empty state', () => { expect(vm.$el.querySelector('.js-empty-state h4').textContent.trim()).toEqual('Build with confidence'); expect(vm.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual(paths.helpPagePath); @@ -192,7 +171,7 @@ describe('Pipelines', () => { describe('When API returns error', () => { beforeEach((done) => { - Vue.http.interceptors.push(errorInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(500, {}); vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: false, @@ -205,12 +184,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, errorInterceptor, - ); - }); - it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -230,7 +203,8 @@ describe('Pipelines', () => { describe('Without permission', () => { describe('With pipelines in main tab', () => { beforeEach((done) => { - Vue.http.interceptors.push(pipelinesInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: false, @@ -243,12 +217,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, pipelinesInterceptor, - ); - }); - it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -268,7 +236,16 @@ describe('Pipelines', () => { describe('Without pipelines on main tab with CI', () => { beforeEach((done) => { - Vue.http.interceptors.push(emptyStateInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, { + pipelines: [], + count: { + all: 0, + pending: 0, + running: 0, + finished: 0, + }, + }); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: true, @@ -281,11 +258,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, emptyStateInterceptor, - ); - }); it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -303,7 +275,16 @@ describe('Pipelines', () => { describe('Without pipelines nor CI', () => { beforeEach((done) => { - Vue.http.interceptors.push(emptyStateInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, { + pipelines: [], + count: { + all: 0, + pending: 0, + running: 0, + finished: 0, + }, + }); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: false, @@ -316,12 +297,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, emptyStateInterceptor, - ); - }); - it('renders empty state without button to set CI', () => { expect(vm.$el.querySelector('.js-empty-state').textContent.trim()).toEqual('This project is not currently set up to run pipelines.'); expect(vm.$el.querySelector('.js-get-started-pipelines')).toBeNull(); @@ -337,7 +312,8 @@ describe('Pipelines', () => { describe('When API returns error', () => { beforeEach((done) => { - Vue.http.interceptors.push(errorInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(500, {}); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: false, @@ -350,12 +326,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, errorInterceptor, - ); - }); - it('renders tabs', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); @@ -375,7 +345,8 @@ describe('Pipelines', () => { describe('successfull request', () => { describe('with pipelines', () => { beforeEach(() => { - Vue.http.interceptors.push(pipelinesInterceptor); + mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines); + vm = mountComponent(PipelinesComponent, { store: new Store(), hasGitlabCi: true, @@ -384,12 +355,6 @@ describe('Pipelines', () => { }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, pipelinesInterceptor, - ); - }); - it('should render table', (done) => { setTimeout(() => { expect(vm.$el.querySelector('.table-holder')).toBeDefined(); diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js index 61c2f783acc..c2ed2e9a31b 100644 --- a/spec/javascripts/pipelines/stage_spec.js +++ b/spec/javascripts/pipelines/stage_spec.js @@ -1,27 +1,35 @@ -import _ from 'underscore'; import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import stage from '~/pipelines/components/stage.vue'; +import mountComponent from 'spec/helpers/vue_mount_component_helper'; describe('Pipelines stage component', () => { let StageComponent; let component; + let mock; beforeEach(() => { + mock = new MockAdapter(axios); + StageComponent = Vue.extend(stage); - component = new StageComponent({ - propsData: { - stage: { - status: { - group: 'success', - icon: 'icon_status_success', - title: 'success', - }, - dropdown_path: 'foo', + component = mountComponent(StageComponent, { + stage: { + status: { + group: 'success', + icon: 'icon_status_success', + title: 'success', }, - updateDropdown: false, + dropdown_path: 'path.json', }, - }).$mount(); + updateDropdown: false, + }); + }); + + afterEach(() => { + component.$destroy(); + mock.restore(); }); it('should render a dropdown with the status icon', () => { @@ -31,23 +39,11 @@ describe('Pipelines stage component', () => { }); describe('with successfull request', () => { - const interceptor = (request, next) => { - next(request.respondWith(JSON.stringify({ html: 'foo' }), { - status: 200, - })); - }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); + mock.onGet('path.json').reply(200, { html: 'foo' }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, interceptor, - ); - }); - - it('should render the received data', (done) => { + it('should render the received data', done => { component.$el.querySelector('button').click(); setTimeout(() => { @@ -60,20 +56,8 @@ describe('Pipelines stage component', () => { }); describe('when request fails', () => { - const interceptor = (request, next) => { - next(request.respondWith(JSON.stringify({}), { - status: 500, - })); - }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - }); - - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, interceptor, - ); + mock.onGet('path.json').reply(500); }); it('should close the dropdown', () => { @@ -86,33 +70,18 @@ describe('Pipelines stage component', () => { }); describe('update endpoint correctly', () => { - const updatedInterceptor = (request, next) => { - if (request.url === 'bar') { - next(request.respondWith(JSON.stringify({ html: 'this is the updated content' }), { - status: 200, - })); - } - next(); - }; - beforeEach(() => { - Vue.http.interceptors.push(updatedInterceptor); + mock.onGet('bar.json').reply(200, { html: 'this is the updated content' }); }); - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, updatedInterceptor, - ); - }); - - it('should update the stage to request the new endpoint provided', (done) => { + it('should update the stage to request the new endpoint provided', done => { component.stage = { status: { group: 'running', icon: 'running', title: 'running', }, - dropdown_path: 'bar', + dropdown_path: 'bar.json', }; Vue.nextTick(() => { @@ -121,7 +90,7 @@ describe('Pipelines stage component', () => { setTimeout(() => { expect( component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(), - ).toEqual('this is the updated content'); + ).toEqual('this is the updated content'); done(); }); }); diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js index b1b03ef1e09..423432c9e5d 100644 --- a/spec/javascripts/signin_tabs_memoizer_spec.js +++ b/spec/javascripts/signin_tabs_memoizer_spec.js @@ -4,7 +4,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; (() => { describe('SigninTabsMemoizer', () => { const fixtureTemplate = 'static/signin_tabs.html.raw'; - const tabSelector = 'ul.nav-tabs'; + const tabSelector = 'ul.new-session-tabs'; const currentTabKey = 'current_signin_tab'; let memo; @@ -27,7 +27,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; it('does nothing if no tab was previously selected', () => { createMemoizer(); - expect(document.querySelector('li a.active').getAttribute('id')).toEqual('standard'); + expect(document.querySelector(`${tabSelector} > li.active a`).getAttribute('href')).toEqual('#ldap'); }); it('shows last selected tab on boot', () => { @@ -48,9 +48,9 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; it('saves last selected tab on change', () => { createMemoizer(); - document.getElementById('standard').click(); + document.querySelector('a[href="#login-pane"]').click(); - expect(memo.readData()).toEqual('#standard'); + expect(memo.readData()).toEqual('#login-pane'); }); it('overrides last selected tab with hash tag when given', () => { diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js index d158786e484..14bff05e537 100644 --- a/spec/javascripts/test_bundle.js +++ b/spec/javascripts/test_bundle.js @@ -5,6 +5,7 @@ import '~/commons'; import Vue from 'vue'; import VueResource from 'vue-resource'; +import Translate from '~/vue_shared/translate'; import { getDefaultAdapter } from '~/lib/utils/axios_utils'; import { FIXTURES_PATH, TEST_HOST } from './test_constants'; @@ -22,12 +23,13 @@ Vue.config.warnHandler = (msg, vm, trace) => { }; let hasVueErrors = false; -Vue.config.errorHandler = function (err) { +Vue.config.errorHandler = function(err) { hasVueErrors = true; fail(err); }; Vue.use(VueResource); +Vue.use(Translate); // enable test fixtures jasmine.getFixtures().fixturesPath = FIXTURES_PATH; @@ -43,10 +45,11 @@ window.gl = window.gl || {}; window.gl.TEST_HOST = TEST_HOST; window.gon = window.gon || {}; window.gon.test_env = true; +gon.relative_url_root = ''; let hasUnhandledPromiseRejections = false; -window.addEventListener('unhandledrejection', (event) => { +window.addEventListener('unhandledrejection', event => { hasUnhandledPromiseRejections = true; console.error('Unhandled promise rejection:'); console.error(event.reason.stack || event.reason); @@ -69,15 +72,25 @@ beforeEach(() => { const axiosDefaultAdapter = getDefaultAdapter(); +let testFiles = process.env.TEST_FILES || []; +if (testFiles.length > 0) { + testFiles = testFiles.map(path => path.replace(/^spec\/javascripts\//, '').replace(/\.js$/, '')); + console.log(`Running only tests matching: ${testFiles}`); +} else { + console.log('Running all tests'); +} + // render all of our tests const testsContext = require.context('.', true, /_spec$/); -testsContext.keys().forEach(function (path) { +testsContext.keys().forEach(function(path) { try { - testsContext(path); + if (testFiles.length === 0 || testFiles.some(p => path.includes(p))) { + testsContext(path); + } } catch (err) { console.error('[ERROR] Unable to load spec: ', path); - describe('Test bundle', function () { - it(`includes '${path}'`, function () { + describe('Test bundle', function() { + it(`includes '${path}'`, function() { expect(err).toBeNull(); }); }); @@ -85,7 +98,7 @@ testsContext.keys().forEach(function (path) { }); describe('test errors', () => { - beforeAll((done) => { + beforeAll(done => { if (hasUnhandledPromiseRejections || hasVueWarnings || hasVueErrors) { setTimeout(done, 1000); } else { @@ -149,18 +162,18 @@ if (process.env.BABEL_ENV === 'coverage') { './issue_show/index.js', ]; - describe('Uncovered files', function () { + describe('Uncovered files', function() { const sourceFiles = require.context('~', true, /\.js$/); $.holdReady(true); - sourceFiles.keys().forEach(function (path) { + sourceFiles.keys().forEach(function(path) { // ignore if there is a matching spec file if (testsContext.keys().indexOf(`${path.replace(/\.js$/, '')}_spec`) > -1) { return; } - it(`includes '${path}'`, function () { + it(`includes '${path}'`, function() { try { sourceFiles(path); } catch (err) { diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js index 046968fbc1f..d797f1266df 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js @@ -1,47 +1,37 @@ import Vue from 'vue'; import UnresolvedDiscussions from '~/vue_merge_request_widget/components/states/unresolved_discussions.vue'; +import mountComponent from 'spec/helpers/vue_mount_component_helper'; describe('UnresolvedDiscussions', () => { - describe('props', () => { - it('should have props', () => { - const { mr } = UnresolvedDiscussions.props; + const Component = Vue.extend(UnresolvedDiscussions); + let vm; - expect(mr.type instanceof Object).toBeTruthy(); - expect(mr.required).toBeTruthy(); - }); + afterEach(() => { + vm.$destroy(); }); - describe('template', () => { - let el; - let vm; - const path = 'foo/bar'; - + describe('with discussions path', () => { beforeEach(() => { - const Component = Vue.extend(UnresolvedDiscussions); - const mr = { - createIssueToResolveDiscussionsPath: path, - }; - vm = new Component({ - el: document.createElement('div'), - propsData: { mr }, - }); - el = vm.$el; + vm = mountComponent(Component, { mr: { + createIssueToResolveDiscussionsPath: gl.TEST_HOST, + } }); }); it('should have correct elements', () => { - expect(el.classList.contains('mr-widget-body')).toBeTruthy(); - expect(el.innerText).toContain('There are unresolved discussions. Please resolve these discussions'); - expect(el.innerText).toContain('Create an issue to resolve them later'); - expect(el.querySelector('.js-create-issue').getAttribute('href')).toEqual(path); + expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions'); + expect(vm.$el.innerText).toContain('Create an issue to resolve them later'); + expect(vm.$el.querySelector('.js-create-issue').getAttribute('href')).toEqual(gl.TEST_HOST); + }); + }); + + describe('without discussions path', () => { + beforeEach(() => { + vm = mountComponent(Component, { mr: {} }); }); - it('should not show create issue button if user cannot create issue', (done) => { - vm.mr.createIssueToResolveDiscussionsPath = ''; - - Vue.nextTick(() => { - expect(el.querySelector('.js-create-issue')).toEqual(null); - done(); - }); + it('should not show create issue link if user cannot create issue', () => { + expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions'); + expect(vm.$el.querySelector('.js-create-issue')).toEqual(null); }); }); }); diff --git a/spec/javascripts/vue_shared/components/markdown/header_spec.js b/spec/javascripts/vue_shared/components/markdown/header_spec.js index edebd822295..02117638b63 100644 --- a/spec/javascripts/vue_shared/components/markdown/header_spec.js +++ b/spec/javascripts/vue_shared/components/markdown/header_spec.js @@ -1,10 +1,11 @@ import Vue from 'vue'; +import $ from 'jquery'; import headerComponent from '~/vue_shared/components/markdown/header.vue'; describe('Markdown field header component', () => { let vm; - beforeEach((done) => { + beforeEach(done => { const Component = Vue.extend(headerComponent); vm = new Component({ @@ -17,24 +18,18 @@ describe('Markdown field header component', () => { }); it('renders markdown buttons', () => { - expect( - vm.$el.querySelectorAll('.js-md').length, - ).toBe(7); + expect(vm.$el.querySelectorAll('.js-md').length).toBe(7); }); it('renders `write` link as active when previewMarkdown is false', () => { - expect( - vm.$el.querySelector('li:nth-child(1)').classList.contains('active'), - ).toBeTruthy(); + expect(vm.$el.querySelector('li:nth-child(1)').classList.contains('active')).toBeTruthy(); }); - it('renders `preview` link as active when previewMarkdown is true', (done) => { + it('renders `preview` link as active when previewMarkdown is true', done => { vm.previewMarkdown = true; Vue.nextTick(() => { - expect( - vm.$el.querySelector('li:nth-child(2)').classList.contains('active'), - ).toBeTruthy(); + expect(vm.$el.querySelector('li:nth-child(2)').classList.contains('active')).toBeTruthy(); done(); }); @@ -52,16 +47,24 @@ describe('Markdown field header component', () => { expect(vm.$emit).toHaveBeenCalledWith('write-markdown'); }); - it('blurs preview link after click', (done) => { + it('does not emit toggle markdown event when triggered from another form', () => { + spyOn(vm, '$emit'); + + $(document).triggerHandler('markdown-preview:show', [ + $(''), + ]); + + expect(vm.$emit).not.toHaveBeenCalled(); + }); + + it('blurs preview link after click', done => { const link = vm.$el.querySelector('li:nth-child(2) a'); spyOn(HTMLElement.prototype, 'blur'); link.click(); setTimeout(() => { - expect( - link.blur, - ).toHaveBeenCalled(); + expect(link.blur).toHaveBeenCalled(); done(); }); diff --git a/spec/lib/banzai/commit_renderer_spec.rb b/spec/lib/banzai/commit_renderer_spec.rb index e7ebb2a332f..1f53657c59c 100644 --- a/spec/lib/banzai/commit_renderer_spec.rb +++ b/spec/lib/banzai/commit_renderer_spec.rb @@ -6,7 +6,10 @@ describe Banzai::CommitRenderer do user = build(:user) project = create(:project, :repository) - expect(Banzai::ObjectRenderer).to receive(:new).with(project, user).and_call_original + expect(Banzai::ObjectRenderer) + .to receive(:new) + .with(user: user, default_project: project) + .and_call_original described_class::ATTRIBUTES.each do |attr| expect_any_instance_of(Banzai::ObjectRenderer).to receive(:render).with([project.commit], attr).once.and_call_original diff --git a/spec/lib/banzai/issuable_extractor_spec.rb b/spec/lib/banzai/issuable_extractor_spec.rb index 69763476dac..f42951d9781 100644 --- a/spec/lib/banzai/issuable_extractor_spec.rb +++ b/spec/lib/banzai/issuable_extractor_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Banzai::IssuableExtractor do let(:project) { create(:project) } let(:user) { create(:user) } - let(:extractor) { described_class.new(project, user) } + let(:extractor) { described_class.new(Banzai::RenderContext.new(project, user)) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } let(:issue_link) do diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index 074d521a5c6..1fe034ae9a2 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -3,7 +3,14 @@ require 'spec_helper' describe Banzai::ObjectRenderer do let(:project) { create(:project, :repository) } let(:user) { project.owner } - let(:renderer) { described_class.new(project, user, custom_value: 'value') } + let(:renderer) do + described_class.new( + default_project: project, + user: user, + redaction_context: { custom_value: 'value' } + ) + end + let(:object) { Note.new(note: 'hello', note_html: 'hello
', cached_markdown_version: CacheMarkdownField::CACHE_VERSION) } describe '#render' do diff --git a/spec/lib/banzai/redactor_spec.rb b/spec/lib/banzai/redactor_spec.rb index 441f3725985..aaeec953e4b 100644 --- a/spec/lib/banzai/redactor_spec.rb +++ b/spec/lib/banzai/redactor_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Banzai::Redactor do let(:user) { create(:user) } let(:project) { build(:project) } - let(:redactor) { described_class.new(project, user) } + let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } describe '#redact' do context 'when reference not visible to user' do @@ -54,7 +54,7 @@ describe Banzai::Redactor do context 'when project is in pending delete' do let!(:issue) { create(:issue, project: project) } - let(:redactor) { described_class.new(project, user) } + let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } before do project.update(pending_delete: true) diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb index 6175d4c4ca9..4e6e8eca38a 100644 --- a/spec/lib/banzai/reference_parser/base_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -5,13 +5,14 @@ describe Banzai::ReferenceParser::BaseParser do let(:user) { create(:user) } let(:project) { create(:project, :public) } + let(:context) { Banzai::RenderContext.new(project, user) } subject do klass = Class.new(described_class) do self.reference_type = :foo end - klass.new(project, user) + klass.new(context) end describe '.reference_type=' do @@ -23,6 +24,19 @@ describe Banzai::ReferenceParser::BaseParser do end end + describe '#project_for_node' do + it 'returns the Project for a node' do + document = instance_double('document', fragment?: false) + project = instance_double('project') + object = instance_double('object', project: project) + node = instance_double('node', document: document) + + context.associate_document(document, object) + + expect(subject.project_for_node(node)).to eq(project) + end + end + describe '#nodes_visible_to_user' do let(:link) { empty_html_link } @@ -164,7 +178,7 @@ describe Banzai::ReferenceParser::BaseParser do self.reference_type = :test end - instance = dummy.new(project, user) + instance = dummy.new(Banzai::RenderContext.new(project, user)) document = Nokogiri::HTML.fragment('') expect(instance).to receive(:gather_references) diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb index 3505659c2c3..cca53a8b9b9 100644 --- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb @@ -5,7 +5,7 @@ describe Banzai::ReferenceParser::CommitParser do let(:project) { create(:project, :public) } let(:user) { create(:user) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb index 21813177deb..23e16fe0213 100644 --- a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb @@ -5,7 +5,7 @@ describe Banzai::ReferenceParser::CommitRangeParser do let(:project) { create(:project, :public) } let(:user) { create(:user) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb index 25969b65168..1cb31e57114 100644 --- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -5,7 +5,7 @@ describe Banzai::ReferenceParser::ExternalIssueParser do let(:project) { create(:project, :public) } let(:user) { create(:user) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb index cb7f8b20dda..77c2064caba 100644 --- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -7,7 +7,7 @@ describe Banzai::ReferenceParser::IssueParser do let(:user) { create(:user) } let(:issue) { create(:issue, project: project) } let(:link) { empty_html_link } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } describe '#nodes_visible_to_user' do context 'when the link has a data-issue attribute' do diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb index b700161d6c2..e4df2533821 100644 --- a/spec/lib/banzai/reference_parser/label_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/label_parser_spec.rb @@ -6,7 +6,7 @@ describe Banzai::ReferenceParser::LabelParser do let(:project) { create(:project, :public) } let(:user) { create(:user) } let(:label) { create(:label, project: project) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb index 14542342cf6..5417b1f00be 100644 --- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -6,7 +6,7 @@ describe Banzai::ReferenceParser::MergeRequestParser do let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:merge_request) { create(:merge_request, source_project: project) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(merge_request.target_project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb index 7dacdf8d629..751d042ffde 100644 --- a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb @@ -6,7 +6,7 @@ describe Banzai::ReferenceParser::MilestoneParser do let(:project) { create(:project, :public) } let(:user) { create(:user) } let(:milestone) { create(:milestone, project: project) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#nodes_visible_to_user' do diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb index 69ec3f66aa8..d410bd4c164 100644 --- a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb @@ -9,7 +9,7 @@ describe Banzai::ReferenceParser::SnippetParser do let(:external_user) { create(:user, :external) } let(:project_member) { create(:user) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } def visible_references(snippet_visibility, user = nil) diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb index b079a3be029..112447f098e 100644 --- a/spec/lib/banzai/reference_parser/user_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/user_parser_spec.rb @@ -6,7 +6,7 @@ describe Banzai::ReferenceParser::UserParser do let(:group) { create(:group) } let(:user) { create(:user) } let(:project) { create(:project, :public, group: group, creator: user) } - subject { described_class.new(project, user) } + subject { described_class.new(Banzai::RenderContext.new(project, user)) } let(:link) { empty_html_link } describe '#referenced_by' do diff --git a/spec/lib/banzai/render_context_spec.rb b/spec/lib/banzai/render_context_spec.rb new file mode 100644 index 00000000000..ad17db11613 --- /dev/null +++ b/spec/lib/banzai/render_context_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Banzai::RenderContext do + let(:document) { Nokogiri::HTML.fragment('hello
') } + + describe '#project_for_node' do + it 'returns the default project if no associated project was found' do + project = instance_double('project') + context = described_class.new(project) + + expect(context.project_for_node(document)).to eq(project) + end + + it 'returns the associated project if one was associated explicitly' do + project = instance_double('project') + obj = instance_double('object', project: project) + context = described_class.new + + context.associate_document(document, obj) + + expect(context.project_for_node(document)).to eq(project) + end + + it 'returns the project associated with a DocumentFragment when using a node' do + project = instance_double('project') + obj = instance_double('object', project: project) + context = described_class.new + node = document.children.first + + context.associate_document(document, obj) + + expect(context.project_for_node(node)).to eq(project) + end + end +end diff --git a/spec/lib/gitlab/ci/status/build/common_spec.rb b/spec/lib/gitlab/ci/status/build/common_spec.rb index 2cce7a23ea7..ca3c66f0152 100644 --- a/spec/lib/gitlab/ci/status/build/common_spec.rb +++ b/spec/lib/gitlab/ci/status/build/common_spec.rb @@ -38,4 +38,10 @@ describe Gitlab::Ci::Status::Build::Common do expect(subject.details_path).to include "jobs/#{build.id}" end end + + describe '#illustration' do + it 'provides a fallback empty state illustration' do + expect(subject.illustration).not_to be_empty + end + end end diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb index 6d5b73bb01b..d53a7d468e3 100644 --- a/spec/lib/gitlab/ci/status/build/factory_spec.rb +++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb @@ -75,7 +75,8 @@ describe Gitlab::Ci::Status::Build::Factory do it 'matches correct extended statuses' do expect(factory.extended_statuses) - .to eq [Gitlab::Ci::Status::Build::Retryable, Gitlab::Ci::Status::Build::Failed] + .to eq [Gitlab::Ci::Status::Build::Retryable, + Gitlab::Ci::Status::Build::Failed] end it 'fabricates a failed build status' do @@ -94,7 +95,7 @@ describe Gitlab::Ci::Status::Build::Factory do end context 'when build is allowed to fail' do - let(:build) { create(:ci_build, :failed, :allowed_to_fail) } + let(:build) { create(:ci_build, :failed, :allowed_to_fail, :trace_artifact) } it 'matches correct core status' do expect(factory.core_status).to be_a Gitlab::Ci::Status::Failed diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb index bf9208f1ff4..e79f0a7f257 100644 --- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb +++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb @@ -5,6 +5,18 @@ describe Gitlab::Ci::Variables::Collection::Item do { key: 'VAR', value: 'something', public: true } end + describe '.new' do + it 'raises error if unknown key i specified' do + expect { described_class.new(key: 'VAR', value: 'abc', files: true) } + .to raise_error ArgumentError, 'unknown keyword: files' + end + + it 'raises error when required keywords are not specified' do + expect { described_class.new(key: 'VAR') } + .to raise_error ArgumentError, 'missing keyword: value' + end + end + describe '.fabricate' do it 'supports using a hash' do resource = described_class.fabricate(variable) @@ -47,12 +59,25 @@ describe Gitlab::Ci::Variables::Collection::Item do end describe '#to_runner_variable' do - it 'returns a runner-compatible hash representation' do - runner_variable = described_class - .new(**variable) - .to_runner_variable + context 'when variable is not a file-related' do + it 'returns a runner-compatible hash representation' do + runner_variable = described_class + .new(**variable) + .to_runner_variable - expect(runner_variable).to eq variable + expect(runner_variable).to eq variable + end + end + + context 'when variable is file-related' do + it 'appends file description component' do + runner_variable = described_class + .new(key: 'VAR', value: 'value', file: true) + .to_runner_variable + + expect(runner_variable) + .to eq(key: 'VAR', value: 'value', public: true, file: true) + end end end end diff --git a/spec/lib/gitlab/email/handler_spec.rb b/spec/lib/gitlab/email/handler_spec.rb index 386d73e6115..cedbfcc0d18 100644 --- a/spec/lib/gitlab/email/handler_spec.rb +++ b/spec/lib/gitlab/email/handler_spec.rb @@ -25,12 +25,12 @@ describe Gitlab::Email::Handler do described_class.for('email', address).class end - expect(matched_handlers.uniq).to match_array(Gitlab::Email::Handler::HANDLERS) + expect(matched_handlers.uniq).to match_array(ce_handlers) end it 'can pick exactly one handler for each address' do addresses.each do |address| - matched_handlers = Gitlab::Email::Handler::HANDLERS.select do |handler| + matched_handlers = ce_handlers.select do |handler| handler.new('email', address).can_handle? end @@ -38,4 +38,10 @@ describe Gitlab::Email::Handler do end end end + + def ce_handlers + @ce_handlers ||= Gitlab::Email::Handler::HANDLERS.reject do |handler| + handler.name.start_with?('Gitlab::Email::Handler::EE::') + end + end end diff --git a/spec/lib/gitlab/git/attributes_parser_spec.rb b/spec/lib/gitlab/git/attributes_parser_spec.rb index 323334e99a5..2d103123998 100644 --- a/spec/lib/gitlab/git/attributes_parser_spec.rb +++ b/spec/lib/gitlab/git/attributes_parser_spec.rb @@ -66,18 +66,6 @@ describe Gitlab::Git::AttributesParser, seed_helper: true do end end - context 'when attributes data is a file handle' do - subject do - File.open(attributes_path, 'r') do |file_handle| - described_class.new(file_handle) - end - end - - it 'returns the attributes as a Hash' do - expect(subject.attributes('test.txt')).to eq({ 'text' => true }) - end - end - context 'when attributes data is nil' do let(:data) { nil } diff --git a/spec/lib/gitlab/git/info_attributes_spec.rb b/spec/lib/gitlab/git/info_attributes_spec.rb deleted file mode 100644 index ea84909c3e0..00000000000 --- a/spec/lib/gitlab/git/info_attributes_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Git::InfoAttributes, seed_helper: true do - let(:path) do - File.join(SEED_STORAGE_PATH, 'with-git-attributes.git') - end - - subject { described_class.new(path) } - - describe '#attributes' do - context 'using a path with attributes' do - it 'returns the attributes as a Hash' do - expect(subject.attributes('test.txt')).to eq({ 'text' => true }) - end - - it 'returns an empty Hash for a defined path without attributes' do - expect(subject.attributes('bla/bla.txt')).to eq({}) - end - end - end - - describe '#parser' do - it 'parses a file with entries' do - expect(subject.patterns).to be_an_instance_of(Hash) - expect(subject.patterns["/*.txt"]).to eq({ 'text' => true }) - end - - it 'does not parse anything when the attributes file does not exist' do - expect(File).to receive(:exist?) - .with(File.join(path, 'info/attributes')) - .and_return(false) - - expect(subject.patterns).to eq({}) - end - - it 'does not parse attributes files with unsupported encoding' do - path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git') - subject = described_class.new(path) - - expect(subject.patterns).to eq({}) - end - end -end diff --git a/spec/lib/gitlab/git/raw_diff_change_spec.rb b/spec/lib/gitlab/git/raw_diff_change_spec.rb new file mode 100644 index 00000000000..eedde34534f --- /dev/null +++ b/spec/lib/gitlab/git/raw_diff_change_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +describe Gitlab::Git::RawDiffChange do + let(:raw_change) { } + let(:change) { described_class.new(raw_change) } + + context 'bad input' do + let(:raw_change) { 'foo' } + + it 'does not set most of the attrs' do + expect(change.blob_id).to eq('foo') + expect(change.operation).to eq(:unknown) + expect(change.old_path).to be_blank + expect(change.new_path).to be_blank + expect(change.blob_size).to be_blank + end + end + + context 'adding a file' do + let(:raw_change) { '93e123ac8a3e6a0b600953d7598af629dec7b735 59 A bar/branch-test.txt' } + + it 'initialize the proper attrs' do + expect(change.operation).to eq(:added) + expect(change.old_path).to be_blank + expect(change.new_path).to eq('bar/branch-test.txt') + expect(change.blob_id).to be_present + expect(change.blob_size).to be_present + end + end + + context 'renaming a file' do + let(:raw_change) { "85bc2f9753afd5f4fc5d7c75f74f8d526f26b4f3 107 R060\tfiles/js/commit.js.coffee\tfiles/js/commit.coffee" } + + it 'initialize the proper attrs' do + expect(change.operation).to eq(:renamed) + expect(change.old_path).to eq('files/js/commit.js.coffee') + expect(change.new_path).to eq('files/js/commit.coffee') + expect(change.blob_id).to be_present + expect(change.blob_size).to be_present + end + end + + context 'modifying a file' do + let(:raw_change) { 'c60514b6d3d6bf4bec1030f70026e34dfbd69ad5 824 M README.md' } + + it 'initialize the proper attrs' do + expect(change.operation).to eq(:modified) + expect(change.old_path).to eq('README.md') + expect(change.new_path).to eq('README.md') + expect(change.blob_id).to be_present + expect(change.blob_size).to be_present + end + end + + context 'deleting a file' do + let(:raw_change) { '60d7a906c2fd9e4509aeb1187b98d0ea7ce827c9 15364 D files/.DS_Store' } + + it 'initialize the proper attrs' do + expect(change.operation).to eq(:deleted) + expect(change.old_path).to eq('files/.DS_Store') + expect(change.new_path).to be_nil + expect(change.blob_id).to be_present + expect(change.blob_size).to be_present + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index d3ab61746f4..1e00e8d2739 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1043,6 +1043,44 @@ describe Gitlab::Git::Repository, seed_helper: true do it { is_expected.to eq(17) } end + describe '#raw_changes_between' do + let(:old_rev) { } + let(:new_rev) { } + let(:changes) { repository.raw_changes_between(old_rev, new_rev) } + + context 'initial commit' do + let(:old_rev) { Gitlab::Git::BLANK_SHA } + let(:new_rev) { '1a0b36b3cdad1d2ee32457c102a8c0b7056fa863' } + + it 'returns the changes' do + expect(changes).to be_present + expect(changes.size).to eq(3) + end + end + + context 'with an invalid rev' do + let(:old_rev) { 'foo' } + let(:new_rev) { 'bar' } + + it 'returns an error' do + expect { changes }.to raise_error(Gitlab::Git::Repository::GitError) + end + end + + context 'with valid revs' do + let(:old_rev) { 'fa1b1e6c004a68b7d8763b86455da9e6b23e36d6' } + let(:new_rev) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' } + + it 'returns the changes' do + expect(changes.size).to eq(9) + expect(changes.first.operation).to eq(:modified) + expect(changes.first.new_path).to eq('.gitmodules') + expect(changes.last.operation).to eq(:added) + expect(changes.last.new_path).to eq('files/lfs/picture-invalid.png') + end + end + end + describe '#merge_base' do shared_examples '#merge_base' do where(:from, :to, :result) do diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb index 9be3fa633a7..7951cbe7b1d 100644 --- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb @@ -33,7 +33,7 @@ describe Gitlab::GitalyClient::CommitService do initial_commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863').raw request = Gitaly::CommitDiffRequest.new( repository: repository_message, - left_commit_id: '4b825dc642cb6eb9a060e54bf8d69288fbee4904', + left_commit_id: Gitlab::Git::EMPTY_TREE_ID, right_commit_id: initial_commit.id, collapse_diffs: true, enforce_limits: true, @@ -77,7 +77,7 @@ describe Gitlab::GitalyClient::CommitService do initial_commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') request = Gitaly::CommitDeltaRequest.new( repository: repository_message, - left_commit_id: '4b825dc642cb6eb9a060e54bf8d69288fbee4904', + left_commit_id: Gitlab::Git::EMPTY_TREE_ID, right_commit_id: initial_commit.id ) @@ -90,7 +90,7 @@ describe Gitlab::GitalyClient::CommitService do describe '#between' do let(:from) { 'master' } - let(:to) { '4b825dc642cb6eb9a060e54bf8d69288fbee4904' } + let(:to) { Gitlab::Git::EMPTY_TREE_ID } it 'sends an RPC request' do request = Gitaly::CommitsBetweenRequest.new( @@ -155,7 +155,7 @@ describe Gitlab::GitalyClient::CommitService do end describe '#find_commit' do - let(:revision) { '4b825dc642cb6eb9a060e54bf8d69288fbee4904' } + let(:revision) { Gitlab::Git::EMPTY_TREE_ID } it 'sends an RPC request' do request = Gitaly::FindCommitRequest.new( repository: repository_message, revision: revision diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb index 21592688bf0..074323d47d2 100644 --- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb @@ -84,6 +84,17 @@ describe Gitlab::GitalyClient::RepositoryService do end end + describe '#info_attributes' do + it 'reads the info attributes' do + expect_any_instance_of(Gitaly::RepositoryService::Stub) + .to receive(:get_info_attributes) + .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) + .and_return([]) + + client.info_attributes + end + end + describe '#has_local_branches?' do it 'sends a has_local_branches message' do expect_any_instance_of(Gitaly::RepositoryService::Stub) diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb index 71a743495a2..4ba99009855 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/spec/lib/gitlab/utils_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' describe Gitlab::Utils do - delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string, to: :described_class + delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string, + :bytes_to_megabytes, to: :described_class describe '.slugify' do { @@ -97,4 +98,12 @@ describe Gitlab::Utils do expect(ensure_array_from_string(str)).to eq(%w[seven eight 9 10]) end end + + describe '.bytes_to_megabytes' do + it 'converts bytes to megabytes' do + bytes = 1.megabyte + + expect(bytes_to_megabytes(bytes)).to eq(1) + end + end end diff --git a/spec/lib/rspec_flaky/config_spec.rb b/spec/lib/rspec_flaky/config_spec.rb index 83556787e85..4a71b1feebd 100644 --- a/spec/lib/rspec_flaky/config_spec.rb +++ b/spec/lib/rspec_flaky/config_spec.rb @@ -16,23 +16,25 @@ describe RspecFlaky::Config, :aggregate_failures do end end - context "when ENV['FLAKY_RSPEC_GENERATE_REPORT'] is set to 'false'" do - before do - stub_env('FLAKY_RSPEC_GENERATE_REPORT', 'false') + context "when ENV['FLAKY_RSPEC_GENERATE_REPORT'] is set" do + using RSpec::Parameterized::TableSyntax + + where(:env_value, :result) do + '1' | true + 'true' | true + 'foo' | false + '0' | false + 'false' | false end - it 'returns false' do - expect(described_class).not_to be_generate_report - end - end + with_them do + before do + stub_env('FLAKY_RSPEC_GENERATE_REPORT', env_value) + end - context "when ENV['FLAKY_RSPEC_GENERATE_REPORT'] is set to 'true'" do - before do - stub_env('FLAKY_RSPEC_GENERATE_REPORT', 'true') - end - - it 'returns true' do - expect(described_class).to be_generate_report + it 'returns false' do + expect(described_class.generate_report?).to be(result) + end end end end diff --git a/spec/lib/rspec_flaky/flaky_examples_collection_spec.rb b/spec/lib/rspec_flaky/flaky_examples_collection_spec.rb index 06a8ba0d02e..6731a27ed17 100644 --- a/spec/lib/rspec_flaky/flaky_examples_collection_spec.rb +++ b/spec/lib/rspec_flaky/flaky_examples_collection_spec.rb @@ -24,14 +24,6 @@ describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do } end - describe '.from_json' do - it 'accepts a JSON' do - collection = described_class.from_json(JSON.pretty_generate(collection_hash)) - - expect(collection.to_report).to eq(described_class.new(collection_hash).to_report) - end - end - describe '#initialize' do it 'accepts no argument' do expect { described_class.new }.not_to raise_error @@ -46,11 +38,11 @@ describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do end end - describe '#to_report' do + describe '#to_h' do it 'calls #to_h on the values' do collection = described_class.new(collection_hash) - expect(collection.to_report).to eq(collection_report) + expect(collection.to_h).to eq(collection_report) end end @@ -61,7 +53,7 @@ describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do a: { example_id: 'spec/foo/bar_spec.rb:2' }, c: { example_id: 'spec/bar/baz_spec.rb:4' }) - expect((collection2 - collection1).to_report).to eq( + expect((collection2 - collection1).to_h).to eq( c: { example_id: 'spec/bar/baz_spec.rb:4', first_flaky_at: nil, diff --git a/spec/lib/rspec_flaky/listener_spec.rb b/spec/lib/rspec_flaky/listener_spec.rb index bfb7648b486..ef085445081 100644 --- a/spec/lib/rspec_flaky/listener_spec.rb +++ b/spec/lib/rspec_flaky/listener_spec.rb @@ -4,7 +4,7 @@ describe RspecFlaky::Listener, :aggregate_failures do let(:already_flaky_example_uid) { '6e869794f4cfd2badd93eb68719371d1' } let(:suite_flaky_example_report) do { - already_flaky_example_uid => { + "#{already_flaky_example_uid}": { example_id: 'spec/foo/bar_spec.rb:2', file: 'spec/foo/bar_spec.rb', line: 2, @@ -55,8 +55,7 @@ describe RspecFlaky::Listener, :aggregate_failures do it 'returns a valid Listener instance' do listener = described_class.new - expect(listener.to_report(listener.suite_flaky_examples)) - .to eq(expected_suite_flaky_examples) + expect(listener.suite_flaky_examples.to_h).to eq(expected_suite_flaky_examples) expect(listener.flaky_examples).to eq({}) end end @@ -65,25 +64,35 @@ describe RspecFlaky::Listener, :aggregate_failures do it_behaves_like 'a valid Listener instance' end - context 'when a report file exists and set by SUITE_FLAKY_RSPEC_REPORT_PATH' do - let(:report_file) do - Tempfile.new(%w[rspec_flaky_report .json]).tap do |f| - f.write(JSON.pretty_generate(suite_flaky_example_report)) - f.rewind + context 'when SUITE_FLAKY_RSPEC_REPORT_PATH is set' do + let(:report_file_path) { 'foo/report.json' } + + before do + stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', report_file_path) + end + + context 'and report file exists' do + before do + expect(File).to receive(:exist?).with(report_file_path).and_return(true) + end + + it 'delegates the load to RspecFlaky::Report' do + report = RspecFlaky::Report.new(RspecFlaky::FlakyExamplesCollection.new(suite_flaky_example_report)) + + expect(RspecFlaky::Report).to receive(:load).with(report_file_path).and_return(report) + expect(described_class.new.suite_flaky_examples.to_h).to eq(report.flaky_examples.to_h) end end - before do - stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', report_file.path) - end + context 'and report file does not exist' do + before do + expect(File).to receive(:exist?).with(report_file_path).and_return(false) + end - after do - report_file.close - report_file.unlink - end - - it_behaves_like 'a valid Listener instance' do - let(:expected_suite_flaky_examples) { suite_flaky_example_report } + it 'return an empty hash' do + expect(RspecFlaky::Report).not_to receive(:load) + expect(described_class.new.suite_flaky_examples.to_h).to eq({}) + end end end end @@ -186,74 +195,21 @@ describe RspecFlaky::Listener, :aggregate_failures do let(:notification_already_flaky_rspec_example) { double(example: already_flaky_rspec_example) } context 'when a report file path is set by FLAKY_RSPEC_REPORT_PATH' do - let(:report_file_path) { Rails.root.join('tmp', 'rspec_flaky_report.json') } - let(:new_report_file_path) { Rails.root.join('tmp', 'rspec_flaky_new_report.json') } + it 'delegates the writes to RspecFlaky::Report' do + listener.example_passed(notification_new_flaky_rspec_example) + listener.example_passed(notification_already_flaky_rspec_example) - before do - stub_env('FLAKY_RSPEC_REPORT_PATH', report_file_path) - stub_env('NEW_FLAKY_RSPEC_REPORT_PATH', new_report_file_path) - FileUtils.rm(report_file_path) if File.exist?(report_file_path) - FileUtils.rm(new_report_file_path) if File.exist?(new_report_file_path) + report1 = double + report2 = double + + expect(RspecFlaky::Report).to receive(:new).with(listener.flaky_examples).and_return(report1) + expect(report1).to receive(:write).with(RspecFlaky::Config.flaky_examples_report_path) + + expect(RspecFlaky::Report).to receive(:new).with(listener.flaky_examples - listener.suite_flaky_examples).and_return(report2) + expect(report2).to receive(:write).with(RspecFlaky::Config.new_flaky_examples_report_path) + + listener.dump_summary(nil) end - - after do - FileUtils.rm(report_file_path) if File.exist?(report_file_path) - FileUtils.rm(new_report_file_path) if File.exist?(new_report_file_path) - end - - context 'when FLAKY_RSPEC_GENERATE_REPORT == "false"' do - before do - stub_env('FLAKY_RSPEC_GENERATE_REPORT', 'false') - end - - it 'does not write any report file' do - listener.example_passed(notification_new_flaky_rspec_example) - - listener.dump_summary(nil) - - expect(File.exist?(report_file_path)).to be(false) - expect(File.exist?(new_report_file_path)).to be(false) - end - end - - context 'when FLAKY_RSPEC_GENERATE_REPORT == "true"' do - before do - stub_env('FLAKY_RSPEC_GENERATE_REPORT', 'true') - end - - around do |example| - Timecop.freeze { example.run } - end - - it 'writes the report files' do - listener.example_passed(notification_new_flaky_rspec_example) - listener.example_passed(notification_already_flaky_rspec_example) - - listener.dump_summary(nil) - - expect(File.exist?(report_file_path)).to be(true) - expect(File.exist?(new_report_file_path)).to be(true) - - expect(File.read(report_file_path)) - .to eq(JSON.pretty_generate(listener.to_report(listener.flaky_examples))) - - new_example = RspecFlaky::Example.new(notification_new_flaky_rspec_example) - new_flaky_example = RspecFlaky::FlakyExample.new(new_example) - new_flaky_example.update_flakiness! - - expect(File.read(new_report_file_path)) - .to eq(JSON.pretty_generate(listener.to_report(new_example.uid => new_flaky_example))) - end - end - end - end - - describe '#to_report' do - let(:listener) { described_class.new(suite_flaky_example_report.to_json) } - - it 'transforms the internal hash to a JSON-ready hash' do - expect(listener.to_report(already_flaky_example_uid => already_flaky_example)) - .to match(hash_including(suite_flaky_example_report)) end end end diff --git a/spec/lib/rspec_flaky/report_spec.rb b/spec/lib/rspec_flaky/report_spec.rb new file mode 100644 index 00000000000..7d57d99f7e5 --- /dev/null +++ b/spec/lib/rspec_flaky/report_spec.rb @@ -0,0 +1,125 @@ +require 'spec_helper' + +describe RspecFlaky::Report, :aggregate_failures do + let(:a_hundred_days) { 3600 * 24 * 100 } + let(:collection_hash) do + { + a: { example_id: 'spec/foo/bar_spec.rb:2' }, + b: { example_id: 'spec/foo/baz_spec.rb:3', first_flaky_at: (Time.now - a_hundred_days).to_s, last_flaky_at: (Time.now - a_hundred_days).to_s } + } + end + let(:suite_flaky_example_report) do + { + '6e869794f4cfd2badd93eb68719371d1': { + example_id: 'spec/foo/bar_spec.rb:2', + file: 'spec/foo/bar_spec.rb', + line: 2, + description: 'hello world', + first_flaky_at: 1234, + last_flaky_at: 4321, + last_attempts_count: 3, + flaky_reports: 1, + last_flaky_job: nil + } + } + end + let(:flaky_examples) { RspecFlaky::FlakyExamplesCollection.new(collection_hash) } + let(:report) { described_class.new(flaky_examples) } + + describe '.load' do + let!(:report_file) do + Tempfile.new(%w[rspec_flaky_report .json]).tap do |f| + f.write(JSON.pretty_generate(suite_flaky_example_report)) + f.rewind + end + end + + after do + report_file.close + report_file.unlink + end + + it 'loads the report file' do + expect(described_class.load(report_file.path).flaky_examples.to_h).to eq(suite_flaky_example_report) + end + end + + describe '.load_json' do + let(:report_json) do + JSON.pretty_generate(suite_flaky_example_report) + end + + it 'loads the report file' do + expect(described_class.load_json(report_json).flaky_examples.to_h).to eq(suite_flaky_example_report) + end + end + + describe '#initialize' do + it 'accepts a RspecFlaky::FlakyExamplesCollection' do + expect { report }.not_to raise_error + end + + it 'does not accept anything else' do + expect { described_class.new([1, 2, 3]) }.to raise_error(ArgumentError, "`flaky_examples` must be a RspecFlaky::FlakyExamplesCollection, Array given!") + end + end + + it 'delegates to #flaky_examples using SimpleDelegator' do + expect(report.__getobj__).to eq(flaky_examples) + end + + describe '#write' do + let(:report_file_path) { Rails.root.join('tmp', 'rspec_flaky_report.json') } + + before do + FileUtils.rm(report_file_path) if File.exist?(report_file_path) + end + + after do + FileUtils.rm(report_file_path) if File.exist?(report_file_path) + end + + context 'when RspecFlaky::Config.generate_report? is false' do + before do + allow(RspecFlaky::Config).to receive(:generate_report?).and_return(false) + end + + it 'does not write any report file' do + report.write(report_file_path) + + expect(File.exist?(report_file_path)).to be(false) + end + end + + context 'when RspecFlaky::Config.generate_report? is true' do + before do + allow(RspecFlaky::Config).to receive(:generate_report?).and_return(true) + end + + it 'delegates the writes to RspecFlaky::Report' do + report.write(report_file_path) + + expect(File.exist?(report_file_path)).to be(true) + expect(File.read(report_file_path)) + .to eq(JSON.pretty_generate(report.flaky_examples.to_h)) + end + end + end + + describe '#prune_outdated' do + it 'returns a new collection without the examples older than 90 days by default' do + new_report = flaky_examples.to_h.dup.tap { |r| r.delete(:b) } + new_flaky_examples = report.prune_outdated + + expect(new_flaky_examples).to be_a(described_class) + expect(new_flaky_examples.to_h).to eq(new_report) + expect(flaky_examples).to have_key(:b) + end + + it 'accepts a given number of days' do + new_flaky_examples = report.prune_outdated(days: 200) + + expect(new_flaky_examples.to_h).to eq(report.to_h) + end + end +end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index cd175dba6da..199f49d0bf2 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -7,62 +7,6 @@ describe Ability do end end - describe '.can_edit_note?' do - let(:project) { create(:project) } - let(:note) { create(:note_on_issue, project: project) } - - context 'using an anonymous user' do - it 'returns false' do - expect(described_class.can_edit_note?(nil, note)).to be_falsy - end - end - - context 'using a system note' do - it 'returns false' do - system_note = create(:note, system: true) - user = create(:user) - - expect(described_class.can_edit_note?(user, system_note)).to be_falsy - end - end - - context 'using users with different access levels' do - let(:user) { create(:user) } - - it 'returns true for the author' do - expect(described_class.can_edit_note?(note.author, note)).to be_truthy - end - - it 'returns false for a guest user' do - project.add_guest(user) - - expect(described_class.can_edit_note?(user, note)).to be_falsy - end - - it 'returns false for a developer' do - project.add_developer(user) - - expect(described_class.can_edit_note?(user, note)).to be_falsy - end - - it 'returns true for a master' do - project.add_master(user) - - expect(described_class.can_edit_note?(user, note)).to be_truthy - end - - it 'returns true for a group owner' do - group = create(:group) - project.project_group_links.create( - group: group, - group_access: Gitlab::Access::MASTER) - group.add_owner(user) - - expect(described_class.can_edit_note?(user, note)).to be_truthy - end - end - end - describe '.users_that_can_read_project' do context 'using a public project' do it 'returns all the users' do diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index 461e754dc1f..5326f9cb8c0 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -51,7 +51,11 @@ describe BroadcastMessage do expect(described_class).to receive(:where).and_call_original.once - 2.times { described_class.current } + described_class.current + + Timecop.travel(1.year) do + described_class.current + end end it 'includes messages that need to be displayed in the future' do diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb index 34f923d3f0c..a980cff28fb 100644 --- a/spec/models/concerns/awardable_spec.rb +++ b/spec/models/concerns/awardable_spec.rb @@ -46,6 +46,31 @@ describe Awardable do end end + describe '#user_can_award?' do + let(:user) { create(:user) } + + before do + issue.project.add_guest(user) + end + + it 'does not allow upvoting or downvoting your own issue' do + issue.update!(author: user) + + expect(issue.user_can_award?(user, AwardEmoji::DOWNVOTE_NAME)).to be_falsy + expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_falsy + end + + it 'is truthy when the user is allowed to award emoji' do + expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_truthy + end + + it 'is falsy when the project is archived' do + issue.project.update!(archived: true) + + expect(issue.user_can_award?(user, AwardEmoji::UPVOTE_NAME)).to be_falsy + end + end + describe "#toggle_award_emoji" do it "adds an emoji if it isn't awarded yet" do expect { issue.toggle_award_emoji("thumbsup", award_emoji.user) }.to change { AwardEmoji.count }.by(1) diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb index 5a15c23def4..780b200e837 100644 --- a/spec/models/deploy_token_spec.rb +++ b/spec/models/deploy_token_spec.rb @@ -78,19 +78,30 @@ describe DeployToken do describe '#has_access_to?' do let(:project) { create(:project) } - subject(:deploy_token) { create(:deploy_token, projects: [project]) } + subject { deploy_token.has_access_to?(project) } - context 'when the deploy token has access to the project' do - it 'should return true' do - expect(deploy_token.has_access_to?(project)).to be_truthy - end + context 'when deploy token is active and related to project' do + let(:deploy_token) { create(:deploy_token, projects: [project]) } + + it { is_expected.to be_truthy } end - context 'when the deploy token does not have access to the project' do - it 'should return false' do - another_project = create(:project) - expect(deploy_token.has_access_to?(another_project)).to be_falsy - end + context 'when deploy token is active but not related to project' do + let(:deploy_token) { create(:deploy_token) } + + it { is_expected.to be_falsy } + end + + context 'when deploy token is revoked and related to project' do + let(:deploy_token) { create(:deploy_token, :revoked, projects: [project]) } + + it { is_expected.to be_falsy } + end + + context 'when deploy token is revoked and not related to the project' do + let(:deploy_token) { create(:deploy_token, :revoked) } + + it { is_expected.to be_falsy } end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index d87c1ca14f0..374a157bec0 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -172,11 +172,12 @@ describe ProjectWiki do describe '#find_file' do shared_examples 'finding a wiki file' do + let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) } + before do - file = File.open(Rails.root.join('spec', 'fixtures', 'dk.png')) subject.wiki # Make sure the wiki repo exists - BareRepoOperations.new(subject.repository.path_to_repo).commit_file(file, 'image.png') + BareRepoOperations.new(subject.repository.path_to_repo).commit_file(image, 'image.png') end it 'returns the latest version of the file if it exists' do @@ -192,6 +193,13 @@ describe ProjectWiki do file = subject.find_file('image.png') expect(file).to be_a Gitlab::Git::WikiFile end + + it 'returns the whole file' do + file = subject.find_file('image.png') + image.rewind + + expect(file.raw_data.b).to eq(image.read.b) + end end context 'when Gitaly wiki_find_file is enabled' do diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb index 58d36a2c84e..e8096358f7d 100644 --- a/spec/policies/note_policy_spec.rb +++ b/spec/policies/note_policy_spec.rb @@ -18,7 +18,6 @@ describe NotePolicy, mdoels: true do context 'when the project is public' do context 'when the note author is not a project member' do it 'can edit a note' do - expect(policies).to be_allowed(:update_note) expect(policies).to be_allowed(:admin_note) expect(policies).to be_allowed(:resolve_note) expect(policies).to be_allowed(:read_note) @@ -29,7 +28,6 @@ describe NotePolicy, mdoels: true do it 'can edit note' do policies = policies(create(:project_snippet, project: project)) - expect(policies).to be_allowed(:update_note) expect(policies).to be_allowed(:admin_note) expect(policies).to be_allowed(:resolve_note) expect(policies).to be_allowed(:read_note) @@ -47,7 +45,6 @@ describe NotePolicy, mdoels: true do end it 'can edit a note' do - expect(policies).to be_allowed(:update_note) expect(policies).to be_allowed(:admin_note) expect(policies).to be_allowed(:resolve_note) expect(policies).to be_allowed(:read_note) @@ -56,7 +53,6 @@ describe NotePolicy, mdoels: true do context 'when the note author is not a project member' do it 'can not edit a note' do - expect(policies).to be_disallowed(:update_note) expect(policies).to be_disallowed(:admin_note) expect(policies).to be_disallowed(:resolve_note) end diff --git a/spec/policies/personal_snippet_policy_spec.rb b/spec/policies/personal_snippet_policy_spec.rb index 50bb0899eba..3809692b373 100644 --- a/spec/policies/personal_snippet_policy_spec.rb +++ b/spec/policies/personal_snippet_policy_spec.rb @@ -27,6 +27,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -37,6 +38,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_allowed(:comment_personal_snippet) + is_expected.to be_allowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -47,6 +49,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_allowed(:comment_personal_snippet) + is_expected.to be_allowed(:award_emoji) is_expected.to be_allowed(*author_permissions) end end @@ -61,6 +64,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_disallowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -71,6 +75,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_allowed(:comment_personal_snippet) + is_expected.to be_allowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -81,6 +86,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_disallowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -91,6 +97,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_allowed(:comment_personal_snippet) + is_expected.to be_allowed(:award_emoji) is_expected.to be_allowed(*author_permissions) end end @@ -105,6 +112,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_disallowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -115,6 +123,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_disallowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -125,6 +134,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_disallowed(:read_personal_snippet) is_expected.to be_disallowed(:comment_personal_snippet) + is_expected.to be_disallowed(:award_emoji) is_expected.to be_disallowed(*author_permissions) end end @@ -135,6 +145,7 @@ describe PersonalSnippetPolicy do it do is_expected.to be_allowed(:read_personal_snippet) is_expected.to be_allowed(:comment_personal_snippet) + is_expected.to be_allowed(:award_emoji) is_expected.to be_allowed(*author_permissions) end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 905d82b3bb1..8b9c4ac0b4b 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -14,7 +14,8 @@ describe ProjectPolicy do read_project read_board read_list read_wiki read_issue read_project_for_iids read_issue_iid read_merge_request_iid read_label read_milestone read_project_snippet read_project_member read_note - create_project create_issue create_note upload_file + create_project create_issue create_note upload_file create_merge_request_in + award_emoji ] end @@ -35,7 +36,7 @@ describe ProjectPolicy do %i[ admin_milestone admin_merge_request update_merge_request create_commit_status update_commit_status create_build update_build create_pipeline - update_pipeline create_merge_request create_wiki push_code + update_pipeline create_merge_request_from create_wiki push_code resolve_note create_container_image update_container_image create_environment create_deployment ] @@ -43,7 +44,7 @@ describe ProjectPolicy do let(:base_master_permissions) do %i[ - delete_protected_branch update_project_snippet update_environment + push_to_delete_protected_branch update_project_snippet update_environment update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project admin_commit_status admin_build admin_container_image @@ -136,13 +137,66 @@ describe ProjectPolicy do end end + context 'merge requests feature' do + subject { described_class.new(owner, project) } + + it 'disallows all permissions when the feature is disabled' do + project.project_feature.update(merge_requests_access_level: ProjectFeature::DISABLED) + + mr_permissions = [:create_merge_request_from, :read_merge_request, + :update_merge_request, :admin_merge_request, + :create_merge_request_in] + + expect_disallowed(*mr_permissions) + end + end + + shared_examples 'archived project policies' do + let(:feature_write_abilities) do + described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature| + described_class.create_update_admin_destroy(feature) + end + end + + let(:other_write_abilities) do + %i[ + create_merge_request_in + create_merge_request_from + push_to_delete_protected_branch + push_code + request_access + upload_file + resolve_note + award_emoji + ] + end + + context 'when the project is archived' do + before do + project.archived = true + end + + it 'disables write actions on all relevant project features' do + expect_disallowed(*feature_write_abilities) + end + + it 'disables some other important write actions' do + expect_disallowed(*other_write_abilities) + end + + it 'does not disable other other abilities' do + expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities)) + end + end + end + shared_examples 'project policies as anonymous' do context 'abilities for public projects' do context 'when a project has pending invites' do let(:group) { create(:group, :public) } let(:project) { create(:project, :public, namespace: group) } - let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] } - let(:anonymous_permissions) { guest_permissions - user_permissions } + let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] } + let(:anonymous_permissions) { guest_permissions - user_permissions } subject { described_class.new(nil, project) } @@ -154,6 +208,10 @@ describe ProjectPolicy do expect_allowed(*anonymous_permissions) expect_disallowed(*user_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { anonymous_permissions } + end end end @@ -184,6 +242,10 @@ describe ProjectPolicy do expect_disallowed(*owner_permissions) end + it_behaves_like 'archived project policies' do + let(:regular_abilities) { guest_permissions } + end + context 'public builds enabled' do it do expect_allowed(*guest_permissions) @@ -224,12 +286,15 @@ describe ProjectPolicy do it do expect_allowed(*guest_permissions) expect_allowed(*reporter_permissions) - expect_allowed(*reporter_permissions) expect_allowed(*team_member_reporter_permissions) expect_disallowed(*developer_permissions) expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { reporter_permissions } + end end end @@ -247,6 +312,10 @@ describe ProjectPolicy do expect_disallowed(*master_permissions) expect_disallowed(*owner_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { developer_permissions } + end end end @@ -264,6 +333,10 @@ describe ProjectPolicy do expect_allowed(*master_permissions) expect_disallowed(*owner_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { master_permissions } + end end end @@ -281,6 +354,10 @@ describe ProjectPolicy do expect_allowed(*master_permissions) expect_allowed(*owner_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { owner_permissions } + end end end @@ -298,6 +375,10 @@ describe ProjectPolicy do expect_allowed(*master_permissions) expect_allowed(*owner_permissions) end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { owner_permissions } + end end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 3764aec0c71..f64623d7018 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -861,7 +861,7 @@ describe API::MergeRequests do expect(json_response['title']).to eq('Test merge_request') end - it 'returns 422 when target project has disabled merge requests' do + it 'returns 403 when target project has disabled merge requests' do project.project_feature.update(merge_requests_access_level: 0) post api("/projects/#{forked_project.id}/merge_requests", user2), @@ -871,7 +871,7 @@ describe API::MergeRequests do author: user2, target_project_id: project.id - expect(response).to have_gitlab_http_status(422) + expect(response).to have_gitlab_http_status(403) end it "returns 400 when source_branch is missing" do diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb index 6b748369f0d..be70cb24dce 100644 --- a/spec/requests/api/v3/merge_requests_spec.rb +++ b/spec/requests/api/v3/merge_requests_spec.rb @@ -340,7 +340,7 @@ describe API::MergeRequests do expect(json_response['title']).to eq('Test merge_request') end - it "returns 422 when target project has disabled merge requests" do + it "returns 403 when target project has disabled merge requests" do project.project_feature.update(merge_requests_access_level: 0) post v3_api("/projects/#{forked_project.id}/merge_requests", user2), @@ -350,7 +350,7 @@ describe API::MergeRequests do author: user2, target_project_id: project.id - expect(response).to have_gitlab_http_status(422) + expect(response).to have_gitlab_http_status(403) end it "returns 400 when source_branch is missing" do diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 290eeae828e..da8e660c16b 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -585,4 +585,140 @@ describe Auth::ContainerRegistryAuthenticationService do it_behaves_like 'not a container repository factory' end end + + context 'for deploy tokens' do + let(:current_params) do + { scope: "repository:#{project.full_path}:pull" } + end + + context 'when deploy token has read_registry as a scope' do + let(:current_user) { create(:deploy_token, projects: [project]) } + + context 'for public project' do + let(:project) { create(:project, :public) } + + context 'when pulling' do + it_behaves_like 'a pullable' + end + + context 'when pushing' do + let(:current_params) do + { scope: "repository:#{project.full_path}:push" } + end + + it_behaves_like 'an inaccessible' + end + end + + context 'for internal project' do + let(:project) { create(:project, :internal) } + + context 'when pulling' do + it_behaves_like 'a pullable' + end + + context 'when pushing' do + let(:current_params) do + { scope: "repository:#{project.full_path}:push" } + end + + it_behaves_like 'an inaccessible' + end + end + + context 'for private project' do + let(:project) { create(:project, :private) } + + context 'when pulling' do + it_behaves_like 'a pullable' + end + + context 'when pushing' do + let(:current_params) do + { scope: "repository:#{project.full_path}:push" } + end + + it_behaves_like 'an inaccessible' + end + end + end + + context 'when deploy token does not have read_registry scope' do + let(:current_user) { create(:deploy_token, projects: [project], read_registry: false) } + + context 'for public project' do + let(:project) { create(:project, :public) } + + context 'when pulling' do + it_behaves_like 'a pullable' + end + end + + context 'for internal project' do + let(:project) { create(:project, :internal) } + + context 'when pulling' do + it_behaves_like 'an inaccessible' + end + end + + context 'for private project' do + let(:project) { create(:project, :internal) } + + context 'when pulling' do + it_behaves_like 'an inaccessible' + end + end + end + + context 'when deploy token is not related to the project' do + let(:current_user) { create(:deploy_token, read_registry: false) } + + context 'for public project' do + let(:project) { create(:project, :public) } + + context 'when pulling' do + it_behaves_like 'a pullable' + end + end + + context 'for internal project' do + let(:project) { create(:project, :internal) } + + context 'when pulling' do + it_behaves_like 'an inaccessible' + end + end + + context 'for private project' do + let(:project) { create(:project, :internal) } + + context 'when pulling' do + it_behaves_like 'an inaccessible' + end + end + end + + context 'when deploy token has been revoked' do + let(:current_user) { create(:deploy_token, :revoked, projects: [project]) } + + context 'for public project' do + let(:project) { create(:project, :public) } + + it_behaves_like 'a pullable' + end + + context 'for internal project' do + let(:project) { create(:project, :internal) } + + it_behaves_like 'an inaccessible' + end + + context 'for private project' do + let(:project) { create(:project, :internal) } + + it_behaves_like 'an inaccessible' + end + end + end end diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index aa7cc268dd7..97a563c1ce1 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -370,89 +370,10 @@ module Ci it_behaves_like 'validation is not active' end end - end - describe '#register_success' do - let!(:current_time) { Time.new(2018, 4, 5, 14, 0, 0) } - let!(:attempt_counter) { double('Gitlab::Metrics::NullMetric') } - let!(:job_queue_duration_seconds) { double('Gitlab::Metrics::NullMetric') } - - before do - allow(Time).to receive(:now).and_return(current_time) - - # Stub defaults for any metrics other than the ones we're testing - allow(Gitlab::Metrics).to receive(:counter) - .with(any_args) - .and_return(Gitlab::Metrics::NullMetric.instance) - allow(Gitlab::Metrics).to receive(:histogram) - .with(any_args) - .and_return(Gitlab::Metrics::NullMetric.instance) - - # Stub tested metrics - allow(Gitlab::Metrics).to receive(:counter) - .with(:job_register_attempts_total, anything) - .and_return(attempt_counter) - allow(Gitlab::Metrics).to receive(:histogram) - .with(:job_queue_duration_seconds, anything, anything, anything) - .and_return(job_queue_duration_seconds) - - project.update(shared_runners_enabled: true) - pending_job.update(created_at: current_time - 3600, queued_at: current_time - 1800) + def execute(runner) + described_class.new(runner).execute.build end - - shared_examples 'metrics collector' do - it 'increments attempt counter' do - allow(job_queue_duration_seconds).to receive(:observe) - expect(attempt_counter).to receive(:increment) - - execute(runner) - end - - it 'counts job queuing time histogram with expected labels' do - allow(attempt_counter).to receive(:increment) - expect(job_queue_duration_seconds).to receive(:observe) - .with({ shared_runner: expected_shared_runner, - jobs_running_for_project: expected_jobs_running_for_project_first_job }, 1800) - - execute(runner) - end - - context 'when project already has running jobs' do - let!(:build2) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) } - let!(:build3) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) } - - it 'counts job queuing time histogram with expected labels' do - allow(attempt_counter).to receive(:increment) - expect(job_queue_duration_seconds).to receive(:observe) - .with({ shared_runner: expected_shared_runner, - jobs_running_for_project: expected_jobs_running_for_project_third_job }, 1800) - - execute(runner) - end - end - end - - context 'when shared runner is used' do - let(:runner) { shared_runner } - let(:expected_shared_runner) { true } - let(:expected_jobs_running_for_project_first_job) { 0 } - let(:expected_jobs_running_for_project_third_job) { 2 } - - it_behaves_like 'metrics collector' - end - - context 'when specific runner is used' do - let(:runner) { specific_runner } - let(:expected_shared_runner) { false } - let(:expected_jobs_running_for_project_first_job) { '+Inf' } - let(:expected_jobs_running_for_project_third_job) { '+Inf' } - - it_behaves_like 'metrics collector' - end - end - - def execute(runner) - described_class.new(runner).execute.build end end end diff --git a/spec/services/events/render_service_spec.rb b/spec/services/events/render_service_spec.rb index b4a4a44d07b..075cb45e46c 100644 --- a/spec/services/events/render_service_spec.rb +++ b/spec/services/events/render_service_spec.rb @@ -9,9 +9,7 @@ describe Events::RenderService do context 'when the request format is atom' do it 'renders the note inside events' do expect(Banzai::ObjectRenderer).to receive(:new) - .with(event.project, user, - only_path: false, - xhtml: true) + .with(user: user, redaction_context: { only_path: false, xhtml: true }) .and_call_original expect_any_instance_of(Banzai::ObjectRenderer) @@ -24,7 +22,7 @@ describe Events::RenderService do context 'when the request format is not atom' do it 'renders the note inside events' do expect(Banzai::ObjectRenderer).to receive(:new) - .with(event.project, user, {}) + .with(user: user, redaction_context: {}) .and_call_original expect_any_instance_of(Banzai::ObjectRenderer) diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index 44a83c436cb..736a50b2c15 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe MergeRequests::CreateService do + include ProjectForksHelper + let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:assignee) { create(:user) } @@ -300,7 +302,7 @@ describe MergeRequests::CreateService do end context 'when source and target projects are different' do - let(:target_project) { create(:project) } + let(:target_project) { fork_project(project, nil, repository: true) } let(:opts) do { @@ -334,6 +336,26 @@ describe MergeRequests::CreateService do .to raise_error Gitlab::Access::AccessDeniedError end end + + context 'when the user has access to both projects' do + before do + target_project.add_developer(user) + project.add_developer(user) + end + + it 'creates the merge request' do + merge_request = described_class.new(project, user, opts).execute + + expect(merge_request).to be_persisted + end + + it 'does not create the merge request when the target project is archived' do + target_project.update!(archived: true) + + expect { described_class.new(project, user, opts).execute } + .to raise_error Gitlab::Access::AccessDeniedError + end + end end context 'when user sets source project id' do diff --git a/spec/services/notes/render_service_spec.rb b/spec/services/notes/render_service_spec.rb index faac498037f..f771620bc0d 100644 --- a/spec/services/notes/render_service_spec.rb +++ b/spec/services/notes/render_service_spec.rb @@ -4,23 +4,28 @@ describe Notes::RenderService do describe '#execute' do it 'renders a Note' do note = double(:note) - project = double(:project) wiki = double(:wiki) user = double(:user) - expect(Banzai::ObjectRenderer).to receive(:new) - .with(project, user, - requested_path: 'foo', - project_wiki: wiki, - ref: 'bar', - only_path: nil, - xhtml: false) + expect(Banzai::ObjectRenderer) + .to receive(:new) + .with( + user: user, + redaction_context: { + requested_path: 'foo', + project_wiki: wiki, + ref: 'bar', + only_path: nil, + xhtml: false + } + ) .and_call_original expect_any_instance_of(Banzai::ObjectRenderer) - .to receive(:render).with([note], :note) + .to receive(:render) + .with([note], :note) - described_class.new(user).execute([note], project, + described_class.new(user).execute([note], requested_path: 'foo', project_wiki: wiki, ref: 'bar', diff --git a/spec/support/bare_repo_operations.rb b/spec/support/bare_repo_operations.rb index 8eeaa37d3c5..3f4a4243cb6 100644 --- a/spec/support/bare_repo_operations.rb +++ b/spec/support/bare_repo_operations.rb @@ -1,19 +1,15 @@ require 'zlib' class BareRepoOperations - # The ID of empty tree. - # See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012 - EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze - include Gitlab::Popen def initialize(path_to_repo) @path_to_repo = path_to_repo end - def commit_tree(tree_id, msg, parent: EMPTY_TREE_ID) + def commit_tree(tree_id, msg, parent: Gitlab::Git::EMPTY_TREE_ID) commit_tree_args = ['commit-tree', tree_id, '-m', msg] - commit_tree_args += ['-p', parent] unless parent == EMPTY_TREE_ID + commit_tree_args += ['-p', parent] unless parent == Gitlab::Git::EMPTY_TREE_ID commit_id = execute(commit_tree_args) commit_id[0] @@ -21,7 +17,7 @@ class BareRepoOperations # Based on https://stackoverflow.com/a/25556917/1856239 def commit_file(file, dst_path, branch = 'master') - head_id = execute(['show', '--format=format:%H', '--no-patch', branch], allow_failure: true)[0] || EMPTY_TREE_ID + head_id = execute(['show', '--format=format:%H', '--no-patch', branch], allow_failure: true)[0] || Gitlab::Git::EMPTY_TREE_ID execute(['read-tree', '--empty']) execute(['read-tree', head_id]) diff --git a/spec/support/filter_spec_helper.rb b/spec/support/filter_spec_helper.rb index b871b7ffc90..721d359c2ee 100644 --- a/spec/support/filter_spec_helper.rb +++ b/spec/support/filter_spec_helper.rb @@ -18,6 +18,11 @@ module FilterSpecHelper context.reverse_merge!(project: project) end + render_context = Banzai::RenderContext + .new(context[:project], context[:current_user]) + + context = context.merge(render_context: render_context) + described_class.call(html, context) end diff --git a/spec/support/helpers/features/branches_helpers.rb b/spec/support/helpers/features/branches_helpers.rb new file mode 100644 index 00000000000..3525d9a70a7 --- /dev/null +++ b/spec/support/helpers/features/branches_helpers.rb @@ -0,0 +1,33 @@ +# These helpers allow you to manipulate with sorting features. +# +# Usage: +# describe "..." do +# include Spec::Support::Helpers::Features::BranchesHelpers +# ... +# +# create_branch("feature") +# select_branch("master") +# +module Spec + module Support + module Helpers + module Features + module BranchesHelpers + def create_branch(branch_name, source_branch_name = "master") + fill_in("branch_name", with: branch_name) + select_branch(source_branch_name) + click_button("Create branch") + end + + def select_branch(branch_name) + find(".git-revision-dropdown-toggle").click + + page.within("#new-branch-form .dropdown-menu") do + click_link(branch_name) + end + end + end + end + end + end +end diff --git a/spec/support/matchers/have_emoji.rb b/spec/support/matchers/have_emoji.rb new file mode 100644 index 00000000000..23fb8e9c1c4 --- /dev/null +++ b/spec/support/matchers/have_emoji.rb @@ -0,0 +1,5 @@ +RSpec::Matchers.define :have_emoji do |emoji_name| + match do |actual| + expect(actual).to have_selector("gl-emoji[data-name='#{emoji_name}']") + end +end diff --git a/spec/support/reference_parser_helpers.rb b/spec/support/reference_parser_helpers.rb index 5d5e80851e6..c01897ed1a1 100644 --- a/spec/support/reference_parser_helpers.rb +++ b/spec/support/reference_parser_helpers.rb @@ -5,9 +5,11 @@ module ReferenceParserHelpers shared_examples 'no N+1 queries' do it 'avoids N+1 queries in #nodes_visible_to_user', :request_store do + context = Banzai::RenderContext.new(project, user) + record_queries = lambda do |links| ActiveRecord::QueryRecorder.new do - described_class.new(project, user).nodes_visible_to_user(user, links) + described_class.new(context).nodes_visible_to_user(user, links) end end @@ -19,9 +21,11 @@ module ReferenceParserHelpers end it 'avoids N+1 queries in #records_for_nodes', :request_store do + context = Banzai::RenderContext.new(project, user) + record_queries = lambda do |links| ActiveRecord::QueryRecorder.new do - described_class.new(project, user).records_for_nodes(links) + described_class.new(context).records_for_nodes(links) end end diff --git a/spec/views/projects/buttons/_dropdown.html.haml_spec.rb b/spec/views/projects/buttons/_dropdown.html.haml_spec.rb index d0e692635b9..8b9aab30286 100644 --- a/spec/views/projects/buttons/_dropdown.html.haml_spec.rb +++ b/spec/views/projects/buttons/_dropdown.html.haml_spec.rb @@ -8,7 +8,8 @@ describe 'projects/buttons/_dropdown' do assign(:project, project) allow(view).to receive(:current_user).and_return(user) - allow(view).to receive(:can?).and_return(true) + allow(view).to receive(:can?).with(user, :push_code, project).and_return(true) + allow(view).to receive(:can_collaborate_with_project?).and_return(true) end context 'empty repository' do diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb index 448b925cf34..2fdd28a3be4 100644 --- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb +++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb @@ -7,6 +7,7 @@ describe 'projects/commit/_commit_box.html.haml' do before do assign(:project, project) assign(:commit, project.commit) + allow(view).to receive(:current_user).and_return(user) allow(view).to receive(:can_collaborate_with_project?).and_return(false) end @@ -47,7 +48,8 @@ describe 'projects/commit/_commit_box.html.haml' do context 'viewing a commit' do context 'as a developer' do before do - expect(view).to receive(:can_collaborate_with_project?).and_return(true) + project.add_developer(user) + allow(view).to receive(:can_collaborate_with_project?).and_return(true) end it 'has a link to create a new tag' do @@ -58,10 +60,6 @@ describe 'projects/commit/_commit_box.html.haml' do end context 'as a non-developer' do - before do - expect(view).to receive(:can_collaborate_with_project?).and_return(false) - end - it 'does not have a link to create a new tag' do render diff --git a/vendor/gitignore/Android.gitignore b/vendor/gitignore/Android.gitignore index d57137223ed..39b6783cef8 100644 --- a/vendor/gitignore/Android.gitignore +++ b/vendor/gitignore/Android.gitignore @@ -37,8 +37,10 @@ captures/ .idea/workspace.xml .idea/tasks.xml .idea/gradle.xml +.idea/assetWizardSettings.xml .idea/dictionaries .idea/libraries +.idea/caches # Keystore files # Uncomment the following line if you do not want to check your keystore files in. diff --git a/vendor/gitignore/Elixir.gitignore b/vendor/gitignore/Elixir.gitignore index b6d65867dac..86e4c3f3905 100644 --- a/vendor/gitignore/Elixir.gitignore +++ b/vendor/gitignore/Elixir.gitignore @@ -6,3 +6,4 @@ erl_crash.dump *.ez *.beam +/config/*.secret.exs diff --git a/vendor/gitignore/Global/JetBrains.gitignore b/vendor/gitignore/Global/JetBrains.gitignore index 9c01e12b050..a83a428c844 100644 --- a/vendor/gitignore/Global/JetBrains.gitignore +++ b/vendor/gitignore/Global/JetBrains.gitignore @@ -1,12 +1,12 @@ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 -# User-specific stuff: +# User-specific stuff .idea/**/workspace.xml .idea/**/tasks.xml .idea/dictionaries -# Sensitive or high-churn files: +# Sensitive or high-churn files .idea/**/dataSources/ .idea/**/dataSources.ids .idea/**/dataSources.local.xml @@ -14,7 +14,7 @@ .idea/**/dynamic.xml .idea/**/uiDesigner.xml -# Gradle: +# Gradle .idea/**/gradle.xml .idea/**/libraries @@ -22,14 +22,12 @@ cmake-build-debug/ cmake-build-release/ -# Mongo Explorer plugin: +# Mongo Explorer plugin .idea/**/mongoSettings.xml -## File-based project format: +# File-based project format *.iws -## Plugin-specific files: - # IntelliJ out/ @@ -47,3 +45,6 @@ com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties + +# Editor-based Rest Client +.idea/httpRequests diff --git a/vendor/gitignore/Global/Windows.gitignore b/vendor/gitignore/Global/Windows.gitignore index 846a1db836c..0251dd21ad8 100644 --- a/vendor/gitignore/Global/Windows.gitignore +++ b/vendor/gitignore/Global/Windows.gitignore @@ -15,6 +15,7 @@ $RECYCLE.BIN/ # Windows Installer files *.cab *.msi +*.msix *.msm *.msp diff --git a/vendor/gitignore/Godot.gitignore b/vendor/gitignore/Godot.gitignore new file mode 100644 index 00000000000..ba45ca4582e --- /dev/null +++ b/vendor/gitignore/Godot.gitignore @@ -0,0 +1,8 @@ + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Mono-specific ignores +.mono/ diff --git a/vendor/gitignore/Joomla.gitignore b/vendor/gitignore/Joomla.gitignore index b6bf3a9c96a..378c158bddf 100644 --- a/vendor/gitignore/Joomla.gitignore +++ b/vendor/gitignore/Joomla.gitignore @@ -1,4 +1,3 @@ -/.gitignore /.htaccess /administrator/cache/* /administrator/components/com_admin/* diff --git a/vendor/gitignore/KiCad.gitignore b/vendor/gitignore/KiCad.gitignore index 208bc4fc591..198392e551e 100644 --- a/vendor/gitignore/KiCad.gitignore +++ b/vendor/gitignore/KiCad.gitignore @@ -1,4 +1,5 @@ # For PCBs designed using KiCad: http://www.kicad-pcb.org/ +# Format documentation: http://kicad-pcb.org/help/file-formats/ # Temporary files *.000 @@ -8,6 +9,10 @@ *~ _autosave-* *.tmp +*-cache.lib +*-rescue.lib +*-save.pro +*-save.kicad_pcb # Netlist files (exported from Eeschema) *.net diff --git a/vendor/gitignore/Leiningen.gitignore b/vendor/gitignore/Leiningen.gitignore index a9fe6fba80d..a4cb69a32cc 100644 --- a/vendor/gitignore/Leiningen.gitignore +++ b/vendor/gitignore/Leiningen.gitignore @@ -11,3 +11,4 @@ pom.xml.asc .lein-plugins/ .lein-failures .nrepl-port +.cpcache/ diff --git a/vendor/gitignore/Node.gitignore b/vendor/gitignore/Node.gitignore index d1bed128fa8..ad46b30886f 100644 --- a/vendor/gitignore/Node.gitignore +++ b/vendor/gitignore/Node.gitignore @@ -36,7 +36,7 @@ build/Release node_modules/ jspm_packages/ -# Typescript v1 declaration files +# TypeScript v1 declaration files typings/ # Optional npm cache directory diff --git a/vendor/gitignore/Python.gitignore b/vendor/gitignore/Python.gitignore index b989be6ca15..894a44cc066 100644 --- a/vendor/gitignore/Python.gitignore +++ b/vendor/gitignore/Python.gitignore @@ -53,9 +53,8 @@ coverage.xml # Django stuff: *.log -.static_storage/ -.media/ local_settings.py +db.sqlite3 # Flask stuff: instance/ diff --git a/vendor/gitignore/Rails.gitignore b/vendor/gitignore/Rails.gitignore index 828ab1d556a..e62f78e17bc 100644 --- a/vendor/gitignore/Rails.gitignore +++ b/vendor/gitignore/Rails.gitignore @@ -14,6 +14,7 @@ pickle-email-*.html # TODO Comment out this rule if you are OK with secrets being uploaded to the repo config/initializers/secret_token.rb +config/master.key # Only include if you have production secrets in this file, which is no longer a Rails default # config/secrets.yml diff --git a/vendor/gitignore/Rust.gitignore b/vendor/gitignore/Rust.gitignore index 50281a44270..088ba6ba7d3 100644 --- a/vendor/gitignore/Rust.gitignore +++ b/vendor/gitignore/Rust.gitignore @@ -3,7 +3,7 @@ /target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock # These are backup files generated by rustfmt diff --git a/vendor/gitignore/TeX.gitignore b/vendor/gitignore/TeX.gitignore index 78c1c5cd26e..c560658e45c 100644 --- a/vendor/gitignore/TeX.gitignore +++ b/vendor/gitignore/TeX.gitignore @@ -153,7 +153,9 @@ _minted* *.mw # nomencl +*.nlg *.nlo +*.nls # pax *.pax diff --git a/vendor/gitignore/Unity.gitignore b/vendor/gitignore/Unity.gitignore index 75e5b1405da..a7c0c70a0b4 100644 --- a/vendor/gitignore/Unity.gitignore +++ b/vendor/gitignore/Unity.gitignore @@ -5,7 +5,7 @@ [Bb]uilds/ Assets/AssetStoreTools* -# Visual Studio 2015 cache directory +# Visual Studio cache directory /.vs/ # Autogenerated VS/MD/Consulo solution and project files diff --git a/vendor/gitignore/VisualStudio.gitignore b/vendor/gitignore/VisualStudio.gitignore index 8e930f59c47..29063cf6072 100644 --- a/vendor/gitignore/VisualStudio.gitignore +++ b/vendor/gitignore/VisualStudio.gitignore @@ -64,8 +64,10 @@ StyleCopReport.xml *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -248,6 +250,7 @@ ServiceFabricBackup/ *.rdl.data *.bim.layout *.bim_*.settings +*.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ @@ -319,3 +322,8 @@ ASALocalRun/ # MSBuild Binary and Structured Log *.binlog +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml index 4223dc18933..4810035a9e3 100644 --- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml @@ -50,9 +50,9 @@ stages: build: stage: build - image: docker:git + image: docker:stable-git services: - - docker:dind + - docker:stable-dind variables: DOCKER_DRIVER: overlay2 script: @@ -76,12 +76,12 @@ test: - branches codequality: - image: docker:latest + image: docker:stable variables: DOCKER_DRIVER: overlay2 allow_failure: true services: - - docker:dind + - docker:stable-dind script: - setup_docker - codeclimate @@ -90,12 +90,12 @@ codequality: performance: stage: performance - image: docker:latest + image: docker:stable variables: DOCKER_DRIVER: overlay2 allow_failure: true services: - - docker:dind + - docker:stable-dind script: - setup_docker - performance @@ -109,25 +109,37 @@ performance: kubernetes: active sast: - image: docker:latest + image: docker:stable variables: DOCKER_DRIVER: overlay2 allow_failure: true services: - - docker:dind + - docker:stable-dind script: - setup_docker - sast artifacts: paths: [gl-sast-report.json] -sast:container: - image: docker:latest +dependency_scanning: + image: docker:stable variables: DOCKER_DRIVER: overlay2 allow_failure: true services: - - docker:dind + - docker:stable-dind + script: + - setup_docker + - dependency_scanning + artifacts: + paths: [gl-dependency-scanning-report.json] +sast:container: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind script: - setup_docker - sast_container @@ -324,7 +336,6 @@ production: fi docker run --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" \ - --env SAST_DISABLE_REMOTE_CHECKS="${SAST_DISABLE_REMOTE_CHECKS:-false}" \ --volume "$PWD:/code" \ --volume /var/run/docker.sock:/var/run/docker.sock \ "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code @@ -335,6 +346,20 @@ production: esac } + function dependency_scanning() { + case "$CI_SERVER_VERSION" in + *-ee) + docker run --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}" \ + --volume "$PWD:/code" \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code + ;; + *) + echo "GitLab EE is required" + ;; + esac + } + function deploy() { track="${1-stable}" name="$CI_ENVIRONMENT_SLUG" @@ -355,10 +380,16 @@ production: if [[ "$track" == "stable" ]]; then # for stable track get number of replicas from `PRODUCTION_REPLICAS` eval new_replicas=\$${env_slug}_REPLICAS + if [[ -z "$new_replicas" ]]; then + new_replicas=$REPLICAS + fi service_enabled="true" else # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS` eval new_replicas=\$${env_track}_${env_slug}_REPLICAS + if [[ -z "$new_replicas" ]]; then + eval new_replicas=\${env_track}_REPLICAS + fi fi if [[ -n "$new_replicas" ]]; then replicas="$new_replicas" diff --git a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml index 0ad662cf704..0688f77a1d2 100644 --- a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml @@ -32,7 +32,7 @@ before_script: - apt-get install git nodejs libcurl4-gnutls-dev libicu-dev libmcrypt-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libpq-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev -yqq # Install php extensions - - docker-php-ext-install mbstring mcrypt pdo_mysql curl json intl gd xml zip bz2 opcache + - docker-php-ext-install mbstring pdo_mysql curl json intl gd xml zip bz2 opcache # Install & enable Xdebug for code coverage reports - pecl install xdebug diff --git a/vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml new file mode 100644 index 00000000000..9df2a4797b2 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml @@ -0,0 +1,17 @@ +image: node:latest + +# This folder is cached between builds +# http://docs.gitlab.com/ce/ci/yaml/README.html#cache +cache: + paths: + - node_modules/ + +pages: + script: + - yarn install + - ./node_modules/.bin/gatsby build --prefix-paths + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml index a72b8281401..b8cfb0f56f6 100644 --- a/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml @@ -1,5 +1,5 @@ # Full project: https://gitlab.com/pages/hugo -image: publysher/hugo +image: dettmering/hugo-build pages: script: diff --git a/vendor/gitlab-ci-yml/Python.gitlab-ci.yml b/vendor/gitlab-ci-yml/Python.gitlab-ci.yml index a2882a5407d..2e0589de652 100644 --- a/vendor/gitlab-ci-yml/Python.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Python.gitlab-ci.yml @@ -1,8 +1,27 @@ -# This file is a template, and might need editing before it works on your project. +# Official language image. Look for the different tagged releases at: +# https://hub.docker.com/r/library/python/tags/ image: python:latest +# Change pip's cache directory to be inside the project directory since we can +# only cache local items. +variables: + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache" + +# Pip's cache doesn't store the python packages +# https://pip.pypa.io/en/stable/reference/pip_install/#caching +# +# If you want to also cache the installed packages, you have to install +# them in a virtualenv and cache it as well. +cache: + paths: + - .cache/pip + - venv/ + before_script: - - python -V # Print out python version for debugging + - python -V # Print out python version for debugging + - pip install virtualenv + - virtualenv venv + - source venv/bin/activate test: script: diff --git a/vendor/licenses.csv b/vendor/licenses.csv index 03115292f02..ca88f867fe5 100644 --- a/vendor/licenses.csv +++ b/vendor/licenses.csv @@ -4,7 +4,7 @@ @babel/template,7.0.0-beta.32,MIT @babel/traverse,7.0.0-beta.32,MIT @babel/types,7.0.0-beta.32,MIT -@gitlab-org/gitlab-svgs,1.8.0,SEE LICENSE IN LICENSE +@gitlab-org/gitlab-svgs,1.17.0,SEE LICENSE IN LICENSE @types/jquery,2.0.48,MIT JSONStream,1.3.2,MIT RedCloth,4.3.2,MIT @@ -27,10 +27,11 @@ activejob,4.2.10,MIT activemodel,4.2.10,MIT activerecord,4.2.10,MIT activesupport,4.2.10,MIT -acts-as-taggable-on,4.0.0,MIT +acts-as-taggable-on,5.0.0,MIT address,1.0.3,MIT addressable,2.5.2,Apache 2.0 addressparser,1.0.1,MIT +aes_key_wrap,1.0.1,MIT after,0.8.2,MIT agent-base,2.1.1,MIT ajv,4.11.8,MIT @@ -80,8 +81,8 @@ array-unique,0.3.2,MIT arraybuffer.slice,0.0.7,MIT arrify,1.0.1,MIT asana,0.6.0,MIT -asciidoctor,1.5.3,MIT -asciidoctor-plantuml,0.0.7,MIT +asciidoctor,1.5.6.2,MIT +asciidoctor-plantuml,0.0.8,MIT asn1,0.2.3,MIT asn1.js,4.10.1,MIT assert,1.4.1,MIT @@ -205,8 +206,8 @@ better-assert,1.0.2,MIT bfj-node4,5.2.1,MIT big.js,3.1.3,MIT binary-extensions,1.11.0,MIT -bindata,2.4.1,ruby -bitsyntax,0.0.4,Unknown +bindata,2.4.3,ruby +bitsyntax,0.0.4,UNKNOWN bl,1.1.2,MIT blackst0ne-mermaid,7.1.0-fixed,MIT blob,0.0.4,MIT* @@ -274,7 +275,7 @@ chalk,1.1.3,MIT chalk,2.3.0,MIT chalk,2.3.1,MIT chardet,0.4.2,MIT -charlock_holmes,0.7.5,MIT +charlock_holmes,0.7.6,MIT chart.js,1.0.2,MIT check-types,7.3.0,MIT chokidar,1.7.0,MIT @@ -314,7 +315,7 @@ combine-lists,1.0.1,MIT combine-source-map,0.7.2,MIT combine-source-map,0.8.0,MIT combined-stream,1.0.6,MIT -commander,2.14.1,MIT +commander,2.15.1,MIT commondir,1.0.1,MIT commonmarker,0.17.8,MIT component-bind,1.0.0,MIT* @@ -352,6 +353,7 @@ core-js,2.5.3,MIT core-util-is,1.0.2,MIT cosmiconfig,2.1.1,MIT crack,0.4.3,MIT +crass,1.0.3,MIT create-ecdh,4.0.0,MIT create-error-class,3.0.2,MIT create-hash,1.1.3,MIT @@ -457,13 +459,13 @@ document-register-element,1.3.0,MIT dom-serialize,2.2.1,MIT dom-serializer,0.1.0,MIT domain-browser,1.1.7,MIT -domain_name,0.5.20161021,"Simplified BSD,New BSD,Mozilla Public License 2.0" +domain_name,0.5.20170404,"Simplified BSD,New BSD,Mozilla Public License 2.0" domelementtype,1.1.3,Simplified BSD domelementtype,1.3.0,Simplified BSD domhandler,2.4.1,Simplified BSD domutils,1.6.2,Simplified BSD -doorkeeper,4.2.6,MIT -doorkeeper-openid_connect,1.2.0,MIT +doorkeeper,4.3.1,MIT +doorkeeper-openid_connect,1.3.0,MIT dot-prop,4.2.0,MIT double-ended-queue,2.1.0-0,MIT dropzone,4.2.0,MIT @@ -543,7 +545,7 @@ eventemitter3,1.2.0,MIT events,1.1.1,MIT eventsource,0.1.6,MIT evp_bytestokey,1.0.3,MIT -excon,0.57.1,MIT +excon,0.60.0,MIT execa,0.7.0,MIT execjs,2.6.0,MIT exit-hook,1.1.1,MIT @@ -571,7 +573,7 @@ fast-deep-equal,1.0.0,MIT fast-json-stable-stringify,2.0.0,MIT fast-levenshtein,2.0.6,MIT fast_blank,1.0.0,MIT -fast_gettext,1.4.0,"MIT,ruby" +fast_gettext,1.6.0,"MIT,ruby" fastparse,1.1.1,MIT faye-websocket,0.10.0,MIT faye-websocket,0.11.1,MIT @@ -594,15 +596,15 @@ find-up,1.1.2,MIT find-up,2.1.0,MIT flat-cache,1.2.2,MIT flatten,1.0.2,MIT -flipper,0.11.0,MIT -flipper-active_record,0.11.0,MIT -flipper-active_support_cache_store,0.11.0,MIT +flipper,0.13.0,MIT +flipper-active_record,0.13.0,MIT +flipper-active_support_cache_store,0.13.0,MIT flowdock,0.7.1,MIT flush-write-stream,1.0.2,MIT fog-aliyun,0.2.0,MIT -fog-aws,1.4.0,MIT -fog-core,1.44.3,MIT -fog-google,0.5.3,MIT +fog-aws,2.0.1,MIT +fog-core,1.45.0,MIT +fog-google,1.3.3,MIT fog-json,1.0.2,MIT fog-local,0.3.1,MIT fog-openstack,0.1.21,MIT @@ -646,8 +648,8 @@ get-value,2.0.6,MIT get_process_mem,0.2.0,MIT getpass,0.1.7,MIT gettext_i18n_rails,1.8.0,MIT -gettext_i18n_rails_js,1.2.0,MIT -gitaly-proto,0.88.0,MIT +gettext_i18n_rails_js,1.3.0,MIT +gitaly-proto,0.94.0,MIT github-linguist,5.3.3,MIT github-markup,1.6.1,MIT gitlab-flowdock-git-hook,1.0.1,MIT @@ -669,12 +671,13 @@ globals,9.18.0,MIT globby,5.0.0,MIT globby,6.1.0,MIT globby,7.1.1,MIT +goldiloader,2.0.1,MIT gollum-grit_adapter,1.0.1,MIT gollum-lib,4.2.7,MIT gollum-rugged_adapter,0.4.4,MIT gon,6.1.0,MIT good-listener,1.2.2,MIT -google-api-client,0.13.6,Apache 2.0 +google-api-client,0.19.8,Apache 2.0 google-protobuf,3.5.1,New BSD googleapis-common-protos-types,1.0.1,Apache 2.0 googleauth,0.6.2,Apache 2.0 @@ -682,7 +685,7 @@ got,6.7.1,MIT got,7.1.0,MIT gpgme,2.0.13,LGPL-2.1+ graceful-fs,4.1.11,ISC -grape,1.0.0,MIT +grape,1.0.2,MIT grape-entity,0.6.0,MIT grape-route-helpers,2.1.0,MIT grape_logging,1.7.0,MIT @@ -716,7 +719,7 @@ hash-base,2.0.2,MIT hash-base,3.0.4,MIT hash-sum,1.0.2,MIT hash.js,1.1.3,MIT -hashie,3.5.6,MIT +hashie,3.5.7,MIT hashie-forbidden_attributes,0.1.1,MIT hawk,3.1.3,New BSD hawk,6.0.2,New BSD @@ -733,16 +736,16 @@ hosted-git-info,2.2.0,ISC hpack.js,2.1.6,MIT html-comment-regex,1.1.1,MIT html-entities,1.2.0,MIT -html-pipeline,1.11.0,MIT +html-pipeline,2.7.1,MIT html2text,0.2.0,MIT htmlentities,4.3.4,MIT htmlescape,1.1.1,MIT htmlparser2,3.9.2,MIT -http,0.9.8,MIT +http,2.2.2,MIT http-cookie,1.0.3,MIT http-deceiver,1.2.7,MIT http-errors,1.6.2,MIT -http-form_data,1.0.1,MIT +http-form_data,1.0.3,MIT http-proxy,1.16.2,MIT http-proxy-agent,1.0.0,MIT http-proxy-middleware,0.17.4,MIT @@ -750,13 +753,13 @@ http-signature,1.1.1,MIT http-signature,1.2.0,MIT http_parser.rb,0.6.0,MIT httparty,0.13.7,MIT -httpclient,2.8.2,ruby +httpclient,2.8.3,ruby httpntlm,1.6.1,MIT httpreq,0.4.24,MIT https-browserify,0.0.1,MIT https-browserify,1.0.0,MIT https-proxy-agent,1.0.0,MIT -i18n,0.9.1,MIT +i18n,0.9.5,MIT ice_nine,0.11.2,MIT iconv-lite,0.4.15,MIT iconv-lite,0.4.19,MIT @@ -881,7 +884,6 @@ jed,1.1.1,MIT jira-ruby,1.4.1,MIT jquery,3.3.1,MIT jquery-atwho-rails,1.3.2,MIT -jquery-rails,4.3.1,MIT jquery-ujs,1.2.2,MIT jquery.waitforimages,2.2.0,MIT js-base64,2.1.9,New BSD @@ -893,7 +895,7 @@ jsbn,0.1.1,MIT jsesc,0.5.0,MIT jsesc,1.3.0,MIT json,1.8.6,ruby -json-jwt,1.7.2,MIT +json-jwt,1.9.2,MIT json-loader,0.5.7,MIT json-schema,0.2.3,BSD json-schema-traverse,0.3.1,MIT @@ -927,7 +929,7 @@ kind-of,3.2.2,MIT kind-of,4.0.0,MIT kind-of,5.1.0,MIT kind-of,6.0.2,MIT -kubeclient,2.2.0,MIT +kubeclient,3.0.0,MIT labeled-stream-splicer,2.0.0,MIT latest-version,3.1.0,MIT lazy-cache,1.0.4,MIT @@ -938,7 +940,7 @@ lexical-scope,1.2.0,MIT libbase64,0.1.0,MIT libmime,3.0.0,MIT libqp,1.1.0,MIT -licensee,8.7.0,MIT +licensee,8.9.2,MIT lie,3.1.1,MIT little-plugger,1.1.4,MIT load-json-file,1.1.0,MIT @@ -980,7 +982,7 @@ loggly,1.1.1,MIT loglevel,1.4.1,MIT lograge,0.5.1,MIT longest,1.0.1,MIT -loofah,2.0.3,MIT +loofah,2.2.2,MIT loose-envify,1.3.1,MIT loud-rejection,1.6.0,MIT lowercase-keys,1.0.0,MIT @@ -994,7 +996,7 @@ mailgun-js,0.7.15,MIT make-dir,1.0.0,MIT map-cache,0.2.2,MIT map-obj,1.0.1,MIT -map-stream,0.1.0,Unknown +map-stream,0.1.0,UNKNOWN map-visit,1.0.0,MIT marked,0.3.12,MIT match-at,0.1.1,MIT @@ -1022,7 +1024,7 @@ mime-types-data,3.2016.0521,MIT mimemagic,0.3.0,MIT mimic-fn,1.1.0,MIT mimic-response,1.0.0,MIT -mini_mime,0.1.4,MIT +mini_mime,1.0.0,MIT mini_portile2,2.3.0,MIT minimalistic-assert,1.0.0,ISC minimalistic-crypto-utils,1.0.1,MIT @@ -1047,7 +1049,7 @@ multi_xml,0.6.0,MIT multicast-dns,6.1.1,MIT multicast-dns-service-types,1.1.0,MIT multipart-post,2.0.0,MIT -mustermann,1.0.0,MIT +mustermann,1.0.2,MIT mustermann-grape,1.0.0,MIT mute-stream,0.0.5,ISC mute-stream,0.0.7,ISC @@ -1058,7 +1060,7 @@ nanomatch,1.2.9,MIT natural-compare,1.4.0,MIT negotiator,0.6.1,MIT net-ldap,0.16.0,MIT -net-ssh,4.1.0,MIT +net-ssh,4.2.0,MIT netmask,1.0.6,MIT netrc,0.11.0,MIT node-forge,0.6.33,New BSD @@ -1088,7 +1090,7 @@ null-check,1.0.0,MIT num2fraction,1.2.2,MIT number-is-nan,1.0.1,MIT numerizer,0.1.1,MIT -oauth,0.5.1,MIT +oauth,0.5.4,MIT oauth-sign,0.8.2,Apache 2.0 oauth2,1.4.0,MIT object-assign,4.1.1,MIT @@ -1099,25 +1101,25 @@ object-visit,1.0.1,MIT object.omit,2.0.1,MIT object.pick,1.3.0,MIT obuf,1.1.1,MIT -octokit,4.6.2,MIT -oj,2.17.5,MIT -omniauth,1.4.2,MIT -omniauth-auth0,1.4.1,MIT +octokit,4.8.0,MIT +omniauth,1.8.1,MIT +omniauth-auth0,2.0.0,MIT omniauth-authentiq,0.3.1,MIT omniauth-azure-oauth2,0.0.9,MIT omniauth-cas3,1.1.4,MIT omniauth-facebook,4.0.0,MIT omniauth-github,1.1.2,MIT omniauth-gitlab,1.0.2,MIT -omniauth-google-oauth2,0.5.2,MIT +omniauth-google-oauth2,0.5.3,MIT +omniauth-jwt,0.0.2,MIT omniauth-kerberos,0.3.0,MIT omniauth-multipassword,0.4.2,MIT omniauth-oauth,1.1.0,MIT -omniauth-oauth2,1.4.0,MIT +omniauth-oauth2,1.5.0,MIT omniauth-oauth2-generic,0.2.2,MIT -omniauth-saml,1.7.0,MIT +omniauth-saml,1.10.0,MIT omniauth-shibboleth,1.2.1,MIT -omniauth-twitter,1.2.1,MIT +omniauth-twitter,1.4.0,MIT omniauth_crowd,2.2.3,MIT on-finished,2.3.0,MIT on-headers,1.0.1,MIT @@ -1181,7 +1183,6 @@ pause-stream,0.0.11,Apache 2.0 pbkdf2,3.0.14,MIT peek,1.0.1,MIT peek-gc,0.0.2,MIT -peek-host,1.0.0,MIT peek-mysql2,1.1.0,MIT peek-performance_bar,1.3.1,MIT peek-pg,1.3.0,MIT @@ -1248,8 +1249,8 @@ premailer,1.10.4,New BSD premailer-rails,1.9.7,MIT prepend-http,1.0.4,MIT preserve,0.2.0,MIT +prettier,1.11.1,MIT prettier,1.8.2,MIT -prettier,1.9.2,MIT prismjs,1.6.0,MIT private,0.1.8,MIT process,0.11.10,MIT @@ -1283,18 +1284,18 @@ querystring,0.2.0,MIT querystring-es3,0.2.1,MIT querystringify,0.0.4,MIT querystringify,1.0.0,MIT -rack,1.6.8,MIT +rack,1.6.9,MIT rack-accept,0.4.5,MIT rack-attack,4.4.1,MIT rack-cors,1.0.2,MIT rack-oauth2,1.2.3,MIT -rack-protection,1.5.3,MIT +rack-protection,2.0.1,MIT rack-proxy,0.6.0,MIT rack-test,0.6.3,MIT rails,4.2.10,MIT rails-deprecated_sanitizer,1.0.3,MIT -rails-dom-testing,1.0.8,MIT -rails-html-sanitizer,1.0.3,MIT +rails-dom-testing,1.0.9,MIT +rails-html-sanitizer,1.0.4,MIT rails-i18n,4.0.9,MIT railties,4.2.10,MIT rainbow,2.2.2,MIT @@ -1331,7 +1332,7 @@ readdirp,2.1.0,MIT readline2,1.0.1,MIT recaptcha,3.0.0,MIT rechoir,0.6.2,MIT -recursive-open-struct,1.0.0,MIT +recursive-open-struct,1.0.5,MIT recursive-readdir,2.2.1,MIT redcarpet,3.4.0,MIT redent,1.0.0,MIT @@ -1383,7 +1384,7 @@ resolve-from,1.0.1,MIT resolve-from,3.0.0,MIT resolve-url,0.2.1,MIT responders,2.3.0,MIT -rest-client,2.0.0,MIT +rest-client,2.0.2,MIT restore-cursor,1.0.1,MIT restore-cursor,2.0.0,MIT ret,0.1.15,MIT @@ -1399,13 +1400,13 @@ rqrcode,0.7.0,MIT rqrcode-rails3,0.1.7,MIT ruby-enum,0.7.2,MIT ruby-fogbugz,0.2.1,MIT -ruby-prof,0.16.2,Simplified BSD -ruby-saml,1.4.1,MIT +ruby-prof,0.17.0,Simplified BSD +ruby-saml,1.7.2,MIT ruby_parser,3.9.0,MIT rubyntlm,0.6.2,MIT rubypants,0.2.0,BSD rufus-scheduler,3.4.0,MIT -rugged,0.26.0,MIT +rugged,0.27.0,MIT run-async,0.1.0,MIT run-async,2.3.0,MIT run-queue,1.0.3,ISC @@ -1436,7 +1437,7 @@ semver,5.3.0,ISC semver,5.5.0,ISC semver-diff,2.1.0,MIT send,0.16.1,MIT -sentry-raven,2.5.3,Apache 2.0 +sentry-raven,2.7.2,Apache 2.0 serialize-javascript,1.4.0,New BSD serve-index,1.9.0,MIT serve-static,1.13.1,MIT @@ -1507,9 +1508,9 @@ srcset,1.0.0,MIT sshkey,1.9.0,MIT sshpk,1.13.1,MIT ssri,5.2.4,ISC -state_machines,0.4.0,MIT -state_machines-activemodel,0.4.0,MIT -state_machines-activerecord,0.4.0,MIT +state_machines,0.5.0,MIT +state_machines-activemodel,0.5.1,MIT +state_machines-activerecord,0.5.1,MIT static-extend,0.1.2,MIT statuses,1.3.1,MIT statuses,1.4.0,MIT @@ -1603,7 +1604,7 @@ tweetnacl,0.14.5,Unlicense type-check,0.3.2,MIT type-is,1.6.16,MIT typedarray,0.0.6,MIT -tzinfo,1.2.4,MIT +tzinfo,1.2.5,MIT u2f,0.2.1,MIT uber,0.1.0,MIT uglifier,2.7.2,MIT @@ -1618,7 +1619,7 @@ undefsafe,2.0.2,MIT underscore,1.7.0,MIT underscore,1.8.3,MIT unf,0.1.4,BSD -unf_ext,0.0.7.4,MIT +unf_ext,0.0.7.5,MIT unicorn,5.1.0,ruby unicorn-worker-killer,0.4.4,ruby union-value,1.0.0,MIT diff --git a/yarn.lock b/yarn.lock index dfa98d0cad1..fde06adf67e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1863,9 +1863,9 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.13.0, commander@^2.9.0: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" +commander@^2.13.0, commander@^2.15.1, commander@^2.9.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" commondir@^1.0.1: version "1.0.1"