From cacc9e55ea744ebe09b8c938fa74ee35e8a8bd48 Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Fri, 24 Oct 2025 04:15:40 +0500 Subject: [PATCH 1/7] Restore Repo and orgs --- lib/travis/remote_vcs/organization.rb | 9 +++ lib/travis/remote_vcs/repository.rb | 9 +++ .../services/assembla_notify_service.rb | 37 +++++++--- .../services/assembla_notify_service_spec.rb | 69 +++++++++++-------- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/lib/travis/remote_vcs/organization.rb b/lib/travis/remote_vcs/organization.rb index 3099608a5..7a11522c9 100644 --- a/lib/travis/remote_vcs/organization.rb +++ b/lib/travis/remote_vcs/organization.rb @@ -13,6 +13,15 @@ def destroy(org_id:) Travis.logger.error("Failed to destroy organization: #{e.message}") false end + + def restore(org_id:) + request(:post, __method__, false) do |req| + req.url "organizations/#{org_id}/restore" + end + rescue ResponseError => e + Travis.logger.error("Failed to restore organization: #{e.message}") + false + end end end end diff --git a/lib/travis/remote_vcs/repository.rb b/lib/travis/remote_vcs/repository.rb index b62c9b868..96def57ba 100644 --- a/lib/travis/remote_vcs/repository.rb +++ b/lib/travis/remote_vcs/repository.rb @@ -82,6 +82,15 @@ def destroy(repository_id:) Travis.logger.error("Failed to destroy repository: #{e.message}") false end + + def restore(repository_id:) + request(:post, __method__, false) do |req| + req.url "repos/#{repository_id}/restore" + end + rescue ResponseError => e + Travis.logger.error("Failed to restore repository: #{e.message}") + false + end end end end diff --git a/lib/travis/services/assembla_notify_service.rb b/lib/travis/services/assembla_notify_service.rb index e0811c9d5..1d1eb9b12 100644 --- a/lib/travis/services/assembla_notify_service.rb +++ b/lib/travis/services/assembla_notify_service.rb @@ -6,7 +6,7 @@ module Travis module Services class AssemblaNotifyService - VALID_ACTIONS = %w[destroy].freeze + VALID_ACTIONS = %w[destroy restore].freeze VALID_OBJECTS = %w[space tool].freeze def initialize(payload) @@ -16,14 +16,15 @@ def initialize(payload) end def run - validate + return false unless validate + case @object when 'tool' - handle_tool_destruction + handle_tool_action when 'space' - handle_space_destruction + handle_space_action else - { status: 400, body: { error: 'Unsupported object type for destruction' } } + false end end @@ -31,22 +32,36 @@ def run def validate unless VALID_ACTIONS.include?(@action) - return { status: 400, body: { error: 'Invalid action', allowed_actions: VALID_ACTIONS } } + Travis.logger.error("Invalid action: #{@action}. Allowed actions: #{VALID_ACTIONS.join(', ')}") + return false end unless VALID_OBJECTS.include?(@object) - return { status: 400, body: { error: 'Invalid object type', allowed_objects: VALID_OBJECTS } } + Travis.logger.error("Invalid object type: #{@object}. Allowed objects: #{VALID_OBJECTS.join(', ')}") + return false end + + true end - def handle_tool_destruction + def handle_tool_action vcs_repository = Travis::RemoteVCS::Repository.new - vcs_repository.destroy(repository_id: @object_id) + case @action + when 'destroy' + vcs_repository.destroy(repository_id: @object_id) + when 'restore' + vcs_repository.restore(repository_id: @object_id) + end end - def handle_space_destruction + def handle_space_action vcs_organization = Travis::RemoteVCS::Organization.new - vcs_organization.destroy(org_id: @object_id) + case @action + when 'destroy' + vcs_organization.destroy(org_id: @object_id) + when 'restore' + vcs_organization.restore(org_id: @object_id) + end end end end diff --git a/spec/lib/services/assembla_notify_service_spec.rb b/spec/lib/services/assembla_notify_service_spec.rb index ba0ed3d33..3fd032bb0 100644 --- a/spec/lib/services/assembla_notify_service_spec.rb +++ b/spec/lib/services/assembla_notify_service_spec.rb @@ -10,15 +10,25 @@ before do allow(Travis::RemoteVCS::Repository).to receive(:new).and_return(vcs_repository) allow(vcs_repository).to receive(:destroy) + allow(vcs_repository).to receive(:restore) allow(Travis::RemoteVCS::Organization).to receive(:new).and_return(vcs_organization) allow(vcs_organization).to receive(:destroy) + allow(vcs_organization).to receive(:restore) allow(Travis.logger).to receive(:error) end describe '#run' do context 'with a valid payload for tool destruction' do - it 'calls handle_tool_destruction' do - expect(service).to receive(:handle_tool_destruction) + it 'calls destroy on the vcs_repository' do + expect(vcs_repository).to receive(:destroy).with(repository_id: '12345') + service.run + end + end + + context 'with a valid payload for tool restoration' do + let(:payload) { { action: 'restore', object: 'tool', id: '12345' } } + it 'calls restore on the vcs_repository' do + expect(vcs_repository).to receive(:restore).with(repository_id: '12345') service.run end end @@ -26,8 +36,17 @@ context 'with a valid payload for space destruction' do let(:payload) { { action: 'destroy', object: 'space', id: '67890' } } - it 'calls handle_space_destruction' do - expect(service).to receive(:handle_space_destruction) + it 'calls destroy on the vcs_organization' do + expect(vcs_organization).to receive(:destroy).with(org_id: '67890') + service.run + end + end + + context 'with a valid payload for space restoration' do + let(:payload) { { action: 'restore', object: 'space', id: '67890' } } + + it 'calls restore on the vcs_organization' do + expect(vcs_organization).to receive(:restore).with(org_id: '67890') service.run end end @@ -35,38 +54,34 @@ context 'with an invalid object type' do let(:payload) { { action: 'destroy', object: 'repository', id: '12345' } } - it 'returns an error' do - result = service.run - expect(result[:status]).to eq(400) + it 'returns false and logs an error' do + expect(service.run).to be_falsey + expect(Travis.logger).to have_received(:error).with("Invalid object type: repository. Allowed objects: space, tool") + end + end + + context 'with an invalid action type' do + let(:payload) { { action: 'modify', object: 'tool', id: '12345' } } + + it 'returns false and logs an error' do + expect(service.run).to be_falsey + expect(Travis.logger).to have_received(:error).with("Invalid action: modify. Allowed actions: destroy, restore") end end - context 'with an unsupported object type for destruction' do + context 'with an unsupported object type for an action' do before do stub_const("Travis::Services::AssemblaNotifyService::VALID_OBJECTS", %w[space tool unsupported]) end let(:payload) { { action: 'destroy', object: 'unsupported', id: '12345' } } - it 'returns an error' do - result = service.run - expect(result[:status]).to eq(400) + it 'returns false without logging an error for the action' do + expect(service.run).to be_falsey + expect(vcs_repository).not_to receive(:destroy) + expect(vcs_repository).not_to receive(:restore) + expect(vcs_organization).not_to receive(:destroy) + expect(vcs_organization).not_to receive(:restore) end end end - - describe '#handle_tool_destruction' do - it 'destroys the repository using RemoteVCS' do - expect(vcs_repository).to receive(:destroy).with(repository_id: '12345') - service.send(:handle_tool_destruction) - end - end - - describe '#handle_space_destruction' do - let(:payload) { { action: 'destroy', object: 'space', id: '67890' } } - - it 'destroys the organization using RemoteVCS' do - expect(vcs_organization).to receive(:destroy).with(org_id: '67890') - service.send(:handle_space_destruction) - end - end end From 5decf4920729533c819357833714d470a7e48787 Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Tue, 28 Oct 2025 01:54:19 +0500 Subject: [PATCH 2/7] Stub request --- spec/travis/remote_vcs/organization_spec.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/spec/travis/remote_vcs/organization_spec.rb b/spec/travis/remote_vcs/organization_spec.rb index 5750f2a52..f65a57598 100644 --- a/spec/travis/remote_vcs/organization_spec.rb +++ b/spec/travis/remote_vcs/organization_spec.rb @@ -19,16 +19,9 @@ it { is_expected.to be true } end - context 'when the request fails' do - let!(:request) do - stub_request(:delete, /http.*\/organizations\/#{org_id}/) - .to_return(status: 500) - end - - it 'returns false' do - expect(subject).to be false - end + before { allow(client).to receive(:request).and_return(false) } + it { is_expected.to be false } end end end From 4c629ec5a2cc0274aa0cff1613857ec9869c2517 Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Tue, 4 Nov 2025 15:37:10 +0500 Subject: [PATCH 3/7] Used restrict instead of destroy --- lib/travis/remote_vcs/repository.rb | 5 +++-- lib/travis/services/assembla_notify_service.rb | 8 ++++---- .../lib/services/assembla_notify_service_spec.rb | 16 ++++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/travis/remote_vcs/repository.rb b/lib/travis/remote_vcs/repository.rb index 96def57ba..08abd32c7 100644 --- a/lib/travis/remote_vcs/repository.rb +++ b/lib/travis/remote_vcs/repository.rb @@ -45,7 +45,7 @@ def delete_key(repository_id:, user_id:, id:) def show(repository_id:, admin_id: nil) request(:get, __method__, false) do |req| req.url "repos/#{repository_id}" - req.params['admin_id'] = admin_id + end rescue ResponseError nil @@ -74,9 +74,10 @@ def set_perforce_ticket(repository_id:, user_id:) {} end - def destroy(repository_id:) + def destroy(repository_id:, vcs_type:) request(:delete, __method__, false) do |req| req.url "repos/#{repository_id}" + req.params['vcs_type'] = vcs_type end rescue ResponseError => e Travis.logger.error("Failed to destroy repository: #{e.message}") diff --git a/lib/travis/services/assembla_notify_service.rb b/lib/travis/services/assembla_notify_service.rb index 1d1eb9b12..276c9bca3 100644 --- a/lib/travis/services/assembla_notify_service.rb +++ b/lib/travis/services/assembla_notify_service.rb @@ -6,7 +6,7 @@ module Travis module Services class AssemblaNotifyService - VALID_ACTIONS = %w[destroy restore].freeze + VALID_ACTIONS = %w[restrict restore].freeze VALID_OBJECTS = %w[space tool].freeze def initialize(payload) @@ -47,8 +47,8 @@ def validate def handle_tool_action vcs_repository = Travis::RemoteVCS::Repository.new case @action - when 'destroy' - vcs_repository.destroy(repository_id: @object_id) + when 'restrict' + vcs_repository.destroy(repository_id: @object_id, vcs_type: 'AssemblaRepository') when 'restore' vcs_repository.restore(repository_id: @object_id) end @@ -57,7 +57,7 @@ def handle_tool_action def handle_space_action vcs_organization = Travis::RemoteVCS::Organization.new case @action - when 'destroy' + when 'restrict' vcs_organization.destroy(org_id: @object_id) when 'restore' vcs_organization.restore(org_id: @object_id) diff --git a/spec/lib/services/assembla_notify_service_spec.rb b/spec/lib/services/assembla_notify_service_spec.rb index 3fd032bb0..209f42960 100644 --- a/spec/lib/services/assembla_notify_service_spec.rb +++ b/spec/lib/services/assembla_notify_service_spec.rb @@ -2,7 +2,7 @@ require 'travis/services/assembla_notify_service' RSpec.describe Travis::Services::AssemblaNotifyService do - let(:payload) { { action: 'destroy', object: 'tool', id: '12345' } } + let(:payload) { { action: 'restrict', object: 'tool', id: '12345' } } let(:service) { described_class.new(payload) } let(:vcs_repository) { instance_double(Travis::RemoteVCS::Repository) } let(:vcs_organization) { instance_double(Travis::RemoteVCS::Organization) } @@ -18,9 +18,9 @@ end describe '#run' do - context 'with a valid payload for tool destruction' do + context 'with a valid payload for tool restriction' do it 'calls destroy on the vcs_repository' do - expect(vcs_repository).to receive(:destroy).with(repository_id: '12345') + expect(vcs_repository).to receive(:destroy).with(repository_id: '12345', vcs_type: 'AssemblaRepository') service.run end end @@ -33,8 +33,8 @@ end end - context 'with a valid payload for space destruction' do - let(:payload) { { action: 'destroy', object: 'space', id: '67890' } } + context 'with a valid payload for space restriction' do + let(:payload) { { action: 'restrict', object: 'space', id: '67890' } } it 'calls destroy on the vcs_organization' do expect(vcs_organization).to receive(:destroy).with(org_id: '67890') @@ -52,7 +52,7 @@ end context 'with an invalid object type' do - let(:payload) { { action: 'destroy', object: 'repository', id: '12345' } } + let(:payload) { { action: 'restrict', object: 'repository', id: '12345' } } it 'returns false and logs an error' do expect(service.run).to be_falsey @@ -65,7 +65,7 @@ it 'returns false and logs an error' do expect(service.run).to be_falsey - expect(Travis.logger).to have_received(:error).with("Invalid action: modify. Allowed actions: destroy, restore") + expect(Travis.logger).to have_received(:error).with("Invalid action: modify. Allowed actions: restrict, restore") end end @@ -73,7 +73,7 @@ before do stub_const("Travis::Services::AssemblaNotifyService::VALID_OBJECTS", %w[space tool unsupported]) end - let(:payload) { { action: 'destroy', object: 'unsupported', id: '12345' } } + let(:payload) { { action: 'restrict', object: 'unsupported', id: '12345' } } it 'returns false without logging an error for the action' do expect(service.run).to be_falsey From 9fc1a15a785212e3cef0d64c9b72e616665158eb Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Tue, 4 Nov 2025 15:41:36 +0500 Subject: [PATCH 4/7] revert admin ID --- lib/travis/remote_vcs/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/remote_vcs/repository.rb b/lib/travis/remote_vcs/repository.rb index 08abd32c7..3d9d41a60 100644 --- a/lib/travis/remote_vcs/repository.rb +++ b/lib/travis/remote_vcs/repository.rb @@ -45,7 +45,7 @@ def delete_key(repository_id:, user_id:, id:) def show(repository_id:, admin_id: nil) request(:get, __method__, false) do |req| req.url "repos/#{repository_id}" - + req.params['admin_id'] = admin_id end rescue ResponseError nil From 84a099c7b5f289c580eb2c4667dd046b0860f35b Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Tue, 4 Nov 2025 16:00:33 +0500 Subject: [PATCH 5/7] fixed specs --- spec/travis/remote_vcs/repository_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/travis/remote_vcs/repository_spec.rb b/spec/travis/remote_vcs/repository_spec.rb index 72a570b91..04d1ec481 100644 --- a/spec/travis/remote_vcs/repository_spec.rb +++ b/spec/travis/remote_vcs/repository_spec.rb @@ -81,7 +81,7 @@ end describe '#destroy' do - subject { repository.destroy(repository_id: id) } + subject { repository.destroy(repository_id: id, vcs_type: 'AssemblaRepository') } context 'when the request is successful' do let!(:request) do From 39cf64a64faf79b51c8d7ec55a11247304d41976 Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Tue, 4 Nov 2025 16:06:22 +0500 Subject: [PATCH 6/7] use hash string --- lib/travis/services/assembla_notify_service.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/travis/services/assembla_notify_service.rb b/lib/travis/services/assembla_notify_service.rb index 276c9bca3..58029069c 100644 --- a/lib/travis/services/assembla_notify_service.rb +++ b/lib/travis/services/assembla_notify_service.rb @@ -10,9 +10,9 @@ class AssemblaNotifyService VALID_OBJECTS = %w[space tool].freeze def initialize(payload) - @action = payload[:action] - @object = payload[:object] - @object_id = payload[:id] + @action = payload['action'] + @object = payload['object'] + @object_id = payload['id'] end def run From 39abcdf780ed25e949c3e10fac7916e1ac730228 Mon Sep 17 00:00:00 2001 From: mshahzaib-travis Date: Thu, 6 Nov 2025 16:03:15 +0500 Subject: [PATCH 7/7] fixed specs --- .../lib/services/assembla_notify_service_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/lib/services/assembla_notify_service_spec.rb b/spec/lib/services/assembla_notify_service_spec.rb index 209f42960..2b730d691 100644 --- a/spec/lib/services/assembla_notify_service_spec.rb +++ b/spec/lib/services/assembla_notify_service_spec.rb @@ -2,14 +2,14 @@ require 'travis/services/assembla_notify_service' RSpec.describe Travis::Services::AssemblaNotifyService do - let(:payload) { { action: 'restrict', object: 'tool', id: '12345' } } + let(:payload) { { 'action' => 'restrict', 'object' => 'tool', 'id' => '12345' } } let(:service) { described_class.new(payload) } let(:vcs_repository) { instance_double(Travis::RemoteVCS::Repository) } let(:vcs_organization) { instance_double(Travis::RemoteVCS::Organization) } before do allow(Travis::RemoteVCS::Repository).to receive(:new).and_return(vcs_repository) - allow(vcs_repository).to receive(:destroy) + allow(vcs_repository).to receive(:destroy).with(any_args) allow(vcs_repository).to receive(:restore) allow(Travis::RemoteVCS::Organization).to receive(:new).and_return(vcs_organization) allow(vcs_organization).to receive(:destroy) @@ -26,7 +26,7 @@ end context 'with a valid payload for tool restoration' do - let(:payload) { { action: 'restore', object: 'tool', id: '12345' } } + let(:payload) { { 'action' => 'restore', 'object' => 'tool', 'id' => '12345' } } it 'calls restore on the vcs_repository' do expect(vcs_repository).to receive(:restore).with(repository_id: '12345') service.run @@ -34,7 +34,7 @@ end context 'with a valid payload for space restriction' do - let(:payload) { { action: 'restrict', object: 'space', id: '67890' } } + let(:payload) { { 'action' => 'restrict', 'object' => 'space', 'id' => '67890' } } it 'calls destroy on the vcs_organization' do expect(vcs_organization).to receive(:destroy).with(org_id: '67890') @@ -43,7 +43,7 @@ end context 'with a valid payload for space restoration' do - let(:payload) { { action: 'restore', object: 'space', id: '67890' } } + let(:payload) { { 'action' => 'restore', 'object' => 'space', 'id' => '67890' } } it 'calls restore on the vcs_organization' do expect(vcs_organization).to receive(:restore).with(org_id: '67890') @@ -52,7 +52,7 @@ end context 'with an invalid object type' do - let(:payload) { { action: 'restrict', object: 'repository', id: '12345' } } + let(:payload) { { 'action' => 'restrict', 'object' => 'repository', 'id' => '12345' } } it 'returns false and logs an error' do expect(service.run).to be_falsey @@ -61,7 +61,7 @@ end context 'with an invalid action type' do - let(:payload) { { action: 'modify', object: 'tool', id: '12345' } } + let(:payload) { { 'action' => 'modify', 'object' => 'tool', 'id' => '12345' } } it 'returns false and logs an error' do expect(service.run).to be_falsey @@ -73,7 +73,7 @@ before do stub_const("Travis::Services::AssemblaNotifyService::VALID_OBJECTS", %w[space tool unsupported]) end - let(:payload) { { action: 'restrict', object: 'unsupported', id: '12345' } } + let(:payload) { { 'action' => 'restrict', 'object' => 'unsupported', 'id' => '12345' } } it 'returns false without logging an error for the action' do expect(service.run).to be_falsey