Commit 9100ee60 authored by Robert Speicher's avatar Robert Speicher

Merge branch '2384-geo-event-log' into 'master'

Add push events to Geo event log

Closes #2384

See merge request !1976
parents 0716348d 9043e664
module Geo
module Model
extend ActiveSupport::Concern
included do
def self.table_name_prefix
"geo_"
end
end
end
end
module Geo
class EventLog < ActiveRecord::Base
include Geo::Model
belongs_to :repository_updated_event,
class_name: 'Geo::RepositoryUpdatedEvent',
foreign_key: :repository_updated_event_id
end
end
module Geo
class RepositoryUpdatedEvent < ActiveRecord::Base
include Geo::Model
REPOSITORY = 0
WIKI = 1
belongs_to :project
enum source: { repository: REPOSITORY, wiki: WIKI }
validates :project, presence: true
end
end
module EE
module WikiPages
# BaseService EE mixin
#
# This module is intended to encapsulate EE-specific service logic
# and be included in the `WikiPages::BaseService` service
module BaseService
extend ActiveSupport::Concern
private
def execute_hooks(page, action = 'create')
super
process_wiki_repository_update
end
def process_wiki_repository_update
if ::Gitlab::Geo.primary?
# Create wiki repository updated event on Geo event log
::Geo::RepositoryUpdatedEventStore.new(project, source: Geo::RepositoryUpdatedEvent::WIKI).create
# Triggers repository update on secondary nodes
::Gitlab::Geo.notify_wiki_update(project)
end
end
end
end
end
module Geo
class RepositoryUpdatedEventStore
attr_reader :project, :source, :refs, :changes
def initialize(project, refs: [], changes: [], source: Geo::RepositoryUpdatedEvent::REPOSITORY)
@project = project
@refs = refs
@changes = changes
@source = source
end
def create
return unless Gitlab::Geo.primary?
Geo::EventLog.transaction do
event_log = Geo::EventLog.new
event_log.repository_updated_event = build_event
event_log.save!
end
rescue ActiveRecord::RecordInvalid
log("#{Geo::PushEvent.sources.key(source).humanize} updated event could not be created")
end
private
def build_event
Geo::RepositoryUpdatedEvent.new(
project: project,
source: source,
ref: ref,
branches_affected: branches_affected,
tags_affected: tags_affected,
new_branch: push_to_new_branch?,
remove_branch: push_remove_branch?
)
end
def ref
refs.first if refs.length == 1
end
def branches_affected
refs.count { |ref| Gitlab::Git.branch_ref?(ref) }
end
def tags_affected
refs.count { |ref| Gitlab::Git.tag_ref?(ref) }
end
def push_to_new_branch?
changes.any? { |change| Gitlab::Git.branch_ref?(change[:ref]) && Gitlab::Git.blank_ref?(change[:before]) }
end
def push_remove_branch?
changes.any? { |change| Gitlab::Git.branch_ref?(change[:ref]) && Gitlab::Git.blank_ref?(change[:after]) }
end
def log(message)
Rails.logger.info("#{self.class.name}: #{message} for project #{project.path_with_namespace} (#{project.id})")
end
end
end
module WikiPages module WikiPages
class BaseService < ::BaseService class BaseService < ::BaseService
prepend EE::WikiPages::BaseService
def hook_data(page, action) def hook_data(page, action)
hook_data = { hook_data = {
object_kind: page.class.name.underscore, object_kind: page.class.name.underscore,
......
...@@ -3,9 +3,6 @@ module WikiPages ...@@ -3,9 +3,6 @@ module WikiPages
def execute(page) def execute(page)
if page&.delete if page&.delete
execute_hooks(page, 'delete') execute_hooks(page, 'delete')
# Triggers repository update on secondary nodes when Geo is enabled
Gitlab::Geo.notify_wiki_update(project) if Gitlab::Geo.primary?
end end
page page
......
module EE
# PostReceive EE mixin
#
# This module is intended to encapsulate EE-specific model logic
# and be prepended in the `PostReceive` worker
module PostReceive
extend ActiveSupport::Concern
extend ::Gitlab::CurrentSettings
private
def after_project_changes_hooks(post_received, user, refs, changes)
super
# Generate repository updated event on Geo event log when Geo is enabled
::Geo::RepositoryUpdatedEventStore.new(post_received.project, refs: refs, changes: changes).create
end
def process_wiki_changes(post_received)
super
update_wiki_es_indexes(post_received)
if ::Gitlab::Geo.enabled?
# Create wiki repository updated event on Geo event log
::Geo::RepositoryUpdatedEventStore.new(post_received.project, source: Geo::RepositoryUpdatedEvent::WIKI).create
# Triggers repository update on secondary nodes
::Gitlab::Geo.notify_wiki_update(post_received.project)
end
end
def update_wiki_es_indexes(post_received)
return unless current_application_settings.elasticsearch_indexing?
post_received.project.wiki.index_blobs
end
end
end
class PostReceive class PostReceive
include Sidekiq::Worker include Sidekiq::Worker
include DedicatedSidekiqQueue include DedicatedSidekiqQueue
extend Gitlab::CurrentSettings prepend EE::PostReceive
def perform(project_identifier, identifier, changes) def perform(project_identifier, identifier, changes)
project, is_wiki = parse_project_identifier(project_identifier) project, is_wiki = parse_project_identifier(project_identifier)
...@@ -18,37 +18,18 @@ class PostReceive ...@@ -18,37 +18,18 @@ class PostReceive
post_received = Gitlab::GitPostReceive.new(project, identifier, changes) post_received = Gitlab::GitPostReceive.new(project, identifier, changes)
if is_wiki if is_wiki
update_wiki_es_indexes(post_received) process_wiki_changes(post_received)
# Triggers repository update on secondary nodes when Geo is enabled
Gitlab::Geo.notify_wiki_update(post_received.project) if Gitlab::Geo.enabled?
else else
process_project_changes(post_received) process_project_changes(post_received)
process_repository_update(post_received)
end end
end end
def process_repository_update(post_received) private
def process_project_changes(post_received)
changes = [] changes = []
refs = Set.new refs = Set.new
post_received.changes_refs do |oldrev, newrev, ref|
@user ||= post_received.identify(newrev)
unless @user
log("Triggered hook for non-existing user \"#{post_received.identifier}\"")
return false
end
changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref)
refs << ref
end
hook_data = Gitlab::DataBuilder::Repository.update(post_received.project, @user, changes, refs.to_a)
SystemHooksService.new.execute_hooks(hook_data, :repository_update_hooks)
end
def process_project_changes(post_received)
post_received.changes_refs do |oldrev, newrev, ref| post_received.changes_refs do |oldrev, newrev, ref|
@user ||= post_received.identify(newrev) @user ||= post_received.identify(newrev)
...@@ -62,16 +43,22 @@ class PostReceive ...@@ -62,16 +43,22 @@ class PostReceive
elsif Gitlab::Git.branch_ref?(ref) elsif Gitlab::Git.branch_ref?(ref)
GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
end end
changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref)
refs << ref
end end
end
def update_wiki_es_indexes(post_received) after_project_changes_hooks(post_received, @user, refs.to_a, changes)
return unless current_application_settings.elasticsearch_indexing? end
post_received.project.wiki.index_blobs def after_project_changes_hooks(post_received, user, refs, changes)
hook_data = Gitlab::DataBuilder::Repository.update(post_received.project, user, changes, refs)
SystemHooksService.new.execute_hooks(hook_data, :repository_update_hooks)
end end
private def process_wiki_changes(post_received)
# Nothing defined here yet.
end
# To maintain backwards compatibility, we accept both gl_repository or # To maintain backwards compatibility, we accept both gl_repository or
# repository paths as project identifiers. Our plan is to migrate to # repository paths as project identifiers. Our plan is to migrate to
......
---
title: Add push events to Geo event log
merge_request:
author:
...@@ -10,6 +10,6 @@ ...@@ -10,6 +10,6 @@
# end # end
# #
ActiveSupport::Inflector.inflections do |inflect| ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w(award_emoji project_statistics project_registry file_registry system_note_metadata) inflect.uncountable %w(award_emoji project_statistics system_note_metadata event_log project_registry file_registry)
inflect.acronym 'EE' inflect.acronym 'EE'
end end
require 'active_record/connection_adapters/abstract_mysql_adapter'
module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter
NATIVE_DATABASE_TYPES.merge!(
bigserial: { name: 'bigint(20) auto_increment PRIMARY KEY' }
)
end
end
end
class CreateGeoRepositoryUpdatedEvents < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :geo_repository_updated_events, id: :bigserial do |t|
t.datetime :created_at, null: false
t.integer :branches_affected, null: false
t.integer :tags_affected, null: false
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
t.integer :source, limit: 2, index: true, null: false
t.boolean :new_branch, default: false, null: false
t.boolean :remove_branch, default: false, null: false
t.text :ref
end
end
end
class CreateGeoEventLog < ActiveRecord::Migration
DOWNTIME = false
def change
create_table :geo_event_log, id: :bigserial do |t|
t.datetime :created_at, null: false
t.integer :repository_updated_event_id, limit: 8, index: true
t.foreign_key :geo_repository_updated_events,
column: :repository_updated_event_id, on_delete: :cascade
end
end
end
...@@ -535,6 +535,13 @@ ActiveRecord::Schema.define(version: 20170602003304) do ...@@ -535,6 +535,13 @@ ActiveRecord::Schema.define(version: 20170602003304) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "geo_event_log", id: :bigserial, force: :cascade do |t|
t.datetime "created_at", null: false
t.integer "repository_updated_event_id", limit: 8
end
add_index "geo_event_log", ["repository_updated_event_id"], name: "index_geo_event_log_on_repository_updated_event_id", using: :btree
create_table "geo_nodes", force: :cascade do |t| create_table "geo_nodes", force: :cascade do |t|
t.string "schema" t.string "schema"
t.string "host" t.string "host"
...@@ -555,6 +562,20 @@ ActiveRecord::Schema.define(version: 20170602003304) do ...@@ -555,6 +562,20 @@ ActiveRecord::Schema.define(version: 20170602003304) do
add_index "geo_nodes", ["host"], name: "index_geo_nodes_on_host", using: :btree add_index "geo_nodes", ["host"], name: "index_geo_nodes_on_host", using: :btree
add_index "geo_nodes", ["primary"], name: "index_geo_nodes_on_primary", using: :btree add_index "geo_nodes", ["primary"], name: "index_geo_nodes_on_primary", using: :btree
create_table "geo_repository_updated_events", id: :bigserial, force: :cascade do |t|
t.datetime "created_at", null: false
t.integer "branches_affected", null: false
t.integer "tags_affected", null: false
t.integer "project_id", null: false
t.integer "source", limit: 2, null: false
t.boolean "new_branch", default: false, null: false
t.boolean "remove_branch", default: false, null: false
t.text "ref"
end
add_index "geo_repository_updated_events", ["project_id"], name: "index_geo_repository_updated_events_on_project_id", using: :btree
add_index "geo_repository_updated_events", ["source"], name: "index_geo_repository_updated_events_on_source", using: :btree
create_table "historical_data", force: :cascade do |t| create_table "historical_data", force: :cascade do |t|
t.date "date", null: false t.date "date", null: false
t.integer "active_user_count" t.integer "active_user_count"
...@@ -1718,6 +1739,8 @@ ActiveRecord::Schema.define(version: 20170602003304) do ...@@ -1718,6 +1739,8 @@ ActiveRecord::Schema.define(version: 20170602003304) do
add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade
add_foreign_key "ci_variables", "projects", name: "fk_ada5eb64b3", on_delete: :cascade add_foreign_key "ci_variables", "projects", name: "fk_ada5eb64b3", on_delete: :cascade
add_foreign_key "container_repositories", "projects" add_foreign_key "container_repositories", "projects"
add_foreign_key "geo_event_log", "geo_repository_updated_events", column: "repository_updated_event_id", on_delete: :cascade
add_foreign_key "geo_repository_updated_events", "projects", on_delete: :cascade
add_foreign_key "issue_assignees", "issues", name: "fk_b7d881734a", on_delete: :cascade add_foreign_key "issue_assignees", "issues", name: "fk_b7d881734a", on_delete: :cascade
add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade
add_foreign_key "issue_links", "issues", column: "source_id", name: "fk_c900194ff2", on_delete: :cascade add_foreign_key "issue_links", "issues", column: "source_id", name: "fk_c900194ff2", on_delete: :cascade
......
require 'spec_helper'
RSpec.describe Geo::EventLog, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:repository_updated_event).class_name('Geo::RepositoryUpdatedEvent').with_foreign_key('repository_updated_event_id') }
end
end
require 'spec_helper'
RSpec.describe Geo::RepositoryUpdatedEvent, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
end
describe '#source' do
it { is_expected.to define_enum_for(:source).with([:repository, :wiki]) }
end
end
require 'spec_helper'
describe WikiPages::CreateService, services: true do
let(:project) { create(:empty_project) }
let(:user) { create(:user) }
let(:opts) do
{
title: 'Title',
content: 'Content for wiki page',
format: 'markdown'
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_master(user)
end
describe '#execute' do
context 'when running on a Geo primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
it 'triggers Geo::RepositoryUpdatedEventStore when Geo is enabled' do
expect(Geo::RepositoryUpdatedEventStore).to receive(:new).with(instance_of(Project), source: Geo::RepositoryUpdatedEvent::WIKI).and_call_original
expect_any_instance_of(Geo::RepositoryUpdatedEventStore).to receive(:create)
service.execute
end
it 'triggers wiki update on secondary nodes' do
expect(Gitlab::Geo).to receive(:notify_wiki_update).with(instance_of(Project))
service.execute
end
end
end
end
require 'spec_helper'
describe WikiPages::DestroyService, services: true do
let(:project) { create(:empty_project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
subject(:service) { described_class.new(project, user) }
before do
project.add_master(user)
end
describe '#execute' do
context 'when running on a Geo primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
it 'triggers Geo::RepositoryUpdatedEventStore when Geo is enabled' do
expect(Geo::RepositoryUpdatedEventStore).to receive(:new).with(instance_of(Project), source: Geo::RepositoryUpdatedEvent::WIKI).and_call_original
expect_any_instance_of(Geo::RepositoryUpdatedEventStore).to receive(:create)
service.execute(page)
end
it 'triggers wiki update on secondary nodes' do
expect(Gitlab::Geo).to receive(:notify_wiki_update).with(instance_of(Project))
service.execute(page)
end
end
end
end
require 'spec_helper'
describe WikiPages::UpdateService, services: true do
let(:project) { create(:empty_project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
let(:opts) do
{
content: 'New content for wiki page',
format: 'markdown',
message: 'New wiki message'
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_master(user)
end
describe '#execute' do
context 'when running on a Geo primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
it 'triggers Geo::RepositoryUpdatedEventStore when Geo is enabled' do
expect(Geo::RepositoryUpdatedEventStore).to receive(:new).with(instance_of(Project), source: Geo::RepositoryUpdatedEvent::WIKI).and_call_original
expect_any_instance_of(Geo::RepositoryUpdatedEventStore).to receive(:create)
service.execute(page)
end
it 'triggers wiki update on secondary nodes' do
expect(Gitlab::Geo).to receive(:notify_wiki_update).with(instance_of(Project))
service.execute(page)
end
end
end
end
require 'spec_helper'
describe Geo::RepositoryUpdatedEventStore, services: true do
let(:project) { create(:project) }
let(:blankrev) { Gitlab::Git::BLANK_SHA }
let(:refs) { ['refs/heads/tést', 'refs/tags/tag'] }
let(:changes) do
[
{ before: '123456', after: '789012', ref: 'refs/heads/tést' },
{ before: '654321', after: '210987', ref: 'refs/tags/tag' }
]
end
describe '#create' do
it 'does not create a push event when not running on a primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false }
subject = described_class.new(project, refs: refs, changes: changes)
expect { subject.create }.not_to change(Geo::RepositoryUpdatedEvent, :count)
end
context 'when running on a primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
it 'creates a push event' do
subject = described_class.new(project, refs: refs, changes: changes)
expect { subject.create }.to change(Geo::RepositoryUpdatedEvent, :count).by(1)
end
context 'when repository is being updated' do
it 'does not track ref name when post-receive event affect multiple refs' do
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.ref).to be_nil
end
it 'tracks ref name when post-receive event affect single ref' do
refs = ['refs/heads/tést']
changes = [{ before: '123456', after: blankrev, ref: 'refs/heads/tést' }]
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.ref).to eq 'refs/heads/tést'
end
it 'tracks number of branches post-receive event affects' do
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.branches_affected).to eq 1
end
it 'tracks number of tags post-receive event affects' do
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.tags_affected).to eq 1
end
it 'tracks when post-receive event create new branches' do
refs = ['refs/heads/tést', 'refs/heads/feature']
changes = [
{ before: '123456', after: '789012', ref: 'refs/heads/tést' },
{ before: blankrev, after: '210987', ref: 'refs/heads/feature' }
]
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.new_branch).to eq true
end
it 'tracks when post-receive event remove branches' do
refs = ['refs/heads/tést', 'refs/heads/feature']
changes = [
{ before: '123456', after: '789012', ref: 'refs/heads/tést' },
{ before: '654321', after: blankrev, ref: 'refs/heads/feature' }
]
subject = described_class.new(project, refs: refs, changes: changes)
subject.create
expect(Geo::RepositoryUpdatedEvent.last.remove_branch).to eq true
end
end
context 'when wiki is being updated' do
it 'does not track any information' do
subject = described_class.new(project, source: Geo::RepositoryUpdatedEvent::WIKI)
subject.create
push_event = Geo::RepositoryUpdatedEvent.last
expect(push_event.ref).to be_nil
expect(push_event.branches_affected).to be_zero
expect(push_event.tags_affected).to be_zero
expect(push_event.new_branch).to eq false
expect(push_event.remove_branch).to eq false
end
end
end
end
end
...@@ -2,7 +2,8 @@ require 'spec_helper' ...@@ -2,7 +2,8 @@ require 'spec_helper'
describe WikiPages::CreateService, services: true do describe WikiPages::CreateService, services: true do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:opts) do let(:opts) do
{ {
title: 'Title', title: 'Title',
...@@ -10,27 +11,25 @@ describe WikiPages::CreateService, services: true do ...@@ -10,27 +11,25 @@ describe WikiPages::CreateService, services: true do
format: 'markdown' format: 'markdown'
} }
end end
let(:service) { described_class.new(project, user, opts) }
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_master(user)
end
describe '#execute' do describe '#execute' do
context "valid params" do it 'creates wiki page with valid attributes' do
before do page = service.execute
allow(service).to receive(:execute_hooks)
project.add_master(user) expect(page).to be_valid
end expect(page).to have_attributes(title: opts[:title], content: opts[:content], format: opts[:format].to_sym)
end
subject { service.execute }
it 'executes webhooks' do
it 'creates a valid wiki page' do expect(service).to receive(:execute_hooks).once.with(instance_of(WikiPage), 'create')
is_expected.to be_valid
expect(subject.title).to eq(opts[:title]) service.execute
expect(subject.content).to eq(opts[:content])
expect(subject.format).to eq(opts[:format].to_sym)
end
it 'executes webhooks' do
expect(service).to have_received(:execute_hooks).once.with(subject, 'create')
end
end end
end end
end end
...@@ -2,20 +2,20 @@ require 'spec_helper' ...@@ -2,20 +2,20 @@ require 'spec_helper'
describe WikiPages::DestroyService, services: true do describe WikiPages::DestroyService, services: true do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:wiki_page) { create(:wiki_page) } let(:page) { create(:wiki_page) }
let(:service) { described_class.new(project, user) }
describe '#execute' do subject(:service) { described_class.new(project, user) }
before do
allow(service).to receive(:execute_hooks)
project.add_master(user)
end
before do
project.add_master(user)
end
describe '#execute' do
it 'executes webhooks' do it 'executes webhooks' do
service.execute(wiki_page) expect(service).to receive(:execute_hooks).once.with(instance_of(WikiPage), 'delete')
expect(service).to have_received(:execute_hooks).once.with(wiki_page, 'delete') service.execute(page)
end end
end end
end end
...@@ -2,8 +2,9 @@ require 'spec_helper' ...@@ -2,8 +2,9 @@ require 'spec_helper'
describe WikiPages::UpdateService, services: true do describe WikiPages::UpdateService, services: true do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:wiki_page) { create(:wiki_page) } let(:page) { create(:wiki_page) }
let(:opts) do let(:opts) do
{ {
content: 'New content for wiki page', content: 'New content for wiki page',
...@@ -11,27 +12,25 @@ describe WikiPages::UpdateService, services: true do ...@@ -11,27 +12,25 @@ describe WikiPages::UpdateService, services: true do
message: 'New wiki message' message: 'New wiki message'
} }
end end
let(:service) { described_class.new(project, user, opts) }
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_master(user)
end
describe '#execute' do describe '#execute' do
context "valid params" do it 'updates the wiki page' do
before do updated_page = service.execute(page)
allow(service).to receive(:execute_hooks)
project.add_master(user) expect(updated_page).to be_valid
end expect(updated_page).to have_attributes(message: opts[:message], content: opts[:content], format: opts[:format].to_sym)
end
subject { service.execute(wiki_page) }
it 'executes webhooks' do
it 'updates the wiki page' do expect(service).to receive(:execute_hooks).once.with(instance_of(WikiPage), 'update')
is_expected.to be_valid
expect(subject.content).to eq(opts[:content]) service.execute(page)
expect(subject.format).to eq(opts[:format].to_sym)
expect(subject.message).to eq(opts[:message])
end
it 'executes webhooks' do
expect(service).to have_received(:execute_hooks).once.with(subject, 'update')
end
end end
end end
end end
require 'spec_helper'
describe PostReceive do
let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
let(:project_identifier) { "project-#{project.id}" }
let(:key) { create(:key, user: project.owner) }
let(:key_id) { key.shell_id }
let(:project) { create(:project, :repository) }
describe "#process_project_changes" do
before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
end
context 'after project changes hooks' do
let(:fake_hook_data) { Hash.new(event_name: 'repository_update') }
before do
allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
# silence hooks so we can isolate
allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
allow_any_instance_of(GitTagPushService).to receive(:execute).and_return(true)
allow_any_instance_of(GitPushService).to receive(:execute).and_return(true)
end
it 'calls Geo::RepositoryUpdatedEventStore' do
expect_any_instance_of(Geo::RepositoryUpdatedEventStore).to receive(:create)
described_class.new.perform(project_identifier, key_id, base64_changes)
end
end
end
describe '#process_wiki_changes' do
let(:project_identifier) { "#{pwd(project)}.wiki" }
it 'triggers Geo::RepositoryUpdatedEventStore when Geo is enabled' do
allow(Gitlab::Geo).to receive(:enabled?) { true }
expect(Geo::RepositoryUpdatedEventStore).to receive(:new).with(instance_of(Project), source: Geo::RepositoryUpdatedEvent::WIKI).and_call_original
expect_any_instance_of(Geo::RepositoryUpdatedEventStore).to receive(:create)
described_class.new.perform(project_identifier, key_id, base64_changes)
end
it 'triggers wiki index update when ElasticSearch is enabled' do
expect(Project).to receive(:find_by_full_path).with("#{project.full_path}.wiki").and_return(nil)
expect(Project).to receive(:find_by_full_path).with(project.full_path).and_return(project)
stub_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
expect_any_instance_of(ProjectWiki).to receive(:index_blobs)
described_class.new.perform(project_identifier, key_id, base64_changes)
end
end
def pwd(project)
File.join(Gitlab.config.repositories.storages.default['path'], project.path_with_namespace)
end
end
...@@ -4,9 +4,10 @@ describe 'Every Sidekiq worker' do ...@@ -4,9 +4,10 @@ describe 'Every Sidekiq worker' do
let(:workers) do let(:workers) do
root = Rails.root.join('app', 'workers') root = Rails.root.join('app', 'workers')
concerns = root.join('concerns').to_s concerns = root.join('concerns').to_s
ee_modules = root.join('ee').to_s
workers = Dir[root.join('**', '*.rb')]. workers = Dir[root.join('**', '*.rb')].
reject { |path| path.start_with?(concerns) } reject { |path| path.start_with?(concerns, ee_modules) }
workers.map do |path| workers.map do |path|
ns = Pathname.new(path).relative_path_from(root).to_s.gsub('.rb', '') ns = Pathname.new(path).relative_path_from(root).to_s.gsub('.rb', '')
......
...@@ -94,26 +94,23 @@ describe PostReceive do ...@@ -94,26 +94,23 @@ describe PostReceive do
it { expect{ subject }.not_to change{ Ci::Pipeline.count } } it { expect{ subject }.not_to change{ Ci::Pipeline.count } }
end end
end end
end
describe '#process_repository_update' do context 'after project changes hooks' do
let(:changes) {'123456 789012 refs/heads/tést'} let(:changes) { '123456 789012 refs/heads/tést' }
let(:fake_hook_data) do let(:fake_hook_data) { Hash.new(event_name: 'repository_update') }
{ event_name: 'repository_update' }
end
before do before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner) allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data) # silence hooks so we can isolate
# silence hooks so we can isolate allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true) allow_any_instance_of(GitPushService).to receive(:execute).and_return(true)
allow(subject).to receive(:process_project_changes).and_return(true) end
end
it 'calls SystemHooksService' do it 'calls SystemHooksService' do
expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true) expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true)
subject.perform(pwd(project), key_id, base64_changes) described_class.new.perform(project_identifier, key_id, base64_changes)
end
end end
end end
...@@ -123,17 +120,6 @@ describe PostReceive do ...@@ -123,17 +120,6 @@ describe PostReceive do
described_class.new.perform(project_identifier, key_id, base64_changes) described_class.new.perform(project_identifier, key_id, base64_changes)
end end
it "triggers wiki index update" do
expect(Project).to receive(:find_by_full_path).with("#{project.full_path}.wiki").and_return(nil)
expect(Project).to receive(:find_by_full_path).with(project.full_path).and_return(project)
stub_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
expect_any_instance_of(ProjectWiki).to receive(:index_blobs)
repo_path = "#{pwd(project)}.wiki"
described_class.new.perform(repo_path, key_id, base64_changes)
end
it "does not run if the author is not in the project" do it "does not run if the author is not in the project" do
allow_any_instance_of(Gitlab::GitPostReceive). allow_any_instance_of(Gitlab::GitPostReceive).
to receive(:identify_using_ssh_key). to receive(:identify_using_ssh_key).
......
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