Create a push event on Geo event log when repository is being updated

parent 2ba6ea60
......@@ -5,7 +5,5 @@ module Geo
belongs_to :project
validates :project, presence: true
enum event_type: { repository_updated: 0, wiki_updated: 1 }
end
end
module Geo
class PushService
attr_reader :project, :refs, :changes
def initialize(project, refs, changes)
@project = project
@refs = refs
@changes = changes
end
def execute
return unless Gitlab::Geo.primary?
Geo::EventLog.transaction do
event_log = Geo::EventLog.new
event_log.push_event = build_push_event
event_log.save!
end
rescue ActiveRecord::RecordInvalid
log('Push event could not created')
end
private
def build_push_event
Geo::PushEvent.new(
project: project,
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
......@@ -44,6 +44,8 @@ class PostReceive
refs << ref
end
Geo::PushService.new(post_received.project, changes, refs.to_a).execute
hook_data = Gitlab::DataBuilder::Repository.update(post_received.project, @user, changes, refs.to_a)
SystemHooksService.new.execute_hooks(hook_data, :repository_update_hooks)
end
......
......@@ -5,7 +5,11 @@ class CreateGeoPushEvents < ActiveRecord::Migration
create_table :geo_push_events do |t|
t.references :project, index: true, foreign_key: { on_delete: :cascade }, null: false
t.datetime :created_at, null: false
t.integer :event_type, limit: 2, index: true, null: false
t.string :ref
t.integer :branches_affected, null: false
t.integer :tags_affected, null: false
t.boolean :new_branch, default: false, null: false
t.boolean :remove_branch, default: false, null: false
end
end
end
......@@ -531,10 +531,13 @@ ActiveRecord::Schema.define(version: 20170602003304) do
create_table "geo_push_events", force: :cascade do |t|
t.integer "project_id", null: false
t.datetime "created_at", null: false
t.integer "event_type", limit: 2, null: false
t.string "ref"
t.integer "branches_affected", null: false
t.integer "tags_affected", null: false
t.boolean "new_branch", default: false, null: false
t.boolean "remove_branch", default: false, null: false
end
add_index "geo_push_events", ["event_type"], name: "index_geo_push_events_on_event_type", using: :btree
add_index "geo_push_events", ["project_id"], name: "index_geo_push_events_on_project_id", using: :btree
create_table "historical_data", force: :cascade do |t|
......
require 'spec_helper'
describe Geo::PushService, 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 '#execute' 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, changes)
expect { subject.execute }.not_to change(Geo::PushEvent, :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, changes)
expect { subject.execute }.to change(Geo::PushEvent, :count).by(1)
end
it 'does not track ref name when post-receive event affect multiple refs' do
subject = described_class.new(project, refs, changes)
subject.execute
expect(Geo::PushEvent.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, changes)
subject.execute
expect(Geo::PushEvent.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, changes)
subject.execute
expect(Geo::PushEvent.last.branches_affected).to eq 1
end
it 'tracks number of tags post-receive event affects' do
subject = described_class.new(project, refs, changes)
subject.execute
expect(Geo::PushEvent.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, changes)
subject.execute
expect(Geo::PushEvent.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, changes)
subject.execute
expect(Geo::PushEvent.last.remove_branch).to eq true
end
end
end
end
......@@ -110,6 +110,12 @@ describe PostReceive do
allow(subject).to receive(:process_project_changes).and_return(true)
end
it 'calls Geo::PushService' do
expect_any_instance_of(Geo::PushService).to receive(:execute)
subject.perform(pwd(project), key_id, base64_changes)
end
it 'calls SystemHooksService' do
expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true)
......
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