Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
344f2d16
Commit
344f2d16
authored
Oct 11, 2017
by
Tiago Botelho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add maximum retry count migration and related logic
parent
43ec8c81
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
304 additions
and
99 deletions
+304
-99
app/controllers/projects/mirrors_controller.rb
app/controllers/projects/mirrors_controller.rb
+9
-1
app/helpers/mirror_helper.rb
app/helpers/mirror_helper.rb
+28
-0
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+0
-6
app/models/project_mirror_data.rb
app/models/project_mirror_data.rb
+4
-2
app/views/projects/mirrors/pull/_mirror_update_fail.html.haml
...views/projects/mirrors/pull/_mirror_update_fail.html.haml
+2
-4
app/views/shared/_mirror_status.html.haml
app/views/shared/_mirror_status.html.haml
+1
-14
app/views/shared/projects/_mirror_status.html.haml
app/views/shared/projects/_mirror_status.html.haml
+12
-0
changelogs/unreleased-ee/2831-hard-fail-mirror-when-retry-count-number-exceeds-the-limit.yml
...fail-mirror-when-retry-count-number-exceeds-the-limit.yml
+6
-0
doc/workflow/repository_mirroring.md
doc/workflow/repository_mirroring.md
+17
-0
doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.png
...itory_mirroring/repository_mirroring_hard_failed_main.png
+0
-0
doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.png
...y_mirroring/repository_mirroring_hard_failed_settings.png
+0
-0
ee/app/helpers/ee/projects_helper.rb
ee/app/helpers/ee/projects_helper.rb
+7
-0
ee/app/models/ee/project.rb
ee/app/models/ee/project.rb
+18
-6
ee/app/models/ee/project/import_status_state_machine.rb
ee/app/models/ee/project/import_status_state_machine.rb
+19
-0
lib/gitlab/mirror.rb
lib/gitlab/mirror.rb
+7
-0
spec/controllers/projects/mirrors_controller_spec.rb
spec/controllers/projects/mirrors_controller_spec.rb
+14
-0
spec/ee/spec/models/ee/project_spec.rb
spec/ee/spec/models/ee/project_spec.rb
+141
-0
spec/factories/projects.rb
spec/factories/projects.rb
+8
-0
spec/models/project_mirror_data_spec.rb
spec/models/project_mirror_data_spec.rb
+11
-4
spec/models/project_spec.rb
spec/models/project_spec.rb
+0
-62
No files found.
app/controllers/projects/mirrors_controller.rb
View file @
344f2d16
...
@@ -62,7 +62,7 @@ class Projects::MirrorsController < Projects::ApplicationController
...
@@ -62,7 +62,7 @@ class Projects::MirrorsController < Projects::ApplicationController
@project
.
update_remote_mirrors
@project
.
update_remote_mirrors
flash
[
:notice
]
=
"The remote repository is being updated..."
flash
[
:notice
]
=
"The remote repository is being updated..."
else
else
@project
.
force_import_job!
force_import_job
flash
[
:notice
]
=
"The repository is being updated..."
flash
[
:notice
]
=
"The repository is being updated..."
end
end
...
@@ -71,6 +71,14 @@ class Projects::MirrorsController < Projects::ApplicationController
...
@@ -71,6 +71,14 @@ class Projects::MirrorsController < Projects::ApplicationController
private
private
def
force_import_job
if
@project
.
hard_failed?
@project
.
resume
else
@project
.
force_import_job!
end
end
def
remote_mirror
def
remote_mirror
@remote_mirror
=
@project
.
remote_mirrors
.
first_or_initialize
@remote_mirror
=
@project
.
remote_mirrors
.
first_or_initialize
end
end
...
...
app/helpers/mirror_helper.rb
View file @
344f2d16
module
MirrorHelper
module
MirrorHelper
def
mirror_update_failed?
return
true
if
@project
.
hard_failed?
@project
.
mirror_last_update_failed?
end
def
render_mirror_failed_message
(
status
:,
icon
:)
message
=
get_mirror_failed_message
(
status
)
return
message
unless
icon
message_with_icon
=
"
#{
icon
(
'warning triangle'
)
}
#{
message
}
"
return
message_with_icon
unless
can?
(
current_user
,
:admin_project
,
@project
)
link_to
(
project_mirror_path
(
@project
))
{
"
#{
icon
(
'warning triangle'
)
}
#{
message
}
"
}
end
def
branch_diverged_tooltip_message
def
branch_diverged_tooltip_message
message
=
s_
(
'Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart.'
)
message
=
s_
(
'Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart.'
)
...
@@ -13,4 +30,15 @@ module MirrorHelper
...
@@ -13,4 +30,15 @@ module MirrorHelper
def
options_for_mirror_user
def
options_for_mirror_user
options_from_collection_for_select
(
default_mirror_users
,
:id
,
:name
,
@project
.
mirror_user_id
||
current_user
.
id
)
options_from_collection_for_select
(
default_mirror_users
,
:id
,
:name
,
@project
.
mirror_user_id
||
current_user
.
id
)
end
end
private
def
get_mirror_failed_message
(
status
)
if
status
==
:failed
"The repository failed to update
#{
time_ago_with_tooltip
(
@project
.
last_update_at
)
}
."
else
"The repository failed to update
#{
time_ago_with_tooltip
(
last_update_at
)
}
.<br>"
\
"Repository mirroring has been paused due to too many failed attempts, and can be resumed by a project admin."
end
end
end
end
app/helpers/projects_helper.rb
View file @
344f2d16
...
@@ -512,12 +512,6 @@ module ProjectsHelper
...
@@ -512,12 +512,6 @@ module ProjectsHelper
end
end
end
end
def
can_force_update_mirror?
(
project
)
return
true
unless
project
.
mirror_last_update_at
Time
.
now
-
project
.
mirror_last_update_at
>=
5
.
minutes
end
def
membership_locked?
def
membership_locked?
if
@project
.
group
&&
@project
.
group
.
membership_lock
if
@project
.
group
&&
@project
.
group
.
membership_lock
true
true
...
...
app/models/project_mirror_data.rb
View file @
344f2d16
class
ProjectMirrorData
<
ActiveRecord
::
Base
class
ProjectMirrorData
<
ActiveRecord
::
Base
include
Gitlab
::
CurrentSettings
BACKOFF_PERIOD
=
24
.
seconds
BACKOFF_PERIOD
=
24
.
seconds
JITTER
=
6
.
seconds
JITTER
=
6
.
seconds
...
@@ -36,6 +34,10 @@ class ProjectMirrorData < ActiveRecord::Base
...
@@ -36,6 +34,10 @@ class ProjectMirrorData < ActiveRecord::Base
self
.
update_attributes
(
next_execution_timestamp:
Time
.
now
)
self
.
update_attributes
(
next_execution_timestamp:
Time
.
now
)
end
end
def
retry_limit_exceeded?
self
.
retry_count
>
Gitlab
::
Mirror
::
MAX_RETRY
end
private
private
def
base_delay
(
timestamp
)
def
base_delay
(
timestamp
)
...
...
app/views/projects/mirrors/pull/_mirror_update_fail.html.haml
View file @
344f2d16
-
if
@project
.
mirror_last
_update_failed?
-
if
mirror
_update_failed?
.panel.panel-danger
.panel.panel-danger
.panel-heading
.panel-heading
The repository failed to update
#{
time_ago_with_tooltip
(
@project
.
mirror_last_update_at
)
}
.
=
render
partial:
'shared/projects/mirror_status'
,
show_icon:
false
-
if
@project
.
mirror_ever_updated_successfully?
Last successful update
#{
time_ago_with_tooltip
(
@project
.
mirror_last_successful_update_at
)
}
.
.panel-body
.panel-body
%pre
%pre
:preserve
:preserve
...
...
app/views/shared/_mirror_status.html.haml
View file @
344f2d16
-
case
@project
.
mirror_last_update_status
=
render
partial:
'shared/projects/mirror_status'
-
when
:success
Updated
#{
time_ago_with_tooltip
(
@project
.
mirror_last_successful_update_at
)
}
.
-
when
:failed
-
if
can?
(
current_user
,
:admin_project
,
@project
)
=
link_to
project_mirror_path
(
@project
)
do
=
icon
(
"exclamation-triangle"
)
Failed to update
#{
time_ago_with_tooltip
(
@project
.
mirror_last_update_at
)
}
.
-
else
=
icon
(
"exclamation-triangle"
)
Failed to update
#{
time_ago_with_tooltip
(
@project
.
mirror_last_update_at
)
}
.
-
if
@project
.
mirror_ever_updated_successfully?
Last successful update
#{
time_ago_with_tooltip
(
@project
.
mirror_last_successful_update_at
)
}
.
app/views/shared/projects/_mirror_status.html.haml
0 → 100644
View file @
344f2d16
-
last_successful_update_at
=
@project
.
mirror_last_successful_update_at
-
mirror_last_update_status
=
@project
.
mirror_last_update_status
-
show_icon
=
local_assigns
.
fetch
(
:show_icon
,
true
)
-
if
mirror_last_update_status
==
:success
Updated
#{
time_ago_with_tooltip
(
last_successful_update_at
)
}
.
-
else
=
render_mirror_failed_message
(
status:
mirror_last_update_status
,
icon:
show_icon
)
-
if
@project
.
mirror_ever_updated_successfully?
%br
Last successful update
#{
time_ago_with_tooltip
(
last_successful_update_at
)
}
.
changelogs/unreleased-ee/2831-hard-fail-mirror-when-retry-count-number-exceeds-the-limit.yml
0 → 100644
View file @
344f2d16
---
title
:
Mirrors can now hard fail, keeping them from being retried until a project
admin takes action.
merge_request
:
3117
author
:
type
:
added
doc/workflow/repository_mirroring.md
View file @
344f2d16
...
@@ -84,6 +84,22 @@ this branch to prevent any changes from being lost.
...
@@ -84,6 +84,22 @@ this branch to prevent any changes from being lost.
![
Diverged branch
](
repository_mirroring/repository_mirroring_diverged_branch.png
)
![
Diverged branch
](
repository_mirroring/repository_mirroring_diverged_branch.png
)
### Hard failure
>[Introduced][ee-3117] in GitLab Enterprise Edition 10.2.
Once a mirror gets retried 14 times in a row, it will get marked as hard failed,
this will become visible in either the project main dashboard or in the
pull mirror settings page.
![
Hard failed mirror main notice
](
repository_mirroring/repository_mirroring_hard_failed_main.png
)
![
Hard failed mirror settings notice
](
repository_mirroring/repository_mirroring_hard_failed_settings.png
)
When a project is hard failed, it will no longer get picked up for mirroring.
A user can resume the project mirroring again by either
[
forcing an update
](
#forcing-an-update
)
or by changing the import URL field in the repository settings.
### SSH authentication
### SSH authentication
> [Introduced][ee-2551] in GitLab Enterprise Edition Starter 9.5
> [Introduced][ee-2551] in GitLab Enterprise Edition Starter 9.5
...
@@ -248,6 +264,7 @@ to resolve this issue.
...
@@ -248,6 +264,7 @@ to resolve this issue.
[
ee-51
]:
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51
[
ee-51
]:
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51
[
ee-2551
]:
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551
[
ee-2551
]:
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551
[
ee-3117
]:
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3117
[
perms
]:
../user/permissions.md
[
perms
]:
../user/permissions.md
[
hooks
]:
https://docs.gitlab.com/ee/administration/custom_hooks.html
[
hooks
]:
https://docs.gitlab.com/ee/administration/custom_hooks.html
[
deploy-key
]:
../ssh/README.md#deploy-keys
[
deploy-key
]:
../ssh/README.md#deploy-keys
doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.png
0 → 100644
View file @
344f2d16
193 KB
doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.png
0 → 100644
View file @
344f2d16
227 KB
ee/app/helpers/ee/projects_helper.rb
View file @
344f2d16
module
EE
module
EE
module
ProjectsHelper
module
ProjectsHelper
def
can_force_update_mirror?
(
project
)
return
true
if
project
.
hard_failed?
return
true
unless
project
.
mirror_last_update_at
Time
.
now
-
project
.
mirror_last_update_at
>=
5
.
minutes
end
def
can_change_push_rule?
(
push_rule
,
rule
)
def
can_change_push_rule?
(
push_rule
,
rule
)
return
true
if
push_rule
.
global?
return
true
if
push_rule
.
global?
...
...
ee/app/models/ee/project.rb
View file @
344f2d16
...
@@ -40,7 +40,12 @@ module EE
...
@@ -40,7 +40,12 @@ module EE
scope
:with_shared_runners_limit_enabled
,
->
{
with_shared_runners
.
non_public_only
}
scope
:with_shared_runners_limit_enabled
,
->
{
with_shared_runners
.
non_public_only
}
scope
:mirror
,
->
{
where
(
mirror:
true
)
}
scope
:mirror
,
->
{
where
(
mirror:
true
)
}
scope
:mirrors_to_sync
,
->
(
freeze_at
)
{
mirror
.
joins
(
:mirror_data
).
without_import_status
(
:scheduled
,
:started
).
where
(
"next_execution_timestamp <= ?"
,
freeze_at
)
}
scope
:mirrors_to_sync
,
->
(
freeze_at
)
do
mirror
.
joins
(
:mirror_data
).
without_import_status
(
:hard_failed
,
:scheduled
,
:started
)
.
where
(
"next_execution_timestamp <= ?"
,
freeze_at
)
end
scope
:with_remote_mirrors
,
->
{
joins
(
:remote_mirrors
).
where
(
remote_mirrors:
{
enabled:
true
}).
distinct
}
scope
:with_remote_mirrors
,
->
{
joins
(
:remote_mirrors
).
where
(
remote_mirrors:
{
enabled:
true
}).
distinct
}
scope
:with_wiki_enabled
,
->
{
with_feature_enabled
(
:wiki
)
}
scope
:with_wiki_enabled
,
->
{
with_feature_enabled
(
:wiki
)
}
...
@@ -100,6 +105,7 @@ module EE
...
@@ -100,6 +105,7 @@ module EE
def
scheduled_mirror?
def
scheduled_mirror?
return
false
unless
mirror_with_content?
return
false
unless
mirror_with_content?
return
false
if
hard_failed?
return
true
if
import_scheduled?
return
true
if
import_scheduled?
self
.
mirror_data
.
next_execution_timestamp
<=
Time
.
now
self
.
mirror_data
.
next_execution_timestamp
<=
Time
.
now
...
@@ -112,11 +118,10 @@ module EE
...
@@ -112,11 +118,10 @@ module EE
def
mirror_last_update_status
def
mirror_last_update_status
return
unless
mirror_updated?
return
unless
mirror_updated?
if
self
.
mirror_last_update_at
==
self
.
mirror_last_successful_update_at
return
:success
if
self
.
last_mirror_update_succeeded?
:success
return
:failed
unless
self
.
mirror_data
.
retry_limit_exceeded?
else
:failed
:hard_failed
end
end
end
def
mirror_last_update_success?
def
mirror_last_update_success?
...
@@ -131,6 +136,10 @@ module EE
...
@@ -131,6 +136,10 @@ module EE
mirror_updated?
&&
self
.
mirror_last_successful_update_at
mirror_updated?
&&
self
.
mirror_last_successful_update_at
end
end
def
last_mirror_update_succeeded?
self
.
mirror_last_update_at
==
self
.
mirror_last_successful_update_at
end
def
has_remote_mirror?
def
has_remote_mirror?
feature_available?
(
:repository_mirrors
)
&&
feature_available?
(
:repository_mirrors
)
&&
remote_mirror_available?
&&
remote_mirror_available?
&&
...
@@ -204,7 +213,10 @@ module EE
...
@@ -204,7 +213,10 @@ module EE
end
end
def
force_import_job!
def
force_import_job!
import_resume
if
hard_failed?
self
.
mirror_data
.
set_next_execution_to_now!
self
.
mirror_data
.
set_next_execution_to_now!
UpdateAllMirrorsWorker
.
perform_async
UpdateAllMirrorsWorker
.
perform_async
end
end
...
...
ee/app/models/ee/project/import_status_state_machine.rb
View file @
344f2d16
...
@@ -5,6 +5,16 @@ module EE
...
@@ -5,6 +5,16 @@ module EE
included
do
included
do
state_machine
:import_status
,
initial: :none
do
state_machine
:import_status
,
initial: :none
do
event
:import_hard_fail
do
transition
failed: :hard_failed
end
event
:import_resume
do
transition
hard_failed: :failed
end
state
:hard_failed
before_transition
[
:none
,
:finished
,
:failed
]
=>
:scheduled
do
|
project
,
_
|
before_transition
[
:none
,
:finished
,
:failed
]
=>
:scheduled
do
|
project
,
_
|
project
.
mirror_data
&
.
last_update_scheduled_at
=
Time
.
now
project
.
mirror_data
&
.
last_update_scheduled_at
=
Time
.
now
end
end
...
@@ -32,6 +42,8 @@ module EE
...
@@ -32,6 +42,8 @@ module EE
mirror_data
=
project
.
mirror_data
mirror_data
=
project
.
mirror_data
mirror_data
.
increment_retry_count!
mirror_data
.
increment_retry_count!
mirror_data
.
set_next_execution_timestamp!
mirror_data
.
set_next_execution_timestamp!
project
.
run_after_commit
{
import_hard_fail
}
if
mirror_data
.
retry_limit_exceeded?
end
end
end
end
...
@@ -54,6 +66,13 @@ module EE
...
@@ -54,6 +66,13 @@ module EE
end
end
end
end
before_transition
hard_failed: :failed
do
|
project
,
_
|
if
project
.
mirror?
project
.
mirror_data
.
reset_retry_count!
project
.
force_import_job!
end
end
after_transition
[
:finished
,
:failed
]
=>
[
:scheduled
,
:started
]
do
|
project
,
_
|
after_transition
[
:finished
,
:failed
]
=>
[
:scheduled
,
:started
]
do
|
project
,
_
|
::
Gitlab
::
Mirror
.
increment_capacity
(
project
.
id
)
if
project
.
mirror?
::
Gitlab
::
Mirror
.
increment_capacity
(
project
.
id
)
if
project
.
mirror?
end
end
...
...
lib/gitlab/mirror.rb
View file @
344f2d16
...
@@ -6,7 +6,14 @@ module Gitlab
...
@@ -6,7 +6,14 @@ module Gitlab
SCHEDULER_CRON
=
'* * * * *'
.
freeze
SCHEDULER_CRON
=
'* * * * *'
.
freeze
PULL_CAPACITY_KEY
=
'MIRROR_PULL_CAPACITY'
.
freeze
PULL_CAPACITY_KEY
=
'MIRROR_PULL_CAPACITY'
.
freeze
JITTER
=
1
.
minute
JITTER
=
1
.
minute
# TODO: Make MIN_DELAY configurable and MAX_RETRY adjust according to it
# ISSUE: https://gitlab.com/gitlab-org/gitlab-ee/issues/3885
# MAX RETRY value was calculated based on the triangular number with a 15 minutes factor
# https://en.wikipedia.org/wiki/Triangular_number in order to make sure the mirror
# gets retried for a full day before it becomes hard failed
MIN_DELAY
=
15
.
minutes
MIN_DELAY
=
15
.
minutes
MAX_RETRY
=
14
class
<<
self
class
<<
self
def
configure_cron_job!
def
configure_cron_job!
...
...
spec/controllers/projects/mirrors_controller_spec.rb
View file @
344f2d16
...
@@ -155,6 +155,20 @@ describe Projects::MirrorsController do
...
@@ -155,6 +155,20 @@ describe Projects::MirrorsController do
put
:update_now
,
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
}
put
:update_now
,
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
}
end
end
context
'when mirror is hard_failed'
do
it
'forces update and changes to failed'
do
allow
(
UpdateAllMirrorsWorker
).
to
receive
(
:perform_async
).
and_return
(
nil
)
project
=
create
(
:project
,
:mirror
,
:import_hard_failed
)
sign_in
(
project
.
owner
)
expect_any_instance_of
(
Project
).
to
receive
(
:import_resume
).
and_call_original
expect
do
put
:update_now
,
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
}
end
.
to
change
{
project
.
reload
.
import_status
}.
from
(
'hard_failed'
).
to
(
'failed'
)
end
end
end
end
describe
'forcing an update on a push mirror'
do
describe
'forcing an update on a push mirror'
do
...
...
spec/ee/spec/models/ee/project_spec.rb
View file @
344f2d16
...
@@ -19,6 +19,34 @@ describe Project do
...
@@ -19,6 +19,34 @@ describe Project do
it
{
is_expected
.
to
have_many
(
:audit_events
)
}
it
{
is_expected
.
to
have_many
(
:audit_events
)
}
end
end
describe
'after update'
do
context
'when mirror is hard failed and import url changed'
do
it
'resumes the mirroring'
do
allow
(
UpdateAllMirrorsWorker
).
to
receive
(
:perform_async
).
and_return
(
nil
)
project
=
create
(
:project
,
:repository
,
:mirror
,
:import_hard_failed
)
expect
do
project
.
update_attributes
(
import_url:
'http://foo.com'
)
end
.
to
change
(
project
,
:import_status
).
from
(
'hard_failed'
).
to
(
'failed'
)
end
end
end
describe
'resuming from a hard failed mirror'
do
it
'resets retry count and schedules a mirroring worker'
do
timestamp
=
Time
.
now
project
=
create
(
:project
,
:mirror
,
:import_hard_failed
)
expect
(
UpdateAllMirrorsWorker
).
to
receive
(
:perform_async
)
Timecop
.
freeze
(
timestamp
)
do
expect
{
project
.
import_resume
}.
to
change
(
project
.
mirror_data
,
:retry_count
).
to
(
0
)
expect
(
project
.
mirror_data
.
next_execution_timestamp
).
to
eq
(
timestamp
)
end
end
end
describe
'#push_rule'
do
describe
'#push_rule'
do
let
(
:project
)
{
create
(
:project
,
push_rule:
create
(
:push_rule
))
}
let
(
:project
)
{
create
(
:project
,
push_rule:
create
(
:push_rule
))
}
...
@@ -200,6 +228,22 @@ describe Project do
...
@@ -200,6 +228,22 @@ describe Project do
end
end
end
end
describe
'#force_import_job!'
do
it
'sets next execution timestamp to now and schedules UpdateAllMirrorsWorker'
do
timestamp
=
Time
.
now
project
=
create
(
:project
,
:mirror
)
project
.
mirror_data
.
update_attributes
(
next_execution_timestamp:
timestamp
-
3
.
minutes
)
Timecop
.
freeze
(
timestamp
)
do
expect
{
project
.
force_import_job!
}.
to
change
(
project
.
mirror_data
,
:next_execution_timestamp
).
to
(
timestamp
)
end
expect
(
UpdateAllMirrorsWorker
).
to
receive
(
:perform_async
)
project
.
run_callbacks
(
:commit
)
end
end
describe
'#fetch_mirror'
do
describe
'#fetch_mirror'
do
where
(
:import_url
,
:auth_method
,
:expected
)
do
where
(
:import_url
,
:auth_method
,
:expected
)
do
'http://foo:bar@example.com'
|
'password'
|
'http://foo:bar@example.com'
'http://foo:bar@example.com'
|
'password'
|
'http://foo:bar@example.com'
...
@@ -239,6 +283,103 @@ describe Project do
...
@@ -239,6 +283,103 @@ describe Project do
end
end
end
end
describe
'#scheduled_mirror?'
do
context
'when mirror is expected to run soon'
do
it
'returns true'
do
timestamp
=
Time
.
now
project
=
create
(
:project
,
:mirror
,
:import_finished
,
:repository
)
project
.
mirror_last_update_at
=
timestamp
-
3
.
minutes
project
.
mirror_data
.
next_execution_timestamp
=
timestamp
-
2
.
minutes
expect
(
project
.
scheduled_mirror?
).
to
be
true
end
end
context
'when mirror was scheduled'
do
it
'returns true'
do
project
=
create
(
:project
,
:mirror
,
:import_scheduled
,
:repository
)
expect
(
project
.
scheduled_mirror?
).
to
be
true
end
end
context
'when mirror is hard_failed'
do
it
'returns false'
do
project
=
create
(
:project
,
:mirror
,
:import_hard_failed
)
expect
(
project
.
scheduled_mirror?
).
to
be
false
end
end
end
describe
'#updating_mirror?'
do
context
'when repository is empty'
do
it
'returns false'
do
project
=
create
(
:project
,
:mirror
,
:import_started
)
expect
(
project
.
updating_mirror?
).
to
be
false
end
end
context
'when project is not a mirror'
do
it
'returns false'
do
project
=
create
(
:project
,
:import_started
)
expect
(
project
.
updating_mirror?
).
to
be
false
end
end
context
'when mirror is in progress'
do
it
'returns true'
do
project
=
create
(
:project
,
:mirror
,
:import_started
,
:repository
)
expect
(
project
.
updating_mirror?
).
to
be
true
end
end
end
describe
'#mirror_last_update_status'
do
let
(
:project
)
{
create
(
:project
,
:mirror
)
}
context
'when mirror has not updated'
do
it
'returns nil'
do
expect
(
project
.
mirror_last_update_status
).
to
be_nil
end
end
context
'when mirror has updated'
do
before
do
project
.
mirror_last_update_at
=
Time
.
now
end
context
'when last update time equals the time of the last successful update'
do
it
'returns success'
do
timestamp
=
Time
.
now
project
.
mirror_last_update_at
=
timestamp
project
.
mirror_last_successful_update_at
=
timestamp
expect
(
project
.
mirror_last_update_status
).
to
eq
(
:success
)
end
end
context
'when retry count has not reached the limit'
do
it
'returns failed'
do
project
.
mirror_data
.
retry_count
=
Gitlab
::
Mirror
::
MAX_RETRY
expect
(
project
.
mirror_last_update_status
).
to
eq
(
:failed
)
end
end
context
'when retry count has reached the limit'
do
it
'returns hard_failed'
do
project
.
mirror_data
.
retry_count
=
Gitlab
::
Mirror
::
MAX_RETRY
+
1
expect
(
project
.
mirror_last_update_status
).
to
eq
(
:hard_failed
)
end
end
end
end
describe
'#has_remote_mirror?'
do
describe
'#has_remote_mirror?'
do
let
(
:project
)
{
create
(
:project
,
:remote_mirror
,
:import_started
)
}
let
(
:project
)
{
create
(
:project
,
:remote_mirror
,
:import_started
)
}
subject
{
project
.
has_remote_mirror?
}
subject
{
project
.
has_remote_mirror?
}
...
...
spec/factories/projects.rb
View file @
344f2d16
...
@@ -85,6 +85,14 @@ FactoryGirl.define do
...
@@ -85,6 +85,14 @@ FactoryGirl.define do
import_status
:failed
import_status
:failed
end
end
trait
:import_hard_failed
do
import_status
:hard_failed
after
(
:create
)
do
|
project
|
project
.
mirror_data
&
.
update_attributes
(
retry_count:
Gitlab
::
Mirror
::
MAX_RETRY
+
1
)
end
end
trait
:mirror
do
trait
:mirror
do
mirror
true
mirror
true
import_url
{
generate
(
:url
)
}
import_url
{
generate
(
:url
)
}
...
...
spec/models/project_mirror_data_spec.rb
View file @
344f2d16
...
@@ -7,10 +7,6 @@ describe ProjectMirrorData, type: :model do
...
@@ -7,10 +7,6 @@ describe ProjectMirrorData, type: :model do
it
{
is_expected
.
to
belong_to
(
:project
)
}
it
{
is_expected
.
to
belong_to
(
:project
)
}
end
end
describe
'modules'
do
it
{
is_expected
.
to
include_module
(
Gitlab
::
CurrentSettings
)
}
end
describe
'validations'
do
describe
'validations'
do
it
{
is_expected
.
to
validate_presence_of
(
:project
)
}
it
{
is_expected
.
to
validate_presence_of
(
:project
)
}
end
end
...
@@ -27,6 +23,17 @@ describe ProjectMirrorData, type: :model do
...
@@ -27,6 +23,17 @@ describe ProjectMirrorData, type: :model do
end
end
end
end
describe
'when update'
do
context
'when retry limit reached'
do
it
'marks mirror as hard failed'
do
project
=
create
(
:project
,
:mirror
,
:import_started
)
project
.
mirror_data
.
update_attributes
(
retry_count:
Gitlab
::
Mirror
::
MAX_RETRY
)
expect
{
project
.
import_fail
}.
to
change
(
project
,
:import_status
).
from
(
'started'
).
to
(
'hard_failed'
)
end
end
end
describe
'#reset_retry_count!'
do
describe
'#reset_retry_count!'
do
let
(
:mirror_data
)
{
create
(
:project
,
:mirror
,
:import_finished
).
mirror_data
}
let
(
:mirror_data
)
{
create
(
:project
,
:mirror
,
:import_finished
).
mirror_data
}
...
...
spec/models/project_spec.rb
View file @
344f2d16
...
@@ -1938,68 +1938,6 @@ describe Project do
...
@@ -1938,68 +1938,6 @@ describe Project do
end
end
end
end
describe
'#scheduled_mirror?'
do
context
'when mirror is expected to run soon'
do
it
'returns true'
do
timestamp
=
Time
.
now
project
=
create
(
:project
,
:mirror
,
:import_finished
,
:repository
)
project
.
mirror_last_update_at
=
timestamp
-
3
.
minutes
project
.
mirror_data
.
next_execution_timestamp
=
timestamp
-
2
.
minutes
expect
(
project
.
scheduled_mirror?
).
to
be
true
end
end
context
'when mirror was scheduled'
do
it
'returns true'
do
project
=
create
(
:project
,
:mirror
,
:import_scheduled
,
:repository
)
expect
(
project
.
scheduled_mirror?
).
to
be
true
end
end
end
describe
'#updating_mirror?'
do
context
'when repository is empty'
do
it
'returns false'
do
project
=
create
(
:project
,
:mirror
,
:import_started
)
expect
(
project
.
updating_mirror?
).
to
be
false
end
end
context
'when project is not a mirror'
do
it
'returns false'
do
project
=
create
(
:project
,
:import_started
)
expect
(
project
.
updating_mirror?
).
to
be
false
end
end
context
'when mirror is in progress'
do
it
'returns true'
do
project
=
create
(
:project
,
:mirror
,
:import_started
,
:repository
)
expect
(
project
.
updating_mirror?
).
to
be
true
end
end
end
describe
'#force_import_job!'
do
it
'sets next execution timestamp to now and schedules UpdateAllMirrorsWorker'
do
timestamp
=
Time
.
now
project
=
create
(
:project
,
:mirror
)
project
.
mirror_data
.
update_attributes
(
next_execution_timestamp:
timestamp
-
3
.
minutes
)
expect
(
UpdateAllMirrorsWorker
).
to
receive
(
:perform_async
)
Timecop
.
freeze
(
timestamp
)
do
expect
{
project
.
force_import_job!
}.
to
change
{
project
.
mirror_data
.
reload
.
next_execution_timestamp
}.
to
be_within
(
1
.
second
).
of
(
timestamp
)
end
end
end
describe
'#add_import_job'
do
describe
'#add_import_job'
do
let
(
:import_jid
)
{
'123'
}
let
(
:import_jid
)
{
'123'
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment