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
fbd3b3d8
Commit
fbd3b3d8
authored
May 12, 2017
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add API support for pipeline schedule
parent
a16cbab3
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
486 additions
and
0 deletions
+486
-0
app/models/ci/pipeline_schedule.rb
app/models/ci/pipeline_schedule.rb
+4
-0
lib/api/api.rb
lib/api/api.rb
+1
-0
lib/api/entities.rb
lib/api/entities.rb
+8
-0
lib/api/pipeline_schedules.rb
lib/api/pipeline_schedules.rb
+127
-0
spec/fixtures/api/schemas/pipeline_schedule.json
spec/fixtures/api/schemas/pipeline_schedule.json
+64
-0
spec/fixtures/api/schemas/pipeline_schedules.json
spec/fixtures/api/schemas/pipeline_schedules.json
+4
-0
spec/requests/api/pipeline_schedules_spec.rb
spec/requests/api/pipeline_schedules_spec.rb
+278
-0
No files found.
app/models/ci/pipeline_schedule.rb
View file @
fbd3b3d8
...
...
@@ -40,6 +40,10 @@ module Ci
self
.
next_run_at
=
Gitlab
::
Ci
::
CronParser
.
new
(
cron
,
cron_timezone
).
next_time_from
(
Time
.
now
)
end
def
last_pipeline
self
.
pipelines
&
.
last
end
def
schedule_next_run!
save!
# with set_next_run_at
rescue
ActiveRecord
::
RecordInvalid
...
...
lib/api/api.rb
View file @
fbd3b3d8
...
...
@@ -110,6 +110,7 @@ module API
mount
::
API
::
Notes
mount
::
API
::
NotificationSettings
mount
::
API
::
Pipelines
mount
::
API
::
PipelineSchedules
mount
::
API
::
ProjectHooks
mount
::
API
::
Projects
mount
::
API
::
ProjectSnippets
...
...
lib/api/entities.rb
View file @
fbd3b3d8
...
...
@@ -686,6 +686,14 @@ module API
expose
:coverage
end
class
PipelineSchedule
<
Grape
::
Entity
expose
:id
expose
:description
,
:ref
,
:cron
,
:cron_timezone
,
:next_run_at
,
:active
expose
:created_at
,
:updated_at
,
:deleted_at
expose
:last_pipeline
,
using:
Entities
::
Pipeline
,
if:
->
(
pipeline_schedule
,
opts
)
{
pipeline_schedule
.
last_pipeline
.
present?
}
expose
:owner
,
using:
Entities
::
UserBasic
end
class
EnvironmentBasic
<
Grape
::
Entity
expose
:id
,
:name
,
:slug
,
:external_url
end
...
...
lib/api/pipeline_schedules.rb
0 → 100644
View file @
fbd3b3d8
module
API
class
PipelineSchedules
<
Grape
::
API
include
PaginationParams
params
do
requires
:id
,
type:
String
,
desc:
'The ID of a project'
end
resource
:projects
,
requirements:
{
id:
%r{[^/]+}
}
do
desc
'Get pipeline_schedules list'
do
success
Entities
::
PipelineSchedule
end
params
do
use
:pagination
end
get
':id/pipeline_schedules'
do
authenticate!
authorize!
:read_pipeline_schedule
,
user_project
pipeline_schedules
=
user_project
.
pipeline_schedules
present
paginate
(
pipeline_schedules
),
with:
Entities
::
PipelineSchedule
end
desc
'Get specific pipeline_schedule of a project'
do
success
Entities
::
PipelineSchedule
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline_schedule ID'
end
get
':id/pipeline_schedules/:pipeline_schedule_id'
do
authenticate!
authorize!
:read_pipeline_schedule
,
user_project
pipeline_schedule
=
user_project
.
pipeline_schedules
.
find
(
params
.
delete
(
:pipeline_schedule_id
))
return
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
present
pipeline_schedule
,
with:
Entities
::
PipelineSchedule
end
desc
'Create a pipeline_schedule'
do
success
Entities
::
PipelineSchedule
end
params
do
requires
:description
,
type:
String
,
desc:
'The pipeline_schedule description'
requires
:ref
,
type:
String
,
desc:
'The pipeline_schedule ref'
requires
:cron
,
type:
String
,
desc:
'The pipeline_schedule cron'
requires
:cron_timezone
,
type:
String
,
desc:
'The pipeline_schedule cron_timezone'
requires
:active
,
type:
Boolean
,
desc:
'The pipeline_schedule active'
end
post
':id/pipeline_schedules'
do
authenticate!
authorize!
:create_pipeline_schedule
,
user_project
pipeline_schedule
=
user_project
.
pipeline_schedules
.
create
(
declared_params
(
include_missing:
false
).
merge
(
owner:
current_user
))
if
pipeline_schedule
.
valid?
present
pipeline_schedule
,
with:
Entities
::
PipelineSchedule
else
render_validation_error!
(
pipeline_schedule
)
end
end
desc
'Update a pipeline_schedule'
do
success
Entities
::
PipelineSchedule
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline_schedule ID'
optional
:description
,
type:
String
,
desc:
'The pipeline_schedule description'
optional
:ref
,
type:
String
,
desc:
'The pipeline_schedule ref'
optional
:cron
,
type:
String
,
desc:
'The pipeline_schedule cron'
optional
:cron_timezone
,
type:
String
,
desc:
'The pipeline_schedule cron_timezone'
optional
:active
,
type:
Boolean
,
desc:
'The pipeline_schedule active'
end
put
':id/pipeline_schedules/:pipeline_schedule_id'
do
authenticate!
authorize!
:create_pipeline_schedule
,
user_project
pipeline_schedule
=
user_project
.
pipeline_schedules
.
find
(
params
.
delete
(
:pipeline_schedule_id
))
return
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
if
pipeline_schedule
.
update
(
declared_params
(
include_missing:
false
))
present
pipeline_schedule
,
with:
Entities
::
PipelineSchedule
else
render_validation_error!
(
pipeline_schedule
)
end
end
desc
'Take ownership of pipeline_schedule'
do
success
Entities
::
PipelineSchedule
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline_schedule ID'
end
post
':id/pipeline_schedules/:pipeline_schedule_id/take_ownership'
do
authenticate!
authorize!
:create_pipeline_schedule
,
user_project
pipeline_schedule
=
user_project
.
pipeline_schedules
.
find
(
params
.
delete
(
:pipeline_schedule_id
))
return
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
if
pipeline_schedule
.
update
(
owner:
current_user
)
status
:ok
present
pipeline_schedule
,
with:
Entities
::
PipelineSchedule
else
render_validation_error!
(
pipeline_schedule
)
end
end
desc
'Delete a pipeline_schedule'
do
success
Entities
::
PipelineSchedule
end
params
do
requires
:pipeline_schedule_id
,
type:
Integer
,
desc:
'The pipeline_schedule ID'
end
delete
':id/pipeline_schedules/:pipeline_schedule_id'
do
authenticate!
authorize!
:admin_pipeline_schedule
,
user_project
pipeline_schedule
=
user_project
.
pipeline_schedules
.
find
(
params
.
delete
(
:pipeline_schedule_id
))
return
not_found!
(
'PipelineSchedule'
)
unless
pipeline_schedule
present
pipeline_schedule
.
destroy
,
with:
Entities
::
PipelineSchedule
end
end
end
end
spec/fixtures/api/schemas/pipeline_schedule.json
0 → 100644
View file @
fbd3b3d8
{
"type"
:
"object"
,
"properties"
:
{
"id"
:
{
"type"
:
"integer"
},
"description"
:
{
"type"
:
"string"
},
"ref"
:
{
"type"
:
"string"
},
"cron"
:
{
"type"
:
"string"
},
"cron_timezone"
:
{
"type"
:
"string"
},
"next_run_at"
:
{
"type"
:
"date"
},
"active"
:
{
"type"
:
"boolean"
},
"created_at"
:
{
"type"
:
"date"
},
"updated_at"
:
{
"type"
:
"date"
},
"deleted_at"
:
{
"type"
:
"date"
},
"last_pipeline"
:
{
"type"
:
[
"object"
,
"null"
],
"properties"
:
{
"id"
:
{
"type"
:
"integer"
},
"sha"
:
{
"type"
:
"string"
},
"ref"
:
{
"type"
:
"string"
},
"status"
:
{
"type"
:
"string"
},
"before_sha"
:
{
"type"
:
[
"string"
,
"null"
]
},
"tag"
:
{
"type"
:
[
"boolean"
,
"null"
]
},
"yaml_errors"
:
{
"type"
:
[
"string"
,
"null"
]
},
"user"
:
{
"type"
:
[
"object"
,
"null"
],
"properties"
:
{
"name"
:
{
"type"
:
"string"
},
"username"
:
{
"type"
:
"string"
},
"id"
:
{
"type"
:
"integer"
},
"state"
:
{
"type"
:
"string"
},
"avatar_url"
:
{
"type"
:
"uri"
},
"web_url"
:
{
"type"
:
"uri"
}
},
"additionalProperties"
:
false
},
"created_at"
:
{
"type"
:
"date"
},
"updated_at"
:
{
"type"
:
"date"
},
"started_at"
:
{
"type"
:
"date"
},
"finished_at"
:
{
"type"
:
"date"
},
"committed_at"
:
{
"type"
:
[
"string"
,
"null"
]
},
"duration"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"coverage"
:
{
"type"
:
[
"string"
,
"null"
]
}
},
"additionalProperties"
:
false
},
"owner"
:
{
"type"
:
"object"
,
"properties"
:
{
"name"
:
{
"type"
:
"string"
},
"username"
:
{
"type"
:
"string"
},
"id"
:
{
"type"
:
"integer"
},
"state"
:
{
"type"
:
"string"
},
"avatar_url"
:
{
"type"
:
"uri"
},
"web_url"
:
{
"type"
:
"uri"
}
},
"additionalProperties"
:
false
}
},
"required"
:
[
"id"
,
"description"
,
"ref"
,
"cron"
,
"cron_timezone"
,
"next_run_at"
,
"active"
,
"created_at"
,
"updated_at"
,
"deleted_at"
,
"owner"
],
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/pipeline_schedules.json
0 → 100644
View file @
fbd3b3d8
{
"type"
:
"array"
,
"items"
:
{
"$ref"
:
"pipeline_schedule.json"
}
}
spec/requests/api/pipeline_schedules_spec.rb
0 → 100644
View file @
fbd3b3d8
require
'spec_helper'
describe
API
::
PipelineSchedules
do
let
(
:developer
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let!
(
:project
)
{
create
(
:project
,
:repository
)
}
before
do
project
.
add_developer
(
developer
)
end
describe
'GET /projects/:id/pipeline_schedules'
do
context
'authenticated user with valid permissions'
do
before
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
.
tap
do
|
pipeline_schedule
|
pipeline_schedule
.
pipelines
<<
build
(
:ci_pipeline
,
project:
project
)
end
end
it
'returns list of pipeline_schedules'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
,
developer
)
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
include_pagination_headers
expect
(
response
).
to
match_response_schema
(
'pipeline_schedules'
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'GET /projects/:id/pipeline_schedules/:pipeline_schedule_id'
do
let
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
.
tap
do
|
pipeline_schedule
|
pipeline_schedule
.
pipelines
<<
build
(
:ci_pipeline
,
project:
project
)
end
end
context
'authenticated user with valid permissions'
do
it
'returns pipeline_schedule details'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
developer
)
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
end
it
'responds with 404 Not Found if requesting non-existing pipeline_schedule'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/-5"
,
developer
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not return pipeline_schedules list'
do
get
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'POST /projects/:id/pipeline_schedules'
do
let
(
:description
)
{
'pipeline_schedule'
}
let
(
:ref
)
{
'master'
}
let
(
:cron
)
{
'* * * * *'
}
let
(
:cron_timezone
)
{
'UTC'
}
let
(
:active
)
{
true
}
context
'authenticated user with valid permissions'
do
context
'with required parameters'
do
it
'creates pipeline_schedule'
do
expect
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
,
developer
),
description:
description
,
ref:
ref
,
cron:
cron
,
cron_timezone:
cron_timezone
,
active:
active
end
.
to
change
{
project
.
pipeline_schedules
.
count
}.
by
(
1
)
expect
(
response
).
to
have_http_status
(
:created
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
expect
(
json_response
[
'description'
]).
to
eq
(
description
)
expect
(
json_response
[
'ref'
]).
to
eq
(
ref
)
expect
(
json_response
[
'cron'
]).
to
eq
(
cron
)
expect
(
json_response
[
'cron_timezone'
]).
to
eq
(
cron_timezone
)
expect
(
json_response
[
'active'
]).
to
eq
(
active
)
end
end
context
'without required parameters'
do
it
'does not create pipeline_schedule'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
,
developer
)
expect
(
response
).
to
have_http_status
(
:bad_request
)
end
end
end
context
'authenticated user with invalid permissions'
do
it
'does not create pipeline_schedule'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
,
user
),
description:
description
,
ref:
ref
,
cron:
cron
,
cron_timezone:
cron_timezone
,
active:
active
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not create pipeline_schedule'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules"
),
description:
description
,
ref:
ref
,
cron:
cron
,
cron_timezone:
cron_timezone
,
active:
active
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id'
do
let
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
context
'authenticated user with valid permissions'
do
let
(
:new_ref
)
{
'patch-x'
}
it
'updates ref'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
developer
),
ref:
new_ref
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
expect
(
json_response
[
'ref'
]).
to
eq
(
new_ref
)
end
let
(
:new_cron
)
{
'1 2 3 4 *'
}
it
'updates cron'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
developer
),
cron:
new_cron
pipeline_schedule
.
reload
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
expect
(
json_response
[
'cron'
]).
to
eq
(
new_cron
)
expect
(
pipeline_schedule
.
next_run_at
.
min
).
to
eq
(
1
)
expect
(
pipeline_schedule
.
next_run_at
.
hour
).
to
eq
(
2
)
expect
(
pipeline_schedule
.
next_run_at
.
day
).
to
eq
(
3
)
expect
(
pipeline_schedule
.
next_run_at
.
month
).
to
eq
(
4
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not update pipeline_schedule'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not update pipeline_schedule'
do
put
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/take_ownership'
do
let
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
context
'authenticated user with valid permissions'
do
let
(
:developer2
)
{
create
(
:user
)
}
before
do
project
.
add_developer
(
developer2
)
end
it
'updates owner'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/take_ownership"
,
developer2
)
pipeline_schedule
.
reload
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
expect
(
pipeline_schedule
.
owner
).
to
eq
(
developer2
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not update owner'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/take_ownership"
,
user
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'unauthenticated user'
do
it
'does not update owner'
do
post
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
/take_ownership"
)
expect
(
response
).
to
have_http_status
(
:unauthorized
)
end
end
end
describe
'DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id'
do
let
(
:master
)
{
create
(
:user
)
}
let!
(
:pipeline_schedule
)
do
create
(
:ci_pipeline_schedule
,
project:
project
,
owner:
developer
)
end
before
do
project
.
add_master
(
master
)
end
context
'authenticated user with valid permissions'
do
it
'deletes pipeline_schedule'
do
expect
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
master
)
end
.
to
change
{
project
.
pipeline_schedules
.
count
}.
by
(
-
1
)
expect
(
response
).
to
have_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'pipeline_schedule'
)
end
it
'responds with 404 Not Found if requesting non-existing pipeline_schedule'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/-5"
,
master
)
expect
(
response
).
to
have_http_status
(
:not_found
)
end
end
context
'authenticated user with invalid permissions'
do
it
'does not delete pipeline_schedule'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
,
developer
)
expect
(
response
).
to
have_http_status
(
403
)
end
end
context
'unauthenticated user'
do
it
'does not delete pipeline_schedule'
do
delete
api
(
"/projects/
#{
project
.
id
}
/pipeline_schedules/
#{
pipeline_schedule
.
id
}
"
)
expect
(
response
).
to
have_http_status
(
401
)
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