diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-17 00:12:05 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-17 00:12:05 +0300 |
commit | f9e0126cad562c7199e26e84a1540df3bc849e55 (patch) | |
tree | 5390ccbadaa4f1f49eeb44c45b805f26bd12ceef /app | |
parent | c1436508fa677bbe850e1e13761d2e6b791c698c (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
18 files changed, 284 insertions, 43 deletions
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue index 591800ee9be..9d355c96af1 100644 --- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue +++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue @@ -2,6 +2,7 @@ import { mapState, mapGetters, mapActions } from 'vuex'; import { s__ } from '~/locale'; import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form'; +import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import MultilineCommentForm from '../../notes/components/multiline_comment_form.vue'; import { @@ -177,16 +178,16 @@ export default { 'saveDiffDiscussion', 'setSuggestPopoverDismissed', ]), - handleCancelCommentForm(shouldConfirm, isDirty) { + async handleCancelCommentForm(shouldConfirm, isDirty) { if (shouldConfirm && isDirty) { const msg = s__('Notes|Are you sure you want to cancel creating this comment?'); - // eslint-disable-next-line no-alert - if (!window.confirm(msg)) { + const confirmed = await confirmAction(msg); + + if (!confirmed) { return; } } - this.cancelCommentForm({ lineCode: this.line.line_code, fileHash: this.diffFileHash, diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js index f0908a60ac5..fdd0e045d07 100644 --- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js +++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js @@ -1,25 +1,9 @@ import Vue from 'vue'; -export function confirmViaGlModal(message, element) { +export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {}) { return new Promise((resolve) => { let confirmed = false; - const props = {}; - - const confirmBtnVariant = element.getAttribute('data-confirm-btn-variant'); - - if (confirmBtnVariant) { - props.primaryVariant = confirmBtnVariant; - } - const screenReaderText = - element.querySelector('.gl-sr-only')?.textContent || - element.querySelector('.sr-only')?.textContent || - element.getAttribute('aria-label'); - - if (screenReaderText) { - props.primaryText = screenReaderText; - } - const component = new Vue({ components: { ConfirmModal: () => import('./confirm_modal.vue'), @@ -28,7 +12,10 @@ export function confirmViaGlModal(message, element) { return h( 'confirm-modal', { - props, + props: { + primaryVariant: primaryBtnVariant, + primaryText: primaryBtnText, + }, on: { confirmed() { confirmed = true; @@ -45,3 +32,24 @@ export function confirmViaGlModal(message, element) { }).$mount(); }); } + +export function confirmViaGlModal(message, element) { + const primaryBtnConfig = {}; + + const confirmBtnVariant = element.getAttribute('data-confirm-btn-variant'); + + if (confirmBtnVariant) { + primaryBtnConfig.primaryBtnVariant = confirmBtnVariant; + } + + const screenReaderText = + element.querySelector('.gl-sr-only')?.textContent || + element.querySelector('.sr-only')?.textContent || + element.getAttribute('aria-label'); + + if (screenReaderText) { + primaryBtnConfig.primaryBtnText = screenReaderText; + } + + return confirmAction(message, primaryBtnConfig); +} diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue index f1fe8cf10fd..905a5f2d271 100644 --- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue +++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue @@ -36,6 +36,11 @@ export default { required: false, default: false, }, + scrollToCommitForm: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -52,6 +57,13 @@ export default { return !(this.message && this.targetBranch); }, }, + watch: { + scrollToCommitForm(flag) { + if (flag) { + this.scrollIntoView(); + } + }, + }, methods: { onSubmit() { this.$emit('submit', { @@ -63,6 +75,10 @@ export default { onReset() { this.$emit('cancel'); }, + scrollIntoView() { + this.$el.scrollIntoView({ behavior: 'smooth' }); + this.$emit('scrolled-to-commit-form'); + }, }, i18n: { commitMessage: __('Commit message'), diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue index 9b5287afae9..14c11099756 100644 --- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue +++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue @@ -45,6 +45,11 @@ export default { required: false, default: false, }, + scrollToCommitForm: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -146,6 +151,8 @@ export default { :current-branch="currentBranch" :default-message="defaultCommitMessage" :is-saving="isSaving" + :scroll-to-commit-form="scrollToCommitForm" + v-on="$listeners" @cancel="onCommitCancel" @submit="onCommitSubmit" /> diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue index ff1e0b6388f..d7594fb318a 100644 --- a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue +++ b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue @@ -2,6 +2,7 @@ import { GlButton, GlIcon } from '@gitlab/ui'; import { __ } from '~/locale'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; +import { experiment } from '~/experimentation/utils'; import { DRAWER_EXPANDED_KEY } from '../../constants'; import FirstPipelineCard from './cards/first_pipeline_card.vue'; import GettingStartedCard from './cards/getting_started_card.vue'; @@ -53,12 +54,23 @@ export default { }, methods: { setInitialExpandState() { + let isExpanded; + + experiment('pipeline_editor_walkthrough', { + control: () => { + isExpanded = true; + }, + candidate: () => { + isExpanded = false; + }, + }); + // We check in the local storage and if no value is defined, we want the default // to be true. We want to explicitly set it to true here so that the drawer // animates to open on load. const localValue = localStorage.getItem(this.$options.localDrawerKey); if (localValue === null) { - this.isExpanded = true; + this.isExpanded = isExpanded; } }, setTopPosition() { diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue index f27c2cd9dca..baf1d17b233 100644 --- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue +++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue @@ -112,7 +112,7 @@ export default { isBranchesLoading() { return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches; }, - showBranchSwitcher() { + enableBranchSwitcher() { return this.branches.length > 0 || this.searchTerm.length > 0; }, }, @@ -230,11 +230,11 @@ export default { <template> <gl-dropdown - v-if="showBranchSwitcher" v-gl-tooltip.hover :title="$options.i18n.dropdownHeader" :header-text="$options.i18n.dropdownHeader" :text="currentBranch" + :disabled="!enableBranchSwitcher" icon="branch" data-qa-selector="branch_selector_button" data-testid="branch-selector" diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue index b86c4df253e..0cd0d17d944 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -4,6 +4,7 @@ import { s__ } from '~/locale'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { getParameterValues, setUrlParams, updateHistory } from '~/lib/utils/url_utility'; +import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; import { CREATE_TAB, EDITOR_APP_STATUS_EMPTY, @@ -22,6 +23,7 @@ import CiEditorHeader from './editor/ci_editor_header.vue'; import TextEditor from './editor/text_editor.vue'; import CiLint from './lint/ci_lint.vue'; import EditorTab from './ui/editor_tab.vue'; +import WalkthroughPopover from './walkthrough_popover.vue'; export default { i18n: { @@ -63,6 +65,8 @@ export default { GlTabs, PipelineGraph, TextEditor, + GitlabExperiment, + WalkthroughPopover, }, mixins: [glFeatureFlagsMixin()], props: { @@ -79,6 +83,10 @@ export default { required: false, default: '', }, + isNewCiConfigFile: { + type: Boolean, + required: true, + }, }, apollo: { appStatus: { @@ -136,11 +144,17 @@ export default { > <editor-tab class="gl-mb-3" + title-link-class="js-walkthrough-popover-target" :title="$options.i18n.tabEdit" lazy data-testid="editor-tab" @click="setCurrentTab($options.tabConstants.CREATE_TAB)" > + <gitlab-experiment name="pipeline_editor_walkthrough"> + <template #candidate> + <walkthrough-popover v-if="isNewCiConfigFile" v-on="$listeners" /> + </template> + </gitlab-experiment> <ci-editor-header /> <text-editor :commit-sha="commitSha" :value="ciFileContent" v-on="$listeners" /> </editor-tab> diff --git a/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue b/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue new file mode 100644 index 00000000000..5742b11b841 --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/components/walkthrough_popover.vue @@ -0,0 +1,83 @@ +<script> +import { GlButton, GlPopover, GlSprintf, GlOutsideDirective as Outside } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +export default { + directives: { Outside }, + i18n: { + title: s__('pipelineEditorWalkthrough|See how GitLab pipelines work'), + description: s__( + 'pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline.', + ), + instruction: s__( + 'pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline.', + ), + ctaText: s__("pipelineEditorWalkthrough|Let's do this!"), + }, + components: { + GlButton, + GlPopover, + GlSprintf, + }, + data() { + return { + show: true, + }; + }, + computed: { + targetElement() { + return document.querySelector('.js-walkthrough-popover-target'); + }, + }, + methods: { + close() { + this.show = false; + }, + handleClickCta() { + this.close(); + this.$emit('walkthrough-popover-cta-clicked'); + }, + }, +}; +</script> + +<template> + <gl-popover + :show.sync="show" + :title="$options.i18n.title" + :target="targetElement" + placement="right" + triggers="focus" + > + <div v-outside="close" class="gl-display-flex gl-flex-direction-column"> + <p> + <gl-sprintf :message="$options.i18n.description"> + <template #code="{ content }"> + <code>{{ content }}</code> + </template> + </gl-sprintf> + </p> + + <p> + <gl-sprintf :message="$options.i18n.instruction"> + <template #bold="{ content }"> + <strong> + {{ content }} + </strong> + </template> + </gl-sprintf> + </p> + + <gl-button + class="gl-align-self-end" + category="tertiary" + data-testid="ctaBtn" + variant="confirm" + @click="handleClickCta" + > + <gl-emoji data-name="rocket" /> + {{ this.$options.i18n.ctaText }} + </gl-button> + </div> + </gl-popover> +</template> diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue index 58723e63f3c..8e8f31a4acc 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue @@ -58,6 +58,7 @@ export default { data() { return { currentTab: CREATE_TAB, + scrollToCommitForm: false, shouldLoadNewBranch: false, showSwitchBranchModal: false, }; @@ -81,6 +82,9 @@ export default { setCurrentTab(tabName) { this.currentTab = tabName; }, + setScrollToCommitForm(newValue = true) { + this.scrollToCommitForm = newValue; + }, }, }; </script> @@ -117,8 +121,10 @@ export default { :ci-config-data="ciConfigData" :ci-file-content="ciFileContent" :commit-sha="commitSha" + :is-new-ci-config-file="isNewCiConfigFile" v-on="$listeners" @set-current-tab="setCurrentTab" + @walkthrough-popover-cta-clicked="setScrollToCommitForm" /> <commit-section v-if="showCommitForm" @@ -126,6 +132,8 @@ export default { :ci-file-content="ciFileContent" :commit-sha="commitSha" :is-new-ci-config-file="isNewCiConfigFile" + :scroll-to-commit-form="scrollToCommitForm" + @scrolled-to-commit-form="setScrollToCommitForm(false)" v-on="$listeners" /> <pipeline-editor-drawer /> diff --git a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue index 759f6b37696..3edb658eaf5 100644 --- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue @@ -1,9 +1,9 @@ <script> -import { GlLink } from '@gitlab/ui'; +import { GlBadge, GlLink } from '@gitlab/ui'; import createFlash from '~/flash'; import { fetchPolicies } from '~/lib/graphql'; import { updateHistory } from '~/lib/utils/url_utility'; -import { formatNumber, sprintf, __ } from '~/locale'; +import { sprintf, __ } from '~/locale'; import RegistrationDropdown from '../components/registration/registration_dropdown.vue'; import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue'; @@ -14,7 +14,13 @@ import RunnerTypeTabs from '../components/runner_type_tabs.vue'; import { statusTokenConfig } from '../components/search_tokens/status_token_config'; import { tagTokenConfig } from '../components/search_tokens/tag_token_config'; -import { ADMIN_FILTERED_SEARCH_NAMESPACE, INSTANCE_TYPE, I18N_FETCH_ERROR } from '../constants'; +import { + ADMIN_FILTERED_SEARCH_NAMESPACE, + INSTANCE_TYPE, + GROUP_TYPE, + PROJECT_TYPE, + I18N_FETCH_ERROR, +} from '../constants'; import getRunnersQuery from '../graphql/get_runners.query.graphql'; import { fromUrlQueryToSearch, @@ -26,6 +32,7 @@ import { captureException } from '../sentry_utils'; export default { name: 'AdminRunnersApp', components: { + GlBadge, GlLink, RegistrationDropdown, RunnerFilteredSearchBar, @@ -35,11 +42,27 @@ export default { RunnerTypeTabs, }, props: { + registrationToken: { + type: String, + required: true, + }, activeRunnersCount: { - type: Number, + type: String, required: true, }, - registrationToken: { + allRunnersCount: { + type: String, + required: true, + }, + instanceRunnersCount: { + type: String, + required: true, + }, + groupRunnersCount: { + type: String, + required: true, + }, + projectRunnersCount: { type: String, required: true, }, @@ -89,7 +112,7 @@ export default { }, activeRunnersMessage() { return sprintf(__('Runners currently online: %{active_runners_count}'), { - active_runners_count: formatNumber(this.activeRunnersCount), + active_runners_count: this.activeRunnersCount, }); }, searchTokens() { @@ -118,6 +141,20 @@ export default { this.reportToSentry(error); }, methods: { + tabCount({ runnerType }) { + switch (runnerType) { + case null: + return this.allRunnersCount; + case INSTANCE_TYPE: + return this.instanceRunnersCount; + case GROUP_TYPE: + return this.groupRunnersCount; + case PROJECT_TYPE: + return this.projectRunnersCount; + default: + return null; + } + }, reportToSentry(error) { captureException({ error, component: this.$options.name }); }, @@ -128,15 +165,25 @@ export default { </script> <template> <div> - <div class="gl-display-flex gl-align-items-center"> + <div + class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0" + > <runner-type-tabs v-model="search" + class="gl-w-full" content-class="gl-display-none" nav-class="gl-border-none!" - /> + > + <template #title="{ tab }"> + {{ tab.title }} + <gl-badge v-if="tabCount(tab)" class="gl-ml-1" size="sm"> + {{ tabCount(tab) }} + </gl-badge> + </template> + </runner-type-tabs> <registration-dropdown - class="gl-ml-auto" + class="gl-w-full gl-sm-w-auto gl-mr-auto" :registration-token="registrationToken" :type="$options.INSTANCE_TYPE" right diff --git a/app/assets/javascripts/runner/admin_runners/index.js b/app/assets/javascripts/runner/admin_runners/index.js index 9d80eec6f54..62da6cbfa2b 100644 --- a/app/assets/javascripts/runner/admin_runners/index.js +++ b/app/assets/javascripts/runner/admin_runners/index.js @@ -16,7 +16,16 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { // TODO `activeRunnersCount` should be implemented using a GraphQL API // https://gitlab.com/gitlab-org/gitlab/-/issues/333806 - const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset; + const { + runnerInstallHelpPage, + registrationToken, + + activeRunnersCount, + allRunnersCount, + instanceRunnersCount, + groupRunnersCount, + projectRunnersCount, + } = el.dataset; const apolloProvider = new VueApollo({ defaultClient: createDefaultClient(), @@ -31,8 +40,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { render(h) { return h(AdminRunnersApp, { props: { - activeRunnersCount: parseInt(activeRunnersCount, 10), registrationToken, + + // All runner counts are returned as formatted + // strings, we do not use `parseInt`. + activeRunnersCount, + allRunnersCount, + instanceRunnersCount, + groupRunnersCount, + projectRunnersCount, }, }); }, diff --git a/app/assets/javascripts/runner/components/runner_type_tabs.vue b/app/assets/javascripts/runner/components/runner_type_tabs.vue index 9de444ea42f..b767dafaccf 100644 --- a/app/assets/javascripts/runner/components/runner_type_tabs.vue +++ b/app/assets/javascripts/runner/components/runner_type_tabs.vue @@ -51,13 +51,16 @@ export default { }; </script> <template> - <gl-tabs v-bind="$attrs"> + <gl-tabs v-bind="$attrs" data-testid="runner-type-tabs"> <gl-tab v-for="tab in $options.tabs" :key="`${tab.runnerType}`" :active="isTabActive(tab)" - :title="tab.title" @click="onTabSelected(tab)" - /> + > + <template #title> + <slot name="title" :tab="tab">{{ tab.title }}</slot> + </template> + </gl-tab> </gl-tabs> </template> diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 76e86f15da8..9312651b8bf 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -8,7 +8,6 @@ class Admin::RunnersController < Admin::ApplicationController feature_category :runner def index - @active_runners_count = Ci::Runner.online.count end def show diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index d32755dbd94..cfd86429df0 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -116,7 +116,9 @@ class Import::BitbucketController < Import::BaseController redirect_to oauth_client.auth_code.authorize_url(redirect_uri: users_import_bitbucket_callback_url) end - def bitbucket_unauthorized + def bitbucket_unauthorized(exception) + log_exception(exception) + go_to_bitbucket_for_permissions end diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb index c8394d91677..70a1a855e91 100644 --- a/app/controllers/projects/ci/pipeline_editor_controller.rb +++ b/app/controllers/projects/ci/pipeline_editor_controller.rb @@ -2,6 +2,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController before_action :check_can_collaborate! + before_action :setup_walkthrough_experiment, only: :show before_action do push_frontend_feature_flag(:schema_linting, @project, default_enabled: :yaml) end @@ -16,4 +17,10 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController def check_can_collaborate! render_404 unless can_collaborate_with_project?(@project) end + + def setup_walkthrough_experiment + experiment(:pipeline_editor_walkthrough, actor: current_user) do |e| + e.candidate {} + end + end end diff --git a/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt b/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt index bbe8271386f..7592c7c6ab7 100644 --- a/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt +++ b/app/experiments/templates/new_project_readme_content/readme_advanced.md.tt @@ -23,13 +23,14 @@ git push -uf origin <%= @project.default_branch_or_main %> ## Integrate with your tools -- [ ] [Set up project integrations](<%= redirect("https://docs.gitlab.com/ee/user/project/integrations/") %>) +- [ ] [Set up project integrations](<%= redirect(project_settings_integrations_url(@project)) %>) ## Collaborate with your team - [ ] [Invite team members and collaborators](<%= redirect("https://docs.gitlab.com/ee/user/project/members/") %>) - [ ] [Create a new merge request](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html") %>) - [ ] [Automatically close issues from merge requests](<%= redirect("https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically") %>) +- [ ] [Enable merge request approvals](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/approvals/") %>) - [ ] [Automatically merge when pipeline succeeds](<%= redirect("https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html") %>) ## Test and Deploy @@ -40,6 +41,7 @@ Use the built-in continuous integration in GitLab. - [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](<%= redirect("https://docs.gitlab.com/ee/user/application_security/sast/") %>) - [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](<%= redirect("https://docs.gitlab.com/ee/topics/autodevops/requirements.html") %>) - [ ] [Use pull-based deployments for improved Kubernetes management](<%= redirect("https://docs.gitlab.com/ee/user/clusters/agent/") %>) +- [ ] [Set up protected environments](<%= redirect("https://docs.gitlab.com/ee/ci/environments/protected_environments.html") %>) *** diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb index 1cd80174f93..17057505173 100644 --- a/app/helpers/ci/runners_helper.rb +++ b/app/helpers/ci/runners_helper.rb @@ -60,6 +60,22 @@ module Ci end end + def admin_runners_data_attributes + { + # Runner install help page is external, located at + # https://gitlab.com/gitlab-org/gitlab-runner + runner_install_help_page: 'https://docs.gitlab.com/runner/install/', + registration_token: Gitlab::CurrentSettings.runners_registration_token, + + # All runner counts are returned as formatted strings + active_runners_count: Ci::Runner.online.count.to_s, + all_runners_count: limited_counter_with_delimiter(Ci::Runner), + instance_runners_count: limited_counter_with_delimiter(Ci::Runner.instance_type), + group_runners_count: limited_counter_with_delimiter(Ci::Runner.group_type), + project_runners_count: limited_counter_with_delimiter(Ci::Runner.project_type) + } + end + def group_shared_runners_settings_data(group) { update_path: api_v4_groups_path(id: group.id), diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index f298fce7bcf..0539d7f13a2 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -1,4 +1,4 @@ - breadcrumb_title _('Runners') - page_title _('Runners') -#js-admin-runners{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } } +#js-admin-runners{ data: admin_runners_data_attributes } |