Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ec0ecba05c
commit
6cffe9ea21
|
|
@ -61,7 +61,7 @@ Consider adding checkboxes and expectations of users with certain levels of memb
|
|||
|
||||
<!-- See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
|
||||
|
||||
* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
|
||||
* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/workflow.html
|
||||
* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html -->
|
||||
|
||||
### Availability & Testing
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ Consider adding checkboxes and expectations of users with certain levels of memb
|
|||
|
||||
See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
|
||||
|
||||
* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
|
||||
* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/workflow.html
|
||||
* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html
|
||||
|
||||
### Availability & Testing
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
320f41869d84d64ebbec8d3e0febfb37eca05ffb
|
||||
88ef3e7f64498ae3574f29b0705c29cf3b4e9311
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
GlPagination,
|
||||
} from '@gitlab/ui';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import AccessorUtils from '~/lib/utils/accessor';
|
||||
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import { __ } from '~/locale';
|
||||
|
|
@ -138,6 +139,9 @@ export default {
|
|||
paginationRequired() {
|
||||
return !isEmpty(this.pagination);
|
||||
},
|
||||
errorTrackingHelpUrl() {
|
||||
return helpPagePath('operations/error_tracking');
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
pagination() {
|
||||
|
|
@ -404,7 +408,7 @@ export default {
|
|||
<template #description>
|
||||
<div>
|
||||
<span>{{ __('Monitor your errors by integrating with Sentry.') }}</span>
|
||||
<gl-link target="_blank" href="/help/user/project/operations/error_tracking.html">{{
|
||||
<gl-link target="_blank" :href="errorTrackingHelpUrl">{{
|
||||
__('More information')
|
||||
}}</gl-link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -159,7 +159,10 @@ class JiraService < IssueTrackerService
|
|||
# support any events.
|
||||
end
|
||||
|
||||
def find_issue(issue_key, options = {})
|
||||
def find_issue(issue_key, rendered_fields: false)
|
||||
options = {}
|
||||
options = options.merge(expand: 'renderedFields') if rendered_fields
|
||||
|
||||
jira_request { client.Issue.find(issue_key, options) }
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
%button.gl-alert-dismiss.js-close-2fa-enabled-success-alert{ type: 'button', aria: { label: _('Close') } }
|
||||
= sprite_icon('close', size: 16)
|
||||
.gl-alert-body
|
||||
= _('Congratulations! You have enabled Two-factor Authentication!')
|
||||
= html_escape(_('You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}.')) % { anchorOpen: '<a href="%{href}">'.html_safe % { href: help_page_path('user/profile/account/two_factor_authentication', anchor: 'generate-new-recovery-codes-using-ssh') }, anchorClose: '</a>'.html_safe }
|
||||
|
||||
.row.gl-mt-3.js-search-settings-section
|
||||
.col-lg-4.profile-settings-sidebar
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
|
||||
- else
|
||||
%p
|
||||
- help_link_start = '<a href="%{url}" target="_blank">' % { url: help_page_path('user/profile/account/two_factor_authentication') }
|
||||
- register_2fa_token = _('Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}.') % { free_otp_link:'<a href="https://freeotp.github.io/">FreeOTP</a>', help_link_start:help_link_start, help_link_end:'</a>' }
|
||||
- register_2fa_token = _('We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device.')
|
||||
= register_2fa_token.html_safe
|
||||
.row.gl-mb-3
|
||||
.col-md-4
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Change UI text for 2FA setup
|
||||
merge_request: 53677
|
||||
author:
|
||||
type: changed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update links to redirected docs
|
||||
merge_request: 53004
|
||||
author:
|
||||
type: other
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Map common severity values from a Prometheus alert payload
|
||||
merge_request: 50871
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: rubygem_packages
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52147
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299383
|
||||
milestone: '13.9'
|
||||
type: development
|
||||
group: group::package
|
||||
default_enabled: false
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: user_mode_in_session
|
||||
introduced_by_url:
|
||||
rollout_issue_url:
|
||||
milestone:
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16981
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321025
|
||||
milestone: 12.4
|
||||
type: development
|
||||
group:
|
||||
group: group::access
|
||||
default_enabled: false
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ production: &base
|
|||
## Gravatar
|
||||
## If using gravatar.com, there's nothing to change here. For Libravatar
|
||||
## you'll need to provide the custom URLs. For more information,
|
||||
## see: https://docs.gitlab.com/ee/customization/libravatar.html
|
||||
## see: https://docs.gitlab.com/ee/administration/libravatar.html
|
||||
gravatar:
|
||||
# Gravatar/Libravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
|
||||
# plain_url: "http://..." # default: https://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
|
||||
|
|
@ -590,7 +590,7 @@ production: &base
|
|||
# enabled: true
|
||||
# primary_api_url: http://localhost:5000/ # internal address to the primary registry, will be used by GitLab to directly communicate with primary registry API
|
||||
|
||||
## Feature Flag https://docs.gitlab.com/ee/user/project/operations/feature_flags.html
|
||||
## Feature Flag https://docs.gitlab.com/ee/operations/feature_flags.html
|
||||
feature_flags:
|
||||
unleash:
|
||||
# enabled: false
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
CHANGED_FILES_MESSAGE = <<~MSG
|
||||
For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
|
||||
Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<engineers_group>s group for a review.
|
||||
Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/usage_ping.html) and reach out to %<engineers_group>s group for a review.
|
||||
|
||||
|
||||
%<changed_files>s
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
self-managed: true
|
||||
gitlab-com: true
|
||||
packages: [Free, Premium, Ultimate]
|
||||
url: https://docs.gitlab.com/ee/user/project/operations/alert_management.html
|
||||
url: https://docs.gitlab.com/ee/operations/incident_management/index.html
|
||||
image_url: https://about.gitlab.com/images/13_1/alert_management.png
|
||||
published_at: 2020-06-22
|
||||
release: 13.1
|
||||
|
|
|
|||
|
|
@ -655,15 +655,41 @@ Non-determinism is the breeding ground for flaky and brittle specs. Such specs e
|
|||
|
||||
### Faking `Date` for determinism
|
||||
|
||||
Consider using `useFakeDate` to ensure a consistent value is returned with every `new Date()` or `Date.now()`.
|
||||
`Date` is faked by default in our Jest environment. This means every call to `Date()` or `Date.now()` returns a fixed deterministic value.
|
||||
|
||||
If you really need to change the default fake date, you can call `useFakeDate` within any `describe` block, and
|
||||
the date will be replaced for that specs within that `describe` context only:
|
||||
|
||||
```javascript
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
|
||||
describe('cool/component', () => {
|
||||
useFakeDate();
|
||||
// Default fake `Date`
|
||||
const TODAY = new Date();
|
||||
|
||||
// ...
|
||||
// NOTE: `useFakeDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
|
||||
describe("on Ada Lovelace's Birthday", () => {
|
||||
useFakeDate(1815, 11, 10)
|
||||
|
||||
it('Date is no longer default', () => {
|
||||
expect(new Date()).not.toEqual(TODAY);
|
||||
});
|
||||
});
|
||||
|
||||
it('Date is still default in this scope', () => {
|
||||
expect(new Date()).toEqual(TODAY)
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
Similarly, if you really need to use the real `Date` class, then you can import and call `useRealDate` within any `describe` block:
|
||||
|
||||
```javascript
|
||||
import { useRealDate } from 'helpers/fake_date';
|
||||
|
||||
// NOTE: `useRealDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
|
||||
describe('with real date', () => {
|
||||
useRealDate();
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,14 @@ values extracted from the [`alerts` field in webhook payload](https://prometheus
|
|||
- `full_query`: Alert query extracted from the payload's `generatorURL` field
|
||||
- Optional list of attached annotations extracted from `annotations/*`
|
||||
- Alert [GFM](../../user/markdown.md): GitLab Flavored Markdown from the payload's `annotations/gitlab_incident_markdown` field.
|
||||
- Alert Severity (introduced in GitLab version [13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50871):
|
||||
Extracted from the alert payload field `labels/severity`. Maps case-insensitive
|
||||
value to [Alert's severity](../incident_management/alerts.md#alert-severity):
|
||||
- **Critical**: `critical`, `s1`, `p1`, `emergency`, `fatal`, or any value not in this list
|
||||
- **High**: `high`, `s2`, `p2`, `major`, `page`
|
||||
- **Medium**: `medium`, `s3`, `p3`, `error`, `alert`
|
||||
- **Low**: `low`, `s4`, `p4`, `warn`, `warning`
|
||||
- **Info**: `info`, `s5`, `p5`, `debug`, `information`, `notice`
|
||||
|
||||
When GitLab receives a **Recovery Alert**, it closes the associated issue.
|
||||
This action is recorded as a system message on the issue indicating that it
|
||||
|
|
|
|||
|
|
@ -1285,6 +1285,7 @@ You may need to reconfigure or restart GitLab for the changes to take effect.
|
|||
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
|
||||
-- Clear instance tokens
|
||||
UPDATE application_settings SET runners_registration_token_encrypted = null;
|
||||
UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
|
||||
-- Clear runner tokens
|
||||
UPDATE ci_runners SET token = null, token_encrypted = null;
|
||||
```
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ module API
|
|||
mount ::API::RemoteMirrors
|
||||
mount ::API::Repositories
|
||||
mount ::API::ResourceAccessTokens
|
||||
mount ::API::RubygemPackages
|
||||
mount ::API::Search
|
||||
mount ::API::Services
|
||||
mount ::API::Settings
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module API
|
|||
default_format :json
|
||||
|
||||
authenticate_with do |accept|
|
||||
accept.token_types(:personal_access_token, :deploy_token, :job_token)
|
||||
accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username)
|
||||
.sent_through(:http_basic_auth)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module API
|
|||
default_format :json
|
||||
|
||||
authenticate_with do |accept|
|
||||
accept.token_types(:personal_access_token, :deploy_token, :job_token)
|
||||
accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username)
|
||||
.sent_through(:http_basic_auth)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
###
|
||||
# API endpoints for the RubyGem package registry
|
||||
module API
|
||||
class RubygemPackages < ::API::Base
|
||||
include ::API::Helpers::Authentication
|
||||
helpers ::API::Helpers::PackagesHelpers
|
||||
|
||||
feature_category :package_registry
|
||||
|
||||
# The Marshal version can be found by "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
|
||||
# Updating the version should require a GitLab API version change.
|
||||
MARSHAL_VERSION = '4.8'
|
||||
|
||||
FILE_NAME_REQUIREMENTS = {
|
||||
file_name: API::NO_SLASH_URL_PART_REGEX
|
||||
}.freeze
|
||||
|
||||
content_type :binary, 'application/octet-stream'
|
||||
|
||||
authenticate_with do |accept|
|
||||
accept.token_types(:personal_access_token, :deploy_token, :job_token)
|
||||
.sent_through(:http_token)
|
||||
end
|
||||
|
||||
before do
|
||||
require_packages_enabled!
|
||||
authenticate!
|
||||
not_found! unless Feature.enabled?(:rubygem_packages, user_project)
|
||||
end
|
||||
|
||||
params do
|
||||
requires :id, type: String, desc: 'The ID or full path of a project'
|
||||
end
|
||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||
namespace ':id/packages/rubygems' do
|
||||
desc 'Download the spec index file' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
params do
|
||||
requires :file_name, type: String, desc: 'Spec file name'
|
||||
end
|
||||
get ":file_name", requirements: FILE_NAME_REQUIREMENTS do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299267
|
||||
not_found!
|
||||
end
|
||||
|
||||
desc 'Download the gemspec file' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
params do
|
||||
requires :file_name, type: String, desc: 'Gemspec file name'
|
||||
end
|
||||
get "quick/Marshal.#{MARSHAL_VERSION}/:file_name", requirements: FILE_NAME_REQUIREMENTS do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299284
|
||||
not_found!
|
||||
end
|
||||
|
||||
desc 'Download the .gem package' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
params do
|
||||
requires :file_name, type: String, desc: 'Package file name'
|
||||
end
|
||||
get "gems/:file_name", requirements: FILE_NAME_REQUIREMENTS do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299283
|
||||
not_found!
|
||||
end
|
||||
|
||||
namespace 'api/v1' do
|
||||
desc 'Authorize a gem upload from workhorse' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
post 'gems/authorize' do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299263
|
||||
not_found!
|
||||
end
|
||||
|
||||
desc 'Upload a gem' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
post 'gems' do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299263
|
||||
not_found!
|
||||
end
|
||||
|
||||
desc 'Fetch a list of dependencies' do
|
||||
detail 'This feature was introduced in GitLab 13.9'
|
||||
end
|
||||
params do
|
||||
optional :gems, type: String, desc: 'Comma delimited gem names'
|
||||
end
|
||||
get 'dependencies' do
|
||||
# To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299282
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -133,7 +133,7 @@ class Feature
|
|||
|
||||
# This method is called from config/initializers/flipper.rb and can be used
|
||||
# to register Flipper groups.
|
||||
# See https://docs.gitlab.com/ee/development/feature_flags.html#feature-groups
|
||||
# See https://docs.gitlab.com/ee/development/feature_flags/index.html
|
||||
def register_feature_groups
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Attribute mapping for alerts via prometheus alerting integration.
|
||||
module Gitlab
|
||||
module AlertManagement
|
||||
module Payload
|
||||
# Attribute mapping for alerts via prometheus alerting integration.
|
||||
class Prometheus < Base
|
||||
attribute :alert_markdown, paths: %w(annotations gitlab_incident_markdown)
|
||||
attribute :annotations, paths: 'annotations'
|
||||
|
|
@ -26,13 +26,49 @@ module Gitlab
|
|||
paths: [%w(annotations title),
|
||||
%w(annotations summary),
|
||||
%w(labels alertname)]
|
||||
|
||||
attribute :starts_at_raw,
|
||||
paths: [%w(startsAt)]
|
||||
private :starts_at_raw
|
||||
|
||||
attribute :severity_raw, paths: %w(labels severity)
|
||||
private :severity_raw
|
||||
|
||||
METRIC_TIME_WINDOW = 30.minutes
|
||||
|
||||
SEVERITY_MAP = {
|
||||
'critical' => :critical,
|
||||
'high' => :high,
|
||||
'medium' => :medium,
|
||||
'low' => :low,
|
||||
'info' => :info,
|
||||
's1' => :critical,
|
||||
's2' => :high,
|
||||
's3' => :medium,
|
||||
's4' => :low,
|
||||
's5' => :info,
|
||||
'p1' => :critical,
|
||||
'p2' => :high,
|
||||
'p3' => :medium,
|
||||
'p4' => :low,
|
||||
'p5' => :info,
|
||||
'debug' => :info,
|
||||
'information' => :info,
|
||||
'notice' => :info,
|
||||
'warn' => :low,
|
||||
'warning' => :low,
|
||||
'minor' => :low,
|
||||
'error' => :medium,
|
||||
'major' => :high,
|
||||
'emergency' => :critical,
|
||||
'fatal' => :critical,
|
||||
'alert' => :medium,
|
||||
'page' => :high
|
||||
}.freeze
|
||||
|
||||
# Handle an unmapped severity value the same way we treat missing values
|
||||
# so we can fallback to alert's default severity `critical`.
|
||||
UNMAPPED_SEVERITY = nil
|
||||
|
||||
def monitoring_tool
|
||||
Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
|
||||
end
|
||||
|
|
@ -65,6 +101,12 @@ module Gitlab
|
|||
project && title && starts_at_raw
|
||||
end
|
||||
|
||||
def severity
|
||||
return unless severity_raw
|
||||
|
||||
SEVERITY_MAP.fetch(severity_raw.to_s.downcase, UNMAPPED_SEVERITY)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def plain_gitlab_fingerprint
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module Gitlab
|
|||
|
||||
attr_reader :location
|
||||
|
||||
validates :location, inclusion: { in: %i[http_basic_auth] }
|
||||
validates :location, inclusion: { in: %i[http_basic_auth http_token] }
|
||||
|
||||
def initialize(location)
|
||||
@location = location
|
||||
|
|
@ -21,6 +21,8 @@ module Gitlab
|
|||
case @location
|
||||
when :http_basic_auth
|
||||
extract_from_http_basic_auth request
|
||||
when :http_token
|
||||
extract_from_http_token request
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -32,6 +34,13 @@ module Gitlab
|
|||
|
||||
UsernameAndPassword.new(username, password)
|
||||
end
|
||||
|
||||
def extract_from_http_token(request)
|
||||
password = request.headers['Authorization']
|
||||
return unless password.present?
|
||||
|
||||
UsernameAndPassword.new(nil, password)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,16 @@ module Gitlab
|
|||
|
||||
attr_reader :token_type
|
||||
|
||||
validates :token_type, inclusion: { in: %i[personal_access_token job_token deploy_token] }
|
||||
validates :token_type, inclusion: {
|
||||
in: %i[
|
||||
personal_access_token_with_username
|
||||
job_token_with_username
|
||||
deploy_token_with_username
|
||||
personal_access_token
|
||||
job_token
|
||||
deploy_token
|
||||
]
|
||||
}
|
||||
|
||||
def initialize(token_type)
|
||||
@token_type = token_type
|
||||
|
|
@ -38,49 +47,94 @@ module Gitlab
|
|||
|
||||
when :deploy_token
|
||||
resolve_deploy_token raw
|
||||
|
||||
when :personal_access_token_with_username
|
||||
resolve_personal_access_token_with_username raw
|
||||
|
||||
when :job_token_with_username
|
||||
resolve_job_token_with_username raw
|
||||
|
||||
when :deploy_token_with_username
|
||||
resolve_deploy_token_with_username raw
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resolve_personal_access_token(raw)
|
||||
# Check if the password is a personal access token
|
||||
pat = ::PersonalAccessToken.find_by_token(raw.password)
|
||||
return unless pat
|
||||
def resolve_personal_access_token_with_username(raw)
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless raw.username
|
||||
|
||||
# Ensure that the username matches the token. This check is a subtle
|
||||
# departure from the existing behavior of #find_personal_access_token_from_http_basic_auth.
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_435907856
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless pat.user.username == raw.username
|
||||
with_personal_access_token(raw) do |pat|
|
||||
break unless pat
|
||||
|
||||
pat
|
||||
# Ensure that the username matches the token. This check is a subtle
|
||||
# departure from the existing behavior of #find_personal_access_token_from_http_basic_auth.
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_435907856
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless pat.user.username == raw.username
|
||||
|
||||
pat
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_job_token(raw)
|
||||
def resolve_job_token_with_username(raw)
|
||||
# Only look for a job if the username is correct
|
||||
return if ::Gitlab::Auth::CI_JOB_USER != raw.username
|
||||
|
||||
job = ::Ci::AuthJobFinder.new(token: raw.password).execute
|
||||
with_job_token(raw) do |job|
|
||||
job
|
||||
end
|
||||
end
|
||||
|
||||
# Actively reject credentials with the username `gitlab-ci-token` if
|
||||
# the password is not a valid job token. This replicates existing
|
||||
# behavior of #find_user_from_job_token.
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless job
|
||||
def resolve_deploy_token_with_username(raw)
|
||||
with_deploy_token(raw) do |token|
|
||||
break unless token
|
||||
|
||||
job
|
||||
# Ensure that the username matches the token. This check is a subtle
|
||||
# departure from the existing behavior of #deploy_token_from_request.
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_474826205
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless token.username == raw.username
|
||||
|
||||
token
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_personal_access_token(raw)
|
||||
with_personal_access_token(raw) do |pat|
|
||||
pat
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_job_token(raw)
|
||||
with_job_token(raw) do |job|
|
||||
job
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_deploy_token(raw)
|
||||
# Check if the password is a deploy token
|
||||
with_deploy_token(raw) do |token|
|
||||
token
|
||||
end
|
||||
end
|
||||
|
||||
def with_personal_access_token(raw, &block)
|
||||
pat = ::PersonalAccessToken.find_by_token(raw.password)
|
||||
return unless pat
|
||||
|
||||
yield(pat)
|
||||
end
|
||||
|
||||
def with_deploy_token(raw, &block)
|
||||
token = ::DeployToken.active.find_by_token(raw.password)
|
||||
return unless token
|
||||
|
||||
# Ensure that the username matches the token. This check is a subtle
|
||||
# departure from the existing behavior of #deploy_token_from_request.
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_474826205
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless token.username == raw.username
|
||||
yield(token)
|
||||
end
|
||||
|
||||
token
|
||||
def with_job_token(raw, &block)
|
||||
job = ::Ci::AuthJobFinder.new(token: raw.password).execute
|
||||
raise ::Gitlab::Auth::UnauthorizedError unless job
|
||||
|
||||
yield(job)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -40,14 +40,14 @@ verify:jdk8:
|
|||
<<: *verify
|
||||
|
||||
# To deploy packages from CI, create a ci_settings.xml file
|
||||
# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details.
|
||||
# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for more details.
|
||||
# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
|
||||
# For `master` branch run `mvn deploy` automatically.
|
||||
deploy:jdk8:
|
||||
stage: deploy
|
||||
script:
|
||||
- if [ ! -f ci_settings.xml ];
|
||||
then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for instructions.";
|
||||
then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for instructions.";
|
||||
fi
|
||||
- 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
|
||||
only:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/license_compliance/
|
||||
# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
|
||||
#
|
||||
# Configure the scanning tool through the environment variables.
|
||||
# List of the variables: https://gitlab.com/gitlab-org/security-products/analyzers/license-finder#settings
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ module Gitlab
|
|||
include TSort
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
def initialize(variables)
|
||||
def initialize(variables, project)
|
||||
@variables = variables
|
||||
@project = project
|
||||
end
|
||||
|
||||
def valid?
|
||||
|
|
@ -19,7 +20,7 @@ module Gitlab
|
|||
# errors sorts an array of variables, ignoring unknown variable references,
|
||||
# and returning an error string if a circular variable reference is found
|
||||
def errors
|
||||
return if Feature.disabled?(:variable_inside_variable)
|
||||
return if Feature.disabled?(:variable_inside_variable, @project)
|
||||
|
||||
strong_memoize(:errors) do
|
||||
# Check for cyclic dependencies and build error message in that case
|
||||
|
|
@ -34,7 +35,7 @@ module Gitlab
|
|||
# sort sorts an array of variables, ignoring unknown variable references.
|
||||
# If a circular variable reference is found, the original array is returned
|
||||
def sort
|
||||
return @variables if Feature.disabled?(:variable_inside_variable)
|
||||
return @variables if Feature.disabled?(:variable_inside_variable, @project)
|
||||
return @variables if errors
|
||||
|
||||
tsort
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ module Gitlab
|
|||
gon.suggested_label_colors = LabelsHelper.suggested_colors
|
||||
gon.first_day_of_week = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week
|
||||
gon.ee = Gitlab.ee?
|
||||
gon.dot_com = Gitlab.com?
|
||||
|
||||
if current_user
|
||||
gon.current_user_id = current_user.id
|
||||
|
|
|
|||
|
|
@ -48,3 +48,13 @@
|
|||
'incident_management_incident_unrelate',
|
||||
'incident_management_incident_change_confidential'
|
||||
]
|
||||
- name: i_testing_paid_monthly_active_user_total
|
||||
operator: OR
|
||||
source: redis
|
||||
events: [
|
||||
'i_testing_web_performance_widget_total',
|
||||
'i_testing_full_code_quality_report_total',
|
||||
'i_testing_group_code_coverage_visit_total',
|
||||
'i_testing_load_performance_widget_total',
|
||||
'i_testing_metrics_report_widget_total'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7567,9 +7567,6 @@ msgstr ""
|
|||
msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Congratulations! You have enabled Two-factor Authentication!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Congratulations, your free trial is activated."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -15747,9 +15744,6 @@ msgstr ""
|
|||
msgid "Install GitLab Runner on Kubernetes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Install on clusters"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -32543,6 +32537,9 @@ msgstr ""
|
|||
msgid "We heard back from your device. You have been authenticated."
|
||||
msgstr ""
|
||||
|
||||
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
|
||||
msgstr ""
|
||||
|
||||
msgid "We recommend that you buy more Pipeline minutes to avoid any interruption of service."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -33457,6 +33454,9 @@ msgstr ""
|
|||
msgid "You have reached your project limit"
|
||||
msgstr ""
|
||||
|
||||
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
|
||||
msgstr ""
|
||||
|
||||
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ run all the tests in the `Test::Instance::All` scenario, and then enable the
|
|||
feature flag again if it was enabled earlier.
|
||||
|
||||
Note: the QA framework doesn't currently allow you to easily toggle a feature
|
||||
flag during a single test, [as you can in unit tests](https://docs.gitlab.com/ee/development/feature_flags.html#specs),
|
||||
flag during a single test, [as you can in unit tests](https://docs.gitlab.com/ee/development/feature_flags/index.html),
|
||||
but [that capability is planned](https://gitlab.com/gitlab-org/quality/team-tasks/issues/77).
|
||||
|
||||
Note also that the `--` separator isn't used because `--enable-feature` and `--disable-feature`
|
||||
|
|
|
|||
|
|
@ -765,7 +765,7 @@ RSpec.describe 'Login' do
|
|||
click_link 'Proceed'
|
||||
|
||||
expect(current_path).to eq(profile_account_path)
|
||||
expect(page).to have_content('Congratulations! You have enabled Two-factor Authentication!')
|
||||
expect(page).to have_content('You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can use that key to generate additional recovery codes.')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// Frida Kahlo's birthday (6 = July)
|
||||
export const DEFAULT_ARGS = [2020, 6, 6];
|
||||
const DEFAULT_ARGS = [2020, 6, 6];
|
||||
|
||||
const RealDate = Date;
|
||||
|
||||
const isMocked = (val) => Boolean(val.mock);
|
||||
|
||||
export const createFakeDateClass = (ctorDefault) => {
|
||||
const createFakeDateClass = (ctorDefaultParam = []) => {
|
||||
const ctorDefault = ctorDefaultParam.length ? ctorDefaultParam : DEFAULT_ARGS;
|
||||
|
||||
const FakeDate = new Proxy(RealDate, {
|
||||
construct: (target, argArray) => {
|
||||
const ctorArgs = argArray.length ? argArray : ctorDefault;
|
||||
|
|
@ -39,11 +41,20 @@ export const createFakeDateClass = (ctorDefault) => {
|
|||
return FakeDate;
|
||||
};
|
||||
|
||||
export const useFakeDate = (...args) => {
|
||||
const FakeDate = createFakeDateClass(args.length ? args : DEFAULT_ARGS);
|
||||
const setGlobalDateToFakeDate = (...args) => {
|
||||
const FakeDate = createFakeDateClass(args);
|
||||
global.Date = FakeDate;
|
||||
};
|
||||
|
||||
export const useRealDate = () => {
|
||||
const setGlobalDateToRealDate = () => {
|
||||
global.Date = RealDate;
|
||||
};
|
||||
|
||||
// We use commonjs so that the test environment module can pick this up
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
module.exports = {
|
||||
setGlobalDateToFakeDate,
|
||||
setGlobalDateToRealDate,
|
||||
createFakeDateClass,
|
||||
RealDate,
|
||||
};
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
import { createFakeDateClass, DEFAULT_ARGS, useRealDate } from './fake_date';
|
||||
import { createFakeDateClass } from './fake_date';
|
||||
|
||||
describe('spec/helpers/fake_date', () => {
|
||||
describe('createFakeDateClass', () => {
|
||||
let FakeDate;
|
||||
|
||||
beforeAll(() => {
|
||||
useRealDate();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
FakeDate = createFakeDateClass(DEFAULT_ARGS);
|
||||
FakeDate = createFakeDateClass();
|
||||
});
|
||||
|
||||
it('should use default args', () => {
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export * from './fake_date';
|
||||
export * from './jest';
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { createJestExecutionWatcher } from '../jest_execution_watcher';
|
||||
import { RealDate, createFakeDateClass } from './fake_date';
|
||||
|
||||
const throwInsideExecutionError = (fnName) => {
|
||||
throw new Error(`Cannot call "${fnName}" during test execution (i.e. within "it", "beforeEach", "beforeAll", etc.).
|
||||
|
||||
Instead, please move the call to "${fnName}" inside the "describe" block itself.
|
||||
|
||||
describe('', () => {
|
||||
+ ${fnName}();
|
||||
|
||||
it('', () => {
|
||||
- ${fnName}();
|
||||
})
|
||||
})
|
||||
`);
|
||||
};
|
||||
|
||||
const isExecutingTest = createJestExecutionWatcher();
|
||||
|
||||
export const useDateInScope = (fnName, factory) => {
|
||||
if (isExecutingTest()) {
|
||||
throwInsideExecutionError(fnName);
|
||||
}
|
||||
|
||||
let origDate;
|
||||
|
||||
beforeAll(() => {
|
||||
origDate = global.Date;
|
||||
global.Date = factory();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.Date = origDate;
|
||||
});
|
||||
};
|
||||
|
||||
export const useFakeDate = (...args) =>
|
||||
useDateInScope('useFakeDate', () => createFakeDateClass(args));
|
||||
|
||||
export const useRealDate = () => useDateInScope('useRealDate', () => RealDate);
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export const createJestExecutionWatcher = () => {
|
||||
let isExecuting = false;
|
||||
|
||||
beforeAll(() => {
|
||||
isExecuting = true;
|
||||
});
|
||||
afterAll(() => {
|
||||
isExecuting = false;
|
||||
});
|
||||
|
||||
return () => isExecuting;
|
||||
};
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import ExpiresAtField from '~/access_tokens/components/expires_at_field.vue';
|
||||
|
||||
describe('~/access_tokens/components/expires_at_field', () => {
|
||||
useFakeDate();
|
||||
|
||||
let wrapper;
|
||||
|
||||
const createComponent = () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { GlLineChart } from '@gitlab/ui/dist/charts';
|
|||
import { GlAlert } from '@gitlab/ui';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import ProjectsAndGroupChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
|
||||
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
|
||||
import projectsQuery from '~/analytics/instance_statistics/graphql/queries/projects.query.graphql';
|
||||
|
|
@ -45,8 +44,8 @@ describe('ProjectsAndGroupChart', () => {
|
|||
|
||||
return shallowMount(ProjectsAndGroupChart, {
|
||||
props: {
|
||||
startDate: useFakeDate(2020, 9, 26),
|
||||
endDate: useFakeDate(2020, 10, 1),
|
||||
startDate: new Date(2020, 9, 26),
|
||||
endDate: new Date(2020, 10, 1),
|
||||
totalDataPoints: mockCountsData2.length,
|
||||
},
|
||||
localVue,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { GlAreaChart } from '@gitlab/ui/dist/charts';
|
|||
import { GlAlert } from '@gitlab/ui';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
|
||||
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
|
||||
import usersQuery from '~/analytics/instance_statistics/graphql/queries/users.query.graphql';
|
||||
|
|
@ -31,8 +30,8 @@ describe('UsersChart', () => {
|
|||
|
||||
return shallowMount(UsersChart, {
|
||||
props: {
|
||||
startDate: useFakeDate(2020, 9, 26),
|
||||
endDate: useFakeDate(2020, 10, 1),
|
||||
startDate: new Date(2020, 9, 26),
|
||||
endDate: new Date(2020, 10, 1),
|
||||
totalDataPoints: mockCountsData2.length,
|
||||
},
|
||||
localVue,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ describe('CompareDropdownLayout', () => {
|
|||
expect(findListItemsData()).toEqual([
|
||||
{
|
||||
href: 'version/1',
|
||||
text: 'version 1 (base) abcdef1 1 commit 2 years ago',
|
||||
text: 'version 1 (base) abcdef1 1 commit 1 year ago',
|
||||
createdAt: TEST_CREATED_AT,
|
||||
isActive: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const path = require('path');
|
|||
const { ErrorWithStack } = require('jest-util');
|
||||
const JSDOMEnvironment = require('jest-environment-jsdom');
|
||||
const { TEST_HOST } = require('./__helpers__/test_constants');
|
||||
const { setGlobalDateToFakeDate } = require('./__helpers__/fake_date/fake_date');
|
||||
|
||||
const ROOT_PATH = path.resolve(__dirname, '../..');
|
||||
|
||||
|
|
@ -12,6 +13,10 @@ class CustomEnvironment extends JSDOMEnvironment {
|
|||
// Setup testURL so that window.location is setup properly
|
||||
super({ ...config, testURL: TEST_HOST }, context);
|
||||
|
||||
// Fake the `Date` for `jsdom` which fixes things like document.cookie
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
|
||||
setGlobalDateToFakeDate();
|
||||
|
||||
Object.assign(context.console, {
|
||||
error(...args) {
|
||||
throw new ErrorWithStack(
|
||||
|
|
|
|||
|
|
@ -298,9 +298,7 @@ describe('ErrorTrackingList', () => {
|
|||
});
|
||||
|
||||
it('shows empty state', () => {
|
||||
expect(wrapper.find('a').attributes('href')).toBe(
|
||||
'/help/user/project/operations/error_tracking.html',
|
||||
);
|
||||
expect(wrapper.find(GlEmptyState).isVisible()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import Vue from 'vue';
|
|||
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { useRealDate } from 'helpers/fake_date';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import appComponent from '~/frequent_items/components/app.vue';
|
||||
import eventHub from '~/frequent_items/event_hub';
|
||||
|
|
@ -93,23 +94,27 @@ describe('Frequent Items App Component', () => {
|
|||
expect(projects.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should increase frequency of report if it was logged multiple times over the course of an hour', () => {
|
||||
let projects;
|
||||
const newTimestamp = Date.now() + HOUR_IN_MS + 1;
|
||||
describe('with real date', () => {
|
||||
useRealDate();
|
||||
|
||||
vm.logItemAccess(session.storageKey, session.project);
|
||||
projects = JSON.parse(storage[session.storageKey]);
|
||||
it('should increase frequency of report if it was logged multiple times over the course of an hour', () => {
|
||||
let projects;
|
||||
const newTimestamp = Date.now() + HOUR_IN_MS + 1;
|
||||
|
||||
expect(projects[0].frequency).toBe(1);
|
||||
vm.logItemAccess(session.storageKey, session.project);
|
||||
projects = JSON.parse(storage[session.storageKey]);
|
||||
|
||||
vm.logItemAccess(session.storageKey, {
|
||||
...session.project,
|
||||
lastAccessedOn: newTimestamp,
|
||||
expect(projects[0].frequency).toBe(1);
|
||||
|
||||
vm.logItemAccess(session.storageKey, {
|
||||
...session.project,
|
||||
lastAccessedOn: newTimestamp,
|
||||
});
|
||||
projects = JSON.parse(storage[session.storageKey]);
|
||||
|
||||
expect(projects[0].frequency).toBe(2);
|
||||
expect(projects[0].lastAccessedOn).not.toBe(session.project.lastAccessedOn);
|
||||
});
|
||||
projects = JSON.parse(storage[session.storageKey]);
|
||||
|
||||
expect(projects[0].frequency).toBe(2);
|
||||
expect(projects[0].lastAccessedOn).not.toBe(session.project.lastAccessedOn);
|
||||
});
|
||||
|
||||
it('should always update project metadata', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
|
||||
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
|
||||
import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
|
||||
|
||||
|
|
@ -19,6 +19,9 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
|
|||
});
|
||||
|
||||
describe('IssuableItem', () => {
|
||||
// The mock data is dependent that this is after our default date
|
||||
useFakeDate(2020, 11, 11);
|
||||
|
||||
const mockLabels = mockIssuable.labels.nodes;
|
||||
const mockAuthor = mockIssuable.author;
|
||||
const originalUrl = gon.gitlab_url;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
|
||||
import IssuableBody from '~/issuable_show/components/issuable_body.vue';
|
||||
|
||||
|
|
@ -35,6 +36,9 @@ const createComponent = (propsData = issuableBodyProps) =>
|
|||
});
|
||||
|
||||
describe('IssuableBody', () => {
|
||||
// Some assertions expect a date later than our default
|
||||
useFakeDate(2020, 11, 11);
|
||||
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -98,11 +102,8 @@ describe('IssuableBody', () => {
|
|||
|
||||
it('renders issuable edit info', () => {
|
||||
const editedEl = wrapper.find('small');
|
||||
const sanitizedText = editedEl.text().replace(/\n/g, ' ').replace(/\s+/g, ' ');
|
||||
|
||||
expect(sanitizedText).toContain('Edited');
|
||||
expect(sanitizedText).toContain('ago');
|
||||
expect(sanitizedText).toContain(`by ${mockIssuable.updatedBy.name}`);
|
||||
expect(editedEl.text()).toMatchInterpolatedText('Edited 3 months ago by Administrator');
|
||||
});
|
||||
|
||||
it('renders issuable-edit-form when `editFormVisible` prop is true', async () => {
|
||||
|
|
|
|||
|
|
@ -12,9 +12,15 @@ import { simpleIssue, testAssignees, testLabels } from '../issuable_list_test_da
|
|||
|
||||
jest.mock('~/user_popovers');
|
||||
|
||||
const TEST_NOW = '2019-08-28T20:03:04.713Z';
|
||||
const TEST_MONTH_AGO = '2019-07-28';
|
||||
const TEST_MONTH_LATER = '2019-09-30';
|
||||
const TODAY = new Date();
|
||||
|
||||
const createTestDateFromDelta = (timeDelta) =>
|
||||
formatDate(new Date(TODAY.getTime() + timeDelta), 'yyyy-mm-dd');
|
||||
|
||||
// TODO: Encapsulate date helpers https://gitlab.com/gitlab-org/gitlab/-/issues/320883
|
||||
const MONTHS_IN_MS = 1000 * 60 * 60 * 24 * 31;
|
||||
const TEST_MONTH_AGO = createTestDateFromDelta(-MONTHS_IN_MS);
|
||||
const TEST_MONTH_LATER = createTestDateFromDelta(MONTHS_IN_MS);
|
||||
const DATE_FORMAT = 'mmm d, yyyy';
|
||||
const TEST_USER_NAME = 'Tyler Durden';
|
||||
const TEST_BASE_URL = `${TEST_HOST}/issues`;
|
||||
|
|
@ -26,16 +32,8 @@ const TEST_MILESTONE = {
|
|||
const TEXT_CLOSED = 'CLOSED';
|
||||
const TEST_META_COUNT = 100;
|
||||
|
||||
// Use FixedDate so that time sensitive info in snapshots don't fail
|
||||
class FixedDate extends Date {
|
||||
constructor(date = TEST_NOW) {
|
||||
super(date);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Issuable component', () => {
|
||||
let issuable;
|
||||
let DateOrig;
|
||||
let wrapper;
|
||||
|
||||
const factory = (props = {}, scopedLabelsAvailable = false) => {
|
||||
|
|
@ -63,15 +61,6 @@ describe('Issuable component', () => {
|
|||
wrapper = null;
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
DateOrig = window.Date;
|
||||
window.Date = FixedDate;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
window.Date = DateOrig;
|
||||
});
|
||||
|
||||
const checkExists = (findFn) => () => findFn().exists();
|
||||
const hasIcon = (iconName, iconWrapper = wrapper) =>
|
||||
iconWrapper.findAll(GlIcon).wrappers.some((icon) => icon.props('name') === iconName);
|
||||
|
|
|
|||
|
|
@ -8,19 +8,9 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
|||
|
||||
const originalRelease = getJSONFixture('api/releases/release.json');
|
||||
|
||||
const mockFutureDate = new Date(9999, 0, 0).toISOString();
|
||||
let mockIsFutureRelease = false;
|
||||
|
||||
jest.mock('~/vue_shared/mixins/timeago', () => ({
|
||||
methods: {
|
||||
timeFormatted() {
|
||||
return mockIsFutureRelease ? 'in 1 month' : '7 fortnights ago';
|
||||
},
|
||||
tooltipTitle() {
|
||||
return 'February 30, 2401';
|
||||
},
|
||||
},
|
||||
}));
|
||||
// TODO: Encapsulate date helpers https://gitlab.com/gitlab-org/gitlab/-/issues/320883
|
||||
const MONTHS_IN_MS = 1000 * 60 * 60 * 24 * 31;
|
||||
const mockFutureDate = new Date(new Date().getTime() + MONTHS_IN_MS).toISOString();
|
||||
|
||||
describe('Release block footer', () => {
|
||||
let wrapper;
|
||||
|
|
@ -44,7 +34,6 @@ describe('Release block footer', () => {
|
|||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
mockIsFutureRelease = false;
|
||||
});
|
||||
|
||||
const commitInfoSection = () => wrapper.find('.js-commit-info');
|
||||
|
|
@ -88,7 +77,7 @@ describe('Release block footer', () => {
|
|||
|
||||
it('renders the author and creation time info', () => {
|
||||
expect(trimText(authorDateInfoSection().text())).toBe(
|
||||
`Created 7 fortnights ago by ${release.author.username}`,
|
||||
`Created 1 year ago by ${release.author.username}`,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -100,7 +89,6 @@ describe('Release block footer', () => {
|
|||
|
||||
describe('renders the author and creation time info with future release date', () => {
|
||||
beforeEach(() => {
|
||||
mockIsFutureRelease = true;
|
||||
factory({ releasedAt: mockFutureDate });
|
||||
});
|
||||
|
||||
|
|
@ -113,7 +101,6 @@ describe('Release block footer', () => {
|
|||
|
||||
describe('when the release date is in the future', () => {
|
||||
beforeEach(() => {
|
||||
mockIsFutureRelease = true;
|
||||
factory({ releasedAt: mockFutureDate });
|
||||
});
|
||||
|
||||
|
|
@ -177,13 +164,12 @@ describe('Release block footer', () => {
|
|||
beforeEach(() => factory({ author: undefined }));
|
||||
|
||||
it('renders the release date without the author name', () => {
|
||||
expect(trimText(authorDateInfoSection().text())).toBe(`Created 7 fortnights ago`);
|
||||
expect(trimText(authorDateInfoSection().text())).toBe(`Created 1 year ago`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('future release without any author info', () => {
|
||||
beforeEach(() => {
|
||||
mockIsFutureRelease = true;
|
||||
factory({ author: undefined, releasedAt: mockFutureDate });
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'jquery';
|
|||
|
||||
import * as jqueryMatchers from 'custom-jquery-matchers';
|
||||
import { config as testUtilsConfig } from '@vue/test-utils';
|
||||
import { setGlobalDateToFakeDate } from 'helpers/fake_date';
|
||||
import Translate from '~/vue_shared/translate';
|
||||
import { initializeTestTimeout } from './__helpers__/timeout';
|
||||
import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
|
||||
|
|
@ -20,6 +21,10 @@ process.on('unhandledRejection', global.promiseRejectionHandler);
|
|||
|
||||
setupManualMocks();
|
||||
|
||||
// Fake the `Date` for the rest of the jest spec runtime environment.
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
|
||||
setGlobalDateToFakeDate();
|
||||
|
||||
afterEach(() =>
|
||||
// give Promises a bit more time so they fail the right test
|
||||
new Promise(setImmediate).then(() => {
|
||||
|
|
|
|||
|
|
@ -156,8 +156,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
|
|||
end
|
||||
|
||||
describe '#gitlab_fingerprint' do
|
||||
subject { parsed_payload.gitlab_fingerprint }
|
||||
|
||||
let(:raw_payload) do
|
||||
{
|
||||
'startsAt' => Time.current.to_s,
|
||||
|
|
@ -166,6 +164,8 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
|
|||
}
|
||||
end
|
||||
|
||||
subject { parsed_payload.gitlab_fingerprint }
|
||||
|
||||
it 'returns a fingerprint' do
|
||||
plain_fingerprint = [
|
||||
parsed_payload.send(:starts_at_raw),
|
||||
|
|
@ -237,4 +237,65 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
|
|||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#severity' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:raw_payload) { { 'labels' => { 'severity' => payload_severity } } }
|
||||
|
||||
subject { parsed_payload.severity }
|
||||
|
||||
context 'when set' do
|
||||
where(:payload_severity, :expected_severity) do
|
||||
'critical' | :critical
|
||||
'high' | :high
|
||||
'medium' | :medium
|
||||
'low' | :low
|
||||
'info' | :info
|
||||
|
||||
's1' | :critical
|
||||
's2' | :high
|
||||
's3' | :medium
|
||||
's4' | :low
|
||||
's5' | :info
|
||||
'p1' | :critical
|
||||
'p2' | :high
|
||||
'p3' | :medium
|
||||
'p4' | :low
|
||||
'p5' | :info
|
||||
|
||||
'CRITICAL' | :critical
|
||||
'cRiTiCaL' | :critical
|
||||
'S1' | :critical
|
||||
|
||||
'unmapped' | nil
|
||||
1 | nil
|
||||
nil | nil
|
||||
|
||||
'debug' | :info
|
||||
'information' | :info
|
||||
'notice' | :info
|
||||
'warn' | :low
|
||||
'warning' | :low
|
||||
'minor' | :low
|
||||
'error' | :medium
|
||||
'major' | :high
|
||||
'emergency' | :critical
|
||||
'fatal' | :critical
|
||||
|
||||
'alert' | :medium
|
||||
'page' | :high
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(expected_severity) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without key' do
|
||||
let(:raw_payload) { {} }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -51,5 +51,26 @@ RSpec.describe Gitlab::APIAuthentication::TokenLocator do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :http_token' do
|
||||
let(:type) { :http_token }
|
||||
|
||||
context 'without credentials' do
|
||||
let(:request) { double(headers: {}) }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(subject).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with credentials' do
|
||||
let(:password) { 'bar' }
|
||||
let(:request) { double(headers: { "Authorization" => password }) }
|
||||
|
||||
it 'returns the credentials' do
|
||||
expect(subject.password).to eq(password)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
|
|||
|
||||
subject { resolver.resolve(raw) }
|
||||
|
||||
context 'with :personal_access_token' do
|
||||
let(:type) { :personal_access_token }
|
||||
context 'with :personal_access_token_with_username' do
|
||||
let(:type) { :personal_access_token_with_username }
|
||||
let(:token) { personal_access_token }
|
||||
|
||||
context 'with valid credentials' do
|
||||
|
|
@ -62,10 +62,16 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
|
|||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
|
||||
context 'with no username' do
|
||||
let(:raw) { username_and_password(nil, token.token) }
|
||||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :job_token' do
|
||||
let(:type) { :job_token }
|
||||
context 'with :job_token_with_username' do
|
||||
let(:type) { :job_token_with_username }
|
||||
let(:token) { ci_job }
|
||||
|
||||
context 'with valid credentials' do
|
||||
|
|
@ -93,8 +99,8 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with :deploy_token' do
|
||||
let(:type) { :deploy_token }
|
||||
context 'with :deploy_token_with_username' do
|
||||
let(:type) { :deploy_token_with_username }
|
||||
let(:token) { deploy_token }
|
||||
|
||||
context 'with a valid deploy token' do
|
||||
|
|
@ -109,6 +115,51 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
|
|||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :personal_access_token' do
|
||||
let(:type) { :personal_access_token }
|
||||
let(:token) { personal_access_token }
|
||||
|
||||
context 'with valid credentials' do
|
||||
let(:raw) { username_and_password(nil, token.token) }
|
||||
|
||||
it_behaves_like 'an authorized request'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :job_token' do
|
||||
let(:type) { :job_token }
|
||||
let(:token) { ci_job }
|
||||
|
||||
context 'with valid credentials' do
|
||||
let(:raw) { username_and_password(nil, token.token) }
|
||||
|
||||
it_behaves_like 'an authorized request'
|
||||
end
|
||||
|
||||
context 'when the job is not running' do
|
||||
let(:raw) { username_and_password(nil, ci_job_done.token) }
|
||||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
|
||||
context 'with an invalid job token' do
|
||||
let(:raw) { username_and_password(nil, "not a valid CI job token") }
|
||||
|
||||
it_behaves_like 'an unauthorized request'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :deploy_token' do
|
||||
let(:type) { :deploy_token }
|
||||
let(:token) { deploy_token }
|
||||
|
||||
context 'with a valid deploy token' do
|
||||
let(:raw) { username_and_password(nil, token.token) }
|
||||
|
||||
it_behaves_like 'an authorized request'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def username_and_password(username, password)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
||||
describe '#errors' do
|
||||
context 'when FF :variable_inside_variable is disabled' do
|
||||
let_it_be(:project_with_flag_disabled) { create(:project) }
|
||||
let_it_be(:project_with_flag_enabled) { create(:project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(variable_inside_variable: false)
|
||||
stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
|
||||
end
|
||||
|
||||
context 'table tests' do
|
||||
|
|
@ -53,7 +56,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
|||
end
|
||||
|
||||
with_them do
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project_with_flag_disabled) }
|
||||
|
||||
it 'does not report error' do
|
||||
expect(subject.errors).to eq(nil)
|
||||
|
|
@ -67,8 +70,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
|||
end
|
||||
|
||||
context 'when FF :variable_inside_variable is enabled' do
|
||||
let_it_be(:project_with_flag_disabled) { create(:project) }
|
||||
let_it_be(:project_with_flag_enabled) { create(:project) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(variable_inside_variable: true)
|
||||
stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
|
||||
end
|
||||
|
||||
context 'table tests' do
|
||||
|
|
@ -100,7 +106,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
|||
end
|
||||
|
||||
with_them do
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project_with_flag_enabled) }
|
||||
|
||||
it 'errors matches expected validation result' do
|
||||
expect(subject.errors).to eq(validation_result)
|
||||
|
|
@ -164,7 +170,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
|||
end
|
||||
|
||||
with_them do
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project) }
|
||||
|
||||
it 'does not expand variables' do
|
||||
expect(subject.sort).to eq(variables)
|
||||
|
|
@ -239,7 +246,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
|
|||
end
|
||||
|
||||
with_them do
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project) }
|
||||
|
||||
it 'sort returns correctly sorted variables' do
|
||||
expect(subject.sort.map { |var| var[:key] }).to eq(result)
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ RSpec.describe JiraService do
|
|||
let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields" }
|
||||
|
||||
it 'calls the Jira API with the options to get the issue' do
|
||||
jira_service.find_issue(issue_key, { expand: 'renderedFields' })
|
||||
jira_service.find_issue(issue_key, rendered_fields: true)
|
||||
|
||||
expect(WebMock).to have_requested(:get, issue_url)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
|
|||
|
||||
describe '#artifacts' do
|
||||
context "when option contains archive-type artifacts" do
|
||||
let(:build) { create(:ci_build, options: { artifacts: archive } ) }
|
||||
let(:build) { create(:ci_build, options: { artifacts: archive }) }
|
||||
|
||||
it 'presents correct hash' do
|
||||
expect(presenter.artifacts.first).to include(archive_expectation)
|
||||
|
|
@ -249,7 +249,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
|
|||
|
||||
it 'returns the correct refspecs' do
|
||||
is_expected.to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
|
||||
"+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
|
||||
"+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::RubygemPackages do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:personal_access_token) { create(:personal_access_token) }
|
||||
let_it_be(:user) { personal_access_token.user }
|
||||
let_it_be(:job) { create(:ci_build, :running, user: user) }
|
||||
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
|
||||
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
|
||||
let_it_be(:headers) { {} }
|
||||
|
||||
shared_examples 'when feature flag is disabled' do
|
||||
let(:headers) do
|
||||
{ 'HTTP_AUTHORIZATION' => personal_access_token.token }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(rubygem_packages: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
shared_examples 'when package feature is disabled' do
|
||||
before do
|
||||
stub_config(packages: { enabled: false })
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
shared_examples 'without authentication' do
|
||||
it_behaves_like 'returning response status', :unauthorized
|
||||
end
|
||||
|
||||
shared_examples 'with authentication' do
|
||||
let(:headers) do
|
||||
{ 'HTTP_AUTHORIZATION' => token }
|
||||
end
|
||||
|
||||
let(:tokens) do
|
||||
{
|
||||
personal_access_token: personal_access_token.token,
|
||||
deploy_token: deploy_token.token,
|
||||
job_token: job.token
|
||||
}
|
||||
end
|
||||
|
||||
where(:user_role, :token_type, :valid_token, :status) do
|
||||
:guest | :personal_access_token | true | :not_found
|
||||
:guest | :personal_access_token | false | :unauthorized
|
||||
:guest | :deploy_token | true | :not_found
|
||||
:guest | :deploy_token | false | :unauthorized
|
||||
:guest | :job_token | true | :not_found
|
||||
:guest | :job_token | false | :unauthorized
|
||||
:reporter | :personal_access_token | true | :not_found
|
||||
:reporter | :personal_access_token | false | :unauthorized
|
||||
:reporter | :deploy_token | true | :not_found
|
||||
:reporter | :deploy_token | false | :unauthorized
|
||||
:reporter | :job_token | true | :not_found
|
||||
:reporter | :job_token | false | :unauthorized
|
||||
:developer | :personal_access_token | true | :not_found
|
||||
:developer | :personal_access_token | false | :unauthorized
|
||||
:developer | :deploy_token | true | :not_found
|
||||
:developer | :deploy_token | false | :unauthorized
|
||||
:developer | :job_token | true | :not_found
|
||||
:developer | :job_token | false | :unauthorized
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
project.send("add_#{user_role}", user) unless user_role == :anonymous
|
||||
end
|
||||
|
||||
let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
|
||||
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'an unimplemented route' do
|
||||
it_behaves_like 'without authentication'
|
||||
it_behaves_like 'with authentication'
|
||||
it_behaves_like 'when feature flag is disabled'
|
||||
it_behaves_like 'when package feature is disabled'
|
||||
end
|
||||
|
||||
describe 'GET /api/v4/projects/:project_id/packages/rubygems/:filename' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/specs.4.8.gz") }
|
||||
|
||||
subject { get(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
|
||||
describe 'GET /api/v4/projects/:project_id/packages/rubygems/quick/Marshal.4.8/:file_name' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/quick/Marshal.4.8/my_gem-1.0.0.gemspec.rz") }
|
||||
|
||||
subject { get(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
|
||||
describe 'GET /api/v4/projects/:project_id/packages/rubygems/gems/:file_name' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/gems/my_gem-1.0.0.gem") }
|
||||
|
||||
subject { get(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
|
||||
describe 'POST /api/v4/projects/:project_id/packages/rubygems/api/v1/gems/authorize' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/gems/authorize") }
|
||||
|
||||
subject { post(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
|
||||
describe 'POST /api/v4/projects/:project_id/packages/rubygems/api/v1/gems' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/gems") }
|
||||
|
||||
subject { post(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
|
||||
describe 'GET /api/v4/projects/:project_id/packages/rubygems/api/v1/dependencies' do
|
||||
let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/dependencies") }
|
||||
|
||||
subject { get(url, headers: headers) }
|
||||
|
||||
it_behaves_like 'an unimplemented route'
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue