diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-15 21:12:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-15 21:12:21 +0300 |
commit | 4481a56a94c579f52e1cdef1cc1f4995f0ee1412 (patch) | |
tree | 9b8d431d53057e6351dd56718d212b2c89b19312 /app | |
parent | e5c7d631a84940c66e46f1824ba7ce0c7f1d0ea4 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
20 files changed, 403 insertions, 39 deletions
diff --git a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue index 5c6f9de0624..af44a23b4b3 100644 --- a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue +++ b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue @@ -11,9 +11,6 @@ export default { getStartedDocsUrl: helpPagePath('user/clusters/agent/index', { anchor: 'define-a-configuration-repository', }), - integrationsDocsUrl: helpPagePath('user/clusters/agent/index', { - anchor: 'get-started-with-gitops-and-the-gitlab-agent', - }), components: { GlButton, GlEmptyState, @@ -30,6 +27,11 @@ export default { type: Boolean, required: true, }, + isChildComponent: { + default: false, + required: false, + type: Boolean, + }, }, computed: { repositoryPath() { @@ -92,6 +94,7 @@ export default { <template #actions> <gl-button + v-if="!isChildComponent" v-gl-modal-directive="$options.modalId" :disabled="!hasConfigurations" data-testid="integration-primary-button" diff --git a/app/assets/javascripts/clusters_list/components/agents.vue b/app/assets/javascripts/clusters_list/components/agents.vue index 4fc79b32b9c..fb5cf7d1206 100644 --- a/app/assets/javascripts/clusters_list/components/agents.vue +++ b/app/assets/javascripts/clusters_list/components/agents.vue @@ -20,6 +20,9 @@ export default { this.updateTreeList(data); return data; }, + result() { + this.emitAgentsLoaded(); + }, }, }, components: { @@ -36,11 +39,21 @@ export default { required: false, type: String, }, + isChildComponent: { + default: false, + required: false, + type: Boolean, + }, + limit: { + default: null, + required: false, + type: Number, + }, }, data() { return { cursor: { - first: MAX_LIST_COUNT, + first: this.limit ? this.limit : MAX_LIST_COUNT, last: null, }, folderList: {}, @@ -68,7 +81,7 @@ export default { return this.$apollo.queries.agents.loading; }, showPagination() { - return this.agentPageInfo.hasPreviousPage || this.agentPageInfo.hasNextPage; + return !this.limit && (this.agentPageInfo.hasPreviousPage || this.agentPageInfo.hasNextPage); }, treePageInfo() { return this.agents?.project?.repository?.tree?.trees?.pageInfo || {}; @@ -128,6 +141,10 @@ export default { } return 'unused'; }, + emitAgentsLoaded() { + const count = this.agents?.project?.clusterAgents?.count; + this.$emit('onAgentsLoad', count); + }, }, }; </script> @@ -144,7 +161,11 @@ export default { </div> </div> - <agent-empty-state v-else :has-configurations="hasConfigurations" /> + <agent-empty-state + v-else + :has-configurations="hasConfigurations" + :is-child-component="isChildComponent" + /> </section> <gl-alert v-else variant="danger" :dismissible="false"> diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue index bc27563b6d5..9c330045596 100644 --- a/app/assets/javascripts/clusters_list/components/clusters.vue +++ b/app/assets/javascripts/clusters_list/components/clusters.vue @@ -34,6 +34,18 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + props: { + isChildComponent: { + default: false, + required: false, + type: Boolean, + }, + limit: { + default: null, + required: false, + type: Number, + }, + }, computed: { ...mapState([ 'clusters', @@ -100,10 +112,14 @@ export default { }, }, mounted() { + if (this.limit) { + this.setClustersPerPage(this.limit); + } + this.fetchClusters(); }, methods: { - ...mapActions(['fetchClusters', 'reportSentryError', 'setPage']), + ...mapActions(['fetchClusters', 'reportSentryError', 'setPage', 'setClustersPerPage']), k8sQuantityToGb(quantity) { if (!quantity) { return 0; @@ -312,10 +328,10 @@ export default { </template> </gl-table> - <clusters-empty-state v-else /> + <clusters-empty-state v-else :is-child-component="isChildComponent" /> <gl-pagination - v-if="hasClustersPerPage" + v-if="hasClustersPerPage && !limit" v-model="currentPage" :per-page="clustersPerPage" :total-items="totalClusters" diff --git a/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue index 993507b18bf..3879af6e9cb 100644 --- a/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue +++ b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue @@ -13,6 +13,13 @@ export default { GlSprintf, }, inject: ['emptyStateHelpText', 'clustersEmptyStateImage', 'newClusterPath'], + props: { + isChildComponent: { + default: false, + required: false, + type: Boolean, + }, + }, learnMoreHelpUrl: helpPagePath('user/project/clusters/index'), multipleClustersHelpUrl: helpPagePath('user/project/clusters/multiple_kubernetes_clusters'), computed: { @@ -54,6 +61,7 @@ export default { <template #actions> <gl-button + v-if="!isChildComponent" data-testid="integration-primary-button" data-qa-selector="add_kubernetes_cluster_link" category="primary" diff --git a/app/assets/javascripts/clusters_list/components/clusters_main_view.vue b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue index c87cf593305..9e03093aa67 100644 --- a/app/assets/javascripts/clusters_list/components/clusters_main_view.vue +++ b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue @@ -1,16 +1,18 @@ <script> import { GlTabs, GlTab } from '@gitlab/ui'; -import { CLUSTERS_TABS } from '../constants'; +import { CLUSTERS_TABS, MAX_CLUSTERS_LIST, MAX_LIST_COUNT, AGENT } from '../constants'; import Agents from './agents.vue'; import InstallAgentModal from './install_agent_modal.vue'; import ClustersActions from './clusters_actions.vue'; import Clusters from './clusters.vue'; +import ClustersViewAll from './clusters_view_all.vue'; export default { components: { GlTabs, GlTab, ClustersActions, + ClustersViewAll, Clusters, Agents, InstallAgentModal, @@ -26,11 +28,14 @@ export default { data() { return { selectedTabIndex: 0, + maxAgents: MAX_CLUSTERS_LIST, }; }, methods: { onTabChange(tabName) { this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName); + + this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST; }, }, }; @@ -63,6 +68,6 @@ export default { </template> </gl-tabs> - <install-agent-modal :default-branch-name="defaultBranchName" /> + <install-agent-modal :default-branch-name="defaultBranchName" :max-agents="maxAgents" /> </div> </template> diff --git a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue new file mode 100644 index 00000000000..48a1944fde3 --- /dev/null +++ b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue @@ -0,0 +1,217 @@ +<script> +import { + GlCard, + GlSprintf, + GlPopover, + GlLink, + GlButton, + GlBadge, + GlLoadingIcon, + GlModalDirective, +} from '@gitlab/ui'; +import { mapState } from 'vuex'; +import { + AGENT_CARD_INFO, + CERTIFICATE_BASED_CARD_INFO, + MAX_CLUSTERS_LIST, + INSTALL_AGENT_MODAL_ID, +} from '../constants'; +import Clusters from './clusters.vue'; +import Agents from './agents.vue'; + +export default { + components: { + GlCard, + GlSprintf, + GlPopover, + GlLink, + GlButton, + GlBadge, + GlLoadingIcon, + Clusters, + Agents, + }, + directives: { + GlModalDirective, + }, + AGENT_CARD_INFO, + CERTIFICATE_BASED_CARD_INFO, + MAX_CLUSTERS_LIST, + INSTALL_AGENT_MODAL_ID, + inject: ['addClusterPath'], + props: { + defaultBranchName: { + default: '.noBranch', + required: false, + type: String, + }, + }, + data() { + return { + loadingAgents: true, + totalAgents: null, + }; + }, + computed: { + ...mapState(['loadingClusters', 'totalClusters']), + isLoading() { + return this.loadingAgents || this.loadingClusters; + }, + agentsCardTitle() { + let cardTitle; + if (this.totalAgents > 0) { + cardTitle = { + message: AGENT_CARD_INFO.title, + number: this.totalAgents < MAX_CLUSTERS_LIST ? this.totalAgents : MAX_CLUSTERS_LIST, + total: this.totalAgents, + }; + } else { + cardTitle = { + message: AGENT_CARD_INFO.emptyTitle, + }; + } + + return cardTitle; + }, + clustersCardTitle() { + let cardTitle; + if (this.totalClusters > 0) { + cardTitle = { + message: CERTIFICATE_BASED_CARD_INFO.title, + number: this.totalClusters < MAX_CLUSTERS_LIST ? this.totalClusters : MAX_CLUSTERS_LIST, + total: this.totalClusters, + }; + } else { + cardTitle = { + message: CERTIFICATE_BASED_CARD_INFO.emptyTitle, + }; + } + + return cardTitle; + }, + }, + methods: { + cardFooterNumber(number) { + return number > MAX_CLUSTERS_LIST ? number : ''; + }, + onAgentsLoad(number) { + this.totalAgents = number; + this.loadingAgents = false; + }, + changeTab($event, tab) { + $event.preventDefault(); + this.$emit('changeTab', tab); + }, + }, +}; +</script> +<template> + <div> + <gl-loading-icon v-if="isLoading" size="md" /> + <div v-show="!isLoading" data-testid="clusters-cards-container"> + <gl-card + header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between gl-py-4" + body-class="gl-pb-0" + footer-class="gl-text-right" + > + <template #header> + <h3 data-testid="agent-card-title" class="gl-my-0 gl-font-weight-normal gl-font-size-h2"> + <gl-sprintf :message="agentsCardTitle.message" + ><template #number>{{ agentsCardTitle.number }}</template> + <template #total>{{ agentsCardTitle.total }}</template> + </gl-sprintf> + </h3> + + <gl-badge id="clusters-recommended-badge" size="md" variant="info">{{ + $options.AGENT_CARD_INFO.tooltip.label + }}</gl-badge> + + <gl-popover + target="clusters-recommended-badge" + container="viewport" + placement="bottom" + :title="$options.AGENT_CARD_INFO.tooltip.title" + > + <p class="gl-mb-0"> + <gl-sprintf :message="$options.AGENT_CARD_INFO.tooltip.text"> + <template #link="{ content }"> + <gl-link + :href="$options.AGENT_CARD_INFO.tooltip.link" + target="_blank" + class="gl-font-sm" + > + {{ content }}</gl-link + > + </template> + </gl-sprintf> + </p> + </gl-popover> + </template> + + <agents + :limit="$options.MAX_CLUSTERS_LIST" + :default-branch-name="defaultBranchName" + :is-child-component="true" + @onAgentsLoad="onAgentsLoad" + /> + + <template #footer> + <gl-link + v-if="totalAgents" + data-testid="agents-tab-footer-link" + :href="`?tab=${$options.AGENT_CARD_INFO.tabName}`" + @click="changeTab($event, $options.AGENT_CARD_INFO.tabName)" + ><gl-sprintf :message="$options.AGENT_CARD_INFO.footerText" + ><template #number>{{ cardFooterNumber(totalAgents) }}</template></gl-sprintf + ></gl-link + ><gl-button + v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID" + class="gl-ml-4" + category="secondary" + variant="confirm" + >{{ $options.AGENT_CARD_INFO.actionText }}</gl-button + > + </template> + </gl-card> + + <gl-card + class="gl-mt-6" + header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between" + body-class="gl-pb-0" + footer-class="gl-text-right" + > + <template #header> + <h3 + class="gl-my-1 gl-font-weight-normal gl-font-size-h2" + data-testid="clusters-card-title" + > + <gl-sprintf :message="clustersCardTitle.message" + ><template #number>{{ clustersCardTitle.number }}</template> + <template #total>{{ clustersCardTitle.total }}</template> + </gl-sprintf> + </h3> + </template> + + <clusters :limit="$options.MAX_CLUSTERS_LIST" :is-child-component="true" /> + + <template #footer> + <gl-link + v-if="totalClusters" + data-testid="clusters-tab-footer-link" + :href="`?tab=${$options.CERTIFICATE_BASED_CARD_INFO.tabName}`" + @click="changeTab($event, $options.CERTIFICATE_BASED_CARD_INFO.tabName)" + ><gl-sprintf :message="$options.CERTIFICATE_BASED_CARD_INFO.footerText" + ><template #number>{{ cardFooterNumber(totalClusters) }}</template></gl-sprintf + ></gl-link + ><gl-button + category="secondary" + variant="confirm" + class="gl-ml-4" + :href="addClusterPath" + >{{ $options.CERTIFICATE_BASED_CARD_INFO.actionText }}</gl-button + > + </template> + </gl-card> + </div> + </div> +</template> diff --git a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue index 0efd3844cc9..6eb2e85ecea 100644 --- a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue +++ b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue @@ -12,7 +12,7 @@ import { helpPagePath } from '~/helpers/help_page_helper'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import CodeBlock from '~/vue_shared/components/code_block.vue'; import { generateAgentRegistrationCommand } from '../clusters_util'; -import { INSTALL_AGENT_MODAL_ID, I18N_INSTALL_AGENT_MODAL, MAX_LIST_COUNT } from '../constants'; +import { INSTALL_AGENT_MODAL_ID, I18N_INSTALL_AGENT_MODAL } from '../constants'; import { addAgentToStore } from '../graphql/cache_update'; import createAgent from '../graphql/mutations/create_agent.mutation.graphql'; import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql'; @@ -41,6 +41,10 @@ export default { required: false, type: String, }, + maxAgents: { + required: true, + type: Number, + }, }, data() { return { @@ -75,7 +79,7 @@ export default { getAgentsQueryVariables() { return { defaultBranchName: this.defaultBranchName, - first: MAX_LIST_COUNT, + first: this.maxAgents, last: null, projectPath: this.projectPath, }; diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js index 36e6a065cbf..9fefdf450c4 100644 --- a/app/assets/javascripts/clusters_list/constants.js +++ b/app/assets/javascripts/clusters_list/constants.js @@ -1,4 +1,5 @@ import { __, s__, sprintf } from '~/locale'; +import { helpPagePath } from '~/helpers/help_page_helper'; export const MAX_LIST_COUNT = 25; export const INSTALL_AGENT_MODAL_ID = 'install-agent'; @@ -167,8 +168,41 @@ export const I18N_CLUSTERS_EMPTY_STATE = { buttonText: s__('ClusterIntegration|Connect with a certificate'), }; +export const AGENT_CARD_INFO = { + tabName: 'agent', + title: sprintf(s__('ClusterAgents|%{number} of %{total} Agent based integrations')), + emptyTitle: s__('ClusterAgents|No Agent based integrations'), + tooltip: { + label: s__('ClusterAgents|Recommended'), + title: s__('ClusterAgents|GitLab Agents'), + text: sprintf( + s__( + 'ClusterAgents|GitLab Agents provide an increased level of security when integrating with clusters. %{linkStart}Learn more about the GitLab Kubernetes Agent.%{linkEnd}', + ), + ), + link: helpPagePath('user/clusters/agent/index'), + }, + actionText: s__('ClusterAgents|Install new Agent'), + footerText: sprintf(s__('ClusterAgents|View all %{number} Agent based integrations')), +}; + +export const CERTIFICATE_BASED_CARD_INFO = { + tabName: 'certificate_based', + title: sprintf(s__('ClusterAgents|%{number} of %{total} Certificate based integrations')), + emptyTitle: s__('ClusterAgents|No Certificate based integrations'), + actionText: s__('ClusterAgents|Connect existing cluster'), + footerText: sprintf(s__('ClusterAgents|View all %{number} Certificate based integrations')), +}; + +export const MAX_CLUSTERS_LIST = 6; + export const CLUSTERS_TABS = [ { + title: s__('ClusterAgents|All'), + component: 'ClustersViewAll', + queryParamValue: 'all', + }, + { title: s__('ClusterAgents|Agent'), component: 'agents', queryParamValue: 'agent', @@ -186,3 +220,6 @@ export const CLUSTERS_ACTIONS = { connectWithAgent: s__('ClusterAgents|Connect with Agent'), connectExistingCluster: s__('ClusterAgents|Connect with certificate'), }; + +export const AGENT = 'agent'; +export const CERTIFICATE_BASED = 'certificate_based'; diff --git a/app/assets/javascripts/clusters_list/graphql/cache_update.js b/app/assets/javascripts/clusters_list/graphql/cache_update.js index ce6daecc908..dd633820952 100644 --- a/app/assets/javascripts/clusters_list/graphql/cache_update.js +++ b/app/assets/javascripts/clusters_list/graphql/cache_update.js @@ -17,6 +17,7 @@ export function addAgentToStore(store, createClusterAgent, query, variables) { }; draftData.project.clusterAgents.nodes.push(clusterAgent); + draftData.project.clusterAgents.count += 1; draftData.project.repository.tree.trees.nodes.push(configuration); }); diff --git a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql index 397895b7d01..47b25988877 100644 --- a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql +++ b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql @@ -20,6 +20,8 @@ query getAgents( pageInfo { ...PageInfo } + + count } repository { diff --git a/app/assets/javascripts/clusters_list/store/actions.js b/app/assets/javascripts/clusters_list/store/actions.js index f0f96fd7872..d70b36e63bc 100644 --- a/app/assets/javascripts/clusters_list/store/actions.js +++ b/app/assets/javascripts/clusters_list/store/actions.js @@ -30,7 +30,13 @@ export const fetchClusters = ({ state, commit, dispatch }) => { const poll = new Poll({ resource: { - fetchClusters: (paginatedEndPoint) => axios.get(paginatedEndPoint), + fetchClusters: (paginatedEndPoint) => + axios.get(paginatedEndPoint, { + params: { + page: state.page, + per_page: state.clustersPerPage, + }, + }), }, data: `${state.endpoint}?page=${state.page}`, method: 'fetchClusters', @@ -78,3 +84,7 @@ export const fetchClusters = ({ state, commit, dispatch }) => { export const setPage = ({ commit }, page) => { commit(types.SET_PAGE, page); }; + +export const setClustersPerPage = ({ commit }, limit) => { + commit(types.SET_CLUSTERS_PER_PAGE, limit); +}; diff --git a/app/assets/javascripts/clusters_list/store/mutation_types.js b/app/assets/javascripts/clusters_list/store/mutation_types.js index beb4388c93e..e88d4c74761 100644 --- a/app/assets/javascripts/clusters_list/store/mutation_types.js +++ b/app/assets/javascripts/clusters_list/store/mutation_types.js @@ -2,3 +2,4 @@ export const SET_CLUSTERS_DATA = 'SET_CLUSTERS_DATA'; export const SET_LOADING_CLUSTERS = 'SET_LOADING_CLUSTERS'; export const SET_LOADING_NODES = 'SET_LOADING_NODES'; export const SET_PAGE = 'SET_PAGE'; +export const SET_CLUSTERS_PER_PAGE = 'SET_CLUSTERS_PER_PAGE'; diff --git a/app/assets/javascripts/clusters_list/store/mutations.js b/app/assets/javascripts/clusters_list/store/mutations.js index e5c15ccbd6e..93156c9200f 100644 --- a/app/assets/javascripts/clusters_list/store/mutations.js +++ b/app/assets/javascripts/clusters_list/store/mutations.js @@ -18,4 +18,7 @@ export default { [types.SET_PAGE](state, value) { state.page = Number(value) || 1; }, + [types.SET_CLUSTERS_PER_PAGE](state, value) { + state.clustersPerPage = Number(value) || 1; + }, }; diff --git a/app/assets/javascripts/clusters_list/store/state.js b/app/assets/javascripts/clusters_list/store/state.js index 3dcbf58c8d3..763d7389d0f 100644 --- a/app/assets/javascripts/clusters_list/store/state.js +++ b/app/assets/javascripts/clusters_list/store/state.js @@ -5,7 +5,7 @@ export default (initialState = {}) => ({ endpoint: initialState.endpoint, hasAncestorClusters: false, clusters: [], - clustersPerPage: 0, + clustersPerPage: 20, loadingClusters: true, loadingNodes: true, page: 1, diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb index 39355853d88..712d5f8c6fb 100644 --- a/app/finders/ci/pipelines_finder.rb +++ b/app/finders/ci/pipelines_finder.rb @@ -5,6 +5,13 @@ module Ci attr_reader :project, :pipelines, :params, :current_user ALLOWED_INDEXED_COLUMNS = %w[id status ref updated_at user_id].freeze + ALLOWED_SCOPES = { + RUNNING: 'running', + PENDING: 'pending', + FINISHED: 'finished', + BRANCHES: 'branches', + TAGS: 'tags' + }.freeze def initialize(project, current_user, params = {}) @project = project @@ -65,15 +72,15 @@ module Ci def by_scope(items) case params[:scope] - when 'running' + when ALLOWED_SCOPES[:RUNNING] items.running - when 'pending' + when ALLOWED_SCOPES[:PENDING] items.pending - when 'finished' + when ALLOWED_SCOPES[:FINISHED] items.finished - when 'branches' + when ALLOWED_SCOPES[:BRANCHES] from_ids(ids_for_ref(branches)) - when 'tags' + when ALLOWED_SCOPES[:TAGS] from_ids(ids_for_ref(tags)) else items diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb index 7fb0852b11e..1c01e5e0250 100644 --- a/app/graphql/resolvers/concerns/resolves_pipelines.rb +++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb @@ -9,6 +9,9 @@ module ResolvesPipelines Types::Ci::PipelineStatusEnum, required: false, description: "Filter pipelines by their status." + argument :scope, ::Types::Ci::PipelineScopeEnum, + required: false, + description: 'Filter pipelines by scope.' argument :ref, GraphQL::Types::String, required: false, diff --git a/app/graphql/types/ci/pipeline_scope_enum.rb b/app/graphql/types/ci/pipeline_scope_enum.rb new file mode 100644 index 00000000000..3ce81bc7bf3 --- /dev/null +++ b/app/graphql/types/ci/pipeline_scope_enum.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Types + module Ci + class PipelineScopeEnum < BaseEnum + SCOPES_DESCRIPTION = { + running: 'Pipeline is running.', + pending: 'Pipeline has not started running yet.', + finished: 'Pipeline has completed.', + branches: 'Branches.', + tags: 'Tags.' + }.freeze + + SCOPES_DESCRIPTION.each do |scope, description| + value scope.to_s.upcase, + description: description, + value: scope.to_s + end + end + end +end diff --git a/app/graphql/types/ci/pipeline_status_enum.rb b/app/graphql/types/ci/pipeline_status_enum.rb index 2800454a999..c8e031e18ea 100644 --- a/app/graphql/types/ci/pipeline_status_enum.rb +++ b/app/graphql/types/ci/pipeline_status_enum.rb @@ -3,10 +3,24 @@ module Types module Ci class PipelineStatusEnum < BaseEnum - ::Ci::Pipeline.all_state_names.each do |state_symbol| - value state_symbol.to_s.upcase, - description: "#{::Ci::Pipeline::STATUSES_DESCRIPTION[state_symbol]}.", - value: state_symbol.to_s + STATUSES_DESCRIPTION = { + created: 'Pipeline has been created.', + waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable.', + preparing: 'Pipeline is preparing to run.', + pending: 'Pipeline has not started running yet.', + running: 'Pipeline is running.', + failed: 'At least one stage of the pipeline failed.', + success: 'Pipeline completed successfully.', + canceled: 'Pipeline was canceled before completion.', + skipped: 'Pipeline was skipped.', + manual: 'Pipeline needs to be manually started.', + scheduled: 'Pipeline is scheduled to run.' + }.freeze + + STATUSES_DESCRIPTION.each do |state, description| + value state.to_s.upcase, + description: description, + value: state.to_s end end end diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb index 595315f14ab..5bf5ae51ec8 100644 --- a/app/models/ci/trigger.rb +++ b/app/models/ci/trigger.rb @@ -3,6 +3,10 @@ module Ci class Trigger < Ci::ApplicationRecord include Presentable + include Limitable + + self.limit_name = 'pipeline_triggers' + self.limit_scope = :project belongs_to :project belongs_to :owner, class_name: "User" diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb index 8d715279da8..ccaccec3b6b 100644 --- a/app/models/concerns/ci/has_status.rb +++ b/app/models/concerns/ci/has_status.rb @@ -14,21 +14,8 @@ module Ci PASSED_WITH_WARNINGS_STATUSES = %w[failed canceled].to_set.freeze EXCLUDE_IGNORED_STATUSES = %w[manual failed canceled].to_set.freeze STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3, - failed: 4, canceled: 5, skipped: 6, manual: 7, - scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze - STATUSES_DESCRIPTION = { - created: 'Pipeline has been created', - waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable', - preparing: 'Pipeline is preparing to run', - pending: 'Pipeline has not started running yet', - running: 'Pipeline is running', - failed: 'At least one stage of the pipeline failed', - success: 'Pipeline completed successfully', - canceled: 'Pipeline was canceled before completion', - skipped: 'Pipeline was skipped', - manual: 'Pipeline needs to be manually started', - scheduled: 'Pipeline is scheduled to run' - }.freeze + failed: 4, canceled: 5, skipped: 6, manual: 7, + scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze UnknownStatusError = Class.new(StandardError) |