Commit 539437b6 authored by Stan Hu's avatar Stan Hu

Merge branch '207870-group-wikis-post-receive' into 'master'

Refactor PostReceive hooks for group wikis [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!37439
parents 293cc469 f5bc1b08
...@@ -25,10 +25,6 @@ module HasWiki ...@@ -25,10 +25,6 @@ module HasWiki
wiki.repository_exists? wiki.repository_exists?
end end
def after_wiki_activity
true
end
private private
def check_wiki_path_conflict def check_wiki_path_conflict
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
class Project < ApplicationRecord class Project < ApplicationRecord
extend ::Gitlab::Utils::Override
include Gitlab::ConfigHelper include Gitlab::ConfigHelper
include Gitlab::VisibilityLevel include Gitlab::VisibilityLevel
include AccessRequestable include AccessRequestable
...@@ -2470,11 +2469,6 @@ class Project < ApplicationRecord ...@@ -2470,11 +2469,6 @@ class Project < ApplicationRecord
jira_imports.last jira_imports.last
end end
override :after_wiki_activity
def after_wiki_activity
touch(:last_activity_at, :last_repository_updated_at)
end
def metrics_setting def metrics_setting
super || build_metrics_setting super || build_metrics_setting
end end
......
...@@ -10,6 +10,23 @@ class ProjectWiki < Wiki ...@@ -10,6 +10,23 @@ class ProjectWiki < Wiki
def disk_path(*args, &block) def disk_path(*args, &block)
container.disk_path + '.wiki' container.disk_path + '.wiki'
end end
override :after_wiki_activity
def after_wiki_activity
# Update activity columns, this is done synchronously to avoid
# replication delays in Geo.
project.touch(:last_activity_at, :last_repository_updated_at)
end
override :after_post_receive
def after_post_receive
# Update storage statistics
ProjectCacheWorker.perform_async(project.id, [], [:wiki_size])
# This call is repeated for post-receive, to make sure we're updating
# the activity columns for Git pushes as well.
after_wiki_activity
end
end end
# TODO: Remove this once we implement ES support for group wikis. # TODO: Remove this once we implement ES support for group wikis.
......
...@@ -133,8 +133,9 @@ class Wiki ...@@ -133,8 +133,9 @@ class Wiki
commit = commit_details(:created, message, title) commit = commit_details(:created, message, title)
wiki.write_page(title, format.to_sym, content, commit) wiki.write_page(title, format.to_sym, content, commit)
after_wiki_activity
update_container_activity true
rescue Gitlab::Git::Wiki::DuplicatePageError => e rescue Gitlab::Git::Wiki::DuplicatePageError => e
@error_message = "Duplicate page: #{e.message}" @error_message = "Duplicate page: #{e.message}"
false false
...@@ -144,16 +145,18 @@ class Wiki ...@@ -144,16 +145,18 @@ class Wiki
commit = commit_details(:updated, message, page.title) commit = commit_details(:updated, message, page.title)
wiki.update_page(page.path, title || page.name, format.to_sym, content, commit) wiki.update_page(page.path, title || page.name, format.to_sym, content, commit)
after_wiki_activity
update_container_activity true
end end
def delete_page(page, message = nil) def delete_page(page, message = nil)
return unless page return unless page
wiki.delete_page(page.path, commit_details(:deleted, message, page.title)) wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
after_wiki_activity
update_container_activity true
end end
def page_title_and_dir(title) def page_title_and_dir(title)
...@@ -209,6 +212,17 @@ class Wiki ...@@ -209,6 +212,17 @@ class Wiki
web_url(only_path: true).sub(%r{/#{Wiki::HOMEPAGE}\z}, '') web_url(only_path: true).sub(%r{/#{Wiki::HOMEPAGE}\z}, '')
end end
# Callbacks for synchronous processing after wiki changes.
# These will be executed after any change made through GitLab itself (web UI and API),
# but not for Git pushes.
def after_wiki_activity
end
# Callbacks for background processing after wiki changes.
# These will be executed after any change to the wiki repository.
def after_post_receive
end
private private
def commit_details(action, message = nil, title = nil) def commit_details(action, message = nil, title = nil)
...@@ -225,10 +239,6 @@ class Wiki ...@@ -225,10 +239,6 @@ class Wiki
def default_message(action, title) def default_message(action, title)
"#{user.username} #{action} page: #{title}" "#{user.username} #{action} page: #{title}"
end end
def update_container_activity
container.after_wiki_activity
end
end end
Wiki.prepend_if_ee('EE::Wiki') Wiki.prepend_if_ee('EE::Wiki')
...@@ -5,7 +5,16 @@ module Git ...@@ -5,7 +5,16 @@ module Git
# Maximum number of change events we will process on any single push # Maximum number of change events we will process on any single push
MAX_CHANGES = 100 MAX_CHANGES = 100
attr_reader :wiki
def initialize(wiki, current_user, params)
@wiki, @current_user, @params = wiki, current_user, params.dup
end
def execute def execute
# Execute model-specific callbacks
wiki.after_post_receive
process_changes process_changes
end end
...@@ -23,7 +32,11 @@ module Git ...@@ -23,7 +32,11 @@ module Git
end end
def can_process_wiki_events? def can_process_wiki_events?
Feature.enabled?(:wiki_events_on_git_push, project) # TODO: Support activity events for group wikis
# https://gitlab.com/gitlab-org/gitlab/-/issues/209306
return false unless wiki.is_a?(ProjectWiki)
Feature.enabled?(:wiki_events_on_git_push, wiki.container)
end end
def push_changes def push_changes
...@@ -36,10 +49,6 @@ module Git ...@@ -36,10 +49,6 @@ module Git
wiki.repository.raw.raw_changes_between(change[:oldrev], change[:newrev]) wiki.repository.raw.raw_changes_between(change[:oldrev], change[:newrev])
end end
def wiki
project.wiki
end
def create_event_for(change) def create_event_for(change)
event_service.execute( event_service.execute(
change.last_known_slug, change.last_known_slug,
...@@ -54,7 +63,7 @@ module Git ...@@ -54,7 +63,7 @@ module Git
end end
def on_default_branch?(change) def on_default_branch?(change)
project.wiki.default_branch == ::Gitlab::Git.branch_name(change[:ref]) wiki.default_branch == ::Gitlab::Git.branch_name(change[:ref])
end end
# See: [Gitlab::GitPostReceive#changes] # See: [Gitlab::GitPostReceive#changes]
......
...@@ -5,11 +5,11 @@ module Git ...@@ -5,11 +5,11 @@ module Git
class Change class Change
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
# @param [ProjectWiki] wiki # @param [Wiki] wiki
# @param [Hash] change - must have keys `:oldrev` and `:newrev` # @param [Hash] change - must have keys `:oldrev` and `:newrev`
# @param [Gitlab::Git::RawDiffChange] raw_change # @param [Gitlab::Git::RawDiffChange] raw_change
def initialize(project_wiki, change, raw_change) def initialize(wiki, change, raw_change)
@wiki, @raw_change, @change = project_wiki, raw_change, change @wiki, @raw_change, @change = wiki, raw_change, change
end end
def page def page
......
...@@ -12,8 +12,8 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker ...@@ -12,8 +12,8 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
def perform(gl_repository, identifier, changes, push_options = {}) def perform(gl_repository, identifier, changes, push_options = {})
container, project, repo_type = Gitlab::GlRepository.parse(gl_repository) container, project, repo_type = Gitlab::GlRepository.parse(gl_repository)
if project.nil? && (!repo_type.snippet? || container.is_a?(ProjectSnippet)) if container.nil? || (container.is_a?(ProjectSnippet) && project.nil?)
log("Triggered hook for non-existing project with gl_repository \"#{gl_repository}\"") log("Triggered hook for non-existing gl_repository \"#{gl_repository}\"")
return false return false
end end
...@@ -24,7 +24,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker ...@@ -24,7 +24,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
post_received = Gitlab::GitPostReceive.new(container, identifier, changes, push_options) post_received = Gitlab::GitPostReceive.new(container, identifier, changes, push_options)
if repo_type.wiki? if repo_type.wiki?
process_wiki_changes(post_received, container) process_wiki_changes(post_received, container.wiki)
elsif repo_type.project? elsif repo_type.project?
process_project_changes(post_received, container) process_project_changes(post_received, container)
elsif repo_type.snippet? elsif repo_type.snippet?
...@@ -59,18 +59,15 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker ...@@ -59,18 +59,15 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
after_project_changes_hooks(project, user, changes.refs, changes.repository_data) after_project_changes_hooks(project, user, changes.refs, changes.repository_data)
end end
def process_wiki_changes(post_received, project) def process_wiki_changes(post_received, wiki)
project.touch(:last_activity_at, :last_repository_updated_at)
project.wiki.repository.expire_statistics_caches
ProjectCacheWorker.perform_async(project.id, [], [:wiki_size])
user = identify_user(post_received) user = identify_user(post_received)
return false unless user return false unless user
# We only need to expire certain caches once per push # We only need to expire certain caches once per push
expire_caches(post_received, project.wiki.repository) expire_caches(post_received, wiki.repository)
wiki.repository.expire_statistics_caches
::Git::WikiPushService.new(project, user, changes: post_received.changes).execute ::Git::WikiPushService.new(wiki, user, changes: post_received.changes).execute
end end
def process_snippet_changes(post_received, snippet) def process_snippet_changes(post_received, snippet)
......
...@@ -30,4 +30,17 @@ class GroupWiki < Wiki ...@@ -30,4 +30,17 @@ class GroupWiki < Wiki
def disk_path(*args, &block) def disk_path(*args, &block)
storage.disk_path + '.wiki' storage.disk_path + '.wiki'
end end
override :after_wiki_activity
def after_wiki_activity
# TODO: Check if we need to update any columns for Geo replication,
# like we do in ProjectWiki#after_wiki_activity
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
end
override :after_post_receive
def after_post_receive
# TODO: Update group wiki storage
# https://gitlab.com/gitlab-org/gitlab/-/issues/230465
end
end end
...@@ -9,10 +9,13 @@ module EE ...@@ -9,10 +9,13 @@ module EE
def execute def execute
super super
return unless project.use_elasticsearch? # TODO: Support Elasticsearch indexing for group wikis
# https://gitlab.com/gitlab-org/gitlab/-/issues/207889
return unless wiki.is_a?(::ProjectWiki)
return unless wiki.container.use_elasticsearch?
return unless default_branch_changes.any? return unless default_branch_changes.any?
project.wiki.index_wiki_blobs wiki.index_wiki_blobs
end end
end end
end end
......
...@@ -22,11 +22,15 @@ module EE ...@@ -22,11 +22,15 @@ module EE
end end
end end
def process_wiki_changes(post_received, project) def process_wiki_changes(post_received, wiki)
super super
# TODO: Support Geo for group wikis.
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
return unless wiki.is_a?(ProjectWiki)
if ::Gitlab::Geo.primary? if ::Gitlab::Geo.primary?
::Geo::RepositoryUpdatedService.new(project.wiki.repository).execute ::Geo::RepositoryUpdatedService.new(wiki.repository).execute
end end
end end
......
...@@ -17,6 +17,14 @@ RSpec.describe ProjectWiki, :elastic do ...@@ -17,6 +17,14 @@ RSpec.describe ProjectWiki, :elastic do
end end
end end
describe '#use_elasticsearch?' do
it 'delegates to Project#use_elasticsearch?' do
expect(project).to receive(:use_elasticsearch?)
project.wiki.use_elasticsearch?
end
end
it "searches wiki page" do it "searches wiki page" do
expect(project.wiki.elastic_search('term1', type: 'wiki_blob')[:wiki_blobs][:total_count]).to eq(1) expect(project.wiki.elastic_search('term1', type: 'wiki_blob')[:wiki_blobs][:total_count]).to eq(1)
expect(project.wiki.elastic_search('term1 | term2', type: 'wiki_blob')[:wiki_blobs][:total_count]).to eq(2) expect(project.wiki.elastic_search('term1 | term2', type: 'wiki_blob')[:wiki_blobs][:total_count]).to eq(2)
......
...@@ -5,59 +5,83 @@ require 'spec_helper' ...@@ -5,59 +5,83 @@ require 'spec_helper'
RSpec.describe Git::WikiPushService do RSpec.describe Git::WikiPushService do
include RepoHelpers include RepoHelpers
let(:gl_repository) { "wiki-#{project.id}" } let_it_be(:key_id) { create(:key, user: current_user).shell_id }
let(:key) { create(:key, user: project.owner) } let_it_be(:wiki) { create(:project_wiki) }
let(:key_id) { key.shell_id } let_it_be(:current_user) { wiki.container.default_owner }
let(:project) { create(:project, :repository, :wiki_repo) } let_it_be(:repository) { wiki.repository }
let(:post_received) { ::Gitlab::GitPostReceive.new(project, key_id, changes, {}) }
let(:post_received) { ::Gitlab::GitPostReceive.new(wiki.container, key_id, changes, {}) }
before do before do
allow(post_received).to receive(:identify).and_return(project.owner) allow(post_received).to receive(:identify).and_return(current_user)
end
describe '#process_changes' do
context 'with a group wiki' do
let_it_be(:wiki) { create(:group_wiki) }
let_it_be(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag\n423423 797823 refs/heads/master" }
it 'does not create any events' do
expect do
described_class.new(wiki, current_user, changes: post_received.changes).execute
end.not_to change(Event, :count)
end
end
end end
context 'when elasticsearch is enabled' do context 'when elasticsearch is enabled' do
before do before do
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true) allow(wiki.container).to receive(:use_elasticsearch?).and_return(true)
end end
describe 'when changes include master ref' do describe 'when changes include master ref' do
let(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag\n423423 797823 refs/heads/master" } let_it_be(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag\n423423 797823 refs/heads/master" }
before do before do
allow(project.wiki.repository.raw).to receive(:raw_changes_between).once.with('423423', '797823').and_return([]) allow(wiki.repository.raw).to receive(:raw_changes_between).once.with('423423', '797823').and_return([])
end end
it 'triggers a wiki update' do it 'triggers a wiki update' do
expect(project.wiki).to receive(:index_wiki_blobs) expect(wiki).to receive(:index_wiki_blobs)
described_class.new(wiki, current_user, changes: post_received.changes).execute
end
context 'with a group wiki' do
let_it_be(:wiki) { build(:group_wiki) }
it 'does not trigger a wiki update' do
expect(wiki).not_to receive(:index_wiki_blobs)
described_class.new(project, project.owner, changes: post_received.changes).execute described_class.new(wiki, current_user, changes: post_received.changes).execute
end
end end
end end
describe 'when changes do not include master ref' do describe 'when changes do not include master ref' do
let(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } let_it_be(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
it 'does not trigger a wiki update' do it 'does not trigger a wiki update' do
expect(project.wiki).not_to receive(:index_wiki_blobs) expect(wiki).not_to receive(:index_wiki_blobs)
described_class.new(project, project.owner, changes: post_received.changes).execute described_class.new(wiki, current_user, changes: post_received.changes).execute
end end
end end
end end
context 'when elasticsearch is disabled' do context 'when elasticsearch is disabled' do
before do before do
stub_ee_application_setting(elasticsearch_search: false, elasticsearch_indexing: false) allow(wiki.container).to receive(:use_elasticsearch?).and_return(false)
allow(project.wiki.repository.raw).to receive(:raw_changes_between).once.with('423423', '797823').and_return([]) allow(wiki.repository.raw).to receive(:raw_changes_between).once.with('423423', '797823').and_return([])
end end
describe 'when changes include master ref' do describe 'when changes include master ref' do
let(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag\n423423 797823 refs/heads/master" } let_it_be(:changes) { +"123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag\n423423 797823 refs/heads/master" }
it 'does nothing even if changes include master ref' do it 'does nothing even if changes include master ref' do
expect(project.wiki).not_to receive(:index_wiki_blobs) expect(wiki).not_to receive(:index_wiki_blobs)
described_class.new(project, project.owner, changes: post_received.changes).execute described_class.new(wiki, current_user, changes: post_received.changes).execute
end end
end end
end end
......
...@@ -11,7 +11,7 @@ RSpec.describe PostReceive do ...@@ -11,7 +11,7 @@ RSpec.describe PostReceive do
let(:gl_repository) { "project-#{project.id}" } let(:gl_repository) { "project-#{project.id}" }
let(:key) { create(:key, user: project.owner) } let(:key) { create(:key, user: project.owner) }
let(:key_id) { key.shell_id } let(:key_id) { key.shell_id }
let(:project) { create(:project, :repository, :wiki_repo) } let(:project) { create(:project, :repository) }
describe "#process_project_changes" do describe "#process_project_changes" do
before do before do
...@@ -81,7 +81,9 @@ RSpec.describe PostReceive do ...@@ -81,7 +81,9 @@ RSpec.describe PostReceive do
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } allow(Gitlab::Geo).to receive(:primary?) { true }
expect_any_instance_of(::Geo::RepositoryUpdatedService).to receive(:execute) expect_next_instance_of(::Geo::RepositoryUpdatedService) do |service|
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
...@@ -89,7 +91,7 @@ RSpec.describe PostReceive do ...@@ -89,7 +91,7 @@ RSpec.describe PostReceive do
it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false } allow(Gitlab::Geo).to receive(:primary?) { false }
expect_any_instance_of(::Geo::RepositoryUpdatedService).not_to receive(:execute) expect_next_instance_of(::Geo::RepositoryUpdatedService).never
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
...@@ -97,23 +99,30 @@ RSpec.describe PostReceive do ...@@ -97,23 +99,30 @@ RSpec.describe PostReceive do
end end
describe '#process_wiki_changes' do describe '#process_wiki_changes' do
let(:gl_repository) { "wiki-#{project.id}" } let(:wiki) { build(:project_wiki, project: project) }
let(:gl_repository) { wiki.repository.repo_type.identifier_for_container(wiki.container) }
it 'calls Git::WikiPushService#process_changes' do it 'calls Git::WikiPushService#execute' do
expect_any_instance_of(::Git::WikiPushService).to receive(:process_changes) expect_next_instance_of(::Git::WikiPushService) do |service|
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
context 'assuming calls to process_changes are successful' do context 'assuming calls to process_changes are successful' do
before do before do
allow_any_instance_of(Git::WikiPushService).to receive(:process_changes) allow_next_instance_of(::Git::WikiPushService) do |service|
allow(service).to receive(:execute)
end
end end
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } allow(Gitlab::Geo).to receive(:primary?) { true }
expect_any_instance_of(::Geo::RepositoryUpdatedService).to receive(:execute) expect_next_instance_of(::Geo::RepositoryUpdatedService) do |service|
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
...@@ -121,73 +130,29 @@ RSpec.describe PostReceive do ...@@ -121,73 +130,29 @@ RSpec.describe PostReceive do
it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false } allow(Gitlab::Geo).to receive(:primary?) { false }
expect_any_instance_of(::Geo::RepositoryUpdatedService).not_to receive(:execute) expect_next_instance_of(::Geo::RepositoryUpdatedService).never
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
end
it 'triggers wiki index update when ElasticSearch is enabled and pushed to master', :elastic do context 'with a group wiki' do
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true) let(:wiki) { build(:group_wiki) }
expect_any_instance_of(ProjectWiki).to receive(:index_wiki_blobs)
described_class.new.perform(gl_repository, key_id, base64_changes_with_master)
end
it 'does not trigger wiki index update when Elasticsearch is enabled and not pushed to master', :elastic do
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
expect_any_instance_of(ProjectWiki).not_to receive(:index_wiki_blobs) it 'calls Git::WikiPushService#execute' do
expect_next_instance_of(::Git::WikiPushService) do |service|
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
context 'when limited indexing is on', :elastic do it 'does not call Geo::RepositoryUpdatedService when running on a Geo primary node' do
before do allow(Gitlab::Geo).to receive(:primary?) { true }
stub_ee_application_setting(
elasticsearch_search: true,
elasticsearch_indexing: true,
elasticsearch_limit_indexing: true
)
end
context 'when the project is not enabled specifically' do
it 'does not trigger wiki index update' do
expect_any_instance_of(ProjectWiki).not_to receive(:index_wiki_blobs)
described_class.new.perform(gl_repository, key_id, base64_changes_with_master)
end
end
context 'when a project is enabled specifically' do
before do
create :elasticsearch_indexed_project, project: project
end
it 'triggers wiki index update' do
expect_any_instance_of(ProjectWiki).to receive(:index_wiki_blobs)
described_class.new.perform(gl_repository, key_id, base64_changes_with_master)
end
end
context 'when a group is enabled' do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, :wiki_repo, group: group) }
let(:key) { create(:key, user: user) }
before do
create :elasticsearch_indexed_namespace, namespace: group
group.add_owner(user)
end
it 'triggers wiki index update' do expect_next_instance_of(::Geo::RepositoryUpdatedService).never
expect_any_instance_of(ProjectWiki).to receive(:index_wiki_blobs)
described_class.new.perform(gl_repository, key_id, base64_changes_with_master) described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
end end
end end
end end
......
...@@ -17,19 +17,28 @@ RSpec.describe ProjectWiki do ...@@ -17,19 +17,28 @@ RSpec.describe ProjectWiki do
end end
end end
describe '#update_container_activity' do describe '#after_wiki_activity' do
it 'updates project activity' do it 'updates project activity' do
wiki_container.update!( wiki_container.update!(
last_activity_at: nil, last_activity_at: nil,
last_repository_updated_at: nil last_repository_updated_at: nil
) )
subject.create_page('Test Page', 'This is content') subject.send(:after_wiki_activity)
wiki_container.reload wiki_container.reload
expect(wiki_container.last_activity_at).to be_within(1.minute).of(Time.current) expect(wiki_container.last_activity_at).to be_within(1.minute).of(Time.current)
expect(wiki_container.last_repository_updated_at).to be_within(1.minute).of(Time.current) expect(wiki_container.last_repository_updated_at).to be_within(1.minute).of(Time.current)
end end
end end
describe '#after_post_receive' do
it 'updates project activity and expires caches' do
expect(wiki).to receive(:after_wiki_activity)
expect(ProjectCacheWorker).to receive(:perform_async).with(wiki_container.id, [], [:wiki_size])
subject.send(:after_post_receive)
end
end
end end
end end
...@@ -6,12 +6,20 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -6,12 +6,20 @@ RSpec.describe Git::WikiPushService, services: true do
include RepoHelpers include RepoHelpers
let_it_be(:key_id) { create(:key, user: current_user).shell_id } let_it_be(:key_id) { create(:key, user: current_user).shell_id }
let_it_be(:project) { create(:project, :wiki_repo) } let_it_be(:wiki) { create(:project_wiki) }
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { wiki.container.default_owner }
let_it_be(:git_wiki) { project.wiki.wiki } let_it_be(:git_wiki) { wiki.wiki }
let_it_be(:repository) { git_wiki.repository } let_it_be(:repository) { wiki.repository }
describe '#execute' do describe '#execute' do
it 'executes model-specific callbacks' do
expect(wiki).to receive(:after_post_receive)
create_service(current_sha).execute
end
end
describe '#process_changes' do
context 'the push contains more than the permitted number of changes' do context 'the push contains more than the permitted number of changes' do
def run_service def run_service
process_changes { described_class::MAX_CHANGES.succ.times { write_new_page } } process_changes { described_class::MAX_CHANGES.succ.times { write_new_page } }
...@@ -37,8 +45,8 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -37,8 +45,8 @@ RSpec.describe Git::WikiPushService, services: true do
let(:count) { Event::WIKI_ACTIONS.size } let(:count) { Event::WIKI_ACTIONS.size }
def run_service def run_service
wiki_page_a = create(:wiki_page, project: project) wiki_page_a = create(:wiki_page, wiki: wiki)
wiki_page_b = create(:wiki_page, project: project) wiki_page_b = create(:wiki_page, wiki: wiki)
process_changes do process_changes do
write_new_page write_new_page
...@@ -135,7 +143,7 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -135,7 +143,7 @@ RSpec.describe Git::WikiPushService, services: true do
end end
context 'when a page we already know about has been updated' do context 'when a page we already know about has been updated' do
let(:wiki_page) { create(:wiki_page, project: project) } let(:wiki_page) { create(:wiki_page, wiki: wiki) }
before do before do
create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page)
...@@ -165,7 +173,7 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -165,7 +173,7 @@ RSpec.describe Git::WikiPushService, services: true do
context 'when a page we do not know about has been updated' do context 'when a page we do not know about has been updated' do
def run_service def run_service
wiki_page = create(:wiki_page, project: project) wiki_page = create(:wiki_page, wiki: wiki)
process_changes { update_page(wiki_page.title) } process_changes { update_page(wiki_page.title) }
end end
...@@ -189,7 +197,7 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -189,7 +197,7 @@ RSpec.describe Git::WikiPushService, services: true do
context 'when a page we do not know about has been deleted' do context 'when a page we do not know about has been deleted' do
def run_service def run_service
wiki_page = create(:wiki_page, project: project) wiki_page = create(:wiki_page, wiki: wiki)
process_changes { delete_page(wiki_page.page.path) } process_changes { delete_page(wiki_page.page.path) }
end end
...@@ -254,9 +262,9 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -254,9 +262,9 @@ RSpec.describe Git::WikiPushService, services: true do
it_behaves_like 'a no-op push' it_behaves_like 'a no-op push'
context 'but is enabled for a given project' do context 'but is enabled for a given container' do
before do before do
stub_feature_flags(wiki_events_on_git_push: project) stub_feature_flags(wiki_events_on_git_push: wiki.container)
end end
it 'creates events' do it 'creates events' do
...@@ -280,19 +288,19 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -280,19 +288,19 @@ RSpec.describe Git::WikiPushService, services: true do
def create_service(base, refs = ['refs/heads/master']) def create_service(base, refs = ['refs/heads/master'])
changes = post_received(base, refs).changes changes = post_received(base, refs).changes
described_class.new(project, current_user, changes: changes) described_class.new(wiki, current_user, changes: changes)
end end
def post_received(base, refs) def post_received(base, refs)
change_str = refs.map { |ref| +"#{base} #{current_sha} #{ref}" }.join("\n") change_str = refs.map { |ref| +"#{base} #{current_sha} #{ref}" }.join("\n")
post_received = ::Gitlab::GitPostReceive.new(project, key_id, change_str, {}) post_received = ::Gitlab::GitPostReceive.new(wiki.container, key_id, change_str, {})
allow(post_received).to receive(:identify).with(key_id).and_return(current_user) allow(post_received).to receive(:identify).with(key_id).and_return(current_user)
post_received post_received
end end
def current_sha def current_sha
repository.gitaly_ref_client.find_branch('master')&.dereferenced_target&.id || Gitlab::Git::BLANK_SHA repository.commit('master')&.id || Gitlab::Git::BLANK_SHA
end end
# It is important not to re-use the WikiPage services here, since they create # It is important not to re-use the WikiPage services here, since they create
...@@ -312,7 +320,7 @@ RSpec.describe Git::WikiPushService, services: true do ...@@ -312,7 +320,7 @@ RSpec.describe Git::WikiPushService, services: true do
file_content: 'some stuff', file_content: 'some stuff',
branch_name: 'master' branch_name: 'master'
} }
::Wikis::CreateAttachmentService.new(container: project, current_user: project.owner, params: params).execute ::Wikis::CreateAttachmentService.new(container: wiki.container, current_user: current_user, params: params).execute
end end
def update_page(title) def update_page(title)
......
...@@ -322,8 +322,8 @@ RSpec.shared_examples 'wiki model' do ...@@ -322,8 +322,8 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email) expect(commit.committer_email).to eq(user.commit_email)
end end
it 'updates container activity' do it 'runs after_wiki_activity callbacks' do
expect(subject).to receive(:update_container_activity) expect(subject).to receive(:after_wiki_activity)
subject.create_page('Test Page', 'This is content') subject.create_page('Test Page', 'This is content')
end end
...@@ -363,10 +363,10 @@ RSpec.shared_examples 'wiki model' do ...@@ -363,10 +363,10 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email) expect(commit.committer_email).to eq(user.commit_email)
end end
it 'updates container activity' do it 'runs after_wiki_activity callbacks' do
page page
expect(subject).to receive(:update_container_activity) expect(subject).to receive(:after_wiki_activity)
update_page update_page
end end
...@@ -389,10 +389,10 @@ RSpec.shared_examples 'wiki model' do ...@@ -389,10 +389,10 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email) expect(commit.committer_email).to eq(user.commit_email)
end end
it 'updates container activity' do it 'runs after_wiki_activity callbacks' do
page page
expect(subject).to receive(:update_container_activity) expect(subject).to receive(:after_wiki_activity)
subject.delete_page(page) subject.delete_page(page)
end end
......
...@@ -27,7 +27,7 @@ RSpec.describe PostReceive do ...@@ -27,7 +27,7 @@ RSpec.describe PostReceive do
context 'with a non-existing project' do context 'with a non-existing project' do
let(:gl_repository) { "project-123456789" } let(:gl_repository) { "project-123456789" }
let(:error_message) do let(:error_message) do
"Triggered hook for non-existing project with gl_repository \"#{gl_repository}\"" "Triggered hook for non-existing gl_repository \"#{gl_repository}\""
end end
it "returns false and logs an error" do it "returns false and logs an error" do
...@@ -314,7 +314,7 @@ RSpec.describe PostReceive do ...@@ -314,7 +314,7 @@ RSpec.describe PostReceive do
it 'processes the changes on the master branch' do it 'processes the changes on the master branch' do
expect_next_instance_of(Git::WikiPushService) do |service| expect_next_instance_of(Git::WikiPushService) do |service|
expect(service).to receive(:process_changes).and_call_original expect(service).to receive(:execute).and_call_original
end end
expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch) expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch)
expect(project.wiki.repository).to receive(:raw).and_return(raw_repo) expect(project.wiki.repository).to receive(:raw).and_return(raw_repo)
...@@ -334,7 +334,7 @@ RSpec.describe PostReceive do ...@@ -334,7 +334,7 @@ RSpec.describe PostReceive do
before do before do
allow_next_instance_of(Git::WikiPushService) do |service| allow_next_instance_of(Git::WikiPushService) do |service|
allow(service).to receive(:process_changes) allow(service).to receive(:execute)
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment