From be9aa7f19474424991923f128053e2523fa166d8 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 26 Jul 2016 09:35:47 +0200 Subject: Add an URL field to Environments This MR adds a string (thus max 255 chars) field to the enviroments table to expose it later in other features. --- app/models/environment.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/environment.rb b/app/models/environment.rb index ac3a571a1f3..9eff0fdab03 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -10,6 +10,10 @@ class Environment < ActiveRecord::Base format: { with: Gitlab::Regex.environment_name_regex, message: Gitlab::Regex.environment_name_regex_message } + validates :external_url, + uniqueness: { scope: :project_id }, + length: { maximum: 255 } + def last_deployment deployments.last end -- cgit v1.2.1 From 76e9b68439510af5c783a81b93944f1c8d96d150 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 26 Jul 2016 14:19:37 +0200 Subject: Incorporate feedback --- app/models/environment.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/environment.rb b/app/models/environment.rb index 9eff0fdab03..baed106e8c8 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -3,6 +3,8 @@ class Environment < ActiveRecord::Base has_many :deployments + before_validation :nullify_external_url + validates :name, presence: true, uniqueness: { scope: :project_id }, @@ -12,9 +14,15 @@ class Environment < ActiveRecord::Base validates :external_url, uniqueness: { scope: :project_id }, - length: { maximum: 255 } + length: { maximum: 255 }, + allow_nil: true, + addressable_url: true def last_deployment deployments.last end + + def nullify_external_url + self.external_url = nil if self.external_url.blank? + end end -- cgit v1.2.1 From 5b4ceeed6317cc8039642981ba356565e11d991e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 29 Jul 2016 18:24:11 -0300 Subject: Fix attr reader to force the intended values for source and target shas When importing a pull request from GitHub, the old and new branches may no longer actually exist by those names, but we need to recreate the merge request diff with the right source and target shas. We use these `target_branch_sha` and `source_branch_sha` attributes to force these to the intended values. But the reader methods were always looking up to the target/source branch head instead of check if these values was previously set. --- app/models/merge_request.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 471e32f3b60..fdcbbdc1d08 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -238,10 +238,14 @@ class MergeRequest < ActiveRecord::Base end def target_branch_sha + return @target_branch_sha if defined?(@target_branch_sha) + target_branch_head.try(:sha) end def source_branch_sha + return @source_branch_sha if defined?(@source_branch_sha) + source_branch_head.try(:sha) end -- cgit v1.2.1 From 285ba1b20f226f0bf7ab01010b64cabdccecf096 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Sun, 31 Jul 2016 19:44:02 -0300 Subject: fixup! Fix attr reader to force the intended values for source and target shas --- app/models/merge_request.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index fdcbbdc1d08..f1b9c1d6feb 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -238,15 +238,11 @@ class MergeRequest < ActiveRecord::Base end def target_branch_sha - return @target_branch_sha if defined?(@target_branch_sha) - - target_branch_head.try(:sha) + @target_branch_sha || target_branch_head.try(:sha) end def source_branch_sha - return @source_branch_sha if defined?(@source_branch_sha) - - source_branch_head.try(:sha) + @source_branch_sha || source_branch_head.try(:sha) end def diff_refs -- cgit v1.2.1 From aad0ae71620d8e988faf75587a612b933df00366 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 22 Jul 2016 12:10:45 +0200 Subject: squashed - fixed label and milestone association problems, updated specs and refactored reader class a bit --- app/models/label_link.rb | 6 ++++-- app/models/project.rb | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/label_link.rb b/app/models/label_link.rb index 47bd6eaf35f..51b5c2b1f4c 100644 --- a/app/models/label_link.rb +++ b/app/models/label_link.rb @@ -1,7 +1,9 @@ class LabelLink < ActiveRecord::Base + include Importable + belongs_to :target, polymorphic: true belongs_to :label - validates :target, presence: true - validates :label, presence: true + validates :target, presence: true, unless: :importing? + validates :label, presence: true, unless: :importing? end diff --git a/app/models/project.rb b/app/models/project.rb index 7aecd7860c5..83b848ded8b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1253,6 +1253,16 @@ class Project < ActiveRecord::Base authorized_for_user_by_shared_projects?(user, min_access_level) end + def append_or_update_attribute(name, value) + old_values = public_send(name.to_s) + + if Project.reflect_on_association(name).try(:macro) == :has_many && old_values.any? + update_attribute(name, old_values + value) + else + update_attribute(name, value) + end + end + private def authorized_for_user_by_group?(user, min_access_level) -- cgit v1.2.1 From 99c02ed53c994fbd71442410c78daf220c6d1ced Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 1 Aug 2016 13:11:45 -0700 Subject: Only use RequestStore in ProjectTeam#max_member_access_for_user if it is active --- app/models/project_team.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/project_team.rb b/app/models/project_team.rb index fdfaf052730..19fd082534c 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -138,8 +138,13 @@ class ProjectTeam def max_member_access_for_user_ids(user_ids) user_ids = user_ids.uniq key = "max_member_access:#{project.id}" - RequestStore.store[key] ||= {} - access = RequestStore.store[key] + + access = {} + + if RequestStore.active? + RequestStore.store[key] ||= {} + access = RequestStore.store[key] + end # Lookup only the IDs we need user_ids = user_ids - access.keys -- cgit v1.2.1 From edc5f4018e45327421e112de18d53bfbdabd38f9 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Mon, 1 Aug 2016 10:06:57 +0100 Subject: developer cannot push to protected branch when project is empty or he has not been granted permission to do so --- app/models/project.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index 83b848ded8b..507813bccf8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -870,10 +870,22 @@ class Project < ActiveRecord::Base # Check if current branch name is marked as protected in the system def protected_branch?(branch_name) + return true if empty_repo? && default_branch_protected? + @protected_branches ||= self.protected_branches.to_a ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present? end + def developers_can_push_to_protected_branch?(branch_name) + return true if empty_repo? && !default_branch_protected? + + protected_branches.matching(branch_name).any?(&:developers_can_push) + end + + def developers_can_merge_to_protected_branch?(branch_name) + protected_branches.matching(branch_name).any?(&:developers_can_merge) + end + def forked? !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) end @@ -1265,6 +1277,10 @@ class Project < ActiveRecord::Base private + def default_branch_protected? + current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL + end + def authorized_for_user_by_group?(user, min_access_level) member = user.group_members.find_by(source_id: group) -- cgit v1.2.1 From 4768afbdbf85abbb5e2281c8855e7d27c07a581e Mon Sep 17 00:00:00 2001 From: Keith Pope Date: Tue, 2 Aug 2016 06:56:23 +0100 Subject: Add simple identifier to public SSH keys --- app/models/key.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/key.rb b/app/models/key.rb index b9bc38a0436..568a60b8af3 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -26,8 +26,9 @@ class Key < ActiveRecord::Base end def publishable_key - # Removes anything beyond the keytype and key itself - self.key.split[0..1].join(' ') + # Strip out the keys comment so we don't leak email addresses + # Replace with simple ident of user_name (hostname) + self.key.split[0..1].push("#{self.user_name} (#{Gitlab.config.gitlab.host})").join(' ') end # projects that has this key -- cgit v1.2.1 From 020ea32e767b9ad033f9fedcaa902865a01fa944 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 2 Aug 2016 18:06:31 +0800 Subject: Implement pipeline hooks, extracted from !5525 Closes #20115 --- app/models/ci/pipeline.rb | 10 +++++++++- app/models/hooks/project_hook.rb | 1 + app/models/hooks/web_hook.rb | 1 + app/models/service.rb | 5 +++++ 4 files changed, 16 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bce6a992af6..4e6ccf48c68 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -237,7 +237,15 @@ module Ci self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration - save + saved = save + execute_hooks if saved && !skip_ci? + saved + end + + def execute_hooks + pipeline_data = Gitlab::DataBuilder::PipelineDataBuilder.build(self) + project.execute_hooks(pipeline_data, :pipeline_hooks) + project.execute_services(pipeline_data.dup, :pipeline_hooks) end def keep_around_commits diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index ba42a8eeb70..836a75b0608 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -5,5 +5,6 @@ class ProjectHook < WebHook scope :note_hooks, -> { where(note_events: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true) } scope :build_hooks, -> { where(build_events: true) } + scope :pipeline_hooks, -> { where(pipeline_events: true) } scope :wiki_page_hooks, -> { where(wiki_page_events: true) } end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 8b87b6c3d64..f365dee3141 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -8,6 +8,7 @@ class WebHook < ActiveRecord::Base default_value_for :merge_requests_events, false default_value_for :tag_push_events, false default_value_for :build_events, false + default_value_for :pipeline_events, false default_value_for :enable_ssl_verification, true scope :push_hooks, -> { where(push_events: true) } diff --git a/app/models/service.rb b/app/models/service.rb index 40cd9b861f0..e4cd44f542a 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -36,6 +36,7 @@ class Service < ActiveRecord::Base scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) } scope :note_hooks, -> { where(note_events: true, active: true) } scope :build_hooks, -> { where(build_events: true, active: true) } + scope :pipeline_hooks, -> { where(pipeline_events: true, active: true) } scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) } scope :external_issue_trackers, -> { issue_trackers.active.without_defaults } @@ -86,6 +87,10 @@ class Service < ActiveRecord::Base [] end + def event_names + supported_events.map { |event| "#{event}_events" } + end + def event_field(event) nil end -- cgit v1.2.1 From 8716ff7f63fff0b056e110bef930c32a98e86c63 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Mon, 1 Aug 2016 16:55:51 +0200 Subject: Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible - Preloading noteable we share the same noteable instance when more than one discussion refers to the same noteable. - Any other call to that object that is cached in that object will be for any discussion. - In those cases where merge_request_diff has all the sha stored to build a diff_refs get that diff_refs using directly those sha instead accessing to the git repository to first get the commits and later the sha. --- app/models/diff_note.rb | 12 ++++++++++-- app/models/discussion.rb | 6 ++++++ app/models/merge_request.rb | 15 ++++++++++++++- app/models/merge_request_diff.rb | 4 ++++ 4 files changed, 34 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index 9671955db36..c816deb4e0c 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -67,7 +67,7 @@ class DiffNote < Note return false unless supported? return true if for_commit? - diff_refs ||= self.noteable.diff_refs + diff_refs ||= noteable_diff_refs self.position.diff_refs == diff_refs end @@ -78,6 +78,14 @@ class DiffNote < Note !self.for_merge_request? || self.noteable.support_new_diff_notes? end + def noteable_diff_refs + if noteable.respond_to?(:diff_sha_refs) + noteable.diff_sha_refs + else + noteable.diff_refs + end + end + def set_original_position self.original_position = self.position.dup end @@ -96,7 +104,7 @@ class DiffNote < Note self.project, nil, old_diff_refs: self.position.diff_refs, - new_diff_refs: self.noteable.diff_refs, + new_diff_refs: noteable_diff_refs, paths: self.position.paths ).execute(self) end diff --git a/app/models/discussion.rb b/app/models/discussion.rb index 74facfd1c9c..e2218a5f02b 100644 --- a/app/models/discussion.rb +++ b/app/models/discussion.rb @@ -49,6 +49,12 @@ class Discussion self.noteable == target && !diff_discussion? end + def active? + return @active if defined?(@active) + + @active = first_note.active? + end + def expanded? !diff_discussion? || active? end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f1b9c1d6feb..a99c4ba52a4 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -255,6 +255,19 @@ class MergeRequest < ActiveRecord::Base ) end + # Return diff_refs instance trying to not touch the git repository + def diff_sha_refs + if merge_request_diff && merge_request_diff.diff_refs_by_sha? + return Gitlab::Diff::DiffRefs.new( + base_sha: merge_request_diff.base_commit_sha, + start_sha: merge_request_diff.start_commit_sha, + head_sha: merge_request_diff.head_commit_sha + ) + else + diff_refs + end + end + def validate_branches if target_project == source_project && target_branch == source_branch errors.add :branch_conflict, "You can not use same project/branch for source and target" @@ -659,7 +672,7 @@ class MergeRequest < ActiveRecord::Base end def support_new_diff_notes? - diff_refs && diff_refs.complete? + diff_sha_refs && diff_sha_refs.complete? end def update_diff_notes_positions(old_diff_refs:, new_diff_refs:) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 3f520c8f3ff..119266f2d2c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -82,6 +82,10 @@ class MergeRequestDiff < ActiveRecord::Base project.commit(self.head_commit_sha) end + def diff_refs_by_sha? + base_commit_sha? && head_commit_sha? && start_commit_sha? + end + def compare @compare ||= begin -- cgit v1.2.1 From e4c517a635b6a45a9afc65b37682cc4b4951e922 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 25 Jul 2016 23:49:06 -0500 Subject: Expand commit message width in repo view --- app/models/commit.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/commit.rb b/app/models/commit.rb index 486ad6714d9..c52b4a051c2 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -123,15 +123,17 @@ class Commit # In case this first line is longer than 100 characters, it is cut off # after 80 characters and ellipses (`&hellp;`) are appended. def title - title = safe_message + full_title.length > 100 ? full_title[0..79] << "…" : full_title + end - return no_commit_message if title.blank? + # Returns the full commits title + def full_title + return @full_title if @full_title - title_end = title.index("\n") - if (!title_end && title.length > 100) || (title_end && title_end > 100) - title[0..79] << "…" + if safe_message.blank? + @full_title = no_commit_message else - title.split("\n", 2).first + @full_title = safe_message.split("\n", 2).first end end -- cgit v1.2.1 From cd7c2cb6ddd4d9c9f9bdae00c887c0022c121c17 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 20 Jul 2016 18:25:36 +0200 Subject: Cache highlighted diff lines for merge requests Introducing the concept of SafeDiffs which relates diffs with UI highlighting. --- app/models/merge_request.rb | 2 ++ app/models/safe_diffs.rb | 5 ++++ app/models/safe_diffs/base.rb | 55 ++++++++++++++++++++++++++++++++++ app/models/safe_diffs/commit.rb | 10 +++++++ app/models/safe_diffs/compare.rb | 10 +++++++ app/models/safe_diffs/merge_request.rb | 52 ++++++++++++++++++++++++++++++++ 6 files changed, 134 insertions(+) create mode 100644 app/models/safe_diffs.rb create mode 100644 app/models/safe_diffs/base.rb create mode 100644 app/models/safe_diffs/commit.rb create mode 100644 app/models/safe_diffs/compare.rb create mode 100644 app/models/safe_diffs/merge_request.rb (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index a99c4ba52a4..774851cc90f 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -313,6 +313,8 @@ class MergeRequest < ActiveRecord::Base merge_request_diff.reload_content + MergeRequests::MergeRequestDiffCacheService.new.execute(self) + new_diff_refs = self.diff_refs update_diff_notes_positions( diff --git a/app/models/safe_diffs.rb b/app/models/safe_diffs.rb new file mode 100644 index 00000000000..8ca9ec4cc39 --- /dev/null +++ b/app/models/safe_diffs.rb @@ -0,0 +1,5 @@ +module SafeDiffs + def self.default_options + ::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false) + end +end diff --git a/app/models/safe_diffs/base.rb b/app/models/safe_diffs/base.rb new file mode 100644 index 00000000000..dfc4708e293 --- /dev/null +++ b/app/models/safe_diffs/base.rb @@ -0,0 +1,55 @@ +module SafeDiffs + class Base + attr_reader :project, :diff_options, :diff_view, :diff_refs + + delegate :count, :real_size, to: :diff_files + + def initialize(diffs, project:, diff_options:, diff_refs: nil) + @diffs = diffs + @project = project + @diff_options = diff_options + @diff_refs = diff_refs + end + + def diff_files + @diff_files ||= begin + diffs = @diffs.decorate! do |diff| + Gitlab::Diff::File.new(diff, diff_refs: @diff_refs, repository: @project.repository) + end + + highlight!(diffs) + diffs + end + end + + private + + def highlight!(diff_files) + if cacheable? + cache_highlight!(diff_files) + else + diff_files.each { |diff_file| highlight_diff_file!(diff_file) } + end + end + + def cacheable? + false + end + + def cache_highlight! + raise NotImplementedError + end + + def highlight_diff_file_from_cache!(diff_file, cache_diff_lines) + diff_file.diff_lines = cache_diff_lines.map do |line| + Gitlab::Diff::Line.init_from_hash(line) + end + end + + def highlight_diff_file!(diff_file) + diff_file.diff_lines = Gitlab::Diff::Highlight.new(diff_file, repository: diff_file.repository).highlight + diff_file.highlighted_diff_lines = diff_file.diff_lines # To be used on parallel diff + diff_file + end + end +end diff --git a/app/models/safe_diffs/commit.rb b/app/models/safe_diffs/commit.rb new file mode 100644 index 00000000000..338878f32e0 --- /dev/null +++ b/app/models/safe_diffs/commit.rb @@ -0,0 +1,10 @@ +module SafeDiffs + class Commit < Base + def initialize(commit, diff_options:) + super(commit.diffs(diff_options), + project: commit.project, + diff_options: diff_options, + diff_refs: commit.diff_refs) + end + end +end diff --git a/app/models/safe_diffs/compare.rb b/app/models/safe_diffs/compare.rb new file mode 100644 index 00000000000..6b64b81137d --- /dev/null +++ b/app/models/safe_diffs/compare.rb @@ -0,0 +1,10 @@ +module SafeDiffs + class Compare < Base + def initialize(compare, project:, diff_options:, diff_refs: nil) + super(compare.diffs(diff_options), + project: project, + diff_options: diff_options, + diff_refs: diff_refs) + end + end +end diff --git a/app/models/safe_diffs/merge_request.rb b/app/models/safe_diffs/merge_request.rb new file mode 100644 index 00000000000..111b9a54f91 --- /dev/null +++ b/app/models/safe_diffs/merge_request.rb @@ -0,0 +1,52 @@ +module SafeDiffs + class MergeRequest < Base + def initialize(merge_request, diff_options:) + @merge_request = merge_request + + super(merge_request.diffs(diff_options), + project: merge_request.project, + diff_options: diff_options, + diff_refs: merge_request.diff_refs) + end + + private + + # + # If we find the highlighted diff files lines on the cache we replace existing diff_files lines (no highlighted) + # for the highlighted ones, so we just skip their execution. + # If the highlighted diff files lines are not cached we calculate and cache them. + # + # The content of the cache is and Hash where the key correspond to the file_path and the values are Arrays of + # hashes than represent serialized diff lines. + # + def cache_highlight!(diff_files) + highlighted_cache = Rails.cache.read(cache_key) || {} + highlighted_cache_was_empty = highlighted_cache.empty? + + diff_files.each do |diff_file| + file_path = diff_file.file_path + + if highlighted_cache[file_path] + highlight_diff_file_from_cache!(diff_file, highlighted_cache[file_path]) + else + highlight_diff_file!(diff_file) + highlighted_cache[file_path] = diff_file.diff_lines.map(&:to_hash) + end + end + + if highlighted_cache_was_empty + Rails.cache.write(cache_key, highlighted_cache) + end + + diff_files + end + + def cacheable? + @merge_request.merge_request_diff.present? + end + + def cache_key + [@merge_request.merge_request_diff, 'highlighted-safe-diff-files', diff_options] + end + end +end -- cgit v1.2.1 From 8f359ea9170b984ad43d126e17628c31ac3a1f14 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Tue, 26 Jul 2016 09:21:42 +0200 Subject: Move to Gitlab::Diff::FileCollection Instead calling diff_collection.count use diff_collection.size which is cache on the diff_collection --- app/models/commit.rb | 4 +++ app/models/compare.rb | 23 ++++++++++++++ app/models/merge_request.rb | 4 +++ app/models/safe_diffs.rb | 5 ---- app/models/safe_diffs/base.rb | 55 ---------------------------------- app/models/safe_diffs/commit.rb | 10 ------- app/models/safe_diffs/compare.rb | 10 ------- app/models/safe_diffs/merge_request.rb | 52 -------------------------------- 8 files changed, 31 insertions(+), 132 deletions(-) create mode 100644 app/models/compare.rb delete mode 100644 app/models/safe_diffs.rb delete mode 100644 app/models/safe_diffs/base.rb delete mode 100644 app/models/safe_diffs/commit.rb delete mode 100644 app/models/safe_diffs/compare.rb delete mode 100644 app/models/safe_diffs/merge_request.rb (limited to 'app/models') diff --git a/app/models/commit.rb b/app/models/commit.rb index c52b4a051c2..d22ecb222e5 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -317,6 +317,10 @@ class Commit nil end + def diff_file_collection(diff_options) + Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options) + end + private def find_author_by_any_email diff --git a/app/models/compare.rb b/app/models/compare.rb new file mode 100644 index 00000000000..6672d1bf059 --- /dev/null +++ b/app/models/compare.rb @@ -0,0 +1,23 @@ +class Compare + delegate :commits, :same, :head, :base, to: :@compare + + def self.decorate(compare, project) + if compare.is_a?(Compare) + compare + else + self.new(compare, project) + end + end + + def initialize(compare, project) + @compare = compare + @project = project + end + + def diff_file_collection(diff_options:, diff_refs: nil) + Gitlab::Diff::FileCollection::Compare.new(@compare, + project: @project, + diff_options: diff_options, + diff_refs: diff_refs) + end +end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 774851cc90f..abc8bacbe59 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -168,6 +168,10 @@ class MergeRequest < ActiveRecord::Base merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args) end + def diff_file_collection(diff_options) + Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) + end + def diff_size merge_request_diff.size end diff --git a/app/models/safe_diffs.rb b/app/models/safe_diffs.rb deleted file mode 100644 index 8ca9ec4cc39..00000000000 --- a/app/models/safe_diffs.rb +++ /dev/null @@ -1,5 +0,0 @@ -module SafeDiffs - def self.default_options - ::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false) - end -end diff --git a/app/models/safe_diffs/base.rb b/app/models/safe_diffs/base.rb deleted file mode 100644 index dfc4708e293..00000000000 --- a/app/models/safe_diffs/base.rb +++ /dev/null @@ -1,55 +0,0 @@ -module SafeDiffs - class Base - attr_reader :project, :diff_options, :diff_view, :diff_refs - - delegate :count, :real_size, to: :diff_files - - def initialize(diffs, project:, diff_options:, diff_refs: nil) - @diffs = diffs - @project = project - @diff_options = diff_options - @diff_refs = diff_refs - end - - def diff_files - @diff_files ||= begin - diffs = @diffs.decorate! do |diff| - Gitlab::Diff::File.new(diff, diff_refs: @diff_refs, repository: @project.repository) - end - - highlight!(diffs) - diffs - end - end - - private - - def highlight!(diff_files) - if cacheable? - cache_highlight!(diff_files) - else - diff_files.each { |diff_file| highlight_diff_file!(diff_file) } - end - end - - def cacheable? - false - end - - def cache_highlight! - raise NotImplementedError - end - - def highlight_diff_file_from_cache!(diff_file, cache_diff_lines) - diff_file.diff_lines = cache_diff_lines.map do |line| - Gitlab::Diff::Line.init_from_hash(line) - end - end - - def highlight_diff_file!(diff_file) - diff_file.diff_lines = Gitlab::Diff::Highlight.new(diff_file, repository: diff_file.repository).highlight - diff_file.highlighted_diff_lines = diff_file.diff_lines # To be used on parallel diff - diff_file - end - end -end diff --git a/app/models/safe_diffs/commit.rb b/app/models/safe_diffs/commit.rb deleted file mode 100644 index 338878f32e0..00000000000 --- a/app/models/safe_diffs/commit.rb +++ /dev/null @@ -1,10 +0,0 @@ -module SafeDiffs - class Commit < Base - def initialize(commit, diff_options:) - super(commit.diffs(diff_options), - project: commit.project, - diff_options: diff_options, - diff_refs: commit.diff_refs) - end - end -end diff --git a/app/models/safe_diffs/compare.rb b/app/models/safe_diffs/compare.rb deleted file mode 100644 index 6b64b81137d..00000000000 --- a/app/models/safe_diffs/compare.rb +++ /dev/null @@ -1,10 +0,0 @@ -module SafeDiffs - class Compare < Base - def initialize(compare, project:, diff_options:, diff_refs: nil) - super(compare.diffs(diff_options), - project: project, - diff_options: diff_options, - diff_refs: diff_refs) - end - end -end diff --git a/app/models/safe_diffs/merge_request.rb b/app/models/safe_diffs/merge_request.rb deleted file mode 100644 index 111b9a54f91..00000000000 --- a/app/models/safe_diffs/merge_request.rb +++ /dev/null @@ -1,52 +0,0 @@ -module SafeDiffs - class MergeRequest < Base - def initialize(merge_request, diff_options:) - @merge_request = merge_request - - super(merge_request.diffs(diff_options), - project: merge_request.project, - diff_options: diff_options, - diff_refs: merge_request.diff_refs) - end - - private - - # - # If we find the highlighted diff files lines on the cache we replace existing diff_files lines (no highlighted) - # for the highlighted ones, so we just skip their execution. - # If the highlighted diff files lines are not cached we calculate and cache them. - # - # The content of the cache is and Hash where the key correspond to the file_path and the values are Arrays of - # hashes than represent serialized diff lines. - # - def cache_highlight!(diff_files) - highlighted_cache = Rails.cache.read(cache_key) || {} - highlighted_cache_was_empty = highlighted_cache.empty? - - diff_files.each do |diff_file| - file_path = diff_file.file_path - - if highlighted_cache[file_path] - highlight_diff_file_from_cache!(diff_file, highlighted_cache[file_path]) - else - highlight_diff_file!(diff_file) - highlighted_cache[file_path] = diff_file.diff_lines.map(&:to_hash) - end - end - - if highlighted_cache_was_empty - Rails.cache.write(cache_key, highlighted_cache) - end - - diff_files - end - - def cacheable? - @merge_request.merge_request_diff.present? - end - - def cache_key - [@merge_request.merge_request_diff, 'highlighted-safe-diff-files', diff_options] - end - end -end -- cgit v1.2.1 From 1d0c7b74920a94e488e6a2c090abb3e525438053 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 27 Jul 2016 13:09:52 +0200 Subject: Introduce Compare model in the codebase. This object will manage Gitlab::Git::Compare instances --- app/models/commit.rb | 2 +- app/models/compare.rb | 47 +++++++++++++++++++++++++++++++++++++++++++-- app/models/merge_request.rb | 8 ++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/commit.rb b/app/models/commit.rb index d22ecb222e5..a339d47f5f3 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -317,7 +317,7 @@ class Commit nil end - def diff_file_collection(diff_options) + def diff_file_collection(diff_options = nil) Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options) end diff --git a/app/models/compare.rb b/app/models/compare.rb index 6672d1bf059..05c8fbbcc36 100644 --- a/app/models/compare.rb +++ b/app/models/compare.rb @@ -1,5 +1,5 @@ class Compare - delegate :commits, :same, :head, :base, to: :@compare + delegate :same, :head, :base, to: :@compare def self.decorate(compare, project) if compare.is_a?(Compare) @@ -14,10 +14,53 @@ class Compare @project = project end - def diff_file_collection(diff_options:, diff_refs: nil) + def commits + @commits ||= Commit.decorate(@compare.commits, @project) + end + + def start_commit + return @start_commit if defined?(@start_commit) + + commit = @compare.base + @start_commit = commit ? ::Commit.new(commit, @project) : nil + end + + def commit + return @commit if defined?(@commit) + + commit = @compare.head + @commit = commit ? ::Commit.new(commit, @project) : nil + end + alias_method :head_commit, :commit + + # Used only on emails_on_push_worker.rb + def base_commit=(commit) + @base_commit = commit + end + + def base_commit + return @base_commit if defined?(@base_commit) + + @base_commit = if start_commit && commit + @project.merge_base_commit(start_commit.id, commit.id) + else + nil + end + end + + # keyword args until we get ride of diff_refs as argument + def diff_file_collection(diff_options:, diff_refs: self.diff_refs) Gitlab::Diff::FileCollection::Compare.new(@compare, project: @project, diff_options: diff_options, diff_refs: diff_refs) end + + def diff_refs + @diff_refs ||= Gitlab::Diff::DiffRefs.new( + base_sha: base_commit.try(:sha), + start_sha: start_commit.try(:sha), + head_sha: commit.try(:sha) + ) + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index abc8bacbe59..62e5573dfdc 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -168,8 +168,12 @@ class MergeRequest < ActiveRecord::Base merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args) end - def diff_file_collection(diff_options) - Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) + def diff_file_collection(diff_options = nil) + if self.compare + self.compare.diff_file_collection(diff_options: diff_options, diff_refs: diff_refs) + else + Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) + end end def diff_size -- cgit v1.2.1 From c86c1905b5574cac234315598d8d715fcaee3ea7 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 27 Jul 2016 19:00:34 +0200 Subject: switch from diff_file_collection to diffs So we have raw_diffs too --- app/models/commit.rb | 10 +++++++--- app/models/compare.rb | 36 ++++++++++++++++++------------------ app/models/legacy_diff_note.rb | 4 ++-- app/models/merge_request.rb | 8 ++++---- app/models/repository.rb | 2 +- 5 files changed, 32 insertions(+), 28 deletions(-) (limited to 'app/models') diff --git a/app/models/commit.rb b/app/models/commit.rb index a339d47f5f3..d58c2fb8106 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -104,7 +104,7 @@ class Commit end def diff_line_count - @diff_line_count ||= Commit::diff_line_count(self.diffs) + @diff_line_count ||= Commit::diff_line_count(raw_diffs) @diff_line_count end @@ -317,7 +317,11 @@ class Commit nil end - def diff_file_collection(diff_options = nil) + def raw_diffs(*args) + raw.diffs(*args) + end + + def diffs(diff_options = nil) Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options) end @@ -330,7 +334,7 @@ class Commit def repo_changes changes = { added: [], modified: [], removed: [] } - diffs.each do |diff| + raw_diffs.each do |diff| if diff.deleted_file changes[:removed] << diff.old_path elsif diff.renamed_file || diff.new_file diff --git a/app/models/compare.rb b/app/models/compare.rb index 05c8fbbcc36..98c042f3809 100644 --- a/app/models/compare.rb +++ b/app/models/compare.rb @@ -1,6 +1,8 @@ class Compare delegate :same, :head, :base, to: :@compare + attr_reader :project + def self.decorate(compare, project) if compare.is_a?(Compare) compare @@ -15,49 +17,47 @@ class Compare end def commits - @commits ||= Commit.decorate(@compare.commits, @project) + @commits ||= Commit.decorate(@compare.commits, project) end def start_commit return @start_commit if defined?(@start_commit) commit = @compare.base - @start_commit = commit ? ::Commit.new(commit, @project) : nil + @start_commit = commit ? ::Commit.new(commit, project) : nil end - def commit - return @commit if defined?(@commit) + def head_commit + return @head_commit if defined?(@head_commit) commit = @compare.head - @commit = commit ? ::Commit.new(commit, @project) : nil - end - alias_method :head_commit, :commit - - # Used only on emails_on_push_worker.rb - def base_commit=(commit) - @base_commit = commit + @head_commit = commit ? ::Commit.new(commit, project) : nil end + alias_method :commit, :head_commit def base_commit return @base_commit if defined?(@base_commit) - @base_commit = if start_commit && commit - @project.merge_base_commit(start_commit.id, commit.id) + @base_commit = if start_commit && head_commit + project.merge_base_commit(start_commit.id, head_commit.id) else nil end end - # keyword args until we get ride of diff_refs as argument - def diff_file_collection(diff_options:, diff_refs: self.diff_refs) - Gitlab::Diff::FileCollection::Compare.new(@compare, - project: @project, + def raw_diffs(*args) + @compare.diffs(*args) + end + + def diffs(diff_options:) + Gitlab::Diff::FileCollection::Compare.new(self, + project: project, diff_options: diff_options, diff_refs: diff_refs) end def diff_refs - @diff_refs ||= Gitlab::Diff::DiffRefs.new( + Gitlab::Diff::DiffRefs.new( base_sha: base_commit.try(:sha), start_sha: start_commit.try(:sha), head_sha: commit.try(:sha) diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb index 865712268a0..6ed66001513 100644 --- a/app/models/legacy_diff_note.rb +++ b/app/models/legacy_diff_note.rb @@ -85,7 +85,7 @@ class LegacyDiffNote < Note return nil unless noteable return @diff if defined?(@diff) - @diff = noteable.diffs(Commit.max_diff_options).find do |d| + @diff = noteable.raw_diffs(Commit.max_diff_options).find do |d| d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash end end @@ -116,7 +116,7 @@ class LegacyDiffNote < Note # Find the diff on noteable that matches our own def find_noteable_diff - diffs = noteable.diffs(Commit.max_diff_options) + diffs = noteable.raw_diffs(Commit.max_diff_options) diffs.find { |d| d.new_path == self.diff.new_path } end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 62e5573dfdc..009262d6b48 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -164,13 +164,13 @@ class MergeRequest < ActiveRecord::Base merge_request_diff ? merge_request_diff.first_commit : compare_commits.first end - def diffs(*args) - merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args) + def raw_diffs(*args) + merge_request_diff ? merge_request_diff.diffs(*args) : compare.raw_diffs(*args) end - def diff_file_collection(diff_options = nil) + def diffs(diff_options = nil) if self.compare - self.compare.diff_file_collection(diff_options: diff_options, diff_refs: diff_refs) + self.compare.diffs(diff_options: diff_options) else Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) end diff --git a/app/models/repository.rb b/app/models/repository.rb index bac37483c47..3d95344a68f 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -372,7 +372,7 @@ class Repository # We don't want to flush the cache if the commit didn't actually make any # changes to any of the possible avatar files. if revision && commit = self.commit(revision) - return unless commit.diffs. + return unless commit.raw_diffs. any? { |diff| AVATAR_FILES.include?(diff.new_path) } end -- cgit v1.2.1 From 62f115dd25c4d3639dceac1b3b81c9fe42eeedd3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 3 Aug 2016 14:35:11 +0800 Subject: Introduce execute_hooks_unless_ci_skipped --- app/models/ci/pipeline.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 4e6ccf48c68..f8506e33295 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -18,6 +18,7 @@ module Ci # Invalidate object and save if when touched after_touch :update_state + after_touch :execute_hooks_unless_ci_skipped after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name @@ -237,9 +238,11 @@ module Ci self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration - saved = save - execute_hooks if saved && !skip_ci? - saved + save + end + + def execute_hooks_unless_ci_skipped + execute_hooks unless skip_ci? end def execute_hooks -- cgit v1.2.1 From 405379bbfcb7821b3dae77e5254362f2d696bb7d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 15 Jul 2016 13:19:29 +0100 Subject: Store OTP secret key in secrets.yml .secret stores the secret token used for both encrypting login cookies and for encrypting stored OTP secrets. We can't rotate this, because that would invalidate all existing OTP secrets. If the secret token is present in the .secret file or an environment variable, save it as otp_key_base in secrets.yml. Now .secret can be rotated without invalidating OTP secrets. If the secret token isn't present (initial setup), then just generate a separate otp_key_base and save in secrets.yml. Update the docs to reflect that secrets.yml needs to be retained past upgrades, but .secret doesn't. --- app/models/user.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index db747434959..73368be7b1b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,13 +23,13 @@ class User < ActiveRecord::Base default_value_for :theme_id, gitlab_config.default_theme attr_encrypted :otp_secret, - key: Gitlab::Application.config.secret_key_base, + key: Gitlab::Application.secrets.otp_key_base, mode: :per_attribute_iv_and_salt, insecure_mode: true, algorithm: 'aes-256-cbc' devise :two_factor_authenticatable, - otp_secret_encryption_key: Gitlab::Application.config.secret_key_base + otp_secret_encryption_key: Gitlab::Application.secrets.otp_key_base devise :two_factor_backupable, otp_number_of_backup_codes: 10 serialize :otp_backup_codes, JSON -- cgit v1.2.1 From 9e06bde269b80b3af01b7cc00bdada1ce2e5e563 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 3 Aug 2016 23:39:14 +0800 Subject: Make sure we only fire hooks upon status changed --- app/models/ci/pipeline.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f8506e33295..822ba7b6c00 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -18,7 +18,7 @@ module Ci # Invalidate object and save if when touched after_touch :update_state - after_touch :execute_hooks_unless_ci_skipped + after_save :execute_hooks_if_status_changed after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name @@ -241,8 +241,8 @@ module Ci save end - def execute_hooks_unless_ci_skipped - execute_hooks unless skip_ci? + def execute_hooks_if_status_changed + execute_hooks if status_changed? && !skip_ci? end def execute_hooks -- cgit v1.2.1 From c008a1a9674f7c01b4504e22ed414b07eff05385 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 3 Aug 2016 09:32:01 -0700 Subject: Make Compare#diffs diff_options a regular argument --- app/models/compare.rb | 2 +- app/models/merge_request.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/compare.rb b/app/models/compare.rb index 98c042f3809..4856510f526 100644 --- a/app/models/compare.rb +++ b/app/models/compare.rb @@ -49,7 +49,7 @@ class Compare @compare.diffs(*args) end - def diffs(diff_options:) + def diffs(diff_options = nil) Gitlab::Diff::FileCollection::Compare.new(self, project: project, diff_options: diff_options, diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 009262d6b48..c4761fac2fb 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -170,7 +170,7 @@ class MergeRequest < ActiveRecord::Base def diffs(diff_options = nil) if self.compare - self.compare.diffs(diff_options: diff_options) + self.compare.diffs(diff_options) else Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) end -- cgit v1.2.1 From 94b3d33de1417b31ef3994e43f901941dc302ca0 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 4 Aug 2016 00:46:58 +0800 Subject: If we use Rails magic it's breaking this test: spec/lib/gitlab/data_builder/pipeline_data_builder_spec.rb Because it would trigger the event just after saved and it would load no builds and cache it. We should really avoid adding more magic. --- app/models/ci/pipeline.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 822ba7b6c00..ca41a998a2b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -18,7 +18,6 @@ module Ci # Invalidate object and save if when touched after_touch :update_state - after_save :execute_hooks_if_status_changed after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name @@ -230,6 +229,7 @@ module Ci def update_state statuses.reload + last_status = status self.status = if yaml_errors.blank? statuses.latest.status || 'skipped' else @@ -238,11 +238,9 @@ module Ci self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration - save - end - - def execute_hooks_if_status_changed - execute_hooks if status_changed? && !skip_ci? + saved = save + execute_hooks if last_status != status && saved && !skip_ci? + saved end def execute_hooks -- cgit v1.2.1 From 80671bf75cdac3f50615253b058fa04da6235a4f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 4 Aug 2016 01:18:33 +0800 Subject: Separate the concern for executing hooks and updating states --- app/models/ci/pipeline.rb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ca41a998a2b..81991e8aa60 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -228,8 +228,18 @@ module Ci end def update_state - statuses.reload last_status = status + + if update_state_from_commit_statuses + execute_hooks if last_status != status && !skip_ci? + true + else + false + end + end + + def update_state_from_commit_statuses + statuses.reload self.status = if yaml_errors.blank? statuses.latest.status || 'skipped' else @@ -238,9 +248,7 @@ module Ci self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration - saved = save - execute_hooks if last_status != status && saved && !skip_ci? - saved + save end def execute_hooks -- cgit v1.2.1 From a16c26c957ae893f6957fd0ad66c189d0b8ca079 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 29 Jul 2016 19:31:37 +0200 Subject: Speed up Commit#repo_changes --- app/models/commit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/commit.rb b/app/models/commit.rb index d58c2fb8106..cc413448ce8 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -334,7 +334,7 @@ class Commit def repo_changes changes = { added: [], modified: [], removed: [] } - raw_diffs.each do |diff| + raw_diffs(deltas_only: true).each do |diff| if diff.deleted_file changes[:removed] << diff.old_path elsif diff.renamed_file || diff.new_file -- cgit v1.2.1 From 6eba7188f1cd1fc0bfcb8b1cf46f40338dc892b5 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 29 Jul 2016 13:46:39 -0700 Subject: Use only deltas in diffs when scanning the last commit for changes in the avatar to save memory --- app/models/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index 3d95344a68f..c1170c470ea 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -372,7 +372,7 @@ class Repository # We don't want to flush the cache if the commit didn't actually make any # changes to any of the possible avatar files. if revision && commit = self.commit(revision) - return unless commit.raw_diffs. + return unless commit.raw_diffs(deltas_only: true). any? { |diff| AVATAR_FILES.include?(diff.new_path) } end -- cgit v1.2.1 From 631f59d4e7f449c59735cd7eab25cf407e06d5d8 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 3 Aug 2016 23:32:12 +0200 Subject: change the API on the merge_request_diff model from diffs -> raw_diffs --- app/models/merge_request.rb | 2 +- app/models/merge_request_diff.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index c4761fac2fb..b1fb3ce5d69 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -165,7 +165,7 @@ class MergeRequest < ActiveRecord::Base end def raw_diffs(*args) - merge_request_diff ? merge_request_diff.diffs(*args) : compare.raw_diffs(*args) + merge_request_diff ? merge_request_diff.raw_diffs(*args) : compare.raw_diffs(*args) end def diffs(diff_options = nil) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 119266f2d2c..fa0efe2d596 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -33,12 +33,12 @@ class MergeRequestDiff < ActiveRecord::Base end def size - real_size.presence || diffs.size + real_size.presence || raw_diffs.size end - def diffs(options={}) + def raw_diffs(options={}) if options[:ignore_whitespace_change] - @diffs_no_whitespace ||= begin + @raw_diffs_no_whitespace ||= begin compare = Gitlab::Git::Compare.new( repository.raw_repository, self.start_commit_sha || self.target_branch_sha, @@ -47,8 +47,8 @@ class MergeRequestDiff < ActiveRecord::Base compare.diffs(options) end else - @diffs ||= {} - @diffs[options] ||= load_diffs(st_diffs, options) + @raw_diffs ||= {} + @raw_diffs[options] ||= load_diffs(st_diffs, options) end end -- cgit v1.2.1 From 6a0bbb5aa58e37a0ad8c3817c4e809143adce1be Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 2 Aug 2016 11:32:28 +0200 Subject: using shared path for project import uploads and refactored gitlab remove export worker --- app/models/project.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index 83b848ded8b..a18aef09acd 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -378,11 +378,6 @@ class Project < ActiveRecord::Base joins(join_body).reorder('join_note_counts.amount DESC') end - - # Deletes gitlab project export files older than 24 hours - def remove_gitlab_exports! - Gitlab::Popen.popen(%W(find #{Gitlab::ImportExport.storage_path} -not -path #{Gitlab::ImportExport.storage_path} -mmin +1440 -delete)) - end end def repository_storage_path -- cgit v1.2.1 From f15ed5f0a5c298a2f0eb5aaa6d848364133532a5 Mon Sep 17 00:00:00 2001 From: Herminio Torres Date: Thu, 4 Aug 2016 01:35:17 -0300 Subject: Fix Rename `add_users_into_project` and `projects_ids` We never add things `into` projects, we just add them `to` projects. So how about we rename this to `add_users_to_project`. Rename `projects_ids` to `project_ids` by following the convention of rails. --- app/models/members/project_member.rb | 6 +++--- app/models/project_team.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index f39afc61ce9..f176feddbad 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -21,19 +21,19 @@ class ProjectMember < Member # or symbol like :master representing role # # Ex. - # add_users_into_projects( + # add_users_to_projects( # project_ids, # user_ids, # ProjectMember::MASTER # ) # - # add_users_into_projects( + # add_users_to_projects( # project_ids, # user_ids, # :master # ) # - def add_users_into_projects(project_ids, user_ids, access, current_user = nil) + def add_users_to_projects(project_ids, user_ids, access, current_user = nil) access_level = if roles_hash.has_key?(access) roles_hash[access] elsif roles_hash.values.include?(access.to_i) diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 19fd082534c..d0a714cd6fc 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -34,7 +34,7 @@ class ProjectTeam end def add_users(users, access, current_user = nil) - ProjectMember.add_users_into_projects( + ProjectMember.add_users_to_projects( [project.id], users, access, -- cgit v1.2.1 From 705085db0c3b869f62f1b0f742686cc2082001fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 4 Aug 2016 16:00:31 +0200 Subject: Move abilities by subject class to a dedicated method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will avoid lame conflicts when merging CE to EE Signed-off-by: Rémy Coutable --- app/models/ability.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/ability.rb b/app/models/ability.rb index d95a2507199..d9113ffd99a 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -6,6 +6,10 @@ class Ability return [] unless user.is_a?(User) return [] if user.blocked? + abilities_by_subject_class(user: user, subject: subject) + end + + def abilities_by_subject_class(user:, subject:) case subject when CommitStatus then commit_status_abilities(user, subject) when Project then project_abilities(user, subject) -- cgit v1.2.1 From 984367f957c8f8d02fa82b08817e2f2f318c6bff Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 4 Aug 2016 23:44:27 +0800 Subject: Move those builders to their own namespace, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5620#note_13540099 --- app/models/ci/build.rb | 4 ++-- app/models/project_services/builds_email_service.rb | 2 +- app/models/service.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 08f396210c9..b919846af22 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -349,7 +349,7 @@ module Ci def execute_hooks return unless project - build_data = Gitlab::BuildDataBuilder.build(self) + build_data = Gitlab::DataBuilder::BuildDataBuilder.build(self) project.execute_hooks(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks) project.running_or_pending_build_count(force: true) @@ -461,7 +461,7 @@ module Ci def build_attributes_from_config return {} unless pipeline.config_processor - + pipeline.config_processor.build_attributes(name) end end diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb index 5e166471077..bf8c68244a1 100644 --- a/app/models/project_services/builds_email_service.rb +++ b/app/models/project_services/builds_email_service.rb @@ -52,7 +52,7 @@ class BuildsEmailService < Service def test_data(project = nil, user = nil) build = project.builds.last - Gitlab::BuildDataBuilder.build(build) + Gitlab::DataBuilder::BuildDataBuilder.build(build) end def fields diff --git a/app/models/service.rb b/app/models/service.rb index e4cd44f542a..76f588f234d 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -80,7 +80,7 @@ class Service < ActiveRecord::Base end def test_data(project, user) - Gitlab::PushDataBuilder.build_sample(project, user) + Gitlab::DataBuilder::PushDataBuilder.build_sample(project, user) end def event_channel_names -- cgit v1.2.1 From 584258dbb82f76c627d8552fc96689c7879b36f6 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 5 Aug 2016 00:43:16 +0800 Subject: Share nothing so it's safest, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5620#note_13581090 --- app/models/ci/pipeline.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 81991e8aa60..59ab8b5ce35 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -252,9 +252,12 @@ module Ci end def execute_hooks - pipeline_data = Gitlab::DataBuilder::PipelineDataBuilder.build(self) project.execute_hooks(pipeline_data, :pipeline_hooks) - project.execute_services(pipeline_data.dup, :pipeline_hooks) + project.execute_services(pipeline_data, :pipeline_hooks) + end + + def pipeline_data + Gitlab::DataBuilder::PipelineDataBuilder.build(self) end def keep_around_commits -- cgit v1.2.1 From 901536b36f3f5d95bd9ba33a2b99ef1c171c1133 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 5 Aug 2016 00:53:07 +0800 Subject: No need to check that as in CreateCommitBuildsService: Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5620#note_13581358 --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 59ab8b5ce35..d6b75411022 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -231,7 +231,7 @@ module Ci last_status = status if update_state_from_commit_statuses - execute_hooks if last_status != status && !skip_ci? + execute_hooks if last_status != status true else false -- cgit v1.2.1 From 482d7802cc71280595cad71882bf1b438461e435 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Mon, 1 Aug 2016 16:48:15 +0100 Subject: changes default_branch_protection to allow devs_can_merge protection option aswell --- app/models/project.rb | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index 507813bccf8..16a418d5a3f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -876,14 +876,8 @@ class Project < ActiveRecord::Base ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present? end - def developers_can_push_to_protected_branch?(branch_name) - return true if empty_repo? && !default_branch_protected? - - protected_branches.matching(branch_name).any?(&:developers_can_push) - end - - def developers_can_merge_to_protected_branch?(branch_name) - protected_branches.matching(branch_name).any?(&:developers_can_merge) + def user_can_push_to_empty_repo?(user) + !default_branch_protected? || team.max_member_access(user.id) > Gitlab::Access::DEVELOPER end def forked? @@ -1278,7 +1272,8 @@ class Project < ActiveRecord::Base private def default_branch_protected? - current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL + current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL || + current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE end def authorized_for_user_by_group?(user, min_access_level) -- cgit v1.2.1 From c9aa19881cf719baaea1bbb9bb00f84145a99b8b Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Sat, 6 Aug 2016 04:03:01 +0200 Subject: Enable Style/SpaceAroundEqualsInParameterDefault cop --- app/models/merge_request_diff.rb | 2 +- app/models/repository.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index fa0efe2d596..32cc6a3bfea 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -36,7 +36,7 @@ class MergeRequestDiff < ActiveRecord::Base real_size.presence || raw_diffs.size end - def raw_diffs(options={}) + def raw_diffs(options = {}) if options[:ignore_whitespace_change] @raw_diffs_no_whitespace ||= begin compare = Gitlab::Git::Compare.new( diff --git a/app/models/repository.rb b/app/models/repository.rb index c1170c470ea..701f867f67c 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -601,7 +601,7 @@ class Repository commit(sha) end - def next_branch(name, opts={}) + def next_branch(name, opts = {}) branch_ids = self.branch_names.map do |n| next 1 if n == name result = n.match(/\A#{name}-([0-9]+)\z/) -- cgit v1.2.1 From 77c8520e2ecd70520757aed0fbdf434643b60234 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 8 Aug 2016 16:18:13 +0200 Subject: Added concern for a faster "cache_key" method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This concern provides an optimized/simplified version of the "cache_key" method. This method is about 9 times faster than the default "cache_key" method. The produced cache keys _are_ different from the previous ones but this is worth the performance improvement. To showcase this I set up a benchmark (using benchmark-ips) that compares FasterCacheKeys#cache_key with the regular cache_key. The output of this benchmark was: Calculating ------------------------------------- cache_key 4.825k i/100ms cache_key_fast 21.723k i/100ms ------------------------------------------------- cache_key 59.422k (± 7.2%) i/s - 299.150k cache_key_fast 543.243k (± 9.2%) i/s - 2.694M Comparison: cache_key_fast: 543243.4 i/s cache_key: 59422.0 i/s - 9.14x slower To see the impact on real code I applied these changes and benchmarked Issue#referenced_merge_requests. For an issue referencing 10 merge requests these changes shaved off between 40 and 60 milliseconds. --- app/models/concerns/faster_cache_keys.rb | 16 ++++++++++++++++ app/models/issue.rb | 1 + app/models/note.rb | 1 + 3 files changed, 18 insertions(+) create mode 100644 app/models/concerns/faster_cache_keys.rb (limited to 'app/models') diff --git a/app/models/concerns/faster_cache_keys.rb b/app/models/concerns/faster_cache_keys.rb new file mode 100644 index 00000000000..5b14723fa2d --- /dev/null +++ b/app/models/concerns/faster_cache_keys.rb @@ -0,0 +1,16 @@ +module FasterCacheKeys + # A faster version of Rails' "cache_key" method. + # + # Rails' default "cache_key" method uses all kind of complex logic to figure + # out the cache key. In many cases this complexity and overhead may not be + # needed. + # + # This method does not do any timestamp parsing as this process is quite + # expensive and not needed when generating cache keys. This method also relies + # on the table name instead of the cache namespace name as the latter uses + # complex logic to generate the exact same value (as when using the table + # name) in 99% of the cases. + def cache_key + "#{self.class.table_name}/#{id}-#{read_attribute_before_type_cast(:updated_at)}" + end +end diff --git a/app/models/issue.rb b/app/models/issue.rb index 11f734cfc6d..d62ffb21467 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -7,6 +7,7 @@ class Issue < ActiveRecord::Base include Sortable include Taskable include Spammable + include FasterCacheKeys DueDateStruct = Struct.new(:title, :name).freeze NoDueDate = DueDateStruct.new('No Due Date', '0').freeze diff --git a/app/models/note.rb b/app/models/note.rb index b6b2ac6aa42..ddcd7f9d034 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -5,6 +5,7 @@ class Note < ActiveRecord::Base include Mentionable include Awardable include Importable + include FasterCacheKeys # Attribute containing rendered and redacted Markdown as generated by # Banzai::ObjectRenderer. -- cgit v1.2.1 From 6af4efea872407bf7f3957f3009984989a3a8e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Mon, 8 Aug 2016 14:36:39 -0400 Subject: Update version_sorter and use new interface for faster tag sorting --- app/models/repository.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index 701f867f67c..e56bac509a4 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -636,9 +636,7 @@ class Repository def tags_sorted_by(value) case value when 'name' - # Would be better to use `sort_by` but `version_sorter` only exposes - # `sort` and `rsort` - VersionSorter.rsort(tag_names).map { |tag_name| find_tag(tag_name) } + VersionSorter.rsort(tags) { |tag| tag.name } when 'updated_desc' tags_sorted_by_committed_date.reverse when 'updated_asc' -- cgit v1.2.1 From 1e6316172b913b622379675d3d48e6837dfc1843 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 9 Aug 2016 14:08:33 -0700 Subject: Add a method in Project to return a cached value of total count of projects This is in preparation to address the DB load caused by the counting in gitlab-com/infrastructure#303. --- app/models/project.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index a667857d058..d306f86f783 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -378,6 +378,12 @@ class Project < ActiveRecord::Base joins(join_body).reorder('join_note_counts.amount DESC') end + + def cached_count + Rails.cache.fetch('total_project_count', expires_in: 5.minutes) do + Project.count + end + end end def repository_storage_path -- cgit v1.2.1 From 4955a47cb1c52168114364e45a2fccf6bc105452 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 6 Aug 2016 07:25:51 -0700 Subject: Clean up project destruction Instead of redirecting from the project service to the service and back to the model, put all destruction code in the service. Also removes a possible source of failure where run_after_commit may not destroy the project. --- app/models/project.rb | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index d306f86f783..3b1a53edc75 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1161,16 +1161,6 @@ class Project < ActiveRecord::Base @wiki ||= ProjectWiki.new(self, self.owner) end - def schedule_delete!(user_id, params) - # Queue this task for after the commit, so once we mark pending_delete it will run - run_after_commit do - job_id = ProjectDestroyWorker.perform_async(id, user_id, params) - Rails.logger.info("User #{user_id} scheduled destruction of project #{path_with_namespace} with job ID #{job_id}") - end - - update_attribute(:pending_delete, true) - end - def running_or_pending_build_count(force: false) Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do builds.running_or_pending.count(:all) -- cgit v1.2.1 From 29850364eccccc3ce7305f6706cea1d5d073de2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 23 Jun 2016 17:14:31 +0200 Subject: New AccessRequests API endpoints for Group & Project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, mutualize AccessRequests and Members endpoints for Group & Project. New API documentation for the AccessRequests endpoints. Signed-off-by: Rémy Coutable --- app/models/members/project_member.rb | 1 + app/models/project.rb | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'app/models') diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index f176feddbad..18e97c969d7 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -8,6 +8,7 @@ class ProjectMember < Member # Make sure project member points only to project as it source default_value_for :source_type, SOURCE_TYPE validates_format_of :source_type, with: /\AProject\z/ + validates :access_level, inclusion: { in: Gitlab::Access.values } default_scope { where(source_type: SOURCE_TYPE) } scope :in_project, ->(project) { where(source_id: project.id) } diff --git a/app/models/project.rb b/app/models/project.rb index 3b1a53edc75..e0b28160937 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -999,6 +999,10 @@ class Project < ActiveRecord::Base project_members.find_by(user_id: user) end + def add_user(user, access_level, current_user = nil) + team.add_user(user, access_level, current_user) + end + def default_branch @default_branch ||= repository.root_ref if repository.exists? end -- cgit v1.2.1 From fb748daf538e43efcf8884f017391bcbfccf2ea2 Mon Sep 17 00:00:00 2001 From: Thomas Balthazar Date: Wed, 10 Aug 2016 12:25:01 +0200 Subject: Replace the tinder gem by bare HTTP requests --- app/models/project_services/campfire_service.rb | 51 +++++++++++++++++++++---- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 511b2eac792..5af93860d09 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -1,4 +1,6 @@ class CampfireService < Service + include HTTParty + prop_accessor :token, :subdomain, :room validates :token, presence: true, if: :activated? @@ -29,18 +31,53 @@ class CampfireService < Service def execute(data) return unless supported_events.include?(data[:object_kind]) - room = gate.find_room_by_name(self.room) - return true unless room - + self.class.base_uri base_uri message = build_message(data) - - room.speak(message) + speak(self.room, message, auth) end private - def gate - @gate ||= Tinder::Campfire.new(subdomain, token: token) + def base_uri + @base_uri ||= "https://#{subdomain}.campfirenow.com" + end + + def auth + # use a dummy password, as explained in the Campfire API doc: + # https://github.com/basecamp/campfire-api#authentication + @auth ||= { + basic_auth: { + username: token, + password: 'X' + } + } + end + + # Post a message into a room, returns the message Hash in case of success. + # Returns nil otherwise. + # https://github.com/basecamp/campfire-api/blob/master/sections/messages.md#create-message + def speak(room_name, message, auth) + room = rooms(auth).find { |r| r["name"] == room_name } + return nil unless room + + path = "/room/#{room["id"]}/speak.json" + body = { + body: { + message: { + type: 'TextMessage', + body: message + } + } + } + res = self.class.post(path, auth.merge(body)) + res.code == 201 ? res : nil + end + + # Returns a list of rooms, or []. + # https://github.com/basecamp/campfire-api/blob/master/sections/rooms.md#get-rooms + def rooms(auth) + res = self.class.get("/rooms.json", auth) + res.code == 200 ? res["rooms"] : [] end def build_message(push) -- cgit v1.2.1 From 39203f1adfc6fee3eca50f0cab99ffc597865200 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 15:22:35 +0200 Subject: Pre-create all builds for Pipeline when a trigger is received This change simplifies a Pipeline processing by introducing a special new status: created. This status is used for all builds that are created for a pipeline. We are then processing next stages and queueing some of the builds (created -> pending) or skipping them (created -> skipped). This makes it possible to simplify and solve a few ordering problems with how previously builds were scheduled. This also allows us to visualise a full pipeline (with created builds). This also removes an after_touch used for updating a pipeline state parameters. Right now in various places we explicitly call a reload_status! on pipeline to force it to be updated and saved. --- app/models/ci/build.rb | 12 ++---- app/models/ci/pipeline.rb | 84 ++++++++++++-------------------------- app/models/commit_status.rb | 31 ++++++++++---- app/models/concerns/statuseable.rb | 31 ++++++++------ 4 files changed, 72 insertions(+), 86 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 08f396210c9..88a340379b8 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -16,7 +16,7 @@ module Ci scope :with_artifacts_not_expired, ->() { with_artifacts.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } - scope :manual_actions, ->() { where(when: :manual) } + scope :manual_actions, ->() { where(when: :manual).relevant } mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader @@ -65,17 +65,11 @@ module Ci end end - state_machine :status, initial: :pending do + state_machine :status do after_transition pending: :running do |build| build.execute_hooks end - # We use around_transition to create builds for next stage as soon as possible, before the `after_*` is executed - around_transition any => [:success, :failed, :canceled] do |build, block| - block.call - build.pipeline.create_next_builds(build) if build.pipeline - end - after_transition any => [:success, :failed, :canceled] do |build| build.update_coverage build.execute_hooks @@ -461,7 +455,7 @@ module Ci def build_attributes_from_config return {} unless pipeline.config_processor - + pipeline.config_processor.build_attributes(name) end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bce6a992af6..718fe3290c1 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -13,11 +13,10 @@ module Ci has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id validates_presence_of :sha + validates_presence_of :ref validates_presence_of :status validate :valid_commit_sha - # Invalidate object and save if when touched - after_touch :update_state after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name @@ -90,12 +89,16 @@ module Ci def cancel_running builds.running_or_pending.each(&:cancel) + + reload_status! end def retry_failed(user) builds.latest.failed.select(&:retryable?).each do |build| Ci::Build.retry(build, user) end + + reload_status! end def latest? @@ -109,37 +112,6 @@ module Ci trigger_requests.any? end - def create_builds(user, trigger_request = nil) - ## - # We persist pipeline only if there are builds available - # - return unless config_processor - - build_builds_for_stages(config_processor.stages, user, - 'success', trigger_request) && save - end - - def create_next_builds(build) - return unless config_processor - - # don't create other builds if this one is retried - latest_builds = builds.latest - return unless latest_builds.exists?(build.id) - - # get list of stages after this build - next_stages = config_processor.stages.drop_while { |stage| stage != build.stage } - next_stages.delete(build.stage) - - # get status for all prior builds - prior_builds = latest_builds.where.not(stage: next_stages) - prior_status = prior_builds.status - - # build builds for next stage that has builds available - # and save pipeline if we have builds - build_builds_for_stages(next_stages, build.user, prior_status, - build.trigger_request) && save - end - def retried @retried ||= (statuses.order(id: :desc) - statuses.latest) end @@ -151,6 +123,14 @@ module Ci end end + def config_builds_attributes + return [] unless config_processor + + config_processor. + builds_for_ref(ref, tag?, trigger_requests.first). + sort_by { |build| build[:stage_idx] } + end + def has_warnings? builds.latest.ignored.any? end @@ -182,10 +162,6 @@ module Ci end end - def skip_ci? - git_commit_message =~ /\[(ci skip|skip ci)\]/i if git_commit_message - end - def environments builds.where.not(environment: nil).success.pluck(:environment).uniq end @@ -207,39 +183,33 @@ module Ci Note.for_commit_id(sha) end + def process! + Ci::ProcessPipelineService.new(project, user).execute(self) + reload_status! + end + def predefined_variables [ { key: 'CI_PIPELINE_ID', value: id.to_s, public: true } ] end - private - - def build_builds_for_stages(stages, user, status, trigger_request) - ## - # Note that `Array#any?` implements a short circuit evaluation, so we - # build builds only for the first stage that has builds available. - # - stages.any? do |stage| - CreateBuildsService.new(self). - execute(stage, user, status, trigger_request). - any?(&:active?) - end - end - - def update_state + def reload_status! statuses.reload - self.status = if yaml_errors.blank? - statuses.latest.status || 'skipped' - else - 'failed' - end + self.status = + if yaml_errors.blank? + statuses.latest.status || 'skipped' + else + 'failed' + end self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration save end + private + def keep_around_commits return unless project diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 2d185c28809..20713314a25 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base self.table_name = 'ci_builds' belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id - belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id, touch: true + belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :user delegate :commit, to: :pipeline @@ -25,28 +25,36 @@ class CommitStatus < ActiveRecord::Base scope :ordered, -> { order(:name) } scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } - state_machine :status, initial: :pending do + state_machine :status do event :queue do - transition skipped: :pending + transition [:created, :skipped] => :pending end event :run do transition pending: :running end + event :skip do + transition [:created, :pending] => :skipped + end + event :drop do - transition [:pending, :running] => :failed + transition [:created, :pending, :running] => :failed end event :success do - transition [:pending, :running] => :success + transition [:created, :pending, :running] => :success end event :cancel do - transition [:pending, :running] => :canceled + transition [:created, :pending, :running] => :canceled + end + + after_transition created: [:pending, :running] do |commit_status| + commit_status.update_attributes queued_at: Time.now end - after_transition pending: :running do |commit_status| + after_transition [:created, :pending] => :running do |commit_status| commit_status.update_attributes started_at: Time.now end @@ -54,13 +62,20 @@ class CommitStatus < ActiveRecord::Base commit_status.update_attributes finished_at: Time.now end - after_transition [:pending, :running] => :success do |commit_status| + after_transition [:created, :pending, :running] => :success do |commit_status| MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.pipeline.project, nil).trigger(commit_status) end after_transition any => :failed do |commit_status| MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.pipeline.project, nil).execute(commit_status) end + + # We use around_transition to process pipeline on next stages as soon as possible, before the `after_*` is executed + around_transition any => [:success, :failed, :canceled] do |commit_status, block| + block.call + + commit_status.pipeline.process! if commit_status.pipeline + end end delegate :sha, :short_sha, to: :pipeline diff --git a/app/models/concerns/statuseable.rb b/app/models/concerns/statuseable.rb index 44c6b30f278..5d4b0a86899 100644 --- a/app/models/concerns/statuseable.rb +++ b/app/models/concerns/statuseable.rb @@ -1,18 +1,22 @@ module Statuseable extend ActiveSupport::Concern - AVAILABLE_STATUSES = %w(pending running success failed canceled skipped) + AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped] + STARTED_STATUSES = %w[running success failed skipped] + ACTIVE_STATUSES = %w[pending running] + COMPLETED_STATUSES = %w[success failed canceled] class_methods do def status_sql - builds = all.select('count(*)').to_sql - success = all.success.select('count(*)').to_sql - ignored = all.ignored.select('count(*)').to_sql if all.respond_to?(:ignored) + scope = all.relevant + builds = scope.select('count(*)').to_sql + success = scope.success.select('count(*)').to_sql + ignored = scope.ignored.select('count(*)').to_sql if scope.respond_to?(:ignored) ignored ||= '0' - pending = all.pending.select('count(*)').to_sql - running = all.running.select('count(*)').to_sql - canceled = all.canceled.select('count(*)').to_sql - skipped = all.skipped.select('count(*)').to_sql + pending = scope.pending.select('count(*)').to_sql + running = scope.running.select('count(*)').to_sql + canceled = scope.canceled.select('count(*)').to_sql + skipped = scope.skipped.select('count(*)').to_sql deduce_status = "(CASE WHEN (#{builds})=0 THEN NULL @@ -48,7 +52,8 @@ module Statuseable included do validates :status, inclusion: { in: AVAILABLE_STATUSES } - state_machine :status, initial: :pending do + state_machine :status, initial: :created do + state :created, value: 'created' state :pending, value: 'pending' state :running, value: 'running' state :failed, value: 'failed' @@ -57,6 +62,8 @@ module Statuseable state :skipped, value: 'skipped' end + scope :created, -> { where(status: 'created') } + scope :relevant, -> { where.not(status: 'created') } scope :running, -> { where(status: 'running') } scope :pending, -> { where(status: 'pending') } scope :success, -> { where(status: 'success') } @@ -68,14 +75,14 @@ module Statuseable end def started? - !pending? && !canceled? && started_at + STARTED_STATUSES.include?(status) && started_at end def active? - running? || pending? + ACTIVE_STATUSES.include?(status) end def complete? - canceled? || success? || failed? + COMPLETED_STATUSES.include?(status) end end -- cgit v1.2.1 From ffa75a497a23bf6f87de626fee08ff4538a12587 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 17:23:07 +0200 Subject: Remove stage parameter from send payload --- app/models/ci/pipeline.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 9545a6e3ab9..e2663f50dd1 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -19,6 +19,8 @@ module Ci after_save :keep_around_commits + delegate :stages, to: :statuses + # ref can't be HEAD or SHA, can only be branch/tag name scope :latest_successful_for, ->(ref = default_branch) do where(ref: ref).success.order(id: :desc).limit(1) -- cgit v1.2.1 From c2a1011f529c21b8b571edc0daaf1f4875509e48 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 11 Aug 2016 08:45:14 -0700 Subject: Remove unused SpamReport model; this was renamed to SpamLog --- app/models/spam_report.rb | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 app/models/spam_report.rb (limited to 'app/models') diff --git a/app/models/spam_report.rb b/app/models/spam_report.rb deleted file mode 100644 index cdc7321b08e..00000000000 --- a/app/models/spam_report.rb +++ /dev/null @@ -1,5 +0,0 @@ -class SpamReport < ActiveRecord::Base - belongs_to :user - - validates :user, presence: true -end -- cgit v1.2.1 From 6109daf480327581b6e2dcdfffe90464be6c7796 Mon Sep 17 00:00:00 2001 From: Scott Le Date: Thu, 28 Jul 2016 11:04:57 +0700 Subject: api for generating new merge request DRY code + fix rubocop Add more test cases Append to changelog DRY changes list find_url service for merge_requests use GET for getting merge request links remove files rename to get_url_service reduce loop add test case for cross project refactor tiny thing update changelog --- app/models/merge_request.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b1fb3ce5d69..f6d0d0c98f5 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -104,6 +104,7 @@ class MergeRequest < ActiveRecord::Base scope :from_project, ->(project) { where(source_project_id: project.id) } scope :merged, -> { with_state(:merged) } scope :closed_and_merged, -> { with_states(:closed, :merged) } + scope :from_source_branches, ->(branches) { where(source_branch: branches) } scope :join_project, -> { joins(:target_project) } scope :references_project, -> { references(:target_project) } -- cgit v1.2.1 From 478990bb3ee0aa6939b656763a97d637189f062d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 18:37:36 +0200 Subject: Fix pipeline status change from pending to running --- app/models/ci/pipeline.rb | 3 ++- app/models/commit_status.rb | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index e2663f50dd1..bf8750ca0f6 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -187,6 +187,7 @@ module Ci def process! Ci::ProcessPipelineService.new(project, user).execute(self) + reload_status! end @@ -197,7 +198,7 @@ module Ci end def reload_status! - statuses.reload + reload self.status = if yaml_errors.blank? statuses.latest.status || 'skipped' diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 20713314a25..3ab44461179 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -76,6 +76,12 @@ class CommitStatus < ActiveRecord::Base commit_status.pipeline.process! if commit_status.pipeline end + + around_transition any => [:pending, :running] do |commit_status, block| + block.call + + commit_status.pipeline.reload_status! if commit_status.pipeline + end end delegate :sha, :short_sha, to: :pipeline -- cgit v1.2.1 From e2c01f397f2f00138d2b4e618306ee2aa141c97c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 18:37:50 +0200 Subject: Fix tests for pipeline events --- app/models/ci/pipeline.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bf8750ca0f6..f8c0e27a5c3 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -208,8 +208,10 @@ module Ci self.started_at = statuses.started_at self.finished_at = statuses.finished_at self.duration = statuses.latest.duration + + should_execute_hooks = status_changed? save - execute_hooks if status_changed? + execute_hooks if should_execute_hooks end private -- cgit v1.2.1 From d983c5bd4671d989edf3741d0db0a54dcef9c3b6 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 18:37:36 +0200 Subject: Verify the pipeline status after executing events on builds --- app/models/ci/pipeline.rb | 3 ++- app/models/commit_status.rb | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 718fe3290c1..8de799d6088 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -185,6 +185,7 @@ module Ci def process! Ci::ProcessPipelineService.new(project, user).execute(self) + reload_status! end @@ -195,7 +196,7 @@ module Ci end def reload_status! - statuses.reload + reload self.status = if yaml_errors.blank? statuses.latest.status || 'skipped' diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 20713314a25..3ab44461179 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -76,6 +76,12 @@ class CommitStatus < ActiveRecord::Base commit_status.pipeline.process! if commit_status.pipeline end + + around_transition any => [:pending, :running] do |commit_status, block| + block.call + + commit_status.pipeline.reload_status! if commit_status.pipeline + end end delegate :sha, :short_sha, to: :pipeline -- cgit v1.2.1 From 49f72e705fa225175834b5e6b2b1f78f1f608b9c Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 2 Aug 2016 14:01:22 +0200 Subject: Show deployment status on a MR view --- app/models/deployment.rb | 7 +++++++ app/models/environment.rb | 6 ++++++ app/models/merge_request.rb | 6 ++++++ 3 files changed, 19 insertions(+) (limited to 'app/models') diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 1a7cd60817e..67a4f3998ec 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -36,4 +36,11 @@ class Deployment < ActiveRecord::Base def manual_actions deployable.try(:other_actions) end + + def deployed_to(ref) + commit = project.commit(ref) + return false unless commit + + project.repository.merge_base(commit.id, sha) == commit.id + end end diff --git a/app/models/environment.rb b/app/models/environment.rb index baed106e8c8..f6fdb8d1ecf 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -25,4 +25,10 @@ class Environment < ActiveRecord::Base def nullify_external_url self.external_url = nil if self.external_url.blank? end + + def deployed_to?(ref) + return unless last_deployment + + last_deployment.deployed_to(ref) + end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b1fb3ce5d69..85e4d1f6b51 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -590,6 +590,12 @@ class MergeRequest < ActiveRecord::Base !pipeline || pipeline.success? end + def environments + target_project.environments.select do |environment| + environment.deployed_to?(ref_path) + end + end + def state_human_name if merged? "Merged" -- cgit v1.2.1 From b497b0ce3fc3c1882639f9c7d55f7991ce41f15d Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 3 Aug 2016 13:37:39 +0200 Subject: Incorporate feedback --- app/models/deployment.rb | 4 ++-- app/models/environment.rb | 6 +++--- app/models/merge_request.rb | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 67a4f3998ec..19b08f49d96 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -37,10 +37,10 @@ class Deployment < ActiveRecord::Base deployable.try(:other_actions) end - def deployed_to(ref) + def deployed_to?(ref) commit = project.commit(ref) return false unless commit - project.repository.merge_base(commit.id, sha) == commit.id + project.repository.is_ancestor?(commit.id, sha) end end diff --git a/app/models/environment.rb b/app/models/environment.rb index f6fdb8d1ecf..7247125f8a0 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -26,9 +26,9 @@ class Environment < ActiveRecord::Base self.external_url = nil if self.external_url.blank? end - def deployed_to?(ref) - return unless last_deployment + def deployed_from?(ref) + return false unless last_deployment - last_deployment.deployed_to(ref) + last_deployment.deployed_to?(ref) end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 85e4d1f6b51..945b0d76505 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -592,7 +592,7 @@ class MergeRequest < ActiveRecord::Base def environments target_project.environments.select do |environment| - environment.deployed_to?(ref_path) + environment.deployed_from?(ref_path) end end -- cgit v1.2.1 From 6a6a69f4afbe0107a75df018b662f02b5ec0166a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 20:54:02 +0200 Subject: Use state machine for pipeline event processing --- app/models/ci/pipeline.rb | 61 ++++++++++++++++++++++++++++++++------------- app/models/commit_status.rb | 8 +++--- 2 files changed, 47 insertions(+), 22 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 8de799d6088..7a0430f277a 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -19,6 +19,37 @@ module Ci after_save :keep_around_commits + state_machine :status, initial: :created do + event :skip do + transition any => :skipped + end + + event :drop do + transition any => :failed + end + + event :update_status do + transition any => :pending, if: ->(pipeline) { pipeline.can_transition_to?('pending') } + transition any => :running, if: ->(pipeline) { pipeline.can_transition_to?('running') } + transition any => :failed, if: ->(pipeline) { pipeline.can_transition_to?('failed') } + transition any => :success, if: ->(pipeline) { pipeline.can_transition_to?('success') } + transition any => :canceled, if: ->(pipeline) { pipeline.can_transition_to?('canceled') } + transition any => :skipped, if: ->(pipeline) { pipeline.can_transition_to?('skipped') } + end + + after_transition [:created, :pending] => :running do |pipeline| + pipeline.update(started_at: Time.now) + end + + after_transition any => [:success, :failed, :canceled] do |pipeline| + pipeline.update(finished_at: Time.now) + end + + after_transition do |pipeline| + pipeline.update_duration + end + end + # ref can't be HEAD or SHA, can only be branch/tag name scope :latest_successful_for, ->(ref = default_branch) do where(ref: ref).success.order(id: :desc).limit(1) @@ -89,16 +120,12 @@ module Ci def cancel_running builds.running_or_pending.each(&:cancel) - - reload_status! end def retry_failed(user) builds.latest.failed.select(&:retryable?).each do |build| Ci::Build.retry(build, user) end - - reload_status! end def latest? @@ -185,8 +212,6 @@ module Ci def process! Ci::ProcessPipelineService.new(project, user).execute(self) - - reload_status! end def predefined_variables @@ -195,22 +220,22 @@ module Ci ] end - def reload_status! - reload - self.status = - if yaml_errors.blank? - statuses.latest.status || 'skipped' - else - 'failed' - end - self.started_at = statuses.started_at - self.finished_at = statuses.finished_at - self.duration = statuses.latest.duration - save + def can_transition_to?(expected_status) + latest_status == expected_status + end + + def update_duration + update(duration: statuses.latest.duration) end private + def latest_status + return 'failed' unless yaml_errors.blank? + + statuses.latest.status || 'skipped' + end + def keep_around_commits return unless project diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 3ab44461179..64ce5431d63 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -74,13 +74,13 @@ class CommitStatus < ActiveRecord::Base around_transition any => [:success, :failed, :canceled] do |commit_status, block| block.call - commit_status.pipeline.process! if commit_status.pipeline + commit_status.pipeline.try(:process!) end - around_transition any => [:pending, :running] do |commit_status, block| - block.call + # Try to update the pipeline status - commit_status.pipeline.reload_status! if commit_status.pipeline + after_transition do |commit_status, transition| + commit_status.pipeline.try(:update_status) unless transition.loopback? end end -- cgit v1.2.1 From 4ccf39cde7356bf98bef5aae694257fb2c001e75 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 11 Aug 2016 22:54:25 +0200 Subject: Fix test failures, that did occur because of missing previously used `reload_status!` call --- app/models/ci/build.rb | 37 +++++++++++++++++++------------------ app/models/commit_status.rb | 18 ++++++++---------- 2 files changed, 27 insertions(+), 28 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 88a340379b8..92dad9377c9 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -42,24 +42,25 @@ module Ci end def retry(build, user = nil) - new_build = Ci::Build.new(status: 'pending') - new_build.ref = build.ref - new_build.tag = build.tag - new_build.options = build.options - new_build.commands = build.commands - new_build.tag_list = build.tag_list - new_build.project = build.project - new_build.pipeline = build.pipeline - new_build.name = build.name - new_build.allow_failure = build.allow_failure - new_build.stage = build.stage - new_build.stage_idx = build.stage_idx - new_build.trigger_request = build.trigger_request - new_build.yaml_variables = build.yaml_variables - new_build.when = build.when - new_build.user = user - new_build.environment = build.environment - new_build.save + new_build = Ci::Build.create( + ref: build.ref, + tag: build.tag, + options: build.options, + commands: build.commands, + tag_list: build.tag_list, + project: build.project, + pipeline: build.pipeline, + name: build.name, + allow_failure: build.allow_failure, + stage: build.stage, + stage_idx: build.stage_idx, + trigger_request: build.trigger_request, + yaml_variables: build.yaml_variables, + when: build.when, + user: user, + environment: build.environment, + status_event: 'queue' + ) MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) new_build end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 64ce5431d63..522fa5d6911 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -62,14 +62,6 @@ class CommitStatus < ActiveRecord::Base commit_status.update_attributes finished_at: Time.now end - after_transition [:created, :pending, :running] => :success do |commit_status| - MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.pipeline.project, nil).trigger(commit_status) - end - - after_transition any => :failed do |commit_status| - MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.pipeline.project, nil).execute(commit_status) - end - # We use around_transition to process pipeline on next stages as soon as possible, before the `after_*` is executed around_transition any => [:success, :failed, :canceled] do |commit_status, block| block.call @@ -77,11 +69,17 @@ class CommitStatus < ActiveRecord::Base commit_status.pipeline.try(:process!) end - # Try to update the pipeline status - after_transition do |commit_status, transition| commit_status.pipeline.try(:update_status) unless transition.loopback? end + + after_transition [:created, :pending, :running] => :success do |commit_status| + MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.pipeline.project, nil).trigger(commit_status) + end + + after_transition any => :failed do |commit_status| + MergeRequests::AddTodoWhenBuildFailsService.new(commit_status.pipeline.project, nil).execute(commit_status) + end end delegate :sha, :short_sha, to: :pipeline -- cgit v1.2.1 From cb8a425ba42e9be23b8712ed29b1db2dcc6bd139 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 28 May 2016 19:54:17 -0700 Subject: Fix bug where destroying a namespace would not always destroy projects There is a race condition in DestroyGroupService now that projects are deleted asynchronously: 1. User attempts to delete group 2. DestroyGroupService iterates through all projects and schedules a Sidekiq job to delete each Project 3. DestroyGroupService destroys the Group, leaving all its projects without a namespace 4. Projects::DestroyService runs later but the can?(current_user, :remove_project) is `false` because the user no longer has permission to destroy projects with no namespace. 5. This leaves the project in pending_delete state with no namespace/group. Projects without a namespace or group also adds another problem: it's not possible to destroy the container registry tags, since container_registry_path_with_namespace is the wrong value. The fix is to destroy the group asynchronously and to run execute directly on Projects::DestroyService. Closes #17893 --- app/models/namespace.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 8b52cc824cd..7c29d27ce97 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -1,4 +1,6 @@ class Namespace < ActiveRecord::Base + acts_as_paranoid + include Sortable include Gitlab::ShellAdapter -- cgit v1.2.1 From d5264e8804bca70e613c418a9d346f5787c6fc7a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 12 Aug 2016 16:09:29 +0800 Subject: Simplify the name for data builder, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5620#note_13671791 --- app/models/ci/build.rb | 2 +- app/models/ci/pipeline.rb | 2 +- app/models/project_services/builds_email_service.rb | 3 +-- app/models/service.rb | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 05b11f3b115..e2b0b996b6f 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -343,7 +343,7 @@ module Ci def execute_hooks return unless project - build_data = Gitlab::DataBuilder::BuildDataBuilder.build(self) + build_data = Gitlab::DataBuilder::Build.build(self) project.execute_hooks(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks) project.running_or_pending_build_count(force: true) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f8c0e27a5c3..2bfe8aa5ddd 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -222,7 +222,7 @@ module Ci end def pipeline_data - Gitlab::DataBuilder::PipelineDataBuilder.build(self) + Gitlab::DataBuilder::Pipeline.build(self) end def keep_around_commits diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb index bf8c68244a1..fa66e5864b8 100644 --- a/app/models/project_services/builds_email_service.rb +++ b/app/models/project_services/builds_email_service.rb @@ -51,8 +51,7 @@ class BuildsEmailService < Service end def test_data(project = nil, user = nil) - build = project.builds.last - Gitlab::DataBuilder::BuildDataBuilder.build(build) + Gitlab::DataBuilder::Build.build(project.builds.last) end def fields diff --git a/app/models/service.rb b/app/models/service.rb index 76f588f234d..09b4717a523 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -80,7 +80,7 @@ class Service < ActiveRecord::Base end def test_data(project, user) - Gitlab::DataBuilder::PushDataBuilder.build_sample(project, user) + Gitlab::DataBuilder::Push.build_sample(project, user) end def event_channel_names -- cgit v1.2.1 From 07fc2f852a0b4136b6d97c1d9773819c47e7e8e7 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 9 Aug 2016 15:11:14 +0200 Subject: Method names changed to #includes_commit? --- app/models/deployment.rb | 3 +-- app/models/environment.rb | 4 ++-- app/models/merge_request.rb | 4 +++- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 19b08f49d96..1e338889714 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -37,8 +37,7 @@ class Deployment < ActiveRecord::Base deployable.try(:other_actions) end - def deployed_to?(ref) - commit = project.commit(ref) + def includes_commit?(commit) return false unless commit project.repository.is_ancestor?(commit.id, sha) diff --git a/app/models/environment.rb b/app/models/environment.rb index 7247125f8a0..75e6f869786 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -26,9 +26,9 @@ class Environment < ActiveRecord::Base self.external_url = nil if self.external_url.blank? end - def deployed_from?(ref) + def includes_commit?(commit) return false unless last_deployment - last_deployment.deployed_to?(ref) + last_deployment.includes_commit?(commit) end end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 945b0d76505..491ee2792ec 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -591,8 +591,10 @@ class MergeRequest < ActiveRecord::Base end def environments + return unless diff_head_commit + target_project.environments.select do |environment| - environment.deployed_from?(ref_path) + environment.includes_commit?(diff_head_commit) end end -- cgit v1.2.1 From e1f05b932de5553462793fb88fdea2ca54072d40 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 11:36:51 +0200 Subject: Use explicit events to transition between states --- app/models/ci/pipeline.rb | 44 ++++++++++++++++++++++++++++++++------------ app/models/commit_status.rb | 2 +- 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 7a0430f277a..6aef91804a2 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -20,6 +20,14 @@ module Ci after_save :keep_around_commits state_machine :status, initial: :created do + event :queue do + transition :created => :pending + end + + event :run do + transition [:pending, :success, :failed, :canceled, :skipped] => :running + end + event :skip do transition any => :skipped end @@ -28,13 +36,12 @@ module Ci transition any => :failed end - event :update_status do - transition any => :pending, if: ->(pipeline) { pipeline.can_transition_to?('pending') } - transition any => :running, if: ->(pipeline) { pipeline.can_transition_to?('running') } - transition any => :failed, if: ->(pipeline) { pipeline.can_transition_to?('failed') } - transition any => :success, if: ->(pipeline) { pipeline.can_transition_to?('success') } - transition any => :canceled, if: ->(pipeline) { pipeline.can_transition_to?('canceled') } - transition any => :skipped, if: ->(pipeline) { pipeline.can_transition_to?('skipped') } + event :succeed do + transition any => :success + end + + event :cancel do + transition any => :canceled end after_transition [:created, :pending] => :running do |pipeline| @@ -214,23 +221,36 @@ module Ci Ci::ProcessPipelineService.new(project, user).execute(self) end + def build_updated + case latest_builds_status + when 'pending' + queue + when 'running' + run + when 'success' + succeed + when 'failed' + drop + when 'canceled' + cancel + when 'skipped' + skip + end + end + def predefined_variables [ { key: 'CI_PIPELINE_ID', value: id.to_s, public: true } ] end - def can_transition_to?(expected_status) - latest_status == expected_status - end - def update_duration update(duration: statuses.latest.duration) end private - def latest_status + def latest_builds_status return 'failed' unless yaml_errors.blank? statuses.latest.status || 'skipped' diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 522fa5d6911..c21c8ce18db 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -70,7 +70,7 @@ class CommitStatus < ActiveRecord::Base end after_transition do |commit_status, transition| - commit_status.pipeline.try(:update_status) unless transition.loopback? + commit_status.pipeline.try(:build_updated) unless transition.loopback? end after_transition [:created, :pending, :running] => :success do |commit_status| -- cgit v1.2.1 From ad3e1edcfce1e24fb9889d5d73852680cf4facf9 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 11:53:27 +0200 Subject: Added specs for started_at and finished_at --- app/models/ci/pipeline.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 6aef91804a2..92fae78fe4e 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -22,10 +22,11 @@ module Ci state_machine :status, initial: :created do event :queue do transition :created => :pending + transition any - [:created, :pending] => :running end event :run do - transition [:pending, :success, :failed, :canceled, :skipped] => :running + transition any => :running end event :skip do @@ -44,15 +45,15 @@ module Ci transition any => :canceled end - after_transition [:created, :pending] => :running do |pipeline| - pipeline.update(started_at: Time.now) + before_transition [:created, :pending] => :running do |pipeline| + pipeline.started_at = Time.now end - after_transition any => [:success, :failed, :canceled] do |pipeline| - pipeline.update(finished_at: Time.now) + before_transition any => [:success, :failed, :canceled] do |pipeline| + pipeline.finished_at = Time.now end - after_transition do |pipeline| + before_transition do |pipeline| pipeline.update_duration end end @@ -245,7 +246,7 @@ module Ci end def update_duration - update(duration: statuses.latest.duration) + self.duration = statuses.latest.duration end private -- cgit v1.2.1 From 706d872eb2ebb462b5c226890120f51cf15ba7c5 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 12:06:37 +0200 Subject: Make `execute_methods` public --- app/models/ci/pipeline.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 40615097804..ad836bbebb8 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -255,13 +255,13 @@ module Ci self.duration = statuses.latest.duration end - private - def execute_hooks project.execute_hooks(pipeline_data, :pipeline_hooks) project.execute_services(pipeline_data, :pipeline_hooks) end + private + def pipeline_data Gitlab::DataBuilder::Pipeline.build(self) end -- cgit v1.2.1 From d7b681512bb738b9b2ca0c56e761616a1a761295 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 12:23:47 +0200 Subject: Fix test failures --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 92fae78fe4e..6820b2d41a7 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -21,7 +21,7 @@ module Ci state_machine :status, initial: :created do event :queue do - transition :created => :pending + transition created: :pending transition any - [:created, :pending] => :running end -- cgit v1.2.1 From a391652fe60930e2139ecfacb175da6aa0f3b1e9 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 12:23:47 +0200 Subject: Fix test failures --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index ad836bbebb8..98185ecd447 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -23,7 +23,7 @@ module Ci state_machine :status, initial: :created do event :queue do - transition :created => :pending + transition created: :pending transition any - [:created, :pending] => :running end -- cgit v1.2.1 From ea4ac578534d3a233c3525bf8351eb2045f6e632 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 13:57:58 +0200 Subject: Use event `enqueue` instead of `queue` --- app/models/ci/build.rb | 4 ++-- app/models/ci/pipeline.rb | 20 +++++++------------- app/models/commit_status.rb | 2 +- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 92dad9377c9..3d6c6ea3209 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -59,7 +59,7 @@ module Ci when: build.when, user: user, environment: build.environment, - status_event: 'queue' + status_event: 'enqueue' ) MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) new_build @@ -102,7 +102,7 @@ module Ci def play(current_user = nil) # Try to queue a current build - if self.queue + if self.enqueue self.update(user: current_user) self else diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 6820b2d41a7..d00de56bf07 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -20,7 +20,7 @@ module Ci after_save :keep_around_commits state_machine :status, initial: :created do - event :queue do + event :enqueue do transition created: :pending transition any - [:created, :pending] => :running end @@ -224,18 +224,12 @@ module Ci def build_updated case latest_builds_status - when 'pending' - queue - when 'running' - run - when 'success' - succeed - when 'failed' - drop - when 'canceled' - cancel - when 'skipped' - skip + when 'pending' then enqueue + when 'running' then run + when 'success' then succeed + when 'failed' then drop + when 'canceled' then cancel + when 'skipped' then skip end end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index c21c8ce18db..703ca90edb6 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -26,7 +26,7 @@ class CommitStatus < ActiveRecord::Base scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } state_machine :status do - event :queue do + event :enqueue do transition [:created, :skipped] => :pending end -- cgit v1.2.1 From a7f84d1a03978243c4fd5b8a878a4fea2b246f87 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 13:59:20 +0200 Subject: Improve transition between states for event `enqueue` --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d00de56bf07..8cfba92ae9b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -22,7 +22,7 @@ module Ci state_machine :status, initial: :created do event :enqueue do transition created: :pending - transition any - [:created, :pending] => :running + transition [:success, :failed, :canceled, :skipped] => :running end event :run do -- cgit v1.2.1 From cae0fa7cba98cb39f70deb87fe30bdc9bfa487fc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 12 Aug 2016 16:22:48 +0200 Subject: Properly select a list of Pipelines for a Merge Requests --- app/models/merge_request.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 471e32f3b60..dc758a45bcf 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -642,10 +642,21 @@ class MergeRequest < ActiveRecord::Base diverged_commits_count > 0 end + def commits_sha + commits.map(&:sha) + end + def pipeline @pipeline ||= source_project.pipeline(diff_head_sha, source_branch) if diff_head_sha && source_project end + def all_pipelines + @all_pipelines ||= + if diff_head_sha && source_project + source_project.pipelines.order(id: :desc).where(sha: commits_sha, ref: source_branch) + end + end + def merge_commit @merge_commit ||= project.commit(merge_commit_sha) if merge_commit_sha end -- cgit v1.2.1 From 1f2253545ba7a902212bace29f144a2246eeedab Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Fri, 8 Jul 2016 18:42:47 +0200 Subject: Use cache for todos counter calling TodoService --- app/models/user.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index 73368be7b1b..87a2d999843 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -809,13 +809,13 @@ class User < ActiveRecord::Base def todos_done_count(force: false) Rails.cache.fetch(['users', id, 'todos_done_count'], force: force) do - todos.done.count + TodosFinder.new(self, state: :done).execute.count end end def todos_pending_count(force: false) Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force) do - todos.pending.count + TodosFinder.new(self, state: :pending).execute.count end end -- cgit v1.2.1 From 28ef06c52b3d76b2e5dc60b0bdcf407162035ee8 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 29 Jul 2016 11:05:33 +0100 Subject: Fix merge conflict reading for new diffs --- app/models/merge_request.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f6d0d0c98f5..e87ce322098 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -204,7 +204,7 @@ class MergeRequest < ActiveRecord::Base def diff_start_commit if persisted? - merge_request_diff.start_commit + merge_request_diff.start_commit || target_branch_head else target_branch_head end @@ -212,7 +212,7 @@ class MergeRequest < ActiveRecord::Base def diff_head_commit if persisted? - merge_request_diff.head_commit + merge_request_diff.head_commit || source_branch_head else source_branch_head end -- cgit v1.2.1 From 427e724698185169536d68e95873415038286849 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 4 Aug 2016 10:31:44 +0100 Subject: Don't allow resolving invalid conflicts An MR can only be resolved in the UI if: - It has conflicts. - It has valid diff_refs (in other words, it supports new diff notes). - It has no conflicts with one side missing. - It has no conflicts in binary files. - It has no conflicts in files too large to display. - It has no conflicts containing invalid conflict markers. --- app/models/diff_note.rb | 2 +- app/models/merge_request.rb | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index c816deb4e0c..e02a3d54c36 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -75,7 +75,7 @@ class DiffNote < Note private def supported? - !self.for_merge_request? || self.noteable.support_new_diff_notes? + !self.for_merge_request? || self.noteable.has_complete_diff_refs? end def noteable_diff_refs diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index e87ce322098..630d31a5d5c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -204,7 +204,7 @@ class MergeRequest < ActiveRecord::Base def diff_start_commit if persisted? - merge_request_diff.start_commit || target_branch_head + merge_request_diff.start_commit else target_branch_head end @@ -212,7 +212,7 @@ class MergeRequest < ActiveRecord::Base def diff_head_commit if persisted? - merge_request_diff.head_commit || source_branch_head + merge_request_diff.head_commit else source_branch_head end @@ -682,12 +682,12 @@ class MergeRequest < ActiveRecord::Base merge_commit end - def support_new_diff_notes? + def has_complete_diff_refs? diff_sha_refs && diff_sha_refs.complete? end def update_diff_notes_positions(old_diff_refs:, new_diff_refs:) - return unless support_new_diff_notes? + return unless has_complete_diff_refs? return if new_diff_refs == old_diff_refs active_diff_notes = self.notes.diff_notes.select do |note| @@ -715,4 +715,19 @@ class MergeRequest < ActiveRecord::Base def keep_around_commit project.repository.keep_around(self.merge_commit_sha) end + + def conflicts + @conflicts ||= Gitlab::Conflict::FileCollection.new(self) + end + + def can_resolve_conflicts_in_ui? + return false unless cannot_be_merged? + return false unless has_complete_diff_refs? + + begin + conflicts.files.each(&:lines) + rescue Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing + false + end + end end -- cgit v1.2.1 From ba327e69ec4b2214f12f577cd86a37c65ea2f3e9 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 4 Aug 2016 14:20:04 +0100 Subject: Move resolving code to ResolveService --- app/models/repository.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index e56bac509a4..01b02ccc0dc 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -869,6 +869,14 @@ class Repository end end + def resolve_conflicts(user, branch, params) + commit_with_hooks(user, branch) do + committer = user_to_committer(user) + + Rugged::Commit.create(rugged, params.merge(author: committer, committer: committer)) + end + end + def check_revert_content(commit, base_branch) source_sha = find_branch(base_branch).target.sha args = [commit.id, source_sha] -- cgit v1.2.1 From cf4cbb018e229b80e8fd0ca427e63f337ef6bdff Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 10 Aug 2016 22:36:13 -0500 Subject: Rename `can_resolve_conflicts_in_ui?` to `conflicts_can_be_resolved_in_ui?` --- app/models/merge_request.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 630d31a5d5c..b41d3b6891a 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -720,14 +720,16 @@ class MergeRequest < ActiveRecord::Base @conflicts ||= Gitlab::Conflict::FileCollection.new(self) end - def can_resolve_conflicts_in_ui? - return false unless cannot_be_merged? - return false unless has_complete_diff_refs? + def conflicts_can_be_resolved_in_ui? + return @conflicts_can_be_resolved_in_ui if defined?(@conflicts_can_be_resolved_in_ui) + + return @conflicts_can_be_resolved_in_ui = false unless cannot_be_merged? + return @conflicts_can_be_resolved_in_ui = false unless has_complete_diff_refs? begin - conflicts.files.each(&:lines) + @conflicts_can_be_resolved_in_ui = conflicts.files.each(&:lines) rescue Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing - false + @conflicts_can_be_resolved_in_ui = false end end end -- cgit v1.2.1 From 9eca67c950829698dabb93102804a6ddf89d5f8d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 10 Aug 2016 22:36:58 -0500 Subject: Verify user is signed in and can actually resolve conflicts --- app/models/merge_request.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/models') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b41d3b6891a..c1e95b1bfbf 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -720,6 +720,11 @@ class MergeRequest < ActiveRecord::Base @conflicts ||= Gitlab::Conflict::FileCollection.new(self) end + def conflicts_can_be_resolved_by?(user) + access = ::Gitlab::UserAccess.new(user, project: source_project) + access.can_push_to_branch?(source_branch) + end + def conflicts_can_be_resolved_in_ui? return @conflicts_can_be_resolved_in_ui if defined?(@conflicts_can_be_resolved_in_ui) -- cgit v1.2.1 From 60aee5b7afb2ba175606fda59d1f0742f7c4270c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Fri, 12 Aug 2016 21:56:40 -0400 Subject: Add method missing from EE --- app/models/project_wiki.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index a255710f577..46f70da2452 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -56,6 +56,10 @@ class ProjectWiki end end + def repository_exists? + !!repository.exists? + end + def empty? pages.empty? end -- cgit v1.2.1 From 4e4ca27ab148f16d9252634e3e2f58447acdeeef Mon Sep 17 00:00:00 2001 From: Egor Lynko Date: Wed, 10 Aug 2016 17:15:27 +0300 Subject: Ability to specify branches for pivotal tracker integration --- .../project_services/pivotaltracker_service.rb | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index ad19b7795da..5301f9fa0ff 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -1,7 +1,9 @@ class PivotaltrackerService < Service include HTTParty - prop_accessor :token + API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits' + + prop_accessor :token, :restrict_to_branch validates :token, presence: true, if: :activated? def title @@ -18,7 +20,17 @@ class PivotaltrackerService < Service def fields [ - { type: 'text', name: 'token', placeholder: '' } + { + type: 'text', + name: 'token', + placeholder: 'Pivotal Tracker API token.' + }, + { + type: 'text', + name: 'restrict_to_branch', + placeholder: 'Comma-separated list of branches which will be ' \ + 'automatically inspected. Leave blank to include all branches.' + } ] end @@ -28,8 +40,8 @@ class PivotaltrackerService < Service def execute(data) return unless supported_events.include?(data[:object_kind]) + return unless allowed_branch?(data[:ref]) - url = 'https://www.pivotaltracker.com/services/v5/source_commits' data[:commits].each do |commit| message = { 'source_commit' => { @@ -40,7 +52,7 @@ class PivotaltrackerService < Service } } PivotaltrackerService.post( - url, + API_ENDPOINT, body: message.to_json, headers: { 'Content-Type' => 'application/json', @@ -49,4 +61,15 @@ class PivotaltrackerService < Service ) end end + + private + + def allowed_branch?(ref) + return true unless ref.present? && restrict_to_branch.present? + + branch = Gitlab::Git.ref_name(ref) + allowed_branches = restrict_to_branch.split(',').map(&:strip) + + branch.present? && allowed_branches.include?(branch) + end end -- cgit v1.2.1 From 8171544b3d44df6ce810aa436bf87d137bc9b28f Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 12 Aug 2016 17:19:17 +0200 Subject: Limit the size of SVGs when viewing them as blobs This ensures that SVGs greater than 2 megabytes are not scrubbed and rendered. This in turn prevents requests from timing out due to reading/scrubbing large SVGs potentially taking a lot of time (and memory). The use of 2 megabytes is completely arbitrary. Fixes gitlab-org/gitlab-ce#1435 --- app/models/blob.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app/models') diff --git a/app/models/blob.rb b/app/models/blob.rb index 0df2805e448..12cc5aaafba 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -3,6 +3,9 @@ class Blob < SimpleDelegator CACHE_TIME = 60 # Cache raw blobs referred to by a (mutable) ref for 1 minute CACHE_TIME_IMMUTABLE = 3600 # Cache blobs referred to by an immutable reference for 1 hour + # The maximum size of an SVG that can be displayed. + MAXIMUM_SVG_SIZE = 2.megabytes + # Wrap a Gitlab::Git::Blob object, or return nil when given nil # # This method prevents the decorated object from evaluating to "truthy" when @@ -31,6 +34,10 @@ class Blob < SimpleDelegator text? && language && language.name == 'SVG' end + def size_within_svg_limits? + size <= MAXIMUM_SVG_SIZE + end + def video? UploaderHelper::VIDEO_EXT.include?(extname.downcase.delete('.')) end -- cgit v1.2.1 From 95419679f23f0628d1885dd9656cc159e9d55ea9 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 27 Jul 2016 19:03:06 -0500 Subject: Lay the ground works to submit information to Akismet - New concern `AkismetSubmittable` to allow issues and other `Spammable` models to be submitted to Akismet. - New model `UserAgentDetail` to store information needed for Akismet. - Services needed for their creation and tests. --- app/models/concerns/akismet_submittable.rb | 15 +++++++++++++++ app/models/issue.rb | 1 + app/models/user_agent_detail.rb | 16 ++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 app/models/concerns/akismet_submittable.rb create mode 100644 app/models/user_agent_detail.rb (limited to 'app/models') diff --git a/app/models/concerns/akismet_submittable.rb b/app/models/concerns/akismet_submittable.rb new file mode 100644 index 00000000000..17821688941 --- /dev/null +++ b/app/models/concerns/akismet_submittable.rb @@ -0,0 +1,15 @@ +module AkismetSubmittable + extend ActiveSupport::Concern + + included do + has_one :user_agent_detail, as: :subject + end + + def can_be_submitted? + if user_agent_detail + user_agent_detail.submittable? + else + false + end + end +end diff --git a/app/models/issue.rb b/app/models/issue.rb index d62ffb21467..6c2635498e5 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -8,6 +8,7 @@ class Issue < ActiveRecord::Base include Taskable include Spammable include FasterCacheKeys + include AkismetSubmittable DueDateStruct = Struct.new(:title, :name).freeze NoDueDate = DueDateStruct.new('No Due Date', '0').freeze diff --git a/app/models/user_agent_detail.rb b/app/models/user_agent_detail.rb new file mode 100644 index 00000000000..6d76dff20e3 --- /dev/null +++ b/app/models/user_agent_detail.rb @@ -0,0 +1,16 @@ +class UserAgentDetail < ActiveRecord::Base + belongs_to :subject, polymorphic: true + + validates :user_agent, + presence: true + validates :ip_address, + presence: true + validates :subject_id, + presence: true + validates :subject_type, + presence: true + + def submittable? + user_agent.present? && ip_address.present? + end +end -- cgit v1.2.1 From 722fc84e3d4785fb3a9db5f1c7d2aabad22e8e01 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Thu, 28 Jul 2016 19:02:56 -0500 Subject: Complete refactor of the `Spammable` concern and tests: - Merged `AkismetSubmittable` into `Spammable` - Clean up `SpamCheckService` - Added tests for `Spammable` - Added submit (ham or spam) options to `AkismetHelper` --- app/models/concerns/akismet_submittable.rb | 15 -------- app/models/concerns/spammable.rb | 58 ++++++++++++++++++++++++++++-- app/models/issue.rb | 2 ++ 3 files changed, 58 insertions(+), 17 deletions(-) delete mode 100644 app/models/concerns/akismet_submittable.rb (limited to 'app/models') diff --git a/app/models/concerns/akismet_submittable.rb b/app/models/concerns/akismet_submittable.rb deleted file mode 100644 index 17821688941..00000000000 --- a/app/models/concerns/akismet_submittable.rb +++ /dev/null @@ -1,15 +0,0 @@ -module AkismetSubmittable - extend ActiveSupport::Concern - - included do - has_one :user_agent_detail, as: :subject - end - - def can_be_submitted? - if user_agent_detail - user_agent_detail.submittable? - else - false - end - end -end diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index 3b8e6df2da9..bbf6a3e0be3 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -1,16 +1,70 @@ module Spammable extend ActiveSupport::Concern + include Gitlab::AkismetHelper + + module ClassMethods + def attr_spammable(*attrs) + attrs.each do |attr| + spammable_attrs << attr.to_s + end + end + end included do + has_one :user_agent_detail, as: :subject, dependent: :destroy attr_accessor :spam after_validation :check_for_spam, on: :create + + cattr_accessor :spammable_attrs, instance_accessor: false do + [] + end + end + + def can_be_submitted? + if user_agent_detail + user_agent_detail.submittable? + else + false + end + end + + def submit_ham + return unless akismet_enabled? && can_be_submitted? + ham!(user_agent_detail, spammable_text, creator) + end + + def submit_spam + return unless akismet_enabled? && can_be_submitted? + spam!(user_agent_detail, spammable_text, creator) + end + + def spam?(env, user) + is_spam?(env, user, spammable_text) end - def spam? + def spam_detected? @spam end def check_for_spam - self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam? + self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam_detected? + end + + private + + def spammable_text + result = [] + self.class.spammable_attrs.each do |entry| + result << self.send(entry) + end + result.reject(&:blank?).join("\n") + end + + def creator + if self.author_id + User.find(self.author_id) + elsif self.creator_id + User.find(self.creator_id) + end end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 6c2635498e5..5408e24b21c 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -37,6 +37,8 @@ class Issue < ActiveRecord::Base scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') } scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') } + attr_spammable :title, :description + state_machine :state, initial: :opened do event :close do transition [:reopened, :opened] => :closed -- cgit v1.2.1 From 64ab2b3d9f10366249c03a6bcf5e8b1d20010d8f Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Fri, 29 Jul 2016 23:18:32 -0500 Subject: Refactored spam related code even further - Removed unnecessary column from `SpamLog` - Moved creation of SpamLogs out of its own service and into SpamCheckService - Simplified code in SpamCheckService. - Moved move spam related code into Spammable concern --- app/models/concerns/spammable.rb | 44 +++++++++++++++++++++++++--------------- app/models/issue.rb | 13 ++++++++++++ 2 files changed, 41 insertions(+), 16 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index bbf6a3e0be3..5c75275b6e2 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -28,26 +28,42 @@ module Spammable end end - def submit_ham - return unless akismet_enabled? && can_be_submitted? - ham!(user_agent_detail, spammable_text, creator) - end - def submit_spam return unless akismet_enabled? && can_be_submitted? - spam!(user_agent_detail, spammable_text, creator) + spam!(user_agent_detail, spammable_text, owner) end - def spam?(env, user) - is_spam?(env, user, spammable_text) + def spam_detected?(env) + @spam = is_spam?(env, owner, spammable_text) end - def spam_detected? + def spam? @spam end def check_for_spam - self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam_detected? + self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam? + end + + def owner_id + if self.respond_to?(:author_id) + self.author_id + elsif self.respond_to?(:creator_id) + self.creator_id + end + end + + # Override this method if an additional check is needed before calling Akismet + def check_for_spam? + akismet_enabled? + end + + def spam_title + raise 'Implement in included model!' + end + + def spam_description + raise 'Implement in included model!' end private @@ -60,11 +76,7 @@ module Spammable result.reject(&:blank?).join("\n") end - def creator - if self.author_id - User.find(self.author_id) - elsif self.creator_id - User.find(self.creator_id) - end + def owner + User.find(owner_id) end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 5408e24b21c..40028e56489 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -265,4 +265,17 @@ class Issue < ActiveRecord::Base def overdue? due_date.try(:past?) || false end + + # To allow polymorphism with Spammable + def check_for_spam? + super && project.public? + end + + def spam_title + title + end + + def spam_description + description + end end -- cgit v1.2.1 From abf2dcd25c4a176801314872733ede91297d1ab0 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Mon, 1 Aug 2016 12:14:03 -0500 Subject: Allow `SpamLog` to be submitted as ham - Added `submitted_as_ham` to `SpamLog` to mark which logs have been submitted to Akismet. - Added routes and controller action. --- app/models/spam_log.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models') diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb index 12df68ef83b..3b8b9833565 100644 --- a/app/models/spam_log.rb +++ b/app/models/spam_log.rb @@ -7,4 +7,8 @@ class SpamLog < ActiveRecord::Base user.block user.destroy end + + def text + [title, description].join("\n") + end end -- cgit v1.2.1 From 96399a81cbb2e8a0f666241eeaff7cc784c26983 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 2 Aug 2016 16:21:57 -0500 Subject: Allow `Issue` to be submitted as spam - Added controller actions as reusable concerns - Added controller tests --- app/models/concerns/spammable.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index 5c75275b6e2..f272e7c5a55 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -22,7 +22,7 @@ module Spammable def can_be_submitted? if user_agent_detail - user_agent_detail.submittable? + user_agent_detail.submittable? && akismet_enabled? else false end @@ -41,6 +41,14 @@ module Spammable @spam end + def submitted? + if user_agent_detail + user_agent_detail.submitted + else + false + end + end + def check_for_spam self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam? end @@ -53,17 +61,21 @@ module Spammable end end + def to_ability_name + self.class.to_s.underscore + end + # Override this method if an additional check is needed before calling Akismet def check_for_spam? akismet_enabled? end def spam_title - raise 'Implement in included model!' + raise NotImplementedError end def spam_description - raise 'Implement in included model!' + raise NotImplementedError end private -- cgit v1.2.1 From 43e756d4eafd79f4d2f366b646ebb94af78b5a4c Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Fri, 5 Aug 2016 17:10:08 -0500 Subject: Refactored AkismetHelper into AkismetService and cleaned up `Spammable` - Refactored SpamCheckService into SpamService --- app/models/concerns/spammable.rb | 68 +++++++++++++++++----------------------- app/models/issue.rb | 13 ++------ 2 files changed, 31 insertions(+), 50 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index f272e7c5a55..694e2efcade 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -1,55 +1,36 @@ module Spammable extend ActiveSupport::Concern - include Gitlab::AkismetHelper module ClassMethods - def attr_spammable(*attrs) - attrs.each do |attr| - spammable_attrs << attr.to_s - end + def attr_spammable(attr, options = {}) + spammable_attrs << [attr.to_s, options] end end included do has_one :user_agent_detail, as: :subject, dependent: :destroy attr_accessor :spam - after_validation :check_for_spam, on: :create + after_validation :spam_detected?, on: :create cattr_accessor :spammable_attrs, instance_accessor: false do [] end + delegate :submitted?, to: :user_agent_detail, allow_nil: true end def can_be_submitted? if user_agent_detail - user_agent_detail.submittable? && akismet_enabled? + user_agent_detail.submittable? else false end end - def submit_spam - return unless akismet_enabled? && can_be_submitted? - spam!(user_agent_detail, spammable_text, owner) - end - - def spam_detected?(env) - @spam = is_spam?(env, owner, spammable_text) - end - def spam? @spam end - def submitted? - if user_agent_detail - user_agent_detail.submitted - else - false - end - end - - def check_for_spam + def spam_detected? self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam? end @@ -61,34 +42,41 @@ module Spammable end end - def to_ability_name - self.class.to_s.underscore - end - - # Override this method if an additional check is needed before calling Akismet - def check_for_spam? - akismet_enabled? + def owner + User.find(owner_id) end def spam_title - raise NotImplementedError + attr = self.class.spammable_attrs.select do |_, options| + options.fetch(:spam_title, false) + end + + attr = attr[0].first + + public_send(attr) if respond_to?(attr.to_sym) end def spam_description - raise NotImplementedError - end + attr = self.class.spammable_attrs.select do |_, options| + options.fetch(:spam_description, false) + end - private + attr = attr[0].first + + public_send(attr) if respond_to?(attr.to_sym) + end def spammable_text result = [] - self.class.spammable_attrs.each do |entry| - result << self.send(entry) + self.class.spammable_attrs.map do |attr| + result << public_send(attr.first) end + result.reject(&:blank?).join("\n") end - def owner - User.find(owner_id) + # Override in Spammable if further checks are necessary + def check_for_spam? + current_application_settings.akismet_enabled end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 40028e56489..ab98d0cf9df 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -37,7 +37,8 @@ class Issue < ActiveRecord::Base scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') } scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') } - attr_spammable :title, :description + attr_spammable :title, spam_title: true + attr_spammable :description, spam_description: true state_machine :state, initial: :opened do event :close do @@ -266,16 +267,8 @@ class Issue < ActiveRecord::Base due_date.try(:past?) || false end - # To allow polymorphism with Spammable + # Only issues on public projects should be checked for spam def check_for_spam? super && project.public? end - - def spam_title - title - end - - def spam_description - description - end end -- cgit v1.2.1 From 5994c11910822463faeabb7b5f11d6529036db9d Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 9 Aug 2016 12:43:47 -0500 Subject: Further refactor and syntax fixes. --- app/models/concerns/spammable.rb | 42 ++++++++++++++-------------------------- app/models/issue.rb | 3 +-- app/models/user_agent_detail.rb | 11 ++--------- 3 files changed, 17 insertions(+), 39 deletions(-) (limited to 'app/models') diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index 694e2efcade..ce54fe5d3bf 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -9,16 +9,19 @@ module Spammable included do has_one :user_agent_detail, as: :subject, dependent: :destroy + attr_accessor :spam - after_validation :spam_detected?, on: :create + + after_validation :check_for_spam, on: :create cattr_accessor :spammable_attrs, instance_accessor: false do [] end - delegate :submitted?, to: :user_agent_detail, allow_nil: true + + delegate :ip_address, :user_agent, to: :user_agent_detail, allow_nil: true end - def can_be_submitted? + def submittable_as_spam? if user_agent_detail user_agent_detail.submittable? else @@ -30,46 +33,29 @@ module Spammable @spam end - def spam_detected? + def check_for_spam self.errors.add(:base, "Your #{self.class.name.underscore} has been recognized as spam and has been discarded.") if spam? end - def owner_id - if self.respond_to?(:author_id) - self.author_id - elsif self.respond_to?(:creator_id) - self.creator_id - end - end - - def owner - User.find(owner_id) - end - def spam_title - attr = self.class.spammable_attrs.select do |_, options| + attr = self.class.spammable_attrs.find do |_, options| options.fetch(:spam_title, false) end - attr = attr[0].first - - public_send(attr) if respond_to?(attr.to_sym) + public_send(attr.first) if attr && respond_to?(attr.first.to_sym) end def spam_description - attr = self.class.spammable_attrs.select do |_, options| + attr = self.class.spammable_attrs.find do |_, options| options.fetch(:spam_description, false) end - attr = attr[0].first - - public_send(attr) if respond_to?(attr.to_sym) + public_send(attr.first) if attr && respond_to?(attr.first.to_sym) end def spammable_text - result = [] - self.class.spammable_attrs.map do |attr| - result << public_send(attr.first) + result = self.class.spammable_attrs.map do |attr| + public_send(attr.first) end result.reject(&:blank?).join("\n") @@ -77,6 +63,6 @@ module Spammable # Override in Spammable if further checks are necessary def check_for_spam? - current_application_settings.akismet_enabled + true end end diff --git a/app/models/issue.rb b/app/models/issue.rb index ab98d0cf9df..788611305fe 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -8,7 +8,6 @@ class Issue < ActiveRecord::Base include Taskable include Spammable include FasterCacheKeys - include AkismetSubmittable DueDateStruct = Struct.new(:title, :name).freeze NoDueDate = DueDateStruct.new('No Due Date', '0').freeze @@ -269,6 +268,6 @@ class Issue < ActiveRecord::Base # Only issues on public projects should be checked for spam def check_for_spam? - super && project.public? + project.public? end end diff --git a/app/models/user_agent_detail.rb b/app/models/user_agent_detail.rb index 6d76dff20e3..0949c6ef083 100644 --- a/app/models/user_agent_detail.rb +++ b/app/models/user_agent_detail.rb @@ -1,16 +1,9 @@ class UserAgentDetail < ActiveRecord::Base belongs_to :subject, polymorphic: true - validates :user_agent, - presence: true - validates :ip_address, - presence: true - validates :subject_id, - presence: true - validates :subject_type, - presence: true + validates :user_agent, :ip_address, :subject_id, :subject_type, presence: true def submittable? - user_agent.present? && ip_address.present? + !submitted? end end -- cgit v1.2.1 From e805a6470031d942f7de604fdf7acfc7cf4f0b1a Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 16 Aug 2016 10:39:13 +0530 Subject: Backport changes from gitlab-org/gitlab-ee!581 to CE. !581 has a lot of changes that would cause merge conflicts if not properly backported to CE. This commit/MR serves as a better foundation for gitlab-org/gitlab-ee!581. = Changes = 1. Move from `has_one {merge,push}_access_level` to `has_many`, with the `length` of the association limited to `1`. This is _effectively_ a `has_one` association, but should cause less conflicts with EE, which is set to `has_many`. This has a number of related changes in the views, specs, and factories. 2. Make `gon` variable loading more consistent (with EE!581) in the `ProtectedBranchesController`. Also use `::` to prefix the `ProtectedBranches` services, because this is required in EE. 3. Extract a `ProtectedBranchAccess` concern from the two access level models. This concern only has a single `humanize` method here, but will have more methods in EE. 4. Add `form_errors` to the protected branches creation form. This is not strictly required for EE compatibility, but was an oversight nonetheless. --- app/models/concerns/protected_branch_access.rb | 7 +++++++ app/models/protected_branch.rb | 11 +++++++---- app/models/protected_branch/merge_access_level.rb | 6 ++---- app/models/protected_branch/push_access_level.rb | 6 ++---- 4 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 app/models/concerns/protected_branch_access.rb (limited to 'app/models') diff --git a/app/models/concerns/protected_branch_access.rb b/app/models/concerns/protected_branch_access.rb new file mode 100644 index 00000000000..5a7b36070e7 --- /dev/null +++ b/app/models/concerns/protected_branch_access.rb @@ -0,0 +1,7 @@ +module ProtectedBranchAccess + extend ActiveSupport::Concern + + def humanize + self.class.human_access_levels[self.access_level] + end +end diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 226b3f54342..6240912a6e1 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -5,11 +5,14 @@ class ProtectedBranch < ActiveRecord::Base validates :name, presence: true validates :project, presence: true - has_one :merge_access_level, dependent: :destroy - has_one :push_access_level, dependent: :destroy + has_many :merge_access_levels, dependent: :destroy + has_many :push_access_levels, dependent: :destroy - accepts_nested_attributes_for :push_access_level - accepts_nested_attributes_for :merge_access_level + validates_length_of :merge_access_levels, is: 1, message: "are restricted to a single instance per protected branch." + validates_length_of :push_access_levels, is: 1, message: "are restricted to a single instance per protected branch." + + accepts_nested_attributes_for :push_access_levels + accepts_nested_attributes_for :merge_access_levels def commit project.commit(self.name) diff --git a/app/models/protected_branch/merge_access_level.rb b/app/models/protected_branch/merge_access_level.rb index b1112ee737d..806b3ccd275 100644 --- a/app/models/protected_branch/merge_access_level.rb +++ b/app/models/protected_branch/merge_access_level.rb @@ -1,4 +1,6 @@ class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base + include ProtectedBranchAccess + belongs_to :protected_branch delegate :project, to: :protected_branch @@ -17,8 +19,4 @@ class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base project.team.max_member_access(user.id) >= access_level end - - def humanize - self.class.human_access_levels[self.access_level] - end end diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb index 6a5e49cf453..92e9c51d883 100644 --- a/app/models/protected_branch/push_access_level.rb +++ b/app/models/protected_branch/push_access_level.rb @@ -1,4 +1,6 @@ class ProtectedBranch::PushAccessLevel < ActiveRecord::Base + include ProtectedBranchAccess + belongs_to :protected_branch delegate :project, to: :protected_branch @@ -20,8 +22,4 @@ class ProtectedBranch::PushAccessLevel < ActiveRecord::Base project.team.max_member_access(user.id) >= access_level end - - def humanize - self.class.human_access_levels[self.access_level] - end end -- cgit v1.2.1 From 5b52da9c32842849f0b6430a6a820fc7456b4841 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 16 Aug 2016 10:00:13 +0200 Subject: Revert unrelevant changes --- app/models/ci/pipeline.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 08b104ccfc8..130afeb724e 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -250,8 +250,9 @@ module Ci end def execute_hooks - project.execute_hooks(pipeline_data, :pipeline_hooks) - project.execute_services(pipeline_data, :pipeline_hooks) + data = pipeline_data + project.execute_hooks(data, :pipeline_hooks) + project.execute_services(data, :pipeline_hooks) end private -- cgit v1.2.1 From 03386633a42bd56b0b0b31b70eebaaaa33e1494e Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Fri, 5 Aug 2016 15:29:20 +0200 Subject: Move to project dropdown with infinite scroll for better performance Use just SQL to check is a user can admin_issue on a project Tradeoff - we duplicate how we check admin_issue in a SQL relation in the Ability class --- app/models/project.rb | 2 ++ app/models/user.rb | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'app/models') diff --git a/app/models/project.rb b/app/models/project.rb index e0b28160937..eefdae35615 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -197,6 +197,8 @@ class Project < ActiveRecord::Base scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } + scope :excluding_project, ->(project) { where.not(id: project) } + state_machine :import_status, initial: :none do event :import_start do transition [:none, :finished] => :started diff --git a/app/models/user.rb b/app/models/user.rb index 87a2d999843..48e83ab7e56 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -429,6 +429,13 @@ class User < ActiveRecord::Base owned_groups.select(:id), namespace.id).joins(:namespace) end + # Returns projects which user can admin issues on (for example to move an issue to that project). + # + # This logic is duplicated from `Ability#project_abilities` into a SQL form. + def projects_where_can_admin_issues + authorized_projects(Gitlab::Access::REPORTER).non_archived.where.not(issues_enabled: false) + end + def is_admin? admin end -- cgit v1.2.1 From d345591fc80e2181acfa71e9eeec99875c523767 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 16 Aug 2016 16:18:48 +0200 Subject: Tracking of custom events GitLab Performance Monitoring is now able to track custom events not directly related to application performance. These events include the number of tags pushed, repositories created, builds registered, etc. The use of these events is to get a better overview of how a GitLab instance is used and how that may affect performance. For example, a large number of Git pushes may have a negative impact on the underlying storage engine. Events are stored in the "events" measurement and are not prefixed with "rails_" or "sidekiq_", this makes it easier to query events with the same name triggered from different parts of the application. All events being stored in the same measurement also makes it easier to downsample data. Currently the following events are tracked: * Creating repositories * Removing repositories * Changing the default branch of a repository * Pushing a new tag * Removing an existing tag * Pushing a commit (along with the branch being pushed to) * Pushing a new branch * Removing an existing branch * Importing a repository (along with the URL we're importing) * Forking a repository (along with the source/target path) * CI builds registered (and when no build could be found) * CI builds being updated * Rails and Sidekiq exceptions Fixes gitlab-org/gitlab-ce#13720 --- app/models/repository.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'app/models') diff --git a/app/models/repository.rb b/app/models/repository.rb index e56bac509a4..916843dabdd 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -391,6 +391,8 @@ class Repository expire_exists_cache expire_root_ref_cache expire_emptiness_caches + + repository_event(:create_repository) end # Runs code just before a repository is deleted. @@ -407,6 +409,8 @@ class Repository expire_root_ref_cache expire_emptiness_caches expire_exists_cache + + repository_event(:remove_repository) end # Runs code just before the HEAD of a repository is changed. @@ -414,6 +418,8 @@ class Repository # Cached divergent commit counts are based on repository head expire_branch_cache expire_root_ref_cache + + repository_event(:change_default_branch) end # Runs code before pushing (= creating or removing) a tag. @@ -421,12 +427,16 @@ class Repository expire_cache expire_tags_cache expire_tag_count_cache + + repository_event(:push_tag) end # Runs code before removing a tag. def before_remove_tag expire_tags_cache expire_tag_count_cache + + repository_event(:remove_tag) end def before_import @@ -443,6 +453,8 @@ class Repository # Runs code after a new commit has been pushed. def after_push_commit(branch_name, revision) expire_cache(branch_name, revision) + + repository_event(:push_commit, branch: branch_name) end # Runs code after a new branch has been created. @@ -450,11 +462,15 @@ class Repository expire_branches_cache expire_has_visible_content_cache expire_branch_count_cache + + repository_event(:push_branch) end # Runs code before removing an existing branch. def before_remove_branch expire_branches_cache + + repository_event(:remove_branch) end # Runs code after an existing branch has been removed. @@ -1059,4 +1075,8 @@ class Repository def keep_around_ref_name(sha) "refs/keep-around/#{sha}" end + + def repository_event(event, tags = {}) + Gitlab::Metrics.add_event(event, { path: path_with_namespace }.merge(tags)) + end end -- cgit v1.2.1 From fee7992c08c434940f0722886dc96f249a8e7fbf Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 17 Aug 2016 09:46:34 +0100 Subject: Fix pipelines visualisation rendering --- app/models/ci/build.rb | 2 +- app/models/ci/pipeline.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 08f396210c9..b42977f9ebd 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -102,7 +102,7 @@ module Ci end def playable? - project.builds_enabled? && commands.present? && manual? + project.builds_enabled? && commands.present? && manual? && skipped? end def play(current_user = nil) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bce6a992af6..caf4d25029f 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -34,6 +34,10 @@ module Ci CommitStatus.where(pipeline: pluck(:id)).stages end + def stages + statuses.order(:stage_idx).latest.group_by(&:stage) + end + def project_id project.id end -- cgit v1.2.1 From 1cd9b3b8a0b1024d043b9344869aceeadb9c84f1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 17 Aug 2016 11:21:00 +0100 Subject: Split pipeline status item for Commit Status and Build --- app/models/ci/pipeline.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d3fc5191721..c360a6ff729 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -78,8 +78,8 @@ module Ci CommitStatus.where(pipeline: pluck(:id)).stages end - def stages - statuses.order(:stage_idx).latest.group_by(&:stage) + def stages_with_latest_statuses + statuses.latest.order(:stage_idx).group_by(&:stage) end def project_id -- cgit v1.2.1 From 611dab2e522e5e59cf09cd459a31686e65616863 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 27 Jul 2016 16:32:32 -0300 Subject: Add Board model --- app/models/board.rb | 7 +++++++ app/models/list.rb | 10 ++++++++++ app/models/project.rb | 2 ++ 3 files changed, 19 insertions(+) create mode 100644 app/models/board.rb create mode 100644 app/models/list.rb (limited to 'app/models') diff --git a/app/models/board.rb b/app/models/board.rb new file mode 100644 index 00000000000..d44df497e78 --- /dev/null +++ b/app/models/board.rb @@ -0,0 +1,7 @@ +class Board < ActiveRecord::Base + belongs_to :project + + has_many :lists, dependent: :destroy + + validates :project, presence: true +end diff --git a/app/models/list.rb b/app/models/list.rb new file mode 100644 index 00000000000..7b347c2255b --- /dev/null +++ b/app/models/list.rb @@ -0,0 +1,10 @@ +class List < ActiveRecord::Base + belongs_to :board + belongs_to :label + + enum list_type: { label: 0, backlog: 1, done: 2 } + + validates :board, :list_type, :position, presence: true + validates :label, presence: true, if: :label? + validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 } +end diff --git a/app/models/project.rb b/app/models/project.rb index eefdae35615..043da030468 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -62,6 +62,8 @@ class Project < ActiveRecord::Base belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id' belongs_to :namespace + has_one :board, dependent: :destroy + has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' # Project services -- cgit v1.2.1 From b07c5f23b8761ae87d29ded1a69b14ae6393443a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 28 Jul 2016 19:26:16 -0300 Subject: Order board lists by list_type, and position --- app/models/board.rb | 2 +- app/models/list.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app/models') diff --git a/app/models/board.rb b/app/models/board.rb index d44df497e78..d6358fb15e8 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -1,7 +1,7 @@ class Board < ActiveRecord::Base belongs_to :project - has_many :lists, dependent: :destroy + has_many :lists, -> { order(:list_type, :position) }, dependent: :destroy validates :project, presence: true end diff --git a/app/models/list.rb b/app/models/list.rb index 7b347c2255b..38cf2050527 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -2,9 +2,9 @@ class List < ActiveRecord::Base belongs_to :board belongs_to :label - enum list_type: { label: 0, backlog: 1, done: 2 } + enum list_type: { backlog: 0, label: 1, done: 2 } - validates :board, :list_type, :position, presence: true - validates :label, presence: true, if: :label? - validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :board, :list_type, presence: true + validates :label, :position, presence: true, if: :label? + validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? end -- cgit v1.2.1 From 252e93c9e664e595ea9b4987f14ca8fb21a0e307 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Sun, 31 Jul 2016 20:45:56 -0300 Subject: Title of a list is either the label name, or Backlog, or Done --- app/models/list.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app/models') diff --git a/app/models/list.rb b/app/models/list.rb index 38cf2050527..b4fdab7893a 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -7,4 +7,10 @@ class List < ActiveRecord::Base validates :board, :list_type, presence: true validates :label, :position, presence: true, if: :label? validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? + + delegate :name, to: :label, allow_nil: true, prefix: true + + def title + label? ? label_name : list_type.humanize + end end -- cgit v1.2.1 From 4b75c75018c9a3eac7a2c8b1772a10c98ea3bdc0 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Sun, 31 Jul 2016 20:48:00 -0300 Subject: The lists: Backlog, and Done cannot be destroyed --- app/models/board.rb | 2 +- app/models/list.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/board.rb b/app/models/board.rb index d6358fb15e8..3240c4bede3 100644 --- a/app/models/board.rb +++ b/app/models/board.rb @@ -1,7 +1,7 @@ class Board < ActiveRecord::Base belongs_to :project - has_many :lists, -> { order(:list_type, :position) }, dependent: :destroy + has_many :lists, -> { order(:list_type, :position) }, dependent: :delete_all validates :project, presence: true end diff --git a/app/models/list.rb b/app/models/list.rb index b4fdab7893a..f2a59d18c46 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -10,7 +10,15 @@ class List < ActiveRecord::Base delegate :name, to: :label, allow_nil: true, prefix: true + before_destroy :can_be_destroyed, unless: :label? + def title label? ? label_name : list_type.humanize end + + private + + def can_be_destroyed + false + end end -- cgit v1.2.1 From c14ac835756d1d0f4d0f8279759e2b7f75364447 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 3 Aug 2016 14:21:22 -0300 Subject: Ensure that we have only one list per label per board --- app/models/list.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models') diff --git a/app/models/list.rb b/app/models/list.rb index f2a59d18c46..6f639a51150 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -6,6 +6,7 @@ class List < ActiveRecord::Base validates :board, :list_type, presence: true validates :label, :position, presence: true, if: :label? + validates :label_id, uniqueness: { scope: :board_id }, if: :label? validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? delegate :name, to: :label, allow_nil: true, prefix: true -- cgit v1.2.1 From e23d1706faa7fe100d5db3d2e4f83198f7bfa900 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 8 Aug 2016 16:14:22 -0300 Subject: Destroy related lists when a label is removed --- app/models/label.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/label.rb b/app/models/label.rb index 35e678001dc..a23140b7d64 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -13,6 +13,8 @@ class Label < ActiveRecord::Base default_value_for :color, DEFAULT_COLOR belongs_to :project + + has_many :lists, dependent: :destroy has_many :label_links, dependent: :destroy has_many :issues, through: :label_links, source: :target, source_type: 'Issue' has_many :merge_requests, through: :label_links, source: :target, source_type: 'MergeRequest' -- cgit v1.2.1 From a8b1ad250e1ebc1c1e835399ccd010b223108a1d Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 8 Aug 2016 19:03:41 -0300 Subject: Add authorization to issues board related controllers --- app/models/ability.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/ability.rb b/app/models/ability.rb index d9113ffd99a..b70451db12f 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -228,6 +228,7 @@ class Ability :read_project, :read_wiki, :read_issue, + :read_board, :read_label, :read_milestone, :read_project_snippet, @@ -249,6 +250,7 @@ class Ability :update_issue, :admin_issue, :admin_label, + :admin_list, :read_commit_status, :read_build, :read_container_image, -- cgit v1.2.1 From 5490a9fe835f12e3d931bc0a47c0ec177c802140 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 9 Aug 2016 13:07:35 -0300 Subject: Turn board for public projects accessible to everyone --- app/models/ability.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models') diff --git a/app/models/ability.rb b/app/models/ability.rb index b70451db12f..4458ee1d590 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -90,6 +90,7 @@ class Ability if project && project.public? rules = [ :read_project, + :read_board, :read_wiki, :read_label, :read_milestone, -- cgit v1.2.1 From cd98ff179cb20d9dc4460d173288d0e1582c4293 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 15 Aug 2016 19:50:23 -0300 Subject: Move action to render board lists to `Projects::Boards::ListsController` --- app/models/ability.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/ability.rb b/app/models/ability.rb index 4458ee1d590..55265c3cfcb 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -91,6 +91,7 @@ class Ability rules = [ :read_project, :read_board, + :read_list, :read_wiki, :read_label, :read_milestone, @@ -230,6 +231,7 @@ class Ability :read_wiki, :read_issue, :read_board, + :read_list, :read_label, :read_milestone, :read_project_snippet, -- cgit v1.2.1 From 847ebce90ab66dd21541ce8bd147931c49814e88 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 15 Aug 2016 23:07:59 -0300 Subject: Remove useless delegate method on List model --- app/models/list.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/models/list.rb b/app/models/list.rb index 6f639a51150..41f79513a10 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -9,12 +9,10 @@ class List < ActiveRecord::Base validates :label_id, uniqueness: { scope: :board_id }, if: :label? validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? - delegate :name, to: :label, allow_nil: true, prefix: true - before_destroy :can_be_destroyed, unless: :label? def title - label? ? label_name : list_type.humanize + label? ? label.name : list_type.humanize end private -- cgit v1.2.1 From c6511235e4253d11447b40c2ea42ecb02c99687e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 16 Aug 2016 11:31:21 -0300 Subject: Add a destroyable scope and a destroyable? method to List model --- app/models/list.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/list.rb b/app/models/list.rb index 41f79513a10..634c012e543 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -9,7 +9,13 @@ class List < ActiveRecord::Base validates :label_id, uniqueness: { scope: :board_id }, if: :label? validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :label? - before_destroy :can_be_destroyed, unless: :label? + before_destroy :can_be_destroyed + + scope :destroyable, -> { where(list_type: list_types[:label]) } + + def destroyable? + label? + end def title label? ? label.name : list_type.humanize @@ -18,6 +24,6 @@ class List < ActiveRecord::Base private def can_be_destroyed - false + destroyable? end end -- cgit v1.2.1 From 50ac488c739718902ba897bc5ad8791d35914324 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 16 Aug 2016 14:38:43 -0300 Subject: Add a movable scope and a movable? method to List model --- app/models/list.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/models') diff --git a/app/models/list.rb b/app/models/list.rb index 634c012e543..eb87decdbc8 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -12,11 +12,16 @@ class List < ActiveRecord::Base before_destroy :can_be_destroyed scope :destroyable, -> { where(list_type: list_types[:label]) } + scope :movable, -> { where(list_type: list_types[:label]) } def destroyable? label? end + def movable? + label? + end + def title label? ? label.name : list_type.humanize end -- cgit v1.2.1