Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-09-11 06:09:49 +00:00
parent b22351fbed
commit 842a565144
25 changed files with 218 additions and 49 deletions

View File

@ -187,7 +187,7 @@ gem 'carrierwave', '~> 1.3' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'mini_magick', '~> 4.12' # rubocop:todo Gemfile/MissingFeatureCategory
# for backups
gem 'fog-aws', '~> 3.25', feature_category: :shared
gem 'fog-aws', '~> 3.26', feature_category: :shared
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
# Also see config/initializers/fog_core_patch.rb.
gem 'fog-core', '= 2.1.0' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -189,7 +189,7 @@
{"name":"flipper-active_record","version":"0.26.2","platform":"ruby","checksum":"61deaeef8ce2f775e67d7095f40fd95fc2d07241e143dd4436e78c7b26a320bc"},
{"name":"flipper-active_support_cache_store","version":"0.26.2","platform":"ruby","checksum":"c2d3883ad1e5c7de827c37df455ffe6e175bc0be93f2a260c54efdabb313d2b0"},
{"name":"fog-aliyun","version":"0.4.0","platform":"ruby","checksum":"8f2334604beb781eafbb9cd5f50141fbb2c7eb77c7f2b01f45c2e04db0e5cc38"},
{"name":"fog-aws","version":"3.25.0","platform":"ruby","checksum":"35d84f12d49634304e2a8ed35014934047b096a744ac7687109fdf7b273255fe"},
{"name":"fog-aws","version":"3.26.0","platform":"ruby","checksum":"b7f8d465ef1e8a1c49cc662812d0c5b62a0e04536e4ea01843528bc311dd150e"},
{"name":"fog-core","version":"2.1.0","platform":"ruby","checksum":"53e5d793554d7080d015ef13cd44b54027e421d924d9dba4ce3d83f95f37eda9"},
{"name":"fog-google","version":"1.24.1","platform":"ruby","checksum":"dcd64ec5d12ed53f269afd7a88738b453e5150ef72b451900bb7abf3678358e0"},
{"name":"fog-json","version":"1.2.0","platform":"ruby","checksum":"dd4f5ab362dbc72b687240bba9d2dd841d5dfe888a285797533f85c03ea548fe"},

View File

@ -637,7 +637,7 @@ GEM
fog-json
ipaddress (~> 0.8)
xml-simple (~> 1.1)
fog-aws (3.25.0)
fog-aws (3.26.0)
base64 (~> 0.2.0)
fog-core (~> 2.1)
fog-json (~> 1.1)
@ -2039,7 +2039,7 @@ DEPENDENCIES
flipper-active_record (~> 0.26.2)
flipper-active_support_cache_store (~> 0.26.2)
fog-aliyun (~> 0.4)
fog-aws (~> 3.25)
fog-aws (~> 3.26)
fog-core (= 2.1.0)
fog-google (~> 1.24.1)
fog-local (~> 0.8)

View File

@ -190,7 +190,7 @@
{"name":"flipper-active_record","version":"0.26.2","platform":"ruby","checksum":"61deaeef8ce2f775e67d7095f40fd95fc2d07241e143dd4436e78c7b26a320bc"},
{"name":"flipper-active_support_cache_store","version":"0.26.2","platform":"ruby","checksum":"c2d3883ad1e5c7de827c37df455ffe6e175bc0be93f2a260c54efdabb313d2b0"},
{"name":"fog-aliyun","version":"0.4.0","platform":"ruby","checksum":"8f2334604beb781eafbb9cd5f50141fbb2c7eb77c7f2b01f45c2e04db0e5cc38"},
{"name":"fog-aws","version":"3.25.0","platform":"ruby","checksum":"35d84f12d49634304e2a8ed35014934047b096a744ac7687109fdf7b273255fe"},
{"name":"fog-aws","version":"3.26.0","platform":"ruby","checksum":"b7f8d465ef1e8a1c49cc662812d0c5b62a0e04536e4ea01843528bc311dd150e"},
{"name":"fog-core","version":"2.1.0","platform":"ruby","checksum":"53e5d793554d7080d015ef13cd44b54027e421d924d9dba4ce3d83f95f37eda9"},
{"name":"fog-google","version":"1.24.1","platform":"ruby","checksum":"dcd64ec5d12ed53f269afd7a88738b453e5150ef72b451900bb7abf3678358e0"},
{"name":"fog-json","version":"1.2.0","platform":"ruby","checksum":"dd4f5ab362dbc72b687240bba9d2dd841d5dfe888a285797533f85c03ea548fe"},

View File

@ -647,7 +647,7 @@ GEM
fog-json
ipaddress (~> 0.8)
xml-simple (~> 1.1)
fog-aws (3.25.0)
fog-aws (3.26.0)
base64 (~> 0.2.0)
fog-core (~> 2.1)
fog-json (~> 1.1)
@ -2066,7 +2066,7 @@ DEPENDENCIES
flipper-active_record (~> 0.26.2)
flipper-active_support_cache_store (~> 0.26.2)
fog-aliyun (~> 0.4)
fog-aws (~> 3.25)
fog-aws (~> 3.26)
fog-core (= 2.1.0)
fog-google (~> 1.24.1)
fog-local (~> 0.8)

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class AddPersonalNamespaceIdToEventsSelfManaged < Gitlab::Database::Migration[2.2]
milestone '17.4'
disable_ddl_transaction!
def up
return if Gitlab.com_except_jh?
return if column_exists?(:events, :personal_namespace_id)
with_lock_retries(raise_on_exhaustion: true) do
add_column :events, :personal_namespace_id, :bigint
end
end
def down
return if Gitlab.com_except_jh?
return unless column_exists?(:events, :personal_namespace_id)
with_lock_retries(raise_on_exhaustion: true) do
remove_column :events, :personal_namespace_id
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class AddIndexOnEventsPersonalNamespaceIdSelfManaged < Gitlab::Database::Migration[2.2]
milestone '17.4'
disable_ddl_transaction!
INDEX = 'index_events_on_personal_namespace_id'
# rubocop:disable Migration/PreventIndexCreation -- https://gitlab.com/gitlab-org/gitlab/-/issues/462801#note_2081632603
def up
return if Gitlab.com_except_jh?
add_concurrent_index :events,
:personal_namespace_id,
where: 'personal_namespace_id IS NOT NULL',
name: INDEX
end
# rubocop:enable Migration/PreventIndexCreation
def down
return if Gitlab.com_except_jh?
remove_concurrent_index_by_name :events, INDEX
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class AddFkOnEventsPersonalNamespaceIdSelfManaged < Gitlab::Database::Migration[2.2]
milestone '17.4'
disable_ddl_transaction!
TABLE_NAME = :events
def up
return if Gitlab.com_except_jh?
add_concurrent_foreign_key TABLE_NAME, :namespaces, column: :personal_namespace_id, on_delete: :cascade
end
def down
return if Gitlab.com_except_jh?
with_lock_retries { remove_foreign_key TABLE_NAME, column: :personal_namespace_id }
end
end

View File

@ -0,0 +1 @@
6e6ffa66e79666cd1c6dfbf60feaccda356d884d468f5fe82a5e257f250ce01a

View File

@ -0,0 +1 @@
7e074e41738a849375bcaed527da01e8e918939c65d6277e9cfff45c042eae16

View File

@ -0,0 +1 @@
89eeda66be6667791f2929a521590636a1b699ef425c05b3baf42f59048b0c53

View File

@ -10872,6 +10872,7 @@ CREATE TABLE events (
id bigint NOT NULL,
target_id bigint,
imported_from smallint DEFAULT 0 NOT NULL,
personal_namespace_id bigint,
CONSTRAINT check_97e06e05ad CHECK ((octet_length(fingerprint) <= 128))
);
@ -28244,6 +28245,8 @@ CREATE INDEX index_events_on_created_at_and_id ON events USING btree (created_at
CREATE INDEX index_events_on_group_id_and_id ON events USING btree (group_id, id) WHERE (group_id IS NOT NULL);
CREATE INDEX index_events_on_personal_namespace_id ON events USING btree (personal_namespace_id) WHERE (personal_namespace_id IS NOT NULL);
CREATE INDEX index_events_on_project_id_and_created_at ON events USING btree (project_id, created_at);
CREATE INDEX index_events_on_project_id_and_id ON events USING btree (project_id, id);
@ -34427,6 +34430,9 @@ ALTER TABLE ONLY workspaces
ALTER TABLE ONLY merge_requests_compliance_violations
ADD CONSTRAINT fk_ec881c1c6f FOREIGN KEY (violating_user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY events
ADD CONSTRAINT fk_eea90e3209 FOREIGN KEY (personal_namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY coverage_fuzzing_corpuses
ADD CONSTRAINT fk_ef5ebf339f FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;

View File

@ -26,12 +26,12 @@ For an overview, see [Project Dependency](https://www.youtube.com/watch?v=ckqkn9
To list your project's dependencies the SBOM document must:
- Comply with [the CycloneDX specification](https://github.com/CycloneDX/specification) version `1.4` or `1.5`.
- Comply with [the CycloneDX specification](https://github.com/CycloneDX/specification) version `1.4` or `1.5`. Online validator available on [CycloneDX Web Tool](https://cyclonedx.github.io/cyclonedx-web-tool/validate).
- Be uploaded as [a CI/CD artifact report](../../../ci/yaml/artifacts_reports.md#artifactsreportscyclonedx) from a successful pipeline on the default branch.
NOTE:
Although this is not mandatory for the dependency list, some security features also require the
document to include and comply with the [GitLab CycloneDX property taxonomy](../../../development/sec/cyclonedx_property_taxonomy.md).
Although this is not mandatory for populating the dependency list, the SBOM document must include and comply with the
[GitLab CycloneDX property taxonomy](../../../development/sec/cyclonedx_property_taxonomy.md) to provide some properties and to enable some security features.
GitLab already generates this document when the following requirements are met:

View File

@ -280,6 +280,7 @@ On self-managed GitLab, by default the `fallback_behavior` field is available. T
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135398) in GitLab 16.7 [with a flag](../../../administration/feature_flags.md) named `security_policies_policy_scope`. Enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/443594) in GitLab 16.11. Feature flag `security_policies_policy_scope` removed.
> - Scoping by group [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/468384) in GitLab 17.4.
Security policy enforcement depends first on establishing a link between the group, subgroup, or
project on which you want to enforce policies, and the security policy project that contains the
@ -291,12 +292,13 @@ You can refine a security policy's scope to:
- _Include_ only projects containing a compliance framework label.
- _Include_ or _exclude_ selected projects from enforcement.
- _Include_ selected groups. Optionally use this with the `projects` object to exclude selected projects.
### Policy scope schema
| Field | Type | Required | Possible values | Description |
|-------|------|----------|-----------------|-------------|
| `policy_scope` | `object` | false | `compliance_frameworks`, `projects` | Scopes the policy based on compliance framework labels or projects you define. |
| `policy_scope` | `object` | false | `compliance_frameworks`, `projects`, `groups` | Scopes the policy based on compliance framework labels, projects, or groups you define. |
### `policy_scope` scope type
@ -304,6 +306,7 @@ You can refine a security policy's scope to:
|-------|------|-----------------|-------------|
| `compliance_frameworks` | `array` | | List of IDs of the compliance frameworks in scope of enforcement, in an array of objects with key `id`. |
| `projects` | `object` | `including`, `excluding` | Use `excluding:` or `including:` then list the IDs of the projects you wish to include or exclude, in an array of objects with key `id`. |
| `groups` | `object` | `including` | Use `including:` then list the IDs of the groups you wish to include, in an array of objects with key `id`. |
### Example `policy.yml` with security policy scopes

View File

@ -134,10 +134,13 @@ These stages are always available, regardless of any project's CI/CD configurati
### `policy_scope` scope type
> - Scoping by group [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/468384) in GitLab 17.4.
| Field | Type | Possible values | Description |
|-------|------|-----------------|-------------|
| `compliance_frameworks` | `array` | | List of IDs of the compliance frameworks in scope of enforcement, in an array of objects with key `id`. |
| `projects` | `object` | `including`, `excluding` | Use `excluding:` or `including:` then list the IDs of the projects you wish to include or exclude, in an array of objects with key `id`. |
| `projects` | `object` | `including`, `excluding` | Use `excluding:` or `including:` then list the IDs of the projects you wish to include or exclude, in an array of objects with key `id`. |
| `groups` | `object` | `including` | Use `including:` then list the IDs of the groups you wish to include, in an array of objects with key `id`. |
For example:

View File

@ -326,6 +326,7 @@ In GitLab 16.9 and earlier:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135398) in GitLab 16.7 [with a flag](../../../administration/feature_flags.md) named `security_policies_policy_scope`. Enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/443594) in GitLab 16.11. Feature flag `security_policies_policy_scope` removed.
> - Scoping by group [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/468384) in GitLab 17.4.
Security policy enforcement depends first on establishing a link between:
@ -342,6 +343,7 @@ You scope security policies to projects by setting the scopes in the `policy.yml
the compliance framework's ID. To include projects, use `policy_scope.compliance_frameworks.id` to specify IDs of
compliance frameworks that are applied to the projects.
- _Include_ or _exclude_ selected projects from enforcement by using the project's ID.
- _Include_ selected groups. Optionally use this with the `projects` object to exclude selected projects.
### Policy scope schema
@ -349,7 +351,7 @@ A policy scope must conform to this schema.
| Field | Type | Required | Possible values | Description |
|-------|------|----------|-----------------|-------------|
| `policy_scope` | `object` | false | `compliance_frameworks`, `projects` | Scopes the policy based on compliance framework labels or projects you define. |
| `policy_scope` | `object` | false | `compliance_frameworks`, `projects`, `groups` | Scopes the policy based on compliance framework labels, projects, or groups you define. |
#### `policy_scope` scope type
@ -359,6 +361,7 @@ Policy scopes are one of two types.
|-------|------|-----------------|-------------|
| `compliance_frameworks` | `array` | | List of IDs of the compliance frameworks in scope of enforcement, in an array of objects with key `id`. |
| `projects` | `object` | `including`, `excluding` | Use `excluding:` or `including:` then list the IDs of the projects you wish to include or exclude, in an array of objects with key `id`. |
| `groups` | `object` | `including` | Use `including:` then list the IDs of the groups you wish to include, in an array of objects with key `id`. |
#### Example `policy.yml` with security policy scopes

View File

@ -11,48 +11,45 @@ module Gitlab
# account for all possible cases. In this regard, a status exception can be directly generated from
# GRPC::BadStatus. Therefore, it is recommended that we capture and rescue the GRPC::BadStatus and assert the
# status code to ensure adequate coverage of error cases.
case e.code
when GRPC::Core::StatusCodes::NOT_FOUND
handle_not_found(e)
when GRPC::Core::StatusCodes::INVALID_ARGUMENT
raise ArgumentError, e
when GRPC::Core::StatusCodes::DEADLINE_EXCEEDED
raise Gitlab::Git::CommandTimedOut, e
when GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED
handle_resource_exhausted(e)
else
raise Gitlab::Git::CommandError, e
end
handle_error(e)
end
private
def handle_resource_exhausted(exception)
detail = Gitlab::GitalyClient.decode_detailed_error(exception)
# handle_error first tries to handle the error as a detailed error, if no mapping found,
# it falls back to handling it as a default error according to the error code.
def handle_error(exception)
error = Gitlab::GitalyClient.unwrap_detailed_error(exception)
handle_detailed_error(error, exception) || handle_default_error(exception)
end
case detail.class.name
when Gitaly::LimitError.name
retry_after = detail&.retry_after&.seconds
def handle_detailed_error(error, exception)
case error
when Gitaly::ReferenceNotFoundError
raise Gitlab::Git::ReferenceNotFoundError.new(exception, error.reference_name)
when Gitaly::FindCommitsError
raise Gitlab::Git::Repository::CommitNotFound, exception
when Gitaly::AmbiguousReferenceError
raise Gitlab::Git::AmbiguousRef, exception
when Gitaly::LimitError
raise ResourceExhaustedError.new(
"Upstream Gitaly has been exhausted: #{detail.error_message}. Try again later", retry_after
"Upstream Gitaly has been exhausted: #{error.error_message}. Try again later", error.retry_after&.seconds
)
else
raise ResourceExhaustedError, _("Upstream Gitaly has been exhausted. Try again later")
end
end
def handle_not_found(exception)
detail = Gitlab::GitalyClient.decode_detailed_error(exception)
case detail.class.name
when Gitaly::ReferenceNotFoundError.name
raise Gitlab::Git::ReferenceNotFoundError.new(
exception, detail.reference_name
)
when Gitaly::FindCommitsError.name
raise Gitlab::Git::Repository::CommitNotFound, exception
else
def handle_default_error(exception)
case exception.code
when GRPC::Core::StatusCodes::NOT_FOUND
raise Gitlab::Git::Repository::NoRepository, exception
when GRPC::Core::StatusCodes::INVALID_ARGUMENT
raise ArgumentError, exception
when GRPC::Core::StatusCodes::DEADLINE_EXCEEDED
raise Gitlab::Git::CommandTimedOut, exception
when GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED
raise ResourceExhaustedError, _("Upstream Gitaly has been exhausted. Try again later")
else
raise Gitlab::Git::CommandError, exception
end
end
end

View File

@ -604,6 +604,7 @@ module Gitlab
stack_counter.select { |_, v| v == max }.keys
end
private_class_method :max_stacks
def self.decode_detailed_error(err)
# details could have more than one in theory, but we only have one to worry about for now.
@ -620,7 +621,19 @@ module Gitlab
nil
end
private_class_method :max_stacks
# This method attempts to unwrap a detailed error from a Gitaly RPC error.
# It first decodes the detailed error using decode_detailed_error. If successful,
# it tries to extract the unwrapped error by calling the method named by the
# error attribute on the decoded error object.
def self.unwrap_detailed_error(err)
e = decode_detailed_error(err)
return e if e.nil? || !e.respond_to?(:error) || e.error.nil? || !e.error.respond_to?(:to_s)
unwrapped_error = e[e.error.to_s]
unwrapped_error || e
end
def self.with_feature_flag_actors(repository: nil, user: nil, project: nil, group: nil, &block)
feature_flag_actors[:repository] = repository

View File

@ -118,6 +118,7 @@ module Gitlab
user.personal_access_tokens.build(params).tap do |pat|
pat.expires_at = 365.days.from_now
pat.set_token("#{admin_token}")
pat.organization = Organizations::Organization.default_organization
pat.save!
end
end

View File

@ -59,6 +59,7 @@ RSpec.describe Gitlab::Cng::Deployment::Configurations::Kind do
user.personal_access_tokens.build(params).tap do |pat|
pat.expires_at = 365.days.from_now
pat.set_token("token")
pat.organization = Organizations::Organization.default_organization
pat.save!
end
end

View File

@ -21,7 +21,8 @@ module QA
praefect_manager.start_all_nodes
end
it 'recovers from dataloss', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347832' do
it 'recovers from dataloss', :blocking,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347832' do
# Create a new project with a commit and wait for it to replicate
praefect_manager.wait_for_replication(project.id)

View File

@ -107,6 +107,22 @@ RSpec.describe Gitlab::Git::WrapsGitalyErrors, feature_category: :gitaly do
end
end
end
context 'with wrapped Gitaly::FindCommitsError' do
let(:original_error) do
new_detailed_error(
GRPC::Core::StatusCodes::NOT_FOUND,
'ambiguous reference',
Gitaly::FindCommitsError.new(ambiguous_ref: Gitaly::AmbiguousReferenceError.new)
)
end
it 'wraps the unwrapped ambiguous reference error' do
expect { wrapped_gitaly_errors }.to raise_error do |wrapped_error|
expect(wrapped_error).to be_a(Gitlab::Git::AmbiguousRef)
end
end
end
end
it 'does not swallow other errors' do

View File

@ -873,6 +873,54 @@ RSpec.describe Gitlab::GitalyClient, feature_category: :gitaly do
end
end
describe '.unwrap_detailed_error' do
let(:wrapped_detailed_error) do
new_detailed_error(GRPC::Core::StatusCodes::INVALID_ARGUMENT,
"error message",
Gitaly::UpdateReferencesError.new(invalid_format: Gitaly::InvalidRefFormatError.new(refs: ['\invali.\d/1', '\.invali/d/2'])))
end
let(:detailed_error) do
new_detailed_error(GRPC::Core::StatusCodes::INVALID_ARGUMENT,
"error message",
Gitaly::InvalidRefFormatError.new)
end
let(:error_without_details) do
error_code = GRPC::Core::StatusCodes::INVALID_ARGUMENT
error_message = "error message"
status_error = Google::Rpc::Status.new(
code: error_code,
message: error_message,
details: nil
)
GRPC::BadStatus.new(
error_code,
error_message,
{ "grpc-status-details-bin" => Google::Rpc::Status.encode(status_error) })
end
context 'unwraps detailed errors' do
using RSpec::Parameterized::TableSyntax
where(:error, :result) do
wrapped_detailed_error | Gitaly::InvalidRefFormatError.new(refs: ['\invali.\d/1', '\.invali/d/2'])
detailed_error | Gitaly::InvalidRefFormatError.new
error_without_details | nil
StandardError.new | nil
nil | nil
end
with_them do
it 'returns unwrapped detailed error' do
expect(described_class.unwrap_detailed_error(error)).to eq(result)
end
end
end
end
describe '.with_feature_flag_actor', :request_store do
shared_examples 'with_feature_flag_actor' do
let(:repository_actor) { double(:actor) }

View File

@ -36,7 +36,7 @@ require (
gocloud.dev v0.39.0
golang.org/x/image v0.20.0
golang.org/x/net v0.28.0
golang.org/x/oauth2 v0.22.0
golang.org/x/oauth2 v0.23.0
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2
)

View File

@ -647,8 +647,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=