Merge branch 'fix/gb/fix-chatops-deploy-multiple-actions-matching' into 'master'
Improve deploy environment chatops slash command Closes #34748 See merge request !13150
This commit is contained in:
commit
0b0d04b4db
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Improve deploy environment chatops slash command
|
||||
merge_request: 13150
|
||||
author:
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
|
||||
|
||||
Commands are scoped to a project, with a trigger term that is specified during configuration. (We suggest you use the project name as the trigger term for simplicty and clarity.) Taking the trigger term as `project-name`, the commands are:
|
||||
Commands are scoped to a project, with a trigger term that is specified during configuration.
|
||||
|
||||
We suggest you use the project name as the trigger term for simplicity and clarity.
|
||||
|
||||
Taking the trigger term as `project-name`, the commands are:
|
||||
|
||||
|
||||
| Command | Effect |
|
||||
|
@ -12,3 +16,18 @@ Commands are scoped to a project, with a trigger term that is specified during c
|
|||
| `/project-name issue show <id>` | Shows the issue with id `<id>` |
|
||||
| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
|
||||
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
|
||||
|
||||
## Issue commands
|
||||
|
||||
It is possible to create new issue, display issue details and search up to 5 issues.
|
||||
|
||||
## Deploy command
|
||||
|
||||
In order to deploy to an environment, GitLab will try to find a deployment
|
||||
manual action in the pipeline.
|
||||
|
||||
If there is only one action for a given environment, it is going to be triggered.
|
||||
If there is more than one action defined, GitLab will try to find an action
|
||||
which name equals the environment name we want to deploy to.
|
||||
|
||||
Command will return an error when no matching action has been found.
|
||||
|
|
|
@ -21,29 +21,34 @@ module Gitlab
|
|||
from = match[:from]
|
||||
to = match[:to]
|
||||
|
||||
actions = find_actions(from, to)
|
||||
action = find_action(from, to)
|
||||
|
||||
if actions.none?
|
||||
Gitlab::SlashCommands::Presenters::Deploy.new(nil).no_actions
|
||||
elsif actions.one?
|
||||
action = play!(from, to, actions.first)
|
||||
Gitlab::SlashCommands::Presenters::Deploy.new(action).present(from, to)
|
||||
if action.nil?
|
||||
Gitlab::SlashCommands::Presenters::Deploy
|
||||
.new(action).action_not_found
|
||||
else
|
||||
Gitlab::SlashCommands::Presenters::Deploy.new(actions).too_many_actions
|
||||
deployment = action.play(current_user)
|
||||
|
||||
Gitlab::SlashCommands::Presenters::Deploy
|
||||
.new(deployment).present(from, to)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def play!(from, to, action)
|
||||
action.play(current_user)
|
||||
end
|
||||
|
||||
def find_actions(from, to)
|
||||
def find_action(from, to)
|
||||
environment = project.environments.find_by(name: from)
|
||||
return [] unless environment
|
||||
return unless environment
|
||||
|
||||
environment.actions_for(to).select(&:starts_environment?)
|
||||
actions = environment.actions_for(to).select do |action|
|
||||
action.starts_environment?
|
||||
end
|
||||
|
||||
if actions.many?
|
||||
actions.find { |action| action.name == to.to_s }
|
||||
else
|
||||
actions.first
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,17 +3,14 @@ module Gitlab
|
|||
module Presenters
|
||||
class Deploy < Presenters::Base
|
||||
def present(from, to)
|
||||
message = "Deployment started from #{from} to #{to}. [Follow its progress](#{resource_url})."
|
||||
message = "Deployment started from #{from} to #{to}. " \
|
||||
"[Follow its progress](#{resource_url})."
|
||||
|
||||
in_channel_response(text: message)
|
||||
end
|
||||
|
||||
def no_actions
|
||||
ephemeral_response(text: "No action found to be executed")
|
||||
end
|
||||
|
||||
def too_many_actions
|
||||
ephemeral_response(text: "Too many actions defined")
|
||||
def action_not_found
|
||||
ephemeral_response(text: "Couldn't find a deployment manual action.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,7 +80,7 @@ describe Gitlab::SlashCommands::Command do
|
|||
|
||||
it 'returns error' do
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to include('Too many actions defined')
|
||||
expect(subject[:text]).to include("Couldn't find a deployment manual action.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ describe Gitlab::SlashCommands::Deploy do
|
|||
context 'if no environment is defined' do
|
||||
it 'does not execute an action' do
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to eq("No action found to be executed")
|
||||
expect(subject[:text]).to eq "Couldn't find a deployment manual action."
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,12 +35,12 @@ describe Gitlab::SlashCommands::Deploy do
|
|||
context 'without actions' do
|
||||
it 'does not execute an action' do
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to eq("No action found to be executed")
|
||||
expect(subject[:text]).to eq "Couldn't find a deployment manual action."
|
||||
end
|
||||
end
|
||||
|
||||
context 'with action' do
|
||||
let!(:manual1) do
|
||||
context 'when single action has been matched' do
|
||||
before do
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'first',
|
||||
environment: 'production')
|
||||
|
@ -48,31 +48,61 @@ describe Gitlab::SlashCommands::Deploy do
|
|||
|
||||
it 'returns success result' do
|
||||
expect(subject[:response_type]).to be(:in_channel)
|
||||
expect(subject[:text]).to start_with('Deployment started from staging to production')
|
||||
expect(subject[:text])
|
||||
.to start_with('Deployment started from staging to production')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when more than one action has been matched' do
|
||||
context 'when there is no specific actions with a environment name' do
|
||||
before do
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'first',
|
||||
environment: 'production')
|
||||
|
||||
context 'when duplicate action exists' do
|
||||
let!(:manual2) do
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'second',
|
||||
environment: 'production')
|
||||
end
|
||||
|
||||
it 'returns error' do
|
||||
it 'returns error about too many actions defined' do
|
||||
expect(subject[:text]).to eq("Couldn't find a deployment manual action.")
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to eq('Too many actions defined')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when teardown action exists' do
|
||||
let!(:teardown) do
|
||||
context 'when one of the actions is environement specific action' do
|
||||
before do
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'first',
|
||||
environment: 'production')
|
||||
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'production',
|
||||
environment: 'production')
|
||||
end
|
||||
|
||||
it 'deploys to production' do
|
||||
expect(subject[:text])
|
||||
.to start_with('Deployment started from staging to production')
|
||||
expect(subject[:response_type]).to be(:in_channel)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when one of the actions is a teardown action' do
|
||||
before do
|
||||
create(:ci_build, :manual, pipeline: pipeline,
|
||||
name: 'first',
|
||||
environment: 'production')
|
||||
|
||||
create(:ci_build, :manual, :teardown_environment,
|
||||
pipeline: pipeline, name: 'teardown', environment: 'production')
|
||||
end
|
||||
|
||||
it 'returns the success message' do
|
||||
it 'deploys to production' do
|
||||
expect(subject[:text])
|
||||
.to start_with('Deployment started from staging to production')
|
||||
expect(subject[:response_type]).to be(:in_channel)
|
||||
expect(subject[:text]).to start_with('Deployment started from staging to production')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,8 +17,8 @@ describe Gitlab::SlashCommands::Presenters::Deploy do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#no_actions' do
|
||||
subject { described_class.new(nil).no_actions }
|
||||
describe '#action_not_found' do
|
||||
subject { described_class.new(nil).action_not_found }
|
||||
|
||||
it { is_expected.to have_key(:text) }
|
||||
it { is_expected.to have_key(:response_type) }
|
||||
|
@ -27,21 +27,7 @@ describe Gitlab::SlashCommands::Presenters::Deploy do
|
|||
|
||||
it 'tells the user there is no action' do
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to eq("No action found to be executed")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#too_many_actions' do
|
||||
subject { described_class.new([]).too_many_actions }
|
||||
|
||||
it { is_expected.to have_key(:text) }
|
||||
it { is_expected.to have_key(:response_type) }
|
||||
it { is_expected.to have_key(:status) }
|
||||
it { is_expected.not_to have_key(:attachments) }
|
||||
|
||||
it 'tells the user there is no action' do
|
||||
expect(subject[:response_type]).to be(:ephemeral)
|
||||
expect(subject[:text]).to eq("Too many actions defined")
|
||||
expect(subject[:text]).to eq "Couldn't find a deployment manual action."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue