Commit 1ea1db49 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 22e9af3c
......@@ -83,6 +83,7 @@ package-lock.json
jsdoc/
**/tmp/rubocop_cache/**
.overcommit.yml
.overcommit.yml.backup
.projections.json
/qa/.rakeTasks
webpack-dev-server.json
......
......@@ -15,6 +15,13 @@
#
# Uncomment the following lines to make the configuration take effect.
# Make sure to run `cd tooling/overcommit && make && cd -`
gemfile: 'tooling/overcommit/gems.rb'
PostCheckout:
BundleInstall:
enabled: true
PreCommit:
AuthorName:
enabled: false
......@@ -35,6 +42,19 @@ PreCommit:
# on_warn: fail # Treat all warnings as failures
ScssLint:
enabled: true
CommitMsg:
TextWidth:
enabled: true
min_subject_width: 8 # three 2-letter words with 2 spaces
max_subject_width: 72
quiet: false
EmptyMessage:
enabled: true
required: true
description: 'Checking for empty commit message'
#PostCheckout:
# ALL: # Special hook name that customizes all hooks of this type
# quiet: true # Change all post-checkout hooks to only display output on failure
......
......@@ -347,6 +347,8 @@ RSpec/HaveGitlabHttpStatus:
- 'ee/spec/features/**/*'
- 'spec/controllers/*.rb'
- 'ee/spec/controllers/*.rb'
- 'spec/requests/*.rb'
- 'ee/spec/requests/*.rb'
Style/MultilineWhenThen:
Enabled: false
......
......@@ -21,7 +21,7 @@ module PrometheusAdapter
raise NotImplemented
end
# This is a heavy-weight check if a prometheus is properly configured and accesible from GitLab.
# This is a heavy-weight check if a prometheus is properly configured and accessible from GitLab.
# This actually sends a request to an external service and often it could take a long time,
# Please consider using `configured?` instead if the process is running on unicorn/puma threads.
def can_query?
......
......@@ -2207,7 +2207,7 @@ class Project < ApplicationRecord
end
def reference_counter(type: Gitlab::GlRepository::PROJECT)
Gitlab::ReferenceCounter.new(type.identifier_for_repositorable(self))
Gitlab::ReferenceCounter.new(type.identifier_for_container(self))
end
def badges
......
......@@ -65,7 +65,7 @@ class ProjectWiki
# Returns the Gitlab::Git::Wiki object.
def wiki
@wiki ||= begin
gl_repository = Gitlab::GlRepository::WIKI.identifier_for_repositorable(project)
gl_repository = Gitlab::GlRepository::WIKI.identifier_for_container(project)
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path)
create_repo!(raw_repository) unless raw_repository.exists?
......
......@@ -1183,7 +1183,7 @@ class Repository
def initialize_raw_repository
Gitlab::Git::Repository.new(project.repository_storage,
disk_path + '.git',
repo_type.identifier_for_repositorable(project),
repo_type.identifier_for_container(project),
project.full_path)
end
end
......
---
title: Filter merge requests by approvals (API)
merge_request: 21379
author:
type: added
---
title: Add separate classes for user related entities for email, membership, status
merge_request: 23748
author: Rajendra Kadam
type: added
......@@ -173,9 +173,11 @@ praefect['virtual_storages'] = {
}
}
# Replace POSTGRESQL_SERVER below with a real IP/host address of the database.
praefect['database_host'] = 'POSTGRESQL_SERVER'
praefect['database_port'] = 5432
praefect['database_user'] = 'praefect'
# Replace PRAEFECT_SQL_PASSWORD below with a real password of the database.
praefect['database_password'] = 'PRAEFECT_SQL_PASSWORD'
praefect['database_dbname'] = 'praefect_production'
......
This diff is collapsed.
......@@ -30,7 +30,9 @@
This is also the style used by linting tools such as
[RuboCop](https://github.com/rubocop-hq/rubocop) and [Hound CI](https://houndci.com).
You can run RuboCop by hand or install a tool like [Overcommit](https://github.com/sds/overcommit) to run it for you.
Overcommit will automatically run the configured checks (like Rubocop) on every modified file before commit. You can use the example overcommit configuration found in `.overcommit.yml.example` as a quickstart.
Overcommit will automatically run the configured checks (like Rubocop) on every modified file before commit.
You can use the example overcommit configuration found in `.overcommit.yml.example` as a quickstart.
This saves you time as you don't have to wait for the same errors to be detected by the CI.
---
......
......@@ -94,6 +94,19 @@ project.
![Releases list](img/releases.png)
### Number of Releases
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/36667) in GitLab 12.8.
The incremental number of Releases is displayed on the project's details page. When clicked,
it takes you to the list of Releases.
![Number of Releases](img/releases_count_v12_8.png "Incremental counter of Releases")
For private projects, the number of Releases is displayed to users with Reporter
[permissions](../../permissions.md#releases-permissions) or higher. For public projects,
it is displayed to every user regardless of their permission level.
## Editing a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/26016) in GitLab 12.6.
......
......@@ -60,4 +60,8 @@ changes will be added to the repository and branch you're merging into.
![New merge request](img/forking_workflow_merge_request.png)
## Removing a fork relationship
You can unlink your fork from its upstream project in the [advanced settings](../settings/index.md#removing-a-fork-relationship).
[gitlab flow]: https://about.gitlab.com/blog/2014/09/29/gitlab-flow/ "GitLab Flow blog post"
......@@ -97,7 +97,8 @@ In case your development workflow dictates to have an issue for every merge
request, you can quickly create a branch right on the issue page which will be
tied with the issue itself. You can see a **Create merge request** dropdown
below the issue description unless there is already a branch with the same
name or a referenced merge request.
name or a referenced merge request or your project (still) has an active
[fork relationship](../settings/index.md#advanced-settings).
![Create Button](img/web_editor_new_branch_from_issue_create_button_v12_6.png)
......
# Project settings
NOTE: **Note:**
Only project Maintainers and Admin users have the [permissions] to access a project
settings.
Only project Maintainers and Admin users have the [permissions](../../permissions.md#project-members-permissions)
to access a project settings.
You can adjust your [project](../index.md) settings by navigating
to your project's homepage and clicking **Settings**.
......@@ -106,12 +106,13 @@ Learn how to [export a project](import_export.md#importing-the-project) in GitLa
### Advanced settings
Here you can run housekeeping, archive, rename, transfer, or remove a project.
Here you can run housekeeping, archive, rename, transfer, [remove a fork relationship](#removing-a-fork-relationship), or remove a project.
#### Archiving a project
NOTE: **Note:**
Only project Owners and Admin users have the [permissions] to archive a project.
Only project Owners and Admin users have the [permissions](../../permissions.md#project-members-permissions)
to archive a project.
Archiving a project makes it read-only for all users and indicates that it is
no longer actively maintained. Projects that have been archived can also be
......@@ -130,7 +131,7 @@ To archive a project:
#### Renaming a repository
NOTE: **Note:**
Only project Maintainers and Admin users have the [permissions] to rename a
Only project Maintainers and Admin users have the [permissions](../../permissions.md#project-members-permissions) to rename a
repository. Not to be confused with a project's name where it can also be
changed from the [general project settings](#general-project-settings).
......@@ -150,11 +151,12 @@ old URL will not be able to push or pull. Read more about what happens with the
#### Transferring an existing project into another namespace
NOTE: **Note:**
Only project Owners and Admin users have the [permissions] to transfer a project.
Only project Owners and Admin users have the [permissions](../../permissions.md#project-members-permissions)
to transfer a project.
You can transfer an existing project into a [group](../../group/index.md) if:
1. You have at least **Maintainer** [permissions] to that group.
1. You have at least **Maintainer** [permissions](../../permissions.md#project-members-permissions) to that group.
1. The project is in a subgroup you own.
1. You are at least a **Maintainer** of the project under your personal namespace.
Similarly, if you are an owner of a group, you can transfer any of its projects
......@@ -175,8 +177,6 @@ NOTE: **Note:**
GitLab administrators can use the admin interface to move any project to any
namespace if needed.
[permissions]: ../../permissions.md#project-members-permissions
#### Remove a project
NOTE: **Note:**
......@@ -202,6 +202,24 @@ To restore a project that is marked for deletion:
1. Navigate to your project, and select **{settings}** **Settings > General > Advanced**.
1. In the Restore project section, click the **Restore project** button.
#### Removing a fork relationship
Forking is a great way to [contribute to a project](../repository/forking_workflow.md)
of which you are not a member.
If you want to use the fork for yourself and do not need to send
[merge requests](../merge_requests.md) to the upstream project,
you can safely remove the fork relationship.
To do so:
1. Navigate to your project's **Settings > General > Advanced**.
1. Under **Remove fork relationship**, click the likewise-labeled button.
1. Confirm the action by typing the project's path as instructed.
NOTE: **Note:**
Only project maintainers have the [permissions](../../permissions.md#project-members-permissions)
to remove a fork relationship.
## Operations settings
### Error Tracking
......
......@@ -2,31 +2,6 @@
module API
module Entities
class Membership < Grape::Entity
expose :source_id
expose :source_name do |member|
member.source.name
end
expose :source_type
expose :access_level
end
class Identity < Grape::Entity
expose :provider, :extern_uid
end
class UserStatus < Grape::Entity
expose :emoji
expose :message
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
end
class Email < Grape::Entity
expose :id, :email
end
class Hook < Grape::Entity
expose :id, :url, :created_at, :push_events, :tag_push_events, :merge_requests_events, :repository_update_events
expose :enable_ssl_verification
......
# frozen_string_literal: true
module API
module Entities
class Email < Grape::Entity
expose :id, :email
end
end
end
# frozen_string_literal: true
module API
module Entities
class Identity < Grape::Entity
expose :provider, :extern_uid
end
end
end
# frozen_string_literal: true
module API
module Entities
class Membership < Grape::Entity
expose :source_id
expose :source_name do |member|
member.source.name
end
expose :source_type
expose :access_level
end
end
end
# frozen_string_literal: true
module API
module Entities
class UserStatus < Grape::Entity
expose :emoji
expose :message
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
end
end
end
......@@ -116,7 +116,7 @@ module API
# Project id to pass between components that don't share/don't have
# access to the same filesystem mounts
def gl_repository
repo_type.identifier_for_repositorable(project)
repo_type.identifier_for_container(project)
end
def gl_project_path
......
......@@ -7,12 +7,13 @@ module Gitlab
PROJECT = RepoType.new(
name: :project,
access_checker_class: Gitlab::GitAccess,
repository_accessor: -> (project) { project.repository }
repository_resolver: -> (project) { project.repository }
).freeze
WIKI = RepoType.new(
name: :wiki,
access_checker_class: Gitlab::GitAccessWiki,
repository_accessor: -> (project) { project.wiki.repository }
repository_resolver: -> (project) { project.wiki.repository },
suffix: :wiki
).freeze
TYPES = {
......@@ -27,15 +28,14 @@ module Gitlab
def self.parse(gl_repository)
type_name, _id = gl_repository.split('-').first
type = types[type_name]
subject_id = type&.fetch_id(gl_repository)
unless subject_id
unless type
raise ArgumentError, "Invalid GL Repository \"#{gl_repository}\""
end
project = Project.find_by_id(subject_id)
container = type.fetch_container!(gl_repository)
[project, type]
[container, type]
end
def self.default_type
......
......@@ -5,16 +5,25 @@ module Gitlab
class RepoType
attr_reader :name,
:access_checker_class,
:repository_accessor
:repository_resolver,
:container_resolver,
:suffix
def initialize(name:, access_checker_class:, repository_accessor:)
def initialize(
name:,
access_checker_class:,
repository_resolver:,
container_resolver: default_container_resolver,
suffix: nil)
@name = name
@access_checker_class = access_checker_class
@repository_accessor = repository_accessor
@repository_resolver = repository_resolver
@container_resolver = container_resolver
@suffix = suffix
end
def identifier_for_repositorable(repositorable)
"#{name}-#{repositorable.id}"
def identifier_for_container(container)
"#{name}-#{container.id}"
end
def fetch_id(identifier)
......@@ -22,6 +31,14 @@ module Gitlab
match[:id] if match
end
def fetch_container!(identifier)
id = fetch_id(identifier)
raise ArgumentError, "Invalid GL Repository \"#{identifier}\"" unless id
container_resolver.call(id)
end
def wiki?
self == WIKI
end
......@@ -31,11 +48,21 @@ module Gitlab
end
def path_suffix
project? ? "" : ".#{name}"
suffix ? ".#{suffix}" : ''
end
def repository_for(repositorable)
repository_accessor.call(repositorable)
def repository_for(container)
repository_resolver.call(container)
end
def valid?(repository_path)
repository_path.end_with?(path_suffix)
end
private
def default_container_resolver
-> (id) { Project.find_by_id(id) }
end
end
end
......
......@@ -4,8 +4,9 @@ module Gitlab
module RepoPath
NotFoundError = Class.new(StandardError)
def self.parse(repo_path)
project_path = repo_path.sub(/\.git\z/, '').sub(%r{\A/}, '')
def self.parse(path)
repo_path = path.sub(/\.git\z/, '').sub(%r{\A/}, '')
redirected_path = nil
# Detect the repo type based on the path, the first one tried is the project
# type, which does not have a suffix.
......@@ -14,10 +15,13 @@ module Gitlab
# type.
# We'll always try to find a project with an empty suffix (for the
# `Gitlab::GlRepository::PROJECT` type.
next unless project_path.end_with?(type.path_suffix)
next unless type.valid?(repo_path)
project, was_redirected = find_project(project_path.chomp(type.path_suffix))
redirected_path = project_path if was_redirected
# Removing the suffix (.wiki, .design, ...) from the project path
full_path = repo_path.chomp(type.path_suffix)
project, was_redirected = find_project(full_path)
redirected_path = repo_path if was_redirected
# If we found a matching project, then the type was matched, no need to
# continue looking.
......
......@@ -24,7 +24,7 @@ module Gitlab
attrs = {
GL_ID: Gitlab::GlId.gl_id(user),
GL_REPOSITORY: repo_type.identifier_for_repositorable(repository.project),
GL_REPOSITORY: repo_type.identifier_for_container(repository.project),
GL_USERNAME: user&.username,
ShowAllRefs: show_all_refs,
Repository: repository.gitaly_repository.to_h,
......
......@@ -2,33 +2,45 @@
require 'spec_helper'
describe Gitlab::GlRepository::RepoType do
set(:project) { create(:project) }
let_it_be(:project) { create(:project) }
describe Gitlab::GlRepository::PROJECT do
it_behaves_like 'a repo type' do
let(:expected_identifier) { "project-#{project.id}" }
let(:expected_id) { project.id.to_s }
let(:expected_suffix) { "" }
let(:expected_suffix) { '' }
let(:expected_repository) { project.repository }
let(:expected_container) { project }
end
it "knows its type" do
it 'knows its type' do
expect(described_class).not_to be_wiki
expect(described_class).to be_project
end
it 'checks if repository path is valid' do
expect(described_class.valid?(project.repository.full_path)).to be_truthy
expect(described_class.valid?(project.wiki.repository.full_path)).to be_truthy
end
end
describe Gitlab::GlRepository::WIKI do
it_behaves_like 'a repo type' do
let(:expected_identifier) { "wiki-#{project.id}" }
let(:expected_id) { project.id.to_s }
let(:expected_suffix) { ".wiki" }
let(:expected_suffix) { '.wiki' }
let(:expected_repository) { project.wiki.repository }
let(:expected_container) { project }
end
it "knows its type" do
it 'knows its type' do
expect(described_class).to be_wiki
expect(described_class).not_to be_project
end
it 'checks if repository path is valid' do
expect(described_class.valid?(project.repository.full_path)).to be_falsey
expect(described_class.valid?(project.wiki.repository.full_path)).to be_truthy
end
end
end
......@@ -4,7 +4,7 @@ require 'spec_helper'
describe ::Gitlab::GlRepository do
describe '.parse' do
set(:project) { create(:project, :repository) }
let_it_be(:project) { create(:project, :repository) }
it 'parses a project gl_repository' do
expect(described_class.parse("project-#{project.id}")).to eq([project, Gitlab::GlRepository::PROJECT])
......@@ -14,8 +14,12 @@ describe ::Gitlab::GlRepository do
expect(described_class.parse("wiki-#{project.id}")).to eq([project, Gitlab::GlRepository::WIKI])
end
it 'throws an argument error on an invalid gl_repository' do
it 'throws an argument error on an invalid gl_repository type' do
expect { described_class.parse("badformat-#{project.id}") }.to raise_error(ArgumentError)
end
it 'throws an argument error on an invalid gl_repository id' do
expect { described_class.parse("project-foo") }.to raise_error(ArgumentError)
end
end
end
......@@ -3992,7 +3992,7 @@ describe Project do
end
it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the project repo is in use' do
Gitlab::ReferenceCounter.new(Gitlab::GlRepository::PROJECT.identifier_for_repositorable(project)).increase
Gitlab::ReferenceCounter.new(Gitlab::GlRepository::PROJECT.identifier_for_container(project)).increase
expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
......@@ -4000,7 +4000,7 @@ describe Project do
end
it 'schedules HashedStorage::ProjectMigrateWorker with delayed start when the wiki repo is in use' do
Gitlab::ReferenceCounter.new(Gitlab::GlRepository::WIKI.identifier_for_repositorable(project)).increase
Gitlab::ReferenceCounter.new(Gitlab::GlRepository::WIKI.identifier_for_container(project)).increase
expect(HashedStorage::ProjectMigrateWorker).to receive(:perform_in)
......
......@@ -268,7 +268,7 @@ describe API::Internal::Base do
end
context 'with env passed as a JSON' do
let(:gl_repository) { Gitlab::GlRepository::WIKI.identifier_for_repositorable(project) }
let(:gl_repository) { Gitlab::GlRepository::WIKI.identifier_for_container(project) }
it 'sets env in RequestStore' do
obj_dir_relative = './objects'
......@@ -1054,9 +1054,9 @@ describe API::Internal::Base do
def gl_repository_for(project_or_wiki)
case project_or_wiki
when ProjectWiki
Gitlab::GlRepository::WIKI.identifier_for_repositorable(project_or_wiki.project)
Gitlab::GlRepository::WIKI.identifier_for_container(project_or_wiki.project)
when Project
Gitlab::GlRepository::PROJECT.identifier_for_repositorable(project_or_wiki)
Gitlab::GlRepository::PROJECT.identifier_for_container(project_or_wiki)
else
nil
end
......
......@@ -848,7 +848,7 @@ describe 'Git HTTP requests' do
end
it "redirects" do
expect(response).to have_gitlab_http_status(302)
expect(response).to have_gitlab_http_status(:found)
end
end
end
......@@ -890,7 +890,7 @@ describe 'Git HTTP requests' do
it "responds with status 200" do
clone_get(path, env) do |response|
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......
......@@ -15,12 +15,12 @@ describe JwtController do
context 'existing service' do
subject! { get '/jwt/auth', params: parameters }
it { expect(response).to have_gitlab_http_status(200) }
it { expect(response).to have_gitlab_http_status(:ok) }
context 'returning custom http code' do
let(:service) { double(execute: { http_status: 505 }) }
it { expect(response).to have_gitlab_http_status(505) }
it { expect(response).to have_gitlab_http_status(:http_version_not_supported) }
end
end
......@@ -43,7 +43,7 @@ describe JwtController do
subject! { get '/jwt/auth', params: parameters, headers: headers }
it { expect(response).to have_gitlab_http_status(401) }
it { expect(response).to have_gitlab_http_status(:unauthorized) }
end
context 'using personal access tokens' do
......@@ -58,7 +58,7 @@ describe JwtController do
subject! { get '/jwt/auth', params: parameters, headers: headers }
it 'authenticates correctly' do
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(service_class).to have_received(:new).with(nil, user, ActionController::Parameters.new(parameters).permit!)
end
end
......@@ -96,7 +96,7 @@ describe JwtController do
context 'without personal token' do
it 'rejects the authorization attempt' do
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
......@@ -106,7 +106,7 @@ describe JwtController do
let(:headers) { { authorization: credentials(user.username, access_token.token) } }
it 'accepts the authorization attempt' do
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -116,7 +116,7 @@ describe JwtController do
get '/jwt/auth', params: parameters, headers: headers
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -127,7 +127,7 @@ describe JwtController do
it 'rejects the authorization attempt' do
get '/jwt/auth', params: parameters, headers: headers
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
......@@ -139,7 +139,7 @@ describe JwtController do
end
get '/jwt/auth', params: parameters, headers: headers
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
......@@ -150,7 +150,7 @@ describe JwtController do
it 'accepts the authorization attempt' do
get '/jwt/auth', params: parameters
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
it 'allows read access' do
......@@ -163,7 +163,7 @@ describe JwtController do
context 'unknown service' do
subject! { get '/jwt/auth', params: { service: 'unknown' } }
it { expect(response).to have_gitlab_http_status(404) }
it { expect(response).to have_gitlab_http_status(:not_found) }
end
def credentials(login, password)
......
......@@ -227,7 +227,7 @@ describe 'Git LFS API and storage' do
end
it 'responds with redirect' do
expect(response).to have_gitlab_http_status(302)
expect(response).to have_gitlab_http_status(:found)
end
it 'responds with the file location' do
......@@ -1011,7 +1011,7 @@ describe 'Git LFS API and storage' do
it 'responds with status 403' do
subject
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
......@@ -1027,7 +1027,7 @@ describe 'Git LFS API and storage' do
it 'responds with status 200' do
subject
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
object = LfsObject.find_by_oid(sample_oid)
expect(object).to be_present
......@@ -1070,7 +1070,7 @@ describe 'Git LFS API and storage' do
it 'rejects slashes in the tempfile name (path traversal)' do
put_finalize('../bar', with_tempfile: true)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
......
......@@ -23,7 +23,7 @@ describe 'Git LFS File Locking API' do
it 'returns a forbidden 403 response' do
post_lfs_json url, body, headers
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
......@@ -51,7 +51,7 @@ describe 'Git LFS File Locking API' do
it 'return an error message' do
post_lfs_json url, body, headers
expect(response).to have_gitlab_http_status(409)
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response.keys).to match_array(%w(lock message documentation_url))
expect(json_response['message']).to match(/already locked/)
......@@ -68,7 +68,7 @@ describe 'Git LFS File Locking API' do
it 'creates the lock' do
post_lfs_json url, body, headers
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['lock'].keys).to match_array(%w(id path locked_at owner))
end
......@@ -87,7 +87,7 @@ describe 'Git LFS File Locking API' do
do_get url, nil, headers
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['locks'].size).to eq(2)
expect(json_response['locks'].first.keys).to match_array(%w(id path locked_at owner))
......@@ -106,7 +106,7 @@ describe 'Git LFS File Locking API' do
post_lfs_json url, nil, headers
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['ours'].size).to eq(1)
expect(json_response['ours'].first['path']).to eq('README')
......@@ -126,7 +126,7 @@ describe 'Git LFS File Locking API' do
it 'deletes the lock' do
post_lfs_json url, nil, headers
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns the deleted lock' do
......@@ -142,7 +142,7 @@ describe 'Git LFS File Locking API' do
project.add_maintainer(maintainer)
post_lfs_json url, { force: true }, headers
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......
......@@ -75,7 +75,7 @@ describe 'OpenID Connect requests' do
it 'userinfo response is unauthorized' do
request_user_info!
expect(response).to have_gitlab_http_status 403
expect(response).to have_gitlab_http_status(:forbidden)
expect(response.body).to be_blank
end
end
......@@ -177,7 +177,7 @@ describe 'OpenID Connect requests' do
it 'correctly returns the configuration' do
get '/.well-known/openid-configuration'
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['issuer']).to eq('http://localhost')
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
expect(json_response['scopes_supported']).to eq(%w[api read_user read_repository write_repository sudo openid profile email])
......
......@@ -53,7 +53,7 @@ describe 'Rack Attack global throttles' do
# At first, allow requests under the rate limit.
requests_per_period.times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
# the last straw
......@@ -63,7 +63,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests after throttling and then waiting for the next period' do
requests_per_period.times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
expect_rejection { get url_that_does_not_require_authentication }
......@@ -71,7 +71,7 @@ describe 'Rack Attack global throttles' do
Timecop.travel(period.from_now) do
requests_per_period.times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
expect_rejection { get url_that_does_not_require_authentication }
......@@ -81,7 +81,7 @@ describe 'Rack Attack global throttles' do
it 'counts requests from different IPs separately' do
requests_per_period.times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
expect_next_instance_of(Rack::Attack::Request) do |instance|
......@@ -90,14 +90,14 @@ describe 'Rack Attack global throttles' do
# would be over limit for the same IP
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
context 'when the request is to the api internal endpoints' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
get url_api_internal, params: { secret_token: Gitlab::Shell.secret_token }
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -109,7 +109,7 @@ describe 'Rack Attack global throttles' do
it 'does not cont as unauthenticated' do
(1 + requests_per_period).times do
post request_jobs_url, params: { token: runner.token }
expect(response).to have_http_status 204
expect(response).to have_gitlab_http_status(:no_content)
end
end
end
......@@ -117,7 +117,7 @@ describe 'Rack Attack global throttles' do
it 'logs RackAttack info into structured logs' do
requests_per_period.times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
arguments = {
......@@ -143,7 +143,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
get url_that_does_not_require_authentication
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -243,7 +243,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -257,7 +257,7 @@ describe 'Rack Attack global throttles' do
it 'rejects requests over the rate limit' do
requests_per_period.times do
post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
expect_rejection { post protected_path_that_does_not_require_authentication, params: post_params }
......@@ -272,7 +272,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
post protected_path_that_does_not_require_authentication, params: post_params
expect(response).to have_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -329,7 +329,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
post(*request_args)
expect(response).not_to have_http_status 429
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
end
end
......@@ -369,7 +369,7 @@ describe 'Rack Attack global throttles' do
it 'allows requests over the rate limit' do
(1 + requests_per_period).times do
post url_that_requires_authentication
expect(response).not_to have_http_status 429
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
end
end
......
......@@ -19,7 +19,7 @@ describe 'Loading a user avatar' do
it 'only performs three SQL queries' do
get user.avatar_url # Skip queries on first application load
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect { get user.avatar_url }.not_to exceed_query_limit(3)
end
end
......@@ -29,7 +29,7 @@ describe 'Loading a user avatar' do
it 'only performs two SQL queries' do
get user.avatar_url # Skip queries on first application load
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect { get user.avatar_url }.not_to exceed_query_limit(2)
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe AkismetService do
let(:fake_akismet_client) { double(:akismet_client) }
let_it_be(:text) { "Would you like to buy some tinned meat product?" }
let_it_be(:spam_owner) { create(:user) }
subject do
options = { ip_address: '1.2.3.4', user_agent: 'some user_agent', referrer: 'some referrer' }
described_class.new(spam_owner.name, spam_owner.email, text, options)
end
before do
stub_application_setting(akismet_enabled: true)
allow(subject).to receive(:akismet_client).and_return(fake_akismet_client)
end
shared_examples 'no activity if Akismet is not enabled' do |method_call|
# if the method name is `submit`, it requires an argument, so add it
before do
stub_application_setting(akismet_enabled: false)
end
it 'is automatically false' do
expect(subject.send(method_call)).to be_falsey
end
it 'performs no check' do
expect(fake_akismet_client).not_to receive(:public_send)
subject.send(method_call)
end
end
shared_examples 'false if Akismet is not available' do |method_call|
context 'if Akismet is not available' do
before do
allow(fake_akismet_client).to receive(:public_send).and_raise(StandardError.new("oh noes!"))
end
specify do
expect(subject.send(method_call)).to be_falsey
end
it 'logs an error' do
logger_spy = double(:logger)
expect(Rails).to receive(:logger).and_return(logger_spy)
expect(logger_spy).to receive(:error).with(/skipping/)
subject.send(method_call)
end
end
end
describe '#spam?' do
it_behaves_like 'no activity if Akismet is not enabled', :spam?, :check
context 'if Akismet is enabled' do
context 'the text is spam' do
before do
allow(fake_akismet_client).to receive(:check).and_return([true, false])
end
specify do
expect(subject.spam?).to be_truthy
end
end
context 'the text is blatant spam' do
before do
allow(fake_akismet_client).to receive(:check).and_return([false, true])
end
specify do
expect(subject.spam?).to be_truthy
end
end
context 'the text is not spam' do
before do
allow(fake_akismet_client).to receive(:check).and_return([false, false])
end
specify do
expect(subject.spam?).to be_falsey
end
end
context 'if Akismet is not available' do
before do
allow(fake_akismet_client).to receive(:check).and_raise(StandardError.new("oh noes!"))
end
specify do
expect(subject.spam?).to be_falsey
end
it 'logs an error' do
logger_spy = double(:logger)
expect(Rails).to receive(:logger).and_return(logger_spy)
expect(logger_spy).to receive(:error).with(/skipping check/)
subject.spam?
end
end
end
end
describe '#submit_ham' do
it_behaves_like 'no activity if Akismet is not enabled', :submit_ham
it_behaves_like 'false if Akismet is not available', :submit_ham
context 'if Akismet is available' do
specify do
expect(fake_akismet_client).to receive(:public_send).with(:ham, any_args)
expect(subject.submit_ham).to be_truthy
end
end
end
describe '#submit_spam' do
it_behaves_like 'no activity if Akismet is not enabled', :submit_spam
it_behaves_like 'false if Akismet is not available', :submit_spam
context 'if Akismet is available' do
specify do
expect(fake_akismet_client).to receive(:public_send).with(:spam, any_args)
expect(subject.submit_spam).to be_truthy
end
end
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
describe Ci::CreatePipelineService do
context '.pre/.post stages' do
describe '.pre/.post stages' do
let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository, creator: user) }
......
# frozen_string_literal: true
RSpec.shared_examples 'a repo type' do
describe "#identifier_for_repositorable" do
subject { described_class.identifier_for_repositorable(project) }
describe '#identifier_for_container' do
subject { described_class.identifier_for_container(project) }
it { is_expected.to eq(expected_identifier) }
end
describe "#fetch_id" do
it "finds an id match in the identifier" do
describe '#fetch_id' do
it 'finds an id match in the identifier' do
expect(described_class.fetch_id(expected_identifier)).to eq(expected_id)
end
it 'does not break on other identifiers' do
expect(described_class.fetch_id("wiki-noid")).to eq(nil)
expect(described_class.fetch_id('wiki-noid')).to eq(nil)
end
end
describe "#path_suffix" do
describe '#fetch_container!' do
it 'returns the container' do
expect(described_class.fetch_container!(expected_identifier)).to eq expected_container
end
it 'raises an exception if the identifier is invalid' do
expect { described_class.fetch_container!('project-noid') }.to raise_error ArgumentError
end
end
describe '#path_suffix' do
subject { described_class.path_suffix }
it { is_expected.to eq(expected_suffix) }
end
describe "#repository_for" do
it "finds the repository for the repo type" do
describe '#repository_for' do
it 'finds the repository for the repo type' do
expect(described_class.repository_for(project)).to eq(expected_repository)
end
end
......
.PHONY: install
install:
if [ -e ../../.overcommit.yml ]; then cp -f ../../.overcommit.yml ../../.overcommit.yml.backup; fi
cp ../../.overcommit.yml.example ../../.overcommit.yml
bundle install
cd ../../ && overcommit -i
GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
childprocess (3.0.0)
ffi (1.12.1)
gitlab-styles (3.1.0)
rubocop (~> 0.74.0)
rubocop-gitlab-security (~> 0.1.0)
rubocop-performance (~> 1.4.1)
rubocop-rails (~> 2.0)
rubocop-rspec (~> 1.36)
haml (5.1.2)
temple (>= 0.8.0)
tilt
haml_lint (0.34.1)
haml (>= 4.0, < 5.2)
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
iniparse (1.4.4)
jaro_winkler (1.5.4)
overcommit (0.52.1)
childprocess (>= 0.6.3, < 4)
iniparse (~> 1.4)
parallel (1.19.1)
parser (2.7.0.2)
ast (~> 2.4.0)
rack (2.1.1)
rainbow (3.0.0)
rake (12.3.3)
rb-fsevent (0.10.3)
rb-inotify (0.10.1)
ffi (~> 1.0)
rubocop (0.74.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
rubocop-performance (1.4.1)
rubocop (>= 0.71.0)
rubocop-rails (2.4.1)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rspec (1.37.1)
rubocop (>= 0.68.1)
ruby-progressbar (1.10.1)
sass (3.5.7)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
scss_lint (0.56.0)
rake (>= 0.9, < 13)
sass (~> 3.5.3)
sysexits (1.2.0)
temple (0.8.2)
tilt (2.0.10)
unicode-display_width (1.6.1)
PLATFORMS
ruby
DEPENDENCIES
gitlab-styles (~> 3.1.0)
haml_lint (~> 0.34.0)
overcommit
scss_lint (~> 0.56.0)
BUNDLED WITH
2.1.2
# frozen_string_literal: true
# Make sure to run `bundle install --gemfile=tooling/overcommit/gems.rb` when you update this file.
source 'https://rubygems.org'
gem 'overcommit'
gem 'gitlab-styles', '~> 3.1.0', require: false
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.34.0', require: false
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment