Merge branch 'dev_devops' of http://gitea.trustie.net/jasder/forgeplus into dev_devops
This commit is contained in:
commit
02e6ecae9e
341
README.md
341
README.md
|
@ -2340,7 +2340,7 @@ http://localhost:3000/api//api/repositories/3868/delete_file | jq
|
||||||
"author": {
|
"author": {
|
||||||
"name": "18816895620",
|
"name": "18816895620",
|
||||||
"email": "2456233122@qq.com",
|
"email": "2456233122@qq.com",
|
||||||
"date": "2020-01-08T07:57:34Z"
|
"date": "2020-01-08T07:57:34Z"``
|
||||||
},
|
},
|
||||||
"committer": {
|
"committer": {
|
||||||
"name": "18816895620",
|
"name": "18816895620",
|
||||||
|
@ -2364,9 +2364,23 @@ POST /api/dev_ops/cloud_accounts
|
||||||
|
|
||||||
*示例*
|
*示例*
|
||||||
```
|
```
|
||||||
curl -X POST http://localhost:3000/api/dev_ops/cloud_accounts | jq
|
curl -X POST \
|
||||||
|
-d "account=xx" \
|
||||||
|
-d "secret=xxx" \
|
||||||
|
-d "ip_num=xx.xx.xx.xx" \
|
||||||
|
-d "repo_id=5988" \
|
||||||
|
https://localhost:3000/api/dev_ops/cloud_accounts.json | jq
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|account |是|string |云服务器ssh连接登录用户名 |
|
||||||
|
|secret |是|string |云服务器ssh连接登录秘密 |
|
||||||
|
|ip_num |否|string |云服务器公网IP |
|
||||||
|
|repo_id |否|string |repository id|
|
||||||
|
|
||||||
*返回参数说明:*
|
*返回参数说明:*
|
||||||
|
|
||||||
|参数名|类型|说明|
|
|参数名|类型|说明|
|
||||||
|
@ -2459,6 +2473,12 @@ GET /api/dev_ops/languages/:id
|
||||||
curl -X GET http://localhost:3000/api/dev_ops/languages/114.json | jq
|
curl -X GET http://localhost:3000/api/dev_ops/languages/114.json | jq
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|id |是|int |language's id |
|
||||||
|
|
||||||
*返回参数说明:*
|
*返回参数说明:*
|
||||||
|
|
||||||
|参数名|类型|说明|
|
|参数名|类型|说明|
|
||||||
|
@ -2480,3 +2500,320 @@ curl -X GET http://localhost:3000/api/dev_ops/languages/114.json | jq
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 获取构建列表
|
||||||
|
```
|
||||||
|
GET /api/dev_ops/builds
|
||||||
|
```
|
||||||
|
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X GET http://localhost:3000/api/dev_ops/builds | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|id |int|build's id|
|
||||||
|
|number |string|build's number|
|
||||||
|
|status |string|build's result|
|
||||||
|
|event |string|build's event|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 100207,
|
||||||
|
"repo_id": 296163,
|
||||||
|
"number": 42,
|
||||||
|
"status": "success",
|
||||||
|
"event": "pull_request",
|
||||||
|
"action": "sync",
|
||||||
|
"link": "https://github.com/octoat/hello-world/compare/e3320539a4c0...9fc1ad6ebf12",
|
||||||
|
"message": "updated README",
|
||||||
|
"before": "e3320539a4c03ccfda992641646deb67d8bf98f3",
|
||||||
|
"after": "9fc1ad6ebf12462f3f9773003e26b4c6f54a772e",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"source_repo": "spaceghost/hello-world",
|
||||||
|
"source": "develop",
|
||||||
|
"target": "master",
|
||||||
|
"author_login": "octocat",
|
||||||
|
"author_name": "The Octocat",
|
||||||
|
"author_email": "octocat@github.com",
|
||||||
|
"author_avatar": "http://www.gravatar.com/avatar/7194e8d48fa1d2b689f99443b767316c",
|
||||||
|
"sender": "bradrydzewski",
|
||||||
|
"started": 1564085874,
|
||||||
|
"finished": 1564086343,
|
||||||
|
"created": 1564085874,
|
||||||
|
"updated": 1564085874,
|
||||||
|
"version": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 获取某条构建详情信息
|
||||||
|
```
|
||||||
|
GET /api/dev_ops/builds/:number
|
||||||
|
```
|
||||||
|
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X GET http://localhost:3000/api/dev_ops/builds/42 | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|number |是|int |build's number |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|id |int|build's id|
|
||||||
|
|status |string|build's status|
|
||||||
|
|event |string|build's event|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"id": 100207,
|
||||||
|
"repo_id": 296163,
|
||||||
|
"number": 42,
|
||||||
|
"status": "pending",
|
||||||
|
"event": "pull_request",
|
||||||
|
"action": "sync",
|
||||||
|
"link": "https://github.com/octoat/hello-world/compare/e3320539a4c0...9fc1ad6ebf12",
|
||||||
|
"message": "updated README",
|
||||||
|
"before": "e3320539a4c03ccfda992641646deb67d8bf98f3",
|
||||||
|
"after": "9fc1ad6ebf12462f3f9773003e26b4c6f54a772e",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"source_repo": "spaceghost/hello-world",
|
||||||
|
"source": "develop",
|
||||||
|
"target": "master",
|
||||||
|
"author_login": "octocat",
|
||||||
|
"author_name": "The Octocat",
|
||||||
|
"author_email": "octocat@github.com",
|
||||||
|
"author_avatar": "http://www.gravatar.com/avatar/7194e8d48fa1d2b689f99443b767316c",
|
||||||
|
"sender": "bradrydzewski",
|
||||||
|
"started": 0,
|
||||||
|
"finished": 0,
|
||||||
|
"created": 1564085874,
|
||||||
|
"updated": 1564085874,
|
||||||
|
"version": 1,
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"id": 199937,
|
||||||
|
"repo_id": 296163,
|
||||||
|
"build_id": 100207,
|
||||||
|
"number": 1,
|
||||||
|
"name": "default",
|
||||||
|
"kind": "pipeline",
|
||||||
|
"type": "docker",
|
||||||
|
"status": "pending",
|
||||||
|
"errignore": false,
|
||||||
|
"exit_code": 0,
|
||||||
|
"machine": "15e89c0f84f1",
|
||||||
|
"os": "linux",
|
||||||
|
"arch": "amd64",
|
||||||
|
"started": 0,
|
||||||
|
"stopped": 0,
|
||||||
|
"created": 1564085874,
|
||||||
|
"updated": 1564086343,
|
||||||
|
"version": 1,
|
||||||
|
"on_success": true,
|
||||||
|
"on_failure": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 重启构建/重新构建
|
||||||
|
```
|
||||||
|
POST /api/dev_ops/builds/:number
|
||||||
|
```
|
||||||
|
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X POST http://localhost:3000/api/dev_ops/builds/42 | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|number |是|int |build's number |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|id |int|build's id|
|
||||||
|
|status |string|build's status|
|
||||||
|
|event |string|build's event|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"id": 100207,
|
||||||
|
"repo_id": 296163,
|
||||||
|
"number": 42,
|
||||||
|
"status": "pending",
|
||||||
|
"event": "pull_request",
|
||||||
|
"action": "sync",
|
||||||
|
"link": "https://github.com/octoat/hello-world/compare/e3320539a4c0...9fc1ad6ebf12",
|
||||||
|
"message": "updated README",
|
||||||
|
"before": "e3320539a4c03ccfda992641646deb67d8bf98f3",
|
||||||
|
"after": "9fc1ad6ebf12462f3f9773003e26b4c6f54a772e",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"source_repo": "spaceghost/hello-world",
|
||||||
|
"source": "develop",
|
||||||
|
"target": "master",
|
||||||
|
"author_login": "octocat",
|
||||||
|
"author_name": "The Octocat",
|
||||||
|
"author_email": "octocat@github.com",
|
||||||
|
"author_avatar": "http://www.gravatar.com/avatar/7194e8d48fa1d2b689f99443b767316c",
|
||||||
|
"sender": "bradrydzewski",
|
||||||
|
"started": 0,
|
||||||
|
"finished": 0,
|
||||||
|
"created": 1564085874,
|
||||||
|
"updated": 1564085874,
|
||||||
|
"version": 1,
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"id": 199937,
|
||||||
|
"repo_id": 296163,
|
||||||
|
"build_id": 100207,
|
||||||
|
"number": 1,
|
||||||
|
"name": "default",
|
||||||
|
"kind": "pipeline",
|
||||||
|
"type": "docker",
|
||||||
|
"status": "pending",
|
||||||
|
"errignore": false,
|
||||||
|
"exit_code": 0,
|
||||||
|
"machine": "15e89c0f84f1",
|
||||||
|
"os": "linux",
|
||||||
|
"arch": "amd64",
|
||||||
|
"started": 0,
|
||||||
|
"stopped": 0,
|
||||||
|
"created": 1564085874,
|
||||||
|
"updated": 1564086343,
|
||||||
|
"version": 1,
|
||||||
|
"on_success": true,
|
||||||
|
"on_failure": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 关闭构建
|
||||||
|
```
|
||||||
|
DELETE /api/dev_ops/builds/:number
|
||||||
|
```
|
||||||
|
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X DELETE http://localhost:3000/api/dev_ops/builds/42 | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|number |是|int |build's number |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|id |int|build's id|
|
||||||
|
|status |string|build's status|
|
||||||
|
|event |string|build's event|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 获取某条构建的log信息
|
||||||
|
```
|
||||||
|
GET /api/dev_ops/builds/:number/logs/:stage/:step
|
||||||
|
```
|
||||||
|
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X GET http://localhost:3000/api/dev_ops/builds/42/logs/ | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|number |是|int |build's number |
|
||||||
|
|stage |是|int |build's stage id |
|
||||||
|
|step |是|int |build's step id |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|id |int|build's id|
|
||||||
|
|status |string|build's status|
|
||||||
|
|event |string|build's event|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 0,
|
||||||
|
"out": "+ git init\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 1,
|
||||||
|
"out": "Initialized empty Git repository in /drone/src/github.com/octocat/hello-world/.git/\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 2,
|
||||||
|
"out": "+ git remote add origin https://github.com/octocat/hello-world.git\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 3,
|
||||||
|
"out": "+ git fetch --no-tags origin +refs/heads/master:\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 4,
|
||||||
|
"out": "From https://github.com/octocat/hello-world\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 5,
|
||||||
|
"out": " * branch master -> FETCH_HEAD\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 6,
|
||||||
|
"out": " * [new branch] master -> origin/master\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 7,
|
||||||
|
"out": "+ git reset --hard -q 62126a02ffea3dabd7789e5c5407553490973665\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"proc": "clone",
|
||||||
|
"pos": 8,
|
||||||
|
"out": "+ git submodule update --init --recursive\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class DevOps::BuildsController < ApplicationController
|
class ::DevOps::BuildsController < ApplicationController
|
||||||
before_action :require_login
|
before_action :require_login
|
||||||
before_action :find_project
|
before_action :find_repo
|
||||||
|
|
||||||
def index
|
def index
|
||||||
cloud_account = @repo.dev_ops_cloud_account
|
cloud_account = @repo.dev_ops_cloud_account
|
||||||
|
@ -37,7 +37,7 @@ class DevOps::BuildsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def find_project
|
def find_repo
|
||||||
@repo = Repository.find params[:id]
|
@repo = ::Repository.find params[:id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,12 +14,12 @@ class DevOps::CloudAccountsController < ApplicationController
|
||||||
logger.info "######### create_params: #{create_params}"
|
logger.info "######### create_params: #{create_params}"
|
||||||
|
|
||||||
|
|
||||||
if cloud_account = @project.dev_ops_cloud_account
|
if cloud_account = @repo.dev_ops_cloud_account
|
||||||
cloud_account
|
cloud_account
|
||||||
else
|
else
|
||||||
cloud_account = DevOps::CloudAccount.new(create_params)
|
cloud_account = DevOps::CloudAccount.new(create_params)
|
||||||
cloud_account.user = current_user
|
cloud_account.user = current_user
|
||||||
cloud_account.project_id = @project.id
|
cloud_account.repo_id = @repo.id
|
||||||
cloud_account.save!
|
cloud_account.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,11 +64,10 @@ class DevOps::CloudAccountsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
def devops_params
|
def devops_params
|
||||||
params.permit(:account, :secret, :ip_num, :project_id)
|
params.permit(:account, :secret, :ip_num, :repo_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_project
|
def find_project
|
||||||
@project = Project.find_by_id params[:project_id]
|
@repo = Repository.find params[:repo_id]
|
||||||
render_not_found("未找到project_id为:#{params[:project_id]}相关的项目") if @project.blank?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,22 +24,22 @@
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(endpoint, path, options={})
|
def get(endpoint, path, options={})
|
||||||
set_request_defaults(endpoint)
|
validate_request_params!(endpoint)
|
||||||
request(:get, endpoint, path, options)
|
request(:get, endpoint, path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def post(endpoint, path, options={})
|
def post(endpoint, path, options={})
|
||||||
set_request_defaults(endpoint)
|
validate_request_params!(endpoint)
|
||||||
request(:post, endpoint, path, options)
|
request(:post, endpoint, path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def put(endpoint, path, options={})
|
def put(endpoint, path, options={})
|
||||||
set_request_defaults(endpoint)
|
validate_request_params!(endpoint)
|
||||||
request(:put, endpoint, path, options)
|
request(:put, endpoint, path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(endpoint, path, options={})
|
def delete(endpoint, path, options={})
|
||||||
set_request_defaults(endpoint)
|
validate_request_params!(endpoint)
|
||||||
request(:delete, endpoint, path, options)
|
request(:delete, endpoint, path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,27 +47,10 @@
|
||||||
def request(method, endpoint, path, **params)
|
def request(method, endpoint, path, **params)
|
||||||
Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:secret).inspect}")
|
Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:secret).inspect}")
|
||||||
|
|
||||||
client = Faraday.new(path: domain)
|
client = Faraday.new(url: endpoint)
|
||||||
response = client.public_send(method, path, params)
|
response = client.public_send(method, path, params)
|
||||||
result = JSON.parse(response.body)
|
|
||||||
|
|
||||||
Rails.logger.info("[drone] response:#{response.status} #{result.inspect}")
|
json_response(response)
|
||||||
|
|
||||||
if response.status != 200
|
|
||||||
raise DevOps::Drone::Error.parse(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
if result['errcode'].present? && result['errcode'].to_i.nonzero?
|
|
||||||
raise DevOps::Drone::Error.parse(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sets a base_uri and default_params for requests.
|
|
||||||
# @raise [Error::MissingCredentials] if endpoint not set.
|
|
||||||
def set_request_defaults(endpoint, private_token, sudo=nil)
|
|
||||||
raise "Please set an endpoint to API" unless endpoint
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checks the response code for common errors.
|
# Checks the response code for common errors.
|
||||||
|
@ -89,8 +72,21 @@
|
||||||
response.parsed_response
|
response.parsed_response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Checks a base_uri and params for requests.
|
||||||
|
def validate_request_params!(endpoint)
|
||||||
|
raise "Please set an endpoint to API" unless endpoint
|
||||||
|
end
|
||||||
|
|
||||||
def error_message(response)
|
def error_message(response)
|
||||||
"Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \
|
"Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \
|
||||||
"Request URI: #{response.request.base_uri}#{response.request.path}"
|
"Request URI: #{response.request.base_uri}#{response.request.path}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def json_response(response)
|
||||||
|
result = JSON.parse(response.body)
|
||||||
|
status = response.status
|
||||||
|
Rails.logger.info("[drone] response:#{status} #{result.inspect}")
|
||||||
|
|
||||||
|
response.status != 200 ? result.merge!(status: response.status) : result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class DevOps::CloudAccount < ApplicationRecord
|
class DevOps::CloudAccount < ApplicationRecord
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :repository
|
belongs_to :repository, foreign_key: :repo_id
|
||||||
|
|
||||||
def drone_host
|
def drone_host
|
||||||
[drone_ip, ":80"].join
|
[drone_ip, ":80"].join
|
||||||
|
|
|
@ -3,7 +3,7 @@ class Repository < ApplicationRecord
|
||||||
belongs_to :project, :touch => true
|
belongs_to :project, :touch => true
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_one :mirror, foreign_key: :repo_id
|
has_one :mirror, foreign_key: :repo_id
|
||||||
has_one :dev_ops_cloud_account, foreign_key: :repo_id
|
has_one :dev_ops_cloud_account, class_name: 'DevOps::CloudAccount', foreign_key: :repo_id
|
||||||
has_many :version_releases, dependent: :destroy
|
has_many :version_releases, dependent: :destroy
|
||||||
|
|
||||||
validates :identifier, presence: true
|
validates :identifier, presence: true
|
||||||
|
|
|
@ -22,13 +22,12 @@ Rails.application.routes.draw do
|
||||||
get :common
|
get :common
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :builds, only: :index do
|
resources :builds, only: :index do
|
||||||
collection do
|
collection do
|
||||||
get ':number', to: 'builds#detail', as: 'detail'
|
get ':number', to: 'builds#detail', as: 'detail'
|
||||||
get ':number/logs/:stage/:step', to: 'builds#detail', as: 'logs'
|
|
||||||
post ':number', to: 'builds#restart', as: 'restart'
|
post ':number', to: 'builds#restart', as: 'restart'
|
||||||
delete ':number', to: 'builds#delete', as: 'delete'
|
delete ':number', to: 'builds#delete', as: 'delete'
|
||||||
|
get ':number/logs/:stage/:step', to: 'builds#detail', as: 'logs'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue