diff options
66 files changed, 975 insertions, 254 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index 293f61fb725..14840ddd262 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -31,6 +31,78 @@ Style/MutableConstant: - 'ee/db/post_migrate/**/*' - 'ee/db/geo/migrate/**/*' +Naming/FileName: + ExpectMatchingDefinition: true + Exclude: + - 'spec/**/*' + - 'features/**/*' + - 'ee/spec/**/*' + - 'qa/spec/**/*' + - 'qa/qa/specs/**/*' + - 'qa/bin/*' + - 'config/**/*' + - 'lib/generators/**/*' + - 'ee/lib/generators/**/*' + IgnoreExecutableScripts: true + AllowedAcronyms: + - EE + - JSON + - LDAP + - IO + - HMAC + - QA + - ENV + - STL + - PDF + - SVG + - CTE + - DN + - RSA + - CI + - CD + - OAuth + # default ones: + - CLI + - DSL + - ACL + - API + - ASCII + - CPU + - CSS + - DNS + - EOF + - GUID + - HTML + - HTTP + - HTTPS + - ID + - IP + - JSON + - LHS + - QPS + - RAM + - RHS + - RPC + - SLA + - SMTP + - SQL + - SSH + - TCP + - TLS + - TTL + - UDP + - UI + - UID + - UUID + - URI + - URL + - UTF8 + - VM + - XML + - XMPP + - XSRF + - XSS + # Gitlab ################################################################### Gitlab/ModuleWithInstanceVariables: diff --git a/PROCESS.md b/PROCESS.md index 5ae191840ff..f206506f7c5 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -53,7 +53,7 @@ Below we describe the contributing process to GitLab for two reasons: Several people from the [GitLab team][team] are helping community members to get their contributions accepted by meeting our [Definition of done][done]. -What you can expect from them is described at https://about.gitlab.com/jobs/merge-request-coach/. +What you can expect from them is described at https://about.gitlab.com/roles/merge-request-coach/. ## Assigning issues @@ -202,6 +202,9 @@ you can ask for an exception to be made. Go to [Release tasks issue tracker](https://gitlab.com/gitlab-org/release/tasks/issues/new) and create an issue using the `Exception-request` issue template. +**Do not** set the relevant `Pick into X.Y` label (see above) before request an +exception; this should be done after the exception is approved. + You can find who is who on the [team page](https://about.gitlab.com/team/). Whether an exception is made is determined by weighing the benefit and urgency of the change diff --git a/app/assets/javascripts/pipelines/components/nav_controls.vue b/app/assets/javascripts/pipelines/components/nav_controls.vue index 383ab51fe56..eba5678e3e5 100644 --- a/app/assets/javascripts/pipelines/components/nav_controls.vue +++ b/app/assets/javascripts/pipelines/components/nav_controls.vue @@ -1,6 +1,11 @@ <script> + import LoadingButton from '../../vue_shared/components/loading_button.vue'; + export default { name: 'PipelineNavControls', + components: { + LoadingButton, + }, props: { newPipelinePath: { type: String, @@ -19,6 +24,17 @@ required: false, default: null, }, + + isResetCacheButtonLoading: { + type: Boolean, + required: false, + default: false, + }, + }, + methods: { + onClickResetCache() { + this.$emit('resetRunnersCache', this.resetCachePath); + }, }, }; </script> @@ -32,14 +48,13 @@ {{ s__('Pipelines|Run Pipeline') }} </a> - <a + <loading-button v-if="resetCachePath" - data-method="post" - :href="resetCachePath" + @click="onClickResetCache" + :loading="isResetCacheButtonLoading" class="btn btn-default js-clear-cache" - > - {{ s__('Pipelines|Clear Runner Caches') }} - </a> + :label="s__('Pipelines|Clear Runner Caches')" + /> <a v-if="ciLintPath" diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue index 6e5ee68eeb1..e0a7284124d 100644 --- a/app/assets/javascripts/pipelines/components/pipelines.vue +++ b/app/assets/javascripts/pipelines/components/pipelines.vue @@ -1,6 +1,7 @@ <script> import _ from 'underscore'; import { __, sprintf, s__ } from '../../locale'; + import createFlash from '../../flash'; import PipelinesService from '../services/pipelines_service'; import pipelinesMixin from '../mixins/pipelines'; import TablePagination from '../../vue_shared/components/table_pagination.vue'; @@ -92,6 +93,7 @@ scope: getParameterByName('scope') || 'all', page: getParameterByName('page') || '1', requestData: {}, + isResetCacheButtonLoading: false, }; }, stateMap: { @@ -265,6 +267,23 @@ this.poll.restart({ data: this.requestData }); }); }, + + handleResetRunnersCache(endpoint) { + this.isResetCacheButtonLoading = true; + + this.service.postAction(endpoint) + .then(() => { + this.isResetCacheButtonLoading = false; + createFlash( + s__('Pipelines|Project cache successfully reset.'), + 'notice', + ); + }) + .catch(() => { + this.isResetCacheButtonLoading = false; + createFlash(s__('Pipelines|Something went wrong while cleaning runners cache.')); + }); + }, }, }; </script> @@ -301,6 +320,8 @@ :new-pipeline-path="newPipelinePath" :reset-cache-path="resetCachePath" :ci-lint-path="ciLintPath" + @resetRunnersCache="handleResetRunnersCache" + :is-reset-cache-button-loading="isResetCacheButtonLoading" /> </div> diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js index 9fcc07abee5..522a4277bd7 100644 --- a/app/assets/javascripts/pipelines/mixins/pipelines.js +++ b/app/assets/javascripts/pipelines/mixins/pipelines.js @@ -51,12 +51,10 @@ export default { } }); - eventHub.$on('refreshPipelines', this.fetchPipelines); eventHub.$on('postAction', this.postAction); }, beforeDestroy() { - eventHub.$off('refreshPipelines'); - eventHub.$on('postAction', this.postAction); + eventHub.$off('postAction', this.postAction); }, destroyed() { this.poll.stop(); @@ -92,7 +90,7 @@ export default { }, postAction(endpoint) { this.service.postAction(endpoint) - .then(() => eventHub.$emit('refreshPipelines')) + .then(() => this.fetchPipelines()) .catch(() => Flash(__('An error occurred while making the request.'))); }, }, diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 86717bb7242..259809f3429 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -13,12 +13,14 @@ module Projects def reset_cache if ResetProjectCacheService.new(@project, current_user).execute - flash[:notice] = _("Project cache successfully reset.") + respond_to do |format| + format.json { head :ok } + end else - flash[:error] = _("Unable to reset project cache.") + respond_to do |format| + format.json { head :bad_request } + end end - - redirect_to project_pipelines_path(@project) end private diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb index 6f7f7c30d92..65d6e019746 100644 --- a/app/finders/user_recent_events_finder.rb +++ b/app/finders/user_recent_events_finder.rb @@ -12,6 +12,8 @@ class UserRecentEventsFinder attr_reader :current_user, :target_user, :params + LIMIT = 20 + def initialize(current_user, target_user, params = {}) @current_user = current_user @target_user = target_user @@ -19,15 +21,44 @@ class UserRecentEventsFinder end def execute - target_user - .recent_events - .merge(projects_for_current_user) - .references(:project) + recent_events(params[:offset] || 0) + .joins(:project) .with_associations - .limit_recent(20, params[:offset]) + .limit_recent(LIMIT, params[:offset]) + end + + private + + def recent_events(offset) + sql = <<~SQL + (#{projects}) AS projects_for_join + JOIN (#{target_events.to_sql}) AS #{Event.table_name} + ON #{Event.table_name}.project_id = projects_for_join.id + SQL + + # Workaround for https://github.com/rails/rails/issues/24193 + Event.from([Arel.sql(sql)]) end - def projects_for_current_user - ProjectsFinder.new(current_user: current_user).execute + def target_events + Event.where(author: target_user) + end + + def projects + # Compile a list of projects `current_user` interacted with + # and `target_user` is allowed to see. + + authorized = target_user + .project_interactions + .joins(:project_authorizations) + .where(project_authorizations: { user: current_user }) + .select(:id) + + visible = target_user + .project_interactions + .where(visibility_level: [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC]) + .select(:id) + + Gitlab::SQL::Union.new([authorized, visible]).to_sql end end diff --git a/app/models/cycle_analytics/summary.rb b/app/models/cycle_analytics/summary.rb deleted file mode 100644 index e69de29bb2d..00000000000 --- a/app/models/cycle_analytics/summary.rb +++ /dev/null diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 06aa67c600f..c1c27ccf3e5 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -197,6 +197,10 @@ class MergeRequestDiff < ActiveRecord::Base CompareService.new(project, head_commit_sha).execute(project, sha, straight: true) end + def commits_count + super || merge_request_diff_commits.size + end + private def create_merge_request_diff_files(diffs) diff --git a/app/models/repository.rb b/app/models/repository.rb index 461dfbec2bc..386fd0b1c9a 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -35,7 +35,7 @@ class Repository CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide changelog license_blob license_key gitignore koding_yml gitlab_ci_yml branch_names tag_names branch_count - tag_count avatar exists? empty? root_ref has_visible_content? + tag_count avatar exists? root_ref has_visible_content? issue_template_names merge_request_template_names).freeze # Methods that use cache_method but only memoize the value @@ -360,7 +360,7 @@ class Repository def expire_emptiness_caches return unless empty? - expire_method_caches(%i(empty? has_visible_content?)) + expire_method_caches(%i(has_visible_content?)) end def lookup_cache @@ -506,12 +506,14 @@ class Repository end cache_method :exists? + # We don't need to cache the output of this method because both exists? and + # has_visible_content? are already memoized and cached. There's no guarantee + # that the values are expired and loaded atomically. def empty? return true unless exists? !has_visible_content? end - cache_method :empty? # The size of this repository in megabytes. def size diff --git a/app/models/user.rb b/app/models/user.rb index 951b161203c..b8c55205ab8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -114,13 +114,15 @@ class User < ActiveRecord::Base has_many :project_authorizations has_many :authorized_projects, through: :project_authorizations, source: :project + has_many :user_interacted_projects + has_many :project_interactions, through: :user_interacted_projects, source: :project, class_name: 'Project' + has_many :snippets, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :notes, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent - has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent has_many :reported_abuse_reports, dependent: :destroy, foreign_key: :reporter_id, class_name: "AbuseReport" # rubocop:disable Cop/ActiveRecordDependent diff --git a/changelogs/unreleased/40525-listing-user-activity-timeouts.yml b/changelogs/unreleased/40525-listing-user-activity-timeouts.yml new file mode 100644 index 00000000000..39ce873dba6 --- /dev/null +++ b/changelogs/unreleased/40525-listing-user-activity-timeouts.yml @@ -0,0 +1,5 @@ +--- +title: Improve database response time for user activity listing. +merge_request: 17454 +author: +type: performance diff --git a/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml b/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml new file mode 100644 index 00000000000..860a8becd65 --- /dev/null +++ b/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml @@ -0,0 +1,5 @@ +--- +title: Ensure foreign keys on clusters applications +merge_request: 17488 +author: +type: other diff --git a/changelogs/unreleased/fix-mattermost-delete-team.yml b/changelogs/unreleased/fix-mattermost-delete-team.yml new file mode 100644 index 00000000000..d14ae023114 --- /dev/null +++ b/changelogs/unreleased/fix-mattermost-delete-team.yml @@ -0,0 +1,5 @@ +--- +title: Fixed group deletion linked to Mattermost +merge_request: 16209 +author: Julien Millau +type: fixed diff --git a/changelogs/unreleased/sh-add-missing-acts-as-taggable-indices.yml b/changelogs/unreleased/sh-add-missing-acts-as-taggable-indices.yml new file mode 100644 index 00000000000..d9a1a0db9e8 --- /dev/null +++ b/changelogs/unreleased/sh-add-missing-acts-as-taggable-indices.yml @@ -0,0 +1,5 @@ +--- +title: Adding missing indexes on taggings table +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/sh-add-section-name-index.yml b/changelogs/unreleased/sh-add-section-name-index.yml new file mode 100644 index 00000000000..c822b4e851b --- /dev/null +++ b/changelogs/unreleased/sh-add-section-name-index.yml @@ -0,0 +1,5 @@ +--- +title: Add index on section_name_id on ci_build_trace_sections table +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/sh-remove-double-caching-repo-empty.yml b/changelogs/unreleased/sh-remove-double-caching-repo-empty.yml new file mode 100644 index 00000000000..1684be4e5e3 --- /dev/null +++ b/changelogs/unreleased/sh-remove-double-caching-repo-empty.yml @@ -0,0 +1,5 @@ +--- +title: Remove double caching of Repository#empty? +merge_request: +author: +type: fixed diff --git a/config/routes/git_http.rb b/config/routes/git_http.rb index ff51823897d..ec5c68f81df 100644 --- a/config/routes/git_http.rb +++ b/config/routes/git_http.rb @@ -40,7 +40,7 @@ scope(path: '*namespace_id/:project_id', # /info/refs?service=git-receive-pack, but nothing else. # git_http_handshake = lambda do |request| - ProjectUrlConstrainer.new.matches?(request) && + ::Constraints::ProjectUrlConstrainer.new.matches?(request) && (request.query_string.blank? || request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/)) end diff --git a/config/routes/group.rb b/config/routes/group.rb index 710f12e33ad..d89a714c7d6 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -1,10 +1,8 @@ -require 'constraints/group_url_constrainer' - resources :groups, only: [:index, :new, :create] do post :preview_markdown end -constraints(GroupUrlConstrainer.new) do +constraints(::Constraints::GroupUrlConstrainer.new) do scope(path: 'groups/*id', controller: :groups, constraints: { id: Gitlab::PathRegex.full_namespace_route_regex, format: /(html|json|atom)/ }) do diff --git a/config/routes/project.rb b/config/routes/project.rb index 710fe0ec325..b82ed27664c 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -1,10 +1,8 @@ -require 'constraints/project_url_constrainer' - resources :projects, only: [:index, :new, :create] draw :git_http -constraints(ProjectUrlConstrainer.new) do +constraints(::Constraints::ProjectUrlConstrainer.new) do # If the route has a wildcard segment, the segment has a regex constraint, # the segment is potentially followed by _another_ wildcard segment, and # the `format` option is not set to false, we need to specify that diff --git a/config/routes/user.rb b/config/routes/user.rb index 733a3f6ce9a..57fb37530bb 100644 --- a/config/routes/user.rb +++ b/config/routes/user.rb @@ -1,5 +1,3 @@ -require 'constraints/user_url_constrainer' - devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations, passwords: :passwords, @@ -35,7 +33,7 @@ scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) d get '/u/:username/contributed', to: redirect('users/%{username}/contributed') end -constraints(UserUrlConstrainer.new) do +constraints(::Constraints::UserUrlConstrainer.new) do # Get all keys of user get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: Gitlab::PathRegex.root_namespace_route_regex } diff --git a/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb b/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb new file mode 100644 index 00000000000..8298979e96a --- /dev/null +++ b/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb @@ -0,0 +1,50 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class EnsureForeignKeysOnClustersApplications < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + existing = Clusters::Cluster + .joins(:application_ingress) + .where('clusters.id = clusters_applications_ingress.cluster_id') + + Clusters::Applications::Ingress.where('NOT EXISTS (?)', existing).in_batches do |batch| + batch.delete_all + end + + unless foreign_keys_for(:clusters_applications_ingress, :cluster_id).any? + add_concurrent_foreign_key :clusters_applications_ingress, :clusters, + column: :cluster_id, + on_delete: :cascade + end + + existing = Clusters::Cluster + .joins(:application_prometheus) + .where('clusters.id = clusters_applications_prometheus.cluster_id') + + Clusters::Applications::Ingress.where('NOT EXISTS (?)', existing).in_batches do |batch| + batch.delete_all + end + + unless foreign_keys_for(:clusters_applications_prometheus, :cluster_id).any? + add_concurrent_foreign_key :clusters_applications_prometheus, :clusters, + column: :cluster_id, + on_delete: :cascade + end + end + + def down + if foreign_keys_for(:clusters_applications_ingress, :cluster_id).any? + remove_foreign_key :clusters_applications_ingress, column: :cluster_id + end + + if foreign_keys_for(:clusters_applications_prometheus, :cluster_id).any? + remove_foreign_key :clusters_applications_prometheus, column: :cluster_id + end + end +end diff --git a/db/migrate/20180304204842_clean_commits_count_migration.rb b/db/migrate/20180304204842_clean_commits_count_migration.rb deleted file mode 100644 index ace4c6aa1cf..00000000000 --- a/db/migrate/20180304204842_clean_commits_count_migration.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CleanCommitsCountMigration < ActiveRecord::Migration - include Gitlab::Database::MigrationHelpers - - DOWNTIME = false - - disable_ddl_transaction! - - def up - Gitlab::BackgroundMigration.steal('AddMergeRequestDiffCommitsCount') - end - - def down - end -end diff --git a/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb b/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb new file mode 100644 index 00000000000..06e402adcd7 --- /dev/null +++ b/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb @@ -0,0 +1,21 @@ +# This migration comes from acts_as_taggable_on_engine (originally 6) +# +# It has been modified to handle no-downtime GitLab migrations. Several +# indexes have been removed since they are not needed for GitLab. +class AddMissingIndexesActsAsTaggableOnEngine < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :taggings, :tag_id unless index_exists? :taggings, :tag_id + add_concurrent_index :taggings, [:taggable_id, :taggable_type] unless index_exists? :taggings, [:taggable_id, :taggable_type] + end + + def down + remove_concurrent_index :taggings, :tag_id + remove_concurrent_index :taggings, [:taggable_id, :taggable_type] + end +end diff --git a/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb new file mode 100644 index 00000000000..0cf665ac935 --- /dev/null +++ b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb @@ -0,0 +1,22 @@ +class AddSectionNameIdIndexOnCiBuildTraceSections < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + def up + # MySQL may already have this as a foreign key + unless index_exists?(:ci_build_trace_sections, :section_name_id) + add_concurrent_index :ci_build_trace_sections, :section_name_id + end + end + + def down + # We cannot remove index for MySQL because it's needed for foreign key + if Gitlab::Database.postgresql? + remove_concurrent_index :ci_build_trace_sections, :section_name_id + end + end +end diff --git a/db/schema.rb b/db/schema.rb index b93e6fa594b..75a094bbbb6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180307012445) do +ActiveRecord::Schema.define(version: 20180308052825) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -264,6 +264,7 @@ ActiveRecord::Schema.define(version: 20180307012445) do add_index "ci_build_trace_sections", ["build_id", "section_name_id"], name: "index_ci_build_trace_sections_on_build_id_and_section_name_id", unique: true, using: :btree add_index "ci_build_trace_sections", ["project_id"], name: "index_ci_build_trace_sections_on_project_id", using: :btree + add_index "ci_build_trace_sections", ["section_name_id"], name: "index_ci_build_trace_sections_on_section_name_id", using: :btree create_table "ci_builds", force: :cascade do |t| t.string "status" @@ -1733,7 +1734,9 @@ ActiveRecord::Schema.define(version: 20180307012445) do end add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree + add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree + add_index "taggings", ["taggable_id", "taggable_type"], name: "index_taggings_on_taggable_id_and_taggable_type", using: :btree create_table "tags", force: :cascade do |t| t.string "name" @@ -2029,6 +2032,8 @@ ActiveRecord::Schema.define(version: 20180307012445) do add_foreign_key "cluster_providers_gcp", "clusters", on_delete: :cascade add_foreign_key "clusters", "users", on_delete: :nullify add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade + add_foreign_key "clusters_applications_ingress", "clusters", name: "fk_753a7b41c1", on_delete: :cascade + add_foreign_key "clusters_applications_prometheus", "clusters", name: "fk_557e773639", on_delete: :cascade add_foreign_key "clusters_applications_runners", "ci_runners", column: "runner_id", name: "fk_02de2ded36", on_delete: :nullify add_foreign_key "clusters_applications_runners", "clusters", on_delete: :cascade add_foreign_key "container_repositories", "projects" diff --git a/doc/install/installation.md b/doc/install/installation.md index 170d92faa09..6eb767b00b3 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -299,9 +299,9 @@ sudo usermod -aG redis git ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-5-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-6-stable gitlab -**Note:** You can change `10-5-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `10-6-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It diff --git a/doc/update/10.5-to-10.6.md b/doc/update/10.5-to-10.6.md new file mode 100644 index 00000000000..af8343b5958 --- /dev/null +++ b/doc/update/10.5-to-10.6.md @@ -0,0 +1,361 @@ +--- +comments: false +--- + +# From 10.5 to 10.6 + +Make sure you view this update guide from the tag (version) of GitLab you would +like to install. In most cases this should be the highest numbered production +tag (without rc in it). You can select the tag in the version dropdown at the +top left corner of GitLab (below the menu bar). + +If the highest number stable branch is unclear please check the +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation +guide links by version. + +### 1. Stop server + +```bash +sudo service gitlab stop +``` + +### 2. Backup + +NOTE: If you installed GitLab from source, make sure `rsync` is installed. + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Update Ruby + +NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be +sure to upgrade your interpreter if necessary. + +You can check which version you are running with `ruby -v`. + +Download and compile Ruby: + +```bash +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.6.tar.gz +echo '4e6a0f828819e15d274ae58485585fc8b7caace0 ruby-2.3.6.tar.gz' | shasum -c - && tar xzf ruby-2.3.6.tar.gz +cd ruby-2.3.6 +./configure --disable-install-rdoc +make +sudo make install +``` + +Install Bundler: + +```bash +sudo gem install bundler --no-ri --no-rdoc +``` + +### 4. Update Node + +GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets. +We require a minimum version of node v6.0.0. + +You can check which version you are running with `node -v`. If you are running +a version older than `v6.0.0` you will need to update to a newer version. You +can find instructions to install from community maintained packages or compile +from source at the nodejs.org website. + +<https://nodejs.org/en/download/> + +Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage +JavaScript dependencies. + +```bash +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). + +### 5. Update Go + +NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go +1.5.x through 1.7.x. Be sure to upgrade your installation if necessary. + +You can check which version you are running with `go version`. + +Download and install Go: + +```bash +# Remove former Go installation folder +sudo rm -rf /usr/local/go + +curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz +echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.8.3.linux-amd64.tar.gz +``` + +### 6. Get latest code + +```bash +cd /home/git/gitlab + +sudo -u git -H git fetch --all +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +sudo -u git -H git checkout -- locale +``` + +For GitLab Community Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 10-6-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 10-6-stable-ee +``` + +### 7. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell + +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION) +sudo -u git -H bin/compile +``` + +### 8. Update gitlab-workhorse + +Install and compile gitlab-workhorse. GitLab-Workhorse uses +[GNU Make](https://www.gnu.org/software/make/). +If you are not using Linux you may have to run `gmake` instead of +`make` below. + +```bash +cd /home/git/gitlab-workhorse + +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION) +sudo -u git -H make +``` + +### 9. Update Gitaly + +#### New Gitaly configuration options required + +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. + +```shell +echo ' +[gitaly-ruby] +dir = "/home/git/gitaly/ruby" + +[gitlab-shell] +dir = "/home/git/gitlab-shell" +' | sudo -u git tee -a /home/git/gitaly/config.toml +``` + +#### Check Gitaly configuration + +Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly +configuration file may contain syntax errors. The block name +`[[storages]]`, which may occur more than once in your `config.toml` +file, should be `[[storage]]` instead. + +```shell +sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml +``` + +#### Compile Gitaly + +```shell +cd /home/git/gitaly +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION) +sudo -u git -H make +``` + +### 10. Update MySQL permissions + +If you are using MySQL you need to grant the GitLab user the necessary +permissions on the database: + +```bash +mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';" +``` + +If you use MySQL with replication, or just have MySQL configured with binary logging, +you will need to also run the following on all of your MySQL servers: + +```bash +mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;" +``` + +You can make this setting permanent by adding it to your `my.cnf`: + +``` +log_bin_trust_function_creators=1 +``` + +### 11. Update configuration files + +#### New configuration options for `gitlab.yml` + +There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +cd /home/git/gitlab + +git diff origin/10-5-stable:config/gitlab.yml.example origin/10-6-stable:config/gitlab.yml.example +``` + +#### 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/10-5-stable:lib/support/nginx/gitlab-ssl origin/10-6-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/10-5-stable:lib/support/nginx/gitlab origin/10-6-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/10-6-stable/lib/support/init.d/gitlab.default.example#L38 + +#### SMTP configuration + +If you're installing from source and use SMTP to deliver mail, you will need to add the following line +to config/initializers/smtp_settings.rb: + +```ruby +ActionMailer::Base.delivery_method = :smtp +``` + +See [smtp_settings.rb.sample] as an example. + +[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/config/initializers/smtp_settings.rb.sample#L13 + +#### Init script + +There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`: + +```sh +cd /home/git/gitlab + +git diff origin/10-5-stable:lib/support/init.d/gitlab.default.example origin/10-6-stable:lib/support/init.d/gitlab.default.example +``` + +Ensure you're still up-to-date with the latest init script changes: + +```bash +cd /home/git/gitlab + +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +For Ubuntu 16.04.1 LTS: + +```bash +sudo systemctl daemon-reload +``` + +### 12. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL installations (note: the line below states '--without postgres') +sudo -u git -H bundle install --without postgres development test --deployment + +# PostgreSQL installations (note: the line below states '--without mysql') +sudo -u git -H bundle install --without mysql development test --deployment + +# Optional: clean up old gems +sudo -u git -H bundle clean + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Compile GetText PO files + +sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production + +# Update node dependencies and recompile assets +sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production + +# Clean up cache +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md). + +### 13. Start application + +```bash +sudo service gitlab start +sudo service nginx restart +``` + +### 14. Check application status + +Check if GitLab and its environment are configured correctly: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +To make sure you didn't miss anything run a more thorough check: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` + +If all items are green, then congratulations, the upgrade is complete! + +## Things went south? Revert to previous version (10.5) + +### 1. Revert the code to the previous version + +Follow the [upgrade guide from 10.4 to 10.5](10.4-to-10.5.md), except for the +database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above. + +[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/config/gitlab.yml.example +[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/10-6-stable/lib/support/init.d/gitlab.default.example diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md index 5ddeb014b30..dedf102fc37 100644 --- a/doc/user/project/settings/import_export.md +++ b/doc/user/project/settings/import_export.md @@ -31,8 +31,7 @@ with all their related data and be moved into a new GitLab instance. | GitLab version | Import/Export version | | ---------------- | --------------------- | -| 10.6 to current | 0.2.3 | -| 10.4 | 0.2.2 | +| 10.4 to current | 0.2.2 | | 10.3 | 0.2.1 | | 10.0 | 0.2.0 | | 9.4.0 | 0.1.8 | diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index fd2ac2db0a9..87649c50424 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -1,9 +1,11 @@ -class GroupUrlConstrainer - def matches?(request) - full_path = request.params[:group_id] || request.params[:id] +module Constraints + class GroupUrlConstrainer + def matches?(request) + full_path = request.params[:group_id] || request.params[:id] - return false unless NamespacePathValidator.valid_path?(full_path) + return false unless NamespacePathValidator.valid_path?(full_path) - Group.find_by_full_path(full_path, follow_redirects: request.get?).present? + Group.find_by_full_path(full_path, follow_redirects: request.get?).present? + end end end diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb index e90ecb5ec69..32aea98f0f7 100644 --- a/lib/constraints/project_url_constrainer.rb +++ b/lib/constraints/project_url_constrainer.rb @@ -1,13 +1,15 @@ -class ProjectUrlConstrainer - def matches?(request) - namespace_path = request.params[:namespace_id] - project_path = request.params[:project_id] || request.params[:id] - full_path = [namespace_path, project_path].join('/') +module Constraints + class ProjectUrlConstrainer + def matches?(request) + namespace_path = request.params[:namespace_id] + project_path = request.params[:project_id] || request.params[:id] + full_path = [namespace_path, project_path].join('/') - return false unless ProjectPathValidator.valid_path?(full_path) + return false unless ProjectPathValidator.valid_path?(full_path) - # We intentionally allow SELECT(*) here so result of this query can be used - # as cache for further Project.find_by_full_path calls within request - Project.find_by_full_path(full_path, follow_redirects: request.get?).present? + # We intentionally allow SELECT(*) here so result of this query can be used + # as cache for further Project.find_by_full_path calls within request + Project.find_by_full_path(full_path, follow_redirects: request.get?).present? + end end end diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index 3b3ed1c6ddb..8afa04d29a4 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -1,9 +1,11 @@ -class UserUrlConstrainer - def matches?(request) - full_path = request.params[:username] +module Constraints + class UserUrlConstrainer + def matches?(request) + full_path = request.params[:username] - return false unless NamespacePathValidator.valid_path?(full_path) + return false unless NamespacePathValidator.valid_path?(full_path) - User.find_by_full_path(full_path, follow_redirects: request.get?).present? + User.find_by_full_path(full_path, follow_redirects: request.get?).present? + end end end diff --git a/lib/declarative_policy.rb b/lib/declarative_policy.rb index b1949d693ad..1dd2855063d 100644 --- a/lib/declarative_policy.rb +++ b/lib/declarative_policy.rb @@ -1,6 +1,8 @@ require_dependency 'declarative_policy/cache' require_dependency 'declarative_policy/condition' -require_dependency 'declarative_policy/dsl' +require_dependency 'declarative_policy/delegate_dsl' +require_dependency 'declarative_policy/policy_dsl' +require_dependency 'declarative_policy/rule_dsl' require_dependency 'declarative_policy/preferred_scope' require_dependency 'declarative_policy/rule' require_dependency 'declarative_policy/runner' diff --git a/lib/declarative_policy/delegate_dsl.rb b/lib/declarative_policy/delegate_dsl.rb new file mode 100644 index 00000000000..f544dffe888 --- /dev/null +++ b/lib/declarative_policy/delegate_dsl.rb @@ -0,0 +1,16 @@ +module DeclarativePolicy + # Used when the name of a delegate is mentioned in + # the rule DSL. + class DelegateDsl + def initialize(rule_dsl, delegate_name) + @rule_dsl = rule_dsl + @delegate_name = delegate_name + end + + def method_missing(m, *a, &b) + return super unless a.empty? && !block_given? + + @rule_dsl.delegate(@delegate_name, m) + end + end +end diff --git a/lib/declarative_policy/dsl.rb b/lib/declarative_policy/dsl.rb deleted file mode 100644 index 6ba1e7a3c5c..00000000000 --- a/lib/declarative_policy/dsl.rb +++ /dev/null @@ -1,103 +0,0 @@ -module DeclarativePolicy - # The DSL evaluation context inside rule { ... } blocks. - # Responsible for creating and combining Rule objects. - # - # See Base.rule - class RuleDsl - def initialize(context_class) - @context_class = context_class - end - - def can?(ability) - Rule::Ability.new(ability) - end - - def all?(*rules) - Rule::And.make(rules) - end - - def any?(*rules) - Rule::Or.make(rules) - end - - def none?(*rules) - ~Rule::Or.new(rules) - end - - def cond(condition) - Rule::Condition.new(condition) - end - - def delegate(delegate_name, condition) - Rule::DelegatedCondition.new(delegate_name, condition) - end - - def method_missing(m, *a, &b) - return super unless a.size == 0 && !block_given? - - if @context_class.delegations.key?(m) - DelegateDsl.new(self, m) - else - cond(m.to_sym) - end - end - end - - # Used when the name of a delegate is mentioned in - # the rule DSL. - class DelegateDsl - def initialize(rule_dsl, delegate_name) - @rule_dsl = rule_dsl - @delegate_name = delegate_name - end - - def method_missing(m, *a, &b) - return super unless a.size == 0 && !block_given? - - @rule_dsl.delegate(@delegate_name, m) - end - end - - # The return value of a rule { ... } declaration. - # Can call back to register rules with the containing - # Policy class (context_class here). See Base.rule - # - # Note that the #policy method just performs an #instance_eval, - # which is useful for multiple #enable or #prevent callse. - # - # Also provides a #method_missing proxy to the context - # class's class methods, so that helper methods can be - # defined and used in a #policy { ... } block. - class PolicyDsl - def initialize(context_class, rule) - @context_class = context_class - @rule = rule - end - - def policy(&b) - instance_eval(&b) - end - - def enable(*abilities) - @context_class.enable_when(abilities, @rule) - end - - def prevent(*abilities) - @context_class.prevent_when(abilities, @rule) - end - - def prevent_all - @context_class.prevent_all_when(@rule) - end - - def method_missing(m, *a, &b) - return super unless @context_class.respond_to?(m) - - @context_class.__send__(m, *a, &b) # rubocop:disable GitlabSecurity/PublicSend - end - - def respond_to_missing?(m) - @context_class.respond_to?(m) || super - end - end -end diff --git a/lib/declarative_policy/policy_dsl.rb b/lib/declarative_policy/policy_dsl.rb new file mode 100644 index 00000000000..f11b6e9f730 --- /dev/null +++ b/lib/declarative_policy/policy_dsl.rb @@ -0,0 +1,44 @@ +module DeclarativePolicy + # The return value of a rule { ... } declaration. + # Can call back to register rules with the containing + # Policy class (context_class here). See Base.rule + # + # Note that the #policy method just performs an #instance_eval, + # which is useful for multiple #enable or #prevent callse. + # + # Also provides a #method_missing proxy to the context + # class's class methods, so that helper methods can be + # defined and used in a #policy { ... } block. + class PolicyDsl + def initialize(context_class, rule) + @context_class = context_class + @rule = rule + end + + def policy(&b) + instance_eval(&b) + end + + def enable(*abilities) + @context_class.enable_when(abilities, @rule) + end + + def prevent(*abilities) + @context_class.prevent_when(abilities, @rule) + end + + def prevent_all + @context_class.prevent_all_when(@rule) + end + + def method_missing(m, *a, &b) + return super unless @context_class.respond_to?(m) + + @context_class.__send__(m, *a, &b) # rubocop:disable GitlabSecurity/PublicSend + end + + def respond_to_missing?(m) + @context_class.respond_to?(m) || super + end + end +end diff --git a/lib/declarative_policy/preferred_scope.rb b/lib/declarative_policy/preferred_scope.rb index b0754098149..5c214408dd0 100644 --- a/lib/declarative_policy/preferred_scope.rb +++ b/lib/declarative_policy/preferred_scope.rb @@ -1,4 +1,4 @@ -module DeclarativePolicy +module DeclarativePolicy # rubocop:disable Naming/FileName PREFERRED_SCOPE_KEY = :"DeclarativePolicy.preferred_scope" class << self diff --git a/lib/declarative_policy/rule_dsl.rb b/lib/declarative_policy/rule_dsl.rb new file mode 100644 index 00000000000..e948b7f2de1 --- /dev/null +++ b/lib/declarative_policy/rule_dsl.rb @@ -0,0 +1,45 @@ +module DeclarativePolicy + # The DSL evaluation context inside rule { ... } blocks. + # Responsible for creating and combining Rule objects. + # + # See Base.rule + class RuleDsl + def initialize(context_class) + @context_class = context_class + end + + def can?(ability) + Rule::Ability.new(ability) + end + + def all?(*rules) + Rule::And.make(rules) + end + + def any?(*rules) + Rule::Or.make(rules) + end + + def none?(*rules) + ~Rule::Or.new(rules) + end + + def cond(condition) + Rule::Condition.new(condition) + end + + def delegate(delegate_name, condition) + Rule::DelegatedCondition.new(delegate_name, condition) + end + + def method_missing(m, *a, &b) + return super unless a.empty? && !block_given? + + if @context_class.delegations.key?(m) + DelegateDsl.new(self, m) + else + cond(m.to_sym) + end + end + end +end diff --git a/lib/gitlab/auth/result.rb b/lib/gitlab/auth/result.rb index 75451cf8aa9..00cdc94a9ef 100644 --- a/lib/gitlab/auth/result.rb +++ b/lib/gitlab/auth/result.rb @@ -1,4 +1,4 @@ -module Gitlab +module Gitlab # rubocop:disable Naming/FileName module Auth Result = Struct.new(:actor, :project, :type, :authentication_abilities) do def ci?(for_project) diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb index 7b19b10e05b..a1849b01c5d 100644 --- a/lib/gitlab/ci/pipeline/chain/command.rb +++ b/lib/gitlab/ci/pipeline/chain/command.rb @@ -1,4 +1,4 @@ -module Gitlab +module Gitlab # rubocop:disable Naming/FileName module Ci module Pipeline module Chain diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index d4f6b543daf..656f3999756 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1433,16 +1433,6 @@ module Gitlab output end - def can_be_merged?(source_sha, target_branch) - gitaly_migrate(:can_be_merged) do |is_enabled| - if is_enabled - gitaly_can_be_merged?(source_sha, find_branch(target_branch).target) - else - rugged_can_be_merged?(source_sha, target_branch) - end - end - end - def last_commit_for_path(sha, path) gitaly_migrate(:last_commit_for_path) do |is_enabled| if is_enabled @@ -2404,14 +2394,6 @@ module Gitlab .map { |c| commit(c) } end - def gitaly_can_be_merged?(their_commit, our_commit) - !gitaly_conflicts_client(our_commit, their_commit).conflicts? - end - - def rugged_can_be_merged?(their_commit, our_commit) - !rugged.merge_commits(our_commit, their_commit).conflicts? - end - def last_commit_for_path_by_gitaly(sha, path) gitaly_commit_client.last_commit_for_path(sha, path) end diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb index 1a2eab0b005..d62d9136886 100644 --- a/lib/gitlab/health_checks/metric.rb +++ b/lib/gitlab/health_checks/metric.rb @@ -1,3 +1,3 @@ -module Gitlab::HealthChecks +module Gitlab::HealthChecks # rubocop:disable Naming/FileName Metric = Struct.new(:name, :value, :labels) end diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb index 8086760023e..e323e2c9723 100644 --- a/lib/gitlab/health_checks/result.rb +++ b/lib/gitlab/health_checks/result.rb @@ -1,3 +1,3 @@ -module Gitlab::HealthChecks +module Gitlab::HealthChecks # rubocop:disable Naming/FileName Result = Struct.new(:success, :message, :labels) end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index b713fa7e1cd..af203ff711d 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -3,7 +3,7 @@ module Gitlab extend self # For every version update, the version history in import_export.md has to be kept up to date. - VERSION = '0.2.3'.freeze + VERSION = '0.2.2'.freeze FILENAME_LIMIT = 50 def export_path(relative_path:) diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb index f8d0a135965..bfe8e113b5e 100644 --- a/lib/gitlab/middleware/release_env.rb +++ b/lib/gitlab/middleware/release_env.rb @@ -1,4 +1,4 @@ -module Gitlab +module Gitlab # rubocop:disable Naming/FileName module Middleware # Some of middleware would hold env for no good reason even after the # request had already been processed, and we could not garbage collect diff --git a/lib/gitlab/slash_commands/result.rb b/lib/gitlab/slash_commands/result.rb index 7021b4b01b2..3669dedf0fe 100644 --- a/lib/gitlab/slash_commands/result.rb +++ b/lib/gitlab/slash_commands/result.rb @@ -1,4 +1,4 @@ -module Gitlab +module Gitlab # rubocop:disable Naming/FileName module SlashCommands Result = Struct.new(:type, :message) end diff --git a/lib/haml_lint/inline_javascript.rb b/lib/haml_lint/inline_javascript.rb index 4f776330e80..adbed20f152 100644 --- a/lib/haml_lint/inline_javascript.rb +++ b/lib/haml_lint/inline_javascript.rb @@ -1,4 +1,4 @@ -unless Rails.env.production? +unless Rails.env.production? # rubocop:disable Naming/FileName require 'haml_lint/haml_visitor' require 'haml_lint/linter' require 'haml_lint/linter_registry' diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb index ef08bd46e17..65ccdb3c347 100644 --- a/lib/mattermost/session.rb +++ b/lib/mattermost/session.rb @@ -83,6 +83,12 @@ module Mattermost end end + def delete(path, options = {}) + handle_exceptions do + self.class.delete(path, options.merge(headers: @headers)) + end + end + private def create diff --git a/lib/mattermost/team.rb b/lib/mattermost/team.rb index b2511f3af1d..75513a9ba04 100644 --- a/lib/mattermost/team.rb +++ b/lib/mattermost/team.rb @@ -16,10 +16,9 @@ module Mattermost end # The deletion is done async, so the response is fast. - # On the mattermost side, this triggers an soft deletion first, after which - # the actuall data is removed + # On the mattermost side, this triggers an soft deletion def destroy(team_id:) - session_delete("/api/v4/teams/#{team_id}?permanent=true") + session_delete("/api/v4/teams/#{team_id}") end end end diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb index 99be21bbe89..17a1bc904e4 100644 --- a/qa/qa/page/project/settings/ci_cd.rb +++ b/qa/qa/page/project/settings/ci_cd.rb @@ -1,4 +1,4 @@ -module QA +module QA # rubocop:disable Naming/FileName module Page module Project module Settings diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb index 9110237c538..b36a3f9c8a0 100644 --- a/rubocop/rubocop.rb +++ b/rubocop/rubocop.rb @@ -1,3 +1,4 @@ +# rubocop:disable Naming/FileName require_relative 'cop/gitlab/module_with_instance_variables' require_relative 'cop/gitlab/predicate_memoization' require_relative 'cop/include_sidekiq_worker' diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index 0202149f335..293e76798ae 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -27,7 +27,7 @@ describe Projects::Settings::CiCdController do allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(true) end - subject { post :reset_cache, namespace_id: project.namespace, project_id: project } + subject { post :reset_cache, namespace_id: project.namespace, project_id: project, format: :json } it 'calls reset project cache service' do expect(ResetProjectCacheService).to receive_message_chain(:new, :execute) @@ -35,19 +35,11 @@ describe Projects::Settings::CiCdController do subject end - it 'redirects to project pipelines path' do - subject - - expect(response).to have_gitlab_http_status(:redirect) - expect(response).to redirect_to(project_pipelines_path(project)) - end - context 'when service returns successfully' do - it 'sets the flash notice variable' do + it 'returns a success header' do subject - expect(controller).to set_flash[:notice] - expect(controller).not_to set_flash[:error] + expect(response).to have_gitlab_http_status(:ok) end end @@ -56,11 +48,10 @@ describe Projects::Settings::CiCdController do allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(false) end - it 'sets the flash error variable' do + it 'returns an error header' do subject - expect(controller).not_to set_flash[:notice] - expect(controller).to set_flash[:error] + expect(response).to have_gitlab_http_status(:bad_request) end end end diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz Binary files differindex 12bfcc177c7..0cc68aff494 100644 --- a/spec/features/projects/import_export/test_project_export.tar.gz +++ b/spec/features/projects/import_export/test_project_export.tar.gz diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 849d85061df..33ad59abfdf 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -557,7 +557,7 @@ describe 'Pipelines', :js do end it 'has a clear caches button' do - expect(page).to have_link 'Clear Runner Caches' + expect(page).to have_button 'Clear Runner Caches' end describe 'user clicks the button' do @@ -567,14 +567,16 @@ describe 'Pipelines', :js do end it 'increments jobs_cache_index' do - click_link 'Clear Runner Caches' + click_button 'Clear Runner Caches' + wait_for_requests expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.' end end context 'when project does not have jobs_cache_index' do it 'sets jobs_cache_index to 1' do - click_link 'Clear Runner Caches' + click_button 'Clear Runner Caches' + wait_for_requests expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.' end end diff --git a/spec/javascripts/pipelines/nav_controls_spec.js b/spec/javascripts/pipelines/nav_controls_spec.js index 77c5258f74c..d6232f5c567 100644 --- a/spec/javascripts/pipelines/nav_controls_spec.js +++ b/spec/javascripts/pipelines/nav_controls_spec.js @@ -39,19 +39,6 @@ describe('Pipelines Nav Controls', () => { expect(component.$el.querySelector('.js-run-pipeline')).toEqual(null); }); - it('should render link for resetting runner caches', () => { - const mockData = { - newPipelinePath: 'foo', - ciLintPath: 'foo', - resetCachePath: 'foo', - }; - - component = mountComponent(NavControlsComponent, mockData); - - expect(component.$el.querySelector('.js-clear-cache').textContent.trim()).toContain('Clear Runner Caches'); - expect(component.$el.querySelector('.js-clear-cache').getAttribute('href')).toEqual(mockData.resetCachePath); - }); - it('should render link for CI lint', () => { const mockData = { newPipelinePath: 'foo', @@ -65,4 +52,28 @@ describe('Pipelines Nav Controls', () => { expect(component.$el.querySelector('.js-ci-lint').textContent.trim()).toContain('CI Lint'); expect(component.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(mockData.ciLintPath); }); + + describe('Reset Runners Cache', () => { + beforeEach(() => { + const mockData = { + newPipelinePath: 'foo', + ciLintPath: 'foo', + resetCachePath: 'foo', + }; + + component = mountComponent(NavControlsComponent, mockData); + }); + + it('should render button for resetting runner caches', () => { + expect(component.$el.querySelector('.js-clear-cache').textContent.trim()).toContain('Clear Runner Caches'); + }); + + it('should emit postAction event when reset runner cache button is clicked', () => { + spyOn(component, '$emit'); + + component.$el.querySelector('.js-clear-cache').click(); + + expect(component.$emit).toHaveBeenCalledWith('resetRunnersCache', 'foo'); + }); + }); }); diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js index 84fd0329f08..7e242eb45e1 100644 --- a/spec/javascripts/pipelines/pipelines_spec.js +++ b/spec/javascripts/pipelines/pipelines_spec.js @@ -95,16 +95,16 @@ describe('Pipelines', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); - it('renders Run Pipeline button', () => { + it('renders Run Pipeline link', () => { expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath); }); - it('renders CI Lint button', () => { + it('renders CI Lint link', () => { expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath); }); it('renders Clear Runner Cache button', () => { - expect(vm.$el.querySelector('.js-clear-cache').getAttribute('href')).toEqual(paths.resetCachePath); + expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches'); }); it('renders pipelines table', () => { @@ -139,16 +139,16 @@ describe('Pipelines', () => { expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All'); }); - it('renders Run Pipeline button', () => { + it('renders Run Pipeline link', () => { expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath); }); - it('renders CI Lint button', () => { + it('renders CI Lint link', () => { expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath); }); it('renders Clear Runner Cache button', () => { - expect(vm.$el.querySelector('.js-clear-cache').getAttribute('href')).toEqual(paths.resetCachePath); + expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches'); }); it('renders tab empty state', () => { @@ -218,7 +218,7 @@ describe('Pipelines', () => { it('renders buttons', () => { expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath); expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath); - expect(vm.$el.querySelector('.js-clear-cache').getAttribute('href')).toEqual(paths.resetCachePath); + expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches'); }); it('renders error state', () => { diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index 4dab58b26a0..ff295068ba9 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe GroupUrlConstrainer do +describe Constraints::GroupUrlConstrainer do let!(:group) { create(:group, path: 'gitlab') } describe '#matches?' do diff --git a/spec/lib/constraints/project_url_constrainer_spec.rb b/spec/lib/constraints/project_url_constrainer_spec.rb index 92331eb2e5d..c96e7ab8495 100644 --- a/spec/lib/constraints/project_url_constrainer_spec.rb +++ b/spec/lib/constraints/project_url_constrainer_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe ProjectUrlConstrainer do +describe Constraints::ProjectUrlConstrainer do let!(:project) { create(:project) } let!(:namespace) { project.namespace } diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index cb3b4ff1391..e2c85bb27bb 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe UserUrlConstrainer do +describe Constraints::UserUrlConstrainer do let!(:user) { create(:user, username: 'dz') } describe '#matches?' do diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb index e638ad7a2c9..3c8206031cf 100644 --- a/spec/lib/mattermost/team_spec.rb +++ b/spec/lib/mattermost/team_spec.rb @@ -64,4 +64,108 @@ describe Mattermost::Team do end end end + + describe '#create' do + subject { described_class.new(nil).create(name: "devteam", display_name: "Dev Team", type: "O") } + + context 'for a new team' do + let(:response) do + { + "id" => "cuojfcetjty7tb4pxe47pwpndo", + "create_at" => 1517688728701, + "update_at" => 1517688728701, + "delete_at" => 0, + "display_name" => "Dev Team", + "name" => "devteam", + "description" => "", + "email" => "admin@example.com", + "type" => "O", + "company_name" => "", + "allowed_domains" => "", + "invite_id" => "7mp9d3ayaj833ymmkfnid8js6w", + "allow_open_invite" => false + } + end + + before do + stub_request(:post, "http://mattermost.example.com/api/v3/teams/create") + .to_return( + status: 200, + body: response.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'returns the new team' do + is_expected.to eq(response) + end + end + + context 'for existing team' do + before do + stub_request(:post, 'http://mattermost.example.com/api/v3/teams/create') + .to_return( + status: 400, + headers: { 'Content-Type' => 'application/json' }, + body: { + id: "store.sql_team.save.domain_exists.app_error", + message: "A team with that name already exists", + detailed_error: "", + request_id: "1hsb5bxs97r8bdggayy7n9gxaw", + status_code: 400 + }.to_json + ) + end + + it 'raises an error with message' do + expect { subject }.to raise_error(Mattermost::Error, 'A team with that name already exists') + end + end + end + + describe '#delete' do + subject { described_class.new(nil).destroy(team_id: "cuojfcetjty7tb4pxe47pwpndo") } + + context 'for an existing team' do + let(:response) do + { + "status" => "OK" + } + end + + before do + stub_request(:delete, "http://mattermost.example.com/api/v4/teams/cuojfcetjty7tb4pxe47pwpndo") + .to_return( + status: 200, + body: response.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'returns team status' do + is_expected.to eq(response) + end + end + + context 'for an unknown team' do + before do + stub_request(:delete, "http://mattermost.example.com/api/v4/teams/cuojfcetjty7tb4pxe47pwpndo") + .to_return( + status: 404, + body: { + id: "store.sql_team.get.find.app_error", + message: "We couldn't find the existing team", + detailed_error: "", + request_id: "my114ab5nbnui8c9pes4kz8mza", + status_code: 404 + }.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'raises an error with message' do + expect { subject }.to raise_error(Mattermost::Error, "We couldn't find the existing team") + end + end + end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 579069ffa14..93a61c6ea71 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1447,7 +1447,6 @@ describe Repository do it 'expires the caches for an empty repository' do allow(repository).to receive(:empty?).and_return(true) - expect(cache).to receive(:expire).with(:empty?) expect(cache).to receive(:expire).with(:has_visible_content?) repository.expire_emptiness_caches @@ -1456,7 +1455,6 @@ describe Repository do it 'does not expire the cache for a non-empty repository' do allow(repository).to receive(:empty?).and_return(false) - expect(cache).not_to receive(:expire).with(:empty?) expect(cache).not_to receive(:expire).with(:has_visible_content?) repository.expire_emptiness_caches diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 00b5226d874..5680eb24985 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -27,7 +27,6 @@ describe User do it { is_expected.to have_many(:keys).dependent(:destroy) } it { is_expected.to have_many(:deploy_keys).dependent(:destroy) } it { is_expected.to have_many(:events).dependent(:destroy) } - it { is_expected.to have_many(:recent_events).class_name('Event') } it { is_expected.to have_many(:issues).dependent(:destroy) } it { is_expected.to have_many(:notes).dependent(:destroy) } it { is_expected.to have_many(:merge_requests).dependent(:destroy) } diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 56d025f0176..9345671a1a7 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -9,7 +9,7 @@ require 'spec_helper' # user_calendar_activities GET /u/:username/calendar_activities(.:format) describe UsersController, "routing" do it "to #show" do - allow_any_instance_of(UserUrlConstrainer).to receive(:matches?).and_return(true) + allow_any_instance_of(::Constraints::UserUrlConstrainer).to receive(:matches?).and_return(true) expect(get("/User")).to route_to('users#show', username: 'User') end @@ -210,7 +210,7 @@ describe Profiles::KeysController, "routing" do # get all the ssh-keys of a user it "to #get_keys" do - allow_any_instance_of(UserUrlConstrainer).to receive(:matches?).and_return(true) + allow_any_instance_of(::Constraints::UserUrlConstrainer).to receive(:matches?).and_return(true) expect(get("/foo.keys")).to route_to('profiles/keys#get_keys', username: 'foo') end diff --git a/vendor/project_templates/express.tar.gz b/vendor/project_templates/express.tar.gz Binary files differindex 06093deb459..dcf5e4a0416 100644 --- a/vendor/project_templates/express.tar.gz +++ b/vendor/project_templates/express.tar.gz diff --git a/vendor/project_templates/rails.tar.gz b/vendor/project_templates/rails.tar.gz Binary files differindex 85cc1b6bb78..d4856090ed9 100644 --- a/vendor/project_templates/rails.tar.gz +++ b/vendor/project_templates/rails.tar.gz diff --git a/vendor/project_templates/spring.tar.gz b/vendor/project_templates/spring.tar.gz Binary files differindex e98d3ce7b8f..6ee7e76f676 100644 --- a/vendor/project_templates/spring.tar.gz +++ b/vendor/project_templates/spring.tar.gz |