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.

Unverified Commit f027f64e authored by John T Skarbek's avatar John T Skarbek
Browse files

Merge remote-tracking branch 'origin/master' into 11-9-stable

parents 098215f3 a592a780
...@@ -173,7 +173,9 @@ export class CopyAsGFM { ...@@ -173,7 +173,9 @@ export class CopyAsGFM {
wrapEl.appendChild(node.cloneNode(true)); wrapEl.appendChild(node.cloneNode(true));
const doc = DOMParser.fromSchema(schema.default).parse(wrapEl); const doc = DOMParser.fromSchema(schema.default).parse(wrapEl);
const res = markdownSerializer.default.serialize(doc); const res = markdownSerializer.default.serialize(doc, {
tightLists: true,
});
return res; return res;
}) })
.catch(() => {}); .catch(() => {});
......
<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 { ...@@ -556,6 +556,7 @@ export default {
<rollback-component <rollback-component
v-if="canRetry" v-if="canRetry"
:environment="model"
:is-last-deployment="isLastDeployment" :is-last-deployment="isLastDeployment"
:retry-url="retryUrl" :retry-url="retryUrl"
/> />
......
...@@ -5,29 +5,38 @@ ...@@ -5,29 +5,38 @@
* *
* Makes a post request when the button is clicked. * Makes a post request when the button is clicked.
*/ */
import { GlTooltipDirective, GlLoadingIcon, GlModalDirective, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
export default { export default {
components: { components: {
Icon, Icon,
GlLoadingIcon, GlLoadingIcon,
GlButton,
ConfirmRollbackModal,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
}, },
props: { props: {
retryUrl: {
type: String,
default: '',
},
isLastDeployment: { isLastDeployment: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
environment: {
type: Object,
required: true,
},
retryUrl: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
...@@ -45,23 +54,31 @@ export default { ...@@ -45,23 +54,31 @@ export default {
methods: { methods: {
onClick() { onClick() {
this.isLoading = true; eventHub.$emit('requestRollbackEnvironment', {
...this.environment,
eventHub.$emit('postAction', { endpoint: this.retryUrl }); retryUrl: this.retryUrl,
isLastDeployment: this.isLastDeployment,
});
eventHub.$on('rollbackEnvironment', environment => {
if (environment.id === this.environment.id) {
this.isLoading = true;
}
});
}, },
}, },
}; };
</script> </script>
<template> <template>
<button <gl-button
v-gl-tooltip v-gl-tooltip
v-gl-modal.confirm-rollback-modal
variant="secondary"
:disabled="isLoading" :disabled="isLoading"
:title="title" :title="title"
type="button" class="d-none d-md-block"
class="btn d-none d-sm-none d-md-block"
@click="onClick" @click="onClick"
> >
<icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" /> <icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" />
<gl-loading-icon v-if="isLoading" /> <gl-loading-icon v-if="isLoading" />
</button> </gl-button>
</template> </template>
...@@ -6,11 +6,13 @@ import eventHub from '../event_hub'; ...@@ -6,11 +6,13 @@ import eventHub from '../event_hub';
import environmentsMixin from '../mixins/environments_mixin'; import environmentsMixin from '../mixins/environments_mixin';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
import StopEnvironmentModal from './stop_environment_modal.vue'; import StopEnvironmentModal from './stop_environment_modal.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
export default { export default {
components: { components: {
emptyState, emptyState,
StopEnvironmentModal, StopEnvironmentModal,
ConfirmRollbackModal,
}, },
mixins: [CIPaginationMixin, environmentsMixin], mixins: [CIPaginationMixin, environmentsMixin],
...@@ -87,6 +89,7 @@ export default { ...@@ -87,6 +89,7 @@ export default {
<template> <template>
<div :class="cssContainerClass"> <div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" /> <stop-environment-modal :environment="environmentInStopModal" />
<confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="top-area"> <div class="top-area">
<tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" /> <tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" />
......
...@@ -36,6 +36,7 @@ export default { ...@@ -36,6 +36,7 @@ export default {
page: getParameterByName('page') || '1', page: getParameterByName('page') || '1',
requestData: {}, requestData: {},
environmentInStopModal: {}, environmentInStopModal: {},
environmentInRollbackModal: {},
}; };
}, },
...@@ -116,6 +117,10 @@ export default { ...@@ -116,6 +117,10 @@ export default {
this.environmentInStopModal = environment; this.environmentInStopModal = environment;
}, },
updateRollbackModal(environment) {
this.environmentInRollbackModal = environment;
},
stopEnvironment(environment) { stopEnvironment(environment) {
const endpoint = environment.stop_path; const endpoint = environment.stop_path;
const errorMessage = s__( const errorMessage = s__(
...@@ -123,6 +128,16 @@ export default { ...@@ -123,6 +128,16 @@ export default {
); );
this.postAction({ endpoint, errorMessage }); 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: { computed: {
...@@ -181,11 +196,17 @@ export default { ...@@ -181,11 +196,17 @@ export default {
eventHub.$on('postAction', this.postAction); eventHub.$on('postAction', this.postAction);
eventHub.$on('requestStopEnvironment', this.updateStopModal); eventHub.$on('requestStopEnvironment', this.updateStopModal);
eventHub.$on('stopEnvironment', this.stopEnvironment); eventHub.$on('stopEnvironment', this.stopEnvironment);
eventHub.$on('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$on('rollbackEnvironment', this.rollbackEnvironment);
}, },
beforeDestroy() { beforeDestroy() {
eventHub.$off('postAction', this.postAction); eventHub.$off('postAction', this.postAction);
eventHub.$off('requestStopEnvironment', this.updateStopModal); eventHub.$off('requestStopEnvironment', this.updateStopModal);
eventHub.$off('stopEnvironment', this.stopEnvironment); eventHub.$off('stopEnvironment', this.stopEnvironment);
eventHub.$off('requestRollbackEnvironment', this.updateRollbackModal);
eventHub.$off('rollbackEnvironment', this.rollbackEnvironment);
}, },
}; };
...@@ -48,7 +48,7 @@ export default { ...@@ -48,7 +48,7 @@ export default {
} }
}, },
methods: { methods: {
...mapActions(['startPolling']), ...mapActions(['startPolling', 'restartPolling']),
}, },
}; };
</script> </script>
...@@ -56,19 +56,17 @@ export default { ...@@ -56,19 +56,17 @@ export default {
<template> <template>
<div> <div>
<div v-if="errorTrackingEnabled"> <div v-if="errorTrackingEnabled">
<div v-if="loading" class="py-3"><gl-loading-icon :size="3" /></div> <div v-if="loading" class="py-3">
<gl-loading-icon :size="3" />
</div>
<div v-else> <div v-else>
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
<gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank" <gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank">
>View in Sentry <icon name="external-link" /> {{ __('View in Sentry') }}
<icon name="external-link" />
</gl-button> </gl-button>
</div> </div>
<gl-table <gl-table :items="errors" :fields="$options.fields" :show-empty="true">
:items="errors"
:fields="$options.fields"
:show-empty="true"
:empty-text="__('No errors to display')"
>
<template slot="HEAD_events" slot-scope="data"> <template slot="HEAD_events" slot-scope="data">
<div class="text-right">{{ data.label }}</div> <div class="text-right">{{ data.label }}</div>
</template> </template>
...@@ -102,6 +100,14 @@ export default { ...@@ -102,6 +100,14 @@ export default {
<time-ago :time="errors.item.lastSeen" class="text-secondary" /> <time-ago :time="errors.item.lastSeen" class="text-secondary" />
</div> </div>
</template> </template>
<template slot="empty">
<div ref="empty">
{{ __('No errors to display.') }}
<gl-link class="js-try-again" @click="restartPolling">
{{ __('Check again') }}
</gl-link>
</div>
</template>
</gl-table> </gl-table>
</div> </div>
</div> </div>
......
...@@ -6,7 +6,7 @@ import { __, sprintf } from '~/locale'; ...@@ -6,7 +6,7 @@ import { __, sprintf } from '~/locale';
let eTagPoll; let eTagPoll;
export function startPolling({ commit }, endpoint) { export function startPolling({ commit, dispatch }, endpoint) {
eTagPoll = new Poll({ eTagPoll = new Poll({
resource: Service, resource: Service,
method: 'getErrorList', method: 'getErrorList',
...@@ -18,6 +18,7 @@ export function startPolling({ commit }, endpoint) { ...@@ -18,6 +18,7 @@ export function startPolling({ commit }, endpoint) {
commit(types.SET_ERRORS, data.errors); commit(types.SET_ERRORS, data.errors);
commit(types.SET_EXTERNAL_URL, data.external_url); commit(types.SET_EXTERNAL_URL, data.external_url);
commit(types.SET_LOADING, false); commit(types.SET_LOADING, false);
dispatch('stopPolling');
}, },
errorCallback: response => { errorCallback: response => {
let errorMessage = ''; let errorMessage = '';
...@@ -36,4 +37,16 @@ export function startPolling({ commit }, endpoint) { ...@@ -36,4 +37,16 @@ export function startPolling({ commit }, endpoint) {
eTagPoll.makeRequest(); eTagPoll.makeRequest();
} }
export const stopPolling = () => {
if (eTagPoll) eTagPoll.stop();
};
export function restartPolling({ commit }) {
commit(types.SET_ERRORS, []);
commit(types.SET_EXTERNAL_URL, '');
commit(types.SET_LOADING, true);
if (eTagPoll) eTagPoll.restart();
}
export default () => {}; export default () => {};
...@@ -404,6 +404,7 @@ img.emoji { ...@@ -404,6 +404,7 @@ img.emoji {
.flex-grow { flex-grow: 1; } .flex-grow { flex-grow: 1; }
.flex-no-shrink { flex-shrink: 0; } .flex-no-shrink { flex-shrink: 0; }
.ws-initial { white-space: initial; } .ws-initial { white-space: initial; }
.ws-normal { white-space: normal; }
.overflow-auto { overflow: auto; } .overflow-auto { overflow: auto; }
.d-flex-center { .d-flex-center {
......
# frozen_string_literal: true
module Resolvers
class MetadataResolver < BaseResolver
type Types::MetadataType, null: false
def resolve(**args)
{ version: Gitlab::VERSION, revision: Gitlab.revision }
end
end
end
# frozen_string_literal: true
module Types
class MetadataType < ::Types::BaseObject
graphql_name 'Metadata'
field :version, GraphQL::STRING_TYPE, null: false
field :revision, GraphQL::STRING_TYPE, null: false
end
end
# frozen_string_literal: true # frozen_string_literal: true
module Types module Types
class QueryType < BaseObject class QueryType < ::Types::BaseObject
graphql_name 'Query' graphql_name 'Query'
field :project, Types::ProjectType, field :project, Types::ProjectType,
...@@ -10,6 +10,14 @@ class QueryType < BaseObject ...@@ -10,6 +10,14 @@ class QueryType < BaseObject
description: "Find a project", description: "Find a project",
authorize: :read_project authorize: :read_project
field :metadata, Types::MetadataType,
null: true,
resolver: Resolvers::MetadataResolver,
description: 'Metadata about GitLab' do |*args|
authorize :read_instance_metadata
end
field :echo, GraphQL::STRING_TYPE, null: false, function: Functions::Echo.new field :echo, GraphQL::STRING_TYPE, null: false, function: Functions::Echo.new
end end
end end
...@@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy ...@@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy
enable :read_users_list enable :read_users_list
end end
rule { ~anonymous }.policy do
enable :read_instance_metadata
end
rule { admin }.policy do rule { admin }.policy do
enable :read_custom_attribute enable :read_custom_attribute
enable :update_custom_attribute enable :update_custom_attribute
......
- 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