Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7118851f02
commit
b9b58dba70
|
@ -1001,6 +1001,7 @@
|
|||
- <<: *if-merge-request-targeting-stable-branch
|
||||
allow_failure: true
|
||||
- <<: *if-ruby3-branch
|
||||
allow_failure: true
|
||||
- <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
|
||||
changes: *feature-flag-development-config-patterns
|
||||
when: manual
|
||||
|
|
|
@ -19,9 +19,14 @@ export const I18N = {
|
|||
),
|
||||
disallowForcePushDescription: s__('BranchRules|Force push is not allowed.'),
|
||||
approvalsTitle: s__('BranchRules|Approvals'),
|
||||
manageApprovalsLinkTitle: s__('BranchRules|Manage in Merge Request Approvals'),
|
||||
approvalsDescription: s__(
|
||||
'BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}',
|
||||
),
|
||||
statusChecksTitle: s__('BranchRules|Status checks'),
|
||||
allowedToPushHeader: s__('BranchRules|Allowed to push (%{total})'),
|
||||
allowedToMergeHeader: s__('BranchRules|Allowed to merge (%{total})'),
|
||||
approvalsHeader: s__('BranchRules|Required approvals (%{total})'),
|
||||
noData: s__('BranchRules|No data to display'),
|
||||
};
|
||||
|
||||
|
@ -33,3 +38,5 @@ export const WILDCARDS_HELP_PATH =
|
|||
'user/project/protected_branches#configure-multiple-protected-branches-by-using-a-wildcard';
|
||||
|
||||
export const PROTECTED_BRANCHES_HELP_PATH = 'user/project/protected_branches';
|
||||
|
||||
export const APPROVALS_HELP_PATH = 'user/project/merge_requests/approvals/index.md';
|
||||
|
|
|
@ -11,16 +11,19 @@ import {
|
|||
BRANCH_PARAM_NAME,
|
||||
WILDCARDS_HELP_PATH,
|
||||
PROTECTED_BRANCHES_HELP_PATH,
|
||||
APPROVALS_HELP_PATH,
|
||||
} from './constants';
|
||||
|
||||
const wildcardsHelpDocLink = helpPagePath(WILDCARDS_HELP_PATH);
|
||||
const protectedBranchesHelpDocLink = helpPagePath(PROTECTED_BRANCHES_HELP_PATH);
|
||||
const approvalsHelpDocLink = helpPagePath(APPROVALS_HELP_PATH);
|
||||
|
||||
export default {
|
||||
name: 'RuleView',
|
||||
i18n: I18N,
|
||||
wildcardsHelpDocLink,
|
||||
protectedBranchesHelpDocLink,
|
||||
approvalsHelpDocLink,
|
||||
components: { Protection, GlSprintf, GlLink, GlLoadingIcon },
|
||||
inject: {
|
||||
projectPath: {
|
||||
|
@ -29,6 +32,9 @@ export default {
|
|||
protectedBranchesPath: {
|
||||
default: '',
|
||||
},
|
||||
approvalRulesPath: {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
project: {
|
||||
|
@ -48,7 +54,9 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
branch: getParameterByName(BRANCH_PARAM_NAME),
|
||||
branchProtection: {},
|
||||
branchProtection: {
|
||||
approvalRules: {},
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -75,6 +83,15 @@ export default {
|
|||
total: this.pushAccessLevels.total,
|
||||
});
|
||||
},
|
||||
approvalsHeader() {
|
||||
const total = this.approvals.reduce(
|
||||
(sum, { approvalsRequired }) => sum + approvalsRequired,
|
||||
0,
|
||||
);
|
||||
return sprintf(this.$options.i18n.approvalsHeader, {
|
||||
total,
|
||||
});
|
||||
},
|
||||
allBranches() {
|
||||
return this.branch === ALL_BRANCHES_WILDCARD;
|
||||
},
|
||||
|
@ -86,6 +103,9 @@ export default {
|
|||
? this.$options.i18n.targetBranch
|
||||
: this.$options.i18n.branchNameOrPattern;
|
||||
},
|
||||
approvals() {
|
||||
return this.branchProtection?.approvalRules?.nodes || [];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getAccessLevels(accessLevels = {}) {
|
||||
|
@ -164,7 +184,22 @@ export default {
|
|||
/>
|
||||
|
||||
<!-- Approvals -->
|
||||
<!-- Follow-up: add approval section (https://gitlab.com/gitlab-org/gitlab/-/issues/372362) -->
|
||||
<h4 class="gl-mb-1 gl-mt-5">{{ $options.i18n.approvalsTitle }}</h4>
|
||||
<gl-sprintf :message="$options.i18n.approvalsDescription">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="$options.approvalsHelpDocLink">
|
||||
{{ content }}
|
||||
</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
|
||||
<protection
|
||||
class="gl-mt-3"
|
||||
:header="approvalsHeader"
|
||||
:header-link-title="$options.i18n.manageApprovalsLinkTitle"
|
||||
:header-link-href="approvalRulesPath"
|
||||
:approvals="approvals"
|
||||
/>
|
||||
|
||||
<!-- Status checks -->
|
||||
<!-- Follow-up: add status checks section (https://gitlab.com/gitlab-org/gitlab/-/issues/372362) -->
|
||||
|
|
|
@ -41,6 +41,11 @@ export default {
|
|||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
approvals: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showUsersDivider() {
|
||||
|
@ -80,5 +85,15 @@ export default {
|
|||
:title="$options.i18n.groupsTitle"
|
||||
:access-levels="groups"
|
||||
/>
|
||||
|
||||
<!-- Approvals -->
|
||||
<protection-row
|
||||
v-for="(approval, index) in approvals"
|
||||
:key="approval.name"
|
||||
:show-divider="index !== 0"
|
||||
:title="approval.name"
|
||||
:users="approval.eligibleApprovers.nodes"
|
||||
:approvals-required="approval.approvalsRequired"
|
||||
/>
|
||||
</gl-card>
|
||||
</template>
|
||||
|
|
|
@ -36,6 +36,11 @@ export default {
|
|||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
approvalsRequired: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
avatarBadgeSrOnlyText() {
|
||||
|
@ -48,6 +53,11 @@ export default {
|
|||
commaSeparateList() {
|
||||
return this.accessLevels.length > 1;
|
||||
},
|
||||
approvalsRequiredTitle() {
|
||||
return this.approvalsRequired
|
||||
? n__('%d approval required', '%d approvals required', this.approvalsRequired)
|
||||
: null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -57,34 +67,44 @@ export default {
|
|||
class="gl-display-flex gl-align-items-center gl-border-gray-100 gl-mb-4 gl-pt-4"
|
||||
:class="{ 'gl-border-t-solid': showDivider }"
|
||||
>
|
||||
<div class="gl-mr-7">{{ title }}</div>
|
||||
<div class="gl-display-flex gl-w-half gl-justify-content-space-between">
|
||||
<div class="gl-mr-7 gl-w-quarter">{{ title }}</div>
|
||||
|
||||
<gl-avatars-inline
|
||||
v-if="users.length"
|
||||
:avatars="users"
|
||||
:collapsed="true"
|
||||
:max-visible="$options.MAX_VISIBLE_AVATARS"
|
||||
:avatar-size="$options.AVATAR_SIZE"
|
||||
badge-tooltip-prop="name"
|
||||
:badge-tooltip-max-chars="$options.AVATAR_TOOLTIP_MAX_CHARS"
|
||||
:badge-sr-only-text="avatarBadgeSrOnlyText"
|
||||
>
|
||||
<template #avatar="{ avatar }">
|
||||
<gl-avatar-link
|
||||
:key="avatar.username"
|
||||
v-gl-tooltip
|
||||
target="_blank"
|
||||
:href="avatar.webUrl"
|
||||
:title="avatar.name"
|
||||
>
|
||||
<gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="$options.AVATAR_SIZE" />
|
||||
</gl-avatar-link>
|
||||
</template>
|
||||
</gl-avatars-inline>
|
||||
<gl-avatars-inline
|
||||
v-if="users.length"
|
||||
class="gl-w-quarter!"
|
||||
:avatars="users"
|
||||
:collapsed="true"
|
||||
:max-visible="$options.MAX_VISIBLE_AVATARS"
|
||||
:avatar-size="$options.AVATAR_SIZE"
|
||||
badge-tooltip-prop="name"
|
||||
:badge-tooltip-max-chars="$options.AVATAR_TOOLTIP_MAX_CHARS"
|
||||
:badge-sr-only-text="avatarBadgeSrOnlyText"
|
||||
>
|
||||
<template #avatar="{ avatar }">
|
||||
<gl-avatar-link
|
||||
:key="avatar.username"
|
||||
v-gl-tooltip
|
||||
target="_blank"
|
||||
:href="avatar.webUrl"
|
||||
:title="avatar.name"
|
||||
>
|
||||
<gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="$options.AVATAR_SIZE" />
|
||||
</gl-avatar-link>
|
||||
</template>
|
||||
</gl-avatars-inline>
|
||||
|
||||
<div v-for="(item, index) in accessLevels" :key="index" data-testid="access-level">
|
||||
<span v-if="commaSeparateList && index > 0" data-testid="comma-separator">,</span>
|
||||
{{ item.accessLevelDescription }}
|
||||
<div
|
||||
v-for="(item, index) in accessLevels"
|
||||
:key="index"
|
||||
data-testid="access-level"
|
||||
class="gl-w-quarter"
|
||||
>
|
||||
<span v-if="commaSeparateList && index > 0" data-testid="comma-separator">,</span>
|
||||
{{ item.accessLevelDescription }}
|
||||
</div>
|
||||
|
||||
<div class="gl-ml-7 gl-w-quarter">{{ approvalsRequiredTitle }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function mountBranchRules(el) {
|
|||
defaultClient: createDefaultClient(),
|
||||
});
|
||||
|
||||
const { projectPath, protectedBranchesPath } = el.dataset;
|
||||
const { projectPath, protectedBranchesPath, approvalRulesPath } = el.dataset;
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
|
@ -22,6 +22,7 @@ export default function mountBranchRules(el) {
|
|||
provide: {
|
||||
projectPath,
|
||||
protectedBranchesPath,
|
||||
approvalRulesPath,
|
||||
},
|
||||
render(h) {
|
||||
return h(View);
|
||||
|
|
|
@ -85,7 +85,7 @@ export default {
|
|||
return this.loading || this.$apollo.queries.issuable.loading;
|
||||
},
|
||||
canUpdate() {
|
||||
return this.issuable.userPermissions?.updateMergeRequest || false;
|
||||
return this.issuable.userPermissions?.adminMergeRequest || false;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
|
|
|
@ -53,6 +53,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
allowMultipleScopedLabels: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
@ -164,6 +169,7 @@ export default {
|
|||
allowLabelCreate: this.allowLabelCreate,
|
||||
allowMultiselect: this.allowMultiselect,
|
||||
allowScopedLabels: this.allowScopedLabels,
|
||||
allowMultipleScopedLabels: this.allowMultipleScopedLabels,
|
||||
dropdownButtonText: this.dropdownButtonText,
|
||||
selectedLabels: this.selectedLabels,
|
||||
labelsFetchPath: this.labelsFetchPath,
|
||||
|
|
|
@ -94,14 +94,13 @@ export default {
|
|||
candidateLabel.indeterminate = false;
|
||||
}
|
||||
|
||||
if (isScopedLabel(candidateLabel)) {
|
||||
if (isScopedLabel(candidateLabel) && !state.allowMultipleScopedLabels) {
|
||||
const currentActiveScopedLabel = state.labels.find(
|
||||
({ set, title }) =>
|
||||
set &&
|
||||
title !== candidateLabel.title &&
|
||||
scopedLabelKey({ title }) === scopedLabelKey(candidateLabel),
|
||||
);
|
||||
|
||||
if (currentActiveScopedLabel) {
|
||||
currentActiveScopedLabel.set = false;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
|
|||
}
|
||||
}
|
||||
userPermissions {
|
||||
updateMergeRequest
|
||||
adminMergeRequest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -455,8 +455,7 @@ module Ci
|
|||
|
||||
def prevent_rollback_deployment?
|
||||
strong_memoize(:prevent_rollback_deployment) do
|
||||
Feature.enabled?(:prevent_outdated_deployment_jobs, project) &&
|
||||
starts_environment? &&
|
||||
starts_environment? &&
|
||||
project.ci_forward_deployment_enabled? &&
|
||||
deployment&.older_than_last_successful_deployment?
|
||||
end
|
||||
|
|
|
@ -105,6 +105,7 @@ class Deployment < ApplicationRecord
|
|||
|
||||
after_transition any => :running do |deployment|
|
||||
next unless deployment.project.ci_forward_deployment_enabled?
|
||||
next if Feature.enabled?(:prevent_outdated_deployment_jobs, deployment.project)
|
||||
|
||||
deployment.run_after_commit do
|
||||
Deployments::DropOlderDeploymentsWorker.perform_async(id)
|
||||
|
|
|
@ -14,9 +14,9 @@ class Namespace::AggregationSchedule < ApplicationRecord
|
|||
|
||||
def self.default_lease_timeout
|
||||
if Feature.enabled?(:remove_namespace_aggregator_delay)
|
||||
1.hour.to_i
|
||||
30.minutes.to_i
|
||||
else
|
||||
1.5.hours.to_i
|
||||
1.hour.to_i
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ module Ci
|
|||
end
|
||||
|
||||
def enqueue(build)
|
||||
return build.drop!(:failed_outdated_deployment_job) if build.prevent_rollback_deployment?
|
||||
|
||||
build.enqueue
|
||||
end
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
%h3.gl-mb-5= s_('BranchRules|Branch rules details')
|
||||
|
||||
#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings') } }
|
||||
#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings'), approval_rules_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-approval-settings') } }
|
||||
|
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.work_items.users_updating_work_item_iteration_monthly
|
||||
description: Unique users updating a work item's iteration
|
||||
product_section: team planning
|
||||
product_stage: dev
|
||||
product_group: plan
|
||||
product_category: project_management
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.5"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98539
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- users_updating_work_item_iteration
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- premium
|
||||
- ultimate
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -21,6 +21,7 @@ options:
|
|||
- users_updating_work_item_title
|
||||
- users_updating_work_item_dates
|
||||
- users_updating_work_item_labels
|
||||
- users_updating_work_item_iteration
|
||||
data_category: optional
|
||||
distribution:
|
||||
- ce
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.work_items.users_updating_work_item_iteration_weekly
|
||||
description: Unique users updating a work item's iteration
|
||||
product_section: team planning
|
||||
product_stage: dev
|
||||
product_group: plan
|
||||
product_category: project_management
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.5"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98539
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- users_updating_work_item_iteration
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- premium
|
||||
- ultimate
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddTempIndexToProjectFeaturesWhereReleasesAccessLevelGtRepository < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'tmp_idx_project_features_on_releases_al_and_repo_al_partial'
|
||||
|
||||
# Temporary index to be removed in 15.6 https://gitlab.com/gitlab-org/gitlab/-/issues/377915
|
||||
def up
|
||||
add_concurrent_index :project_features,
|
||||
[:releases_access_level, :repository_access_level],
|
||||
name: INDEX_NAME,
|
||||
where: 'releases_access_level > repository_access_level'
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :project_features, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PopulateReleasesAccessLevelFromRepository < Gitlab::Database::Migration[2.0]
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
update_column_in_batches(
|
||||
:project_features,
|
||||
:releases_access_level,
|
||||
Arel.sql('repository_access_level')
|
||||
) do |table, query|
|
||||
query.where(table[:releases_access_level].gt(table[:repository_access_level]))
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
bc05939dc672c078161cd9b7dbd7f92601edb6888a77c62adb014964e30c6ae8
|
|
@ -0,0 +1 @@
|
|||
58ee7f51a0da4ee4ec471d4492106d1fc3124419ba83591913967d6bd38105e5
|
|
@ -30993,6 +30993,8 @@ CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, t
|
|||
|
||||
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
|
||||
|
||||
CREATE INDEX tmp_idx_project_features_on_releases_al_and_repo_al_partial ON project_features USING btree (releases_access_level, repository_access_level) WHERE (releases_access_level > repository_access_level);
|
||||
|
||||
CREATE INDEX tmp_idx_vulnerabilities_on_id_where_report_type_7_99 ON vulnerabilities USING btree (id) WHERE (report_type = ANY (ARRAY[7, 99]));
|
||||
|
||||
CREATE INDEX tmp_index_approval_merge_request_rules_on_report_type_equal_one ON approval_merge_request_rules USING btree (id, report_type) WHERE (report_type = 1);
|
||||
|
|
|
@ -248,7 +248,6 @@ GitLab SaaS runners have different cost factors, depending on the runner type (L
|
|||
| Linux OS + Docker executor| Small |1|
|
||||
| Linux OS + Docker executor| Medium |2|
|
||||
| Linux OS + Docker executor| Large |3|
|
||||
| macOS + shell executor | Large| 6 |
|
||||
|
||||
### Monthly reset of CI/CD minutes
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ To add a pipeline schedule:
|
|||
These variables are available only when the scheduled pipeline runs,
|
||||
and not in any other pipeline run.
|
||||
|
||||
If the project already has the [maximum number of pipeline schedules](../../administration/instance_limits.md#number-of-pipeline-schedules),
|
||||
you must delete unused schedules before you can add another.
|
||||
|
||||
## Edit a pipeline schedule
|
||||
|
||||
> Introduced in GitLab 14.8, only a pipeline schedule owner can edit the schedule.
|
||||
|
|
|
@ -95,9 +95,14 @@ after a given period of time.
|
|||
|
||||
The following are example projects that demonstrate Review App configuration:
|
||||
|
||||
- [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx).
|
||||
- [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift).
|
||||
- [HashiCorp Nomad](https://gitlab.com/gitlab-examples/review-apps-nomad).
|
||||
| Project | Configuration file |
|
||||
|-------------------------------------------------------------------------|--------------------|
|
||||
| [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-nginx/-/blob/b9c1f6a8a7a0dfd9c8784cbf233c0a7b6a28ff27/.gitlab-ci.yml#L20) |
|
||||
| [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-openshift/-/blob/82ebd572334793deef2d5ddc379f38942f3488be/.gitlab-ci.yml#L42) |
|
||||
| [HashiCorp Nomad](https://gitlab.com/gitlab-examples/review-apps-nomad) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-examples/review-apps-nomad/-/blob/ca372c778be7aaed5e82d3be24e98c3f10a465af/.gitlab-ci.yml#L110) |
|
||||
| [GitLab Documentation](https://gitlab.com/gitlab-org/gitlab-docs/) | [`build-and-deploy.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/a715625496303cbd90ff89f3d3658ea8d36ce0f3/.gitlab/ci/build-and-deploy.gitlab-ci.yml#L59) |
|
||||
| [`https://about.gitlab.com/`](https://gitlab.com/gitlab-com/www-gitlab-com/) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/6ffcdc3cb9af2abed490cbe5b7417df3e83cd76c/.gitlab-ci.yml#L332) |
|
||||
| [GitLab Insights](https://gitlab.com/gitlab-org/gitlab-insights/) | [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-insights/-/blob/9e63f44ac2a5a4defc965d0d61d411a768e20546/.gitlab-ci.yml#L234) |
|
||||
|
||||
Other examples of Review Apps:
|
||||
|
||||
|
|
|
@ -19,3 +19,11 @@
|
|||
redis_slot: users
|
||||
aggregation: weekly
|
||||
feature_flag: track_work_items_activity
|
||||
- name: users_updating_work_item_iteration
|
||||
# The event tracks an EE feature.
|
||||
# It's added here so it can be aggregated into the CE/EE 'OR' aggregate metrics.
|
||||
# It will report 0 for CE instances and should not be used with 'AND' aggregators.
|
||||
category: work_items
|
||||
redis_slot: users
|
||||
aggregation: weekly
|
||||
feature_flag: track_work_items_activity
|
||||
|
|
|
@ -143,6 +143,11 @@ msgid_plural "%d additional users"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d approval required"
|
||||
msgid_plural "%d approvals required"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d approver"
|
||||
msgid_plural "%d approvers"
|
||||
msgstr[0] ""
|
||||
|
@ -6826,6 +6831,9 @@ msgstr ""
|
|||
msgid "BranchRules|Approvals"
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Approvals to ensure separation of duties for new merge requests. %{linkStart}Lean more.%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Branch"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6853,6 +6861,9 @@ msgstr ""
|
|||
msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Manage in Merge Request Approvals"
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Manage in Protected Branches"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6874,6 +6885,9 @@ msgstr ""
|
|||
msgid "BranchRules|Require approval from code owners."
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Required approvals (%{total})"
|
||||
msgstr ""
|
||||
|
||||
msgid "BranchRules|Roles"
|
||||
msgstr ""
|
||||
|
||||
|
@ -9841,6 +9855,9 @@ msgstr ""
|
|||
msgid "Complete verification to sign up."
|
||||
msgstr ""
|
||||
|
||||
msgid "Complete with errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
|
@ -12572,6 +12589,9 @@ msgstr ""
|
|||
msgid "Decrease"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default - Never run"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default CI/CD configuration file"
|
||||
msgstr ""
|
||||
|
||||
|
@ -21985,6 +22005,9 @@ msgstr ""
|
|||
msgid "Invalid yaml"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalidated"
|
||||
msgstr ""
|
||||
|
||||
msgid "Investigate vulnerability: %{title}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -30441,6 +30464,27 @@ msgstr ""
|
|||
msgid "Pre-defined push rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|(optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|Last run %{timeAgo} in pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|Pre-scan verification"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|Started %{timeAgo} in pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|Test your configuration and identify potential errors before running a full scan."
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|Verify configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "PreScanVerification|View results"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ gem 'rspec-retry', '~> 0.6.1', require: 'rspec/retry'
|
|||
gem 'rspec_junit_formatter', '~> 0.4.1'
|
||||
gem 'faker', '~> 2.19', '>= 2.19.0'
|
||||
gem 'knapsack', '~> 4.0'
|
||||
gem 'parallel_tests', '~> 2.29'
|
||||
gem 'parallel_tests', '~> 2.32'
|
||||
gem 'rotp', '~> 3.1.0'
|
||||
gem 'timecop', '~> 0.9.1'
|
||||
gem 'timecop', '~> 0.9.5'
|
||||
gem 'parallel', '~> 1.19'
|
||||
gem 'rainbow', '~> 3.0.0'
|
||||
gem 'rspec-parameterized', '~> 0.4.2'
|
||||
|
@ -45,5 +45,5 @@ gem 'deprecation_toolkit', '~> 1.5.1', require: false
|
|||
|
||||
group :development do
|
||||
gem 'pry-byebug', '~> 3.5.1', platform: :mri
|
||||
gem "ruby-debug-ide", "~> 0.7.0"
|
||||
gem "ruby-debug-ide", "~> 0.7.3"
|
||||
end
|
||||
|
|
|
@ -196,7 +196,7 @@ GEM
|
|||
oj (3.13.11)
|
||||
os (1.1.4)
|
||||
parallel (1.19.2)
|
||||
parallel_tests (2.29.0)
|
||||
parallel_tests (2.32.0)
|
||||
parallel
|
||||
parser (3.1.2.1)
|
||||
ast (~> 2.4.1)
|
||||
|
@ -255,7 +255,7 @@ GEM
|
|||
rspec-support (3.10.2)
|
||||
rspec_junit_formatter (0.4.1)
|
||||
rspec-core (>= 2, < 4, != 2.12.0)
|
||||
ruby-debug-ide (0.7.2)
|
||||
ruby-debug-ide (0.7.3)
|
||||
rake (>= 0.8.1)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
|
@ -277,7 +277,7 @@ GEM
|
|||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
thread_safe (0.3.6)
|
||||
timecop (0.9.1)
|
||||
timecop (0.9.5)
|
||||
trailblazer-option (0.1.2)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
@ -332,7 +332,7 @@ DEPENDENCIES
|
|||
nokogiri (~> 1.13, >= 1.13.8)
|
||||
octokit (~> 5.6.1)
|
||||
parallel (~> 1.19)
|
||||
parallel_tests (~> 2.29)
|
||||
parallel_tests (~> 2.32)
|
||||
pry-byebug (~> 3.5.1)
|
||||
rainbow (~> 3.0.0)
|
||||
rake (~> 13)
|
||||
|
@ -342,11 +342,11 @@ DEPENDENCIES
|
|||
rspec-parameterized (~> 0.4.2)
|
||||
rspec-retry (~> 0.6.1)
|
||||
rspec_junit_formatter (~> 0.4.1)
|
||||
ruby-debug-ide (~> 0.7.0)
|
||||
ruby-debug-ide (~> 0.7.3)
|
||||
selenium-webdriver (~> 4.0)
|
||||
slack-notifier (~> 2.4)
|
||||
terminal-table (~> 3.0.0)
|
||||
timecop (~> 0.9.1)
|
||||
timecop (~> 0.9.5)
|
||||
warning (~> 1.3)
|
||||
webdrivers (~> 5.2)
|
||||
zeitwerk (~> 2.4)
|
||||
|
|
|
@ -31,6 +31,13 @@ class PipelineFailedJobs
|
|||
failed_jobs << job
|
||||
end
|
||||
|
||||
client.pipeline_bridges(project, pipeline_id, scope: 'failed', per_page: 100).auto_paginate do |job|
|
||||
next if exclude_allowed_to_fail_jobs && job.allow_failure
|
||||
|
||||
job.web_url = job.downstream_pipeline.web_url # job.web_url is linking to an invalid page
|
||||
failed_jobs << job
|
||||
end
|
||||
|
||||
failed_jobs
|
||||
end
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ describe('View branch rules', () => {
|
|||
let fakeApollo;
|
||||
const projectPath = 'test/testing';
|
||||
const protectedBranchesPath = 'protected/branches';
|
||||
const approvalRulesPath = 'approval/rules';
|
||||
const branchProtectionsMockRequestHandler = jest
|
||||
.fn()
|
||||
.mockResolvedValue(branchProtectionsMockResponse);
|
||||
|
@ -42,7 +43,7 @@ describe('View branch rules', () => {
|
|||
|
||||
wrapper = shallowMountExtended(RuleView, {
|
||||
apolloProvider: fakeApollo,
|
||||
provide: { projectPath, protectedBranchesPath },
|
||||
provide: { projectPath, protectedBranchesPath, approvalRulesPath },
|
||||
});
|
||||
|
||||
await waitForPromises();
|
||||
|
@ -57,6 +58,7 @@ describe('View branch rules', () => {
|
|||
const findBranchProtectionTitle = () => wrapper.findByText(I18N.protectBranchTitle);
|
||||
const findBranchProtections = () => wrapper.findAllComponents(Protection);
|
||||
const findForcePushTitle = () => wrapper.findByText(I18N.allowForcePushDescription);
|
||||
const findApprovalsTitle = () => wrapper.findByText(I18N.approvalsTitle);
|
||||
|
||||
it('gets the branch param from url and renders it in the view', () => {
|
||||
expect(util.getParameterByName).toHaveBeenCalledWith('branch');
|
||||
|
@ -98,4 +100,14 @@ describe('View branch rules', () => {
|
|||
...protectionMockProps,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a branch protection component for approvals', () => {
|
||||
expect(findApprovalsTitle().exists()).toBe(true);
|
||||
|
||||
expect(findBranchProtections().at(2).props()).toMatchObject({
|
||||
header: sprintf(I18N.approvalsHeader, { total: 0 }),
|
||||
headerLinkHref: approvalRulesPath,
|
||||
headerLinkTitle: I18N.manageApprovalsLinkTitle,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -36,6 +36,8 @@ const accessLevelsMock = [
|
|||
{ accessLevelDescription: 'Maintainer' },
|
||||
];
|
||||
|
||||
const approvalsRequired = 3;
|
||||
|
||||
const groupsMock = [{ name: 'test_group_1' }, { name: 'test_group_2' }];
|
||||
|
||||
export const protectionPropsMock = {
|
||||
|
@ -45,12 +47,20 @@ export const protectionPropsMock = {
|
|||
roles: accessLevelsMock,
|
||||
users: usersMock,
|
||||
groups: groupsMock,
|
||||
approvals: [
|
||||
{
|
||||
name: 'test',
|
||||
eligibleApprovers: { nodes: usersMock },
|
||||
approvalsRequired,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const protectionRowPropsMock = {
|
||||
title: 'Test title',
|
||||
users: usersMock,
|
||||
accessLevels: accessLevelsMock,
|
||||
approvalsRequired,
|
||||
};
|
||||
|
||||
export const accessLevelsMockResponse = [
|
||||
|
|
|
@ -25,6 +25,8 @@ describe('Branch rule protection row', () => {
|
|||
const findAvatarLinks = () => wrapper.findAllComponents(GlAvatarLink);
|
||||
const findAvatars = () => wrapper.findAllComponents(GlAvatar);
|
||||
const findAccessLevels = () => wrapper.findAllByTestId('access-level');
|
||||
const findApprovalsRequired = () =>
|
||||
wrapper.findByText(`${protectionRowPropsMock.approvalsRequired} approvals required`);
|
||||
|
||||
it('renders a title', () => {
|
||||
expect(findTitle().exists()).toBe(true);
|
||||
|
@ -62,4 +64,8 @@ describe('Branch rule protection row', () => {
|
|||
protectionRowPropsMock.accessLevels[1].accessLevelDescription,
|
||||
);
|
||||
});
|
||||
|
||||
it('renders the number of approvals required', () => {
|
||||
expect(findApprovalsRequired().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -56,4 +56,13 @@ describe('Branch rule protection', () => {
|
|||
title: i18n.groupsTitle,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a protection row for approvals', () => {
|
||||
const approval = protectionPropsMock.approvals[0];
|
||||
expect(findProtectionRows().at(3).props()).toMatchObject({
|
||||
title: approval.name,
|
||||
users: approval.eligibleApprovers.nodes,
|
||||
approvalsRequired: approval.approvalsRequired,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -193,6 +193,16 @@ describe('LabelsSelect Mutations', () => {
|
|||
expect(state.labels[l.id - 1].set).toBe(false);
|
||||
});
|
||||
});
|
||||
it('allows selection of multiple scoped labels', () => {
|
||||
const state = { labels: cloneDeep(labels), allowMultipleScopedLabels: true };
|
||||
|
||||
mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: labels[4].id }] });
|
||||
mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: labels[5].id }] });
|
||||
|
||||
expect(state.labels[4].set).toBe(true);
|
||||
expect(state.labels[5].set).toBe(true);
|
||||
expect(state.labels[6].set).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`${types.UPDATE_LABELS_SET_STATE}`, () => {
|
||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::WorkItemsActivityAggreg
|
|||
let(:metric_definition) do
|
||||
{
|
||||
data_source: 'redis_hll',
|
||||
time_frame: '7d',
|
||||
time_frame: time_frame,
|
||||
options: {
|
||||
aggregate: {
|
||||
operator: 'OR'
|
||||
|
@ -15,6 +15,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::WorkItemsActivityAggreg
|
|||
users_creating_work_items
|
||||
users_updating_work_item_title
|
||||
users_updating_work_item_dates
|
||||
users_updating_work_item_iteration
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -24,31 +25,36 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::WorkItemsActivityAggreg
|
|||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
describe '#available?' do
|
||||
it 'returns false without track_work_items_activity feature' do
|
||||
stub_feature_flags(track_work_items_activity: false)
|
||||
where(:time_frame) { [['28d'], ['7d']] }
|
||||
|
||||
expect(described_class.new(metric_definition).available?).to eq(false)
|
||||
with_them do
|
||||
describe '#available?' do
|
||||
it 'returns false without track_work_items_activity feature' do
|
||||
stub_feature_flags(track_work_items_activity: false)
|
||||
|
||||
expect(described_class.new(metric_definition).available?).to eq(false)
|
||||
end
|
||||
|
||||
it 'returns true with track_work_items_activity feature' do
|
||||
stub_feature_flags(track_work_items_activity: true)
|
||||
|
||||
expect(described_class.new(metric_definition).available?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns true with track_work_items_activity feature' do
|
||||
stub_feature_flags(track_work_items_activity: true)
|
||||
describe '#value', :clean_gitlab_redis_shared_state do
|
||||
let(:counter) { Gitlab::UsageDataCounters::HLLRedisCounter }
|
||||
|
||||
expect(described_class.new(metric_definition).available?).to eq(true)
|
||||
end
|
||||
end
|
||||
before do
|
||||
counter.track_event(:users_creating_work_items, values: 1, time: 1.week.ago)
|
||||
counter.track_event(:users_updating_work_item_title, values: 1, time: 1.week.ago)
|
||||
counter.track_event(:users_updating_work_item_dates, values: 2, time: 1.week.ago)
|
||||
counter.track_event(:users_updating_work_item_iteration, values: 2, time: 1.week.ago)
|
||||
end
|
||||
|
||||
describe '#value', :clean_gitlab_redis_shared_state do
|
||||
let(:counter) { Gitlab::UsageDataCounters::HLLRedisCounter }
|
||||
|
||||
before do
|
||||
counter.track_event(:users_creating_work_items, values: 1, time: 1.week.ago)
|
||||
counter.track_event(:users_updating_work_item_title, values: 1, time: 1.week.ago)
|
||||
counter.track_event(:users_updating_work_item_dates, values: 2, time: 1.week.ago)
|
||||
end
|
||||
|
||||
it 'has correct value' do
|
||||
expect(described_class.new(metric_definition).value).to eq 2
|
||||
it 'has correct value' do
|
||||
expect(described_class.new(metric_definition).value).to eq 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require_migration!
|
||||
|
||||
RSpec.describe PopulateReleasesAccessLevelFromRepository, :migration do
|
||||
let(:projects) { table(:projects) }
|
||||
let(:groups) { table(:namespaces) }
|
||||
let(:project_features) { table(:project_features) }
|
||||
|
||||
let(:group) { groups.create!(name: 'test-group', path: 'test-group') }
|
||||
let(:project) { projects.create!(namespace_id: group.id, project_namespace_id: group.id) }
|
||||
let(:project_feature) do
|
||||
project_features.create!(project_id: project.id, pages_access_level: 20, **project_feature_attributes)
|
||||
end
|
||||
|
||||
# repository_access_level and releases_access_level default to ENABLED
|
||||
describe '#up' do
|
||||
context 'when releases_access_level is greater than repository_access_level' do
|
||||
let(:project_feature_attributes) { { repository_access_level: ProjectFeature::PRIVATE } }
|
||||
|
||||
it 'reduces releases_access_level to match repository_access_level' do
|
||||
expect { migrate! }.to change { project_feature.reload.releases_access_level }
|
||||
.from(ProjectFeature::ENABLED)
|
||||
.to(ProjectFeature::PRIVATE)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when releases_access_level is less than repository_access_level' do
|
||||
let(:project_feature_attributes) { { releases_access_level: ProjectFeature::DISABLED } }
|
||||
|
||||
it 'does not change releases_access_level' do
|
||||
expect { migrate! }.not_to change { project_feature.reload.releases_access_level }
|
||||
.from(ProjectFeature::DISABLED)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -632,15 +632,6 @@ RSpec.describe Ci::Build do
|
|||
it { expect(subject).to be_falsey }
|
||||
end
|
||||
|
||||
context 'when prevent_outdated_deployment_jobs FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(prevent_outdated_deployment_jobs: false)
|
||||
expect(build.deployment).not_to receive(:rollback?)
|
||||
end
|
||||
|
||||
it { expect(subject).to be_falsey }
|
||||
end
|
||||
|
||||
context 'when build can prevent rollback deployment' do
|
||||
before do
|
||||
expect(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(true)
|
||||
|
|
|
@ -171,11 +171,22 @@ RSpec.describe Deployment do
|
|||
end
|
||||
|
||||
it 'executes Deployments::DropOlderDeploymentsWorker asynchronously' do
|
||||
stub_feature_flags(prevent_outdated_deployment_jobs: false)
|
||||
|
||||
expect(Deployments::DropOlderDeploymentsWorker)
|
||||
.to receive(:perform_async).once.with(deployment.id)
|
||||
|
||||
deployment.run!
|
||||
end
|
||||
|
||||
it 'does not execute Deployments::DropOlderDeploymentsWorker when FF enabled' do
|
||||
stub_feature_flags(prevent_outdated_deployment_jobs: true)
|
||||
|
||||
expect(Deployments::DropOlderDeploymentsWorker)
|
||||
.not_to receive(:perform_async).with(deployment.id)
|
||||
|
||||
deployment.run!
|
||||
end
|
||||
end
|
||||
|
||||
context 'when deployment succeeded' do
|
||||
|
|
|
@ -12,14 +12,14 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state,
|
|||
describe "#default_lease_timeout" do
|
||||
subject(:default_lease_timeout) { default_timeout }
|
||||
|
||||
it { is_expected.to eq 1.hour.to_i }
|
||||
it { is_expected.to eq 30.minutes.to_i }
|
||||
|
||||
context 'when remove_namespace_aggregator_delay FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(remove_namespace_aggregator_delay: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq 1.5.hours.to_i }
|
||||
it { is_expected.to eq 1.hour.to_i }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ require (
|
|||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||
golang.org/x/tools v0.1.12
|
||||
google.golang.org/grpc v1.50.0
|
||||
google.golang.org/grpc v1.50.1
|
||||
google.golang.org/protobuf v1.28.1
|
||||
honnef.co/go/tools v0.3.3
|
||||
)
|
||||
|
|
|
@ -1550,8 +1550,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
|
|||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.0 h1:fPVVDxY9w++VjTZsYvXWqEf9Rqar/e+9zYfxKK+W+YU=
|
||||
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
|
|
Loading…
Reference in New Issue