Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-24 12:09:10 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-24 12:09:10 +0300
commitbd818d0618b0c1316c23f47f9ae41449e5d41fa8 (patch)
tree39909be45555a6ea4ee5143fc961caf33a76143f
parentf1d39f5bea74d84c38b4713f66cfcc9fdbcd1c57 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--Gemfile6
-rw-r--r--Gemfile.lock18
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue6
-rw-r--r--app/finders/merge_requests/oldest_per_commit_finder.rb19
-rw-r--r--app/models/merge_request.rb3
-rw-r--r--app/models/packages/debian/file_entry.rb44
-rw-r--r--app/services/packages/debian/extract_changes_metadata_service.rb112
-rw-r--r--changelogs/unreleased/include-squash-commits-in-changelogs.yml5
-rw-r--r--changelogs/unreleased/inherited_issuable_templates_default_enabled.yml5
-rw-r--r--changelogs/unreleased/manifest-unsafe-scheme.yml5
-rw-r--r--changelogs/unreleased/sh-update-mailroom.yml5
-rw-r--r--config/dependency_decisions.yml6
-rw-r--r--config/feature_flags/development/inherited_issuable_templates.yml2
-rw-r--r--doc/development/usage_ping/dictionary.md48
-rw-r--r--doc/user/analytics/index.md12
-rw-r--r--doc/user/project/description_templates.md70
-rw-r--r--lib/gitlab/manifest_import/manifest.rb8
-rw-r--r--lib/gitlab/usage_data_counters/known_events/epic_events.yml12
-rw-r--r--locale/gitlab.pot8
-rw-r--r--qa/qa/page/component/invite_members_modal.rb2
-rw-r--r--spec/factories/packages/package_file.rb18
-rw-r--r--spec/features/import/manifest_import_spec.rb9
-rw-r--r--spec/features/projects/members/list_spec.rb2
-rw-r--r--spec/finders/merge_requests/oldest_per_commit_finder_spec.rb39
-rw-r--r--spec/fixtures/unsafe_javascript.xml10
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js2
-rw-r--r--spec/models/merge_request_spec.rb13
-rw-r--r--spec/models/packages/debian/file_entry_spec.rb98
-rw-r--r--spec/services/packages/debian/extract_changes_metadata_service_spec.rb160
29 files changed, 698 insertions, 49 deletions
diff --git a/Gemfile b/Gemfile
index 522122b13e4..1774f09a61a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -440,7 +440,11 @@ end
gem 'octokit', '~> 4.15'
# https://gitlab.com/gitlab-org/gitlab/issues/207207
-gem 'gitlab-mail_room', '~> 0.0.9', require: 'mail_room'
+gem 'gitlab-mail_room', '~> 0.0.10', require: false
+# Ruby v3.0 promoted net-http and net-imap from stdlib. Adding net-http as a
+# dependency avoids "already initialized constant errors" if net-imap is installed.
+gem 'net-http', '~> 0.1'
+gem 'uri', '= 0.10.0' # Lock this for bundler v2.1.4
gem 'email_reply_trimmer', '~> 0.1'
gem 'html2text'
diff --git a/Gemfile.lock b/Gemfile.lock
index 5d63cb1cb2d..5a2787130ef 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -268,6 +268,7 @@ GEM
diff-lcs (1.4.4)
diff_match_patch (0.1.0)
diffy (3.3.0)
+ digest (3.0.0)
discordrb-webhooks (3.4.2)
rest-client (>= 2.0.0)
docile (1.3.2)
@@ -464,7 +465,8 @@ GEM
pg_query (~> 1.3)
redis (> 3.0.0, < 5.0.0)
gitlab-license (1.3.1)
- gitlab-mail_room (0.0.9)
+ gitlab-mail_room (0.0.10)
+ net-imap (>= 0.2.1)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
gitlab-pry-byebug (3.9.0)
@@ -763,10 +765,18 @@ GEM
mustermann (>= 1.0.0)
nap (1.1.0)
nenv (0.3.0)
+ net-http (0.1.1)
+ net-protocol
+ uri
net-http-persistent (4.0.1)
connection_pool (~> 2.2)
+ net-imap (0.2.1)
+ digest
+ net-protocol
+ strscan
net-ldap (0.16.3)
net-ntp (2.1.3)
+ net-protocol (0.1.0)
net-scp (3.0.0)
net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (6.0.0)
@@ -1208,6 +1218,7 @@ GEM
state_machines-activerecord (0.8.0)
activerecord (>= 5.1)
state_machines-activemodel (>= 0.8.0)
+ strscan (3.0.0)
swd (1.1.2)
activesupport (>= 3)
attr_required (>= 0.0.5)
@@ -1278,6 +1289,7 @@ GEM
equalizer (~> 0.0.9)
parser (>= 2.6.5)
procto (~> 0.0.2)
+ uri (0.10.0)
uri_template (0.7.0)
valid_email (0.1.3)
activemodel
@@ -1427,7 +1439,7 @@ DEPENDENCIES
gitlab-fog-google (~> 1.13)
gitlab-labkit (~> 0.16.2)
gitlab-license (~> 1.3)
- gitlab-mail_room (~> 0.0.9)
+ gitlab-mail_room (~> 0.0.10)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
gitlab-pry-byebug
@@ -1489,6 +1501,7 @@ DEPENDENCIES
mini_magick (~> 4.10.1)
minitest (~> 5.11.0)
multi_json (~> 1.14.1)
+ net-http (~> 0.1)
net-ldap (~> 0.16.3)
net-ntp
net-ssh (~> 6.0)
@@ -1597,6 +1610,7 @@ DEPENDENCIES
unicorn (~> 5.5)
unicorn-worker-killer (~> 0.4.4)
unleash (~> 0.1.5)
+ uri (= 0.10.0)
valid_email (~> 0.1)
validates_hostname (~> 1.0.11)
version_sorter (~> 2.2.4)
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 906965f4395..d00a0f1633b 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -222,9 +222,9 @@ export default {
},
labels: {
members: {
- modalTitle: s__('InviteMembersModal|Invite team members'),
- searchField: s__('InviteMembersModal|GitLab member or Email address'),
- placeHolder: s__('InviteMembersModal|Search for members to invite'),
+ modalTitle: s__('InviteMembersModal|Invite members'),
+ searchField: s__('InviteMembersModal|GitLab member or email address'),
+ placeHolder: s__('InviteMembersModal|Select members or type email addresses'),
toGroup: {
introText: s__(
"InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group.",
diff --git a/app/finders/merge_requests/oldest_per_commit_finder.rb b/app/finders/merge_requests/oldest_per_commit_finder.rb
index 5360f301036..5da7a08e36c 100644
--- a/app/finders/merge_requests/oldest_per_commit_finder.rb
+++ b/app/finders/merge_requests/oldest_per_commit_finder.rb
@@ -18,8 +18,8 @@ module MergeRequests
mapping = {}
shas = commits.map(&:id)
- # To include merge requests by the commit SHA, we don't need to go through
- # any diff rows.
+ # To include merge requests by the merge/squash SHA, we don't need to go
+ # through any diff rows.
#
# We can't squeeze all this into a single query, as the diff based data
# relies on a GROUP BY. On the other hand, retrieving MRs by their merge
@@ -27,12 +27,17 @@ module MergeRequests
@project
.merge_requests
.preload_target_project
- .by_merge_commit_sha(shas)
+ .by_merge_or_squash_commit_sha(shas)
.each do |mr|
- # Merge SHAs can't be in the merge request itself. It _is_ possible a
- # newer merge request includes the merge commit, but in that case we
- # still want the oldest merge request.
- mapping[mr.merge_commit_sha] = mr
+ # Merge/squash SHAs can't be in the merge request itself. It _is_
+ # possible a newer merge request includes the commit, but in that case
+ # we still want the oldest merge request.
+ #
+ # It's also possible that a merge request produces both a squashed
+ # commit and a merge commit. In that case we want to store the mapping
+ # for both the SHAs.
+ mapping[mr.squash_commit_sha] = mr if mr.squash_commit_sha
+ mapping[mr.merge_commit_sha] = mr if mr.merge_commit_sha
end
remaining = shas - mapping.keys
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 76f0417ab35..834d28f1e3c 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -276,6 +276,9 @@ class MergeRequest < ApplicationRecord
scope :by_squash_commit_sha, -> (sha) do
where(squash_commit_sha: sha)
end
+ scope :by_merge_or_squash_commit_sha, -> (sha) do
+ from_union([by_squash_commit_sha(sha), by_merge_commit_sha(sha)])
+ end
scope :by_related_commit_sha, -> (sha) do
from_union(
[
diff --git a/app/models/packages/debian/file_entry.rb b/app/models/packages/debian/file_entry.rb
new file mode 100644
index 00000000000..eb66f4acfa9
--- /dev/null
+++ b/app/models/packages/debian/file_entry.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class FileEntry
+ include ActiveModel::Model
+
+ DIGESTS = %i[md5 sha1 sha256].freeze
+ FILENAME_REGEX = %r{\A[a-zA-Z0-9][a-zA-Z0-9_.~+-]*\z}.freeze
+
+ attr_accessor :filename,
+ :size,
+ :md5sum,
+ :section,
+ :priority,
+ :sha1sum,
+ :sha256sum,
+ :package_file
+
+ validates :filename, :size, :md5sum, :section, :priority, :sha1sum, :sha256sum, :package_file, presence: true
+ validates :filename, format: { with: FILENAME_REGEX }
+ validate :valid_package_file_digests, if: -> { md5sum.present? && sha1sum.present? && sha256sum.present? && package_file.present? }
+
+ def component
+ return 'main' if section.blank?
+ return 'main' unless section.include?('/')
+
+ section.split('/')[0]
+ end
+
+ private
+
+ def valid_package_file_digests
+ DIGESTS.each do |digest|
+ package_file_digest = package_file["file_#{digest}"]
+ sum = public_send("#{digest}sum") # rubocop:disable GitlabSecurity/PublicSend
+ next if package_file_digest == sum
+
+ errors.add("#{digest}sum".to_sym, "mismatch for #{filename}: #{package_file_digest} != #{sum}")
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/extract_changes_metadata_service.rb b/app/services/packages/debian/extract_changes_metadata_service.rb
new file mode 100644
index 00000000000..242b4cc8e54
--- /dev/null
+++ b/app/services/packages/debian/extract_changes_metadata_service.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class ExtractChangesMetadataService
+ include Gitlab::Utils::StrongMemoize
+
+ ExtractionError = Class.new(StandardError)
+
+ def initialize(package_file)
+ @package_file = package_file
+ @entries = {}
+ end
+
+ def execute
+ {
+ file_type: file_type,
+ architecture: metadata[:architecture],
+ fields: fields,
+ files: files
+ }
+ rescue ActiveModel::ValidationError => e
+ raise ExtractionError.new(e.message)
+ end
+
+ private
+
+ def metadata
+ strong_memoize(:metadata) do
+ ::Packages::Debian::ExtractMetadataService.new(@package_file).execute
+ end
+ end
+
+ def file_type
+ metadata[:file_type]
+ end
+
+ def fields
+ metadata[:fields]
+ end
+
+ def files
+ strong_memoize(:files) do
+ raise ExtractionError.new("is not a changes file") unless file_type == :changes
+ raise ExtractionError.new("Files field is missing") if fields[:Files].blank?
+ raise ExtractionError.new("Checksums-Sha1 field is missing") if fields[:'Checksums-Sha1'].blank?
+ raise ExtractionError.new("Checksums-Sha256 field is missing") if fields[:'Checksums-Sha256'].blank?
+
+ init_entries_from_files
+ entries_from_checksums_sha1
+ entries_from_checksums_sha256
+ entries_from_package_files
+
+ @entries
+ end
+ end
+
+ def init_entries_from_files
+ each_lines_for(:Files) do |line|
+ md5sum, size, section, priority, filename = line.split
+ entry = FileEntry.new(
+ filename: filename,
+ size: size.to_i,
+ md5sum: md5sum,
+ section: section,
+ priority: priority)
+
+ @entries[filename] = entry
+ end
+ end
+
+ def entries_from_checksums_sha1
+ each_lines_for(:'Checksums-Sha1') do |line|
+ sha1sum, size, filename = line.split
+ entry = @entries[filename]
+ raise ExtractionError.new("#{filename} is listed in Checksums-Sha1 but not in Files") unless entry
+ raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha1 differ") unless entry.size == size.to_i
+
+ entry.sha1sum = sha1sum
+ end
+ end
+
+ def entries_from_checksums_sha256
+ each_lines_for(:'Checksums-Sha256') do |line|
+ sha256sum, size, filename = line.split
+ entry = @entries[filename]
+ raise ExtractionError.new("#{filename} is listed in Checksums-Sha256 but not in Files") unless entry
+ raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha256 differ") unless entry.size == size.to_i
+
+ entry.sha256sum = sha256sum
+ end
+ end
+
+ def each_lines_for(field)
+ fields[field].split("\n").each do |line|
+ next if line.blank?
+
+ yield(line)
+ end
+ end
+
+ def entries_from_package_files
+ @entries.each do |filename, entry|
+ entry.package_file = ::Packages::PackageFileFinder.new(@package_file.package, filename).execute!
+ entry.validate!
+ rescue ActiveRecord::RecordNotFound
+ raise ExtractionError.new("#{filename} is listed in Files but was not uploaded")
+ end
+ end
+ end
+ end
+end
diff --git a/changelogs/unreleased/include-squash-commits-in-changelogs.yml b/changelogs/unreleased/include-squash-commits-in-changelogs.yml
new file mode 100644
index 00000000000..cbcf2e8190b
--- /dev/null
+++ b/changelogs/unreleased/include-squash-commits-in-changelogs.yml
@@ -0,0 +1,5 @@
+---
+title: Link squashed commits using the changelog API
+merge_request: 56985
+author:
+type: added
diff --git a/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml b/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml
new file mode 100644
index 00000000000..25bf183e441
--- /dev/null
+++ b/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml
@@ -0,0 +1,5 @@
+---
+title: Configure issue and merge request description templates at group level and rolldown description templates in the group hierarchy
+merge_request: 56737
+author:
+type: added
diff --git a/changelogs/unreleased/manifest-unsafe-scheme.yml b/changelogs/unreleased/manifest-unsafe-scheme.yml
new file mode 100644
index 00000000000..8158af93b31
--- /dev/null
+++ b/changelogs/unreleased/manifest-unsafe-scheme.yml
@@ -0,0 +1,5 @@
+---
+title: Validate import manifest url scheme
+merge_request: 57071
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-update-mailroom.yml b/changelogs/unreleased/sh-update-mailroom.yml
new file mode 100644
index 00000000000..b53221ba787
--- /dev/null
+++ b/changelogs/unreleased/sh-update-mailroom.yml
@@ -0,0 +1,5 @@
+---
+title: Update mailroom to v0.0.10
+merge_request: 56913
+author:
+type: fixed
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 774254d2ff1..326c7acb28a 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -331,3 +331,9 @@
:why: https://github.com/xijo/reverse_markdown/blob/master/LICENSE
:versions: []
:when: 2021-02-03 08:47:28.792907000 Z
+- - :approve
+ - net-protocol
+ - :who: Stan Hu
+ :why: "This license is the same as the Ruby license (BSD): https://github.com/ruby/net-protocol/blob/master/LICENSE.txt"
+ :versions: []
+ :when: 2021-03-18 00:00:46.124036000 Z
diff --git a/config/feature_flags/development/inherited_issuable_templates.yml b/config/feature_flags/development/inherited_issuable_templates.yml
index fb322e9468a..403361ff784 100644
--- a/config/feature_flags/development/inherited_issuable_templates.yml
+++ b/config/feature_flags/development/inherited_issuable_templates.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321247
milestone: '13.9'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index 45a1c5c29fa..887ecd858ff 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -9812,6 +9812,30 @@ Status: `implemented`
Tiers: `premium`, `ultimate`
+### `redis_hll_counters.epics_usage.g_project_management_epic_closed_monthly`
+
+Counts of MAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210310163213_g_project_management_epic_closed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_closed_weekly`
+
+Counts of WAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210310162703_g_project_management_epic_closed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `redis_hll_counters.epics_usage.g_project_management_epic_created_monthly`
Count of MAU creating epics
@@ -9860,6 +9884,30 @@ Status: `implemented`
Tiers: `premium`, `ultimate`
+### `redis_hll_counters.epics_usage.g_project_management_epic_reopened_monthly`
+
+Counts of MAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210310164247_g_project_management_epic_reopened_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_reopened_weekly`
+
+Counts of WAU re-opening epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210310164112_g_project_management_epic_reopened_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `redis_hll_counters.epics_usage.g_project_management_users_destroying_epic_notes_monthly`
Counts of MAU destroying epic notes
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index fe35d575373..bcc063dea28 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -48,9 +48,10 @@ The following analytics features are available at the group level:
- [Contribution](../group/contribution_analytics/index.md). **(PREMIUM)**
- [Insights](../group/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
-- [Productivity](productivity_analytics.md) **(PREMIUM)**
-- [Repositories](../group/repositories_analytics/index.md) **(PREMIUM)**
+- [Productivity](productivity_analytics.md). **(PREMIUM)**
+- [Repositories](../group/repositories_analytics/index.md). **(PREMIUM)**
- [Value Stream](../group/value_stream_analytics/index.md). **(PREMIUM)**
+- [Application Security](../application_security/security_dashboard/#group-security-dashboard). **(ULTIMATE)**
## Project-level analytics
@@ -64,3 +65,10 @@ The following analytics features are available at the project level:
[feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development). **(PREMIUM)**
- [Repository](repository_analytics.md). **(FREE)**
- [Value Stream](value_stream_analytics.md). **(FREE)**
+- [Application Security](../application_security/security_dashboard/#project-security-dashboard). **(ULTIMATE)**
+
+## User-configurable analytics
+
+The following analytics features are available for users to create personalized views:
+
+- [Application Security](../application_security/security_dashboard/#security-center). **(ULTIMATE)**
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 2267cb55f16..c45ce7a02d9 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -89,32 +89,27 @@ For example: `https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_templat
![Description templates](img/description_templates.png)
-### Set an issue and merge request description template at group level **(PREMIUM)**
+You can set description templates at various levels:
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled by default on GitLab.com.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to
- [enable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level).
-
-Templates can be useful because you can create a template once and use it multiple times.
-To re-use templates [you've created](../project/description_templates.md#create-an-issue-template):
-
-1. Go to the group's **Settings > General > Templates**.
-1. From the dropdown, select your template project as the template repository at group level.
+- The entire [instance](#set-instance-level-description-templates)
+- A specific [group or subgroup](#set-group-level-description-templates)
+- A specific [project](#set-a-default-template-for-merge-requests-and-issues)
-![Group template settings](../group/img/group_file_template_settings.png)
+The templates are inherited. For example, in a project, you can also access templates set for the
+instance or the project's parent groups.
-### Set an issue and merge request description template at instance level **(PREMIUM ONLY)**
+### Set instance-level description templates **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled by default on GitLab.com.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to
- [enable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level).
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
+> - It's enabled by default on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+
+You can set a description template at the **instance level** for issues
+and merge requests.
+As a result, these templates are available in all projects within the instance.
-Similar to group templates, issue and merge request templates can also be set up at the instance level.
-This results in those templates being available in all projects within the instance.
Only instance administrators can set instance-level templates.
To set the instance-level description template repository:
@@ -122,15 +117,41 @@ To set the instance-level description template repository:
1. Select the **Admin Area** icon (**{admin}**).
1. Go to **Settings > Templates**.
1. From the dropdown, select your template project as the template repository at instance level.
+1. Select **Save changes**.
+
+![Setting templates in the Admin Area](../admin_area/settings/img/file_template_admin_area.png)
Learn more about [instance template repository](../admin_area/settings/instance_template_repository.md).
-![Setting templates in the Admin Area](../admin_area/settings/img/file_template_admin_area.png)
+### Set group-level description templates **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
+> - It's enabled by default on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+
+With **group-level** description templates, you can store your templates in a single repository and
+configure the group file templates setting to point to that repository.
+As a result, you can use the same templates in issues and merge requests in all the group's projects.
+
+To re-use templates [you've created](../project/description_templates.md#create-an-issue-template):
+
+1. Go to the group's **Settings > General > Templates**.
+1. From the dropdown, select your template project as the template repository at group level.
+1. Select **Save changes**.
+
+![Group template settings](../group/img/group_file_template_settings.png)
### Set a default template for merge requests and issues **(PREMIUM)**
+In a project, you can choose a default description template for new issues and merge requests.
+As a result, every time a new merge request or issue is created, it's pre-filled with the text you
+entered in the template.
+
The visibility of issues or merge requests should be set to either "Everyone
-with access" or "Only Project Members" in your project's **Settings / Visibility, project features, permissions** section, otherwise the
+with access" or "Only Project Members" in your project's
+**Settings / Visibility, project features, permissions** section. Otherwise, the
template text areas don't show. This is the default behavior, so in most cases
you should be fine.
@@ -149,9 +170,6 @@ To set a default description template for issues:
Because GitLab merge request and issues support [Markdown](../markdown.md), you can use it to format
headings, lists, and so on.
-Now, every time a new merge request or issue is created, it's pre-filled with the text you entered
-in the templates.
-
[GitLab versions 13.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/885)
provide `issues_template` and `merge_requests_template` attributes in the
[Projects API](../../api/projects.md) to help you keep your templates up to date.
@@ -211,9 +229,9 @@ it's very hard to read otherwise.)
Setting issue and merge request description templates at group and instance levels
is under development and not ready for production use. It is deployed behind a
-feature flag that is **disabled by default**.
+feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
+can disable it.
To enable it:
diff --git a/lib/gitlab/manifest_import/manifest.rb b/lib/gitlab/manifest_import/manifest.rb
index 7208fe5bbc5..618ddf37b88 100644
--- a/lib/gitlab/manifest_import/manifest.rb
+++ b/lib/gitlab/manifest_import/manifest.rb
@@ -47,6 +47,10 @@ module Gitlab
@errors << 'Make sure every <project> tag has name and path attributes.'
end
+ unless validate_scheme
+ @errors << 'Make sure the url does not start with javascript'
+ end
+
@errors.empty?
end
@@ -64,6 +68,10 @@ module Gitlab
end
end
+ def validate_scheme
+ remote !~ /\Ajavascript/i
+ end
+
def repository_url(name)
Gitlab::Utils.append_path(remote, name)
end
diff --git a/lib/gitlab/usage_data_counters/known_events/epic_events.yml b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
index 79dfae98157..3defa3e932e 100644
--- a/lib/gitlab/usage_data_counters/known_events/epic_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
@@ -38,3 +38,15 @@
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
+
+- name: g_project_management_epic_closed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_reopened
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index cb7bdb7c1f5..118b971b35f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16888,7 +16888,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16897,7 +16897,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16906,10 +16906,10 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb
index fbddb37f15e..9883ef22029 100644
--- a/qa/qa/page/component/invite_members_modal.rb
+++ b/qa/qa/page/component/invite_members_modal.rb
@@ -42,7 +42,7 @@ module QA
within_element(:invite_members_modal_content) do
fill_element :access_level_dropdown, with: access_level
- fill_in 'Search for members to invite', with: username
+ fill_in 'Select members or type email addresses', with: username
Support::WaitForRequests.wait_for_requests
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index 6d8b119040e..6cbe9e6219d 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -125,6 +125,9 @@ FactoryBot.define do
trait(:source) do
file_name { 'sample_1.2.3~alpha2.tar.xz' }
+ file_md5 { 'd79b34f58f61ff4ad696d9bd0b8daa68' }
+ file_sha1 { '5f8bba5574eb01ac3b1f5e2988e8c29307788236' }
+ file_sha256 { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362' }
transient do
file_metadatum_trait { :source }
@@ -133,6 +136,9 @@ FactoryBot.define do
trait(:dsc) do
file_name { 'sample_1.2.3~alpha2.dsc' }
+ file_md5 { '3b0817804f669e16cdefac583ad88f0e' }
+ file_sha1 { '32ecbd674f0bfd310df68484d87752490685a8d6' }
+ file_sha256 { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
transient do
file_metadatum_trait { :dsc }
@@ -141,6 +147,9 @@ FactoryBot.define do
trait(:deb) do
file_name { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ file_md5 { 'fb0842b21adc44207996296fe14439dd' }
+ file_sha1 { '5248b95600e85bfe7f63c0dfce330a75f5777366' }
+ file_sha256 { '1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1' }
transient do
file_metadatum_trait { :deb }
@@ -149,6 +158,9 @@ FactoryBot.define do
trait(:deb2) do
file_name { 'sample-dev_1.2.3~binary_amd64.deb' }
+ file_md5 { 'd2afbd28e4d74430d22f9504e18bfdf5' }
+ file_sha1 { 'f81e4f66c8c6bb899653a3340c157965ee69634f' }
+ file_sha256 { '9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d' }
transient do
file_metadatum_trait { :deb }
@@ -157,6 +169,9 @@ FactoryBot.define do
trait(:udeb) do
file_name { 'sample-udeb_1.2.3~alpha2_amd64.udeb' }
+ file_md5 { '72b1dd7d98229e2fb0355feda1d3a165' }
+ file_sha1 { 'e42e8f2fe04ed1bb73b44a187674480d0e49dcba' }
+ file_sha256 { '2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f' }
transient do
file_metadatum_trait { :udeb }
@@ -165,6 +180,9 @@ FactoryBot.define do
trait(:buildinfo) do
file_name { 'sample_1.2.3~alpha2_amd64.buildinfo' }
+ file_md5 { '4e085dd67c120ca967ec314f65770a42' }
+ file_sha1 { '0d47e899f3cc67a2253a4629456ff927e0db5c60' }
+ file_sha256 { 'f9900d3c94e94b329232668dcbef3dba2d96c07147b15b6dc0533452e4dd8a43' }
transient do
file_metadatum_trait { :buildinfo }
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index ce22171a560..520cf850da2 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -42,6 +42,15 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
end
end
+ it 'renders an error if the remote url scheme starts with javascript' do
+ visit new_import_manifest_path
+
+ attach_file('manifest', Rails.root.join('spec/fixtures/unsafe_javascript.xml'))
+ click_on 'List available repositories'
+
+ expect(page).to have_content 'Make sure the url does not start with javascript'
+ end
+
it 'renders an error if invalid file was provided' do
visit new_import_manifest_path
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 0830585da9b..384b8ae9929 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'Project members list', :js do
click_on 'Invite members'
page.within '#invite-members-modal' do
- fill_in 'Search for members to invite', with: id
+ fill_in 'Select members or type email addresses', with: id
wait_for_requests
click_button id
diff --git a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
index 4724a8eb5c7..6dffaff294d 100644
--- a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
+++ b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
@@ -77,6 +77,45 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
expect(described_class.new(project).execute(commits)).to eq(sha => mr)
end
+ it 'includes a merge request that was squashed into the target branch' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ squash_commit_sha: sha
+ )
+
+ commits = [double(:commit, id: sha)]
+
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr)
+ end
+
+ it 'includes a merge request for both a squash and merge commit' do
+ project = create(:project)
+ sha1 = Digest::SHA1.hexdigest('foo')
+ sha2 = Digest::SHA1.hexdigest('bar')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ squash_commit_sha: sha1,
+ merge_commit_sha: sha2
+ )
+
+ commits = [double(:commit1, id: sha1), double(:commit2, id: sha2)]
+
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits))
+ .to eq(sha1 => mr, sha2 => mr)
+ end
+
it 'includes the oldest merge request when a merge commit is present in a newer merge request' do
project = create(:project)
sha = Digest::SHA1.hexdigest('foo')
diff --git a/spec/fixtures/unsafe_javascript.xml b/spec/fixtures/unsafe_javascript.xml
new file mode 100644
index 00000000000..0c23d1e07db
--- /dev/null
+++ b/spec/fixtures/unsafe_javascript.xml
@@ -0,0 +1,10 @@
+<manifest>
+ <remote review="javascript://HelloTheGitlabSecurityTeam%0Aprompt(1)%0A" />
+
+ <project path="test1" name="manifest1" />
+ <project path="test2" name="manifest2" />
+ <project path="test3" name="manifest3" />
+ <project path="test4" name="manifest4" />
+ <project path="test5" name="manifest5" />
+ <project path="test6" name="manifest6" />
+</manifest> \ No newline at end of file
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 7b2ea890d35..7ed18775693 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -93,7 +93,7 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite team members');
+ expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite members');
});
it('renders the Cancel button text correctly', () => {
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index b2c45135de1..d330169eab0 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -420,6 +420,19 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '.by_merge_or_squash_commit_sha' do
+ subject { described_class.by_merge_or_squash_commit_sha([sha1, sha2]) }
+
+ let(:sha1) { '123abc' }
+ let(:sha2) { '456abc' }
+ let(:mr1) { create(:merge_request, :merged, squash_commit_sha: sha1) }
+ let(:mr2) { create(:merge_request, :merged, merge_commit_sha: sha2) }
+
+ it 'returns merge requests that match the given squash and merge commits' do
+ is_expected.to include(mr1, mr2)
+ end
+ end
+
describe '.by_related_commit_sha' do
subject { described_class.by_related_commit_sha(sha) }
diff --git a/spec/models/packages/debian/file_entry_spec.rb b/spec/models/packages/debian/file_entry_spec.rb
new file mode 100644
index 00000000000..7aa16bc0cce
--- /dev/null
+++ b/spec/models/packages/debian/file_entry_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::FileEntry, type: :model do
+ let_it_be(:package_file) { create(:debian_package_file, :dsc) }
+
+ let(:filename) { 'sample_1.2.3~alpha2.dsc' }
+ let(:size) { 671 }
+ let(:md5sum) { '3b0817804f669e16cdefac583ad88f0e' }
+ let(:section) { 'libs' }
+ let(:priority) { 'optional' }
+ let(:sha1sum) { '32ecbd674f0bfd310df68484d87752490685a8d6' }
+ let(:sha256sum) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
+
+ let(:file_entry) do
+ described_class.new(
+ filename: filename,
+ size: size,
+ md5sum: md5sum,
+ section: section,
+ priority: priority,
+ sha1sum: sha1sum,
+ sha256sum: sha256sum,
+ package_file: package_file
+ )
+ end
+
+ subject { file_entry }
+
+ describe 'validations' do
+ it { is_expected.to be_valid }
+
+ describe '#filename' do
+ it { is_expected.to validate_presence_of(:filename) }
+ it { is_expected.not_to allow_value('Hé').for(:filename) }
+ end
+
+ describe '#size' do
+ it { is_expected.to validate_presence_of(:size) }
+ end
+
+ describe '#md5sum' do
+ it { is_expected.to validate_presence_of(:md5sum) }
+ it { is_expected.not_to allow_value('12345678901234567890123456789012').for(:md5sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 12345678901234567890123456789012') }
+ end
+
+ describe '#section' do
+ it { is_expected.to validate_presence_of(:section) }
+ end
+
+ describe '#priority' do
+ it { is_expected.to validate_presence_of(:priority) }
+ end
+
+ describe '#sha1sum' do
+ it { is_expected.to validate_presence_of(:sha1sum) }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890').for(:sha1sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890') }
+ end
+
+ describe '#sha256sum' do
+ it { is_expected.to validate_presence_of(:sha256sum) }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890123456789012345678901234').for(:sha256sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234') }
+ end
+
+ describe '#package_file' do
+ it { is_expected.to validate_presence_of(:package_file) }
+ end
+ end
+
+ describe '#component' do
+ subject { file_entry.component }
+
+ context 'without section' do
+ let(:section) { nil }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with empty section' do
+ let(:section) { '' }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with ruby section' do
+ let(:section) { 'ruby' }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with contrib/ruby section' do
+ let(:section) { 'contrib/ruby' }
+
+ it { is_expected.to eq 'contrib' }
+ end
+ end
+end
diff --git a/spec/services/packages/debian/extract_changes_metadata_service_spec.rb b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
new file mode 100644
index 00000000000..a7d121819a1
--- /dev/null
+++ b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
@@ -0,0 +1,160 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ExtractChangesMetadataService do
+ describe '#execute' do
+ let_it_be(:distribution) { create(:debian_project_distribution, codename: 'unstable') }
+ let_it_be(:incoming) { create(:debian_incoming, project: distribution.project) }
+
+ let(:package_file) { incoming.package_files.last }
+ let(:service) { described_class.new(package_file) }
+
+ subject { service.execute }
+
+ context 'with valid package file' do
+ it 'extract metadata', :aggregate_failures do
+ expected_fields = { 'Architecture': 'source amd64', 'Binary': 'libsample0 sample-dev sample-udeb' }
+
+ expect(subject[:file_type]).to eq(:changes)
+ expect(subject[:architecture]).to be_nil
+ expect(subject[:fields]).to include(expected_fields)
+ expect(subject[:files].count).to eq(6)
+ end
+ end
+
+ context 'with invalid package file' do
+ let(:package_file) { incoming.package_files.first }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "is not a changes file")
+ end
+ end
+
+ context 'with invalid metadata' do
+ let(:md5_dsc) { '3b0817804f669e16cdefac583ad88f0e 671 libs optional sample_1.2.3~alpha2.dsc' }
+ let(:md5_source) { 'd79b34f58f61ff4ad696d9bd0b8daa68 864 libs optional sample_1.2.3~alpha2.tar.xz' }
+ let(:md5s) { "#{md5_dsc}\n#{md5_source}" }
+ let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc' }
+ let(:sha1_source) { '5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha1s) { "#{sha1_dsc}\n#{sha1_source}" }
+ let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc' }
+ let(:sha256_source) { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha256s) { "#{sha256_dsc}\n#{sha256_source}" }
+ let(:fields) { { Files: md5s, 'Checksums-Sha1': sha1s, 'Checksums-Sha256': sha256s } }
+ let(:metadata) { { file_type: :changes, architecture: 'amd64', fields: fields } }
+
+ before do
+ allow_next_instance_of(::Packages::Debian::ExtractMetadataService) do |extract_metadata_service|
+ allow(extract_metadata_service).to receive(:execute).and_return(metadata)
+ end
+ end
+
+ context 'without Files field' do
+ let(:md5s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Files field is missing")
+ end
+ end
+
+ context 'without Checksums-Sha1 field' do
+ let(:sha1s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Checksums-Sha1 field is missing")
+ end
+ end
+
+ context 'without Checksums-Sha256 field' do
+ let(:sha256s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Checksums-Sha256 field is missing")
+ end
+ end
+
+ context 'with file in Checksums-Sha1 but not in Files' do
+ let(:md5_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.dsc is listed in Checksums-Sha1 but not in Files")
+ end
+ end
+
+ context 'with different size in Checksums-Sha1' do
+ let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 42 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha1 differ")
+ end
+ end
+
+ context 'with file in Checksums-Sha256 but not in Files' do
+ let(:md5_dsc) { '' }
+ let(:sha1_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.dsc is listed in Checksums-Sha256 but not in Files")
+ end
+ end
+
+ context 'with different size in Checksums-Sha256' do
+ let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 42 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha256 differ")
+ end
+ end
+
+ context 'with file in Files but not in Checksums-Sha1' do
+ let(:sha1_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum can't be blank")
+ end
+ end
+
+ context 'with file in Files but not in Checksums-Sha256' do
+ let(:sha256_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum can't be blank")
+ end
+ end
+
+ context 'with invalid MD5' do
+ let(:md5_dsc) { '1234567890123456789012345678012 671 libs optional sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Md5sum mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 1234567890123456789012345678012")
+ end
+ end
+
+ context 'with invalid SHA1' do
+ let(:sha1_dsc) { '1234567890123456789012345678901234567890 671 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890")
+ end
+ end
+
+ context 'with invalid SHA256' do
+ let(:sha256_dsc) { '1234567890123456789012345678901234567890123456789012345678901234 671 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234")
+ end
+ end
+ end
+
+ context 'with missing package file' do
+ before do
+ incoming.package_files.first.destroy!
+ end
+
+ it 'raise ArgumentError' do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.tar.xz is listed in Files but was not uploaded")
+ end
+ end
+ end
+end