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
624a2abb
Commit
624a2abb
authored
Apr 19, 2018
by
Toon Claes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pick Various improvements to repository checks into EE
Pick the changes from gitlab-org/gitlab-ce!18484 into EE.
parent
7032fc65
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
135 additions
and
73 deletions
+135
-73
app/views/admin/application_settings/_repository_check.html.haml
...ws/admin/application_settings/_repository_check.html.haml
+1
-1
app/workers/admin_email_worker.rb
app/workers/admin_email_worker.rb
+6
-0
app/workers/repository_check/batch_worker.rb
app/workers/repository_check/batch_worker.rb
+2
-12
app/workers/repository_check/single_repository_worker.rb
app/workers/repository_check/single_repository_worker.rb
+26
-15
doc/administration/repository_checks.md
doc/administration/repository_checks.md
+13
-11
spec/workers/admin_email_worker_spec.rb
spec/workers/admin_email_worker_spec.rb
+41
-0
spec/workers/repository_check/batch_worker_spec.rb
spec/workers/repository_check/batch_worker_spec.rb
+2
-2
spec/workers/repository_check/single_repository_worker_spec.rb
...workers/repository_check/single_repository_worker_spec.rb
+44
-32
No files found.
app/views/admin/application_settings/_repository_check.html.haml
View file @
624a2abb
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
Enable Repository Checks
Enable Repository Checks
.help-block
.help-block
GitLab will periodically run
GitLab will periodically run
%a
{
href:
'https://
www.kernel.org/pub/software/scm/git/docs/git-fsck.html
'
,
target:
'blank'
}
'git fsck'
%a
{
href:
'https://
git-scm.com/docs/git-fsck
'
,
target:
'blank'
}
'git fsck'
in all project and wiki repositories to look for silent disk corruption issues.
in all project and wiki repositories to look for silent disk corruption issues.
.form-group
.form-group
.col-sm-offset-2.col-sm-10
.col-sm-offset-2.col-sm-10
...
...
app/workers/admin_email_worker.rb
View file @
624a2abb
...
@@ -3,6 +3,12 @@ class AdminEmailWorker
...
@@ -3,6 +3,12 @@ class AdminEmailWorker
include
CronjobQueue
include
CronjobQueue
def
perform
def
perform
send_repository_check_mail
if
Gitlab
::
CurrentSettings
.
repository_checks_enabled
end
private
def
send_repository_check_mail
repository_check_failed_count
=
Project
.
where
(
last_repository_check_failed:
true
).
count
repository_check_failed_count
=
Project
.
where
(
last_repository_check_failed:
true
).
count
return
if
repository_check_failed_count
.
zero?
return
if
repository_check_failed_count
.
zero?
...
...
app/workers/repository_check/batch_worker.rb
View file @
624a2abb
...
@@ -6,6 +6,8 @@ module RepositoryCheck
...
@@ -6,6 +6,8 @@ module RepositoryCheck
RUN_TIME
=
3600
RUN_TIME
=
3600
def
perform
def
perform
break
unless
Gitlab
::
CurrentSettings
.
repository_checks_enabled
start
=
Time
.
now
start
=
Time
.
now
# This loop will break after a little more than one hour ('a little
# This loop will break after a little more than one hour ('a little
...
@@ -15,7 +17,6 @@ module RepositoryCheck
...
@@ -15,7 +17,6 @@ module RepositoryCheck
# check, only one (or two) will be checked at a time.
# check, only one (or two) will be checked at a time.
project_ids
.
each
do
|
project_id
|
project_ids
.
each
do
|
project_id
|
break
if
Time
.
now
-
start
>=
RUN_TIME
break
if
Time
.
now
-
start
>=
RUN_TIME
break
unless
current_settings
.
repository_checks_enabled
next
unless
try_obtain_lease
(
project_id
)
next
unless
try_obtain_lease
(
project_id
)
...
@@ -47,16 +48,5 @@ module RepositoryCheck
...
@@ -47,16 +48,5 @@ module RepositoryCheck
timeout:
24
.
hours
timeout:
24
.
hours
).
try_obtain
).
try_obtain
end
end
def
current_settings
# No caching of the settings! If we cache them and an admin disables
# this feature, an active RepositoryCheckWorker would keep going for up
# to 1 hour after the feature was disabled.
if
Rails
.
env
.
test?
Gitlab
::
CurrentSettings
.
fake_application_settings
else
ApplicationSetting
.
current
end
end
end
end
end
end
app/workers/repository_check/single_repository_worker.rb
View file @
624a2abb
...
@@ -5,27 +5,38 @@ module RepositoryCheck
...
@@ -5,27 +5,38 @@ module RepositoryCheck
def
perform
(
project_id
)
def
perform
(
project_id
)
project
=
Project
.
find
(
project_id
)
project
=
Project
.
find
(
project_id
)
save_result
(
project
,
!
check
)
end
private
def
save_result
(
project
,
failure
)
project
.
update_columns
(
project
.
update_columns
(
last_repository_check_failed:
!
check
(
project
)
,
last_repository_check_failed:
failure
,
last_repository_check_at:
Time
.
now
last_repository_check_at:
Time
.
now
)
)
end
end
private
def
check
(
project
)
def
check
(
project
)
if
has_pushes?
(
project
)
&&
!
git_fsck
(
project
.
repository
)
check_repo
(
project
)
&&
check_wiki_repo
(
project
)
false
end
elsif
project
.
wiki_enabled?
def
check_repo
(
project
)
return
true
if
project
.
empty_repo?
git_fsck
(
project
.
repository
)
end
def
check_wiki_repo
(
project
)
return
true
unless
project
.
wiki_enabled?
# Historically some projects never had their wiki repos initialized;
# Historically some projects never had their wiki repos initialized;
# this happens on project creation now. Let's initialize an empty repo
# this happens on project creation now. Let's initialize an empty repo
# if it is not already there.
# if it is not already there.
project
.
create_wiki
project
.
create_wiki
git_fsck
(
project
.
wiki
.
repository
)
git_fsck
(
project
.
wiki
.
repository
)
else
true
end
end
end
def
git_fsck
(
repository
)
def
git_fsck
(
repository
)
...
...
doc/administration/repository_checks.md
View file @
624a2abb
...
@@ -28,16 +28,18 @@ panel.
...
@@ -28,16 +28,18 @@ panel.
## What to do if a check failed
## What to do if a check failed
If the repository check fails for some repository you should look up the error
If the repository check fails for some repository you should look up the error
in repocheck.log (in the admin panel or on disk; see
in
`repocheck.log`
:
`/var/log/gitlab/gitlab-rails`
for Omnibus installations or
`/home/git/gitlab/log`
for installations from source). Once you have
-
in the
[
admin panel
](
logs.md#repocheck.log
)
resolved the issue use the admin panel to trigger a new repository check on
-
or on disk, see:
the project. This will clear the 'check failed' state.
-
`/var/log/gitlab/gitlab-rails`
for Omnibus installations
-
`/home/git/gitlab/log`
for installations from source
If for some reason the periodic repository check caused a lot of false
If for some reason the periodic repository check caused a lot of false
alarms you can choose to clear ALL repository check states from the
alarms you can choose to clear
*all*
repository check states by
'Settings' page of the admin panel.
clicking "Clear all repository checks" on the 'Settings' page of the
admin panel.
---
---
[
ce-3232
]:
https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3232
"Auto git fsck"
[
ce-3232
]:
https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3232
"Auto git fsck"
[
git-fsck
]:
https://
www.kernel.org/pub/software/scm/git/docs/git-fsck.html
"git fsck documentation"
[
git-fsck
]:
https://
git-scm.com/docs/git-fsck
"git fsck documentation"
spec/workers/admin_email_worker_spec.rb
0 → 100644
View file @
624a2abb
require
'spec_helper'
describe
AdminEmailWorker
do
subject
(
:worker
)
{
described_class
.
new
}
describe
'.perform'
do
it
'does not attempt to send repository check mail when they are disabled'
do
stub_application_setting
(
repository_checks_enabled:
false
)
expect
(
worker
).
not_to
receive
(
:send_repository_check_mail
)
worker
.
perform
end
context
'repository_checks enabled'
do
before
do
stub_application_setting
(
repository_checks_enabled:
true
)
end
it
'checks if repository check mail should be sent'
do
expect
(
worker
).
to
receive
(
:send_repository_check_mail
)
worker
.
perform
end
it
'does not send mail when there are no failed repos'
do
expect
(
RepositoryCheckMailer
).
not_to
receive
(
:notify
)
worker
.
perform
end
it
'send mail when there is a failed repo'
do
create
(
:project
,
last_repository_check_failed:
true
,
last_repository_check_at:
Date
.
yesterday
)
expect
(
RepositoryCheckMailer
).
to
receive
(
:notify
).
and_return
(
spy
)
worker
.
perform
end
end
end
end
spec/workers/repository_check/batch_worker_spec.rb
View file @
624a2abb
...
@@ -31,8 +31,8 @@ describe RepositoryCheck::BatchWorker do
...
@@ -31,8 +31,8 @@ describe RepositoryCheck::BatchWorker do
it
'does nothing when repository checks are disabled'
do
it
'does nothing when repository checks are disabled'
do
create
(
:project
,
created_at:
1
.
week
.
ago
)
create
(
:project
,
created_at:
1
.
week
.
ago
)
current_settings
=
double
(
'settings'
,
repository_checks_enabled:
false
)
expect
(
subject
).
to
receive
(
:current_settings
)
{
current_settings
}
stub_application_setting
(
repository_checks_enabled:
false
)
expect
(
subject
.
perform
).
to
eq
(
nil
)
expect
(
subject
.
perform
).
to
eq
(
nil
)
end
end
...
...
spec/workers/repository_check/single_repository_worker_spec.rb
View file @
624a2abb
...
@@ -2,44 +2,55 @@ require 'spec_helper'
...
@@ -2,44 +2,55 @@ require 'spec_helper'
require
'fileutils'
require
'fileutils'
describe
RepositoryCheck
::
SingleRepositoryWorker
do
describe
RepositoryCheck
::
SingleRepositoryWorker
do
subject
{
described_class
.
new
}
subject
(
:worker
)
{
described_class
.
new
}
it
'passes when the project has no push events'
do
it
'skips when the project repo is empty'
do
project
=
create
(
:project_empty_repo
,
:wiki_disabled
)
project
=
create
(
:project
,
:wiki_disabled
)
project
.
events
.
destroy_all
break_repo
(
project
)
subject
.
perform
(
project
.
id
)
expect
(
worker
).
not_to
receive
(
:git_fsck
)
worker
.
perform
(
project
.
id
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
false
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
false
)
end
end
it
'fails when the project has push events and a broken repository'
do
it
'succeeds when the project repo is valid'
do
project
=
create
(
:project_empty_repo
)
project
=
create
(
:project
,
:repository
,
:wiki_disabled
)
create_push_event
(
project
)
break_repo
(
project
)
subject
.
perform
(
project
.
id
)
expect
(
worker
).
to
receive
(
:git_fsck
).
and_call_original
expect
do
worker
.
perform
(
project
.
id
)
end
.
to
change
{
project
.
reload
.
last_repository_check_at
}
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
false
)
end
it
'fails when the project is not empty and a broken repository'
do
project
=
create
(
:project
,
:repository
)
break_project
(
project
)
worker
.
perform
(
project
.
id
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
true
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
true
)
end
end
it
'fails if the wiki repository is broken'
do
it
'fails if the wiki repository is broken'
do
project
=
create
(
:project
_empty_repo
,
:wiki_enabled
)
project
=
create
(
:project
,
:wiki_enabled
)
project
.
create_wiki
project
.
create_wiki
# Test sanity: everything should be fine before the wiki repo is broken
# Test sanity: everything should be fine before the wiki repo is broken
subject
.
perform
(
project
.
id
)
worker
.
perform
(
project
.
id
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
false
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
false
)
break_wiki
(
project
)
break_wiki
(
project
)
subject
.
perform
(
project
.
id
)
worker
.
perform
(
project
.
id
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
true
)
expect
(
project
.
reload
.
last_repository_check_failed
).
to
eq
(
true
)
end
end
it
'skips wikis when disabled'
do
it
'skips wikis when disabled'
do
project
=
create
(
:project
_empty_repo
,
:wiki_disabled
)
project
=
create
(
:project
,
:wiki_disabled
)
# Make sure the test would fail if the wiki repo was checked
# Make sure the test would fail if the wiki repo was checked
break_wiki
(
project
)
break_wiki
(
project
)
...
@@ -49,8 +60,8 @@ describe RepositoryCheck::SingleRepositoryWorker do
...
@@ -49,8 +60,8 @@ describe RepositoryCheck::SingleRepositoryWorker do
end
end
it
'creates missing wikis'
do
it
'creates missing wikis'
do
project
=
create
(
:project
_empty_repo
,
:wiki_enabled
)
project
=
create
(
:project
,
:wiki_enabled
)
FileUtils
.
rm_rf
(
wiki_path
(
project
)
)
Gitlab
::
Shell
.
new
.
rm_directory
(
project
.
repository_storage_path
,
project
.
wiki
.
path
)
subject
.
perform
(
project
.
id
)
subject
.
perform
(
project
.
id
)
...
@@ -58,34 +69,35 @@ describe RepositoryCheck::SingleRepositoryWorker do
...
@@ -58,34 +69,35 @@ describe RepositoryCheck::SingleRepositoryWorker do
end
end
it
'does not create a wiki if the main repo does not exist at all'
do
it
'does not create a wiki if the main repo does not exist at all'
do
project
=
create
(
:project_empty_repo
)
project
=
create
(
:project
,
:repository
)
create_push_event
(
project
)
Gitlab
::
Shell
.
new
.
rm_directory
(
project
.
repository_storage_path
,
project
.
path
)
FileUtils
.
rm_rf
(
project
.
repository
.
path_to_repo
)
Gitlab
::
Shell
.
new
.
rm_directory
(
project
.
repository_storage_path
,
project
.
wiki
.
path
)
FileUtils
.
rm_rf
(
wiki_path
(
project
))
subject
.
perform
(
project
.
id
)
subject
.
perform
(
project
.
id
)
expect
(
File
.
exist?
(
wiki_path
(
project
)
)).
to
eq
(
false
)
expect
(
Gitlab
::
Shell
.
new
.
exists?
(
project
.
repository_storage_path
,
project
.
wiki
.
path
)).
to
eq
(
false
)
end
end
def
break_wiki
(
project
)
def
break_wiki
(
project
)
objects_dir
=
wiki_path
(
project
)
+
'/objects'
break_repo
(
wiki_path
(
project
))
# Replace the /objects directory with a file so that the repo is
# invalid, _and_ 'git init' cannot fix it.
FileUtils
.
rm_rf
(
objects_dir
)
FileUtils
.
touch
(
objects_dir
)
if
File
.
directory?
(
wiki_path
(
project
))
end
end
def
wiki_path
(
project
)
def
wiki_path
(
project
)
project
.
wiki
.
repository
.
path_to_repo
project
.
wiki
.
repository
.
path_to_repo
end
end
def
create_push_even
t
(
project
)
def
break_projec
t
(
project
)
project
.
events
.
create
(
action:
Event
::
PUSHED
,
author_id:
create
(
:user
).
id
)
break_repo
(
project
.
repository
.
path_to_repo
)
end
end
def
break_repo
(
project
)
def
break_repo
(
repo
)
FileUtils
.
rm_rf
(
File
.
join
(
project
.
repository
.
path_to_repo
,
'objects'
))
# Create or replace blob ffffffffffffffffffffffffffffffffffffffff with an empty file
# This will make the repo invalid, _and_ 'git init' cannot fix it.
path
=
File
.
join
(
repo
,
'objects'
,
'ff'
)
file
=
File
.
join
(
path
,
'ffffffffffffffffffffffffffffffffffffff'
)
FileUtils
.
mkdir_p
(
path
)
FileUtils
.
rm_f
(
file
)
FileUtils
.
touch
(
file
)
end
end
end
end
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