Skip to content
Snippets Groups Projects
Commit 5b266be8 authored by Vladimir Shushlin's avatar Vladimir Shushlin
Browse files

Add status_changed_at to deployment webhooks payload

* Add Deployments::HooksWorker with flexible params
* Pass event_at to Deployment::HooksWorker
* It will be passed in webhook payload
* Add deployment_hooks to all_queues
* Add TODO for removing old Deployments::ExecuteHooksWorker
parent 36c9bb54
No related branches found
No related tags found
No related merge requests found
Showing
with 143 additions and 43 deletions
Loading
Loading
@@ -87,7 +87,7 @@ class Deployment < ApplicationRecord
 
after_transition any => :running do |deployment|
deployment.run_after_commit do
Deployments::ExecuteHooksWorker.perform_async(id)
Deployments::HooksWorker.perform_async(deployment_id: id, status_changed_at: Time.current)
end
end
 
Loading
Loading
@@ -100,7 +100,7 @@ class Deployment < ApplicationRecord
 
after_transition any => FINISHED_STATUSES do |deployment|
deployment.run_after_commit do
Deployments::ExecuteHooksWorker.perform_async(id)
Deployments::HooksWorker.perform_async(deployment_id: id, status_changed_at: Time.current)
end
end
 
Loading
Loading
@@ -182,8 +182,8 @@ def short_sha
Commit.truncate_sha(sha)
end
 
def execute_hooks
deployment_data = Gitlab::DataBuilder::Deployment.build(self)
def execute_hooks(status_changed_at)
deployment_data = Gitlab::DataBuilder::Deployment.build(self, status_changed_at)
project.execute_hooks(deployment_data, :deployment_hooks)
project.execute_services(deployment_data, :deployment_hooks)
end
Loading
Loading
Loading
Loading
@@ -63,7 +63,7 @@ def deployment_events_data
 
return { error: s_('TestHooks|Ensure the project has deployments.') } unless deployment.present?
 
Gitlab::DataBuilder::Deployment.build(deployment)
Gitlab::DataBuilder::Deployment.build(deployment, Time.current)
end
 
def releases_events_data
Loading
Loading
Loading
Loading
@@ -642,6 +642,15 @@
:weight: 3
:idempotent:
:tags: []
- :name: deployment:deployments_hooks
:worker_name: Deployments::HooksWorker
:feature_category: :continuous_delivery
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 3
:idempotent:
:tags: []
- :name: deployment:deployments_link_merge_request
:worker_name: Deployments::LinkMergeRequestWorker
:feature_category: :continuous_delivery
Loading
Loading
# frozen_string_literal: true
 
module Deployments
# TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/329360
class ExecuteHooksWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
 
Loading
Loading
@@ -10,7 +11,7 @@ class ExecuteHooksWorker # rubocop:disable Scalability/IdempotentWorker
 
def perform(deployment_id)
if (deploy = Deployment.find_by_id(deployment_id))
deploy.execute_hooks
deploy.execute_hooks(Time.current)
end
end
end
Loading
Loading
Loading
Loading
@@ -13,7 +13,7 @@ class FinishedWorker # rubocop:disable Scalability/IdempotentWorker
def perform(deployment_id)
if (deploy = Deployment.find_by_id(deployment_id))
LinkMergeRequestsService.new(deploy).execute
deploy.execute_hooks
deploy.execute_hooks(Time.current)
end
end
end
Loading
Loading
# frozen_string_literal: true
module Deployments
class HooksWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
queue_namespace :deployment
feature_category :continuous_delivery
def perform(params = {})
params = params.with_indifferent_access
if (deploy = Deployment.find_by_id(params[:deployment_id]))
deploy.execute_hooks(params[:status_changed_at].to_time)
end
end
end
end
---
title: Add status_changed_at to deployments webhooks
merge_request: 60518
author:
type: added
Loading
Loading
@@ -1368,6 +1368,7 @@ X-Gitlab-Event: Deployment Hook
{
"object_kind": "deployment",
"status": "success",
"status_changed_at":"2021-04-28 21:50:00 +0200",
"deployable_id": 796,
"deployable_url": "http://10.126.0.2:3000/root/test-deployment-webhooks/-/jobs/796",
"environment": "staging",
Loading
Loading
Loading
Loading
@@ -36,7 +36,7 @@
context 'when user does not have access to the environment' do
it 'fails the build' do
allow(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
allow(Deployments::HooksWorker).to receive(:perform_async)
subject
 
expect(ci_build.failed?).to be_truthy
Loading
Loading
Loading
Loading
@@ -5,7 +5,7 @@ module DataBuilder
module Deployment
extend self
 
def build(deployment)
def build(deployment, status_changed_at)
# Deployments will not have a deployable when created using the API.
deployable_url =
if deployment.deployable
Loading
Loading
@@ -15,6 +15,7 @@ def build(deployment)
{
object_kind: 'deployment',
status: deployment.status,
status_changed_at: status_changed_at,
deployable_id: deployment.deployable_id,
deployable_url: deployable_url,
environment: deployment.environment.name,
Loading
Loading
Loading
Loading
@@ -7,7 +7,7 @@
it 'returns the object kind for a deployment' do
deployment = build(:deployment, deployable: nil, environment: create(:environment))
 
data = described_class.build(deployment)
data = described_class.build(deployment, Time.current)
 
expect(data[:object_kind]).to eq('deployment')
end
Loading
Loading
@@ -21,10 +21,12 @@
expected_deployable_url = Gitlab::Routing.url_helpers.project_job_url(deployable.project, deployable)
expected_user_url = Gitlab::Routing.url_helpers.user_url(deployment.deployed_by)
expected_commit_url = Gitlab::UrlBuilder.build(commit)
status_changed_at = Time.current
 
data = described_class.build(deployment)
data = described_class.build(deployment, status_changed_at)
 
expect(data[:status]).to eq('failed')
expect(data[:status_changed_at]).to eq(status_changed_at)
expect(data[:deployable_id]).to eq(deployable.id)
expect(data[:deployable_url]).to eq(expected_deployable_url)
expect(data[:environment]).to eq("somewhere")
Loading
Loading
@@ -38,7 +40,7 @@
 
it 'does not include the deployable URL when there is no deployable' do
deployment = create(:deployment, status: :failed, deployable: nil)
data = described_class.build(deployment)
data = described_class.build(deployment, Time.current)
 
expect(data[:deployable_url]).to be_nil
end
Loading
Loading
Loading
Loading
@@ -1205,7 +1205,7 @@
 
before do
allow(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
allow(Deployments::HooksWorker).to receive(:perform_async)
end
 
it 'has deployments record with created status' do
Loading
Loading
@@ -1241,7 +1241,7 @@
 
before do
allow(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
allow(Deployments::HooksWorker).to receive(:perform_async)
end
 
it_behaves_like 'avoid deadlock'
Loading
Loading
Loading
Loading
@@ -107,11 +107,13 @@
end
end
 
it 'executes Deployments::ExecuteHooksWorker asynchronously' do
expect(Deployments::ExecuteHooksWorker)
.to receive(:perform_async).with(deployment.id)
it 'executes Deployments::HooksWorker asynchronously' do
freeze_time do
expect(Deployments::HooksWorker)
.to receive(:perform_async).with(deployment_id: deployment.id, status_changed_at: Time.current)
 
deployment.run!
deployment.run!
end
end
 
it 'executes Deployments::DropOlderDeploymentsWorker asynchronously' do
Loading
Loading
@@ -141,11 +143,13 @@
deployment.succeed!
end
 
it 'executes Deployments::ExecuteHooksWorker asynchronously' do
expect(Deployments::ExecuteHooksWorker)
.to receive(:perform_async).with(deployment.id)
it 'executes Deployments::HooksWorker asynchronously' do
freeze_time do
expect(Deployments::HooksWorker)
.to receive(:perform_async).with(deployment_id: deployment.id, status_changed_at: Time.current)
 
deployment.succeed!
deployment.succeed!
end
end
end
 
Loading
Loading
@@ -168,11 +172,13 @@
deployment.drop!
end
 
it 'executes Deployments::ExecuteHooksWorker asynchronously' do
expect(Deployments::ExecuteHooksWorker)
.to receive(:perform_async).with(deployment.id)
it 'executes Deployments::HooksWorker asynchronously' do
freeze_time do
expect(Deployments::HooksWorker)
.to receive(:perform_async).with(deployment_id: deployment.id, status_changed_at: Time.current)
 
deployment.drop!
deployment.drop!
end
end
end
 
Loading
Loading
@@ -195,11 +201,13 @@
deployment.cancel!
end
 
it 'executes Deployments::ExecuteHooksWorker asynchronously' do
expect(Deployments::ExecuteHooksWorker)
.to receive(:perform_async).with(deployment.id)
it 'executes Deployments::HooksWorker asynchronously' do
freeze_time do
expect(Deployments::HooksWorker)
.to receive(:perform_async).with(deployment_id: deployment.id, status_changed_at: Time.current)
 
deployment.cancel!
deployment.cancel!
end
end
end
 
Loading
Loading
@@ -220,11 +228,13 @@
deployment.skip!
end
 
it 'does not execute Deployments::ExecuteHooksWorker' do
expect(Deployments::ExecuteHooksWorker)
.not_to receive(:perform_async).with(deployment.id)
it 'does not execute Deployments::HooksWorker' do
freeze_time do
expect(Deployments::HooksWorker)
.not_to receive(:perform_async).with(deployment_id: deployment.id, status_changed_at: Time.current)
 
deployment.skip!
deployment.skip!
end
end
end
 
Loading
Loading
@@ -714,7 +724,7 @@
it 'schedules workers when finishing a deploy' do
expect(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
expect(Deployments::ExecuteHooksWorker).to receive(:perform_async)
expect(Deployments::HooksWorker).to receive(:perform_async)
 
deploy.update_status('success')
end
Loading
Loading
Loading
Loading
@@ -9,7 +9,7 @@
project = create(:project, :repository)
commit = project.commit('HEAD')
deployment = create(:deployment, status: :success, environment: environment, project: project, sha: commit.sha)
data = Gitlab::DataBuilder::Deployment.build(deployment)
data = Gitlab::DataBuilder::Deployment.build(deployment, Time.current)
 
message = described_class.new(data)
 
Loading
Loading
@@ -118,7 +118,7 @@ def deployment_data(params)
job_url = Gitlab::Routing.url_helpers.project_job_url(project, ci_build)
commit_url = Gitlab::UrlBuilder.build(deployment.commit)
user_url = Gitlab::Routing.url_helpers.user_url(user)
data = Gitlab::DataBuilder::Deployment.build(deployment)
data = Gitlab::DataBuilder::Deployment.build(deployment, Time.current)
 
message = described_class.new(data)
 
Loading
Loading
Loading
Loading
@@ -59,7 +59,7 @@
context 'deployment notification' do
let_it_be(:deployment) { create(:deployment, user: user) }
 
let(:data) { Gitlab::DataBuilder::Deployment.build(deployment) }
let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
 
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification'
end
Loading
Loading
Loading
Loading
@@ -21,7 +21,7 @@
 
expect(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
expect(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
expect(Deployments::ExecuteHooksWorker).to receive(:perform_async)
expect(Deployments::HooksWorker).to receive(:perform_async)
 
expect(service.execute).to be_persisted
end
Loading
Loading
@@ -37,7 +37,7 @@
 
expect(Deployments::UpdateEnvironmentWorker).not_to receive(:perform_async)
expect(Deployments::LinkMergeRequestWorker).not_to receive(:perform_async)
expect(Deployments::ExecuteHooksWorker).not_to receive(:perform_async)
expect(Deployments::HooksWorker).not_to receive(:perform_async)
 
expect(service.execute).to be_persisted
end
Loading
Loading
@@ -57,7 +57,7 @@
 
expect(Deployments::UpdateEnvironmentWorker).not_to receive(:perform_async)
expect(Deployments::LinkMergeRequestWorker).not_to receive(:perform_async)
expect(Deployments::ExecuteHooksWorker).not_to receive(:perform_async)
expect(Deployments::HooksWorker).not_to receive(:perform_async)
 
described_class.new(environment.reload, user, params).execute
end
Loading
Loading
Loading
Loading
@@ -33,7 +33,7 @@
 
before do
allow(Deployments::LinkMergeRequestWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
allow(Deployments::HooksWorker).to receive(:perform_async)
job.success! # Create/Succeed deployment
end
 
Loading
Loading
Loading
Loading
@@ -201,7 +201,7 @@ def execute_with_options(options)
 
context 'deployment events' do
let_it_be(:deployment) { create(:deployment) }
let(:data) { Gitlab::DataBuilder::Deployment.build(deployment) }
let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, Time.current) }
 
it_behaves_like 'calls the service API with the event message', /Deploy to (.*?) created/
end
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Deployments::HooksWorker do
let(:worker) { described_class.new }
describe '#perform' do
before do
allow(ProjectServiceWorker).to receive(:perform_async)
end
it 'executes project services for deployment_hooks' do
deployment = create(:deployment, :running)
project = deployment.project
service = create(:service, type: 'SlackService', project: project, deployment_events: true, active: true)
expect(ProjectServiceWorker).to receive(:perform_async).with(service.id, an_instance_of(Hash))
worker.perform(deployment_id: deployment.id, status_changed_at: Time.current)
end
it 'does not execute an inactive service' do
deployment = create(:deployment, :running)
project = deployment.project
create(:service, type: 'SlackService', project: project, deployment_events: true, active: false)
expect(ProjectServiceWorker).not_to receive(:perform_async)
worker.perform(deployment_id: deployment.id, status_changed_at: Time.current)
end
it 'does not execute if a deployment does not exist' do
expect(ProjectServiceWorker).not_to receive(:perform_async)
worker.perform(deployment_id: non_existing_record_id, status_changed_at: Time.current)
end
it 'execute webhooks' do
deployment = create(:deployment, :running)
project = deployment.project
web_hook = create(:project_hook, deployment_events: true, project: project)
status_changed_at = Time.current
expect_next_instance_of(WebHookService, web_hook, hash_including(status_changed_at: status_changed_at), "deployment_hooks") do |service|
expect(service).to receive(:async_execute)
end
worker.perform(deployment_id: deployment.id, status_changed_at: status_changed_at)
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment