diff --git a/config/feature_flags/gitlab_com_derisk/ref_extract_sha256.yml b/config/feature_flags/gitlab_com_derisk/ref_extract_sha256.yml new file mode 100644 index 0000000000000000000000000000000000000000..84370a6c36c51cd4e631a32479b49d558b940db9 --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/ref_extract_sha256.yml @@ -0,0 +1,9 @@ +--- +name: ref_extract_sha256 +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419905 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144853 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442021 +milestone: '16.10' +group: group::source code +type: gitlab_com_derisk +default_enabled: false diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb index af3f841ea6edc93fa237b1d434f4adb772df0380..90414d3f98b469286870d83815e188662ae728e1 100644 --- a/lib/extracts_ref.rb +++ b/lib/extracts_ref.rb @@ -109,8 +109,15 @@ def ref_type def extract_raw_ref(id) return ['', ''] unless repository_container + sha_regex = + if Feature.enabled?(:ref_extract_sha256, Feature.current_request) + /^(\h{40}\h{24}?)(.*)/ + else + /^(\h{40})(.+)/ + end + # If the ref appears to be a SHA, we're done, just split the string - return $~.captures if id =~ /^(\h{40})(.+)/ + return $~.captures if id =~ sha_regex # No slash means we must have a ref and no path return [id, ''] unless id.include?('/') diff --git a/spec/support/shared_examples/path_extraction_shared_examples.rb b/spec/support/shared_examples/path_extraction_shared_examples.rb index 5ceaf182d03de10a1d917fbcab4ddd38f8decb3d..6bc6a84e8b4c1e1fe3588a5bb4dd3d97ff25d0f0 100644 --- a/spec/support/shared_examples/path_extraction_shared_examples.rb +++ b/spec/support/shared_examples/path_extraction_shared_examples.rb @@ -79,12 +79,30 @@ expect(extract_ref('v2.0.0')).to eq(['v2.0.0', '']) end - it 'extracts a valid commit ref without a path' do + it 'extracts a valid commit SHA1 ref without a path' do expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062')).to eq( ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] ) end + it 'extracts a valid commit SHA256 ref without a path' do + expect(extract_ref('34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c')).to eq( + ['34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c', ''] + ) + end + + context 'when feature flag "ref_extract_sha256" is disabled' do + before do + stub_feature_flags(ref_extract_sha256: false) + end + + it 'cannot extract a valid commit SHA256 ref' do + expect(extract_ref('34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c')).to eq( + %w[34627760127d5ff2a644771225af09bbd79f28a5 4a0a4c03c1881bf2c26dc13c] + ) + end + end + it 'falls back to a primitive split for an invalid ref' do expect(extract_ref('stable')).to eq(['stable', '']) end @@ -112,12 +130,30 @@ expect(extract_ref('v2.0.0/CHANGELOG')).to eq(['v2.0.0', 'CHANGELOG']) end - it 'extracts a valid commit SHA' do + it 'extracts a valid commit SHA1' do expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG')).to eq( %w[f4b14494ef6abf3d144c28e4af0c20143383e062 CHANGELOG] ) end + it 'extracts a valid commit SHA256' do + expect(extract_ref('34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c/CHANGELOG')).to eq( + %w[34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c CHANGELOG] + ) + end + + context 'when feature flag "ref_extract_sha256" is disabled' do + before do + stub_feature_flags(ref_extract_sha256: false) + end + + it 'cannot extract a valid commit SHA256 ref' do + expect(extract_ref('34627760127d5ff2a644771225af09bbd79f28a54a0a4c03c1881bf2c26dc13c/CHANGELOG')).to eq( + ['34627760127d5ff2a644771225af09bbd79f28a5', '4a0a4c03c1881bf2c26dc13c/CHANGELOG'] + ) + end + end + it 'falls back to a primitive split for an invalid ref' do expect(extract_ref('stable/CHANGELOG')).to eq(%w[stable CHANGELOG]) end