diff options
-rw-r--r-- | .eslintrc | 2 | ||||
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rw-r--r-- | Gemfile | 2 | ||||
-rw-r--r-- | Gemfile.lock | 4 | ||||
-rw-r--r-- | app/assets/javascripts/abuse_reports.js (renamed from app/assets/javascripts/abuse_reports.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/activities.js (renamed from app/assets/javascripts/activities.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/blob/blob_ci_yaml.js (renamed from app/assets/javascripts/blob/blob_ci_yaml.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/blob/blob_dockerfile_selector.js (renamed from app/assets/javascripts/blob/blob_dockerfile_selector.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/blob/blob_dockerfile_selectors.js (renamed from app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/blob/blob_license_selectors.js (renamed from app/assets/javascripts/blob/blob_license_selectors.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/blob/template_selector.js (renamed from app/assets/javascripts/blob/template_selector.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/boards_bundle.js (renamed from app/assets/javascripts/boards/boards_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board.js (renamed from app/assets/javascripts/boards/components/board.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_blank_state.js (renamed from app/assets/javascripts/boards/components/board_blank_state.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_delete.js (renamed from app/assets/javascripts/boards/components/board_delete.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_list.js (renamed from app/assets/javascripts/boards/components/board_list.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/board_sidebar.js (renamed from app/assets/javascripts/boards/components/board_sidebar.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/issue_card_inner.js (renamed from app/assets/javascripts/boards/components/issue_card_inner.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/empty_state.js (renamed from app/assets/javascripts/boards/components/modal/empty_state.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/filters.js (renamed from app/assets/javascripts/boards/components/modal/filters.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/filters/label.js (renamed from app/assets/javascripts/boards/components/modal/filters/label.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/filters/milestone.js (renamed from app/assets/javascripts/boards/components/modal/filters/milestone.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/filters/user.js (renamed from app/assets/javascripts/boards/components/modal/filters/user.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/footer.js (renamed from app/assets/javascripts/boards/components/modal/footer.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/header.js (renamed from app/assets/javascripts/boards/components/modal/header.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/index.js (renamed from app/assets/javascripts/boards/components/modal/index.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/list.js (renamed from app/assets/javascripts/boards/components/modal/list.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/lists_dropdown.js (renamed from app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/modal/tabs.js (renamed from app/assets/javascripts/boards/components/modal/tabs.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/new_list_dropdown.js (renamed from app/assets/javascripts/boards/components/new_list_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/components/sidebar/remove_issue.js (renamed from app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/filters/due_date_filters.js (renamed from app/assets/javascripts/boards/filters/due_date_filters.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/mixins/modal_mixins.js (renamed from app/assets/javascripts/boards/mixins/modal_mixins.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/mixins/sortable_default_options.js (renamed from app/assets/javascripts/boards/mixins/sortable_default_options.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/issue.js (renamed from app/assets/javascripts/boards/models/issue.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/label.js (renamed from app/assets/javascripts/boards/models/label.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/list.js (renamed from app/assets/javascripts/boards/models/list.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/milestone.js (renamed from app/assets/javascripts/boards/models/milestone.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/models/user.js (renamed from app/assets/javascripts/boards/models/user.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/services/board_service.js (renamed from app/assets/javascripts/boards/services/board_service.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/boards_store.js (renamed from app/assets/javascripts/boards/stores/boards_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/modal_store.js (renamed from app/assets/javascripts/boards/stores/modal_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/build_variables.js (renamed from app/assets/javascripts/build_variables.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/ci_lint_editor.js (renamed from app/assets/javascripts/ci_lint_editor.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/commit/pipelines/pipelines_bundle.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/commit/pipelines/pipelines_service.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_service.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/commit/pipelines/pipelines_store.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/commit/pipelines/pipelines_table.js (renamed from app/assets/javascripts/commit/pipelines/pipelines_table.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/commons/bootstrap.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/commons/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/commons/jquery.js | 11 | ||||
-rw-r--r-- | app/assets/javascripts/compare_autocomplete.js (renamed from app/assets/javascripts/compare_autocomplete.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/copy_as_gfm.js (renamed from app/assets/javascripts/copy_as_gfm.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/create_label.js (renamed from app/assets/javascripts/create_label.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_code_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_issue_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_plan_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_production_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_review_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_staging_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/stage_test_component.js (renamed from app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/components/total_time_component.js (renamed from app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/cycle_analytics_service.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/cycle_analytics_store.js (renamed from app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/cycle_analytics/default_event_objects.js (renamed from app/assets/javascripts/cycle_analytics/default_event_objects.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff.js (renamed from app/assets/javascripts/diff.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/components/comment_resolve_btn.js (renamed from app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/components/jump_to_discussion.js (renamed from app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/components/resolve_btn.js (renamed from app/assets/javascripts/diff_notes/components/resolve_btn.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/components/resolve_count.js (renamed from app/assets/javascripts/diff_notes/components/resolve_count.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js (renamed from app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/diff_notes_bundle.js (renamed from app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/mixins/discussion.js (renamed from app/assets/javascripts/diff_notes/mixins/discussion.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/models/discussion.js (renamed from app/assets/javascripts/diff_notes/models/discussion.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/models/note.js (renamed from app/assets/javascripts/diff_notes/models/note.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/services/resolve.js (renamed from app/assets/javascripts/diff_notes/services/resolve.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/diff_notes/stores/comments.js (renamed from app/assets/javascripts/diff_notes/stores/comments.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/dispatcher.js (renamed from app/assets/javascripts/dispatcher.js.es6) | 13 | ||||
-rw-r--r-- | app/assets/javascripts/due_date_select.js (renamed from app/assets/javascripts/due_date_select.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment.js (renamed from app/assets/javascripts/environments/components/environment.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_actions.js (renamed from app/assets/javascripts/environments/components/environment_actions.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_external_url.js (renamed from app/assets/javascripts/environments/components/environment_external_url.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_item.js (renamed from app/assets/javascripts/environments/components/environment_item.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_rollback.js (renamed from app/assets/javascripts/environments/components/environment_rollback.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_stop.js (renamed from app/assets/javascripts/environments/components/environment_stop.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environment_terminal_button.js (renamed from app/assets/javascripts/environments/components/environment_terminal_button.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/components/environments_table.js (renamed from app/assets/javascripts/environments/components/environments_table.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/environments_bundle.js (renamed from app/assets/javascripts/environments/environments_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/folder/environments_folder_bundle.js (renamed from app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/folder/environments_folder_view.js (renamed from app/assets/javascripts/environments/folder/environments_folder_view.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/services/environments_service.js (renamed from app/assets/javascripts/environments/services/environments_service.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/environments/stores/environments_store.js (renamed from app/assets/javascripts/environments/stores/environments_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/extensions/array.js (renamed from app/assets/javascripts/extensions/array.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/extensions/custom_event.js (renamed from app/assets/javascripts/extensions/custom_event.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/extensions/element.js (renamed from app/assets/javascripts/extensions/element.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/extensions/object.js (renamed from app/assets/javascripts/extensions/object.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filterable_list.js | 45 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/dropdown_hint.js (renamed from app/assets/javascripts/filtered_search/dropdown_hint.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/dropdown_non_user.js (renamed from app/assets/javascripts/filtered_search/dropdown_non_user.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/dropdown_user.js (renamed from app/assets/javascripts/filtered_search/dropdown_user.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/dropdown_utils.js (renamed from app/assets/javascripts/filtered_search/dropdown_utils.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/filtered_search_dropdown.js (renamed from app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js (renamed from app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/filtered_search_manager.js (renamed from app/assets/javascripts/filtered_search/filtered_search_manager.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/filtered_search_token_keys.js (renamed from app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/filtered_search_tokenizer.js (renamed from app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/gfm_auto_complete.js (renamed from app/assets/javascripts/gfm_auto_complete.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/gl_field_error.js (renamed from app/assets/javascripts/gl_field_error.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/gl_field_errors.js (renamed from app/assets/javascripts/gl_field_errors.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/gl_form.js (renamed from app/assets/javascripts/gl_form.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/graphs/graphs_bundle.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/group_label_subscription.js (renamed from app/assets/javascripts/group_label_subscription.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/groups_list.js | 45 | ||||
-rw-r--r-- | app/assets/javascripts/issuable.js (renamed from app/assets/javascripts/issuable.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/issuable_bundle.js (renamed from app/assets/javascripts/issuable/issuable_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js (renamed from app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/help_state.js (renamed from app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js (renamed from app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/components/time_tracker.js (renamed from app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js (renamed from app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6) | 2 | ||||
-rw-r--r-- | app/assets/javascripts/issues_bulk_assignment.js (renamed from app/assets/javascripts/issues_bulk_assignment.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/label_manager.js (renamed from app/assets/javascripts/label_manager.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/chart.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/lib/cropper.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/lib/d3.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js (renamed from app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/common_utils.js (renamed from app/assets/javascripts/lib/utils/common_utils.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/datetime_utility.js (renamed from app/assets/javascripts/lib/utils/datetime_utility.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/pretty_time.js (renamed from app/assets/javascripts/lib/utils/pretty_time.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/url_utility.js (renamed from app/assets/javascripts/lib/utils/url_utility.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/lib/vue_resource.js.es6 | 2 | ||||
-rw-r--r-- | app/assets/javascripts/main.js (renamed from app/assets/javascripts/application.js) | 48 | ||||
-rw-r--r-- | app/assets/javascripts/member_expiration_date.js (renamed from app/assets/javascripts/member_expiration_date.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/members.js (renamed from app/assets/javascripts/members.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/components/diff_file_editor.js (renamed from app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js (renamed from app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js (renamed from app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/merge_conflict_service.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/merge_conflict_store.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js (renamed from app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js (renamed from app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js (renamed from app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_request_tabs.js (renamed from app/assets/javascripts/merge_request_tabs.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/merge_request_widget.js (renamed from app/assets/javascripts/merge_request_widget.js.es6) | 46 | ||||
-rw-r--r-- | app/assets/javascripts/merge_request_widget/ci_bundle.js (renamed from app/assets/javascripts/merge_request_widget/ci_bundle.js.es6) | 10 | ||||
-rw-r--r-- | app/assets/javascripts/mini_pipeline_graph_dropdown.js (renamed from app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/notes.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/pager.js (renamed from app/assets/javascripts/pager.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/pipelines.js (renamed from app/assets/javascripts/pipelines.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/profile/gl_crop.js (renamed from app/assets/javascripts/profile/gl_crop.js.es6) | 2 | ||||
-rw-r--r-- | app/assets/javascripts/profile/profile.js (renamed from app/assets/javascripts/profile/profile.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/project_label_subscription.js (renamed from app/assets/javascripts/project_label_subscription.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/project_variables.js (renamed from app/assets/javascripts/project_variables.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/projects_list.js | 64 | ||||
-rw-r--r-- | app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js (renamed from app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/protected_branches/protected_branch_create.js (renamed from app/assets/javascripts/protected_branches/protected_branch_create.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/protected_branches/protected_branch_dropdown.js (renamed from app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/protected_branches/protected_branch_edit.js (renamed from app/assets/javascripts/protected_branches/protected_branch_edit.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/protected_branches/protected_branch_edit_list.js (renamed from app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/search_autocomplete.js (renamed from app/assets/javascripts/search_autocomplete.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/shortcuts_blob.js (renamed from app/assets/javascripts/shortcuts_blob.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/signin_tabs_memoizer.js (renamed from app/assets/javascripts/signin_tabs_memoizer.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/smart_interval.js (renamed from app/assets/javascripts/smart_interval.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/snippets_list.js (renamed from app/assets/javascripts/snippets_list.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/subbable_resource.js (renamed from app/assets/javascripts/subbable_resource.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/subscription.js (renamed from app/assets/javascripts/subscription.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/templates/issuable_template_selector.js (renamed from app/assets/javascripts/templates/issuable_template_selector.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/templates/issuable_template_selectors.js (renamed from app/assets/javascripts/templates/issuable_template_selectors.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/terminal/terminal.js (renamed from app/assets/javascripts/terminal/terminal.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/terminal/terminal_bundle.js (renamed from app/assets/javascripts/terminal/terminal_bundle.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/todos.js (renamed from app/assets/javascripts/todos.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/u2f/authenticate.js (renamed from app/assets/javascripts/u2f/authenticate.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/user.js (renamed from app/assets/javascripts/user.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/user_tabs.js (renamed from app/assets/javascripts/user_tabs.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/username_validator.js (renamed from app/assets/javascripts/username_validator.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/users/calendar.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/version_check_image.js (renamed from app/assets/javascripts/version_check_image.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/visibility_select.js (renamed from app/assets/javascripts/visibility_select.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/index.js (renamed from app/assets/javascripts/vue_pipelines_index/index.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/pipeline_actions.js (renamed from app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/pipeline_url.js (renamed from app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/pipelines.js (renamed from app/assets/javascripts/vue_pipelines_index/pipelines.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/stage.js (renamed from app/assets/javascripts/vue_pipelines_index/stage.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/status.js (renamed from app/assets/javascripts/vue_pipelines_index/status.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/store.js (renamed from app/assets/javascripts/vue_pipelines_index/store.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_pipelines_index/time_ago.js (renamed from app/assets/javascripts/vue_pipelines_index/time_ago.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_realtime_listener/index.js (renamed from app/assets/javascripts/vue_realtime_listener/index.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/commit.js (renamed from app/assets/javascripts/vue_shared/components/commit.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/pipelines_table.js (renamed from app/assets/javascripts/vue_shared/components/pipelines_table.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/pipelines_table_row.js (renamed from app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/table_pagination.js (renamed from app/assets/javascripts/vue_shared/components/table_pagination.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/vue_resource_interceptor.js (renamed from app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/wikis.js (renamed from app/assets/javascripts/wikis.js.es6) | 0 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/header.scss | 6 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/layout.scss | 13 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/merge_requests.scss | 8 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/search.scss | 6 | ||||
-rw-r--r-- | app/controllers/admin/health_check_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/admin/projects_controller.rb | 9 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 4 | ||||
-rw-r--r-- | app/controllers/concerns/creates_commit.rb | 57 | ||||
-rw-r--r-- | app/controllers/concerns/filter_projects.rb | 2 | ||||
-rw-r--r-- | app/controllers/groups_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/profiles_controller.rb | 11 | ||||
-rw-r--r-- | app/controllers/projects/blob_controller.rb | 6 | ||||
-rw-r--r-- | app/controllers/projects/branches_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/commit_controller.rb | 32 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests_controller.rb | 5 | ||||
-rw-r--r-- | app/controllers/projects/notes_controller.rb | 7 | ||||
-rw-r--r-- | app/helpers/application_helper.rb | 2 | ||||
-rw-r--r-- | app/helpers/explore_helper.rb | 9 | ||||
-rw-r--r-- | app/helpers/mattermost_helper.rb | 6 | ||||
-rw-r--r-- | app/helpers/preferences_helper.rb | 4 | ||||
-rw-r--r-- | app/models/merge_request.rb | 5 | ||||
-rw-r--r-- | app/models/note.rb | 13 | ||||
-rw-r--r-- | app/models/project_services/kubernetes_service.rb | 7 | ||||
-rw-r--r-- | app/models/repository.rb | 33 | ||||
-rw-r--r-- | app/models/user.rb | 1 | ||||
-rw-r--r-- | app/services/ci/retry_build_service.rb | 19 | ||||
-rw-r--r-- | app/services/commits/change_service.rb | 52 | ||||
-rw-r--r-- | app/services/projects/update_pages_service.rb | 2 | ||||
-rw-r--r-- | app/services/system_note_service.rb | 1 | ||||
-rw-r--r-- | app/views/admin/projects/_projects.html.haml | 32 | ||||
-rw-r--r-- | app/views/admin/projects/index.html.haml | 85 | ||||
-rw-r--r-- | app/views/dashboard/_groups_head.html.haml | 3 | ||||
-rw-r--r-- | app/views/dashboard/_projects_head.html.haml | 3 | ||||
-rw-r--r-- | app/views/dashboard/projects/index.html.haml | 5 | ||||
-rw-r--r-- | app/views/explore/groups/_nav.html.haml | 8 | ||||
-rw-r--r-- | app/views/explore/groups/index.html.haml | 2 | ||||
-rw-r--r-- | app/views/explore/projects/_nav.html.haml | 27 | ||||
-rw-r--r-- | app/views/explore/projects/index.html.haml | 7 | ||||
-rw-r--r-- | app/views/groups/show.html.haml | 3 | ||||
-rw-r--r-- | app/views/layouts/_head.html.haml | 4 | ||||
-rw-r--r-- | app/views/layouts/application.html.haml | 2 | ||||
-rw-r--r-- | app/views/profiles/_head.html.haml | 1 | ||||
-rw-r--r-- | app/views/profiles/accounts/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/profiles/update_username.js.haml | 7 | ||||
-rw-r--r-- | app/views/projects/boards/_show.html.haml | 1 | ||||
-rw-r--r-- | app/views/projects/commit/_change.html.haml | 10 | ||||
-rw-r--r-- | app/views/projects/commit/_pipelines_list.haml | 1 | ||||
-rw-r--r-- | app/views/projects/cycle_analytics/show.html.haml | 1 | ||||
-rw-r--r-- | app/views/projects/environments/folder.html.haml | 1 | ||||
-rw-r--r-- | app/views/projects/environments/index.html.haml | 1 | ||||
-rw-r--r-- | app/views/projects/graphs/charts.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/graphs/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/issues/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/mattermosts/_team_selection.html.haml | 13 | ||||
-rw-r--r-- | app/views/projects/mattermosts/new.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/merge_requests/_show.html.haml | 1 | ||||
-rw-r--r-- | app/views/projects/merge_requests/conflicts.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/merge_requests/widget/open/_accept.html.haml | 10 | ||||
-rw-r--r-- | app/views/projects/milestones/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/notes/_notes_with_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/pipelines/charts.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/pipelines/index.html.haml | 1 | ||||
-rw-r--r-- | app/views/shared/_logo.svg | 2 | ||||
-rw-r--r-- | app/views/shared/groups/_search_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/shared/issuable/_sidebar.html.haml | 1 | ||||
-rw-r--r-- | app/views/shared/milestones/_summary.html.haml | 27 | ||||
-rw-r--r-- | app/views/shared/milestones/_tabs.html.haml | 34 | ||||
-rw-r--r-- | app/views/shared/projects/_dropdown.html.haml | 20 | ||||
-rw-r--r-- | app/views/shared/projects/_list.html.haml | 5 | ||||
-rw-r--r-- | app/views/shared/projects/_search_form.html.haml | 23 | ||||
-rw-r--r-- | app/views/users/show.html.haml | 2 | ||||
-rw-r--r-- | changelogs/unreleased/19497-hide-relevant-info-when-project-issues-are-disabled.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/26847-api-pipelines-use-basic.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/27532_api_changes.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/28010-mr-merge-button-default-to-danger.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/28655-current-path-text-is-not-updated-after-setting-the-new-username.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/28865-filter-by-authorized-projects-in-v4.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/28898-fix-search-branches-in-cherry-picking.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/28935-make-logo-smaller.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/3440-remove-hsts-header.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/add-kube-ca-pem-file-deprecate-kube-ca-pem.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/commons-chunk-plugin.yml | 5 | ||||
-rw-r--r-- | changelogs/unreleased/dashboard-filter-search-keep-params.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/delete-artifacts-for-pages.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/dm-fix-cherry-pick.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/dz-change-project-view.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/etag-notes-polling.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/format-timeago-date.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/list_issues_with_no_labels.yml | 4 | ||||
-rw-r--r-- | changelogs/unreleased/remove-es6-extension.yml | 4 | ||||
-rw-r--r-- | config/application.rb | 1 | ||||
-rw-r--r-- | config/initializers/8_metrics.rb (renamed from config/initializers/metrics.rb) | 0 | ||||
-rw-r--r-- | config/initializers/etag_caching.rb | 4 | ||||
-rw-r--r-- | config/karma.config.js | 13 | ||||
-rw-r--r-- | config/routes/project.rb | 4 | ||||
-rw-r--r-- | config/webpack.config.js | 54 | ||||
-rw-r--r-- | db/fixtures/development/13_comments.rb | 4 | ||||
-rw-r--r-- | doc/administration/reply_by_email.md | 56 | ||||
-rw-r--r-- | doc/api/issues.md | 6 | ||||
-rw-r--r-- | doc/api/milestones.md | 6 | ||||
-rw-r--r-- | doc/api/pipelines.md | 40 | ||||
-rw-r--r-- | doc/api/projects.md | 3 | ||||
-rw-r--r-- | doc/api/v3_to_v4.md | 9 | ||||
-rw-r--r-- | doc/development/instrumentation.md | 2 | ||||
-rw-r--r-- | doc/development/limit_ee_conflicts.md | 5 | ||||
-rw-r--r-- | doc/update/8.17-to-9.0.md | 24 | ||||
-rw-r--r-- | doc/user/project/integrations/kubernetes.md | 3 | ||||
-rw-r--r-- | doc/user/project/pages/getting_started_part_four.md | 3 | ||||
-rw-r--r-- | features/steps/project/commits/revert.rb | 1 | ||||
-rw-r--r-- | features/steps/project/fork.rb | 2 | ||||
-rw-r--r-- | features/steps/shared/project.rb | 8 | ||||
-rw-r--r-- | lib/api/api.rb | 2 | ||||
-rw-r--r-- | lib/api/commits.rb | 2 | ||||
-rw-r--r-- | lib/api/helpers.rb | 4 | ||||
-rw-r--r-- | lib/api/milestones.rb | 4 | ||||
-rw-r--r-- | lib/api/pipelines.rb | 4 | ||||
-rw-r--r-- | lib/api/projects.rb | 3 | ||||
-rw-r--r-- | lib/api/v3/commits.rb | 4 | ||||
-rw-r--r-- | lib/api/v3/milestones.rb | 43 | ||||
-rw-r--r-- | lib/api/v3/pipelines.rb | 36 | ||||
-rw-r--r-- | lib/gitlab/etag_caching/middleware.rb | 66 | ||||
-rw-r--r-- | lib/gitlab/etag_caching/store.rb | 32 | ||||
-rw-r--r-- | lib/gitlab/seeder.rb | 19 | ||||
-rw-r--r-- | lib/gitlab/sidekiq_status.rb | 35 | ||||
-rw-r--r-- | lib/mattermost/team.rb | 2 | ||||
-rw-r--r-- | lib/support/nginx/gitlab-ssl | 3 | ||||
-rw-r--r-- | spec/controllers/health_check_controller_spec.rb | 4 | ||||
-rw-r--r-- | spec/controllers/projects/branches_controller_spec.rb | 23 | ||||
-rw-r--r-- | spec/controllers/projects/commit_controller_spec.rb | 12 | ||||
-rw-r--r-- | spec/controllers/projects/graphs_controller_spec.rb | 10 | ||||
-rw-r--r-- | spec/controllers/projects/notes_controller_spec.rb | 27 | ||||
-rw-r--r-- | spec/factories/ci/builds.rb | 12 | ||||
-rw-r--r-- | spec/features/commits_spec.rb | 2 | ||||
-rw-r--r-- | spec/features/dashboard/archived_projects_spec.rb | 15 | ||||
-rw-r--r-- | spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb | 2 | ||||
-rw-r--r-- | spec/features/merge_requests/widget_spec.rb | 67 | ||||
-rw-r--r-- | spec/features/profile_spec.rb | 14 | ||||
-rw-r--r-- | spec/features/projects/commit/cherry_pick_spec.rb | 1 | ||||
-rw-r--r-- | spec/features/projects/milestones/milestone_spec.rb | 64 | ||||
-rw-r--r-- | spec/features/projects/services/mattermost_slash_command_spec.rb | 42 | ||||
-rw-r--r-- | spec/helpers/application_helper_spec.rb | 6 | ||||
-rw-r--r-- | spec/initializers/8_metrics_spec.rb (renamed from spec/initializers/metrics_spec.rb) | 2 | ||||
-rw-r--r-- | spec/javascripts/abuse_reports_spec.js (renamed from spec/javascripts/abuse_reports_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/activities_spec.js (renamed from spec/javascripts/activities_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/boards_store_spec.js (renamed from spec/javascripts/boards/boards_store_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/issue_card_spec.js (renamed from spec/javascripts/boards/issue_card_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/issue_spec.js (renamed from spec/javascripts/boards/issue_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/list_spec.js (renamed from spec/javascripts/boards/list_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/mock_data.js (renamed from spec/javascripts/boards/mock_data.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/boards/modal_store_spec.js (renamed from spec/javascripts/boards/modal_store_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/bootstrap_linked_tabs_spec.js (renamed from spec/javascripts/bootstrap_linked_tabs_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/build_spec.js (renamed from spec/javascripts/build_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/commit/pipelines/mock_data.js (renamed from spec/javascripts/commit/pipelines/mock_data.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/commit/pipelines/pipelines_spec.js (renamed from spec/javascripts/commit/pipelines/pipelines_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/commit/pipelines/pipelines_store_spec.js (renamed from spec/javascripts/commit/pipelines/pipelines_store_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/commits_spec.js (renamed from spec/javascripts/commits_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/datetime_utility_spec.js (renamed from spec/javascripts/datetime_utility_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/diff_comments_store_spec.js (renamed from spec/javascripts/diff_comments_store_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_actions_spec.js (renamed from spec/javascripts/environments/environment_actions_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_external_url_spec.js (renamed from spec/javascripts/environments/environment_external_url_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_item_spec.js (renamed from spec/javascripts/environments/environment_item_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_rollback_spec.js (renamed from spec/javascripts/environments/environment_rollback_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_spec.js (renamed from spec/javascripts/environments/environment_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_stop_spec.js (renamed from spec/javascripts/environments/environment_stop_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_table_spec.js (renamed from spec/javascripts/environments/environment_table_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/environments_store_spec.js (renamed from spec/javascripts/environments/environments_store_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/folder/environments_folder_view_spec.js (renamed from spec/javascripts/environments/folder/environments_folder_view_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/environments/mock_data.js (renamed from spec/javascripts/environments/mock_data.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/extensions/array_spec.js (renamed from spec/javascripts/extensions/array_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/extensions/element_spec.js (renamed from spec/javascripts/extensions/element_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/extensions/object_spec.js (renamed from spec/javascripts/extensions/object_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/dropdown_user_spec.js (renamed from spec/javascripts/filtered_search/dropdown_user_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/dropdown_utils_spec.js (renamed from spec/javascripts/filtered_search/dropdown_utils_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js (renamed from spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_manager_spec.js (renamed from spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_token_keys_spec.js (renamed from spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js (renamed from spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/gfm_auto_complete_spec.js (renamed from spec/javascripts/gfm_auto_complete_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/gl_dropdown_spec.js (renamed from spec/javascripts/gl_dropdown_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/gl_field_errors_spec.js (renamed from spec/javascripts/gl_field_errors_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/gl_form_spec.js (renamed from spec/javascripts/gl_form_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/helpers/class_spec_helper.js (renamed from spec/javascripts/helpers/class_spec_helper.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/helpers/class_spec_helper_spec.js (renamed from spec/javascripts/helpers/class_spec_helper_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/issuable_spec.js (renamed from spec/javascripts/issuable_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/issuable_time_tracker_spec.js (renamed from spec/javascripts/issuable_time_tracker_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/labels_issue_sidebar_spec.js (renamed from spec/javascripts/labels_issue_sidebar_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/common_utils_spec.js (renamed from spec/javascripts/lib/utils/common_utils_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/text_utility_spec.js (renamed from spec/javascripts/lib/utils/text_utility_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/mini_pipeline_graph_dropdown_spec.js (renamed from spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/pipelines_spec.js (renamed from spec/javascripts/pipelines_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/pretty_time_spec.js (renamed from spec/javascripts/pretty_time_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/signin_tabs_memoizer_spec.js (renamed from spec/javascripts/signin_tabs_memoizer_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/smart_interval_spec.js (renamed from spec/javascripts/smart_interval_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/subbable_resource_spec.js (renamed from spec/javascripts/subbable_resource_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/test_bundle.js | 13 | ||||
-rw-r--r-- | spec/javascripts/user_callout_spec.js (renamed from spec/javascripts/user_callout_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/version_check_image_spec.js (renamed from spec/javascripts/version_check_image_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/visibility_select_spec.js (renamed from spec/javascripts/visibility_select_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/commit_spec.js (renamed from spec/javascripts/vue_shared/components/commit_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/pipelines_table_row_spec.js (renamed from spec/javascripts/vue_shared/components/pipelines_table_row_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/pipelines_table_spec.js (renamed from spec/javascripts/vue_shared/components/pipelines_table_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/javascripts/vue_shared/components/table_pagination_spec.js (renamed from spec/javascripts/vue_shared/components/table_pagination_spec.js.es6) | 0 | ||||
-rw-r--r-- | spec/lib/gitlab/etag_caching/middleware_spec.rb | 163 | ||||
-rw-r--r-- | spec/lib/gitlab/sidekiq_status_spec.rb | 26 | ||||
-rw-r--r-- | spec/lib/mattermost/team_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/note_spec.rb | 12 | ||||
-rw-r--r-- | spec/models/project_services/kubernetes_service_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/project_services/mattermost_slash_commands_service_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 16 | ||||
-rw-r--r-- | spec/requests/api/milestones_spec.rb | 43 | ||||
-rw-r--r-- | spec/requests/api/pipelines_spec.rb | 1 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 69 | ||||
-rw-r--r-- | spec/requests/api/v3/milestones_spec.rb | 232 | ||||
-rw-r--r-- | spec/requests/api/v3/pipelines_spec.rb | 203 | ||||
-rw-r--r-- | spec/routing/project_routing_spec.rb | 18 | ||||
-rw-r--r-- | spec/services/ci/retry_build_service_spec.rb | 47 | ||||
-rw-r--r-- | spec/services/projects/update_pages_service_spec.rb | 22 | ||||
-rw-r--r-- | spec/services/system_note_service_spec.rb | 39 |
415 files changed, 2117 insertions, 707 deletions
diff --git a/.eslintrc b/.eslintrc index 0fcd866778f..b0ae2a31919 100644 --- a/.eslintrc +++ b/.eslintrc @@ -23,7 +23,7 @@ } }, "rules": { - "filenames/match-regex": [2, "^[a-z0-9_]+(.js)?$"], + "filenames/match-regex": [2, "^[a-z0-9_]+$"], "no-multiple-empty-lines": ["error", { "max": 1 }] } } diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9006fef6a27..deeb01f9a3c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -421,6 +421,7 @@ pages: - public only: - master@gitlab-org/gitlab-ce + - master@gitlab-org/gitlab-ee # Insurance in case a gem needed by one of our releases gets yanked from # rubygems.org in the future. @@ -437,3 +438,4 @@ cache gems: - vendor/cache only: - master@gitlab-org/gitlab-ce + - master@gitlab-org/gitlab-ee @@ -344,7 +344,7 @@ gem 'oauth2', '~> 1.2.0' gem 'paranoia', '~> 2.2' # Health check -gem 'health_check', '~> 2.2.0' +gem 'health_check', '~> 2.6.0' # System information gem 'vmstat', '~> 2.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 2d7e6f6f0bf..65120df205c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -336,7 +336,7 @@ GEM thor tilt hashie (3.5.5) - health_check (2.2.1) + health_check (2.6.0) rails (>= 4.0) hipchat (1.5.2) httparty @@ -895,7 +895,7 @@ DEPENDENCIES grape-entity (~> 0.6.0) haml_lint (~> 0.21.0) hamlit (~> 2.6.1) - health_check (~> 2.2.0) + health_check (~> 2.6.0) hipchat (~> 1.5.0) html-pipeline (~> 1.11.0) html2text diff --git a/app/assets/javascripts/abuse_reports.js.es6 b/app/assets/javascripts/abuse_reports.js index 8a260aae1b1..8a260aae1b1 100644 --- a/app/assets/javascripts/abuse_reports.js.es6 +++ b/app/assets/javascripts/abuse_reports.js diff --git a/app/assets/javascripts/activities.js.es6 b/app/assets/javascripts/activities.js index 648cb4d5d85..648cb4d5d85 100644 --- a/app/assets/javascripts/activities.js.es6 +++ b/app/assets/javascripts/activities.js diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js index ec1c018424d..ec1c018424d 100644 --- a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 +++ b/app/assets/javascripts/blob/blob_ci_yaml.js diff --git a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selector.js index d4f60cc6ecd..d4f60cc6ecd 100644 --- a/app/assets/javascripts/blob/blob_dockerfile_selector.js.es6 +++ b/app/assets/javascripts/blob/blob_dockerfile_selector.js diff --git a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 b/app/assets/javascripts/blob/blob_dockerfile_selectors.js index 9cee79fa5d5..9cee79fa5d5 100644 --- a/app/assets/javascripts/blob/blob_dockerfile_selectors.js.es6 +++ b/app/assets/javascripts/blob/blob_dockerfile_selectors.js diff --git a/app/assets/javascripts/blob/blob_license_selectors.js.es6 b/app/assets/javascripts/blob/blob_license_selectors.js index c5067b0feae..c5067b0feae 100644 --- a/app/assets/javascripts/blob/blob_license_selectors.js.es6 +++ b/app/assets/javascripts/blob/blob_license_selectors.js diff --git a/app/assets/javascripts/blob/template_selector.js.es6 b/app/assets/javascripts/blob/template_selector.js index 7e03ec3b391..7e03ec3b391 100644 --- a/app/assets/javascripts/blob/template_selector.js.es6 +++ b/app/assets/javascripts/blob/template_selector.js diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js index 55d13be6e5f..55d13be6e5f 100644 --- a/app/assets/javascripts/boards/boards_bundle.js.es6 +++ b/app/assets/javascripts/boards/boards_bundle.js diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js index 18324de18b3..18324de18b3 100644 --- a/app/assets/javascripts/boards/components/board.js.es6 +++ b/app/assets/javascripts/boards/components/board.js diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js index d76314c1892..d76314c1892 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js.es6 +++ b/app/assets/javascripts/boards/components/board_blank_state.js diff --git a/app/assets/javascripts/boards/components/board_delete.js.es6 b/app/assets/javascripts/boards/components/board_delete.js index 861600424a5..861600424a5 100644 --- a/app/assets/javascripts/boards/components/board_delete.js.es6 +++ b/app/assets/javascripts/boards/components/board_delete.js diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js index 2d52e96e7fb..2d52e96e7fb 100644 --- a/app/assets/javascripts/boards/components/board_list.js.es6 +++ b/app/assets/javascripts/boards/components/board_list.js diff --git a/app/assets/javascripts/boards/components/board_sidebar.js.es6 b/app/assets/javascripts/boards/components/board_sidebar.js index dfc6eed785c..dfc6eed785c 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js.es6 +++ b/app/assets/javascripts/boards/components/board_sidebar.js diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js.es6 b/app/assets/javascripts/boards/components/issue_card_inner.js index 22a8b971ff8..22a8b971ff8 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js.es6 +++ b/app/assets/javascripts/boards/components/issue_card_inner.js diff --git a/app/assets/javascripts/boards/components/modal/empty_state.js.es6 b/app/assets/javascripts/boards/components/modal/empty_state.js index 9538f5b69e9..9538f5b69e9 100644 --- a/app/assets/javascripts/boards/components/modal/empty_state.js.es6 +++ b/app/assets/javascripts/boards/components/modal/empty_state.js diff --git a/app/assets/javascripts/boards/components/modal/filters.js.es6 b/app/assets/javascripts/boards/components/modal/filters.js index 6de06811d94..6de06811d94 100644 --- a/app/assets/javascripts/boards/components/modal/filters.js.es6 +++ b/app/assets/javascripts/boards/components/modal/filters.js diff --git a/app/assets/javascripts/boards/components/modal/filters/label.js.es6 b/app/assets/javascripts/boards/components/modal/filters/label.js index 4fc8f72a145..4fc8f72a145 100644 --- a/app/assets/javascripts/boards/components/modal/filters/label.js.es6 +++ b/app/assets/javascripts/boards/components/modal/filters/label.js diff --git a/app/assets/javascripts/boards/components/modal/filters/milestone.js.es6 b/app/assets/javascripts/boards/components/modal/filters/milestone.js index d555599d300..d555599d300 100644 --- a/app/assets/javascripts/boards/components/modal/filters/milestone.js.es6 +++ b/app/assets/javascripts/boards/components/modal/filters/milestone.js diff --git a/app/assets/javascripts/boards/components/modal/filters/user.js.es6 b/app/assets/javascripts/boards/components/modal/filters/user.js index 8523028c29c..8523028c29c 100644 --- a/app/assets/javascripts/boards/components/modal/filters/user.js.es6 +++ b/app/assets/javascripts/boards/components/modal/filters/user.js diff --git a/app/assets/javascripts/boards/components/modal/footer.js.es6 b/app/assets/javascripts/boards/components/modal/footer.js index 1cbc422c961..1cbc422c961 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js.es6 +++ b/app/assets/javascripts/boards/components/modal/footer.js diff --git a/app/assets/javascripts/boards/components/modal/header.js.es6 b/app/assets/javascripts/boards/components/modal/header.js index 70c088f9054..70c088f9054 100644 --- a/app/assets/javascripts/boards/components/modal/header.js.es6 +++ b/app/assets/javascripts/boards/components/modal/header.js diff --git a/app/assets/javascripts/boards/components/modal/index.js.es6 b/app/assets/javascripts/boards/components/modal/index.js index f290cd13763..f290cd13763 100644 --- a/app/assets/javascripts/boards/components/modal/index.js.es6 +++ b/app/assets/javascripts/boards/components/modal/index.js diff --git a/app/assets/javascripts/boards/components/modal/list.js.es6 b/app/assets/javascripts/boards/components/modal/list.js index 3730c1ecaeb..3730c1ecaeb 100644 --- a/app/assets/javascripts/boards/components/modal/list.js.es6 +++ b/app/assets/javascripts/boards/components/modal/list.js diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6 b/app/assets/javascripts/boards/components/modal/lists_dropdown.js index 3c05120a2da..3c05120a2da 100644 --- a/app/assets/javascripts/boards/components/modal/lists_dropdown.js.es6 +++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.js diff --git a/app/assets/javascripts/boards/components/modal/tabs.js.es6 b/app/assets/javascripts/boards/components/modal/tabs.js index e8cb43f3503..e8cb43f3503 100644 --- a/app/assets/javascripts/boards/components/modal/tabs.js.es6 +++ b/app/assets/javascripts/boards/components/modal/tabs.js diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 b/app/assets/javascripts/boards/components/new_list_dropdown.js index 556826a9148..556826a9148 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 b/app/assets/javascripts/boards/components/sidebar/remove_issue.js index e74935e1cb0..e74935e1cb0 100644 --- a/app/assets/javascripts/boards/components/sidebar/remove_issue.js.es6 +++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.js diff --git a/app/assets/javascripts/boards/filters/due_date_filters.js.es6 b/app/assets/javascripts/boards/filters/due_date_filters.js index 03425bb145b..03425bb145b 100644 --- a/app/assets/javascripts/boards/filters/due_date_filters.js.es6 +++ b/app/assets/javascripts/boards/filters/due_date_filters.js diff --git a/app/assets/javascripts/boards/mixins/modal_mixins.js.es6 b/app/assets/javascripts/boards/mixins/modal_mixins.js index d378b7d4baf..d378b7d4baf 100644 --- a/app/assets/javascripts/boards/mixins/modal_mixins.js.es6 +++ b/app/assets/javascripts/boards/mixins/modal_mixins.js diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 b/app/assets/javascripts/boards/mixins/sortable_default_options.js index b6c6d17274f..b6c6d17274f 100644 --- a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 +++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js diff --git a/app/assets/javascripts/boards/models/issue.js.es6 b/app/assets/javascripts/boards/models/issue.js index 2d0a295ae4d..2d0a295ae4d 100644 --- a/app/assets/javascripts/boards/models/issue.js.es6 +++ b/app/assets/javascripts/boards/models/issue.js diff --git a/app/assets/javascripts/boards/models/label.js.es6 b/app/assets/javascripts/boards/models/label.js index 9af88d167d6..9af88d167d6 100644 --- a/app/assets/javascripts/boards/models/label.js.es6 +++ b/app/assets/javascripts/boards/models/label.js diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js index 8158ed4ec2c..8158ed4ec2c 100644 --- a/app/assets/javascripts/boards/models/list.js.es6 +++ b/app/assets/javascripts/boards/models/list.js diff --git a/app/assets/javascripts/boards/models/milestone.js.es6 b/app/assets/javascripts/boards/models/milestone.js index c867b06d320..c867b06d320 100644 --- a/app/assets/javascripts/boards/models/milestone.js.es6 +++ b/app/assets/javascripts/boards/models/milestone.js diff --git a/app/assets/javascripts/boards/models/user.js.es6 b/app/assets/javascripts/boards/models/user.js index 8e9de4d4cbb..8e9de4d4cbb 100644 --- a/app/assets/javascripts/boards/models/user.js.es6 +++ b/app/assets/javascripts/boards/models/user.js diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js index 065e90518df..065e90518df 100644 --- a/app/assets/javascripts/boards/services/board_service.js.es6 +++ b/app/assets/javascripts/boards/services/board_service.js diff --git a/app/assets/javascripts/boards/stores/boards_store.js.es6 b/app/assets/javascripts/boards/stores/boards_store.js index 56436c8fdc7..56436c8fdc7 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js.es6 +++ b/app/assets/javascripts/boards/stores/boards_store.js diff --git a/app/assets/javascripts/boards/stores/modal_store.js.es6 b/app/assets/javascripts/boards/stores/modal_store.js index 15fc6c79e8d..15fc6c79e8d 100644 --- a/app/assets/javascripts/boards/stores/modal_store.js.es6 +++ b/app/assets/javascripts/boards/stores/modal_store.js diff --git a/app/assets/javascripts/build_variables.js.es6 b/app/assets/javascripts/build_variables.js index 99082b412e2..99082b412e2 100644 --- a/app/assets/javascripts/build_variables.js.es6 +++ b/app/assets/javascripts/build_variables.js diff --git a/app/assets/javascripts/ci_lint_editor.js.es6 b/app/assets/javascripts/ci_lint_editor.js index 56ffaa765a8..56ffaa765a8 100644 --- a/app/assets/javascripts/ci_lint_editor.js.es6 +++ b/app/assets/javascripts/ci_lint_editor.js diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js index b5a988df897..b5a988df897 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js.es6 +++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js diff --git a/app/assets/javascripts/commit/pipelines/pipelines_service.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_service.js index 8ae98f9bf97..8ae98f9bf97 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_service.js.es6 +++ b/app/assets/javascripts/commit/pipelines/pipelines_service.js diff --git a/app/assets/javascripts/commit/pipelines/pipelines_store.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_store.js index f1b80e45444..f1b80e45444 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_store.js.es6 +++ b/app/assets/javascripts/commit/pipelines/pipelines_store.js diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js.es6 b/app/assets/javascripts/commit/pipelines/pipelines_table.js index 631ed34851c..631ed34851c 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.js.es6 +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js new file mode 100644 index 00000000000..db0cbfd87c3 --- /dev/null +++ b/app/assets/javascripts/commons/bootstrap.js @@ -0,0 +1,10 @@ +import 'jquery'; + +// bootstrap jQuery plugins +import 'bootstrap-sass/assets/javascripts/bootstrap/affix'; +import 'bootstrap-sass/assets/javascripts/bootstrap/alert'; +import 'bootstrap-sass/assets/javascripts/bootstrap/dropdown'; +import 'bootstrap-sass/assets/javascripts/bootstrap/modal'; +import 'bootstrap-sass/assets/javascripts/bootstrap/tab'; +import 'bootstrap-sass/assets/javascripts/bootstrap/transition'; +import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip'; diff --git a/app/assets/javascripts/commons/index.js b/app/assets/javascripts/commons/index.js new file mode 100644 index 00000000000..72ede1d621a --- /dev/null +++ b/app/assets/javascripts/commons/index.js @@ -0,0 +1,2 @@ +import './jquery'; +import './bootstrap'; diff --git a/app/assets/javascripts/commons/jquery.js b/app/assets/javascripts/commons/jquery.js new file mode 100644 index 00000000000..b53f6284afc --- /dev/null +++ b/app/assets/javascripts/commons/jquery.js @@ -0,0 +1,11 @@ +import 'jquery'; + +// common jQuery plugins +import 'jquery-ujs'; +import 'vendor/jquery.endless-scroll'; +import 'vendor/jquery.caret'; +import 'vendor/jquery.atwho'; +import 'vendor/jquery.scrollTo'; +import 'vendor/jquery.nicescroll'; +import 'vendor/jquery.waitforimages'; +import 'select2/select2'; diff --git a/app/assets/javascripts/compare_autocomplete.js.es6 b/app/assets/javascripts/compare_autocomplete.js index 1eca973e069..1eca973e069 100644 --- a/app/assets/javascripts/compare_autocomplete.js.es6 +++ b/app/assets/javascripts/compare_autocomplete.js diff --git a/app/assets/javascripts/copy_as_gfm.js.es6 b/app/assets/javascripts/copy_as_gfm.js index 2bc3d85fba4..2bc3d85fba4 100644 --- a/app/assets/javascripts/copy_as_gfm.js.es6 +++ b/app/assets/javascripts/copy_as_gfm.js diff --git a/app/assets/javascripts/create_label.js.es6 b/app/assets/javascripts/create_label.js index 85384d98126..85384d98126 100644 --- a/app/assets/javascripts/create_label.js.es6 +++ b/app/assets/javascripts/create_label.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js index b83a4c63fad..b83a4c63fad 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js index cb1687dcc7a..cb1687dcc7a 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js index 42e1bbce744..42e1bbce744 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js index 73f4205b578..73f4205b578 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js index 501ffb1fac9..501ffb1fac9 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js index 8fa63734cf1..8fa63734cf1 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js index 0015249cfaa..0015249cfaa 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6 b/app/assets/javascripts/cycle_analytics/components/total_time_component.js index 0d85e1a4678..0d85e1a4678 100644 --- a/app/assets/javascripts/cycle_analytics/components/total_time_component.js.es6 +++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.js diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index beff293b587..beff293b587 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js.es6 +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js index 9f74b14c4b9..9f74b14c4b9 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js.es6 +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6 b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js index 7ae9de7297c..7ae9de7297c 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js.es6 +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js diff --git a/app/assets/javascripts/cycle_analytics/default_event_objects.js.es6 b/app/assets/javascripts/cycle_analytics/default_event_objects.js index cfaf9835bf8..cfaf9835bf8 100644 --- a/app/assets/javascripts/cycle_analytics/default_event_objects.js.es6 +++ b/app/assets/javascripts/cycle_analytics/default_event_objects.js diff --git a/app/assets/javascripts/diff.js.es6 b/app/assets/javascripts/diff.js index 6829e8aeaea..6829e8aeaea 100644 --- a/app/assets/javascripts/diff.js.es6 +++ b/app/assets/javascripts/diff.js diff --git a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js index d948dff58ec..d948dff58ec 100644 --- a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js index 283dc330cad..283dc330cad 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_btn.js index d1873d6c7a2..d1873d6c7a2 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js diff --git a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_count.js index de9367f2136..de9367f2136 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_count.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_count.js diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js index 7c5fcd04d2d..7c5fcd04d2d 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6 +++ b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 b/app/assets/javascripts/diff_notes/diff_notes_bundle.js index cadf8b96b87..cadf8b96b87 100644 --- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js.es6 +++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js diff --git a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 b/app/assets/javascripts/diff_notes/mixins/discussion.js index 3c08c222f46..3c08c222f46 100644 --- a/app/assets/javascripts/diff_notes/mixins/discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/mixins/discussion.js diff --git a/app/assets/javascripts/diff_notes/models/discussion.js.es6 b/app/assets/javascripts/diff_notes/models/discussion.js index fa518ba4d33..fa518ba4d33 100644 --- a/app/assets/javascripts/diff_notes/models/discussion.js.es6 +++ b/app/assets/javascripts/diff_notes/models/discussion.js diff --git a/app/assets/javascripts/diff_notes/models/note.js.es6 b/app/assets/javascripts/diff_notes/models/note.js index f3a7cba5ef6..f3a7cba5ef6 100644 --- a/app/assets/javascripts/diff_notes/models/note.js.es6 +++ b/app/assets/javascripts/diff_notes/models/note.js diff --git a/app/assets/javascripts/diff_notes/services/resolve.js.es6 b/app/assets/javascripts/diff_notes/services/resolve.js index 090c454e9e4..090c454e9e4 100644 --- a/app/assets/javascripts/diff_notes/services/resolve.js.es6 +++ b/app/assets/javascripts/diff_notes/services/resolve.js diff --git a/app/assets/javascripts/diff_notes/stores/comments.js.es6 b/app/assets/javascripts/diff_notes/stores/comments.js index c80d979b977..c80d979b977 100644 --- a/app/assets/javascripts/diff_notes/stores/comments.js.es6 +++ b/app/assets/javascripts/diff_notes/stores/comments.js diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js index fc25122aedc..ef5785b5532 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js @@ -36,6 +36,7 @@ /* global Shortcuts */ import GroupsList from './groups_list'; +import ProjectsList from './projects_list'; const ShortcutsBlob = require('./shortcuts_blob'); const UserCallout = require('./user_callout'); @@ -98,6 +99,14 @@ const UserCallout = require('./user_callout'); case 'dashboard:todos:index': new gl.Todos(); break; + case 'dashboard:projects:index': + case 'dashboard:projects:starred': + case 'explore:projects:index': + case 'explore:projects:trending': + case 'explore:projects:starred': + case 'admin:projects:index': + new ProjectsList(); + break; case 'dashboard:groups:index': case 'explore:groups:index': new GroupsList(); @@ -163,9 +172,6 @@ const UserCallout = require('./user_callout'); case 'dashboard:activity': new gl.Activities(); break; - case 'dashboard:projects:starred': - new gl.Activities(); - break; case 'projects:commit:show': new Commit(); new gl.Diff(); @@ -208,6 +214,7 @@ const UserCallout = require('./user_callout'); shortcut_handler = new ShortcutsNavigation(); new NotificationsForm(); new NotificationsDropdown(); + new ProjectsList(); break; case 'groups:group_members:index': new gl.MemberExpirationDate(); diff --git a/app/assets/javascripts/due_date_select.js.es6 b/app/assets/javascripts/due_date_select.js index 9169fcd7328..9169fcd7328 100644 --- a/app/assets/javascripts/due_date_select.js.es6 +++ b/app/assets/javascripts/due_date_select.js diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js index 2cb48dde628..2cb48dde628 100644 --- a/app/assets/javascripts/environments/components/environment.js.es6 +++ b/app/assets/javascripts/environments/components/environment.js diff --git a/app/assets/javascripts/environments/components/environment_actions.js.es6 b/app/assets/javascripts/environments/components/environment_actions.js index 15e3f8823d2..15e3f8823d2 100644 --- a/app/assets/javascripts/environments/components/environment_actions.js.es6 +++ b/app/assets/javascripts/environments/components/environment_actions.js diff --git a/app/assets/javascripts/environments/components/environment_external_url.js.es6 b/app/assets/javascripts/environments/components/environment_external_url.js index 2599bba3c59..2599bba3c59 100644 --- a/app/assets/javascripts/environments/components/environment_external_url.js.es6 +++ b/app/assets/javascripts/environments/components/environment_external_url.js diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js index 7f4e070b229..7f4e070b229 100644 --- a/app/assets/javascripts/environments/components/environment_item.js.es6 +++ b/app/assets/javascripts/environments/components/environment_item.js diff --git a/app/assets/javascripts/environments/components/environment_rollback.js.es6 b/app/assets/javascripts/environments/components/environment_rollback.js index daf126eb4e8..daf126eb4e8 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.js.es6 +++ b/app/assets/javascripts/environments/components/environment_rollback.js diff --git a/app/assets/javascripts/environments/components/environment_stop.js.es6 b/app/assets/javascripts/environments/components/environment_stop.js index 96983a19568..96983a19568 100644 --- a/app/assets/javascripts/environments/components/environment_stop.js.es6 +++ b/app/assets/javascripts/environments/components/environment_stop.js diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.js.es6 b/app/assets/javascripts/environments/components/environment_terminal_button.js index e86607e78f4..e86607e78f4 100644 --- a/app/assets/javascripts/environments/components/environment_terminal_button.js.es6 +++ b/app/assets/javascripts/environments/components/environment_terminal_button.js diff --git a/app/assets/javascripts/environments/components/environments_table.js.es6 b/app/assets/javascripts/environments/components/environments_table.js index 4088d63be80..4088d63be80 100644 --- a/app/assets/javascripts/environments/components/environments_table.js.es6 +++ b/app/assets/javascripts/environments/components/environments_table.js diff --git a/app/assets/javascripts/environments/environments_bundle.js.es6 b/app/assets/javascripts/environments/environments_bundle.js index 7bbba91bc10..7bbba91bc10 100644 --- a/app/assets/javascripts/environments/environments_bundle.js.es6 +++ b/app/assets/javascripts/environments/environments_bundle.js diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_bundle.js index d2ca465351a..d2ca465351a 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6 +++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_view.js index 2a9d0492d7a..2a9d0492d7a 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6 +++ b/app/assets/javascripts/environments/folder/environments_folder_view.js diff --git a/app/assets/javascripts/environments/services/environments_service.js.es6 b/app/assets/javascripts/environments/services/environments_service.js index effc6c4c838..effc6c4c838 100644 --- a/app/assets/javascripts/environments/services/environments_service.js.es6 +++ b/app/assets/javascripts/environments/services/environments_service.js diff --git a/app/assets/javascripts/environments/stores/environments_store.js.es6 b/app/assets/javascripts/environments/stores/environments_store.js index 15cd9bde08e..15cd9bde08e 100644 --- a/app/assets/javascripts/environments/stores/environments_store.js.es6 +++ b/app/assets/javascripts/environments/stores/environments_store.js diff --git a/app/assets/javascripts/extensions/array.js.es6 b/app/assets/javascripts/extensions/array.js index f8256a8d26d..f8256a8d26d 100644 --- a/app/assets/javascripts/extensions/array.js.es6 +++ b/app/assets/javascripts/extensions/array.js diff --git a/app/assets/javascripts/extensions/custom_event.js.es6 b/app/assets/javascripts/extensions/custom_event.js index abedae4c1c7..abedae4c1c7 100644 --- a/app/assets/javascripts/extensions/custom_event.js.es6 +++ b/app/assets/javascripts/extensions/custom_event.js diff --git a/app/assets/javascripts/extensions/element.js.es6 b/app/assets/javascripts/extensions/element.js index 90ab79305a7..90ab79305a7 100644 --- a/app/assets/javascripts/extensions/element.js.es6 +++ b/app/assets/javascripts/extensions/element.js diff --git a/app/assets/javascripts/extensions/object.js.es6 b/app/assets/javascripts/extensions/object.js index 70a2d765abd..70a2d765abd 100644 --- a/app/assets/javascripts/extensions/object.js.es6 +++ b/app/assets/javascripts/extensions/object.js diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js new file mode 100644 index 00000000000..47a40e28461 --- /dev/null +++ b/app/assets/javascripts/filterable_list.js @@ -0,0 +1,45 @@ +/** + * Makes search request for content when user types a value in the search input. + * Updates the html content of the page with the received one. + */ +export default class FilterableList { + constructor(form, filter, holder) { + this.filterForm = form; + this.listFilterElement = filter; + this.listHolderElement = holder; + } + + initSearch() { + this.debounceFilter = _.debounce(this.filterResults.bind(this), 500); + + this.listFilterElement.removeEventListener('input', this.debounceFilter); + this.listFilterElement.addEventListener('input', this.debounceFilter); + } + + filterResults() { + const form = this.filterForm; + const filterUrl = `${form.getAttribute('action')}?${$(form).serialize()}`; + + $(this.listHolderElement).fadeTo(250, 0.5); + + return $.ajax({ + url: form.getAttribute('action'), + data: $(form).serialize(), + type: 'GET', + dataType: 'json', + context: this, + complete() { + $(this.listHolderElement).fadeTo(250, 1); + }, + success(data) { + this.listHolderElement.innerHTML = data.html; + + // Change url so if user reload a page - search results are saved + return window.history.replaceState({ + page: filterUrl, + + }, document.title, filterUrl); + }, + }); + } +} diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6 b/app/assets/javascripts/filtered_search/dropdown_hint.js index 9e92d544bef..9e92d544bef 100644 --- a/app/assets/javascripts/filtered_search/dropdown_hint.js.es6 +++ b/app/assets/javascripts/filtered_search/dropdown_hint.js diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_non_user.js index b3dc3e502c5..b3dc3e502c5 100644 --- a/app/assets/javascripts/filtered_search/dropdown_non_user.js.es6 +++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js.es6 b/app/assets/javascripts/filtered_search/dropdown_user.js index 7e9c6f74aa5..7e9c6f74aa5 100644 --- a/app/assets/javascripts/filtered_search/dropdown_user.js.es6 +++ b/app/assets/javascripts/filtered_search/dropdown_user.js diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6 b/app/assets/javascripts/filtered_search/dropdown_utils.js index de3fa116717..de3fa116717 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js.es6 +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js index dd565da507e..dd565da507e 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js index cecd3518ce3..cecd3518ce3 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_manager.js index bbafead0305..bbafead0305 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js index e6b53cd4b55..e6b53cd4b55 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js diff --git a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js index 9bf1b1ced88..9bf1b1ced88 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js.es6 +++ b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js diff --git a/app/assets/javascripts/gfm_auto_complete.js.es6 b/app/assets/javascripts/gfm_auto_complete.js index 60d6658dc16..60d6658dc16 100644 --- a/app/assets/javascripts/gfm_auto_complete.js.es6 +++ b/app/assets/javascripts/gfm_auto_complete.js diff --git a/app/assets/javascripts/gl_field_error.js.es6 b/app/assets/javascripts/gl_field_error.js index f7cbecc0385..f7cbecc0385 100644 --- a/app/assets/javascripts/gl_field_error.js.es6 +++ b/app/assets/javascripts/gl_field_error.js diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js index e9add115429..e9add115429 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js diff --git a/app/assets/javascripts/gl_form.js.es6 b/app/assets/javascripts/gl_form.js index 0b446ff364a..0b446ff364a 100644 --- a/app/assets/javascripts/gl_form.js.es6 +++ b/app/assets/javascripts/gl_form.js diff --git a/app/assets/javascripts/graphs/graphs_bundle.js b/app/assets/javascripts/graphs/graphs_bundle.js index ea5afbd9d29..a433c7ba8f0 100644 --- a/app/assets/javascripts/graphs/graphs_bundle.js +++ b/app/assets/javascripts/graphs/graphs_bundle.js @@ -1,4 +1,6 @@ +import Chart from 'vendor/Chart'; import ContributorsStatGraph from './stat_graph_contributors'; // export to global scope +window.Chart = Chart; window.ContributorsStatGraph = ContributorsStatGraph; diff --git a/app/assets/javascripts/group_label_subscription.js.es6 b/app/assets/javascripts/group_label_subscription.js index 15e695e81cf..15e695e81cf 100644 --- a/app/assets/javascripts/group_label_subscription.js.es6 +++ b/app/assets/javascripts/group_label_subscription.js diff --git a/app/assets/javascripts/groups_list.js b/app/assets/javascripts/groups_list.js index 0ef81e49444..56a8cbf6d03 100644 --- a/app/assets/javascripts/groups_list.js +++ b/app/assets/javascripts/groups_list.js @@ -1,47 +1,18 @@ +import FilterableList from './filterable_list'; + /** - * Based on project list search. * Makes search request for groups when user types a value in the search input. * Updates the html content of the page with the received one. */ export default class GroupsList { constructor() { - this.groupsListFilterElement = document.querySelector('.js-groups-list-filter'); - this.groupsListHolderElement = document.querySelector('.js-groups-list-holder'); - - this.initSearch(); - } - - initSearch() { - this.debounceFilter = _.debounce(this.filterResults.bind(this), 500); - - this.groupsListFilterElement.removeEventListener('input', this.debounceFilter); - this.groupsListFilterElement.addEventListener('input', this.debounceFilter); - } - - filterResults() { const form = document.querySelector('form#group-filter-form'); - const groupFilterUrl = `${form.getAttribute('action')}?${$(form).serialize()}`; - - $(this.groupsListHolderElement).fadeTo(250, 0.5); - - return $.ajax({ - url: form.getAttribute('action'), - data: $(form).serialize(), - type: 'GET', - dataType: 'json', - context: this, - complete() { - $(this.groupsListHolderElement).fadeTo(250, 1); - }, - success(data) { - this.groupsListHolderElement.innerHTML = data.html; - - // Change url so if user reload a page - search results are saved - return window.history.replaceState({ - page: groupFilterUrl, + const filter = document.querySelector('.js-groups-list-filter'); + const holder = document.querySelector('.js-groups-list-holder'); - }, document.title, groupFilterUrl); - }, - }); + if (form && filter && holder) { + const list = new FilterableList(form, filter, holder); + list.initSearch(); + } } } diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js index 3bfce32768a..3bfce32768a 100644 --- a/app/assets/javascripts/issuable.js.es6 +++ b/app/assets/javascripts/issuable.js diff --git a/app/assets/javascripts/issuable/issuable_bundle.js.es6 b/app/assets/javascripts/issuable/issuable_bundle.js index e927cc0077c..e927cc0077c 100644 --- a/app/assets/javascripts/issuable/issuable_bundle.js.es6 +++ b/app/assets/javascripts/issuable/issuable_bundle.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js index 357b3487ca9..357b3487ca9 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/collapsed_state.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js index 750468c679b..750468c679b 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/comparison_pane.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js index 309e9f2f9ef..309e9f2f9ef 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/estimate_only_pane.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/help_state.js index d7ced6d7151..d7ced6d7151 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/help_state.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/help_state.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js index 1d2ca643b5b..1d2ca643b5b 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/no_tracking_pane.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js index ed283fec3c3..ed283fec3c3 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/spent_only_pane.js diff --git a/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6 b/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js index 1fae2d62b14..1fae2d62b14 100644 --- a/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/components/time_tracker.js diff --git a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js index 958a0cc6d50..0134b7cb6f3 100644 --- a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js @@ -1,5 +1,7 @@ /* global Vue */ +window.Vue = require('vue'); +window.Vue.use(require('vue-resource')); require('./components/time_tracker'); require('../../smart_interval'); require('../../subbable_resource'); diff --git a/app/assets/javascripts/issues_bulk_assignment.js.es6 b/app/assets/javascripts/issues_bulk_assignment.js index e0ebd36a65c..e0ebd36a65c 100644 --- a/app/assets/javascripts/issues_bulk_assignment.js.es6 +++ b/app/assets/javascripts/issues_bulk_assignment.js diff --git a/app/assets/javascripts/label_manager.js.es6 b/app/assets/javascripts/label_manager.js index 38b2eb9ff14..38b2eb9ff14 100644 --- a/app/assets/javascripts/label_manager.js.es6 +++ b/app/assets/javascripts/label_manager.js diff --git a/app/assets/javascripts/lib/chart.js b/app/assets/javascripts/lib/chart.js deleted file mode 100644 index 9b011d89e93..00000000000 --- a/app/assets/javascripts/lib/chart.js +++ /dev/null @@ -1,3 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren */ - -window.Chart = require('vendor/Chart'); diff --git a/app/assets/javascripts/lib/cropper.js b/app/assets/javascripts/lib/cropper.js deleted file mode 100644 index 7862c6797c3..00000000000 --- a/app/assets/javascripts/lib/cropper.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren */ - -/*= require cropper */ - -(function() { - -}).call(window); diff --git a/app/assets/javascripts/lib/d3.js b/app/assets/javascripts/lib/d3.js deleted file mode 100644 index a9dd32edbed..00000000000 --- a/app/assets/javascripts/lib/d3.js +++ /dev/null @@ -1,3 +0,0 @@ -/* eslint-disable func-names, space-before-function-paren */ - -window.d3 = require('d3'); diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6 b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js index 2955bda1a36..2955bda1a36 100644 --- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js.es6 +++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js diff --git a/app/assets/javascripts/lib/utils/common_utils.js.es6 b/app/assets/javascripts/lib/utils/common_utils.js index a1423b6fda5..a1423b6fda5 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js.es6 +++ b/app/assets/javascripts/lib/utils/common_utils.js diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js.es6 b/app/assets/javascripts/lib/utils/datetime_utility.js index 82dcbdc26c8..82dcbdc26c8 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js.es6 +++ b/app/assets/javascripts/lib/utils/datetime_utility.js diff --git a/app/assets/javascripts/lib/utils/pretty_time.js.es6 b/app/assets/javascripts/lib/utils/pretty_time.js index ae397212e55..ae397212e55 100644 --- a/app/assets/javascripts/lib/utils/pretty_time.js.es6 +++ b/app/assets/javascripts/lib/utils/pretty_time.js diff --git a/app/assets/javascripts/lib/utils/url_utility.js.es6 b/app/assets/javascripts/lib/utils/url_utility.js index 1bc81d2e4a4..1bc81d2e4a4 100644 --- a/app/assets/javascripts/lib/utils/url_utility.js.es6 +++ b/app/assets/javascripts/lib/utils/url_utility.js diff --git a/app/assets/javascripts/lib/vue_resource.js.es6 b/app/assets/javascripts/lib/vue_resource.js.es6 deleted file mode 100644 index 49babdea2e1..00000000000 --- a/app/assets/javascripts/lib/vue_resource.js.es6 +++ /dev/null @@ -1,2 +0,0 @@ -window.Vue = require('vue'); -window.Vue.use(require('vue-resource')); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/main.js index 4c24d35b5bb..798553c16ac 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/main.js @@ -6,35 +6,34 @@ /* global AwardsHandler */ /* global Aside */ -window.$ = window.jQuery = require('jquery'); -require('jquery-ujs'); -require('vendor/jquery.endless-scroll'); -require('vendor/jquery.waitforimages'); -require('vendor/jquery.caret'); -require('vendor/jquery.atwho'); -require('vendor/jquery.scrollTo'); -window.Cookies = require('js-cookie'); -require('./autosave'); -require('bootstrap/js/affix'); -require('bootstrap/js/alert'); -require('bootstrap/js/dropdown'); -require('bootstrap/js/modal'); -require('bootstrap/js/tab'); -require('bootstrap/js/transition'); -require('bootstrap/js/tooltip'); -require('select2/select2.js'); -window.Pikaday = require('pikaday'); -window._ = require('underscore'); -window.Dropzone = require('dropzone'); -window.Sortable = require('vendor/Sortable'); +import jQuery from 'jquery'; +import _ from 'underscore'; +import Cookies from 'js-cookie'; +import Pikaday from 'pikaday'; +import Dropzone from 'dropzone'; +import Sortable from 'vendor/Sortable'; + +// libraries with import side-effects require('mousetrap'); require('mousetrap/plugins/pause/mousetrap-pause'); +require('vendor/fuzzaldrin-plus'); +require('es6-promise').polyfill(); + +// expose common libraries as globals (TODO: remove these) +window.jQuery = jQuery; +window.$ = jQuery; +window._ = _; +window.Cookies = Cookies; +window.Pikaday = Pikaday; +window.Dropzone = Dropzone; +window.Sortable = Sortable; + +// shortcuts require('./shortcuts'); require('./shortcuts_navigation'); require('./shortcuts_dashboard_navigation'); require('./shortcuts_issuable'); require('./shortcuts_network'); -require('vendor/jquery.nicescroll'); // behaviors require('./behaviors/autosize'); @@ -205,9 +204,6 @@ require('./visibility_select'); require('./wikis'); require('./zen_mode'); -require('vendor/fuzzaldrin-plus'); -require('es6-promise').polyfill(); - (function () { document.addEventListener('beforeunload', function () { // Unbind scroll events @@ -285,7 +281,7 @@ require('es6-promise').polyfill(); $.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover'; $body.tooltip({ selector: '.has-tooltip, [data-toggle="tooltip"]', - placement: function (_, el) { + placement: function (tip, el) { return $(el).data('placement') || 'bottom'; } }); diff --git a/app/assets/javascripts/member_expiration_date.js.es6 b/app/assets/javascripts/member_expiration_date.js index 129d2dc5f0a..129d2dc5f0a 100644 --- a/app/assets/javascripts/member_expiration_date.js.es6 +++ b/app/assets/javascripts/member_expiration_date.js diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js index e3f367a11eb..e3f367a11eb 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js index c7e78fed8fe..c7e78fed8fe 100644 --- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js diff --git a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js index 240c8f98932..240c8f98932 100644 --- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js index 97753c50b60..97753c50b60 100644 --- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js.es6 +++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js index c012b77e0bf..c012b77e0bf 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js index 74587df22c5..74587df22c5 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js index 653e52fb6bf..653e52fb6bf 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js.es6 +++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js index 53e000d7e9e..53e000d7e9e 100644 --- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js.es6 +++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js index 0f475f62ee6..0f475f62ee6 100644 --- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js.es6 +++ b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_utils.js diff --git a/app/assets/javascripts/merge_request_tabs.js.es6 b/app/assets/javascripts/merge_request_tabs.js index 190336dbd20..190336dbd20 100644 --- a/app/assets/javascripts/merge_request_tabs.js.es6 +++ b/app/assets/javascripts/merge_request_tabs.js diff --git a/app/assets/javascripts/merge_request_widget.js.es6 b/app/assets/javascripts/merge_request_widget.js index 00c6c050612..5f1bd474a0c 100644 --- a/app/assets/javascripts/merge_request_widget.js.es6 +++ b/app/assets/javascripts/merge_request_widget.js @@ -129,8 +129,9 @@ require('./smart_interval'); }; MergeRequestWidget.prototype.getMergeStatus = function() { - return $.get(this.opts.merge_check_url, function(data) { + return $.get(this.opts.merge_check_url, (data) => { var $html = $(data); + this.updateMergeButton(this.status, this.hasCi, $html); $('.mr-widget-body').replaceWith($html.find('.mr-widget-body')); $('.mr-widget-footer').replaceWith($html.find('.mr-widget-footer')); }); @@ -154,9 +155,9 @@ require('./smart_interval'); return $.getJSON(this.opts.ci_status_url, (function(_this) { return function(data) { var message, status, title; - if (!data.status) { - return; - } + _this.status = data.status; + _this.hasCi = data.has_ci; + _this.updateMergeButton(_this.status, _this.hasCi); if (data.environments && data.environments.length) _this.renderEnvironments(data.environments); if (data.status !== _this.opts.ci_status || data.sha !== _this.opts.ci_sha || @@ -232,36 +233,45 @@ require('./smart_interval'); return; } $('.ci_widget').hide(); - allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"]; - if (indexOf.call(allowed_states, state) !== -1) { - $('.ci_widget.ci-' + state).show(); + $('.ci_widget.ci-' + state).show(); + + this.initMiniPipelineGraph(); + }; + + MergeRequestWidget.prototype.showCICoverage = function(coverage) { + var text = `Coverage ${coverage}%`; + return $('.ci_widget:visible .ci-coverage').text(text); + }; + + MergeRequestWidget.prototype.updateMergeButton = function(state, hasCi, $html) { + const allowed_states = ["failed", "canceled", "running", "pending", "success", "success_with_warnings", "skipped", "not_found"]; + let stateClass = 'btn-danger'; + if (!hasCi) { + stateClass = 'btn-create'; + } else if (indexOf.call(allowed_states, state) !== -1) { switch (state) { case "failed": case "canceled": case "not_found": - this.setMergeButtonClass('btn-danger'); + stateClass = 'btn-danger'; break; case "running": - this.setMergeButtonClass('btn-info'); + stateClass = 'btn-info'; break; case "success": case "success_with_warnings": - this.setMergeButtonClass('btn-create'); + stateClass = 'btn-create'; } } else { $('.ci_widget.ci-error').show(); - this.setMergeButtonClass('btn-danger'); + stateClass = 'btn-danger'; } - }; - MergeRequestWidget.prototype.showCICoverage = function(coverage) { - var text; - text = 'Coverage ' + coverage + '%'; - return $('.ci_widget:visible .ci-coverage').text(text); + this.setMergeButtonClass(stateClass, $html); }; - MergeRequestWidget.prototype.setMergeButtonClass = function(css_class) { - return $('.js-merge-button,.accept-action .dropdown-toggle').removeClass('btn-danger btn-info btn-create').addClass(css_class); + MergeRequestWidget.prototype.setMergeButtonClass = function(css_class, $html = $('.mr-state-widget')) { + return $html.find('.js-merge-button').removeClass('btn-danger btn-info btn-create').addClass(css_class); }; MergeRequestWidget.prototype.updatePipelineUrls = function(id) { diff --git a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 b/app/assets/javascripts/merge_request_widget/ci_bundle.js index 547dfa9e677..21d7c3e168e 100644 --- a/app/assets/javascripts/merge_request_widget/ci_bundle.js.es6 +++ b/app/assets/javascripts/merge_request_widget/ci_bundle.js @@ -15,14 +15,14 @@ }); $(document) - .off('click', '.accept_merge_request') - .on('click', '.accept_merge_request', () => { - $('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress'); + .off('click', '.accept-merge-request') + .on('click', '.accept-merge-request', () => { + $('.js-merge-button, .js-merge-when-pipeline-succeeds-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress'); }); $(document) - .off('click', '.merge_when_pipeline_succeeds') - .on('click', '.merge_when_pipeline_succeeds', () => { + .off('click', '.merge-when-pipeline-succeeds') + .on('click', '.merge-when-pipeline-succeeds', () => { $('#merge_when_pipeline_succeeds').val('1'); }); diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 b/app/assets/javascripts/mini_pipeline_graph_dropdown.js index 2145e531331..2145e531331 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6 +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 47fa0f2eb96..df7a7d2a459 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -198,7 +198,7 @@ require('./task_list'); this.refreshing = true; return $.ajax({ url: this.notes_url, - data: "last_fetched_at=" + this.last_fetched_at, + headers: { "X-Last-Fetched-At": this.last_fetched_at }, dataType: "json", success: (function(_this) { return function(data) { diff --git a/app/assets/javascripts/pager.js.es6 b/app/assets/javascripts/pager.js index e35cf6d295e..e35cf6d295e 100644 --- a/app/assets/javascripts/pager.js.es6 +++ b/app/assets/javascripts/pager.js diff --git a/app/assets/javascripts/pipelines.js.es6 b/app/assets/javascripts/pipelines.js index 9203abefbbc..9203abefbbc 100644 --- a/app/assets/javascripts/pipelines.js.es6 +++ b/app/assets/javascripts/pipelines.js diff --git a/app/assets/javascripts/profile/gl_crop.js.es6 b/app/assets/javascripts/profile/gl_crop.js index 192b1192d07..cf1566eeb87 100644 --- a/app/assets/javascripts/profile/gl_crop.js.es6 +++ b/app/assets/javascripts/profile/gl_crop.js @@ -1,5 +1,7 @@ /* eslint-disable no-useless-escape, max-len, quotes, no-var, no-underscore-dangle, func-names, space-before-function-paren, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, new-parens */ +import 'vendor/cropper'; + ((global) => { // Matches everything but the file name const FILENAMEREGEX = /^.*[\\\/]/; diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js index 4ccea0624ee..4ccea0624ee 100644 --- a/app/assets/javascripts/profile/profile.js.es6 +++ b/app/assets/javascripts/profile/profile.js diff --git a/app/assets/javascripts/project_label_subscription.js.es6 b/app/assets/javascripts/project_label_subscription.js index 0a811627600..0a811627600 100644 --- a/app/assets/javascripts/project_label_subscription.js.es6 +++ b/app/assets/javascripts/project_label_subscription.js diff --git a/app/assets/javascripts/project_variables.js.es6 b/app/assets/javascripts/project_variables.js index 4ee2e49306d..4ee2e49306d 100644 --- a/app/assets/javascripts/project_variables.js.es6 +++ b/app/assets/javascripts/project_variables.js diff --git a/app/assets/javascripts/projects_list.js b/app/assets/javascripts/projects_list.js index acdf9b7eb5a..c67d59d2be5 100644 --- a/app/assets/javascripts/projects_list.js +++ b/app/assets/javascripts/projects_list.js @@ -1,50 +1,18 @@ -/* eslint-disable func-names, space-before-function-paren, object-shorthand, quotes, no-var, one-var, one-var-declaration-per-line, prefer-arrow-callback, consistent-return, no-unused-vars, camelcase, prefer-template, comma-dangle, max-len */ +import FilterableList from './filterable_list'; -(function() { - window.ProjectsList = { - init: function() { - $(".projects-list-filter").off('keyup'); - this.initSearch(); - return this.initPagination(); - }, - initSearch: function() { - var debounceFilter, projectsListFilter; - projectsListFilter = $('.projects-list-filter'); - debounceFilter = _.debounce(window.ProjectsList.filterResults, 500); - return projectsListFilter.on('keyup', function(e) { - if (projectsListFilter.val() !== '') { - return debounceFilter(); - } - }); - }, - filterResults: function() { - var form, project_filter_url, search; - $('.projects-list-holder').fadeTo(250, 0.5); - form = null; - form = $("form#project-filter-form"); - search = $(".projects-list-filter").val(); - project_filter_url = form.attr('action') + '?' + form.serialize(); - return $.ajax({ - type: "GET", - url: form.attr('action'), - data: form.serialize(), - complete: function() { - return $('.projects-list-holder').fadeTo(250, 1); - }, - success: function(data) { - $('.projects-list-holder').replaceWith(data.html); - return history.replaceState({ - page: project_filter_url - // Change url so if user reload a page - search results are saved - }, document.title, project_filter_url); - }, - dataType: "json" - }); - }, - initPagination: function() { - return $('.projects-list-holder .pagination').on('ajax:success', function(e, data) { - return $('.projects-list-holder').replaceWith(data.html); - }); +/** + * Makes search request for projects when user types a value in the search input. + * Updates the html content of the page with the received one. + */ +export default class ProjectsList { + constructor() { + const form = document.querySelector('form#project-filter-form'); + const filter = document.querySelector('.js-projects-list-filter'); + const holder = document.querySelector('.js-projects-list-holder'); + + if (form && filter && holder) { + const list = new FilterableList(form, filter, holder); + list.initSearch(); } - }; -}).call(window); + } +} diff --git a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js index e7fff57ff45..e7fff57ff45 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_create.js index 57ea2f52814..57ea2f52814 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_create.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_create.js diff --git a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js index 5cf28aa7a73..5cf28aa7a73 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_dropdown.js diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit.js index 6ef59e94384..6ef59e94384 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_edit.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js index 336fa6c57a7..336fa6c57a7 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_edit_list.js.es6 +++ b/app/assets/javascripts/protected_branches/protected_branch_edit_list.js diff --git a/app/assets/javascripts/search_autocomplete.js.es6 b/app/assets/javascripts/search_autocomplete.js index 6fd5345a0a6..6fd5345a0a6 100644 --- a/app/assets/javascripts/search_autocomplete.js.es6 +++ b/app/assets/javascripts/search_autocomplete.js diff --git a/app/assets/javascripts/shortcuts_blob.js.es6 b/app/assets/javascripts/shortcuts_blob.js index bfe90aef71e..bfe90aef71e 100644 --- a/app/assets/javascripts/shortcuts_blob.js.es6 +++ b/app/assets/javascripts/shortcuts_blob.js diff --git a/app/assets/javascripts/signin_tabs_memoizer.js.es6 b/app/assets/javascripts/signin_tabs_memoizer.js index d811d1cd53a..d811d1cd53a 100644 --- a/app/assets/javascripts/signin_tabs_memoizer.js.es6 +++ b/app/assets/javascripts/signin_tabs_memoizer.js diff --git a/app/assets/javascripts/smart_interval.js.es6 b/app/assets/javascripts/smart_interval.js index d1bdc353be2..d1bdc353be2 100644 --- a/app/assets/javascripts/smart_interval.js.es6 +++ b/app/assets/javascripts/smart_interval.js diff --git a/app/assets/javascripts/snippets_list.js.es6 b/app/assets/javascripts/snippets_list.js index 2128007113f..2128007113f 100644 --- a/app/assets/javascripts/snippets_list.js.es6 +++ b/app/assets/javascripts/snippets_list.js diff --git a/app/assets/javascripts/subbable_resource.js.es6 b/app/assets/javascripts/subbable_resource.js index d8191605128..d8191605128 100644 --- a/app/assets/javascripts/subbable_resource.js.es6 +++ b/app/assets/javascripts/subbable_resource.js diff --git a/app/assets/javascripts/subscription.js.es6 b/app/assets/javascripts/subscription.js index 62d1604fe9e..62d1604fe9e 100644 --- a/app/assets/javascripts/subscription.js.es6 +++ b/app/assets/javascripts/subscription.js diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js index e9e9aafd71a..e9e9aafd71a 100644 --- a/app/assets/javascripts/templates/issuable_template_selector.js.es6 +++ b/app/assets/javascripts/templates/issuable_template_selector.js diff --git a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 b/app/assets/javascripts/templates/issuable_template_selectors.js index 97f6d37364d..97f6d37364d 100644 --- a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 +++ b/app/assets/javascripts/templates/issuable_template_selectors.js diff --git a/app/assets/javascripts/terminal/terminal.js.es6 b/app/assets/javascripts/terminal/terminal.js index 6b9422b1816..6b9422b1816 100644 --- a/app/assets/javascripts/terminal/terminal.js.es6 +++ b/app/assets/javascripts/terminal/terminal.js diff --git a/app/assets/javascripts/terminal/terminal_bundle.js.es6 b/app/assets/javascripts/terminal/terminal_bundle.js index 13cf3a10a38..13cf3a10a38 100644 --- a/app/assets/javascripts/terminal/terminal_bundle.js.es6 +++ b/app/assets/javascripts/terminal/terminal_bundle.js diff --git a/app/assets/javascripts/todos.js.es6 b/app/assets/javascripts/todos.js index e9513725d9d..e9513725d9d 100644 --- a/app/assets/javascripts/todos.js.es6 +++ b/app/assets/javascripts/todos.js diff --git a/app/assets/javascripts/u2f/authenticate.js.es6 b/app/assets/javascripts/u2f/authenticate.js index 500b78fc5d8..500b78fc5d8 100644 --- a/app/assets/javascripts/u2f/authenticate.js.es6 +++ b/app/assets/javascripts/u2f/authenticate.js diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js index 059e6c628b3..059e6c628b3 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js index 465618e3d53..465618e3d53 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js index 137cefa3b8e..137cefa3b8e 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js index 5111b260e1c..754d448564f 100644 --- a/app/assets/javascripts/users/calendar.js +++ b/app/assets/javascripts/users/calendar.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, camelcase, vars-on-top, object-shorthand, comma-dangle, eqeqeq, no-mixed-operators, no-return-assign, newline-per-chained-call, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, no-else-return, max-len */ -/* global d3 */ + +import d3 from 'd3'; (function() { var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }; diff --git a/app/assets/javascripts/version_check_image.js.es6 b/app/assets/javascripts/version_check_image.js index d4f716acb72..d4f716acb72 100644 --- a/app/assets/javascripts/version_check_image.js.es6 +++ b/app/assets/javascripts/version_check_image.js diff --git a/app/assets/javascripts/visibility_select.js.es6 b/app/assets/javascripts/visibility_select.js index f712d7ba930..f712d7ba930 100644 --- a/app/assets/javascripts/visibility_select.js.es6 +++ b/app/assets/javascripts/visibility_select.js diff --git a/app/assets/javascripts/vue_pipelines_index/index.js.es6 b/app/assets/javascripts/vue_pipelines_index/index.js index a90bd1518e9..a90bd1518e9 100644 --- a/app/assets/javascripts/vue_pipelines_index/index.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/index.js diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js index 891f1f17fb3..891f1f17fb3 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js index ae5649f0519..ae5649f0519 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipeline_url.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipeline_url.js diff --git a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipelines.js index 601ef41e917..601ef41e917 100644 --- a/app/assets/javascripts/vue_pipelines_index/pipelines.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/pipelines.js diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js index f67ebd6a265..f67ebd6a265 100644 --- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/stage.js diff --git a/app/assets/javascripts/vue_pipelines_index/status.js.es6 b/app/assets/javascripts/vue_pipelines_index/status.js index 8d9f83ac113..8d9f83ac113 100644 --- a/app/assets/javascripts/vue_pipelines_index/status.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/status.js diff --git a/app/assets/javascripts/vue_pipelines_index/store.js.es6 b/app/assets/javascripts/vue_pipelines_index/store.js index 909007267b9..909007267b9 100644 --- a/app/assets/javascripts/vue_pipelines_index/store.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/store.js diff --git a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 b/app/assets/javascripts/vue_pipelines_index/time_ago.js index a383570857d..a383570857d 100644 --- a/app/assets/javascripts/vue_pipelines_index/time_ago.js.es6 +++ b/app/assets/javascripts/vue_pipelines_index/time_ago.js diff --git a/app/assets/javascripts/vue_realtime_listener/index.js.es6 b/app/assets/javascripts/vue_realtime_listener/index.js index 30f6680a673..30f6680a673 100644 --- a/app/assets/javascripts/vue_realtime_listener/index.js.es6 +++ b/app/assets/javascripts/vue_realtime_listener/index.js diff --git a/app/assets/javascripts/vue_shared/components/commit.js.es6 b/app/assets/javascripts/vue_shared/components/commit.js index 4381487b79e..4381487b79e 100644 --- a/app/assets/javascripts/vue_shared/components/commit.js.es6 +++ b/app/assets/javascripts/vue_shared/components/commit.js diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table.js.es6 b/app/assets/javascripts/vue_shared/components/pipelines_table.js index 0d8f85db965..0d8f85db965 100644 --- a/app/assets/javascripts/vue_shared/components/pipelines_table.js.es6 +++ b/app/assets/javascripts/vue_shared/components/pipelines_table.js diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6 b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js index e5e88186a85..e5e88186a85 100644 --- a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js.es6 +++ b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.js.es6 b/app/assets/javascripts/vue_shared/components/table_pagination.js index 8943b850a72..8943b850a72 100644 --- a/app/assets/javascripts/vue_shared/components/table_pagination.js.es6 +++ b/app/assets/javascripts/vue_shared/components/table_pagination.js diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6 b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js index d3229f9f730..d3229f9f730 100644 --- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js.es6 +++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js diff --git a/app/assets/javascripts/wikis.js.es6 b/app/assets/javascripts/wikis.js index 75fd1394a03..75fd1394a03 100644 --- a/app/assets/javascripts/wikis.js.es6 +++ b/app/assets/javascripts/wikis.js diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 685a4847731..f4316ec7022 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -149,14 +149,14 @@ header { .header-logo { display: inline-block; - margin: 0 8px 0 3px; + margin: 0 7px 0 2px; position: relative; - top: 7px; + top: 10px; transition-duration: .3s; svg, img { - height: 36px; + height: 28px; } &:hover { diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index 29d55c44699..0a42b17c1f5 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -8,6 +8,19 @@ body { &.navless { background-color: $white-light !important; } + + &.card-content { + background-color: $gray-darker; + + .content-wrapper { + padding: 0; + + .container-fluid, + .container-limited { + background-color: $gray-darker; + } + } + } } .container { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 0b0c4bc130d..a629a5333d7 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -29,7 +29,7 @@ background-color: $gl-success; } - .accept_merge_request { + .accept-merge-request { &.ci-pending, &.ci-running { @include btn-blue; @@ -42,6 +42,12 @@ @include btn-red; } } + + .dropdown-toggle { + .fa { + color: inherit; + } + } } .accept-control { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 88ea92c5afb..543d2ece3df 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -182,7 +182,8 @@ input[type="checkbox"]:hover { display: flex; } - .search-field-holder { + .search-field-holder, + .project-filter-form { -webkit-flex: 1 0 auto; flex: 1 0 auto; position: relative; @@ -201,7 +202,8 @@ input[type="checkbox"]:hover { pointer-events: none; } - .search-text-input { + .search-text-input, + .project-filter-form-field { padding-left: $gl-padding + 15px; padding-right: $gl-padding + 15px; } diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb index 241c7be0ea1..caf4c138da8 100644 --- a/app/controllers/admin/health_check_controller.rb +++ b/app/controllers/admin/health_check_controller.rb @@ -1,5 +1,5 @@ class Admin::HealthCheckController < Admin::ApplicationController def show - @errors = HealthCheck::Utils.process_checks('standard') + @errors = HealthCheck::Utils.process_checks(['standard']) end end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 39c8c6d8a0c..daecfc832bf 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -14,6 +14,15 @@ class Admin::ProjectsController < Admin::ApplicationController @projects = @projects.search(params[:name]) if params[:name].present? @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]) + + respond_to do |format| + format.html + format.json do + render json: { + html: view_to_html_string("admin/projects/_projects", locals: { projects: @projects }) + } + end + end end def show diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 32484f810da..cc7b7f247e8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -122,10 +122,6 @@ class ApplicationController < ActionController::Base headers['X-XSS-Protection'] = '1; mode=block' headers['X-UA-Compatible'] = 'IE=edge' headers['X-Content-Type-Options'] = 'nosniff' - # Enabling HSTS for non-standard ports would send clients to the wrong port - if Gitlab.config.gitlab.https && Gitlab.config.gitlab.port == 443 - headers['Strict-Transport-Security'] = 'max-age=31536000' - end end def validate_user_service_ticket! diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index f897f828cec..9ac8197e45a 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -4,10 +4,9 @@ module CreatesCommit def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil) set_commit_variables - start_branch = @mr_target_branch commit_params = @commit_params.merge( start_project: @mr_target_project, - start_branch: start_branch, + start_branch: @mr_target_branch, target_branch: @mr_source_branch ) @@ -17,12 +16,16 @@ module CreatesCommit if result[:status] == :success update_flash_notice(success_notice) + success_path = final_success_path(success_path) + respond_to do |format| - format.html { redirect_to final_success_path(success_path) } - format.json { render json: { message: "success", filePath: final_success_path(success_path) } } + format.html { redirect_to success_path } + format.json { render json: { message: "success", filePath: success_path } } end else flash[:alert] = result[:message] + failure_path = failure_path.call if failure_path.respond_to?(:call) + respond_to do |format| format.html do if failure_view @@ -58,9 +61,13 @@ module CreatesCommit end def final_success_path(success_path) - return success_path unless create_merge_request? + if create_merge_request? + merge_request_exists? ? existing_merge_request_path : new_merge_request_path + else + success_path = success_path.call if success_path.respond_to?(:call) - merge_request_exists? ? existing_merge_request_path : new_merge_request_path + success_path + end end def new_merge_request_path @@ -92,42 +99,26 @@ module CreatesCommit end def create_merge_request? - # XXX: Even if the field is set, if we're checking the same branch + # Even if the field is set, if we're checking the same branch # as the target branch in the same project, # we don't want to create a merge request. params[:create_merge_request].present? && - (different_project? || @ref != @target_branch) + (different_project? || @mr_target_branch != @mr_source_branch) end - # TODO: We should really clean this up def set_commit_variables - @mr_source_project = - if can?(current_user, :push_code, @project) - # Edit file in this project - @project - else - # Merge request from fork to this project - current_user.fork_of(@project) - end + if can?(current_user, :push_code, @project) + @mr_source_project = @project + @target_branch ||= @ref + else + @mr_source_project = current_user.fork_of(@project) + @target_branch ||= @mr_source_project.repository.next_branch('patch') + end # Merge request to this project @mr_target_project = @project - @mr_target_branch = @ref || @target_branch - - @mr_source_branch = guess_mr_source_branch - end + @mr_target_branch ||= @ref || @target_branch - def guess_mr_source_branch - # XXX: Happens when viewing a commit without a branch. In this case, - # @target_branch would be the default branch for @mr_source_project, - # however we want a generated new branch here. Thus we can't use - # @target_branch, but should pass nil to indicate that we want a new - # branch instead of @target_branch. - return if - create_merge_request? && - # XXX: Don't understand why rubocop prefers this indention - @mr_source_project.repository.branch_exists?(@target_branch) - - @target_branch + @mr_source_branch = @target_branch end end diff --git a/app/controllers/concerns/filter_projects.rb b/app/controllers/concerns/filter_projects.rb index 586f97c5eb4..6014112256a 100644 --- a/app/controllers/concerns/filter_projects.rb +++ b/app/controllers/concerns/filter_projects.rb @@ -8,7 +8,7 @@ module FilterProjects extend ActiveSupport::Concern def filter_projects(projects) - projects = projects.search(params[:filter_projects]) if params[:filter_projects].present? + projects = projects.search(params[:name]) if params[:name].present? projects = projects.non_archived if params[:archived].blank? projects = projects.personal(current_user) if params[:personal].present? && current_user diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 7ed54479599..15db5b7762d 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -108,7 +108,7 @@ class GroupsController < Groups::ApplicationController @projects = @projects.sorted_by_activity @projects = filter_projects(@projects) @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.page(params[:page]) if params[:filter_projects].blank? + @projects = @projects.page(params[:page]) if params[:name].blank? end def authorize_create_group! diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f0c71725ea8..987b95e89b9 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -47,11 +47,14 @@ class ProfilesController < Profiles::ApplicationController end def update_username - @user.update_attributes(username: user_params[:username]) - - respond_to do |format| - format.js + if @user.update_attributes(username: user_params[:username]) + options = { notice: "Username successfully changed" } + else + message = @user.errors.full_messages.uniq.join('. ') + options = { alert: "Username change failed - #{message}" } end + + redirect_back_or_default(default: { action: 'show' }, options: options) end private diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index f9a5ef46786..21ed0660762 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -24,7 +24,7 @@ class Projects::BlobController < Projects::ApplicationController def create create_commit(Files::CreateService, success_notice: "The file has been successfully created.", - success_path: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)), + success_path: -> { namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) }, failure_view: :new, failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref)) end @@ -40,7 +40,7 @@ class Projects::BlobController < Projects::ApplicationController def update @path = params[:file_path] if params[:file_path].present? - create_commit(Files::UpdateService, success_path: after_edit_path, + create_commit(Files::UpdateService, success_path: -> { after_edit_path }, failure_view: :edit, failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) @@ -62,7 +62,7 @@ class Projects::BlobController < Projects::ApplicationController def destroy create_commit(Files::DestroyService, success_notice: "The file has been successfully deleted.", - success_path: namespace_project_tree_path(@project.namespace, @project, @target_branch), + success_path: -> { namespace_project_tree_path(@project.namespace, @project, @target_branch) }, failure_view: :show, failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index a01c0caa959..c40f9b7f75f 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -20,7 +20,7 @@ class Projects::BranchesController < Projects::ApplicationController respond_to do |format| format.html format.json do - render json: @repository.branch_names + render json: @branches.map(&:name) end end end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index e10d7992db7..cc67f688d51 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -51,23 +51,35 @@ class Projects::CommitController < Projects::ApplicationController def revert assign_change_commit_vars - return render_404 if @target_branch.blank? + return render_404 if @start_branch.blank? + + @target_branch = create_new_branch? ? @commit.revert_branch_name : @start_branch + + @mr_target_branch = @start_branch create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully reverted.", - success_path: successful_change_path, failure_path: failed_change_path) + success_path: -> { successful_change_path }, failure_path: failed_change_path) end def cherry_pick assign_change_commit_vars - return render_404 if @target_branch.blank? + return render_404 if @start_branch.blank? + + @target_branch = create_new_branch? ? @commit.cherry_pick_branch_name : @start_branch + + @mr_target_branch = @start_branch create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully cherry-picked.", - success_path: successful_change_path, failure_path: failed_change_path) + success_path: -> { successful_change_path }, failure_path: failed_change_path) end private + def create_new_branch? + params[:create_merge_request].present? || !can?(current_user, :push_code, @project) + end + def successful_change_path referenced_merge_request_url || namespace_project_commits_url(@project.namespace, @project, @target_branch) end @@ -78,7 +90,7 @@ class Projects::CommitController < Projects::ApplicationController def referenced_merge_request_url if merge_request = @commit.merged_merge_request(current_user) - namespace_project_merge_request_url(@project.namespace, @project, merge_request) + namespace_project_merge_request_url(merge_request.target_project.namespace, merge_request.target_project, merge_request) end end @@ -94,7 +106,7 @@ class Projects::CommitController < Projects::ApplicationController @diffs = commit.diffs(opts) @notes_count = commit.notes.count - + @environment = EnvironmentsFinder.new(@project, current_user, commit: @commit).execute.last end @@ -118,11 +130,7 @@ class Projects::CommitController < Projects::ApplicationController end def assign_change_commit_vars - @commit = project.commit(params[:id]) - @target_branch = params[:target_branch] - @commit_params = { - commit: @commit, - create_merge_request: params[:create_merge_request].present? || different_project? - } + @start_branch = params[:start_branch] + @commit_params = { commit: @commit } end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 76519022381..82f9b6e06db 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -324,6 +324,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def merge_check @merge_request.check_if_can_be_merged + @pipelines = @merge_request.all_pipelines render partial: "projects/merge_requests/widget/show.html.haml", layout: false end @@ -446,6 +447,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def ci_status pipeline = @merge_request.head_pipeline + @pipelines = @merge_request.all_pipelines if pipeline status = pipeline.status @@ -464,7 +466,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController sha: (merge_request.diff_head_commit.short_id if merge_request.diff_head_sha), status: status, coverage: coverage, - pipeline: pipeline.try(:id) + pipeline: pipeline.try(:id), + has_ci: @merge_request.has_ci? } render json: response diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 5cf3a7f593b..d00177e7612 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -211,6 +211,11 @@ class Projects::NotesController < Projects::ApplicationController end def find_current_user_notes - @notes = NotesFinder.new(project, current_user, params).execute.inc_author + @notes = NotesFinder.new(project, current_user, params.merge(last_fetched_at: last_fetched_at)) + .execute.inc_author + end + + def last_fetched_at + request.headers['X-Last-Fetched-At'] end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 70419eb4bde..a3213581498 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -167,7 +167,7 @@ module ApplicationHelper css_classes = short_format ? 'js-short-timeago' : 'js-timeago' css_classes << " #{html_class}" unless html_class.blank? - element = content_tag :time, time.to_s, + element = content_tag :time, time.strftime("%b %d, %Y"), class: css_classes, title: time.to_time.in_time_zone.to_s(:medium), datetime: time.to_time.getutc.iso8601, diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index bbcb52f7eaf..7bd212a3ef9 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -1,14 +1,19 @@ module ExploreHelper def filter_projects_path(options = {}) exist_opts = { - sort: params[:sort], + sort: params[:sort] || @sort, scope: params[:scope], group: params[:group], tag: params[:tag], visibility_level: params[:visibility_level], + name: params[:name], + personal: params[:personal], + archived: params[:archived], + shared: params[:shared], + namespace_id: params[:namespace_id], } - options = exist_opts.merge(options) + options = exist_opts.merge(options).delete_if { |key, value| value.blank? } request_path_with_options(options) end diff --git a/app/helpers/mattermost_helper.rb b/app/helpers/mattermost_helper.rb index 49ac12db832..27ff4051c8d 100644 --- a/app/helpers/mattermost_helper.rb +++ b/app/helpers/mattermost_helper.rb @@ -1,9 +1,7 @@ module MattermostHelper def mattermost_teams_options(teams) - teams_options = teams.map do |id, options| - [options['display_name'] || options['name'], id] + teams.map do |team| + [team['display_name'] || team['name'], team['id']] end - - teams_options.compact.unshift(['Select team...', '0']) end end diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb index c3a08d76318..74cccb23956 100644 --- a/app/helpers/preferences_helper.rb +++ b/app/helpers/preferences_helper.rb @@ -35,9 +35,9 @@ module PreferencesHelper def project_view_choices [ - ['Readme (default)', :readme], + ['Readme', :readme], ['Activity view', :activity], - ['Files view', :files] + ['Files and Readme (default)', :files] ] end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 81bde54d5dc..0f7b8311588 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -684,7 +684,10 @@ class MergeRequest < ActiveRecord::Base end def has_ci? - source_project.try(:ci_service) && commits.any? + has_ci_integration = source_project.try(:ci_service) + uses_gitlab_ci = all_pipelines.any? + + (has_ci_integration || uses_gitlab_ci) && commits.any? end def branch_missing? diff --git a/app/models/note.rb b/app/models/note.rb index 4c97e4a986c..e22e96aec6f 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -85,6 +85,7 @@ class Note < ActiveRecord::Base before_validation :nullify_blank_type, :nullify_blank_line_code before_validation :set_discussion_id after_save :keep_around_commit, unless: :for_personal_snippet? + after_save :expire_etag_cache class << self def model_name @@ -272,4 +273,16 @@ class Note < ActiveRecord::Base self.class.build_discussion_id(noteable_type, noteable_id || commit_id) end end + + def expire_etag_cache + return unless for_issue? + + key = Gitlab::Routing.url_helpers.namespace_project_noteable_notes_path( + noteable.project.namespace, + noteable.project, + target_type: noteable_type.underscore, + target_id: noteable.id + ) + Gitlab::EtagCaching::Store.new.touch(key) + end end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index 9819e723fe8..f2e1c906dac 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -94,7 +94,12 @@ class KubernetesService < DeploymentService { key: 'KUBE_TOKEN', value: token, public: false }, { key: 'KUBE_NAMESPACE', value: namespace, public: true } ] - variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } if ca_pem.present? + + if ca_pem.present? + variables << { key: 'KUBE_CA_PEM', value: ca_pem, public: true } + variables << { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true } + end + variables end diff --git a/app/models/repository.rb b/app/models/repository.rb index d410d60dbad..e7cc8d6e083 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -6,6 +6,7 @@ class Repository attr_accessor :path_with_namespace, :project CommitError = Class.new(StandardError) + CreateTreeError = Class.new(StandardError) # Methods that cache data from the Git repository. # @@ -862,17 +863,18 @@ class Repository end def revert( - user, commit, branch_name, revert_tree_id = nil, + user, commit, branch_name, start_branch_name: nil, start_project: project) - revert_tree_id ||= check_revert_content(commit, branch_name) - - return false unless revert_tree_id - GitOperationService.new(user, self).with_branch( branch_name, start_branch_name: start_branch_name, start_project: start_project) do |start_commit| + revert_tree_id = check_revert_content(commit, start_commit.sha) + unless revert_tree_id + raise Repository::CreateTreeError.new('Failed to revert commit') + end + committer = user_to_committer(user) Rugged::Commit.create(rugged, @@ -885,17 +887,18 @@ class Repository end def cherry_pick( - user, commit, branch_name, cherry_pick_tree_id = nil, + user, commit, branch_name, start_branch_name: nil, start_project: project) - cherry_pick_tree_id ||= check_cherry_pick_content(commit, branch_name) - - return false unless cherry_pick_tree_id - GitOperationService.new(user, self).with_branch( branch_name, start_branch_name: start_branch_name, start_project: start_project) do |start_commit| + cherry_pick_tree_id = check_cherry_pick_content(commit, start_commit.sha) + unless cherry_pick_tree_id + raise Repository::CreateTreeError.new('Failed to cherry-pick commit') + end + committer = user_to_committer(user) Rugged::Commit.create(rugged, @@ -919,9 +922,8 @@ class Repository end end - def check_revert_content(target_commit, branch_name) - source_sha = commit(branch_name).sha - args = [target_commit.sha, source_sha] + def check_revert_content(target_commit, source_sha) + args = [target_commit.sha, source_sha] args << { mainline: 1 } if target_commit.merge_commit? revert_index = rugged.revert_commit(*args) @@ -933,9 +935,8 @@ class Repository tree_id end - def check_cherry_pick_content(target_commit, branch_name) - source_sha = commit(branch_name).sha - args = [target_commit.sha, source_sha] + def check_cherry_pick_content(target_commit, source_sha) + args = [target_commit.sha, source_sha] args << 1 if target_commit.merge_commit? cherry_pick_index = rugged.cherrypick_commit(*args) diff --git a/app/models/user.rb b/app/models/user.rb index 8443594c055..d3bb04060bf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -21,6 +21,7 @@ class User < ActiveRecord::Base default_value_for :can_create_team, false default_value_for :hide_no_ssh_key, false default_value_for :hide_no_password, false + default_value_for :project_view, :files attr_encrypted :otp_secret, key: Gitlab::Application.secrets.otp_key_base, diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb index 38ef323f6e5..89da05b72bb 100644 --- a/app/services/ci/retry_build_service.rb +++ b/app/services/ci/retry_build_service.rb @@ -1,18 +1,9 @@ module Ci class RetryBuildService < ::BaseService - CLONE_ATTRIBUTES = %i[pipeline project ref tag options commands name - allow_failure stage stage_idx trigger_request - yaml_variables when environment coverage_regex] - .freeze - - REJECT_ATTRIBUTES = %i[id status user token coverage trace runner - artifacts_expire_at artifacts_file - artifacts_metadata artifacts_size - created_at updated_at started_at finished_at - queued_at erased_by erased_at].freeze - - IGNORE_ATTRIBUTES = %i[type lock_version gl_project_id target_url - deploy job_id description].freeze + CLONE_ACCESSORS = %i[pipeline project ref tag options commands name + allow_failure stage stage_idx trigger_request + yaml_variables when environment coverage_regex + description tag_list].freeze def execute(build) reprocess(build).tap do |new_build| @@ -31,7 +22,7 @@ module Ci raise Gitlab::Access::AccessDeniedError end - attributes = CLONE_ATTRIBUTES.map do |attribute| + attributes = CLONE_ACCESSORS.map do |attribute| [attribute, build.send(attribute)] end diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb index 8a9bcd2d053..1297a792259 100644 --- a/app/services/commits/change_service.rb +++ b/app/services/commits/change_service.rb @@ -8,9 +8,9 @@ module Commits @start_branch = params[:start_branch] @target_branch = params[:target_branch] @commit = params[:commit] - @create_merge_request = params[:create_merge_request].present? - check_push_permissions unless @create_merge_request + check_push_permissions + commit rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError, ChangeError => ex @@ -26,34 +26,21 @@ module Commits def commit_change(action) raise NotImplementedError unless repository.respond_to?(action) - if @create_merge_request - into = @commit.public_send("#{action}_branch_name") - tree_branch = @start_branch - else - into = tree_branch = @target_branch - end - - tree_id = repository.public_send( - "check_#{action}_content", @commit, tree_branch) - - if tree_id - validate_target_branch(into) if @create_merge_request + validate_target_branch if different_branch? - repository.public_send( - action, - current_user, - @commit, - into, - tree_id, - start_project: @start_project, - start_branch_name: @start_branch) + repository.public_send( + action, + current_user, + @commit, + @target_branch, + start_project: @start_project, + start_branch_name: @start_branch) - success - else - error_msg = "Sorry, we cannot #{action.to_s.dasherize} this #{@commit.change_type_title(current_user)} automatically. + success + rescue Repository::CreateTreeError + error_msg = "Sorry, we cannot #{action.to_s.dasherize} this #{@commit.change_type_title(current_user)} automatically. A #{action.to_s.dasherize} may have already been performed with this #{@commit.change_type_title(current_user)}, or a more recent commit may have updated some of its content." - raise ChangeError, error_msg - end + raise ChangeError, error_msg end def check_push_permissions @@ -66,16 +53,17 @@ module Commits true end - def validate_target_branch(new_branch) - # Temporary branch exists and contains the change commit - return if repository.find_branch(new_branch) - + def validate_target_branch result = ValidateNewBranchService.new(@project, current_user) - .execute(new_branch) + .execute(@target_branch) if result[:status] == :error raise ChangeError, "There was an error creating the source branch: #{result[:message]}" end end + + def different_branch? + @start_branch != @target_branch || @start_project != @project + end end end diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb index 2d42c4fc04a..523b9f41916 100644 --- a/app/services/projects/update_pages_service.rb +++ b/app/services/projects/update_pages_service.rb @@ -34,6 +34,8 @@ module Projects end rescue => e error(e.message) + ensure + build.erase_artifacts! unless build.has_expiring_artifacts? end private diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index db6a092d8fc..8e02fe3741a 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -385,7 +385,6 @@ module SystemNoteService # Returns Boolean def cross_reference_disallowed?(noteable, mentioner) return true if noteable.is_a?(ExternalIssue) && !noteable.project.jira_tracker_active? - return true if noteable.is_a?(Issuable) && (noteable.try(:closed?) || noteable.try(:merged?)) return false unless mentioner.is_a?(MergeRequest) return false unless noteable.is_a?(Commit) diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml new file mode 100644 index 00000000000..c1a9f8d6ddd --- /dev/null +++ b/app/views/admin/projects/_projects.html.haml @@ -0,0 +1,32 @@ +.js-projects-list-holder + - if @projects.any? + %ul.projects-list.content-list + - @projects.each_with_index do |project| + %li.project-row + .controls + - if project.archived + %span.label.label-warning archived + %span.badge + = storage_counter(project.statistics.storage_size) + = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn" + = link_to 'Delete', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-remove" + .title + = link_to [:admin, project.namespace.becomes(Namespace), project] do + .dash-project-avatar + .avatar-container.s40 + = project_icon(project, alt: '', class: 'avatar project-avatar s40') + %span.project-full-name + %span.namespace-name + - if project.namespace + = project.namespace.human_name + \/ + %span.project-name.filter-title + = project.name + + - if project.description.present? + .description + = markdown_field(project, :description) + + = paginate @projects, theme: 'gitlab' + - else + .nothing-here-block No projects found diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index c35945c5a35..3301f55b8a8 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -7,40 +7,24 @@ %div{ class: container_class } .top-area .prepend-top-default - = form_tag admin_projects_path, method: :get do |f| - .search-holder - .search-field-holder - = search_field_tag :name, params[:name], class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false, placeholder: 'Search by name' - - - if params[:visibility_level].present? - = hidden_field_tag 'visibility_level', params[:visibility_level] - - - if params[:sort].present? - = hidden_field_tag 'sort', params[:sort] - - - if params[:personal].present? - = hidden_field_tag 'visibility_level', 'true' - - - if params[:archived].present? - = hidden_field_tag 'archived', 'true' - - = icon("search", class: "search-icon") - - .dropdown - - toggle_text = 'Namespace' - - if params[:namespace_id].present? - - namespace = Namespace.find(params[:namespace_id]) - - toggle_text = "#{namespace.kind}: #{namespace.full_path}" - = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' }) - .dropdown-menu.dropdown-select.dropdown-menu-align-right - = dropdown_title('Namespaces') - = dropdown_filter("Search for Namespace") - = dropdown_content - = dropdown_loading - = render 'shared/projects/dropdown' - = link_to new_project_path, class: 'btn btn-new' do - New Project - = button_tag "Search", class: "btn btn-primary btn-search hide" + .search-holder + = render 'shared/projects/search_form', autofocus: true, icon: true + .dropdown + - toggle_text = 'Namespace' + - if params[:namespace_id].present? + = hidden_field_tag :namespace_id, params[:namespace_id] + - namespace = Namespace.find(params[:namespace_id]) + - toggle_text = "#{namespace.kind}: #{namespace.full_path}" + = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' }) + .dropdown-menu.dropdown-select.dropdown-menu-align-right + = dropdown_title('Namespaces') + = dropdown_filter("Search for Namespace") + = dropdown_content + = dropdown_loading + = render 'shared/projects/dropdown' + = link_to new_project_path, class: 'btn btn-new' do + New Project + = button_tag "Search", class: "btn btn-primary btn-search hide" %ul.nav-links - opts = params[:visibility_level].present? ? {} : { page: admin_projects_path } @@ -58,35 +42,4 @@ = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do Public - .projects-list-holder - - if @projects.any? - %ul.projects-list.content-list - - @projects.each_with_index do |project| - %li.project-row - .controls - - if project.archived - %span.label.label-warning archived - %span.badge - = storage_counter(project.statistics.storage_size) - = link_to 'Edit', edit_namespace_project_path(project.namespace, project), id: "edit_#{dom_id(project)}", class: "btn" - = link_to 'Delete', [project.namespace.becomes(Namespace), project], data: { confirm: remove_project_message(project) }, method: :delete, class: "btn btn-remove" - .title - = link_to [:admin, project.namespace.becomes(Namespace), project] do - .dash-project-avatar - .avatar-container.s40 - = project_icon(project, alt: '', class: 'avatar project-avatar s40') - %span.project-full-name - %span.namespace-name - - if project.namespace - = project.namespace.human_name - \/ - %span.project-name.filter-title - = project.name - - - if project.description.present? - .description - = markdown_field(project, :description) - - = paginate @projects, theme: 'gitlab' - - else - .nothing-here-block No projects found + = render 'projects' diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index c6d5937a3c3..13eaba41f4c 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -7,8 +7,7 @@ = link_to explore_groups_path, title: 'Explore groups' do Explore Groups .nav-controls - = form_tag request.path, method: :get, class: 'group-filter-form', id: 'group-filter-form' do |f| - = search_field_tag :filter_groups, params[:filter_groups], placeholder: 'Filter by name...', class: 'group-filter-form-field form-control input-short js-groups-list-filter', spellcheck: false, id: 'group-filter-form-field', tabindex: "2" + = render 'shared/groups/search_form' = render 'shared/groups/dropdown' - if current_user.can_create_group? = link_to new_group_path, class: "btn btn-new" do diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 48b0fd504f4..600ee63a5c0 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -13,8 +13,7 @@ Explore projects .nav-controls - = form_tag request.path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| - = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control input-short projects-list-filter', spellcheck: false, id: 'project-filter-form-field', tabindex: "2" + = render 'shared/projects/search_form' = render 'shared/projects/dropdown' - if current_user.can_create_project? = link_to new_project_path, class: 'btn btn-new' do diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index f0adbad8412..eef794dbd51 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -5,14 +5,13 @@ - header_title "Projects", dashboard_projects_path .user-callout{ 'callout-svg' => custom_icon('icon_customization') } - -- if @projects.any? || params[:filter_projects] +- if @projects.any? || params[:name] = render 'dashboard/projects_head' - if @last_push = render "events/event_last_push", event: @last_push -- if @projects.any? || params[:filter_projects] +- if @projects.any? || params[:name] = render 'projects' - else = render "zero_authorized_projects" diff --git a/app/views/explore/groups/_nav.html.haml b/app/views/explore/groups/_nav.html.haml new file mode 100644 index 00000000000..c8d95b52156 --- /dev/null +++ b/app/views/explore/groups/_nav.html.haml @@ -0,0 +1,8 @@ +.top-area + %ul.nav-links + = nav_link(page: explore_groups_path) do + = link_to explore_groups_path do + Explore Groups + .nav-controls + = render 'shared/groups/search_form' + = render 'shared/groups/dropdown' diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 7f1bacc91cb..8374f5a009f 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -5,7 +5,7 @@ = render 'dashboard/groups_head' - else = render 'explore/head' - + = render 'nav' - if @groups.present? = render 'groups' diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml index 614b5431779..e0a2a1e9c96 100644 --- a/app/views/explore/projects/_nav.html.haml +++ b/app/views/explore/projects/_nav.html.haml @@ -1,10 +1,17 @@ -%ul.nav-links - = nav_link(page: [trending_explore_projects_path, explore_root_path]) do - = link_to trending_explore_projects_path do - Trending - = nav_link(page: starred_explore_projects_path) do - = link_to starred_explore_projects_path do - Most stars - = nav_link(page: explore_projects_path) do - = link_to explore_projects_path do - All +.top-area + %ul.nav-links + = nav_link(page: [trending_explore_projects_path, explore_root_path]) do + = link_to trending_explore_projects_path do + Trending + = nav_link(page: starred_explore_projects_path) do + = link_to starred_explore_projects_path do + Most stars + = nav_link(page: explore_projects_path) do + = link_to explore_projects_path do + All + + .nav-controls + - unless current_user + = render 'shared/projects/search_form' + = render 'shared/projects/dropdown' + = render 'filter' diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 42b50481b9d..ec461755103 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -6,10 +6,5 @@ - else = render 'explore/head' -.top-area - = render 'explore/projects/nav' - - .nav-controls - = render 'filter' - += render 'explore/projects/nav' = render 'projects', projects: @projects diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 8f0f2708194..18997baa998 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -11,8 +11,7 @@ .top-area = render 'groups/show_nav' .nav-controls - = form_tag request.path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false + = render 'shared/projects/search_form' = render 'shared/projects/dropdown' - if can? current_user, :create_projects, @group = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new pull-right' do diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 302c1794628..f6d8bb08a64 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -28,7 +28,9 @@ = stylesheet_link_tag "application", media: "all" = stylesheet_link_tag "print", media: "print" - = javascript_include_tag(*webpack_asset_paths("application")) + = javascript_include_tag(*webpack_asset_paths("runtime")) + = javascript_include_tag(*webpack_asset_paths("common")) + = javascript_include_tag(*webpack_asset_paths("main")) - if content_for?(:page_specific_javascripts) = yield :page_specific_javascripts diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 19bd9b6d5c9..36543edc040 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: "en", class: "#{page_class}" } = render "layouts/head" - %body{ data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } } + %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } } = Gon::Base.render_data = render "layouts/header/default", title: header_title diff --git a/app/views/profiles/_head.html.haml b/app/views/profiles/_head.html.haml index 1df04ea614e..83ae9129807 100644 --- a/app/views/profiles/_head.html.haml +++ b/app/views/profiles/_head.html.haml @@ -1,3 +1,2 @@ - content_for :page_specific_javascripts do - = page_specific_javascript_tag('lib/cropper.js') = page_specific_javascript_bundle_tag('profile') diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 02fb47ec981..8a994f6d600 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -93,7 +93,7 @@ %p Changing your username will change path to all personal projects! .col-lg-9 - = form_for @user, url: update_username_profile_path, method: :put, remote: true, html: {class: "update-username"} do |f| + = form_for @user, url: update_username_profile_path, method: :put, html: {class: "update-username"} do |f| .form-group = f.label :username, "Path", class: "label-light" .input-group diff --git a/app/views/profiles/update_username.js.haml b/app/views/profiles/update_username.js.haml deleted file mode 100644 index 5307e0b48cb..00000000000 --- a/app/views/profiles/update_username.js.haml +++ /dev/null @@ -1,7 +0,0 @@ -- if @user.valid? - :plain - new Flash("Username successfully changed", "notice") -- else - - error = @user.errors.full_messages.first - :plain - new Flash("Username change failed - #{escape_javascript error.html_safe}", "alert") diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml index b3bc6010efb..3ae78387938 100644 --- a/app/views/projects/boards/_show.html.haml +++ b/app/views/projects/boards/_show.html.haml @@ -3,6 +3,7 @@ - page_title "Boards" - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('boards') = page_specific_javascript_bundle_tag('simulate_drag') if Rails.env.test? diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml index 421b3db342d..2ebd4f9069a 100644 --- a/app/views/projects/commit/_change.html.haml +++ b/app/views/projects/commit/_change.html.haml @@ -1,10 +1,10 @@ - case type.to_s - when 'revert' - label = 'Revert' - - target_label = 'Revert in branch' + - branch_label = 'Revert in branch' - when 'cherry-pick' - label = 'Cherry-pick' - - target_label = 'Pick into branch' + - branch_label = 'Pick into branch' .modal{ id: "modal-#{type}-commit" } .modal-dialog @@ -15,10 +15,10 @@ .modal-body = form_tag [type.underscore, @project.namespace.becomes(Namespace), @project, commit], method: :post, remote: false, class: "form-horizontal js-#{type}-form js-requires-input" do .form-group.branch - = label_tag 'target_branch', target_label, class: 'control-label' + = label_tag 'start_branch', branch_label, class: 'control-label' .col-sm-10 - = hidden_field_tag :target_branch, @project.default_branch, id: 'target_branch' - = dropdown_tag(@project.default_branch, options: { title: "Switch branch", filter: true, placeholder: "Search branches", toggle_class: 'js-project-refs-dropdown js-target-branch dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "target_branch", selected: @project.default_branch, target_branch: @project.default_branch, refs_url: namespace_project_branches_path(@project.namespace, @project), submit_form_on_click: false } }) + = hidden_field_tag :start_branch, @project.default_branch, id: 'start_branch' + = dropdown_tag(@project.default_branch, options: { title: "Switch branch", filter: true, placeholder: "Search branches", toggle_class: 'js-project-refs-dropdown js-target-branch dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: namespace_project_branches_path(@project.namespace, @project), submit_form_on_click: false } }) - if can?(current_user, :push_code, @project) .js-create-merge-request-container diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml index 6792b3f7a83..da5a676274f 100644 --- a/app/views/projects/commit/_pipelines_list.haml +++ b/app/views/projects/commit/_pipelines_list.haml @@ -4,4 +4,5 @@ } } - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('commit_pipelines') diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index be17f2c764e..dd3fa814716 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -1,6 +1,7 @@ - @no_container = true - page_title "Cycle Analytics" - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('cycle_analytics') = render "projects/head" diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index d9cb7bc0331..4b101447bc0 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -3,6 +3,7 @@ = render "projects/pipelines/head" - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag("environments_folder") #environments-folder-list-view{ data: { "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index d6366b57957..80d2b6f5d95 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -3,6 +3,7 @@ = render "projects/pipelines/head" - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag("environments") #environments-list-view{ data: { environments_data: environments_list_data, diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml index d3bce45e974..464ac34d961 100644 --- a/app/views/projects/graphs/charts.html.haml +++ b/app/views/projects/graphs/charts.html.haml @@ -1,7 +1,7 @@ - @no_container = true - page_title "Charts" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_chart') + = page_specific_javascript_bundle_tag('common_d3') = page_specific_javascript_bundle_tag('graphs') = render "projects/commits/head" diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index d89dfe31e47..680f8ae6c8f 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,7 +1,7 @@ - @no_container = true - page_title "Contributors" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_chart') + = page_specific_javascript_bundle_tag('common_d3') = page_specific_javascript_bundle_tag('graphs') = render 'projects/commits/head' diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 069f3d97943..d39f36e94c7 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -2,8 +2,6 @@ - page_title "#{@issue.title} (#{@issue.to_reference})", "Issues" - page_description @issue.description - page_card_attributes @issue.card_attributes -- content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_vue') .clearfix.detail-page-header .issuable-header diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml index a80f9aa4c4a..04bd4e8b683 100644 --- a/app/views/projects/mattermosts/_team_selection.html.haml +++ b/app/views/projects/mattermosts/_team_selection.html.haml @@ -2,16 +2,15 @@ This service will be installed on the Mattermost instance at %strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host %hr -= form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project)) do |f| += form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project), html: { class: 'js-requires-input'} ) do |f| %h4 Team %p = @teams.one? ? 'The team' : 'Select the team' where the slash commands will be used in - - selected_id = @teams.one? ? @teams.keys.first : 0 - - options = mattermost_teams_options(@teams) - - options = options_for_select(options, selected_id) - = f.select(:team_id, options, {}, { class: 'form-control', disabled: @teams.one?, selected: selected_id }) - = f.hidden_field(:team_id, value: selected_id) if @teams.one? + - selected_id = @teams.one? ? @teams.first['id'] : nil + - options = options_for_select(mattermost_teams_options(@teams), selected_id) + = f.select(:team_id, options, { include_blank: 'Select team...'}, { class: 'form-control', disabled: @teams.one?, selected: selected_id, required: true }) + = f.hidden_field(:team_id, value: selected_id, required: true) if @teams.one? .help-block - if @teams.one? This is the only available team. @@ -25,7 +24,7 @@ %hr %h4 Command trigger word %p Choose the word that will trigger commands - = f.text_field(:trigger, value: @project.path, class: 'form-control') + = f.text_field(:trigger, value: @project.path, class: 'form-control', required: true) .help-block %p Trigger word must be unique, and can't begin with a slash or contain any spaces. diff --git a/app/views/projects/mattermosts/new.html.haml b/app/views/projects/mattermosts/new.html.haml index 96b1d2aee61..15829a3f143 100644 --- a/app/views/projects/mattermosts/new.html.haml +++ b/app/views/projects/mattermosts/new.html.haml @@ -1,3 +1,5 @@ +- @body_class = 'card-content' + .service-installation .inline.pull-right = custom_icon('mattermost_logo', size: 48) diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 521b0694ca9..03d618327d4 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -3,6 +3,7 @@ - page_description @merge_request.description - page_card_attributes @merge_request.card_attributes - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('diff_notes') .merge-request{ 'data-url' => merge_request_path(@merge_request), 'data-project-path' => project_path(@merge_request.project) } diff --git a/app/views/projects/merge_requests/conflicts.html.haml b/app/views/projects/merge_requests/conflicts.html.haml index 1ecd9924d88..51d59280be8 100644 --- a/app/views/projects/merge_requests/conflicts.html.haml +++ b/app/views/projects/merge_requests/conflicts.html.haml @@ -1,6 +1,6 @@ - page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_vue') + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('merge_conflicts') = page_specific_javascript_tag('lib/ace.js') = render "projects/merge_requests/show/mr_title" diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index 1fa987bf537..c94c7944c0b 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -1,8 +1,6 @@ - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('merge_request_widget') -- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil - = form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f| = hidden_field_tag :authenticity_token, form_authenticity_token = hidden_field_tag :sha, @merge_request.diff_head_sha @@ -11,10 +9,10 @@ .accept-action - if @pipeline && @pipeline.active? %span.btn-group - = button_tag class: "btn btn-create js-merge-button merge_when_pipeline_succeeds" do + = button_tag class: "btn btn-info js-merge-when-pipeline-succeeds-button merge-when-pipeline-succeeds" do Merge When Pipeline Succeeds - unless @project.only_allow_merge_if_pipeline_succeeds? - = button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do + = button_tag class: "btn btn-info dropdown-toggle", 'data-toggle' => 'dropdown' do = icon('caret-down') %span.sr-only Select Merge Moment @@ -24,11 +22,11 @@ = icon('check fw') Merge When Pipeline Succeeds %li - = link_to "#", class: "accept_merge_request" do + = link_to "#", class: "accept-merge-request" do = icon('warning fw') Merge Immediately - else - = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do + = f.button class: "btn btn-grouped js-merge-button accept-merge-request" do Accept Merge Request - if @merge_request.force_remove_source_branch? .accept-control diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index a216d59bc74..b4dde2c86c9 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -46,7 +46,7 @@ = preserve do = markdown_field(@milestone, :description) - - if @milestone.total_items_count(current_user).zero? + - if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero? .alert.alert-success.prepend-top-default %span Assign some issues to this milestone. - elsif @milestone.complete?(current_user) && @milestone.active? diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 08c73d94a09..90a150aa74c 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -23,4 +23,4 @@ to post a comment :javascript - var notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, project_id: @project, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") + var notes = new Notes("#{namespace_project_noteable_notes_path(namespace_id: @project.namespace, project_id: @project, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml index 8ffdfa1a2cf..4a5043aac3c 100644 --- a/app/views/projects/pipelines/charts.html.haml +++ b/app/views/projects/pipelines/charts.html.haml @@ -1,7 +1,7 @@ - @no_container = true - page_title "Charts", "Pipelines" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_chart') + = page_specific_javascript_bundle_tag('common_d3') = page_specific_javascript_bundle_tag('graphs') = render 'head' diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index acb61aa2490..5d59ce06612 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -50,4 +50,5 @@ .content-list.pipelines{ data: { url: namespace_project_pipelines_path(@project.namespace, @project, format: :json) } } .vue-pipelines-index += page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('vue_pipelines') diff --git a/app/views/shared/_logo.svg b/app/views/shared/_logo.svg index 9b67422da2c..10e6c49ae9f 100644 --- a/app/views/shared/_logo.svg +++ b/app/views/shared/_logo.svg @@ -1,4 +1,4 @@ -<svg width="36" height="36" class="tanuki-logo"> +<svg width="28" height="28" class="tanuki-logo" viewBox="0 0 36 36"> <path class="tanuki-shape tanuki-left-ear" fill="#e24329" d="M2 14l9.38 9v-9l-4-12.28c-.205-.632-1.176-.632-1.38 0z"/> <path class="tanuki-shape tanuki-right-ear" fill="#e24329" d="M34 14l-9.38 9v-9l4-12.28c.205-.632 1.176-.632 1.38 0z"/> <path class="tanuki-shape tanuki-nose" fill="#e24329" d="M18,34.38 3,14 33,14 Z"/> diff --git a/app/views/shared/groups/_search_form.html.haml b/app/views/shared/groups/_search_form.html.haml new file mode 100644 index 00000000000..ad7a7faedf1 --- /dev/null +++ b/app/views/shared/groups/_search_form.html.haml @@ -0,0 +1,2 @@ += form_tag request.path, method: :get, class: 'group-filter-form', id: 'group-filter-form' do |f| + = search_field_tag :filter_groups, params[:filter_groups], placeholder: 'Filter by name...', class: 'group-filter-form-field form-control input-short js-groups-list-filter', spellcheck: false, id: 'group-filter-form-field', tabindex: "2" diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 37a0c63e514..048fc488207 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,5 +1,6 @@ - todo = issuable_todo(issuable) - content_for :page_specific_javascripts do + = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('issuable') %aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => "101", "spy" => "affix" }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } diff --git a/app/views/shared/milestones/_summary.html.haml b/app/views/shared/milestones/_summary.html.haml index d27fba805a3..78079f633d5 100644 --- a/app/views/shared/milestones/_summary.html.haml +++ b/app/views/shared/milestones/_summary.html.haml @@ -6,14 +6,15 @@ .milestone-stats-and-buttons .milestone-stats - %span.milestone-stat.with-drilldown - %strong= milestone.issues_visible_to_user(current_user).size - issues: - %span.milestone-stat - %strong= milestone.issues_visible_to_user(current_user).opened.size - open and - %strong= milestone.issues_visible_to_user(current_user).closed.size - closed + - if !project || can?(current_user, :read_issue, project) + %span.milestone-stat.with-drilldown + %strong= milestone.issues_visible_to_user(current_user).size + issues: + %span.milestone-stat + %strong= milestone.issues_visible_to_user(current_user).opened.size + open and + %strong= milestone.issues_visible_to_user(current_user).closed.size + closed %span.milestone-stat.with-drilldown %strong= milestone.merge_requests.size merge requests: @@ -32,10 +33,12 @@ .milestone-progress-buttons %span.tab-issues-buttons - - if project && can?(current_user, :create_issue, project) - = link_to new_namespace_project_issue_path(project.namespace, project, issue: { milestone_id: milestone.id }), class: "btn", title: "New Issue" do - New Issue - = link_to 'Browse Issues', milestones_browse_issuables_path(milestone, type: :issues), class: "btn" + - if project + - if can?(current_user, :create_issue, project) + = link_to new_namespace_project_issue_path(project.namespace, project, issue: { milestone_id: milestone.id }), class: "btn", title: "New Issue" do + New Issue + - if can?(current_user, :read_issue, project) + = link_to 'Browse Issues', milestones_browse_issuables_path(milestone, type: :issues), class: "btn" %span.tab-merge-requests-buttons.hidden = link_to 'Browse Merge Requests', milestones_browse_issuables_path(milestone, type: :merge_requests), class: "btn" diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml index c8f2319d95a..a0e9ec46220 100644 --- a/app/views/shared/milestones/_tabs.html.haml +++ b/app/views/shared/milestones/_tabs.html.haml @@ -1,12 +1,18 @@ %ul.nav-links.no-top.no-bottom - %li.active - = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do - Issues - %span.badge= milestone.issues_visible_to_user(current_user).size - %li - = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do - Merge Requests - %span.badge= milestone.merge_requests.size + - if milestone.is_a?(GlobalMilestone) || can?(current_user, :read_issue, @project) + %li.active + = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do + Issues + %span.badge= milestone.issues_visible_to_user(current_user).size + %li + = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do + Merge Requests + %span.badge= milestone.merge_requests.size + - else + %li.active + = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do + Merge Requests + %span.badge= milestone.merge_requests.size %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants @@ -20,10 +26,14 @@ - show_full_project_name = local_assigns.fetch(:show_full_project_name, false) .tab-content.milestone-content - .tab-pane.active#tab-issues - = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user).include_associations, show_project_name: show_project_name, show_full_project_name: show_full_project_name - .tab-pane#tab-merge-requests - = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name + - if milestone.is_a?(GlobalMilestone) || can?(current_user, :read_issue, @project) + .tab-pane.active#tab-issues + = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user).include_associations, show_project_name: show_project_name, show_full_project_name: show_full_project_name + .tab-pane#tab-merge-requests + = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name + - else + .tab-pane.active#tab-merge-requests + = render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name .tab-pane#tab-participants = render 'shared/milestones/participants_tab', users: milestone.participants .tab-pane#tab-labels diff --git a/app/views/shared/projects/_dropdown.html.haml b/app/views/shared/projects/_dropdown.html.haml index c19697802ce..2d25b8aad62 100644 --- a/app/views/shared/projects/_dropdown.html.haml +++ b/app/views/shared/projects/_dropdown.html.haml @@ -1,8 +1,4 @@ - @sort ||= sort_value_recently_updated -- personal = params[:personal] -- archived = params[:archived] -- shared = params[:shared] -- namespace_id = params[:namespace_id] .dropdown - toggle_text = projects_sort_options_hash[@sort] = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { id: 'sort-projects-dropdown' }) @@ -11,32 +7,32 @@ Sort by - projects_sort_options_hash.each do |value, title| %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: value, archived: archived, personal: personal), class: ("is-active" if @sort == value) do + = link_to filter_projects_path(sort: value), class: ("is-active" if @sort == value) do = title %li.divider %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, archived: nil), class: ("is-active" unless params[:archived].present?) do + = link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do Hide archived projects %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, archived: true), class: ("is-active" if params[:archived].present?) do + = link_to filter_projects_path(archived: true), class: ("is-active" if params[:archived].present?) do Show archived projects - if current_user %li.divider %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, personal: nil), class: ("is-active" unless personal.present?) do + = link_to filter_projects_path(personal: nil), class: ("is-active" unless params[:personal].present?) do Owned by anyone %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, personal: true), class: ("is-active" if personal.present?) do + = link_to filter_projects_path(personal: true), class: ("is-active" if params[:personal].present?) do Owned by me - if @group && @group.shared_projects.present? %li.divider %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: nil), class: ("is-active" unless shared.present?) do + = link_to filter_projects_path(shared: nil), class: ("is-active" unless params[:shared].present?) do All projects %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: 0), class: ("is-active" if shared == '0') do + = link_to filter_projects_path(shared: 0), class: ("is-active" if params[:shared] == '0') do Hide shared projects %li - = link_to filter_projects_path(namespace_id: namespace_id, sort: @sort, shared: 1), class: ("is-active" if shared == '1') do + = link_to filter_projects_path(shared: 1), class: ("is-active" if params[:shared] == '1') do Hide group projects diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 3a9dd37dc7d..c57282c5742 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -8,7 +8,7 @@ - show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true - remote = false unless local_assigns[:remote] == true -.projects-list-holder +.js-projects-list-holder - if projects.any? %ul.projects-list.content-list - projects.each_with_index do |project, i| @@ -25,6 +25,3 @@ = paginate(projects, remote: remote, theme: "gitlab") if projects.respond_to? :total_pages - else .nothing-here-block No projects found - -:javascript - ProjectsList.init(); diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml new file mode 100644 index 00000000000..b89194bcc67 --- /dev/null +++ b/app/views/shared/projects/_search_form.html.haml @@ -0,0 +1,23 @@ += form_tag filter_projects_path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| + = search_field_tag :name, params[:name], + placeholder: 'Filter by name...', + class: 'project-filter-form-field form-control input-short js-projects-list-filter', + spellcheck: false, + id: 'project-filter-form-field', + tabindex: "2", + autofocus: local_assigns[:autofocus] + + - if local_assigns[:icon] + = icon("search", class: "search-icon") + + - if params[:sort].present? + = hidden_field_tag :sort, params[:sort] + + - if params[:personal].present? + = hidden_field_tag :personal, params[:personal] + + - if params[:archived].present? + = hidden_field_tag :archived, params[:archived] + + - if params[:visibility_level].present? + = hidden_field_tag :visibility_level, params[:visibility_level] diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index af091f9ab88..76cd330e80a 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,7 +1,7 @@ - page_title @user.name - page_description @user.bio - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('lib_d3') + = page_specific_javascript_bundle_tag('common_d3') = page_specific_javascript_bundle_tag('users') - header_title @user.name, user_path(@user) - @no_container = true diff --git a/changelogs/unreleased/19497-hide-relevant-info-when-project-issues-are-disabled.yml b/changelogs/unreleased/19497-hide-relevant-info-when-project-issues-are-disabled.yml new file mode 100644 index 00000000000..eceb2b9fac6 --- /dev/null +++ b/changelogs/unreleased/19497-hide-relevant-info-when-project-issues-are-disabled.yml @@ -0,0 +1,4 @@ +--- +title: Hide issue info when project issues are disabled +merge_request: +author: George Andrinopoulos diff --git a/changelogs/unreleased/26847-api-pipelines-use-basic.yml b/changelogs/unreleased/26847-api-pipelines-use-basic.yml new file mode 100644 index 00000000000..2034a4ba080 --- /dev/null +++ b/changelogs/unreleased/26847-api-pipelines-use-basic.yml @@ -0,0 +1,4 @@ +--- +title: Expose pipelines as PipelineBasic `api/v3/projects/:id/pipelines` +merge_request: 8875 +author: diff --git a/changelogs/unreleased/27532_api_changes.yml b/changelogs/unreleased/27532_api_changes.yml new file mode 100644 index 00000000000..778469d5a86 --- /dev/null +++ b/changelogs/unreleased/27532_api_changes.yml @@ -0,0 +1,4 @@ +--- +title: Use iids as filter parameter +merge_request: 9096 +author: diff --git a/changelogs/unreleased/28010-mr-merge-button-default-to-danger.yml b/changelogs/unreleased/28010-mr-merge-button-default-to-danger.yml new file mode 100644 index 00000000000..06bb669ceac --- /dev/null +++ b/changelogs/unreleased/28010-mr-merge-button-default-to-danger.yml @@ -0,0 +1,4 @@ +--- +title: Default to subtle MR mege button until CI status is available +merge_request: +author: diff --git a/changelogs/unreleased/28655-current-path-text-is-not-updated-after-setting-the-new-username.yml b/changelogs/unreleased/28655-current-path-text-is-not-updated-after-setting-the-new-username.yml new file mode 100644 index 00000000000..bff996172f3 --- /dev/null +++ b/changelogs/unreleased/28655-current-path-text-is-not-updated-after-setting-the-new-username.yml @@ -0,0 +1,4 @@ +--- +title: Update account view to display new username +merge_request: +author: diff --git a/changelogs/unreleased/28865-filter-by-authorized-projects-in-v4.yml b/changelogs/unreleased/28865-filter-by-authorized-projects-in-v4.yml new file mode 100644 index 00000000000..7c64783cbd0 --- /dev/null +++ b/changelogs/unreleased/28865-filter-by-authorized-projects-in-v4.yml @@ -0,0 +1,4 @@ +--- +title: Add filter param for project membership for current_user in API v4 +merge_request: +author: diff --git a/changelogs/unreleased/28898-fix-search-branches-in-cherry-picking.yml b/changelogs/unreleased/28898-fix-search-branches-in-cherry-picking.yml new file mode 100644 index 00000000000..48e62f8f70d --- /dev/null +++ b/changelogs/unreleased/28898-fix-search-branches-in-cherry-picking.yml @@ -0,0 +1,4 @@ +--- +title: Fix json response in branches controller +merge_request: 9710 +author: George Andrinopoulos diff --git a/changelogs/unreleased/28935-make-logo-smaller.yml b/changelogs/unreleased/28935-make-logo-smaller.yml new file mode 100644 index 00000000000..ef79fc7d212 --- /dev/null +++ b/changelogs/unreleased/28935-make-logo-smaller.yml @@ -0,0 +1,4 @@ +--- +title: Decrease tanuki logo size +merge_request: +author: diff --git a/changelogs/unreleased/3440-remove-hsts-header.yml b/changelogs/unreleased/3440-remove-hsts-header.yml new file mode 100644 index 00000000000..0310e733f4e --- /dev/null +++ b/changelogs/unreleased/3440-remove-hsts-header.yml @@ -0,0 +1,4 @@ +--- +title: Stop setting Strict-Transport-Securty header from within the app +merge_request: +author: diff --git a/changelogs/unreleased/add-kube-ca-pem-file-deprecate-kube-ca-pem.yml b/changelogs/unreleased/add-kube-ca-pem-file-deprecate-kube-ca-pem.yml new file mode 100644 index 00000000000..1ae1e3c7a7a --- /dev/null +++ b/changelogs/unreleased/add-kube-ca-pem-file-deprecate-kube-ca-pem.yml @@ -0,0 +1,4 @@ +--- +title: Add KUBE_CA_PEM_FILE, deprecate KUBE_CA_PEM +merge_request: 9398 +author: diff --git a/changelogs/unreleased/commons-chunk-plugin.yml b/changelogs/unreleased/commons-chunk-plugin.yml new file mode 100644 index 00000000000..5c11ea3bbb2 --- /dev/null +++ b/changelogs/unreleased/commons-chunk-plugin.yml @@ -0,0 +1,5 @@ +--- +title: Use webpack CommonsChunkPlugin to place common javascript libraries in their + own bundles +merge_request: 9647 +author: diff --git a/changelogs/unreleased/dashboard-filter-search-keep-params.yml b/changelogs/unreleased/dashboard-filter-search-keep-params.yml new file mode 100644 index 00000000000..a140715b7a2 --- /dev/null +++ b/changelogs/unreleased/dashboard-filter-search-keep-params.yml @@ -0,0 +1,4 @@ +--- +title: Dashboard project search keeps selected sort & filters +merge_request: +author: diff --git a/changelogs/unreleased/delete-artifacts-for-pages.yml b/changelogs/unreleased/delete-artifacts-for-pages.yml new file mode 100644 index 00000000000..50b3dd81d60 --- /dev/null +++ b/changelogs/unreleased/delete-artifacts-for-pages.yml @@ -0,0 +1,4 @@ +--- +title: Delete artifacts for pages unless expiry date is specified +merge_request: 9716 +author: diff --git a/changelogs/unreleased/dm-fix-cherry-pick.yml b/changelogs/unreleased/dm-fix-cherry-pick.yml new file mode 100644 index 00000000000..e924b821d7e --- /dev/null +++ b/changelogs/unreleased/dm-fix-cherry-pick.yml @@ -0,0 +1,4 @@ +--- +title: Fix cherry-picking or reverting through an MR +merge_request: +author: diff --git a/changelogs/unreleased/dz-change-project-view.yml b/changelogs/unreleased/dz-change-project-view.yml new file mode 100644 index 00000000000..47e007a80a8 --- /dev/null +++ b/changelogs/unreleased/dz-change-project-view.yml @@ -0,0 +1,4 @@ +--- +title: Change default project view for user from readme to files view +merge_request: 9584 +author: diff --git a/changelogs/unreleased/etag-notes-polling.yml b/changelogs/unreleased/etag-notes-polling.yml new file mode 100644 index 00000000000..53990821d25 --- /dev/null +++ b/changelogs/unreleased/etag-notes-polling.yml @@ -0,0 +1,4 @@ +--- +title: Use ETag to improve performance of issue notes polling +merge_request: 9036 +author: diff --git a/changelogs/unreleased/format-timeago-date.yml b/changelogs/unreleased/format-timeago-date.yml new file mode 100644 index 00000000000..f331c34abbc --- /dev/null +++ b/changelogs/unreleased/format-timeago-date.yml @@ -0,0 +1,4 @@ +--- +title: Format timeago date to short format +merge_request: +author: diff --git a/changelogs/unreleased/list_issues_with_no_labels.yml b/changelogs/unreleased/list_issues_with_no_labels.yml new file mode 100644 index 00000000000..ab44841631b --- /dev/null +++ b/changelogs/unreleased/list_issues_with_no_labels.yml @@ -0,0 +1,4 @@ +--- +title: Document ability to list issues with no labels using API +merge_request: 9697 +author: Vignesh Ravichandran diff --git a/changelogs/unreleased/remove-es6-extension.yml b/changelogs/unreleased/remove-es6-extension.yml new file mode 100644 index 00000000000..65f4a7a7867 --- /dev/null +++ b/changelogs/unreleased/remove-es6-extension.yml @@ -0,0 +1,4 @@ +--- +title: Remove es6 file extension from JavaScript files +merge_request: 9241 +author: winniehell diff --git a/config/application.rb b/config/application.rb index 45f3b20d214..f1a986d1731 100644 --- a/config/application.rb +++ b/config/application.rb @@ -100,7 +100,6 @@ module Gitlab config.assets.precompile << "katex.js" config.assets.precompile << "xterm/xterm.css" config.assets.precompile << "lib/ace.js" - config.assets.precompile << "lib/cropper.js" config.assets.precompile << "lib/raphael.js" config.assets.precompile << "u2f.js" config.assets.precompile << "vendor/assets/fonts/*" diff --git a/config/initializers/metrics.rb b/config/initializers/8_metrics.rb index a1517e6afc8..a1517e6afc8 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/8_metrics.rb diff --git a/config/initializers/etag_caching.rb b/config/initializers/etag_caching.rb new file mode 100644 index 00000000000..eba88801141 --- /dev/null +++ b/config/initializers/etag_caching.rb @@ -0,0 +1,4 @@ +# This middleware has to come after Gitlab::Metrics::RackMiddleware +# in the middleware stack, because it tracks events with +# GitLab Performance Monitoring +Rails.application.config.middleware.use(Gitlab::EtagCaching::Middleware) diff --git a/config/karma.config.js b/config/karma.config.js index 2f3cc932413..a23e62f5022 100644 --- a/config/karma.config.js +++ b/config/karma.config.js @@ -1,9 +1,10 @@ var path = require('path'); +var webpack = require('webpack'); var webpackConfig = require('./webpack.config.js'); var ROOT_PATH = path.resolve(__dirname, '..'); // add coverage instrumentation to babel config -if (webpackConfig && webpackConfig.module && webpackConfig.module.rules) { +if (webpackConfig.module && webpackConfig.module.rules) { var babelConfig = webpackConfig.module.rules.find(function (rule) { return rule.loader === 'babel-loader'; }); @@ -13,6 +14,16 @@ if (webpackConfig && webpackConfig.module && webpackConfig.module.rules) { babelConfig.options.plugins.push('istanbul'); } +// remove problematic plugins +if (webpackConfig.plugins) { + webpackConfig.plugins = webpackConfig.plugins.filter(function (plugin) { + return !( + plugin instanceof webpack.optimize.CommonsChunkPlugin || + plugin instanceof webpack.DefinePlugin + ); + }); +} + // Karma configuration module.exports = function(config) { var progressReporter = process.env.CI ? 'mocha' : 'progress'; diff --git a/config/routes/project.rb b/config/routes/project.rb index 2703bf4ab46..7dc7963ab88 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -267,7 +267,7 @@ constraints(ProjectUrlConstrainer.new) do resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ } - resources :notes, only: [:index, :create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do + resources :notes, only: [:create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do member do delete :delete_attachment post :resolve @@ -275,6 +275,8 @@ constraints(ProjectUrlConstrainer.new) do end end + get 'noteable/:target_type/:target_id/notes' => 'notes#index', as: 'noteable_notes' + resources :boards, only: [:index, :show] do scope module: :boards do resources :issues, only: [:index, :update] diff --git a/config/webpack.config.js b/config/webpack.config.js index 13273902b0e..d9fa70c29fb 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -17,7 +17,10 @@ var WEBPACK_REPORT = process.env.WEBPACK_REPORT; var config = { context: path.join(ROOT_PATH, 'app/assets/javascripts'), entry: { - application: './application.js', + common: './commons/index.js', + common_vue: ['vue', 'vue-resource'], + common_d3: ['d3'], + main: './main.js', blob_edit: './blob_edit/blob_edit_bundle.js', boards: './boards/boards_bundle.js', simulate_drag: './test_utils/simulate_drag.js', @@ -38,16 +41,13 @@ var config = { snippet: './snippet/snippet_bundle.js', terminal: './terminal/terminal_bundle.js', users: './users/users_bundle.js', - lib_chart: './lib/chart.js', - lib_d3: './lib/d3.js', - lib_vue: './lib/vue_resource.js', vue_pipelines: './vue_pipelines_index/index.js', }, output: { path: path.join(ROOT_PATH, 'public/assets/webpack'), publicPath: '/assets/webpack/', - filename: IS_PRODUCTION ? '[name]-[chunkhash].js' : '[name].js' + filename: IS_PRODUCTION ? '[name].[chunkhash].bundle.js' : '[name].bundle.js' }, devtool: 'inline-source-map', @@ -82,14 +82,56 @@ var config = { modules: false, assets: true }), + + // prevent pikaday from including moment.js new webpack.IgnorePlugin(/moment/, /pikaday/), + + // fix legacy jQuery plugins which depend on globals + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + }), + + // use deterministic module ids in all environments + IS_PRODUCTION ? + new webpack.HashedModuleIdsPlugin() : + new webpack.NamedModulesPlugin(), + + // create cacheable common library bundle for all vue chunks + new webpack.optimize.CommonsChunkPlugin({ + name: 'common_vue', + chunks: [ + 'boards', + 'commit_pipelines', + 'cycle_analytics', + 'diff_notes', + 'environments', + 'environments_folder', + 'issuable', + 'merge_conflicts', + 'vue_pipelines', + ], + minChunks: function(module, count) { + return module.resource && (/vue_shared/).test(module.resource); + }, + }), + + // create cacheable common library bundle for all d3 chunks + new webpack.optimize.CommonsChunkPlugin({ + name: 'common_d3', + chunks: ['graphs', 'users'], + }), + + // create cacheable common library bundles + new webpack.optimize.CommonsChunkPlugin({ + names: ['main', 'common', 'runtime'], + }), ], resolve: { extensions: ['.js', '.es6', '.js.es6'], alias: { '~': path.join(ROOT_PATH, 'app/assets/javascripts'), - 'bootstrap/js': 'bootstrap-sass/assets/javascripts/bootstrap', 'emoji-aliases$': path.join(ROOT_PATH, 'fixtures/emojis/aliases.json'), 'icons': path.join(ROOT_PATH, 'app/views/shared/icons'), 'vendor': path.join(ROOT_PATH, 'vendor/assets/javascripts'), diff --git a/db/fixtures/development/13_comments.rb b/db/fixtures/development/13_comments.rb index 29b8081055d..bc2d74c8034 100644 --- a/db/fixtures/development/13_comments.rb +++ b/db/fixtures/development/13_comments.rb @@ -1,7 +1,7 @@ require './spec/support/sidekiq' Gitlab::Seeder.quiet do - Issue.all.each do |issue| + Issue.find_each do |issue| project = issue.project project.team.users.each do |user| @@ -16,7 +16,7 @@ Gitlab::Seeder.quiet do end end - MergeRequest.all.each do |mr| + MergeRequest.find_each do |mr| project = mr.project project.team.users.each do |user| diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md index 4f5c22e2d29..e99a7ee29cc 100644 --- a/doc/administration/reply_by_email.md +++ b/doc/administration/reply_by_email.md @@ -13,7 +13,8 @@ three strategies for this feature: ### Email sub-addressing -**If your provider or server supports email sub-addressing, we recommend using it.** +**If your provider or server supports email sub-addressing, we recommend using it. +Some features (e.g. create new issue via email) only work with sub-addressing.** [Sub-addressing](https://en.wikipedia.org/wiki/Email_address#Sub-addressing) is a feature where any email to `user+some_arbitrary_tag@example.com` will end up @@ -140,12 +141,32 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow the # The IDLE command timeout. gitlab_rails['incoming_email_idle_timeout'] = 60 ``` + + ```ruby + # Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes mailbox incoming@exchange.example.com + gitlab_rails['incoming_email_enabled'] = true + + # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here + gitlab_rails['incoming_email_address'] = "incoming@exchange.example.com" + + # Email account username + # Typically this is the userPrincipalName (UPN) + gitlab_rails['incoming_email_email'] = "incoming@ad-domain.example.com" + # Email account password + gitlab_rails['incoming_email_password'] = "[REDACTED]" + + # IMAP server host + gitlab_rails['incoming_email_host'] = "exchange.example.com" + # IMAP server port + gitlab_rails['incoming_email_port'] = 993 + # Whether the IMAP server uses SSL + gitlab_rails['incoming_email_ssl'] = true + ``` -1. Reconfigure GitLab and restart mailroom for the changes to take effect: +1. Reconfigure GitLab for the changes to take effect: ```sh sudo gitlab-ctl reconfigure - sudo gitlab-ctl restart mailroom ``` 1. Verify that everything is configured correctly: @@ -232,6 +253,35 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow the # The IDLE command timeout. idle_timeout: 60 ``` + + ```yaml + # Configuration for Microsoft Exchange mail server w/ IMAP enabled, assumes mailbox incoming@exchange.example.com + incoming_email: + enabled: true + + # The email address replies are sent to - Exchange does not support sub-addressing so %{key} is not used here + address: "incoming@exchange.example.com" + + # Email account username + # Typically this is the userPrincipalName (UPN) + user: "incoming@ad-domain.example.com" + # Email account password + password: "[REDACTED]" + + # IMAP server host + host: "exchange.example.com" + # IMAP server port + port: 993 + # Whether the IMAP server uses SSL + ssl: true + # Whether the IMAP server uses StartTLS + start_tls: false + + # The mailbox where incoming mail will end up. Usually "inbox". + mailbox: "inbox" + # The IDLE command timeout. + idle_timeout: 60 + ``` 1. Enable `mail_room` in the init script at `/etc/default/gitlab`: diff --git a/doc/api/issues.md b/doc/api/issues.md index 51ce08c873e..0f22d0b7f94 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -23,6 +23,7 @@ GET /issues?state=closed GET /issues?labels=foo GET /issues?labels=foo,bar GET /issues?labels=foo,bar&state=opened +GET /projects/:id/issues?labels_name=No+Label GET /issues?milestone=1.0.0 GET /issues?milestone=1.0.0&state=opened GET /issues?iids[]=42&iids[]=43 @@ -32,6 +33,7 @@ GET /issues?iids[]=42&iids[]=43 | --------- | ---- | -------- | ----------- | | `state` | string | no | Return all issues or just those that are `opened` or `closed`| | `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned | +| `labels_name` | string | no | Return all issues with the mentioned label. `No+Label` lists all issues with no labels | | `milestone` | string| no | The milestone title | | `iids` | Array[integer] | no | Return only the issues having the given `iid` | | `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | @@ -102,6 +104,7 @@ GET /groups/:id/issues?state=closed GET /groups/:id/issues?labels=foo GET /groups/:id/issues?labels=foo,bar GET /groups/:id/issues?labels=foo,bar&state=opened +GET /projects/:id/issues?labels_name=No+Label GET /groups/:id/issues?milestone=1.0.0 GET /groups/:id/issues?milestone=1.0.0&state=opened GET /groups/:id/issues?iids[]=42&iids[]=43 @@ -112,6 +115,7 @@ GET /groups/:id/issues?iids[]=42&iids[]=43 | `id` | integer | yes | The ID of a group | | `state` | string | no | Return all issues or just those that are `opened` or `closed`| | `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned | +| `labels_name` | string | no | Return all issues with the mentioned label. `No+Label` lists all issues with no labels | | `iids` | Array[integer] | no | Return only the issues having the given `iid` | | `milestone` | string| no | The milestone title | | `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | @@ -183,6 +187,7 @@ GET /projects/:id/issues?state=closed GET /projects/:id/issues?labels=foo GET /projects/:id/issues?labels=foo,bar GET /projects/:id/issues?labels=foo,bar&state=opened +GET /projects/:id/issues?labels_name=No+Label GET /projects/:id/issues?milestone=1.0.0 GET /projects/:id/issues?milestone=1.0.0&state=opened GET /projects/:id/issues?iids[]=42&iids[]=43 @@ -194,6 +199,7 @@ GET /projects/:id/issues?iids[]=42&iids[]=43 | `iids` | Array[integer] | no | Return only the milestone having the given `iid` | | `state` | string | no | Return all issues or just those that are `opened` or `closed`| | `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned | +| `labels_name` | string | no | Return all issues with the mentioned label. `No+Label` lists all issues with no labels | | `milestone` | string| no | The milestone title | | `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | | `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` | diff --git a/doc/api/milestones.md b/doc/api/milestones.md index 9439db84e9b..3c86357a6c3 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -6,8 +6,8 @@ Returns a list of project milestones. ``` GET /projects/:id/milestones -GET /projects/:id/milestones?iid=42 -GET /projects/:id/milestones?iid[]=42&iid[]=43 +GET /projects/:id/milestones?iids=42 +GET /projects/:id/milestones?iids[]=42&iids[]=43 GET /projects/:id/milestones?state=active GET /projects/:id/milestones?state=closed GET /projects/:id/milestones?search=version @@ -18,7 +18,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `id` | integer | yes | The ID of a project | -| `iid` | Array[integer] | optional | Return only the milestone having the given `iid` | +| `iids` | Array[integer] | optional | Return only the milestones having the given `iids` | | `state` | string | optional | Return only `active` or `closed` milestones` | | `search` | string | optional | Return only milestones with a title or description matching the provided string | diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index 9d6f3ea41d9..d809ec032f8 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -24,49 +24,13 @@ Example of response "id": 47, "status": "pending", "ref": "new-pipeline", - "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", - "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", - "tag": false, - "yaml_errors": null, - "user": { - "name": "Administrator", - "username": "root", - "id": 1, - "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "web_url": "http://localhost:3000/root" - }, - "created_at": "2016-08-16T10:23:19.007Z", - "updated_at": "2016-08-16T10:23:19.216Z", - "started_at": null, - "finished_at": null, - "committed_at": null, - "duration": null, - "coverage": "30.0" + "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a" }, { "id": 48, "status": "pending", "ref": "new-pipeline", - "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", - "before_sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a", - "tag": false, - "yaml_errors": null, - "user": { - "name": "Administrator", - "username": "root", - "id": 1, - "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "web_url": "http://localhost:3000/root" - }, - "created_at": "2016-08-16T10:23:21.184Z", - "updated_at": "2016-08-16T10:23:21.314Z", - "started_at": null, - "finished_at": null, - "committed_at": null, - "duration": null, - "coverage": null + "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a" } ] ``` diff --git a/doc/api/projects.md b/doc/api/projects.md index f6eabc1f663..6062c5ccd71 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -34,9 +34,10 @@ Parameters: | `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` | | `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` | | `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` | -| `search` | string | no | Return list of authorized projects matching the search criteria | +| `search` | string | no | Return list of projects matching the search criteria | | `simple` | boolean | no | Return only the ID, URL, name, and path of each project | | `owned` | boolean | no | Limit by projects owned by the current user | +| `membership` | boolean | no | Limit by projects that the current user is a member of | | `starred` | boolean | no | Limit by projects starred by the current user | ```json diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md index 1b51b9200cd..39dc6d98e7b 100644 --- a/doc/api/v3_to_v4.md +++ b/doc/api/v3_to_v4.md @@ -28,7 +28,12 @@ changes are in V4: - `/dockerfiles/:key` - Moved `/projects/fork/:id` to `/projects/:id/fork` [!8940](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8940) - Moved `DELETE /todos` to `POST /todos/mark_as_done` and `DELETE /todos/:todo_id` to `POST /todos/:todo_id/mark_as_done` [!9410](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9410) -- Endpoints `/projects/owned`, `/projects/visible`, `/projects/starred` & `/projects/all` are consolidated into `/projects` using query parameters [!8962](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8962) +- Project filters are no longer available as `GET /projects/foo`, but as `GET /projects?foo=true` instead [!8962](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8962) + - `GET /projects/visible` & `GET /projects/all` are consolidated into `GET /projects` and can be used with or without authorization + - `GET /projects/owned` moved to `GET /projects?owned=true` + - `GET /projects/starred` moved to `GET /projects?starred=true` +- `GET /projects` returns all projects visible to current user, even if the user is not a member [!9674](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9674) + - To get projects the user is a member of, use `/projects?membership=true` - Return pagination headers for all endpoints that return an array [!8606](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8606) - Added `POST /environments/:environment_id/stop` to stop an environment [!8808](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8808) - Removed `DELETE projects/:id/deploy_keys/:key_id/disable`. Use `DELETE projects/:id/deploy_keys/:key_id` instead [!9366](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9366) @@ -52,3 +57,5 @@ changes are in V4: - Return HTTP status code `400` for all validation errors when creating or updating a member instead of sometimes `422` error. [!9523](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9523) - Remove `GET /groups/owned`. Use `GET /groups?owned=true` instead [!9505](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9505) - Return 202 with JSON body on async removals on V4 API (DELETE `/projects/:id/repository/merged_branches` and DELETE `/projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9449) +- `projects/:id/milestones?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!9096](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9096) +- Return basic info about pipeline in `GET /projects/:id/pipelines` [!8875](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8875) diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md index b8669964c84..a14c0752366 100644 --- a/doc/development/instrumentation.md +++ b/doc/development/instrumentation.md @@ -35,7 +35,7 @@ Using this method is in general preferred over directly calling the various instrumentation methods. Method instrumentation should be added in the initializer -`config/initializers/metrics.rb`. +`config/initializers/8_metrics.rb`. ### Examples diff --git a/doc/development/limit_ee_conflicts.md b/doc/development/limit_ee_conflicts.md index e3568b65b18..51b4b398f2c 100644 --- a/doc/development/limit_ee_conflicts.md +++ b/doc/development/limit_ee_conflicts.md @@ -53,9 +53,12 @@ Notes: - Code reviews for merge requests often consist of multiple iterations of feedback and fixes. There is no need to update your EE MR after each iteration. Instead, create an EE MR as soon as you see the - `rake ee_compat_check` job failing and update it after the CE MR is merged. + `rake ee_compat_check` job failing. After you receive the final acceptance + from a Maintainer (but before the CE MR is merged) update the EE MR. This helps to identify significant conflicts sooner, but also reduces the number of times you have to resolve conflicts. +- You can use [`git rerere`](https://git-scm.com/blog/2010/03/08/rerere.html) + to avoid resolving the same conflicts multiple times. ## Possible type of conflicts diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md new file mode 100644 index 00000000000..7b934ecd87a --- /dev/null +++ b/doc/update/8.17-to-9.0.md @@ -0,0 +1,24 @@ +#### Nginx configuration + +Ensure you're still up-to-date with the latest NGINX configuration changes: + +```sh +cd /home/git/gitlab + +# For HTTPS configurations +git diff origin/8-17-stable:lib/support/nginx/gitlab-ssl origin/9-0-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/8-17-stable:lib/support/nginx/gitlab origin/9-0-stable:lib/support/nginx/gitlab +``` + +If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx +configuration as GitLab application no longer handles setting it. + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/9-0-stable/lib/support/init.d/gitlab.default.example#L38 diff --git a/doc/user/project/integrations/kubernetes.md b/doc/user/project/integrations/kubernetes.md index cc67e667472..2a890acde4d 100644 --- a/doc/user/project/integrations/kubernetes.md +++ b/doc/user/project/integrations/kubernetes.md @@ -49,7 +49,8 @@ GitLab CI build environment: - `KUBE_URL` - equal to the API URL - `KUBE_TOKEN` - `KUBE_NAMESPACE` -- `KUBE_CA_PEM` - only if a custom CA bundle was specified +- `KUBE_CA_PEM_FILE` - only present if a custom CA bundle was specified. Path to a file containing PEM data. +- `KUBE_CA_PEM` (deprecated)- only if a custom CA bundle was specified. Raw PEM data. ## Web terminals diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md index 6edf99239ea..35af48724f2 100644 --- a/doc/user/project/pages/getting_started_part_four.md +++ b/doc/user/project/pages/getting_started_part_four.md @@ -133,6 +133,9 @@ your Jekyll 3.4.0 site with GitLab Pages. This is the minimum configuration for our example. On the steps below, we'll refine the script by adding extra options to our GitLab CI. +Artifacts will be automatically deleted once GitLab Pages got deployed. +You can preserve artifacts for limited time by specifying the expiry time. + ### Image At this point, you probably ask yourself: "okay, but to install Jekyll diff --git a/features/steps/project/commits/revert.rb b/features/steps/project/commits/revert.rb index 94a5d4e2e4d..c9746407344 100644 --- a/features/steps/project/commits/revert.rb +++ b/features/steps/project/commits/revert.rb @@ -36,5 +36,6 @@ class Spinach::Features::RevertCommits < Spinach::FeatureSteps step 'I should see the new merge request notice' do page.should have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.') + page.should have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master") end end diff --git a/features/steps/project/fork.rb b/features/steps/project/fork.rb index 9a6c04fba7a..79db9728227 100644 --- a/features/steps/project/fork.rb +++ b/features/steps/project/fork.rb @@ -56,7 +56,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps end step 'I should see my fork on the list' do - page.within('.projects-list-holder') do + page.within('.js-projects-list-holder') do project = @user.fork_of(@project) expect(page).to have_content("#{project.namespace.human_name} / #{project.name}") end diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index dae248b8b7e..345a28f27dc 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -166,11 +166,15 @@ module SharedProject end step 'I should see project "Internal"' do - expect(page).to have_content "Internal" + page.within '.js-projects-list-holder' do + expect(page).to have_content "Internal" + end end step 'I should not see project "Internal"' do - expect(page).not_to have_content "Internal" + page.within '.js-projects-list-holder' do + expect(page).not_to have_content "Internal" + end end step 'public project "Community"' do diff --git a/lib/api/api.rb b/lib/api/api.rb index 02f7bc2fbbf..89449ce8813 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -20,7 +20,9 @@ module API mount ::API::V3::MergeRequestDiffs mount ::API::V3::MergeRequests mount ::API::V3::Notes + mount ::API::V3::Pipelines mount ::API::V3::ProjectHooks + mount ::API::V3::Milestones mount ::API::V3::Projects mount ::API::V3::ProjectSnippets mount ::API::V3::Repositories diff --git a/lib/api/commits.rb b/lib/api/commits.rb index fd03e92264d..b0aa10f8bf2 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -127,7 +127,7 @@ module API commit_params = { commit: commit, - create_merge_request: false, + start_branch: params[:branch], target_branch: params[:branch] } diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 4600abc7dc7..9c41146f1e3 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -252,6 +252,10 @@ module API # project helpers def filter_projects(projects) + if params[:membership] + projects = projects.merge(current_user.authorized_projects) + end + if params[:owned] projects = projects.merge(current_user.owned_projects) end diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index 44bdaea7fa4..bd74174c655 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -30,7 +30,7 @@ module API params do optional :state, type: String, values: %w[active closed all], default: 'all', desc: 'Return "active", "closed", or "all" milestones' - optional :iid, type: Array[Integer], desc: 'The IID of the milestone' + optional :iids, type: Array[Integer], desc: 'The IIDs of the milestones' optional :search, type: String, desc: 'The search criteria for the title or description of the milestone' use :pagination end @@ -39,7 +39,7 @@ module API milestones = user_project.milestones milestones = filter_milestones_state(milestones, params[:state]) - milestones = filter_by_iid(milestones, params[:iid]) if params[:iid].present? + milestones = filter_by_iid(milestones, params[:iids]) if params[:iids].present? milestones = filter_by_search(milestones, params[:search]) if params[:search] present paginate(milestones), with: Entities::Milestone diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb index 3afc1e385fe..0721b975ba4 100644 --- a/lib/api/pipelines.rb +++ b/lib/api/pipelines.rb @@ -10,7 +10,7 @@ module API resource :projects do desc 'Get all Pipelines of the project' do detail 'This feature was introduced in GitLab 8.11.' - success Entities::Pipeline + success Entities::PipelineBasic end params do use :pagination @@ -21,7 +21,7 @@ module API authorize! :read_pipeline, user_project pipelines = PipelinesFinder.new(user_project).execute(scope: params[:scope]) - present paginate(pipelines), with: Entities::Pipeline + present paginate(pipelines), with: Entities::PipelineBasic end desc 'Create a new pipeline' do diff --git a/lib/api/projects.rb b/lib/api/projects.rb index f302496c12b..63a4cdd5954 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -46,9 +46,10 @@ module API optional :archived, type: Boolean, default: false, desc: 'Limit by archived status' optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'Limit by visibility' - optional :search, type: String, desc: 'Return list of authorized projects matching the search criteria' + optional :search, type: String, desc: 'Return list of projects matching the search criteria' optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user' optional :starred, type: Boolean, default: false, desc: 'Limit by starred status' + optional :membership, type: Boolean, default: false, desc: 'Limit by projects that the current user is a member of' end params :statistics_params do diff --git a/lib/api/v3/commits.rb b/lib/api/v3/commits.rb index 506204b3517..d254d247042 100644 --- a/lib/api/v3/commits.rb +++ b/lib/api/v3/commits.rb @@ -130,9 +130,7 @@ module API commit_params = { commit: commit, - create_merge_request: false, - source_project: user_project, - source_branch: commit.cherry_pick_branch_name, + start_branch: params[:branch], target_branch: params[:branch] } diff --git a/lib/api/v3/milestones.rb b/lib/api/v3/milestones.rb new file mode 100644 index 00000000000..bbc29c40ee2 --- /dev/null +++ b/lib/api/v3/milestones.rb @@ -0,0 +1,43 @@ +module API + module V3 + class Milestones < Grape::API + include PaginationParams + + before { authenticate! } + + helpers do + def filter_milestones_state(milestones, state) + case state + when 'active' then milestones.active + when 'closed' then milestones.closed + else milestones + end + end + end + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects do + desc 'Get a list of project milestones' do + success ::API::Entities::Milestone + end + params do + optional :state, type: String, values: %w[active closed all], default: 'all', + desc: 'Return "active", "closed", or "all" milestones' + optional :iid, type: Array[Integer], desc: 'The IID of the milestone' + use :pagination + end + get ":id/milestones" do + authorize! :read_milestone, user_project + + milestones = user_project.milestones + milestones = filter_milestones_state(milestones, params[:state]) + milestones = filter_by_iid(milestones, params[:iid]) if params[:iid].present? + + present paginate(milestones), with: ::API::Entities::Milestone + end + end + end + end +end diff --git a/lib/api/v3/pipelines.rb b/lib/api/v3/pipelines.rb new file mode 100644 index 00000000000..2c26a5f7d35 --- /dev/null +++ b/lib/api/v3/pipelines.rb @@ -0,0 +1,36 @@ +module API + module V3 + class Pipelines < Grape::API + include PaginationParams + + before { authenticate! } + + params do + requires :id, type: String, desc: 'The project ID' + end + resource :projects do + desc 'Get all Pipelines of the project' do + detail 'This feature was introduced in GitLab 8.11.' + success ::API::Entities::Pipeline + end + params do + use :pagination + optional :scope, type: String, values: %w(running branches tags), + desc: 'Either running, branches, or tags' + end + get ':id/pipelines' do + authorize! :read_pipeline, user_project + + pipelines = PipelinesFinder.new(user_project).execute(scope: params[:scope]) + present paginate(pipelines), with: ::API::Entities::Pipeline + end + end + + helpers do + def pipeline + @pipeline ||= user_project.pipelines.find(params[:pipeline_id]) + end + end + end + end +end diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb new file mode 100644 index 00000000000..0f24f9bbfde --- /dev/null +++ b/lib/gitlab/etag_caching/middleware.rb @@ -0,0 +1,66 @@ +module Gitlab + module EtagCaching + class Middleware + RESERVED_WORDS = ProjectPathValidator::RESERVED.map { |word| "/#{word}/" }.join('|') + ROUTE_REGEXP = Regexp.union( + %r(^(?!.*(#{RESERVED_WORDS})).*/noteable/issue/\d+/notes\z) + ) + + def initialize(app) + @app = app + end + + def call(env) + return @app.call(env) unless enabled_for_current_route?(env) + Gitlab::Metrics.add_event(:etag_caching_middleware_used) + + etag, cached_value_present = get_etag(env) + if_none_match = env['HTTP_IF_NONE_MATCH'] + + if if_none_match == etag + Gitlab::Metrics.add_event(:etag_caching_cache_hit) + [304, { 'ETag' => etag }, ['']] + else + track_cache_miss(if_none_match, cached_value_present) + + status, headers, body = @app.call(env) + headers['ETag'] = etag + [status, headers, body] + end + end + + private + + def enabled_for_current_route?(env) + ROUTE_REGEXP.match(env['PATH_INFO']) + end + + def get_etag(env) + cache_key = env['PATH_INFO'] + store = Store.new + current_value = store.get(cache_key) + cached_value_present = current_value.present? + + unless cached_value_present + current_value = store.touch(cache_key, only_if_missing: true) + end + + [weak_etag_format(current_value), cached_value_present] + end + + def weak_etag_format(value) + %Q{W/"#{value}"} + end + + def track_cache_miss(if_none_match, cached_value_present) + if if_none_match.blank? + Gitlab::Metrics.add_event(:etag_caching_header_missing) + elsif !cached_value_present + Gitlab::Metrics.add_event(:etag_caching_key_not_found) + else + Gitlab::Metrics.add_event(:etag_caching_resource_changed) + end + end + end + end +end diff --git a/lib/gitlab/etag_caching/store.rb b/lib/gitlab/etag_caching/store.rb new file mode 100644 index 00000000000..9532e432f78 --- /dev/null +++ b/lib/gitlab/etag_caching/store.rb @@ -0,0 +1,32 @@ +module Gitlab + module EtagCaching + class Store + EXPIRY_TIME = 10.minutes + REDIS_NAMESPACE = 'etag:'.freeze + + def get(key) + Gitlab::Redis.with { |redis| redis.get(redis_key(key)) } + end + + def touch(key, only_if_missing: false) + etag = generate_etag + + Gitlab::Redis.with do |redis| + redis.set(redis_key(key), etag, ex: EXPIRY_TIME, nx: only_if_missing) + end + + etag + end + + private + + def generate_etag + SecureRandom.hex + end + + def redis_key(key) + "#{REDIS_NAMESPACE}#{key}" + end + end + end +end diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb index b7f825e8284..823f697f51c 100644 --- a/lib/gitlab/seeder.rb +++ b/lib/gitlab/seeder.rb @@ -1,24 +1,23 @@ +module DeliverNever + def deliver_later + self + end +end + module Gitlab class Seeder def self.quiet mute_mailer SeedFu.quiet = true + yield + SeedFu.quiet = false puts "\nOK".color(:green) end - def self.by_user(user) - yield - end - def self.mute_mailer - code = <<-eos -def Notify.deliver_later - self -end - eos - eval(code) # rubocop:disable Security/Eval + ActionMailer::MessageDelivery.prepend(DeliverNever) end end end diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb index aadc401ff8d..11e5f1b645c 100644 --- a/lib/gitlab/sidekiq_status.rb +++ b/lib/gitlab/sidekiq_status.rb @@ -44,19 +44,42 @@ module Gitlab # Returns true if all the given job have been completed. # - # jids - The Sidekiq job IDs to check. + # job_ids - The Sidekiq job IDs to check. # # Returns true or false. - def self.all_completed?(jids) - keys = jids.map { |jid| key_for(jid) } + def self.all_completed?(job_ids) + self.num_running(job_ids).zero? + end + + # Returns the number of jobs that are running. + # + # job_ids - The Sidekiq job IDs to check. + def self.num_running(job_ids) + responses = self.job_status(job_ids) - responses = Sidekiq.redis do |redis| + responses.select(&:present?).count + end + + # Returns the number of jobs that have completed. + # + # job_ids - The Sidekiq job IDs to check. + def self.num_completed(job_ids) + job_ids.size - self.num_running(job_ids) + end + + # Returns the job status for each of the given job IDs. + # + # job_ids - The Sidekiq job IDs to check. + # + # Returns an array of true or false indicating job completion. + def self.job_status(job_ids) + keys = job_ids.map { |jid| key_for(jid) } + + Sidekiq.redis do |redis| redis.pipelined do keys.each { |key| redis.exists(key) } end end - - responses.all? { |value| !value } end def self.key_for(jid) diff --git a/lib/mattermost/team.rb b/lib/mattermost/team.rb index 09dfd082b3a..afc152aa02e 100644 --- a/lib/mattermost/team.rb +++ b/lib/mattermost/team.rb @@ -1,7 +1,7 @@ module Mattermost class Team < Client def all - session_get('/api/v3/teams/all') + session_get('/api/v3/teams/all').values end end end diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl index 5661394058d..330031aaddc 100644 --- a/lib/support/nginx/gitlab-ssl +++ b/lib/support/nginx/gitlab-ssl @@ -82,6 +82,9 @@ server { ## # ssl_dhparam /etc/ssl/certs/dhparam.pem; + ## [Optional] Enable HTTP Strict Transport Security + # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; + ## Individual nginx logs for this GitLab vhost access_log /var/log/nginx/gitlab_access.log; error_log /var/log/nginx/gitlab_error.log; diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb index cfe18dd4b6c..58c16cc57e6 100644 --- a/spec/controllers/health_check_controller_spec.rb +++ b/spec/controllers/health_check_controller_spec.rb @@ -64,8 +64,8 @@ describe HealthCheckController do context 'when a service is down and an access token is provided' do before do - allow(HealthCheck::Utils).to receive(:process_checks).with('standard').and_return('The server is on fire') - allow(HealthCheck::Utils).to receive(:process_checks).with('email').and_return('Email is on fire') + allow(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire') + allow(HealthCheck::Utils).to receive(:process_checks).with(['email']).and_return('Email is on fire') end it 'supports passing the token in the header' do diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index e70737376af..298a7ff179c 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -244,4 +244,27 @@ describe Projects::BranchesController do end end end + + describe "GET index" do + render_views + + before do + sign_in(user) + end + + context 'when rendering a JSON format' do + it 'filters branches by name' do + get :index, + namespace_id: project.namespace, + project_id: project, + format: :json, + search: 'master' + + parsed_response = JSON.parse(response.body) + + expect(parsed_response.length).to eq 1 + expect(parsed_response.first).to eq 'master' + end + end + end end diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb index 640baa3a01c..b223a22ae60 100644 --- a/spec/controllers/projects/commit_controller_spec.rb +++ b/spec/controllers/projects/commit_controller_spec.rb @@ -166,7 +166,7 @@ describe Projects::CommitController do post(:revert, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: commit.id) expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master') @@ -179,7 +179,7 @@ describe Projects::CommitController do post(:revert, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: commit.id) end @@ -188,7 +188,7 @@ describe Projects::CommitController do post(:revert, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: commit.id) expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, commit.id) @@ -215,7 +215,7 @@ describe Projects::CommitController do post(:cherry_pick, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: master_pickable_commit.id) expect(response).to redirect_to namespace_project_commits_path(project.namespace, project, 'master') @@ -228,7 +228,7 @@ describe Projects::CommitController do post(:cherry_pick, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: master_pickable_commit.id) end @@ -237,7 +237,7 @@ describe Projects::CommitController do post(:cherry_pick, namespace_id: project.namespace, project_id: project, - target_branch: 'master', + start_branch: 'master', id: master_pickable_commit.id) expect(response).to redirect_to namespace_project_commit_path(project.namespace, project, master_pickable_commit.id) diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index 049bae1899d..e0de62e4454 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -30,18 +30,18 @@ describe Projects::GraphsController do double(languages: { 'Ruby' => 1000, 'CoffeeScript' => 350, - 'PowerShell' => 15 + 'NSIS' => 15 }) end let(:expected_values) do - ps_color = "##{Digest::SHA256.hexdigest('PowerShell')[0...6]}" + nsis_color = "##{Digest::SHA256.hexdigest('NSIS')[0...6]}" [ # colors from Linguist: - { label: "Ruby", color: "#701516", highlight: "#701516" }, - { label: "CoffeeScript", color: "#244776", highlight: "#244776" }, + { label: "Ruby", color: "#701516", highlight: "#701516" }, + { label: "CoffeeScript", color: "#244776", highlight: "#244776" }, # colors from SHA256 fallback: - { label: "PowerShell", color: ps_color, highlight: ps_color } + { label: "NSIS", color: nsis_color, highlight: nsis_color } ] end diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index dc597202050..d80780b1d90 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -200,4 +200,31 @@ describe Projects::NotesController do end end end + + describe 'GET index' do + let(:last_fetched_at) { '1487756246' } + let(:request_params) do + { + namespace_id: project.namespace, + project_id: project, + target_type: 'issue', + target_id: issue.id + } + end + + before do + sign_in(user) + project.team << [user, :developer] + end + + it 'passes last_fetched_at from headers to NotesFinder' do + request.headers['X-Last-Fetched-At'] = last_fetched_at + + expect(NotesFinder).to receive(:new) + .with(anything, anything, hash_including(last_fetched_at: last_fetched_at)) + .and_call_original + + get :index, request_params + end + end end diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index a90534d10ba..cabe128acf7 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -76,6 +76,18 @@ FactoryGirl.define do manual end + trait :tags do + tag_list [:docker, :ruby] + end + + trait :on_tag do + tag true + end + + trait :triggered do + trigger_request factory: :ci_trigger_request_with_variables + end + after(:build) do |build, evaluator| build.project = build.pipeline.project end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 324ede798fe..0e305c52358 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -192,7 +192,7 @@ describe 'Commits' do commits = project.repository.commits(branch_name) commits.each do |commit| - expect(page).to have_content("committed #{commit.committed_date}") + expect(page).to have_content("committed #{commit.committed_date.strftime("%b %d, %Y")}") end end end diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb index 038c1641be9..f33bcbb5318 100644 --- a/spec/features/dashboard/archived_projects_spec.rb +++ b/spec/features/dashboard/archived_projects_spec.rb @@ -25,4 +25,19 @@ RSpec.describe 'Dashboard Archived Project', feature: true do expect(page).to have_link(project.name) expect(page).to have_link(archived_project.name) end + + it 'searchs archived projects', :js do + click_button 'Last updated' + click_link 'Show archived projects' + + expect(page).to have_link(project.name) + expect(page).to have_link(archived_project.name) + + fill_in 'project-filter-form-field', with: archived_project.name + + find('#project-filter-form-field').native.send_keys :return + + expect(page).not_to have_link(project.name) + expect(page).to have_link(archived_project.name) + end end diff --git a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb index f2f8f11ab28..0ceaf7bc830 100644 --- a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb +++ b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb @@ -34,7 +34,7 @@ feature 'Merge immediately', :feature, :js do click_link 'Merge Immediately' - expect(find('.js-merge-button')).to have_content('Merge in progress') + expect(find('.js-merge-when-pipeline-succeeds-button')).to have_content('Merge in progress') end end end diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index 4ad944366c8..b575aeff0d8 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -3,8 +3,8 @@ require 'rails_helper' describe 'Merge request', :feature, :js do include WaitForAjax - let(:project) { create(:project) } let(:user) { create(:user) } + let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } before do @@ -31,7 +31,7 @@ describe 'Merge request', :feature, :js do wait_for_ajax - expect(page).to have_selector('.accept_merge_request') + expect(page).to have_selector('.accept-merge-request') end end @@ -51,6 +51,69 @@ describe 'Merge request', :feature, :js do expect(find('.js-environment-link')[:href]).to include(environment.formatted_external_url) end end + + it 'shows green accept merge request button' do + # Wait for the `ci_status` and `merge_check` requests + wait_for_ajax + expect(page).to have_selector('.accept-merge-request.btn-create') + end + end + + context 'view merge request with external CI service' do + before do + create(:service, project: project, + active: true, + type: 'CiService', + category: 'ci') + + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'has danger button while waiting for external CI status' do + # Wait for the `ci_status` and `merge_check` requests + wait_for_ajax + expect(page).to have_selector('.accept-merge-request.btn-danger') + end + end + + context 'view merge request with failed GitLab CI pipelines' do + before do + commit_status = create(:commit_status, project: project, status: 'failed') + pipeline = create(:ci_pipeline, project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + status: 'failed', + statuses: [commit_status]) + create(:ci_build, :pending, pipeline: pipeline) + + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'has danger button when not succeeded' do + # Wait for the `ci_status` and `merge_check` requests + wait_for_ajax + expect(page).to have_selector('.accept-merge-request.btn-danger') + end + end + + context 'view merge request with MWBS button' do + before do + commit_status = create(:commit_status, project: project, status: 'pending') + pipeline = create(:ci_pipeline, project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + status: 'pending', + statuses: [commit_status]) + create(:ci_build, :pending, pipeline: pipeline) + + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'has info button when MWBS button' do + # Wait for the `ci_status` and `merge_check` requests + wait_for_ajax + expect(page).to have_selector('.merge-when-pipeline-succeeds.btn-info') + end end context 'merge error' do diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 406d7cf791c..e63feb14b7e 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -61,4 +61,18 @@ describe 'Profile account page', feature: true do expect(find('#incoming-email-token').value).not_to eq(previous_token) end end + + describe 'when I change my username' do + before do + visit profile_account_path + end + + it 'changes my username' do + fill_in 'user_username', with: 'new-username' + + click_button('Update username') + + expect(page).to have_content('new-username') + end + end end diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb index 7baf7913424..0b972d2a439 100644 --- a/spec/features/projects/commit/cherry_pick_spec.rb +++ b/spec/features/projects/commit/cherry_pick_spec.rb @@ -60,6 +60,7 @@ describe 'Cherry-pick Commits' do click_button 'Cherry-pick' end expect(page).to have_content('The commit has been successfully cherry-picked. You can now submit a merge request to get this change into the original branch.') + expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master") end end diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb new file mode 100644 index 00000000000..df229d0aa78 --- /dev/null +++ b/spec/features/projects/milestones/milestone_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper' + +feature 'Project milestone', :feature do + let(:user) { create(:user) } + let(:project) { create(:empty_project, name: 'test', namespace: user.namespace) } + let(:milestone) { create(:milestone, project: project) } + + before do + login_as(user) + end + + context 'when project has enabled issues' do + before do + visit namespace_project_milestone_path(project.namespace, project, milestone) + end + + it 'shows issues tab' do + within('#content-body') do + expect(page).to have_link 'Issues', href: '#tab-issues' + expect(page).to have_selector '.nav-links li.active', count: 1 + expect(find('.nav-links li.active')).to have_content 'Issues' + end + end + + it 'shows issues stats' do + expect(page).to have_content 'issues:' + end + + it 'shows Browse Issues button' do + within('#content-body') do + expect(page).to have_link 'Browse Issues' + end + end + end + + context 'when project has disabled issues' do + before do + project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) + visit namespace_project_milestone_path(project.namespace, project, milestone) + end + + it 'hides issues tab' do + within('#content-body') do + expect(page).not_to have_link 'Issues', href: '#tab-issues' + expect(page).to have_selector '.nav-links li.active', count: 1 + expect(find('.nav-links li.active')).to have_content 'Merge Requests' + end + end + + it 'hides issues stats' do + expect(page).to have_no_content 'issues:' + end + + it 'hides Browse Issues button' do + within('#content-body') do + expect(page).not_to have_link 'Browse Issues' + end + end + + it 'does not show an informative message' do + expect(page).not_to have_content('Assign some issues to this milestone.') + end + end +end diff --git a/spec/features/projects/services/mattermost_slash_command_spec.rb b/spec/features/projects/services/mattermost_slash_command_spec.rb index f5adb53a2dc..24d22a092d4 100644 --- a/spec/features/projects/services/mattermost_slash_command_spec.rb +++ b/spec/features/projects/services/mattermost_slash_command_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Setup Mattermost slash commands', feature: true do +feature 'Setup Mattermost slash commands', :feature, :js do let(:user) { create(:user) } let(:project) { create(:empty_project) } let(:service) { project.create_mattermost_slash_commands_service } @@ -62,11 +62,11 @@ feature 'Setup Mattermost slash commands', feature: true do click_link 'Add to Mattermost' - team_name = teams.first[1]['display_name'] - select_element = find('select#mattermost_team_id') + team_name = teams.first['display_name'] + select_element = find('#mattermost_team_id') selected_option = select_element.find('option[selected]') - expect(select_element['disabled']).to eq('disabled') + expect(select_element['disabled']).to be(true) expect(selected_option).to have_content(team_name.to_s) end @@ -75,7 +75,7 @@ feature 'Setup Mattermost slash commands', feature: true do click_link 'Add to Mattermost' - expect(find('input#mattermost_team_id', visible: false).value).to eq(teams.first[0].to_s) + expect(find('input#mattermost_team_id', visible: false).value).to eq(teams.first['id']) end it 'shows an explanation user is a member of multiple teams' do @@ -92,12 +92,9 @@ feature 'Setup Mattermost slash commands', feature: true do click_link 'Add to Mattermost' - select_element = find('select#mattermost_team_id') - selected_option = select_element.find('option[selected]') + select_element = find('#mattermost_team_id') - expect(select_element['disabled']).to be(nil) - expect(selected_option).to have_content('Select team...') - # The 'Select team...' placeholder is item `0`. + expect(select_element['disabled']).to be(false) expect(select_element.all('option').count).to eq(3) end @@ -110,20 +107,37 @@ feature 'Setup Mattermost slash commands', feature: true do expect(page).to have_content('test mattermost error message') end + it 'enables the submit button if the required fields are provided', :js do + stub_teams(count: 1) + + click_link 'Add to Mattermost' + + expect(find('input[type="submit"]')['disabled']).not_to be(true) + end + + it 'disables the submit button if the required fields are not provided', :js do + stub_teams(count: 1) + + click_link 'Add to Mattermost' + + fill_in('mattermost_trigger', with: '') + + expect(find('input[type="submit"]')['disabled']).to be(true) + end + def stub_teams(count: 0) teams = create_teams(count) - allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { teams } + allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { [teams, nil] } teams end def create_teams(count = 0) - teams = {} + teams = [] count.times do |i| - i += 1 - teams[i] = { id: i, display_name: i } + teams.push({ "id" => "x#{i}", "display_name" => "x#{i}-name" }) end teams diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 4ffdd530171..5c07ea8a872 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -193,8 +193,8 @@ describe ApplicationHelper do describe 'time_ago_with_tooltip' do def element(*arguments) Time.zone = 'UTC' - time = Time.zone.parse('2015-07-02 08:23') - element = helper.time_ago_with_tooltip(time, *arguments) + @time = Time.zone.parse('2015-07-02 08:23') + element = helper.time_ago_with_tooltip(@time, *arguments) Nokogiri::HTML::DocumentFragment.parse(element).first_element_child end @@ -204,7 +204,7 @@ describe ApplicationHelper do end it 'includes the date string' do - expect(element.text).to eq '2015-07-02 08:23:00 UTC' + expect(element.text).to eq @time.strftime("%b %d, %Y") end it 'has a datetime attribute' do diff --git a/spec/initializers/metrics_spec.rb b/spec/initializers/8_metrics_spec.rb index bb595162370..570754621f3 100644 --- a/spec/initializers/metrics_spec.rb +++ b/spec/initializers/8_metrics_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -require_relative '../../config/initializers/metrics' +require_relative '../../config/initializers/8_metrics' describe 'instrument_classes', lib: true do let(:config) { double(:config) } diff --git a/spec/javascripts/abuse_reports_spec.js.es6 b/spec/javascripts/abuse_reports_spec.js index 76b370b345b..76b370b345b 100644 --- a/spec/javascripts/abuse_reports_spec.js.es6 +++ b/spec/javascripts/abuse_reports_spec.js diff --git a/spec/javascripts/activities_spec.js.es6 b/spec/javascripts/activities_spec.js index e6a6fc36ca1..e6a6fc36ca1 100644 --- a/spec/javascripts/activities_spec.js.es6 +++ b/spec/javascripts/activities_spec.js diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js index 9dd741a680b..9dd741a680b 100644 --- a/spec/javascripts/boards/boards_store_spec.js.es6 +++ b/spec/javascripts/boards/boards_store_spec.js diff --git a/spec/javascripts/boards/issue_card_spec.js.es6 b/spec/javascripts/boards/issue_card_spec.js index 4340a571017..4340a571017 100644 --- a/spec/javascripts/boards/issue_card_spec.js.es6 +++ b/spec/javascripts/boards/issue_card_spec.js diff --git a/spec/javascripts/boards/issue_spec.js.es6 b/spec/javascripts/boards/issue_spec.js index aab4d9c501e..aab4d9c501e 100644 --- a/spec/javascripts/boards/issue_spec.js.es6 +++ b/spec/javascripts/boards/issue_spec.js diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js index c8a18af7198..c8a18af7198 100644 --- a/spec/javascripts/boards/list_spec.js.es6 +++ b/spec/javascripts/boards/list_spec.js diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js index 7a399b307ad..7a399b307ad 100644 --- a/spec/javascripts/boards/mock_data.js.es6 +++ b/spec/javascripts/boards/mock_data.js diff --git a/spec/javascripts/boards/modal_store_spec.js.es6 b/spec/javascripts/boards/modal_store_spec.js index 1815847f3fa..1815847f3fa 100644 --- a/spec/javascripts/boards/modal_store_spec.js.es6 +++ b/spec/javascripts/boards/modal_store_spec.js diff --git a/spec/javascripts/bootstrap_linked_tabs_spec.js.es6 b/spec/javascripts/bootstrap_linked_tabs_spec.js index fa9f95e16cd..fa9f95e16cd 100644 --- a/spec/javascripts/bootstrap_linked_tabs_spec.js.es6 +++ b/spec/javascripts/bootstrap_linked_tabs_spec.js diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js index 0bd50588f5a..0bd50588f5a 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js diff --git a/spec/javascripts/commit/pipelines/mock_data.js.es6 b/spec/javascripts/commit/pipelines/mock_data.js index 188908d66bd..188908d66bd 100644 --- a/spec/javascripts/commit/pipelines/mock_data.js.es6 +++ b/spec/javascripts/commit/pipelines/mock_data.js diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js.es6 b/spec/javascripts/commit/pipelines/pipelines_spec.js index f09c57978a1..f09c57978a1 100644 --- a/spec/javascripts/commit/pipelines/pipelines_spec.js.es6 +++ b/spec/javascripts/commit/pipelines/pipelines_spec.js diff --git a/spec/javascripts/commit/pipelines/pipelines_store_spec.js.es6 b/spec/javascripts/commit/pipelines/pipelines_store_spec.js index 94973419979..94973419979 100644 --- a/spec/javascripts/commit/pipelines/pipelines_store_spec.js.es6 +++ b/spec/javascripts/commit/pipelines/pipelines_store_spec.js diff --git a/spec/javascripts/commits_spec.js.es6 b/spec/javascripts/commits_spec.js index 05260760c43..05260760c43 100644 --- a/spec/javascripts/commits_spec.js.es6 +++ b/spec/javascripts/commits_spec.js diff --git a/spec/javascripts/datetime_utility_spec.js.es6 b/spec/javascripts/datetime_utility_spec.js index d5eec10be42..d5eec10be42 100644 --- a/spec/javascripts/datetime_utility_spec.js.es6 +++ b/spec/javascripts/datetime_utility_spec.js diff --git a/spec/javascripts/diff_comments_store_spec.js.es6 b/spec/javascripts/diff_comments_store_spec.js index f956394ef53..f956394ef53 100644 --- a/spec/javascripts/diff_comments_store_spec.js.es6 +++ b/spec/javascripts/diff_comments_store_spec.js diff --git a/spec/javascripts/environments/environment_actions_spec.js.es6 b/spec/javascripts/environments/environment_actions_spec.js index d50d45d295e..d50d45d295e 100644 --- a/spec/javascripts/environments/environment_actions_spec.js.es6 +++ b/spec/javascripts/environments/environment_actions_spec.js diff --git a/spec/javascripts/environments/environment_external_url_spec.js.es6 b/spec/javascripts/environments/environment_external_url_spec.js index 393dbb5aae0..393dbb5aae0 100644 --- a/spec/javascripts/environments/environment_external_url_spec.js.es6 +++ b/spec/javascripts/environments/environment_external_url_spec.js diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js index 7fea80ed799..7fea80ed799 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js diff --git a/spec/javascripts/environments/environment_rollback_spec.js.es6 b/spec/javascripts/environments/environment_rollback_spec.js index 4a596baad09..4a596baad09 100644 --- a/spec/javascripts/environments/environment_rollback_spec.js.es6 +++ b/spec/javascripts/environments/environment_rollback_spec.js diff --git a/spec/javascripts/environments/environment_spec.js.es6 b/spec/javascripts/environments/environment_spec.js index edd0cad32d0..edd0cad32d0 100644 --- a/spec/javascripts/environments/environment_spec.js.es6 +++ b/spec/javascripts/environments/environment_spec.js diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js index 5ca65b1debc..5ca65b1debc 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js diff --git a/spec/javascripts/environments/environment_table_spec.js.es6 b/spec/javascripts/environments/environment_table_spec.js index be4330b5012..be4330b5012 100644 --- a/spec/javascripts/environments/environment_table_spec.js.es6 +++ b/spec/javascripts/environments/environment_table_spec.js diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js index 77e182b3830..77e182b3830 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js.es6 b/spec/javascripts/environments/folder/environments_folder_view_spec.js index d1335b5b304..d1335b5b304 100644 --- a/spec/javascripts/environments/folder/environments_folder_view_spec.js.es6 +++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js index 5c395c6b2d8..5c395c6b2d8 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js diff --git a/spec/javascripts/extensions/array_spec.js.es6 b/spec/javascripts/extensions/array_spec.js index 60f6b9b78e3..60f6b9b78e3 100644 --- a/spec/javascripts/extensions/array_spec.js.es6 +++ b/spec/javascripts/extensions/array_spec.js diff --git a/spec/javascripts/extensions/element_spec.js.es6 b/spec/javascripts/extensions/element_spec.js index 2d8a128ed33..2d8a128ed33 100644 --- a/spec/javascripts/extensions/element_spec.js.es6 +++ b/spec/javascripts/extensions/element_spec.js diff --git a/spec/javascripts/extensions/object_spec.js.es6 b/spec/javascripts/extensions/object_spec.js index 2467ed78459..2467ed78459 100644 --- a/spec/javascripts/extensions/object_spec.js.es6 +++ b/spec/javascripts/extensions/object_spec.js diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js.es6 b/spec/javascripts/filtered_search/dropdown_user_spec.js index fa9d03c8a9a..fa9d03c8a9a 100644 --- a/spec/javascripts/filtered_search/dropdown_user_spec.js.es6 +++ b/spec/javascripts/filtered_search/dropdown_user_spec.js diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6 b/spec/javascripts/filtered_search/dropdown_utils_spec.js index 1e2d7582d5b..1e2d7582d5b 100644 --- a/spec/javascripts/filtered_search/dropdown_utils_spec.js.es6 +++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js diff --git a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js index ed0b0196ec4..ed0b0196ec4 100644 --- a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js.es6 +++ b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_manager_spec.js index 98959dda242..98959dda242 100644 --- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 +++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js index cf409a7e509..cf409a7e509 100644 --- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6 +++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js index a91801cfc89..a91801cfc89 100644 --- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js.es6 +++ b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js diff --git a/spec/javascripts/gfm_auto_complete_spec.js.es6 b/spec/javascripts/gfm_auto_complete_spec.js index 5dfa4008fbd..5dfa4008fbd 100644 --- a/spec/javascripts/gfm_auto_complete_spec.js.es6 +++ b/spec/javascripts/gfm_auto_complete_spec.js diff --git a/spec/javascripts/gl_dropdown_spec.js.es6 b/spec/javascripts/gl_dropdown_spec.js index c207fb00a47..c207fb00a47 100644 --- a/spec/javascripts/gl_dropdown_spec.js.es6 +++ b/spec/javascripts/gl_dropdown_spec.js diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js index 733023481f5..733023481f5 100644 --- a/spec/javascripts/gl_field_errors_spec.js.es6 +++ b/spec/javascripts/gl_field_errors_spec.js diff --git a/spec/javascripts/gl_form_spec.js.es6 b/spec/javascripts/gl_form_spec.js index 71d6e2a7e22..71d6e2a7e22 100644 --- a/spec/javascripts/gl_form_spec.js.es6 +++ b/spec/javascripts/gl_form_spec.js diff --git a/spec/javascripts/helpers/class_spec_helper.js.es6 b/spec/javascripts/helpers/class_spec_helper.js index 61db27a8fcc..61db27a8fcc 100644 --- a/spec/javascripts/helpers/class_spec_helper.js.es6 +++ b/spec/javascripts/helpers/class_spec_helper.js diff --git a/spec/javascripts/helpers/class_spec_helper_spec.js.es6 b/spec/javascripts/helpers/class_spec_helper_spec.js index 0a61e561640..0a61e561640 100644 --- a/spec/javascripts/helpers/class_spec_helper_spec.js.es6 +++ b/spec/javascripts/helpers/class_spec_helper_spec.js diff --git a/spec/javascripts/issuable_spec.js.es6 b/spec/javascripts/issuable_spec.js index 26d87cc5931..26d87cc5931 100644 --- a/spec/javascripts/issuable_spec.js.es6 +++ b/spec/javascripts/issuable_spec.js diff --git a/spec/javascripts/issuable_time_tracker_spec.js.es6 b/spec/javascripts/issuable_time_tracker_spec.js index cb068a4f879..cb068a4f879 100644 --- a/spec/javascripts/issuable_time_tracker_spec.js.es6 +++ b/spec/javascripts/issuable_time_tracker_spec.js diff --git a/spec/javascripts/labels_issue_sidebar_spec.js.es6 b/spec/javascripts/labels_issue_sidebar_spec.js index 37e038c16da..37e038c16da 100644 --- a/spec/javascripts/labels_issue_sidebar_spec.js.es6 +++ b/spec/javascripts/labels_issue_sidebar_spec.js diff --git a/spec/javascripts/lib/utils/common_utils_spec.js.es6 b/spec/javascripts/lib/utils/common_utils_spec.js index f4d3e77e515..f4d3e77e515 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js.es6 +++ b/spec/javascripts/lib/utils/common_utils_spec.js diff --git a/spec/javascripts/lib/utils/text_utility_spec.js.es6 b/spec/javascripts/lib/utils/text_utility_spec.js index 4200e943121..4200e943121 100644 --- a/spec/javascripts/lib/utils/text_utility_spec.js.es6 +++ b/spec/javascripts/lib/utils/text_utility_spec.js diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js index 7cdade01e00..7cdade01e00 100644 --- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 +++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js diff --git a/spec/javascripts/pipelines_spec.js.es6 b/spec/javascripts/pipelines_spec.js index 72770a702d3..72770a702d3 100644 --- a/spec/javascripts/pipelines_spec.js.es6 +++ b/spec/javascripts/pipelines_spec.js diff --git a/spec/javascripts/pretty_time_spec.js.es6 b/spec/javascripts/pretty_time_spec.js index a4662cfb557..a4662cfb557 100644 --- a/spec/javascripts/pretty_time_spec.js.es6 +++ b/spec/javascripts/pretty_time_spec.js diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js.es6 b/spec/javascripts/signin_tabs_memoizer_spec.js index d83d9a57b42..d83d9a57b42 100644 --- a/spec/javascripts/signin_tabs_memoizer_spec.js.es6 +++ b/spec/javascripts/signin_tabs_memoizer_spec.js diff --git a/spec/javascripts/smart_interval_spec.js.es6 b/spec/javascripts/smart_interval_spec.js index 4366ec2a5b8..4366ec2a5b8 100644 --- a/spec/javascripts/smart_interval_spec.js.es6 +++ b/spec/javascripts/smart_interval_spec.js diff --git a/spec/javascripts/subbable_resource_spec.js.es6 b/spec/javascripts/subbable_resource_spec.js index 454386697f5..454386697f5 100644 --- a/spec/javascripts/subbable_resource_spec.js.es6 +++ b/spec/javascripts/subbable_resource_spec.js diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js index ca707d872a4..fae462561e9 100644 --- a/spec/javascripts/test_bundle.js +++ b/spec/javascripts/test_bundle.js @@ -5,23 +5,12 @@ jasmine.getFixtures().fixturesPath = 'base/spec/javascripts/fixtures'; jasmine.getJSONFixtures().fixturesPath = 'base/spec/javascripts/fixtures'; // include common libraries +require('~/commons/index.js'); window.$ = window.jQuery = require('jquery'); window._ = require('underscore'); window.Cookies = require('js-cookie'); window.Vue = require('vue'); window.Vue.use(require('vue-resource')); -require('jquery-ujs'); -require('bootstrap/js/affix'); -require('bootstrap/js/alert'); -require('bootstrap/js/button'); -require('bootstrap/js/collapse'); -require('bootstrap/js/dropdown'); -require('bootstrap/js/modal'); -require('bootstrap/js/scrollspy'); -require('bootstrap/js/tab'); -require('bootstrap/js/transition'); -require('bootstrap/js/tooltip'); -require('bootstrap/js/popover'); // stub expected globals window.gl = window.gl || {}; diff --git a/spec/javascripts/user_callout_spec.js.es6 b/spec/javascripts/user_callout_spec.js index 205e72af600..205e72af600 100644 --- a/spec/javascripts/user_callout_spec.js.es6 +++ b/spec/javascripts/user_callout_spec.js diff --git a/spec/javascripts/version_check_image_spec.js.es6 b/spec/javascripts/version_check_image_spec.js index 464c1fce210..464c1fce210 100644 --- a/spec/javascripts/version_check_image_spec.js.es6 +++ b/spec/javascripts/version_check_image_spec.js diff --git a/spec/javascripts/visibility_select_spec.js.es6 b/spec/javascripts/visibility_select_spec.js index 9727c03c91e..9727c03c91e 100644 --- a/spec/javascripts/visibility_select_spec.js.es6 +++ b/spec/javascripts/visibility_select_spec.js diff --git a/spec/javascripts/vue_shared/components/commit_spec.js.es6 b/spec/javascripts/vue_shared/components/commit_spec.js index 15ab10b9b69..15ab10b9b69 100644 --- a/spec/javascripts/vue_shared/components/commit_spec.js.es6 +++ b/spec/javascripts/vue_shared/components/commit_spec.js diff --git a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js.es6 b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js index 412abfd5e41..412abfd5e41 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js.es6 +++ b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js diff --git a/spec/javascripts/vue_shared/components/pipelines_table_spec.js.es6 b/spec/javascripts/vue_shared/components/pipelines_table_spec.js index 54d81e2ea7d..54d81e2ea7d 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_spec.js.es6 +++ b/spec/javascripts/vue_shared/components/pipelines_table_spec.js diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js.es6 b/spec/javascripts/vue_shared/components/table_pagination_spec.js index 9cb067921a7..9cb067921a7 100644 --- a/spec/javascripts/vue_shared/components/table_pagination_spec.js.es6 +++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js diff --git a/spec/lib/gitlab/etag_caching/middleware_spec.rb b/spec/lib/gitlab/etag_caching/middleware_spec.rb new file mode 100644 index 00000000000..8b5bfc4dbb0 --- /dev/null +++ b/spec/lib/gitlab/etag_caching/middleware_spec.rb @@ -0,0 +1,163 @@ +require 'spec_helper' + +describe Gitlab::EtagCaching::Middleware do + let(:app) { double(:app) } + let(:middleware) { described_class.new(app) } + let(:app_status_code) { 200 } + let(:if_none_match) { nil } + let(:enabled_path) { '/gitlab-org/gitlab-ce/noteable/issue/1/notes' } + + context 'when ETag caching is not enabled for current route' do + let(:path) { '/gitlab-org/gitlab-ce/tree/master/noteable/issue/1/notes' } + + before do + mock_app_response + end + + it 'does not add ETag header' do + _, headers, _ = middleware.call(build_env(path, if_none_match)) + + expect(headers['ETag']).to be_nil + end + + it 'passes status code from app' do + status, _, _ = middleware.call(build_env(path, if_none_match)) + + expect(status).to eq app_status_code + end + end + + context 'when there is no ETag in store for given resource' do + let(:path) { enabled_path } + + before do + mock_app_response + mock_value_in_store(nil) + end + + it 'generates ETag' do + expect_any_instance_of(Gitlab::EtagCaching::Store) + .to receive(:touch).and_return('123') + + middleware.call(build_env(path, if_none_match)) + end + + context 'when If-None-Match header was specified' do + let(:if_none_match) { 'W/"abc"' } + + it 'tracks "etag_caching_key_not_found" event' do + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_middleware_used) + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_key_not_found) + + middleware.call(build_env(path, if_none_match)) + end + end + end + + context 'when there is ETag in store for given resource' do + let(:path) { enabled_path } + + before do + mock_app_response + mock_value_in_store('123') + end + + it 'returns this value as header' do + _, headers, _ = middleware.call(build_env(path, if_none_match)) + + expect(headers['ETag']).to eq 'W/"123"' + end + end + + context 'when If-None-Match header matches ETag in store' do + let(:path) { enabled_path } + let(:if_none_match) { 'W/"123"' } + + before do + mock_value_in_store('123') + end + + it 'does not call app' do + expect(app).not_to receive(:call) + + middleware.call(build_env(path, if_none_match)) + end + + it 'returns status code 304' do + status, _, _ = middleware.call(build_env(path, if_none_match)) + + expect(status).to eq 304 + end + + it 'tracks "etag_caching_cache_hit" event' do + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_middleware_used) + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_cache_hit) + + middleware.call(build_env(path, if_none_match)) + end + end + + context 'when If-None-Match header does not match ETag in store' do + let(:path) { enabled_path } + let(:if_none_match) { 'W/"abc"' } + + before do + mock_value_in_store('123') + end + + it 'calls app' do + expect(app).to receive(:call).and_return([app_status_code, {}, ['body']]) + + middleware.call(build_env(path, if_none_match)) + end + + it 'tracks "etag_caching_resource_changed" event' do + mock_app_response + + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_middleware_used) + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_resource_changed) + + middleware.call(build_env(path, if_none_match)) + end + end + + context 'when If-None-Match header is not specified' do + let(:path) { enabled_path } + + before do + mock_value_in_store('123') + mock_app_response + end + + it 'tracks "etag_caching_header_missing" event' do + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_middleware_used) + expect(Gitlab::Metrics).to receive(:add_event) + .with(:etag_caching_header_missing) + + middleware.call(build_env(path, if_none_match)) + end + end + + def mock_app_response + allow(app).to receive(:call).and_return([app_status_code, {}, ['body']]) + end + + def mock_value_in_store(value) + allow_any_instance_of(Gitlab::EtagCaching::Store) + .to receive(:get).and_return(value) + end + + def build_env(path, if_none_match) + { + 'PATH_INFO' => path, + 'HTTP_IF_NONE_MATCH' => if_none_match + } + end +end diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb index 0aa36a3416b..56f06b61afb 100644 --- a/spec/lib/gitlab/sidekiq_status_spec.rb +++ b/spec/lib/gitlab/sidekiq_status_spec.rb @@ -39,6 +39,32 @@ describe Gitlab::SidekiqStatus do end end + describe '.num_running', :redis do + it 'returns 0 if all jobs have been completed' do + expect(described_class.num_running(%w(123))).to eq(0) + end + + it 'returns 2 if two jobs are still running' do + described_class.set('123') + described_class.set('456') + + expect(described_class.num_running(%w(123 456 789))).to eq(2) + end + end + + describe '.num_completed', :redis do + it 'returns 1 if all jobs have been completed' do + expect(described_class.num_completed(%w(123))).to eq(1) + end + + it 'returns 1 if a job has not yet been completed' do + described_class.set('123') + described_class.set('456') + + expect(described_class.num_completed(%w(123 456 789))).to eq(1) + end + end + describe '.key_for' do it 'returns the key for a job ID' do key = described_class.key_for('123') diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb index 6a9c7cebfff..ac493fdb20f 100644 --- a/spec/lib/mattermost/team_spec.rb +++ b/spec/lib/mattermost/team_spec.rb @@ -13,7 +13,7 @@ describe Mattermost::Team do context 'for valid request' do let(:response) do - [{ + { "xiyro8huptfhdndadpz8r3wnbo" => { "id" => "xiyro8huptfhdndadpz8r3wnbo", "create_at" => 1482174222155, "update_at" => 1482174222155, @@ -26,7 +26,7 @@ describe Mattermost::Team do "allowed_domains" => "", "invite_id" => "o4utakb9jtb7imctdfzbf9r5ro", "allow_open_invite" => false - }] + } } end before do @@ -39,7 +39,7 @@ describe Mattermost::Team do end it 'returns a token' do - is_expected.to eq(response) + is_expected.to eq(response.values) end end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 1cde9e04951..33536487c41 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -387,4 +387,16 @@ describe Note, models: true do end end end + + describe 'expiring ETag cache' do + let(:note) { build(:note_on_issue) } + + it "expires cache for note's issue when note is saved" do + expect_any_instance_of(Gitlab::EtagCaching::Store) + .to receive(:touch) + .with("/#{note.project.namespace.to_param}/#{note.project.to_param}/noteable/issue/#{note.noteable.id}/notes") + + note.save! + end + end end diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index 24356447fed..585c899cdf9 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -163,6 +163,12 @@ describe KubernetesService, models: true, caching: true do { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true } ) end + + it 'sets KUBE_CA_PEM_FILE' do + expect(subject.predefined_variables).to include( + { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true } + ) + end end describe '#terminals' do diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb index 598ff232c82..f9531be5d25 100644 --- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb +++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb @@ -92,7 +92,7 @@ describe MattermostSlashCommandsService, :models do to_return( status: 200, headers: { 'Content-Type' => 'application/json' }, - body: ['list'].to_json + body: { 'list' => true }.to_json ) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index ae203fada12..eb992e1354e 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1112,16 +1112,16 @@ describe Repository, models: true do let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') } context 'when there is a conflict' do - it 'aborts the operation' do - expect(repository.revert(user, new_image_commit, 'master')).to eq(false) + it 'raises an error' do + expect { repository.revert(user, new_image_commit, 'master') }.to raise_error(/Failed to/) end end context 'when commit was already reverted' do - it 'aborts the operation' do + it 'raises an error' do repository.revert(user, update_image_commit, 'master') - expect(repository.revert(user, update_image_commit, 'master')).to eq(false) + expect { repository.revert(user, update_image_commit, 'master') }.to raise_error(/Failed to/) end end @@ -1148,16 +1148,16 @@ describe Repository, models: true do let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') } context 'when there is a conflict' do - it 'aborts the operation' do - expect(repository.cherry_pick(user, conflict_commit, 'master')).to eq(false) + it 'raises an error' do + expect { repository.cherry_pick(user, conflict_commit, 'master') }.to raise_error(/Failed to/) end end context 'when commit was already cherry-picked' do - it 'aborts the operation' do + it 'raises an error' do repository.cherry_pick(user, pickable_commit, 'master') - expect(repository.cherry_pick(user, pickable_commit, 'master')).to eq(false) + expect { repository.cherry_pick(user, pickable_commit, 'master') }.to raise_error(/Failed to/) end end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index 570651165ea..78c230117b8 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -45,8 +45,37 @@ describe API::Milestones, api: true do expect(json_response.first['id']).to eq(closed_milestone.id) end - it 'returns a project milestone by iid' do - get api("/projects/#{project.id}/milestones?iid=#{closed_milestone.iid}", user) + it 'returns an array of milestones specified by iids' do + other_milestone = create(:milestone, project: project) + + get api("/projects/#{project.id}/milestones", user), iids: [closed_milestone.iid, other_milestone.iid] + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.map{ |m| m['id'] }).to match_array([closed_milestone.id, other_milestone.id]) + end + + it 'does not return any milestone if none found' do + get api("/projects/#{project.id}/milestones", user), iids: [Milestone.maximum(:iid).succ] + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) + end + end + + describe 'GET /projects/:id/milestones/:milestone_id' do + it 'returns a project milestone by id' do + get api("/projects/#{project.id}/milestones/#{milestone.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['title']).to eq(milestone.title) + expect(json_response['iid']).to eq(milestone.iid) + end + + it 'returns a project milestone by iids array' do + get api("/projects/#{project.id}/milestones?iids=#{closed_milestone.iid}", user) expect(response.status).to eq 200 expect(response).to include_pagination_headers @@ -56,16 +85,6 @@ describe API::Milestones, api: true do expect(json_response.first['id']).to eq closed_milestone.id end - it 'returns a project milestone by iid array' do - get api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid] - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response.size).to eq(2) - expect(json_response.first['title']).to eq milestone.title - expect(json_response.first['id']).to eq milestone.id - end - it 'returns a project milestone by searching for title' do get api("/projects/#{project.id}/milestones", user), search: 'version2' diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 98d004b572e..51af999b455 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -24,6 +24,7 @@ describe API::Pipelines, api: true do expect(json_response).to be_an Array expect(json_response.first['sha']).to match /\A\h{40}\z/ expect(json_response.first['id']).to eq pipeline.id + expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status]) end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 2e8b557e9e2..03cae074803 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -43,9 +43,10 @@ describe API::Projects, api: true do describe 'GET /projects' do shared_examples_for 'projects response' do it 'returns an array of projects' do - get api('/projects', current_user) + get api('/projects', current_user), filter expect(response).to have_http_status(200) + expect(response).to include_pagination_headers expect(json_response).to be_an Array expect(json_response.map { |p| p['id'] }).to contain_exactly(*projects.map(&:id)) end @@ -61,6 +62,7 @@ describe API::Projects, api: true do context 'when unauthenticated' do it_behaves_like 'projects response' do + let(:filter) { {} } let(:current_user) { nil } let(:projects) { [public_project] } end @@ -68,6 +70,7 @@ describe API::Projects, api: true do context 'when authenticated as regular user' do it_behaves_like 'projects response' do + let(:filter) { {} } let(:current_user) { user } let(:projects) { [public_project, project, project2, project3] } end @@ -133,13 +136,18 @@ describe API::Projects, api: true do end context 'and using search' do - it 'returns searched project' do - get api('/projects', user), { search: project.name } + it_behaves_like 'projects response' do + let(:filter) { { search: project.name } } + let(:current_user) { user } + let(:projects) { [project] } + end + end - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.length).to eq(1) + context 'and membership=true' do + it_behaves_like 'projects response' do + let(:filter) { { membership: true } } + let(:current_user) { user } + let(:projects) { [project, project2, project3] } end end @@ -216,36 +224,52 @@ describe API::Projects, api: true do end context 'and with all query parameters' do - # | | project5 | project6 | project7 | project8 | project9 | - # |---------+----------+----------+----------+----------+----------| - # | search | x | | x | x | x | - # | starred | x | x | | x | x | - # | public | x | x | x | | x | - # | owned | x | x | x | x | | - let!(:project5) { create(:empty_project, :public, path: 'gitlab5', namespace: user.namespace) } + let!(:project5) { create(:empty_project, :public, path: 'gitlab5', namespace: create(:namespace)) } let!(:project6) { create(:empty_project, :public, path: 'project6', namespace: user.namespace) } let!(:project7) { create(:empty_project, :public, path: 'gitlab7', namespace: user.namespace) } let!(:project8) { create(:empty_project, path: 'gitlab8', namespace: user.namespace) } let!(:project9) { create(:empty_project, :public, path: 'gitlab9') } before do - user.update_attributes(starred_projects: [project5, project6, project8, project9]) + user.update_attributes(starred_projects: [project5, project7, project8, project9]) end - it 'returns only projects that satify all query parameters' do - get api('/projects', user), { visibility: 'public', owned: true, starred: true, search: 'gitlab' } + context 'including owned filter' do + it 'returns only projects that satisfy all query parameters' do + get api('/projects', user), { visibility: 'public', owned: true, starred: true, search: 'gitlab' } - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['id']).to eq(project5.id) + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + expect(json_response.first['id']).to eq(project7.id) + end + end + + context 'including membership filter' do + before do + create(:project_member, + user: user, + project: project5, + access_level: ProjectMember::MASTER) + end + + it 'returns only projects that satisfy all query parameters' do + get api('/projects', user), { visibility: 'public', membership: true, starred: true, search: 'gitlab' } + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(2) + expect(json_response.map { |project| project['id'] }).to contain_exactly(project5.id, project7.id) + end end end end context 'when authenticated as a different user' do it_behaves_like 'projects response' do + let(:filter) { {} } let(:current_user) { user2 } let(:projects) { [public_project] } end @@ -253,6 +277,7 @@ describe API::Projects, api: true do context 'when authenticated as admin' do it_behaves_like 'projects response' do + let(:filter) { {} } let(:current_user) { admin } let(:projects) { Project.all } end diff --git a/spec/requests/api/v3/milestones_spec.rb b/spec/requests/api/v3/milestones_spec.rb new file mode 100644 index 00000000000..77705d8c839 --- /dev/null +++ b/spec/requests/api/v3/milestones_spec.rb @@ -0,0 +1,232 @@ +require 'spec_helper' + +describe API::V3::Milestones, api: true do + include ApiHelpers + let(:user) { create(:user) } + let!(:project) { create(:empty_project, namespace: user.namespace ) } + let!(:closed_milestone) { create(:closed_milestone, project: project) } + let!(:milestone) { create(:milestone, project: project) } + + before { project.team << [user, :developer] } + + describe 'GET /projects/:id/milestones' do + it 'returns project milestones' do + get v3_api("/projects/#{project.id}/milestones", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(milestone.title) + end + + it 'returns a 401 error if user not authenticated' do + get v3_api("/projects/#{project.id}/milestones") + + expect(response).to have_http_status(401) + end + + it 'returns an array of active milestones' do + get v3_api("/projects/#{project.id}/milestones?state=active", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(milestone.id) + end + + it 'returns an array of closed milestones' do + get v3_api("/projects/#{project.id}/milestones?state=closed", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(closed_milestone.id) + end + end + + describe 'GET /projects/:id/milestones/:milestone_id' do + it 'returns a project milestone by id' do + get v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['title']).to eq(milestone.title) + expect(json_response['iid']).to eq(milestone.iid) + end + + it 'returns a project milestone by iid' do + get v3_api("/projects/#{project.id}/milestones?iid=#{closed_milestone.iid}", user) + + expect(response.status).to eq 200 + expect(json_response.size).to eq(1) + expect(json_response.first['title']).to eq closed_milestone.title + expect(json_response.first['id']).to eq closed_milestone.id + end + + it 'returns a project milestone by iid array' do + get v3_api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid] + + expect(response).to have_http_status(200) + expect(json_response.size).to eq(2) + expect(json_response.first['title']).to eq milestone.title + expect(json_response.first['id']).to eq milestone.id + end + + it 'returns 401 error if user not authenticated' do + get v3_api("/projects/#{project.id}/milestones/#{milestone.id}") + + expect(response).to have_http_status(401) + end + + it 'returns a 404 error if milestone id not found' do + get v3_api("/projects/#{project.id}/milestones/1234", user) + + expect(response).to have_http_status(404) + end + end + + describe 'POST /projects/:id/milestones' do + it 'creates a new project milestone' do + post v3_api("/projects/#{project.id}/milestones", user), title: 'new milestone' + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq('new milestone') + expect(json_response['description']).to be_nil + end + + it 'creates a new project milestone with description and dates' do + post v3_api("/projects/#{project.id}/milestones", user), + title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02' + + expect(response).to have_http_status(201) + expect(json_response['description']).to eq('release') + expect(json_response['due_date']).to eq('2013-03-02') + expect(json_response['start_date']).to eq('2013-02-02') + end + + it 'returns a 400 error if title is missing' do + post v3_api("/projects/#{project.id}/milestones", user) + + expect(response).to have_http_status(400) + end + + it 'returns a 400 error if params are invalid (duplicate title)' do + post v3_api("/projects/#{project.id}/milestones", user), + title: milestone.title, description: 'release', due_date: '2013-03-02' + + expect(response).to have_http_status(400) + end + + it 'creates a new project with reserved html characters' do + post v3_api("/projects/#{project.id}/milestones", user), title: 'foo & bar 1.1 -> 2.2' + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq('foo & bar 1.1 -> 2.2') + expect(json_response['description']).to be_nil + end + end + + describe 'PUT /projects/:id/milestones/:milestone_id' do + it 'updates a project milestone' do + put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user), + title: 'updated title' + + expect(response).to have_http_status(200) + expect(json_response['title']).to eq('updated title') + end + + it 'removes a due date if nil is passed' do + milestone.update!(due_date: "2016-08-05") + + put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user), due_date: nil + + expect(response).to have_http_status(200) + expect(json_response['due_date']).to be_nil + end + + it 'returns a 404 error if milestone id not found' do + put v3_api("/projects/#{project.id}/milestones/1234", user), + title: 'updated title' + + expect(response).to have_http_status(404) + end + end + + describe 'PUT /projects/:id/milestones/:milestone_id to close milestone' do + it 'updates a project milestone' do + put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user), + state_event: 'close' + expect(response).to have_http_status(200) + + expect(json_response['state']).to eq('closed') + end + end + + describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do + it 'creates an activity event when an milestone is closed' do + expect(Event).to receive(:create) + + put v3_api("/projects/#{project.id}/milestones/#{milestone.id}", user), + state_event: 'close' + end + end + + describe 'GET /projects/:id/milestones/:milestone_id/issues' do + before do + milestone.issues << create(:issue, project: project) + end + it 'returns project issues for a particular milestone' do + get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['milestone']['title']).to eq(milestone.title) + end + + it 'returns a 401 error if user not authenticated' do + get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues") + + expect(response).to have_http_status(401) + end + + describe 'confidential issues' do + let(:public_project) { create(:empty_project, :public) } + let(:milestone) { create(:milestone, project: public_project) } + let(:issue) { create(:issue, project: public_project) } + let(:confidential_issue) { create(:issue, confidential: true, project: public_project) } + + before do + public_project.team << [user, :developer] + milestone.issues << issue << confidential_issue + end + + it 'returns confidential issues to team members' do + get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(2) + expect(json_response.map { |issue| issue['id'] }).to include(issue.id, confidential_issue.id) + end + + it 'does not return confidential issues to team members with guest role' do + member = create(:user) + project.team << [member, :guest] + + get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", member) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + expect(json_response.map { |issue| issue['id'] }).to include(issue.id) + end + + it 'does not return confidential issues to regular users' do + get v3_api("/projects/#{public_project.id}/milestones/#{milestone.id}/issues", create(:user)) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + expect(json_response.map { |issue| issue['id'] }).to include(issue.id) + end + end + end +end diff --git a/spec/requests/api/v3/pipelines_spec.rb b/spec/requests/api/v3/pipelines_spec.rb new file mode 100644 index 00000000000..3786eb06932 --- /dev/null +++ b/spec/requests/api/v3/pipelines_spec.rb @@ -0,0 +1,203 @@ +require 'spec_helper' + +describe API::V3::Pipelines, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:non_member) { create(:user) } + let(:project) { create(:project, :repository, creator: user) } + + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + before { project.team << [user, :master] } + + shared_examples 'a paginated resources' do + before do + # Fires the request + request + end + + it 'has pagination headers' do + expect(response).to include_pagination_headers + end + end + + describe 'GET /projects/:id/pipelines ' do + it_behaves_like 'a paginated resources' do + let(:request) { get v3_api("/projects/#{project.id}/pipelines", user) } + end + + context 'authorized user' do + it 'returns project pipelines' do + get v3_api("/projects/#{project.id}/pipelines", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['sha']).to match(/\A\h{40}\z/) + expect(json_response.first['id']).to eq pipeline.id + expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status before_sha tag yaml_errors user created_at updated_at started_at finished_at committed_at duration coverage]) + end + end + + context 'unauthorized user' do + it 'does not return project pipelines' do + get v3_api("/projects/#{project.id}/pipelines", non_member) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + expect(json_response).not_to be_an Array + end + end + end + + describe 'POST /projects/:id/pipeline ' do + context 'authorized user' do + context 'with gitlab-ci.yml' do + before { stub_ci_pipeline_to_return_yaml_file } + + it 'creates and returns a new pipeline' do + expect do + post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch + end.to change { Ci::Pipeline.count }.by(1) + + expect(response).to have_http_status(201) + expect(json_response).to be_a Hash + expect(json_response['sha']).to eq project.commit.id + end + + it 'fails when using an invalid ref' do + post v3_api("/projects/#{project.id}/pipeline", user), ref: 'invalid_ref' + + expect(response).to have_http_status(400) + expect(json_response['message']['base'].first).to eq 'Reference not found' + expect(json_response).not_to be_an Array + end + end + + context 'without gitlab-ci.yml' do + it 'fails to create pipeline' do + post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch + + expect(response).to have_http_status(400) + expect(json_response['message']['base'].first).to eq 'Missing .gitlab-ci.yml file' + expect(json_response).not_to be_an Array + end + end + end + + context 'unauthorized user' do + it 'does not create pipeline' do + post v3_api("/projects/#{project.id}/pipeline", non_member), ref: project.default_branch + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + expect(json_response).not_to be_an Array + end + end + end + + describe 'GET /projects/:id/pipelines/:pipeline_id' do + context 'authorized user' do + it 'returns project pipelines' do + get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['sha']).to match /\A\h{40}\z/ + end + + it 'returns 404 when it does not exist' do + get v3_api("/projects/#{project.id}/pipelines/123456", user) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Not found' + expect(json_response['id']).to be nil + end + + context 'with coverage' do + before do + create(:ci_build, coverage: 30, pipeline: pipeline) + end + + it 'exposes the coverage' do + get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user) + + expect(json_response["coverage"].to_i).to eq(30) + end + end + end + + context 'unauthorized user' do + it 'should not return a project pipeline' do + get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + expect(json_response['id']).to be nil + end + end + end + + describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do + context 'authorized user' do + let!(:pipeline) do + create(:ci_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + let!(:build) { create(:ci_build, :failed, pipeline: pipeline) } + + it 'retries failed builds' do + expect do + post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", user) + end.to change { pipeline.builds.count }.from(1).to(2) + + expect(response).to have_http_status(201) + expect(build.reload.retried?).to be true + end + end + + context 'unauthorized user' do + it 'should not return a project pipeline' do + post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", non_member) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + expect(json_response['id']).to be nil + end + end + end + + describe 'POST /projects/:id/pipelines/:pipeline_id/cancel' do + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: project.commit.id, + ref: project.default_branch) + end + + let!(:build) { create(:ci_build, :running, pipeline: pipeline) } + + context 'authorized user' do + it 'retries failed builds' do + post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user) + + expect(response).to have_http_status(200) + expect(json_response['status']).to eq('canceled') + end + end + + context 'user without proper access rights' do + let!(:reporter) { create(:user) } + + before { project.team << [reporter, :reporter] } + + it 'rejects the action' do + post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", reporter) + + expect(response).to have_http_status(403) + expect(pipeline.reload.status).to eq('pending') + end + end + end +end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index a5bc62ef6c2..d31f1bdfb7c 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -431,12 +431,22 @@ describe 'project routing' do end end - # project_notes GET /:project_id/notes(.:format) notes#index - # POST /:project_id/notes(.:format) notes#create - # project_note DELETE /:project_id/notes/:id(.:format) notes#destroy + # project_noteable_notes GET /:project_id/noteable/:target_type/:target_id/notes notes#index + # POST /:project_id/notes(.:format) notes#create + # project_note DELETE /:project_id/notes/:id(.:format) notes#destroy describe Projects::NotesController, 'routing' do + it 'to #index' do + expect(get('/gitlab/gitlabhq/noteable/issue/1/notes')).to route_to( + 'projects/notes#index', + namespace_id: 'gitlab', + project_id: 'gitlabhq', + target_type: 'issue', + target_id: '1' + ) + end + it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :create, :destroy] } + let(:actions) { [:create, :destroy] } let(:controller) { 'notes' } end end diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb index d03f7505eac..65af4e13118 100644 --- a/spec/services/ci/retry_build_service_spec.rb +++ b/spec/services/ci/retry_build_service_spec.rb @@ -10,22 +10,39 @@ describe Ci::RetryBuildService, :services do described_class.new(project, user) end + CLONE_ACCESSORS = described_class::CLONE_ACCESSORS + + REJECT_ACCESSORS = + %i[id status user token coverage trace runner artifacts_expire_at + artifacts_file artifacts_metadata artifacts_size created_at + updated_at started_at finished_at queued_at erased_by + erased_at].freeze + + IGNORE_ACCESSORS = + %i[type lock_version target_url gl_project_id deploy job_id base_tags + commit_id deployments erased_by_id last_deployment project_id + runner_id tag_taggings taggings tags trigger_request_id + user_id].freeze + shared_examples 'build duplication' do let(:build) do - create(:ci_build, :failed, :artifacts_expired, :erased, :trace, - :queued, :coverage, pipeline: pipeline) + create(:ci_build, :failed, :artifacts_expired, :erased, + :queued, :coverage, :tags, :allowed_to_fail, :on_tag, + :teardown_environment, :triggered, :trace, + description: 'some build', pipeline: pipeline) end - describe 'clone attributes' do - described_class::CLONE_ATTRIBUTES.each do |attribute| + describe 'clone accessors' do + CLONE_ACCESSORS.each do |attribute| it "clones #{attribute} build attribute" do + expect(new_build.send(attribute)).to be_present expect(new_build.send(attribute)).to eq build.send(attribute) end end end - describe 'reject attributes' do - described_class::REJECT_ATTRIBUTES.each do |attribute| + describe 'reject acessors' do + REJECT_ACCESSORS.each do |attribute| it "does not clone #{attribute} build attribute" do expect(new_build.send(attribute)).not_to eq build.send(attribute) end @@ -33,12 +50,20 @@ describe Ci::RetryBuildService, :services do end it 'has correct number of known attributes' do - attributes = - described_class::CLONE_ATTRIBUTES + - described_class::IGNORE_ATTRIBUTES + - described_class::REJECT_ATTRIBUTES + known_accessors = CLONE_ACCESSORS + REJECT_ACCESSORS + IGNORE_ACCESSORS + + # :tag_list is a special case, this accessor does not exist + # in reflected associations, comes from `act_as_taggable` and + # we use it to copy tags, instead of reusing tags. + # + current_accessors = + Ci::Build.attribute_names.map(&:to_sym) + + Ci::Build.reflect_on_all_associations.map(&:name) + + [:tag_list] + + current_accessors.uniq! - expect(build.attributes.size).to eq(attributes.size) + expect(known_accessors).to contain_exactly(*current_accessors) end end diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index 411b22a0fb8..f75fdd9e03f 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -26,6 +26,28 @@ describe Projects::UpdatePagesService do build.update_attributes(artifacts_metadata: metadata) end + describe 'pages artifacts' do + context 'with expiry date' do + before do + build.artifacts_expire_in = "2 days" + end + + it "doesn't delete artifacts" do + expect(execute).to eq(:success) + + expect(build.reload.artifacts_file?).to eq(true) + end + end + + context 'without expiry date' do + it "does delete artifacts" do + expect(execute).to eq(:success) + + expect(build.reload.artifacts_file?).to eq(false) + end + end + end + it 'succeeds' do expect(project.pages_deployed?).to be_falsey expect(execute).to eq(:success) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 1f2ec9eacf0..36a17a3bf2e 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -418,45 +418,6 @@ describe SystemNoteService, services: true do to be_truthy end end - - context 'when noteable is an Issue' do - let(:issue) { create(:issue, project: project) } - - it 'is truthy when issue is closed' do - issue.close - - expect(described_class.cross_reference_disallowed?(issue, project.commit)). - to be_truthy - end - - it 'is falsey when issue is open' do - expect(described_class.cross_reference_disallowed?(issue, project.commit)). - to be_falsy - end - end - - context 'when noteable is a Merge Request' do - let(:merge_request) { create(:merge_request, :simple, source_project: project) } - - it 'is truthy when merge request is closed' do - allow(merge_request).to receive(:closed?).and_return(:true) - - expect(described_class.cross_reference_disallowed?(merge_request, project.commit)). - to be_truthy - end - - it 'is truthy when merge request is merged' do - allow(merge_request).to receive(:closed?).and_return(:true) - - expect(described_class.cross_reference_disallowed?(merge_request, project.commit)). - to be_truthy - end - - it 'is falsey when merge request is open' do - expect(described_class.cross_reference_disallowed?(merge_request, project.commit)). - to be_falsy - end - end end describe '.cross_reference_exists?' do |