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
0
Merge Requests
0
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
Jérome Perrin
gitlab-ce
Commits
37d6d1e4
Commit
37d6d1e4
authored
Mar 24, 2017
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
basic components
parent
5f715f1d
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
127 additions
and
99 deletions
+127
-99
app/models/ci/scheduled_trigger.rb
app/models/ci/scheduled_trigger.rb
+4
-6
app/services/ci/create_pipeline_service.rb
app/services/ci/create_pipeline_service.rb
+6
-4
app/workers/scheduled_trigger_worker.rb
app/workers/scheduled_trigger_worker.rb
+4
-4
spec/factories/ci/scheduled_triggers.rb
spec/factories/ci/scheduled_triggers.rb
+17
-1
spec/lib/ci/cron_parser_spec.rb
spec/lib/ci/cron_parser_spec.rb
+31
-60
spec/models/ci/scheduled_trigger_spec.rb
spec/models/ci/scheduled_trigger_spec.rb
+11
-20
spec/services/ci/create_pipeline_service_spec.rb
spec/services/ci/create_pipeline_service_spec.rb
+4
-0
spec/workers/scheduled_trigger_worker_spec.rb
spec/workers/scheduled_trigger_worker_spec.rb
+50
-4
No files found.
app/models/ci/scheduled_trigger.rb
View file @
37d6d1e4
...
@@ -9,15 +9,13 @@ module Ci
...
@@ -9,15 +9,13 @@ module Ci
def
schedule_next_run!
def
schedule_next_run!
next_time
=
Ci
::
CronParser
.
new
(
cron
,
cron_time_zone
).
next_time_from_now
next_time
=
Ci
::
CronParser
.
new
(
cron
,
cron_time_zone
).
next_time_from_now
update
(
:next_run_at
=>
next_time
)
if
next_time
.
present?
if
next_time
.
present?
end
update_attributes
(
next_run_at:
next_time
)
end
def
valid_ref?
true
#TODO:
end
end
def
update_last_run!
def
update_last_run!
update
(
:last_run_at
=>
Time
.
now
)
update
_attributes
(
last_run_at:
Time
.
now
)
end
end
end
end
end
end
app/services/ci/create_pipeline_service.rb
View file @
37d6d1e4
...
@@ -2,14 +2,14 @@ module Ci
...
@@ -2,14 +2,14 @@ module Ci
class
CreatePipelineService
<
BaseService
class
CreatePipelineService
<
BaseService
attr_reader
:pipeline
attr_reader
:pipeline
def
execute
(
ignore_skip_ci:
false
,
save_on_errors:
true
,
trigger_request:
nil
)
def
execute
(
ignore_skip_ci:
false
,
save_on_errors:
true
,
trigger_request:
nil
,
scheduled_trigger:
false
)
@pipeline
=
Ci
::
Pipeline
.
new
(
@pipeline
=
Ci
::
Pipeline
.
new
(
project:
project
,
project:
project
,
ref:
ref
,
ref:
ref
,
sha:
sha
,
sha:
sha
,
before_sha:
before_sha
,
before_sha:
before_sha
,
tag:
tag?
,
tag:
tag?
,
trigger_requests:
Array
(
trigger_request
),
trigger_requests:
(
scheduled_trigger
)
?
[]
:
Array
(
trigger_request
),
user:
current_user
user:
current_user
)
)
...
@@ -17,8 +17,10 @@ module Ci
...
@@ -17,8 +17,10 @@ module Ci
return
error
(
'Pipeline is disabled'
)
return
error
(
'Pipeline is disabled'
)
end
end
unless
trigger_request
||
can?
(
current_user
,
:create_pipeline
,
project
)
unless
scheduled_trigger
return
error
(
'Insufficient permissions to create a new pipeline'
)
unless
trigger_request
||
can?
(
current_user
,
:create_pipeline
,
project
)
return
error
(
'Insufficient permissions to create a new pipeline'
)
end
end
end
unless
branch?
||
tag?
unless
branch?
||
tag?
...
...
app/workers/scheduled_trigger_worker.rb
View file @
37d6d1e4
...
@@ -3,15 +3,15 @@ class ScheduledTriggerWorker
...
@@ -3,15 +3,15 @@ class ScheduledTriggerWorker
include
CronjobQueue
include
CronjobQueue
def
perform
def
perform
# TODO: Update next_run_at
Ci
::
ScheduledTrigger
.
where
(
"next_run_at < ?"
,
Time
.
now
).
find_each
do
|
trigger
|
Ci
::
ScheduledTriggers
.
where
(
"next_run_at < ?"
,
Time
.
now
).
find_each
do
|
trigger
|
begin
begin
Ci
::
CreateTriggerRequestService
.
new
.
execute
(
trigger
.
project
,
trigger
,
trigger
.
ref
)
Ci
::
CreatePipelineService
.
new
(
trigger
.
project
,
trigger
.
owner
,
ref:
trigger
.
ref
).
execute
(
ignore_skip_ci:
true
,
scheduled_trigger:
true
)
rescue
=>
e
rescue
=>
e
Rails
.
logger
.
error
"
#{
trigger
.
id
}
: Failed to trigger job:
#{
e
.
message
}
"
Rails
.
logger
.
error
"
#{
trigger
.
id
}
: Failed to trigger job:
#{
e
.
message
}
"
ensure
ensure
trigger
.
schedule_next_run!
trigger
.
schedule_next_run!
trigger
.
update_last_run!
end
end
end
end
end
end
...
...
spec/factories/ci/scheduled_triggers.rb
View file @
37d6d1e4
FactoryGirl
.
define
do
FactoryGirl
.
define
do
factory
:ci_scheduled_trigger
,
class:
Ci
::
ScheduledTrigger
do
factory
:ci_scheduled_trigger
,
class:
Ci
::
ScheduledTrigger
do
project
factory: :
empty_
project
project
factory: :project
owner
factory: :user
owner
factory: :user
ref
'master'
ref
'master'
trait
:force_triggable
do
next_run_at
Time
.
now
-
1
.
month
end
trait
:cron_nightly_build
do
trait
:cron_nightly_build
do
cron
'0 1 * * *'
cron
'0 1 * * *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
next_run_at
do
# TODO: Use CronParser
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
time
=
time
+
1
.
day
if
time
.
hour
>
1
time
=
time
.
change
(
sec:
0
,
min:
0
,
hour:
1
)
time
end
end
end
trait
:cron_weekly_build
do
trait
:cron_weekly_build
do
cron
'0 1 * * 5'
cron
'0 1 * * 5'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
trait
:cron_monthly_build
do
trait
:cron_monthly_build
do
cron
'0 1 22 * *'
cron
'0 1 22 * *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
trait
:cron_every_5_minutes
do
trait
:cron_every_5_minutes
do
cron
'*/5 * * * *'
cron
'*/5 * * * *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
trait
:cron_every_5_hours
do
trait
:cron_every_5_hours
do
cron
'* */5 * * *'
cron
'* */5 * * *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
trait
:cron_every_5_days
do
trait
:cron_every_5_days
do
cron
'* * */5 * *'
cron
'* * */5 * *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
trait
:cron_every_5_months
do
trait
:cron_every_5_months
do
cron
'* * * */5 *'
cron
'* * * */5 *'
cron_time_zone
'Europe/Istanbul'
cron_time_zone
'Europe/Istanbul'
# TODO: next_run_at
end
end
end
end
end
end
spec/lib/ci/cron_parser_spec.rb
View file @
37d6d1e4
...
@@ -6,91 +6,62 @@ module Ci
...
@@ -6,91 +6,62 @@ module Ci
subject
{
described_class
.
new
(
cron
,
cron_time_zone
).
next_time_from_now
}
subject
{
described_class
.
new
(
cron
,
cron_time_zone
).
next_time_from_now
}
context
'when cron and cron_time_zone are valid'
do
context
'when cron and cron_time_zone are valid'
do
context
'
at 00:00, 00:10, 00:20, 00:30, 00:40, 00:50
'
do
context
'
when specific time
'
do
let
(
:cron
)
{
'
*/10 * * *
*'
}
let
(
:cron
)
{
'
3 4 5 6
*'
}
let
(
:cron_time_zone
)
{
'
US/Pacific
'
}
let
(
:cron_time_zone
)
{
'
Europe/London
'
}
it
'returns next time from now'
do
it
'returns exact time in the future'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
expect
(
subject
).
to
be
>
Time
.
now
.
in_time_zone
(
cron_time_zone
)
time
=
time
+
10
.
minutes
expect
(
subject
.
min
).
to
eq
(
3
)
time
=
time
.
change
(
sec:
0
,
min:
time
.
min
-
time
.
min
%
10
)
expect
(
subject
.
hour
).
to
eq
(
4
)
is_expected
.
to
eq
(
time
)
expect
(
subject
.
day
).
to
eq
(
5
)
expect
(
subject
.
month
).
to
eq
(
6
)
end
end
end
end
context
'
at 10:00, 20:00
'
do
context
'
when specific day of week
'
do
let
(
:cron
)
{
'
0 */10 * * *
'
}
let
(
:cron
)
{
'
* * * * 0
'
}
let
(
:cron_time_zone
)
{
'
US/Pacific
'
}
let
(
:cron_time_zone
)
{
'
Europe/London
'
}
it
'returns next time from now'
do
it
'returns exact day of week in the future'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
expect
(
subject
).
to
be
>
Time
.
now
.
in_time_zone
(
cron_time_zone
)
time
=
time
+
10
.
hours
expect
(
subject
.
wday
).
to
eq
(
0
)
time
=
time
.
change
(
sec:
0
,
min:
0
,
hour:
time
.
hour
-
time
.
hour
%
10
)
is_expected
.
to
eq
(
time
)
end
end
end
end
context
'when
cron is every 10 days
'
do
context
'when
slash used
'
do
let
(
:cron
)
{
'
0 0 */10 *
*'
}
let
(
:cron
)
{
'
*/10 */6 */10 */10
*'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
it
'returns next time from now'
do
it
'returns exact minute'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
expect
(
subject
).
to
be
>
Time
.
now
.
in_time_zone
(
cron_time_zone
)
time
=
time
+
10
.
days
expect
(
subject
.
min
).
to
be_in
([
0
,
10
,
20
,
30
,
40
,
50
])
time
=
time
.
change
(
sec:
0
,
min:
0
,
hour:
0
,
day:
time
.
day
-
time
.
day
%
10
)
expect
(
subject
.
hour
).
to
be_in
([
0
,
6
,
12
,
18
])
is_expected
.
to
eq
(
time
)
expect
(
subject
.
day
).
to
be_in
([
1
,
11
,
21
,
31
])
expect
(
subject
.
month
).
to
be_in
([
1
,
11
])
end
end
end
end
context
'when
cron is every week 2:00 AM
'
do
context
'when
range used
'
do
let
(
:cron
)
{
'0
2 *
* *'
}
let
(
:cron
)
{
'0
,20,40 * 1-5
* *'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
it
'returns next time from now'
do
it
'returns next time from now'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
expect
(
subject
).
to
be
>
Time
.
now
.
in_time_zone
(
cron_time_zone
)
is_expected
.
to
eq
(
time
.
change
(
sec:
0
,
min:
0
,
hour:
2
,
day:
time
.
day
+
1
))
expect
(
subject
.
min
).
to
be_in
([
0
,
20
,
40
])
expect
(
subject
.
day
).
to
be_in
((
1
..
5
).
to_a
)
end
end
end
end
context
'when cron_time_zone is US/Pacific'
do
context
'when cron_time_zone is US/Pacific'
do
let
(
:cron
)
{
'
0 1
* * *'
}
let
(
:cron
)
{
'
* *
* * *'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
let
(
:cron_time_zone
)
{
'US/Pacific'
}
it
'returns next time from now'
do
it
'returns next time from now'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
expect
(
subject
).
to
be
>
Time
.
now
.
in_time_zone
(
cron_time_zone
)
is_expected
.
to
eq
(
time
.
change
(
sec:
0
,
min:
0
,
hour:
1
,
day:
time
.
day
+
1
))
expect
(
subject
.
utc_offset
/
60
/
60
).
to
eq
(
-
7
)
end
end
context
'when cron_time_zone is Europe/London'
do
let
(
:cron
)
{
'0 1 * * *'
}
let
(
:cron_time_zone
)
{
'Europe/London'
}
it
'returns next time from now'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
is_expected
.
to
eq
(
time
.
change
(
sec:
0
,
min:
0
,
hour:
1
,
day:
time
.
day
+
1
))
end
end
end
end
context
'when cron_time_zone is Asia/Tokyo'
do
let
(
:cron
)
{
'0 1 * * *'
}
let
(
:cron_time_zone
)
{
'Asia/Tokyo'
}
it
'returns next time from now'
do
time
=
Time
.
now
.
in_time_zone
(
cron_time_zone
)
is_expected
.
to
eq
(
time
.
change
(
sec:
0
,
min:
0
,
hour:
1
,
day:
time
.
day
+
1
))
end
end
end
context
'when cron is given and cron_time_zone is not given'
do
let
(
:cron
)
{
'0 1 * * *'
}
it
'returns next time from now in utc'
do
obj
=
described_class
.
new
(
cron
).
next_time_from_now
time
=
Time
.
now
.
in_time_zone
(
'UTC'
)
expect
(
obj
).
to
eq
(
time
.
change
(
sec:
0
,
min:
0
,
hour:
1
,
day:
time
.
day
+
1
))
end
end
end
context
'when cron and cron_time_zone are invalid'
do
context
'when cron and cron_time_zone are invalid'
do
...
...
spec/models/ci/scheduled_trigger_spec.rb
View file @
37d6d1e4
require
'spec_helper'
require
'spec_helper'
require
'rufus-scheduler'
# Included in sidekiq-cron
describe
Ci
::
ScheduledTrigger
,
models:
true
do
describe
Ci
::
ScheduledTrigger
,
models:
true
do
...
@@ -9,30 +8,22 @@ describe Ci::ScheduledTrigger, models: true do
...
@@ -9,30 +8,22 @@ describe Ci::ScheduledTrigger, models: true do
end
end
describe
'#schedule_next_run!'
do
describe
'#schedule_next_run!'
do
context
'when cron and cron_time_zone are vaild'
do
subject
{
scheduled_trigger
.
schedule_next_run!
}
context
'when nightly build'
do
it
'schedules next run'
do
scheduled_trigger
=
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
)
scheduled_trigger
.
schedule_next_run!
puts
"scheduled_trigger:
#{
scheduled_trigger
.
inspect
}
"
expect
(
scheduled_trigger
.
cron
).
to
be_nil
let
(
:scheduled_trigger
)
{
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
,
next_run_at:
nil
)
}
end
end
context
'when weekly build'
do
it
'updates next_run_at'
do
is_expected
.
not_to
be_nil
end
context
'when monthly build'
do
end
end
end
end
describe
'#update_last_run!'
do
subject
{
scheduled_trigger
.
update_last_run!
}
context
'when cron and cron_time_zone are invaild'
do
let
(
:scheduled_trigger
)
{
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
,
last_run_at:
nil
)
}
it
'schedules nothing'
do
end
it
'updates last_run_at'
do
is_expected
.
not_to
be_nil
end
end
end
end
end
end
spec/services/ci/create_pipeline_service_spec.rb
View file @
37d6d1e4
...
@@ -214,5 +214,9 @@ describe Ci::CreatePipelineService, services: true do
...
@@ -214,5 +214,9 @@ describe Ci::CreatePipelineService, services: true do
expect
(
Environment
.
find_by
(
name:
"review/master"
)).
not_to
be_nil
expect
(
Environment
.
find_by
(
name:
"review/master"
)).
not_to
be_nil
end
end
end
end
context
'when scheduled_trigger'
do
# TODO: spec if approved
end
end
end
end
end
spec/workers/scheduled_trigger_worker_spec.rb
View file @
37d6d1e4
require
'spec_helper'
require
'spec_helper'
describe
ScheduledTriggerWorker
do
describe
ScheduledTriggerWorker
do
subject
{
described_class
.
new
.
perform
}
let
(
:worker
)
{
described_class
.
new
}
context
'#perform'
do
# TODO:
before
do
it
'does'
do
stub_ci_pipeline_to_return_yaml_file
is_expected
.
to
be_nil
end
context
'when there is a scheduled trigger within next_run_at'
do
before
do
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
,
:force_triggable
)
worker
.
perform
end
it
'creates a new pipeline'
do
expect
(
Ci
::
Pipeline
.
last
.
status
).
to
eq
(
'pending'
)
end
it
'schedules next_run_at'
do
scheduled_trigger2
=
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
)
expect
(
Ci
::
ScheduledTrigger
.
last
.
next_run_at
).
to
eq
(
scheduled_trigger2
.
next_run_at
)
end
end
context
'when there are no scheduled triggers within next_run_at'
do
let!
(
:scheduled_trigger
)
{
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
)
}
before
do
worker
.
perform
end
it
'do not create a new pipeline'
do
expect
(
Ci
::
Pipeline
.
all
).
to
be_empty
end
it
'do not reschedule next_run_at'
do
expect
(
Ci
::
ScheduledTrigger
.
last
.
next_run_at
).
to
eq
(
scheduled_trigger
.
next_run_at
)
end
end
context
'when next_run_at is nil'
do
let!
(
:scheduled_trigger
)
{
create
(
:ci_scheduled_trigger
,
:cron_nightly_build
,
next_run_at:
nil
)
}
before
do
worker
.
perform
end
it
'do not create a new pipeline'
do
expect
(
Ci
::
Pipeline
.
all
).
to
be_empty
end
it
'do not reschedule next_run_at'
do
expect
(
Ci
::
ScheduledTrigger
.
last
.
next_run_at
).
to
eq
(
scheduled_trigger
.
next_run_at
)
end
end
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