Commit a48184a7 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-05-01

# Conflicts:
#	Gemfile.lock
#	doc/README.md
#	doc/development/README.md

[ci skip]
parents a2e85860 8b3db0d6
...@@ -1109,7 +1109,10 @@ DEPENDENCIES ...@@ -1109,7 +1109,10 @@ DEPENDENCIES
grape-route-helpers (~> 2.1.0) grape-route-helpers (~> 2.1.0)
grape_logging (~> 1.7) grape_logging (~> 1.7)
grpc (~> 1.11.0) grpc (~> 1.11.0)
<<<<<<< HEAD
gssapi gssapi
=======
>>>>>>> upstream/master
haml_lint (~> 0.26.0) haml_lint (~> 0.26.0)
hamlit (~> 2.6.1) hamlit (~> 2.6.1)
hashie-forbidden_attributes hashie-forbidden_attributes
......
...@@ -86,7 +86,7 @@ export default { ...@@ -86,7 +86,7 @@ export default {
v-html="resolveSvg" v-html="resolveSvg"
></span> ></span>
</span> </span>
<span class=".line-resolve-text"> <span class="line-resolve-text">
{{ resolvedDiscussionCount }}/{{ discussionCount }} {{ countText }} resolved {{ resolvedDiscussionCount }}/{{ discussionCount }} {{ countText }} resolved
</span> </span>
</div> </div>
......
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore';
function isValidProjectId(id) { function isValidProjectId(id) {
return id > 0; return id > 0;
...@@ -43,7 +44,7 @@ class SidebarMoveIssue { ...@@ -43,7 +44,7 @@ class SidebarMoveIssue {
renderRow: project => ` renderRow: project => `
<li> <li>
<a href="#" class="js-move-issue-dropdown-item"> <a href="#" class="js-move-issue-dropdown-item">
${project.name_with_namespace} ${_.escape(project.name_with_namespace)}
</a> </a>
</li> </li>
`, `,
......
...@@ -772,7 +772,3 @@ ul.notes { ...@@ -772,7 +772,3 @@ ul.notes {
height: auto; height: auto;
} }
} }
.line-resolve-text {
vertical-align: middle;
}
module Projects module Projects
class UpdatePagesService < BaseService class UpdatePagesService < BaseService
InvaildStateError = Class.new(StandardError) InvalidStateError = Class.new(StandardError)
FailedToExtractError = Class.new(StandardError) FailedToExtractError = Class.new(StandardError)
BLOCK_SIZE = 32.kilobytes BLOCK_SIZE = 32.kilobytes
...@@ -21,8 +21,8 @@ module Projects ...@@ -21,8 +21,8 @@ module Projects
@status.enqueue! @status.enqueue!
@status.run! @status.run!
raise InvaildStateError, 'missing pages artifacts' unless build.artifacts? raise InvalidStateError, 'missing pages artifacts' unless build.artifacts?
raise InvaildStateError, 'pages are outdated' unless latest? raise InvalidStateError, 'pages are outdated' unless latest?
# Create temporary directory in which we will extract the artifacts # Create temporary directory in which we will extract the artifacts
FileUtils.mkdir_p(tmp_path) FileUtils.mkdir_p(tmp_path)
...@@ -31,16 +31,16 @@ module Projects ...@@ -31,16 +31,16 @@ module Projects
# Check if we did extract public directory # Check if we did extract public directory
archive_public_path = File.join(archive_path, 'public') archive_public_path = File.join(archive_path, 'public')
raise InvaildStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path) raise InvalidStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path)
raise InvaildStateError, 'pages are outdated' unless latest? raise InvalidStateError, 'pages are outdated' unless latest?
deploy_page!(archive_public_path) deploy_page!(archive_public_path)
success success
end end
rescue InvaildStateError => e rescue InvalidStateError => e
error(e.message) error(e.message)
rescue => e rescue => e
error(e.message, false) error(e.message)
raise e raise e
end end
...@@ -48,17 +48,15 @@ module Projects ...@@ -48,17 +48,15 @@ module Projects
def success def success
@status.success @status.success
delete_artifact!
super super
end end
def error(message, allow_delete_artifact = true) def error(message)
register_failure register_failure
log_error("Projects::UpdatePagesService: #{message}") log_error("Projects::UpdatePagesService: #{message}")
@status.allow_failure = !latest? @status.allow_failure = !latest?
@status.description = message @status.description = message
@status.drop(:script_failure) @status.drop(:script_failure)
delete_artifact! if allow_delete_artifact
super super
end end
...@@ -77,18 +75,18 @@ module Projects ...@@ -77,18 +75,18 @@ module Projects
if artifacts.ends_with?('.zip') if artifacts.ends_with?('.zip')
extract_zip_archive!(temp_path) extract_zip_archive!(temp_path)
else else
raise InvaildStateError, 'unsupported artifacts format' raise InvalidStateError, 'unsupported artifacts format'
end end
end end
def extract_zip_archive!(temp_path) def extract_zip_archive!(temp_path)
raise InvaildStateError, 'missing artifacts metadata' unless build.artifacts_metadata? raise InvalidStateError, 'missing artifacts metadata' unless build.artifacts_metadata?
# Calculate page size after extract # Calculate page size after extract
public_entry = build.artifacts_metadata_entry(SITE_PATH, recursive: true) public_entry = build.artifacts_metadata_entry(SITE_PATH, recursive: true)
if public_entry.total_size > max_size if public_entry.total_size > max_size
raise InvaildStateError, "artifacts for pages are too large: #{public_entry.total_size}" raise InvalidStateError, "artifacts for pages are too large: #{public_entry.total_size}"
end end
# Requires UnZip at least 6.00 Info-ZIP. # Requires UnZip at least 6.00 Info-ZIP.
...@@ -162,11 +160,6 @@ module Projects ...@@ -162,11 +160,6 @@ module Projects
build.artifacts_file.path build.artifacts_file.path
end end
def delete_artifact!
build.reload # Reload stable object to prevent erase artifacts with old state
build.erase_artifacts! unless build.has_expiring_artifacts?
end
def latest_sha def latest_sha
project.commit(build.ref).try(:sha).to_s project.commit(build.ref).try(:sha).to_s
ensure ensure
......
...@@ -20,11 +20,12 @@ class RepositoryArchiveCleanUpService ...@@ -20,11 +20,12 @@ class RepositoryArchiveCleanUpService
private private
def clean_up_old_archives def clean_up_old_archives
run(%W(find #{path} -not -path #{path} -type f \( -name \*.tar -o -name \*.bz2 -o -name \*.tar.gz -o -name \*.zip \) -maxdepth 2 -mmin +#{mmin} -delete)) run(%W(find #{path} -mindepth 1 -maxdepth 3 -type f \( -name \*.tar -o -name \*.bz2 -o -name \*.tar.gz -o -name \*.zip \) -mmin +#{mmin} -delete))
end end
def clean_up_empty_directories def clean_up_empty_directories
run(%W(find #{path} -not -path #{path} -type d -empty -name \*.git -maxdepth 1 -delete)) run(%W(find #{path} -mindepth 2 -maxdepth 2 -type d -empty -delete))
run(%W(find #{path} -mindepth 1 -maxdepth 1 -type d -empty -delete))
end end
def run(cmd) def run(cmd)
......
...@@ -8,18 +8,17 @@ ...@@ -8,18 +8,17 @@
%li{ class: "branch-item js-branch-#{branch.name}" } %li{ class: "branch-item js-branch-#{branch.name}" }
.branch-info .branch-info
.branch-title .branch-title
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name' do = sprite_icon('fork', size: 12)
= sprite_icon('fork', size: 12) = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8' do
= branch.name = branch.name
&nbsp;
- if branch.name == @repository.root_ref - if branch.name == @repository.root_ref
%span.label.label-primary default %span.label.label-primary.prepend-left-5 default
- elsif merged - elsif merged
%span.label.label-info.has-tooltip{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } } %span.label.label-info.has-tooltip.prepend-left-5{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
= s_('Branches|merged') = s_('Branches|merged')
- if protected_branch?(@project, branch) - if protected_branch?(@project, branch)
%span.label.label-success %span.label.label-success.prepend-left-5
= s_('Branches|protected') = s_('Branches|protected')
- if @project.mirror_ever_updated_successfully? && @repository.diverged_from_upstream?(branch.name) - if @project.mirror_ever_updated_successfully? && @repository.diverged_from_upstream?(branch.name)
......
---
title: Don't automatically remove artifacts for pages jobs after pages:deploy has
run
merge_request: 18628
author:
type: fixed
---
title: Fix redirection error for applications using OpenID
merge_request: 18599
author:
type: fixed
---
title: Fixed inconsistent protected branch pill baseline
merge_request:
author:
type: fixed
---
title: Revert discussion counter height
merge_request: 18656
author: George Tsiolis
type: changed
---
title: Serve archive requests with the correct file in all cases
merge_request:
author:
type: security
---
title: Sanitizes user name to avoid XSS attacks
merge_request:
author:
type: security
...@@ -104,5 +104,5 @@ Doorkeeper.configure do ...@@ -104,5 +104,5 @@ Doorkeeper.configure do
# set to true if you want this to be allowed # set to true if you want this to be allowed
# wildcard_redirect_uri false # wildcard_redirect_uri false
base_controller 'ApplicationController' base_controller '::Gitlab::BaseDoorkeeperController'
end end
...@@ -116,6 +116,14 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i ...@@ -116,6 +116,14 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i
#### Merge Requests #### Merge Requests
- [Merge Requests](user/project/merge_requests/index.md)
- [Work In Progress "WIP" Merge Requests](user/project/merge_requests/work_in_progress_merge_requests.md)
- [Merge Request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue): Resolve discussions, move discussions in a merge request to an issue, only allow merge requests to be merged if all discussions are resolved.
- [Checkout merge requests locally](user/project/merge_requests/index.md#checkout-merge-requests-locally)
- [Cherry-pick](user/project/merge_requests/cherry_pick_changes.md)
#### Merge Requests
- [Merge Requests](user/project/merge_requests/index.md) - [Merge Requests](user/project/merge_requests/index.md)
- [Work In Progress "WIP" Merge Requests](user/project/merge_requests/work_in_progress_merge_requests.md) - [Work In Progress "WIP" Merge Requests](user/project/merge_requests/work_in_progress_merge_requests.md)
- [Merge Request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue): Resolve discussions, move discussions in a merge request to an issue, only allow merge requests to be merged if all discussions are resolved. - [Merge Request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue): Resolve discussions, move discussions in a merge request to an issue, only allow merge requests to be merged if all discussions are resolved.
...@@ -146,12 +154,15 @@ scales to run your tests faster. ...@@ -146,12 +154,15 @@ scales to run your tests faster.
- [GitLab CI/CD](ci/README.md): Explore the features and capabilities of Continuous Integration, Continuous Delivery, and Continuous Deployment with GitLab. - [GitLab CI/CD](ci/README.md): Explore the features and capabilities of Continuous Integration, Continuous Delivery, and Continuous Deployment with GitLab.
- [Review Apps](ci/review_apps/index.md): Preview changes to your app right from a merge request. - [Review Apps](ci/review_apps/index.md): Preview changes to your app right from a merge request.
- [Pipeline Graphs](ci/pipelines.md#pipeline-graphs) - [Pipeline Graphs](ci/pipelines.md#pipeline-graphs)
<<<<<<< HEAD
- [Multi-project pipeline graphs](ci/multi_project_pipeline_graphs.md) **[PREMIUM]** - [Multi-project pipeline graphs](ci/multi_project_pipeline_graphs.md) **[PREMIUM]**
- [Code Quality](user/project/merge_requests/code_quality_diff.md) **[STARTER]** - [Code Quality](user/project/merge_requests/code_quality_diff.md) **[STARTER]**
- [Static Application Security Testing (SAST)](user/project/merge_requests/sast.md) **[ULTIMATE]** - [Static Application Security Testing (SAST)](user/project/merge_requests/sast.md) **[ULTIMATE]**
- [Dynamic Application Security Testing (DAST)](user/project/merge_requests/dast.md) **[ULTIMATE]** - [Dynamic Application Security Testing (DAST)](user/project/merge_requests/dast.md) **[ULTIMATE]**
- [Container Scanning](ci/examples/container_scanning.md) **[ULTIMATE]** - [Container Scanning](ci/examples/container_scanning.md) **[ULTIMATE]**
- [Dependency Scanning](ci/examples/dependency_scanning.md) **[ULTIMATE]** - [Dependency Scanning](ci/examples/dependency_scanning.md) **[ULTIMATE]**
=======
>>>>>>> upstream/master
### Package ### Package
...@@ -172,8 +183,11 @@ confidently and securely with GitLab’s built-in Continuous Delivery and Deploy ...@@ -172,8 +183,11 @@ confidently and securely with GitLab’s built-in Continuous Delivery and Deploy
- [GitLab Pages](user/project/pages/index.md): Build, test, and deploy a static site directly from GitLab. - [GitLab Pages](user/project/pages/index.md): Build, test, and deploy a static site directly from GitLab.
- [Scheduled Pipelines](user/project/pipelines/schedules.md) - [Scheduled Pipelines](user/project/pipelines/schedules.md)
- [Protected Runners](ci/runners/README.md#protected-runners) - [Protected Runners](ci/runners/README.md#protected-runners)
<<<<<<< HEAD
- [Deploy Boards](user/project/deploy_boards.md): View of the current health and status of each CI environment running on Kubernetes, displaying the status of the pods in the deployment. **[PREMIUM]** - [Deploy Boards](user/project/deploy_boards.md): View of the current health and status of each CI environment running on Kubernetes, displaying the status of the pods in the deployment. **[PREMIUM]**
- [Canary Deployments](user/project/canary_deployments.md): A popular CI strategy, where a small portion of the fleet is updated to the new version first. **[PREMIUM]** - [Canary Deployments](user/project/canary_deployments.md): A popular CI strategy, where a small portion of the fleet is updated to the new version first. **[PREMIUM]**
=======
>>>>>>> upstream/master
### Configure ### Configure
...@@ -185,8 +199,11 @@ configuration. Then customize everything from buildpacks to CI/CD. ...@@ -185,8 +199,11 @@ configuration. Then customize everything from buildpacks to CI/CD.
- [Deployment of Helm, Ingress, and Prometheus on Kubernetes](user/project/clusters/index.md#installing-applications) - [Deployment of Helm, Ingress, and Prometheus on Kubernetes](user/project/clusters/index.md#installing-applications)
- [Protected secret variables](ci/variables/README.md#protected-secret-variables) - [Protected secret variables](ci/variables/README.md#protected-secret-variables)
- [Easy creation of Kubernetes clusters on GKE](user/project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab) - [Easy creation of Kubernetes clusters on GKE](user/project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab)
<<<<<<< HEAD
- [Multiple Kubernetes Clusters](user/project/clusters/index.md#multiple-kubernetes-clusters) **[PREMIUM]** - [Multiple Kubernetes Clusters](user/project/clusters/index.md#multiple-kubernetes-clusters) **[PREMIUM]**
- [Environment-specific secret variables](ci/variables/README.md#limiting-environment-scopes-of-secret-variables) **[PREMIUM]** - [Environment-specific secret variables](ci/variables/README.md#limiting-environment-scopes-of-secret-variables) **[PREMIUM]**
=======
>>>>>>> upstream/master
### Monitor ### Monitor
......
...@@ -42,7 +42,10 @@ comments: false ...@@ -42,7 +42,10 @@ comments: false
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible - [Avoid modules with instance variables](module_with_instance_variables.md) if possible
- [How to dump production data to staging](db_dump.md) - [How to dump production data to staging](db_dump.md)
- [Working with the GitHub importer](github_importer.md) - [Working with the GitHub importer](github_importer.md)
<<<<<<< HEAD
- [Elasticsearch integration docs](elasticsearch.md) - [Elasticsearch integration docs](elasticsearch.md)
=======
>>>>>>> upstream/master
- [Working with Merge Request diffs](diffs.md) - [Working with Merge Request diffs](diffs.md)
## Performance guides ## Performance guides
......
# This is a base controller for doorkeeper.
# It adds the `can?` helper used in the views.
module Gitlab
class BaseDoorkeeperController < ActionController::Base
include Gitlab::Allowable
helper_method :can?
end
end
...@@ -12,7 +12,7 @@ module Gitlab ...@@ -12,7 +12,7 @@ module Gitlab
# class. # class.
# #
class RemoteRepository class RemoteRepository
attr_reader :path, :relative_path, :gitaly_repository attr_reader :relative_path, :gitaly_repository
def initialize(repository) def initialize(repository)
@relative_path = repository.relative_path @relative_path = repository.relative_path
...@@ -21,7 +21,6 @@ module Gitlab ...@@ -21,7 +21,6 @@ module Gitlab
# These instance variables will not be available in gitaly-ruby, where # These instance variables will not be available in gitaly-ruby, where
# we have no disk access to this repository. # we have no disk access to this repository.
@repository = repository @repository = repository
@path = repository.path
end end
def empty? def empty?
...@@ -69,6 +68,10 @@ module Gitlab ...@@ -69,6 +68,10 @@ module Gitlab
env env
end end
def path
@repository.path
end
private private
# Must return an object that responds to 'address' and 'storage'. # Must return an object that responds to 'address' and 'storage'.
......
...@@ -391,18 +391,6 @@ module Gitlab ...@@ -391,18 +391,6 @@ module Gitlab
nil nil
end end
def archive_prefix(ref, sha, append_sha:)
append_sha = (ref != sha) if append_sha.nil?
project_name = self.name.chomp('.git')
formatted_ref = ref.tr('/', '-')
prefix_segments = [project_name, formatted_ref]
prefix_segments << sha if append_sha
prefix_segments.join('-')
end
def archive_metadata(ref, storage_path, format = "tar.gz", append_sha:) def archive_metadata(ref, storage_path, format = "tar.gz", append_sha:)
ref ||= root_ref ref ||= root_ref
commit = Gitlab::Git::Commit.find(self, ref) commit = Gitlab::Git::Commit.find(self, ref)
...@@ -413,12 +401,44 @@ module Gitlab ...@@ -413,12 +401,44 @@ module Gitlab
{ {
'RepoPath' => path, 'RepoPath' => path,
'ArchivePrefix' => prefix, 'ArchivePrefix' => prefix,
'ArchivePath' => archive_file_path(prefix, storage_path, format), 'ArchivePath' => archive_file_path(storage_path, commit.id, prefix, format),
'CommitId' => commit.id 'CommitId' => commit.id
} }
end end
def archive_file_path(name, storage_path, format = "tar.gz") # This is both the filename of the archive (missing the extension) and the
# name of the top-level member of the archive under which all files go
#
# FIXME: The generated prefix is incorrect for projects with hashed
# storage enabled
def archive_prefix(ref, sha, append_sha:)
append_sha = (ref != sha) if append_sha.nil?
project_name = self.name.chomp('.git')
formatted_ref = ref.tr('/', '-')
prefix_segments = [project_name, formatted_ref]
prefix_segments << sha if append_sha
prefix_segments.join('-')
end
private :archive_prefix
# The full path on disk where the archive should be stored. This is used
# to cache the archive between requests.
#
# The path is a global namespace, so needs to be globally unique. This is
# achieved by including `gl_repository` in the path.
#
# Archives relating to a particular ref when the SHA is not present in the
# filename must be invalidated when the ref is updated to point to a new
# SHA. This is achieved by including the SHA in the path.
#
# As this is a full path on disk, it is not "cloud native". This should
# be resolved by either removing the cache, or moving the implementation
# into Gitaly and removing the ArchivePath parameter from the git-archive
# senddata response.
def archive_file_path(storage_path, sha, name, format = "tar.gz")
# Build file path # Build file path
return nil unless name return nil unless name
...@@ -436,8 +456,9 @@ module Gitlab ...@@ -436,8 +456,9 @@ module Gitlab
end end
file_name = "#{name}.#{extension}" file_name = "#{name}.#{extension}"
File.join(storage_path, self.name, file_name) File.join(storage_path, self.gl_repository, sha, file_name)
end end
private :archive_file_path
# Return repo size in megabytes # Return repo size in megabytes
def size def size
...@@ -1183,6 +1204,8 @@ module Gitlab ...@@ -1183,6 +1204,8 @@ module Gitlab
if is_enabled if is_enabled
gitaly_fetch_ref(source_repository, source_ref: source_ref, target_ref: target_ref) gitaly_fetch_ref(source_repository, source_ref: source_ref, target_ref: target_ref)
else else
# When removing this code, also remove source_repository#path
# to remove deprecated method calls
local_fetch_ref(source_repository.path, source_ref: source_ref, target_ref: target_ref) local_fetch_ref(source_repository.path, source_ref: source_ref, target_ref: target_ref)
end end
end end
......
...@@ -142,7 +142,7 @@ module Gitlab ...@@ -142,7 +142,7 @@ module Gitlab
:repository_service, :repository_service,
:is_rebase_in_progress, :is_rebase_in_progress,
request, request,
timeout: GitalyClient.default_timeout timeout: GitalyClient.fast_timeout
) )
response.in_progress response.in_progress
...@@ -159,7 +159,7 @@ module Gitlab ...@@ -159,7 +159,7 @@ module Gitlab
:repository_service, :repository_service,
:is_squash_in_progress, :is_squash_in_progress,
request, request,
timeout: GitalyClient.default_timeout timeout: GitalyClient.fast_timeout
) )
response.in_progress response.in_progress
......
...@@ -138,7 +138,7 @@ const RESPONSE_MAP = { ...@@ -138,7 +138,7 @@ const RESPONSE_MAP = {
}, },
{ {
id: 20, id: 20,
name_with_namespace: 'foo / bar', name_with_namespace: '<img src=x onerror=alert(document.domain)> foo / bar',
}, },
], ],
}, },
......
...@@ -69,6 +69,15 @@ describe('SidebarMoveIssue', function () { ...@@ -69,6 +69,15 @@ describe('SidebarMoveIssue', function () {
expect($.fn.glDropdown).toHaveBeenCalled(); expect($.fn.glDropdown).toHaveBeenCalled();
}); });
it('escapes html from project name', (done) => {
this.$toggleButton.dropdown('toggle');
setTimeout(() => {
expect(this.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual('&lt;img src=x onerror=alert(document.domain)&gt; foo / bar');
done();
});
});
}); });
describe('onConfirmClicked', () => { describe('onConfirmClicked', () => {
......
...@@ -234,59 +234,72 @@ describe Gitlab::Git::Repository, seed_helper: true do ...@@ -234,59 +234,72 @@ describe Gitlab::Git::Repository, seed_helper: true do
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :tag_names it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :tag_names
end end
shared_examples 'archive check' do |extenstion| describe '#archive_metadata' do
it { expect(metadata['ArchivePath']).to match(%r{tmp/gitlab-git-test.git/gitlab-git-test-master-#{SeedRepo::LastCommit::ID}}) } let(:storage_path) { '/tmp' }
it { expect(metadata['ArchivePath']).to end_with extenstion } let(:cache_key) { File.join(repository.gl_repository, SeedRepo::LastCommit::ID) }
end
describe '#archive_prefix' do let(:append_sha) { true }
let(:project_name) { 'project-name'} let(:ref) { 'master' }
let(:format) { nil }
before do let(:expected_extension) { 'tar.gz' }
expect(repository).to receive(:name).once.and_return(project_name) let(:expected_filename) { "#{expected_prefix}.#{expected_extension}" }
end let(:expected_path) { File.join(storage_path, cache_key, expected_filename) }
let(:expected_prefix) { "gitlab-git-test-#{ref}-#{SeedRepo::LastCommit::ID}" }
it 'returns parameterised string for a ref containing slashes' do subject(:metadata) { repository.archive_metadata(ref, storage_path, format, append_sha: append_sha) }
prefix = repository.archive_prefix('test/branch', 'SHA', append_sha: nil)
expect(prefix).to eq("#{project_name}-test-branch-SHA") it 'sets RepoPath to the repository path' do
expect(metadata['RepoPath']).to eq(repository.path)
end end
it 'returns correct string for a ref containing dots' do it 'sets CommitId to the commit SHA' do
prefix = repository.archive_prefix('test.branch', 'SHA', append_sha: nil) expect(metadata['CommitId']).to eq(SeedRepo::LastCommit::ID)
expect(prefix).to eq("#{project_name}-test.branch-SHA")
end end
it 'returns string with sha when append_sha is false' do it 'sets ArchivePrefix to the expected prefix' do
prefix = repository.archive_prefix('test.branch', 'SHA', append_sha: false) expect(metadata['ArchivePrefix']).to eq(expected_prefix)
expect(prefix).to eq("#{project_name}-test.branch")
end end
end
describe '#archive' do it 'sets ArchivePath to the expected globally-unique path' do
let(:metadata) { repository.archive_metadata('master', '/tmp', append_sha: true) } # This is really important from a security perspective. Think carefully
# before changing it: https://gitlab.com/gitlab-org/gitlab-ce/issues/45689
expect(expected_path).to include(File.join(repository.gl_repository, SeedRepo::LastCommit::ID))
it_should_behave_like 'archive check', '.tar.gz' expect(metadata['ArchivePath']).to eq(expected_path)
end end
describe '#archive_zip' do
let(:metadata) { repository.archive_metadata('master', '/tmp', 'zip', append_sha: true) }
it_should_behave_like 'archive check', '.zip' context 'append_sha varies archive path and filename' do
end where(:append_sha, :ref, :expected_prefix) do
sha = SeedRepo::LastCommit::ID
describe '#archive_bz2' do true | 'master' | "gitlab-git-test-master-#{sha}"
let(:metadata) { repository.archive_metadata('master', '/tmp', 'tbz2', append_sha: true) } true | sha | "gitlab-git-test-#{sha}-#{sha}"
false | 'master' | "gitlab-git-test-master"
false | sha | "gitlab-git-test-#{sha}"
nil | 'master' | "gitlab-git-test-master-#{sha}"
nil | sha | "gitlab-git-test-#{sha}"
end
it_should_behave_like 'archive check', '.tar.bz2' with_them do
end it { expect(metadata['ArchivePrefix']).to eq(expected_prefix) }
it { expect(metadata['ArchivePath']).to eq(expected_path) }
end
end
describe '#archive_fallback' do context 'format varies archive path and filename' do
let(:metadata) { repository.archive_metadata('master', '/tmp', 'madeup', append_sha: true) } where(:format, :expected_extension) do
nil | 'tar.gz'
'madeup' | 'tar.gz'
'tbz2' | 'tar.bz2'
'zip' | 'zip'
end
it_should_behave_like 'archive check', '.tar.gz' with_them do
it { expect(metadata['ArchivePrefix']).to eq(expected_prefix) }
it { expect(metadata['ArchivePath']).to eq(expected_path) }
end
end
end end
describe '#size' do describe '#size' do
......
...@@ -153,4 +153,13 @@ describe 'OpenID Connect requests' do ...@@ -153,4 +153,13 @@ describe 'OpenID Connect requests' do
end end
end end
end end
context 'OpenID configuration information' do
it 'correctly returns the configuration' do
get '/.well-known/openid-configuration'
expect(response).to have_gitlab_http_status(200)
expect(json_response).to have_key('issuer')
end
end
end end
...@@ -29,25 +29,10 @@ describe Projects::UpdatePagesService do ...@@ -29,25 +29,10 @@ describe Projects::UpdatePagesService do
end end
describe 'pages artifacts' do describe 'pages artifacts' do
context 'with expiry date' do it "doesn't delete artifacts after deploying" do
before do expect(execute).to eq(:success)
build.artifacts_expire_in = "2 days"
build.save!
end
it "doesn't delete artifacts" do
expect(execute).to eq(:success)
expect(build.reload.artifacts?).to eq(true)
end
end
context 'without expiry date' do
it "does delete artifacts" do
expect(execute).to eq(:success)
expect(build.reload.artifacts?).to eq(false) expect(build.reload.artifacts?).to eq(true)
end
end end
end end
...@@ -100,25 +85,10 @@ describe Projects::UpdatePagesService do ...@@ -100,25 +85,10 @@ describe Projects::UpdatePagesService do
end end
describe 'pages artifacts' do describe 'pages artifacts' do
context 'with expiry date' do it "doesn't delete artifacts after deploying" do
before do expect(execute).to eq(:success)
build.artifacts_expire_in = "2 days"
build.save!
end
it "doesn't delete artifacts" do
expect(execute).to eq(:success)
expect(build.artifacts?).to eq(true)
end
end
context 'without expiry date' do
it "does delete artifacts" do
expect(execute).to eq(:success)
expect(build.reload.artifacts?).to eq(false) expect(build.artifacts?).to eq(true)
end
end end
end end
...@@ -171,13 +141,12 @@ describe Projects::UpdatePagesService do ...@@ -171,13 +141,12 @@ describe Projects::UpdatePagesService do
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(build.artifacts?).to be_truthy
end end
end end
context 'when failed to extract zip artifacts' do context 'when failed to extract zip artifacts' do
before do before do
allow_any_instance_of(described_class) expect_any_instance_of(described_class)
.to receive(:extract_zip_archive!) .to receive(:extract_zip_archive!)
.and_raise(Projects::UpdatePagesService::FailedToExtractError) .and_raise(Projects::UpdatePagesService::FailedToExtractError)
end end
...@@ -188,21 +157,19 @@ describe Projects::UpdatePagesService do ...@@ -188,21 +157,19 @@ describe Projects::UpdatePagesService do
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(build.artifacts?).to be_truthy
end end
end end
context 'when missing artifacts metadata' do context 'when missing artifacts metadata' do
before do before do
allow(build).to receive(:artifacts_metadata?).and_return(false) expect(build).to receive(:artifacts_metadata?).and_return(false)
end end
it 'does not raise an error and remove artifacts as failed job' do it 'does not raise an error as failed job' do
execute execute
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(build.artifacts?).to be_falsey
end end
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe RepositoryArchiveCleanUpService do describe RepositoryArchiveCleanUpService do
describe '#execute' do subject(:service) { described_class.new }
subject(:service) { described_class.new }
describe '#execute (new archive locations)' do
let(:sha) { "0" * 40 }
it 'removes outdated archives and directories in a new-style path' do
in_directory_with_files("project-999/#{sha}", %w[tar tar.bz2 tar.gz zip], 3.hours) do |dirname, files|
service.execute
files.each { |filename| expect(File.exist?(filename)).to be_falsy }
expect(File.directory?(dirname)).to be_falsy
expect(File.directory?(File.dirname(dirname))).to be_falsy
end
end
it 'does not remove directories when they contain outdated non-archives' do
in_directory_with_files("project-999/#{sha}", %w[tar conf rb], 2.hours) do |dirname, files|
service.execute
expect(File.directory?(dirname)).to be_truthy
end
end
it 'does not remove in-date archives in a new-style path' do
in_directory_with_files("project-999/#{sha}", %w[tar tar.bz2 tar.gz zip], 1.hour) do |dirname, files|
service.execute
files.each { |filename| expect(File.exist?(filename)).to be_truthy }
end
end
end
describe '#execute (legacy archive locations)' do
context 'when the downloads directory does not exist' do context 'when the downloads directory does not exist' do
it 'does not remove any archives' do it 'does not remove any archives' do
path = '/invalid/path/' path = '/invalid/path/'
stub_repository_downloads_path(path) stub_repository_downloads_path(path)
allow(File).to receive(:directory?).and_call_original
expect(File).to receive(:directory?).with(path).and_return(false) expect(File).to receive(:directory?).with(path).and_return(false)
expect(service).not_to receive(:clean_up_old_archives) expect(service).not_to receive(:clean_up_old_archives)
expect(service).not_to receive(:clean_up_empty_directories) expect(service).not_to receive(:clean_up_empty_directories)
...@@ -19,7 +51,7 @@ describe RepositoryArchiveCleanUpService do ...@@ -19,7 +51,7 @@ describe RepositoryArchiveCleanUpService do
context 'when the downloads directory exists' do context 'when the downloads directory exists' do
shared_examples 'invalid archive files' do |dirname, extensions, mtime| shared_examples 'invalid archive files' do |dirname, extensions, mtime|
it 'does not remove files and directoy' do it 'does not remove files and directory' do
in_directory_with_files(dirname, extensions, mtime) do |dir, files| in_directory_with_files(dirname, extensions, mtime) do |dir, files|
service.execute service.execute
...@@ -43,7 +75,7 @@ describe RepositoryArchiveCleanUpService do ...@@ -43,7 +75,7 @@ describe RepositoryArchiveCleanUpService do
end end
context 'with files older than 2 hours inside invalid directories' do context 'with files older than 2 hours inside invalid directories' do
it_behaves_like 'invalid archive files', 'john_doe/sample.git', %w[conf rb tar tar.gz], 2.hours it_behaves_like 'invalid archive files', 'john/doe/sample.git', %w[conf rb tar tar.gz], 2.hours
end end
context 'with files newer than 2 hours that matches valid archive extensions' do context 'with files newer than 2 hours that matches valid archive extensions' do
...@@ -58,24 +90,24 @@ describe RepositoryArchiveCleanUpService do ...@@ -58,24 +90,24 @@ describe RepositoryArchiveCleanUpService do
it_behaves_like 'invalid archive files', 'sample.git', %w[conf rb tar tar.gz], 1.hour it_behaves_like 'invalid archive files', 'sample.git', %w[conf rb tar tar.gz], 1.hour
end end
end end
end
def in_directory_with_files(dirname, extensions, mtime) def in_directory_with_files(dirname, extensions, mtime)
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
stub_repository_downloads_path(tmpdir) stub_repository_downloads_path(tmpdir)
dir = File.join(tmpdir, dirname) dir = File.join(tmpdir, dirname)
files = create_temporary_files(dir, extensions, mtime) files = create_temporary_files(dir, extensions, mtime)
yield(dir, files) yield(dir, files)
end
end end
end
def stub_repository_downloads_path(path) def stub_repository_downloads_path(path)
allow(Gitlab.config.gitlab).to receive(:repository_downloads_path).and_return(path) allow(Gitlab.config.gitlab).to receive(:repository_downloads_path).and_return(path)
end end
def create_temporary_files(dir, extensions, mtime) def create_temporary_files(dir, extensions, mtime)
FileUtils.mkdir_p(dir) FileUtils.mkdir_p(dir)
FileUtils.touch(extensions.map { |ext| File.join(dir, "sample.#{ext}") }, mtime: Time.now - mtime) FileUtils.touch(extensions.map { |ext| File.join(dir, "sample.#{ext}") }, mtime: Time.now - mtime)
end
end end
end end
...@@ -22,13 +22,11 @@ describe NamespacelessProjectDestroyWorker do ...@@ -22,13 +22,11 @@ describe NamespacelessProjectDestroyWorker do
end end
end end
# Only possible with schema 20180222043024 and lower. context 'project has no namespace' do
# Project#namespace_id has not null constraint since then let!(:project) { create(:project) }
context 'project has no namespace', :migration, schema: 20180222043024 do
let!(:project) do before do
project = build(:project, namespace_id: nil) allow_any_instance_of(Project).to receive(:namespace).and_return(nil)
project.save(validate: false)
project
end end
context 'project not a fork of another project' do context 'project not a fork of another project' do
...@@ -61,8 +59,7 @@ describe NamespacelessProjectDestroyWorker do ...@@ -61,8 +59,7 @@ describe NamespacelessProjectDestroyWorker do
let!(:parent_project) { create(:project) } let!(:parent_project) { create(:project) }
let(:project) do let(:project) do
namespaceless_project = fork_project(parent_project) namespaceless_project = fork_project(parent_project)
namespaceless_project.namespace_id = nil namespaceless_project.save
namespaceless_project.save(validate: false)
namespaceless_project namespaceless_project
end end
......
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