summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-09 09:08:04 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-09 09:08:04 +0000
commit2e2db606cc7547b445a11c367d8db6f5feb42443 (patch)
tree58a4d9c8ea1e78aaea796a525ef79c037f3e0e51 /app
parentc789d0002c97a00e262be992adfcc0d26b72910e (diff)
downloadgitlab-ce-2e2db606cc7547b445a11c367d8db6f5feb42443.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue15
-rw-r--r--app/assets/javascripts/ci/runner/admin_new_runner/index.js7
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_platforms_radio.vue76
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue97
-rw-r--r--app/assets/javascripts/ci/runner/constants.js14
-rw-r--r--app/graphql/mutations/work_items/update.rb33
-rw-r--r--app/models/design_user_mention.rb4
-rw-r--r--app/models/work_items/type.rb4
-rw-r--r--app/services/issues/create_service.rb8
-rw-r--r--app/services/issues/update_service.rb8
-rw-r--r--app/views/admin/runners/new.html.haml6
11 files changed, 270 insertions, 2 deletions
diff --git a/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue b/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue
index 293fbfcf7a7..db65268166c 100644
--- a/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue
+++ b/app/assets/javascripts/ci/runner/admin_new_runner/admin_new_runner_app.vue
@@ -1,6 +1,8 @@
<script>
import { GlSprintf, GlLink, GlModalDirective } from '@gitlab/ui';
import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
+import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue';
+import { DEFAULT_PLATFORM } from '../constants';
export default {
name: 'AdminNewRunnerApp',
@@ -8,6 +10,7 @@ export default {
GlLink,
GlSprintf,
RunnerInstructionsModal,
+ RunnerPlatformsRadioGroup,
},
directives: {
GlModal: GlModalDirective,
@@ -18,6 +21,11 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ platform: DEFAULT_PLATFORM,
+ };
+ },
modalId: 'runners-legacy-registration-instructions-modal',
};
</script>
@@ -44,5 +52,12 @@ export default {
</template>
</gl-sprintf>
</p>
+
+ <hr />
+
+ <h2 class="gl-font-weight-normal gl-font-lg gl-my-5">
+ {{ s__('Runners|Platform') }}
+ </h2>
+ <runner-platforms-radio-group v-model="platform" />
</div>
</template>
diff --git a/app/assets/javascripts/ci/runner/admin_new_runner/index.js b/app/assets/javascripts/ci/runner/admin_new_runner/index.js
index 502d9d33b4d..7aca19572b3 100644
--- a/app/assets/javascripts/ci/runner/admin_new_runner/index.js
+++ b/app/assets/javascripts/ci/runner/admin_new_runner/index.js
@@ -12,7 +12,7 @@ export const initAdminNewRunner = (selector = '#js-admin-new-runner') => {
return null;
}
- const { legacyRegistrationToken } = el.dataset;
+ const { legacyRegistrationToken, awsImgPath, dockerImgPath, kubernetesImgPath } = el.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
@@ -21,6 +21,11 @@ export const initAdminNewRunner = (selector = '#js-admin-new-runner') => {
return new Vue({
el,
apolloProvider,
+ provide: {
+ awsImgPath,
+ dockerImgPath,
+ kubernetesImgPath,
+ },
render(h) {
return h(AdminNewRunnerApp, {
props: {
diff --git a/app/assets/javascripts/ci/runner/components/runner_platforms_radio.vue b/app/assets/javascripts/ci/runner/components/runner_platforms_radio.vue
new file mode 100644
index 00000000000..d70c51e83f9
--- /dev/null
+++ b/app/assets/javascripts/ci/runner/components/runner_platforms_radio.vue
@@ -0,0 +1,76 @@
+<script>
+import { GlFormRadio } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlFormRadio,
+ },
+ model: {
+ event: 'input',
+ prop: 'checked',
+ },
+ props: {
+ image: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ checked: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ value: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ isChecked() {
+ return this.value && this.value === this.checked;
+ },
+ },
+ methods: {
+ onInput($event) {
+ if (!$event) {
+ return;
+ }
+ this.$emit('input', $event);
+ },
+ onChange($event) {
+ this.$emit('change', $event);
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="runner-platforms-radio gl-display-flex gl-border gl-rounded-base gl-px-5 gl-py-6"
+ :class="{ 'gl-bg-blue-50 gl-border-blue-500': isChecked, 'gl-cursor-pointer': value }"
+ @click="onInput(value)"
+ >
+ <gl-form-radio
+ v-if="value"
+ class="gl-min-h-5"
+ :checked="checked"
+ :value="value"
+ @input="onInput($event)"
+ @change="onChange($event)"
+ >
+ <img v-if="image" :src="image" aria-hidden="true" class="gl-h-5 gl-mr-2" />
+ <span class="gl-font-weight-bold"><slot></slot></span>
+ </gl-form-radio>
+ <div v-else class="gl-h-5">
+ <img v-if="image" :src="image" aria-hidden="true" class="gl-h-5 gl-mr-2" />
+ <span class="gl-font-weight-bold"><slot></slot></span>
+ </div>
+ </div>
+</template>
+
+<style>
+.runner-platforms-radio {
+ min-width: 173px;
+}
+</style>
diff --git a/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue b/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue
new file mode 100644
index 00000000000..304fdadbca2
--- /dev/null
+++ b/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue
@@ -0,0 +1,97 @@
+<script>
+import { GlFormRadioGroup, GlIcon, GlLink } from '@gitlab/ui';
+import {
+ LINUX_PLATFORM,
+ MACOS_PLATFORM,
+ WINDOWS_PLATFORM,
+ AWS_PLATFORM,
+ DOCKER_HELP_URL,
+ KUBERNETES_HELP_URL,
+} from '../constants';
+
+import RunnerPlatformsRadio from './runner_platforms_radio.vue';
+
+export default {
+ components: {
+ GlFormRadioGroup,
+ GlLink,
+ GlIcon,
+ RunnerPlatformsRadio,
+ },
+ inject: ['awsImgPath', 'dockerImgPath', 'kubernetesImgPath'],
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ model: this.value,
+ };
+ },
+ watch: {
+ model() {
+ this.$emit('input', this.model);
+ },
+ },
+ LINUX_PLATFORM,
+ MACOS_PLATFORM,
+ WINDOWS_PLATFORM,
+ AWS_PLATFORM,
+ DOCKER_HELP_URL,
+ KUBERNETES_HELP_URL,
+};
+</script>
+
+<template>
+ <gl-form-radio-group v-model="model">
+ <div class="gl-mt-3 gl-mb-6">
+ <label>{{ s__('Runners|Operating systems') }}</label>
+
+ <div class="gl-display-flex gl-flex-wrap gl-gap-5">
+ <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
+ <runner-platforms-radio v-model="model" :value="$options.LINUX_PLATFORM">
+ Linux
+ </runner-platforms-radio>
+ <runner-platforms-radio v-model="model" :value="$options.MACOS_PLATFORM">
+ macOS
+ </runner-platforms-radio>
+ <runner-platforms-radio v-model="model" :value="$options.WINDOWS_PLATFORM">
+ Windows
+ </runner-platforms-radio>
+ </div>
+ </div>
+
+ <div class="gl-mt-3 gl-mb-6">
+ <label>{{ s__('Runners|Cloud templates') }}</label>
+ <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
+ <div class="gl-display-flex gl-flex-wrap gl-gap-5">
+ <runner-platforms-radio v-model="model" :image="awsImgPath" :value="$options.AWS_PLATFORM">
+ AWS
+ </runner-platforms-radio>
+ </div>
+ </div>
+
+ <div class="gl-mt-3 gl-mb-6">
+ <label>{{ s__('Runners|Containers') }}</label>
+
+ <div class="gl-display-flex gl-flex-wrap gl-gap-5">
+ <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
+ <runner-platforms-radio :image="dockerImgPath">
+ <gl-link :href="$options.DOCKER_HELP_URL" target="_blank">
+ Docker
+ <gl-icon name="external-link" />
+ </gl-link>
+ </runner-platforms-radio>
+ <runner-platforms-radio :image="kubernetesImgPath">
+ <gl-link :href="$options.KUBERNETES_HELP_URL" target="_blank">
+ Kubernetes
+ <gl-icon name="external-link" />
+ </gl-link>
+ </runner-platforms-radio>
+ </div>
+ </div>
+ </gl-form-radio-group>
+</template>
diff --git a/app/assets/javascripts/ci/runner/constants.js b/app/assets/javascripts/ci/runner/constants.js
index dc4a62852ed..ddad456a6dc 100644
--- a/app/assets/javascripts/ci/runner/constants.js
+++ b/app/assets/javascripts/ci/runner/constants.js
@@ -172,3 +172,17 @@ export const DEFAULT_MEMBERSHIP = MEMBERSHIP_DESCENDANTS;
export const ADMIN_FILTERED_SEARCH_NAMESPACE = 'admin_runners';
export const GROUP_FILTERED_SEARCH_NAMESPACE = 'group_runners';
+
+// Platforms
+
+export const LINUX_PLATFORM = 'linux';
+export const MACOS_PLATFORM = 'osx';
+export const WINDOWS_PLATFORM = 'windows';
+export const AWS_PLATFORM = 'aws';
+
+export const DEFAULT_PLATFORM = LINUX_PLATFORM;
+
+// Runner docs are in a separate repository and are not shipped with GitLab
+// they are rendered as external URLs.
+export const DOCKER_HELP_URL = 'https://docs.gitlab.com/runner/install/docker.html';
+export const KUBERNETES_HELP_URL = 'https://docs.gitlab.com/runner/install/kubernetes.html';
diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb
index 04c63d8e876..741a0ca771f 100644
--- a/app/graphql/mutations/work_items/update.rb
+++ b/app/graphql/mutations/work_items/update.rb
@@ -22,6 +22,8 @@ module Mutations
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
widget_params = extract_widget_params!(work_item.work_item_type, attributes)
+ interpret_quick_actions!(work_item, current_user, widget_params, attributes)
+
update_result = ::WorkItems::UpdateService.new(
project: work_item.project,
current_user: current_user,
@@ -43,6 +45,37 @@ module Mutations
def find_object(id:)
GitlabSchema.find_by_gid(id)
end
+
+ def interpret_quick_actions!(work_item, current_user, widget_params, attributes = {})
+ return unless work_item.work_item_type.widgets.include?(::WorkItems::Widgets::Description)
+
+ description_param = widget_params[::WorkItems::Widgets::Description.api_symbol]
+ return unless description_param
+
+ original_description = description_param.fetch(:description, work_item.description)
+
+ description, command_params = QuickActions::InterpretService
+ .new(work_item.project, current_user, {})
+ .execute(original_description, work_item)
+
+ description_param[:description] = description if description && description != original_description
+
+ # Widgets have a set of quick action params that they must process.
+ # Map them to widget_params so they can be picked up by widget services.
+ work_item.work_item_type.widgets
+ .filter { |widget| widget.respond_to?(:quick_action_params) }
+ .each do |widget|
+ widget.quick_action_params
+ .filter { |param_name| command_params.key?(param_name) }
+ .each do |param_name|
+ widget_params[widget.api_symbol] ||= {}
+ widget_params[widget.api_symbol][param_name] = command_params.delete(param_name)
+ end
+ end
+
+ # The command_params not processed by widgets (e.g. title) should be placed in 'attributes'.
+ attributes.merge!(command_params || {})
+ end
end
end
end
diff --git a/app/models/design_user_mention.rb b/app/models/design_user_mention.rb
index baf4db29a0f..87899f65cb1 100644
--- a/app/models/design_user_mention.rb
+++ b/app/models/design_user_mention.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class DesignUserMention < UserMention
+ include IgnorableColumns
+
+ ignore_column :note_id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22'
+
belongs_to :design, class_name: 'DesignManagement::Design'
belongs_to :note
end
diff --git a/app/models/work_items/type.rb b/app/models/work_items/type.rb
index 9b434ef946c..258a86d7316 100644
--- a/app/models/work_items/type.rb
+++ b/app/models/work_items/type.rb
@@ -145,6 +145,10 @@ module WorkItems
widgets.include? ::WorkItems::Widgets::Assignees
end
+ def default_issue?
+ name == WorkItems::Type::TYPE_NAMES[:issue]
+ end
+
private
def strip_whitespace
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index f6a1db2dcaa..a92110fd843 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -100,6 +100,14 @@ module Issues
private
+ def handle_quick_actions(issue)
+ # Do not handle quick actions unless the work item is the default Issue.
+ # The available quick actions for a work item depend on its type and widgets.
+ return if @params[:work_item_type].present? && @params[:work_item_type] != WorkItems::Type.default_by_type(:issue)
+
+ super
+ end
+
def authorization_action
:create_issue
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index d56e7858990..d43df0da3fd 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -116,6 +116,14 @@ module Issues
attr_reader :spam_params
+ def handle_quick_actions(issue)
+ # Do not handle quick actions unless the work item is the default Issue.
+ # The available quick actions for a work item depend on its type and widgets.
+ return unless issue.work_item_type.default_issue?
+
+ super
+ end
+
def handle_date_changes(issue)
return unless issue.previous_changes.slice('due_date', 'start_date').any?
diff --git a/app/views/admin/runners/new.html.haml b/app/views/admin/runners/new.html.haml
index 12a569862e6..cf5638d0294 100644
--- a/app/views/admin/runners/new.html.haml
+++ b/app/views/admin/runners/new.html.haml
@@ -2,4 +2,8 @@
- breadcrumb_title s_('Runner|New')
- page_title s_('Runners|Create an instance runner')
-#js-admin-new-runner{ data: { legacy_registration_token: Gitlab::CurrentSettings.runners_registration_token } }
+#js-admin-new-runner{ data: {
+ legacy_registration_token: Gitlab::CurrentSettings.runners_registration_token,
+ aws_img_path: image_path('illustrations/logos/aws.svg'),
+ kubernetes_img_path: image_path('illustrations/logos/kubernetes.svg'),
+ docker_img_path: image_path('illustrations/third-party-logos/ci_cd-template-logos/docker.png') } }