GitLab wurde aktualisiert. Dank regelmäßiger Updates bleibt das THM GitLab sicher und Sie profitieren von den neuesten Funktionen. Vielen Dank für Ihre Geduld.

Commit ba98e91c authored by Andrew Fontaine's avatar Andrew Fontaine Committed by Filipa Lacerda
Browse files

Add Component to Confirm Environment Rollback

Ensure a vue.js component to confirm the re-deployment/rollback of an
environment pops up when rollback/re-deploy has been clicked so the user
must confirm their actions before accidentally rolling back or
re-deploying an environment.

Only on the `environment-table` view.
parent 5fd1dc15
<script>
/**
* Render modal to confirm rollback/redeploy.
*/
import _ from 'underscore';
import { GlModal } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
name: 'ConfirmRollbackModal',
components: {
GlModal,
},
props: {
environment: {
type: Object,
required: true,
},
},
computed: {
modalTitle() {
const title = this.environment.isLastDeployment
? s__('Environments|Re-deploy environment %{name}?')
: s__('Environments|Rollback environment %{name}?');
return sprintf(title, {
name: _.escape(this.environment.name),
});
},
commitShortSha() {
const { last_deployment } = this.environment;
return this.commitData(last_deployment, 'short_id');
},
commitUrl() {
const { last_deployment } = this.environment;
return this.commitData(last_deployment, 'commit_path');
},
commitTitle() {
const { last_deployment } = this.environment;
return this.commitData(last_deployment, 'title');
},
modalText() {
const linkStart = `<a class="commit-sha" href="${_.escape(this.commitUrl)}">`;
const commitId = _.escape(this.commitShortSha);
const linkEnd = '</a>';
const name = _.escape(this.name);
const body = this.environment.isLastDeployment
? s__(
'Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?',
)
: s__(
'Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?',
);
return sprintf(
body,
{
commitId,
linkStart,
linkEnd,
name,
},
false,
);
},
modalActionText() {
return this.environment.isLastDeployment
? s__('Environments|Re-deploy')
: s__('Environments|Rollback');
},
},
methods: {
onOk() {
eventHub.$emit('rollbackEnvironment', this.environment);
},
commitData(lastDeployment, key) {
if (lastDeployment && lastDeployment.commit) {
return lastDeployment.commit[key];
}
return '';
},
},
};
</script>
<template>
<gl-modal
:title="modalTitle"
modal-id="confirm-rollback-modal"
:ok-title="modalActionText"
ok-variant="danger"
@ok="onOk"
>
<p v-html="modalText"></p>
</gl-modal>
</template>
......@@ -556,6 +556,7 @@ export default {
<rollback-component
v-if="canRetry"
:environment="model"
:is-last-deployment="isLastDeployment"
:retry-url="retryUrl"
/>
......
......@@ -5,29 +5,38 @@
*
* Makes a post request when the button is clicked.
*/
import { GlTooltipDirective, GlLoadingIcon, GlModalDirective, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale';
import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import eventHub from '../event_hub';
export default {
components: {
Icon,
GlLoadingIcon,
GlButton,
ConfirmRollbackModal,
},
directives: {
GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
},
props: {
retryUrl: {
type: String,
default: '',
},
isLastDeployment: {
type: Boolean,
default: true,
},
environment: {
type: Object,
required: true,
},
retryUrl: {
type: String,
required: true,
},
},
data() {
return {
......@@ -45,23 +54,31 @@ export default {
methods: {
onClick() {
this.isLoading = true;
eventHub.$emit('postAction', { endpoint: this.retryUrl });
eventHub.$emit('requestRollbackEnvironment', {
...this.environment,
retryUrl: this.retryUrl,
isLastDeployment: this.isLastDeployment,
});
eventHub.$on('rollbackEnvironment', environment => {
if (environment.id === this.environment.id) {
this.isLoading = true;
}
});
},
},
};
</script>
<template>
<button
<gl-button
v-gl-tooltip
v-gl-modal.confirm-rollback-modal
variant="secondary"
:disabled="isLoading"
:title="title"
type="button"
class="btn d-none d-sm-none d-md-block"
class="d-none d-md-block"
@click="onClick"
>
<icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" />
<gl-loading-icon v-if="isLoading" />
</button>
</gl-button>
</template>
......@@ -6,11 +6,13 @@ import eventHub from '../event_hub';
import environmentsMixin from '../mixins/environments_mixin';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
import StopEnvironmentModal from './stop_environment_modal.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
export default {
components: {
emptyState,
StopEnvironmentModal,
ConfirmRollbackModal,
},
mixins: [CIPaginationMixin, environmentsMixin],
......@@ -87,6 +89,7 @@ export default {
<template>
<div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" />
<confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="top-area">
<tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" />
......
......@@ -36,6 +36,7 @@ export default {
page: getParameterByName('page') || '1',
requestData: {},
environmentInStopModal: {},
environmentInRollbackModal: {},
};
},
......@@ -116,6 +117,10 @@ export default {
this.environmentInStopModal = environment;
},
updateRollbackModal(environment) {
this.environmentInRollbackModal = environment;
},
stopEnvironment(environment) {
const endpoint = environment.stop_path;
const errorMessage = s__(
......@@ -123,6 +128,16 @@ export default {
);
this.postAction({ endpoint, errorMessage });
},
rollbackEnvironment(environment) {
const { retryUrl, isLastDeployment } = environment;
const errorMessage = isLastDeployment
? s__('Environments|An error occurred while re-deploying the environment, please try again')
: s__(
'Environments|An error occurred while rolling back the environment, please try again',
);
this.postAction({ endpoint: retryUrl, errorMessage });
},
},
computed: {
......@@ -181,11 +196,17 @@ export default {
eventHub.$on('postAction', this.postAction);
eventHub.$on('requestStopEnvironment', this.updateStopModal);
eventHub.$on('stopEnvironment', this.stopEnvironment);
eventHub.$on('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$on('rollbackEnvironment', this.rollbackEnvironment);
},
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
eventHub.$off('requestStopEnvironment', this.updateStopModal);
eventHub.$off('stopEnvironment', this.stopEnvironment);
eventHub.$off('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$off('rollbackEnvironment', this.rollbackEnvironment);
},
};
......@@ -404,6 +404,7 @@ img.emoji {
.flex-grow { flex-grow: 1; }
.flex-no-shrink { flex-shrink: 0; }
.ws-initial { white-space: initial; }
.ws-normal { white-space: normal; }
.overflow-auto { overflow: auto; }
.d-flex-center {
......
- commit_sha = link_to deployment.short_sha, project_commit_path(@project, deployment.sha), class: "commit-sha has-tooltip", title: h(deployment.commit_title)
.modal.ws-normal.fade{ tabindex: -1, id: "confirm-rollback-modal-#{deployment.id}" }
.modal-dialog
.modal-content
.modal-header
%h4.modal-title.d-flex.mw-100
- if deployment.last?
= s_("Environments|Re-deploy environment %{environment_name}?") % {environment_name: @environment.name}
- else
= s_("Environments|Rollback environment %{environment_name}?") % {environment_name: @environment.name}
.modal-body
- if deployment.last?
%p= s_('Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?').html_safe % {commit_id: commit_sha}
- else
%p
= s_('Environments|This action will run the job defined by staging for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?').html_safe % {commit_id: commit_sha}
.modal-footer
= button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' }
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-danger' do
- if deployment.last?
= s_('Environments|Re-deploy')
- else
= s_('Environments|Rollback')
- if can?(current_user, :create_deployment, deployment)
- tooltip = deployment.last? ? s_('Environments|Re-deploy to environment') : s_('Environments|Rollback environment')
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build has-tooltip', title: tooltip do
= button_tag class: 'btn btn-default btn-build has-tooltip', type: 'button', data: { toggle: 'modal', target: "#confirm-rollback-modal-#{deployment.id}" }, title: tooltip do
- if deployment.last?
= sprite_icon('repeat')
- else
= sprite_icon('redo')
= render 'projects/deployments/confirm_rollback_modal', deployment: deployment
---
title: Add Confirmation Modal to Rollback on Environment
merge_request: 25110
author:
type: added
......@@ -3055,6 +3055,12 @@ msgstr ""
msgid "Environments|An error occurred while making the request."
msgstr ""
msgid "Environments|An error occurred while re-deploying the environment, please try again"
msgstr ""
msgid "Environments|An error occurred while rolling back the environment, please try again"
msgstr ""
msgid "Environments|An error occurred while stopping the environment, please try again"
msgstr ""
......@@ -3100,15 +3106,33 @@ msgstr ""
msgid "Environments|Open live environment"
msgstr ""
msgid "Environments|Re-deploy"
msgstr ""
msgid "Environments|Re-deploy environment %{environment_name}?"
msgstr ""
msgid "Environments|Re-deploy environment %{name}?"
msgstr ""
msgid "Environments|Re-deploy to environment"
msgstr ""
msgid "Environments|Read more about environments"
msgstr ""
msgid "Environments|Rollback"
msgstr ""
msgid "Environments|Rollback environment"
msgstr ""
msgid "Environments|Rollback environment %{environment_name}?"
msgstr ""
msgid "Environments|Rollback environment %{name}?"
msgstr ""
msgid "Environments|Show all"
msgstr ""
......@@ -3121,6 +3145,18 @@ msgstr ""
msgid "Environments|Stopping"
msgstr ""
msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
msgstr ""
msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
msgstr ""
msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
msgstr ""
msgid "Environments|This action will run the job defined by staging for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
msgstr ""
msgid "Environments|Updated"
msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
import ConfirmRollbackModal from '~/environments/components/confirm_rollback_modal.vue';
import eventHub from '~/environments/event_hub';
describe('Confirm Rollback Modal Component', () => {
let environment;
beforeEach(() => {
environment = {
name: 'test',
last_deployment: {
commit: {
short_id: 'abc0123',
},
},
modalId: 'test',
};
});
it('should show "Rollback" when isLastDeployment is false', () => {
const component = shallowMount(ConfirmRollbackModal, {
propsData: {
environment: {
...environment,
isLastDeployment: false,
},
},
});
const modal = component.find(GlModal);
expect(modal.attributes('title')).toContain('Rollback');
expect(modal.attributes('title')).toContain('test');
expect(modal.attributes('ok-title')).toBe('Rollback');
expect(modal.text()).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
});
it('should show "Re-deploy" when isLastDeployment is true', () => {
const component = shallowMount(ConfirmRollbackModal, {
propsData: {
environment: {
...environment,
isLastDeployment: true,
},
},
});
const modal = component.find(GlModal);
expect(modal.attributes('title')).toContain('Re-deploy');
expect(modal.attributes('title')).toContain('test');
expect(modal.attributes('ok-title')).toBe('Re-deploy');
expect(modal.text()).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
});
it('should emit the "rollback" event when "ok" is clicked', () => {
environment = { ...environment, isLastDeployment: true };
const component = shallowMount(ConfirmRollbackModal, {
propsData: {
environment,
},
});
const eventHubSpy = spyOn(eventHub, '$emit');
const modal = component.find(GlModal);
modal.vm.$emit('ok');
expect(eventHubSpy).toHaveBeenCalledWith('rollbackEnvironment', environment);
});
});
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import eventHub from '~/environments/event_hub';
import rollbackComp from '~/environments/components/environment_rollback.vue';
describe('Rollback Component', () => {
const retryURL = 'https://gitlab.com/retry';
const retryUrl = 'https://gitlab.com/retry';
let RollbackComponent;
beforeEach(() => {
......@@ -13,8 +16,9 @@ describe('Rollback Component', () => {
const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
retryUrl: retryURL,
retryUrl,
isLastDeployment: true,
environment: {},
},
}).$mount();
......@@ -25,11 +29,33 @@ describe('Rollback Component', () => {
const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'),
propsData: {
retryUrl: retryURL,
retryUrl,
isLastDeployment: false,
environment: {},
},
}).$mount();
expect(component.$el).toHaveSpriteIcon('redo');
});
it('should emit a "rollback" event on button click', () => {
const eventHubSpy = spyOn(eventHub, '$emit');
const component = shallowMount(RollbackComponent, {
propsData: {
retryUrl,
environment: {
name: 'test',
},
},
});
const button = component.find(GlButton);
button.vm.$emit('click');
expect(eventHubSpy).toHaveBeenCalledWith('requestRollbackEnvironment', {
retryUrl,
isLastDeployment: true,
name: 'test',
});
});
});
# frozen_string_literal: true
require 'spec_helper'
describe 'projects/deployments/_confirm_rollback_modal' do
let(:environment) { create(:environment, :with_review_app) }
let(:deployments) { environment.deployments }
let(:project) { environment.project }
before do
assign(:environment, environment)
assign(:deployments, deployments)
assign(:project, project)
end
context 'when re-deploying last deployment' do
let(:deployment) { deployments.first }
before do
allow(view).to receive(:deployment).and_return(deployment)
end
it 'shows "re-deploy"' do
render
expect(rendered).to have_selector('h4', text: "Re-deploy environment #{environment.name}?")
expect(rendered).to have_selector('p', text: "This action will relaunch the job for commit #{deployment.short_sha}, putting the environment in a previous version. Are you sure you want to continue?")
expect(rendered).to have_selector('a.btn-danger', text: 'Re-deploy')
end
it 'links to re-deploying the environment' do
expected_link = retry_project_job_path(environment.project, deployment.deployable)
render
expect(rendered).to have_selector("a[href='#{expected_link}']", text: 'Re-deploy')
end
end
context 'when rolling back to previous deployment' do
let(:deployment) { create(:deployment, environment: environment) }
before do
allow(view).to receive(:deployment).and_return(deployment)
end
it 'shows "rollback"' do
render
expect(rendered).to have_selector('h4', text: "Rollback environment #{environment.name}?")
expect(rendered).to have_selector('p', text: "This action will run the job defined by staging for commit #{deployment.short_sha}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?")
expect(rendered).to have_selector('a.btn-danger', text: 'Rollback')
end
it 'links to re-deploying the environment' do
expected_link = retry_project_job_path(environment.project, deployment.deployable)
render
expect(rendered).to have_selector("a[href='#{expected_link}']", text: 'Rollback')
end
end
end
Markdown is supported
0% or .