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

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

parents 098215f3 a592a780
......@@ -173,7 +173,9 @@ export class CopyAsGFM {
wrapEl.appendChild(node.cloneNode(true));
const doc = DOMParser.fromSchema(schema.default).parse(wrapEl);
const res = markdownSerializer.default.serialize(doc);
const res = markdownSerializer.default.serialize(doc, {
tightLists: true,
});
return res;
})
.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 {
<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);
},
};
......@@ -48,7 +48,7 @@ export default {
}
},
methods: {
...mapActions(['startPolling']),
...mapActions(['startPolling', 'restartPolling']),
},
};
</script>
......@@ -56,19 +56,17 @@ export default {
<template>
<div>
<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 class="d-flex justify-content-end">
<gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank"
>View in Sentry <icon name="external-link" />
<gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank">
{{ __('View in Sentry') }}
<icon name="external-link" />
</gl-button>
</div>
<gl-table
:items="errors"
:fields="$options.fields"
:show-empty="true"
:empty-text="__('No errors to display')"
>
<gl-table :items="errors" :fields="$options.fields" :show-empty="true">
<template slot="HEAD_events" slot-scope="data">
<div class="text-right">{{ data.label }}</div>
</template>
......@@ -102,6 +100,14 @@ export default {
<time-ago :time="errors.item.lastSeen" class="text-secondary" />
</div>
</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>
</div>
</div>
......
......@@ -6,7 +6,7 @@ import { __, sprintf } from '~/locale';
let eTagPoll;
export function startPolling({ commit }, endpoint) {
export function startPolling({ commit, dispatch }, endpoint) {
eTagPoll = new Poll({
resource: Service,
method: 'getErrorList',
......@@ -18,6 +18,7 @@ export function startPolling({ commit }, endpoint) {
commit(types.SET_ERRORS, data.errors);
commit(types.SET_EXTERNAL_URL, data.external_url);
commit(types.SET_LOADING, false);
dispatch('stopPolling');
},
errorCallback: response => {
let errorMessage = '';
......@@ -36,4 +37,16 @@ export function startPolling({ commit }, endpoint) {
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 () => {};
......@@ -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 {
......
# 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
module Types
class QueryType < BaseObject
class QueryType < ::Types::BaseObject
graphql_name 'Query'
field :project, Types::ProjectType,
......@@ -10,6 +10,14 @@ module Types
description: "Find a 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
end
end
......@@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy
enable :read_users_list
end
rule { ~anonymous }.policy do
enable :read_instance_metadata
end
rule { admin }.policy do
enable :read_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
- 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
......@@ -41,6 +41,11 @@ if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
// Jest is running in node environment
if (BABEL_ENV === 'jest') {
plugins.push('@babel/plugin-transform-modules-commonjs');
/*
without the following, babel-plugin-istanbul throws an error:
https://gitlab.com/gitlab-org/gitlab-ce/issues/58390
*/
plugins.push('babel-plugin-dynamic-import-node');
}
module.exports = { presets, plugins };
---
title: Add Confirmation Modal to Rollback on Environment
merge_request: 25110
author:
type: added
---
title: Fixed "Copying comment with ordered list includes extraneous newlines"
merge_request: 25695
author:
type: fixed
---
title: Add metadata about the GitLab server to GraphQL
merge_request: 24636
author:
type: added
---
title: Fix error tracking list page
merge_request: 24806
author:
type: fixed
......@@ -51,6 +51,8 @@ Apart from a local hard drive you can also mount a volume that supports the netw
If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab.
NOTE: **Note:** Since file system performance may affect GitLab's overall performance, we do not recommend using EFS for storage. See the [relevant documentation](../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
### CPU
- 1 core supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core
......
# frozen_string_literal: true
module API
module Helpers
# GraphqlHelpers is used by the REST API when it is acting like a client
# against the graphql API. Helper code for the graphql server implementation
# should be in app/graphql/ or lib/gitlab/graphql/
module GraphqlHelpers
def conditionally_graphql!(fallback:, query:, context: {}, transform: nil)
return fallback.call unless Feature.enabled?(:graphql)
result = GitlabSchema.execute(query, context: context)
if transform
transform.call(result)
else
result
end
end
end
end
end
......@@ -2,13 +2,29 @@
module API
class Version < Grape::API
helpers ::API::Helpers::GraphqlHelpers
before { authenticate! }
METADATA_QUERY = <<~EOF
{
metadata {
version
revision
}
}
EOF
desc 'Get the version information of the GitLab instance.' do
detail 'This feature was introduced in GitLab 8.13.'
end
get '/version' do
{ version: Gitlab::VERSION, revision: Gitlab.revision }
conditionally_graphql!(
query: METADATA_QUERY,
context: { current_user: current_user },
transform: ->(result) { result.dig('data', 'metadata') },
fallback: -> { { version: Gitlab::VERSION, revision: Gitlab.revision } }
)
end
end
end
......@@ -1389,6 +1389,9 @@ msgstr ""
msgid "Chat"
msgstr ""
msgid "Check again"
msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
......@@ -3052,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 ""
......@@ -3097,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 ""