forked from Gitlink/forgeplus
ADD protected branch Features
This commit is contained in:
parent
a24f0f8b45
commit
6a8ae5234b
277
api_document.md
277
api_document.md
|
@ -2650,6 +2650,283 @@ http://localhost:3000/api/ysfns/test-txt/compare/master...Jason/test-txt:develop
|
||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 创建保护分支
|
||||||
|
```
|
||||||
|
POST /api/:owner/:repo/protected_branches
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X POST \
|
||||||
|
-d 'branch_name=master' \
|
||||||
|
-d 'enable_push=true' \
|
||||||
|
-d 'enable_push_whitelist=true' \
|
||||||
|
-d 'enable_push_whitelist=["demo1", "demo1"]' \
|
||||||
|
-d 'enable_merge_whitelist=true' \
|
||||||
|
http://localhost:3000/api/trustie/truesite/protected_branches.json | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |项目拥有者登录名 |
|
||||||
|
|repo |否|boolean |仓库名称 |
|
||||||
|
|branch_name |是|string |保护分支名称 |
|
||||||
|
|enable_push |否|boolean |是否启用推送, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|enable_push_whitelist |否|boolean |是否启用白名单推送, true: 启用; false: 不启用, 默认为false, 该参数与enable_push参数为单选项,只能选择|
|
||||||
|
|push_whitelist_usernames |否|array |推送白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_push_whitelist参数配合使用 |
|
||||||
|
|enable_merge_whitelist |否|boolean |是否启用合并白名单, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|merge_whitelist_usernames |否|array |合并白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_merge_whitelist配合使用 |
|
||||||
|
|enable_status_check |否|boolean |是否启用状态检查, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|required_approvals |否|int |所需的批准数, 默认为0 |
|
||||||
|
|enable_approvals_whitelist |否|boolean |是否启用批准仅限列入白名单的用户或团队, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|approvals_whitelist_username |否|array |审查者白名单(即具有写操作的项目成员名称的数组), 该参数与enable_approvals_whitelist配合使用 |
|
||||||
|
|block_on_rejected_reviews |否|boolean |是否启用拒绝审核阻止合并功能, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|dismiss_stale_approvals |否|boolean |是否启用取消过时的批准, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|require_signed_commits |否|boolean |是否需要签名提交, true: 是, false: 否, 默认为false |
|
||||||
|
|block_on_outdated_branch |否|boolean |如果拉取请求已经过时,是否阻止合并, true: 是, false: 否, 默认为false |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|branch_name |string |保护分支名称 |
|
||||||
|
|enable_push |boolean |是否启用推送, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|enable_push_whitelist |boolean |是否启用白名单推送, true: 启用; false: 不启用, 默认为false, 该参数与enable_push参数为单选项,只能选择|
|
||||||
|
|push_whitelist_usernames |array |推送白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_push_whitelist参数配合使用 |
|
||||||
|
|enable_merge_whitelist |boolean |是否启用合并白名单, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|merge_whitelist_usernames |array |合并白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_merge_whitelist配合使用 |
|
||||||
|
|enable_status_check |boolean |是否启用状态检查, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|required_approvals |int |所需的批准数, 默认为0 |
|
||||||
|
|enable_approvals_whitelist |boolean |是否启用批准仅限列入白名单的用户或团队, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|approvals_whitelist_username |array |审查者白名单(即具有写操作的项目成员名称的数组), 该参数与enable_approvals_whitelist配合使用 |
|
||||||
|
|block_on_rejected_reviews |boolean |是否启用拒绝审核阻止合并功能, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|dismiss_stale_approvals |boolean |是否启用取消过时的批准, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|require_signed_commits |boolean |是否需要签名提交, true: 是, false: 否, 默认为false |
|
||||||
|
|block_on_outdated_branch |boolean |如果拉取请求已经过时,是否阻止合并, true: 是, false: 否, 默认为false |
|
||||||
|
|created_at |string|创建时间|
|
||||||
|
|updated_at |string|更新时间|
|
||||||
|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"branch_name": "develop",
|
||||||
|
"enable_push": true,
|
||||||
|
"required_approvals": 0,
|
||||||
|
"enable_status_check": true,
|
||||||
|
"enable_push_whitelist": true,
|
||||||
|
"enable_merge_whitelist": true,
|
||||||
|
"enable_approvals_whitelist": false,
|
||||||
|
"dismiss_stale_approvals": false,
|
||||||
|
"block_on_rejected_reviews": false,
|
||||||
|
"block_on_outdated_branch": false,
|
||||||
|
"require_signed_commits": false,
|
||||||
|
"merge_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"push_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"approvals_whitelist_usernames": [],
|
||||||
|
"created_at": "2020-12-02 17:40",
|
||||||
|
"updated_at": "2020-12-03 11:29"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
### 修改保护分支参数
|
||||||
|
```
|
||||||
|
PATCH /api/:owner/:repo/protected_branches/:branch_name
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X PATCH \
|
||||||
|
-d 'branch_name=master' \
|
||||||
|
-d 'enable_push=true' \
|
||||||
|
-d 'enable_push_whitelist=true' \
|
||||||
|
-d 'enable_push_whitelist=["demo1", "demo1"]' \
|
||||||
|
-d 'enable_merge_whitelist=true' \
|
||||||
|
http://localhost:3000/api/trustie/truesite/protected_branches/master.json | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |项目拥有者登录名 |
|
||||||
|
|repo |否|boolean |仓库名称 |
|
||||||
|
|branch_name |是|string |保护分支名称 |
|
||||||
|
|enable_push |否|boolean |是否启用推送, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|enable_push_whitelist |否|boolean |是否启用白名单推送, true: 启用; false: 不启用, 默认为false, 该参数与enable_push参数为单选项,只能选择|
|
||||||
|
|push_whitelist_usernames |否|array |推送白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_push_whitelist参数配合使用 |
|
||||||
|
|enable_merge_whitelist |否|boolean |是否启用合并白名单, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|merge_whitelist_usernames |否|array |合并白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_merge_whitelist配合使用 |
|
||||||
|
|enable_status_check |否|boolean |是否启用状态检查, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|required_approvals |否|int |所需的批准数, 默认为0 |
|
||||||
|
|enable_approvals_whitelist |否|boolean |是否启用批准仅限列入白名单的用户或团队, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|approvals_whitelist_username |否|array |审查者白名单(即具有写操作的项目成员名称的数组), 该参数与enable_approvals_whitelist配合使用 |
|
||||||
|
|block_on_rejected_reviews |否|boolean |是否启用拒绝审核阻止合并功能, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|dismiss_stale_approvals |否|boolean |是否启用取消过时的批准, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|require_signed_commits |否|boolean |是否需要签名提交, true: 是, false: 否, 默认为false |
|
||||||
|
|block_on_outdated_branch |否|boolean |如果拉取请求已经过时,是否阻止合并, true: 是, false: 否, 默认为false |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|branch_name |string |保护分支名称 |
|
||||||
|
|enable_push |boolean |是否启用推送, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|enable_push_whitelist |boolean |是否启用白名单推送, true: 启用; false: 不启用, 默认为false, 该参数与enable_push参数为单选项,只能选择|
|
||||||
|
|push_whitelist_usernames |array |推送白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_push_whitelist参数配合使用 |
|
||||||
|
|enable_merge_whitelist |boolean |是否启用合并白名单, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|merge_whitelist_usernames |array |合并白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_merge_whitelist配合使用 |
|
||||||
|
|enable_status_check |boolean |是否启用状态检查, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|required_approvals |int |所需的批准数, 默认为0 |
|
||||||
|
|enable_approvals_whitelist |boolean |是否启用批准仅限列入白名单的用户或团队, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|approvals_whitelist_username |array |审查者白名单(即具有写操作的项目成员名称的数组), 该参数与enable_approvals_whitelist配合使用 |
|
||||||
|
|block_on_rejected_reviews |boolean |是否启用拒绝审核阻止合并功能, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|dismiss_stale_approvals |boolean |是否启用取消过时的批准, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|require_signed_commits |boolean |是否需要签名提交, true: 是, false: 否, 默认为false |
|
||||||
|
|block_on_outdated_branch |boolean |如果拉取请求已经过时,是否阻止合并, true: 是, false: 否, 默认为false |
|
||||||
|
|created_at |string|创建时间|
|
||||||
|
|updated_at |string|更新时间|
|
||||||
|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"branch_name": "develop",
|
||||||
|
"enable_push": true,
|
||||||
|
"required_approvals": 0,
|
||||||
|
"enable_status_check": true,
|
||||||
|
"enable_push_whitelist": true,
|
||||||
|
"enable_merge_whitelist": true,
|
||||||
|
"enable_approvals_whitelist": false,
|
||||||
|
"dismiss_stale_approvals": false,
|
||||||
|
"block_on_rejected_reviews": false,
|
||||||
|
"block_on_outdated_branch": false,
|
||||||
|
"require_signed_commits": false,
|
||||||
|
"merge_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"push_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"approvals_whitelist_usernames": [],
|
||||||
|
"created_at": "2020-12-02 17:40",
|
||||||
|
"updated_at": "2020-12-03 11:29"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
### 删除保护分支
|
||||||
|
```
|
||||||
|
DELETE /api/:owner/:repo/protected_branches/:branch_name
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X DELETE \
|
||||||
|
-d 'branch_name=master' \
|
||||||
|
http://localhost:3000/api/trustie/truesite/protected_branches/master.json | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |项目拥有者登录名 |
|
||||||
|
|repo |否|boolean |仓库名称 |
|
||||||
|
|branch_name |是|string |保护分支名称 |
|
||||||
|
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|status |int|状态值,0: 请求成功; -1: 请求失败|
|
||||||
|
|message |string|信息说明|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
### 获取保护分支列表
|
||||||
|
```
|
||||||
|
GET /api/:owner/:repo/protected_branches/
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```
|
||||||
|
curl -X GET \
|
||||||
|
-d "page=1" \
|
||||||
|
-d "limit=5" \
|
||||||
|
http://localhost:3000/api/trustie/truesite/protected_branches.json | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|owner |是|string |项目拥有者登录名 |
|
||||||
|
|repo |否|boolean |仓库名称 |
|
||||||
|
|page |否|string |页数,第几页 |
|
||||||
|
|limit |否|string |每页多少条数据,默认15条 |
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|total_count |int | 总记录数 |
|
||||||
|
|branch_name |string |保护分支名称 |
|
||||||
|
|enable_push |boolean |是否启用推送, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|enable_push_whitelist |boolean |是否启用白名单推送, true: 启用; false: 不启用, 默认为false, 该参数与enable_push参数为单选项,只能选择|
|
||||||
|
|push_whitelist_usernames |array |推送白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_push_whitelist参数配合使用 |
|
||||||
|
|enable_merge_whitelist |boolean |是否启用合并白名单, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|merge_whitelist_usernames |array |合并白名单用户(即具有写操作的项目成员名称的数组), 该参数与enable_merge_whitelist配合使用 |
|
||||||
|
|enable_status_check |boolean |是否启用状态检查, true: 启用; false: 不启用, 默认为false |
|
||||||
|
|required_approvals |int |所需的批准数, 默认为0 |
|
||||||
|
|enable_approvals_whitelist |boolean |是否启用批准仅限列入白名单的用户或团队, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|approvals_whitelist_username |array |审查者白名单(即具有写操作的项目成员名称的数组), 该参数与enable_approvals_whitelist配合使用 |
|
||||||
|
|block_on_rejected_reviews |boolean |是否启用拒绝审核阻止合并功能, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|dismiss_stale_approvals |boolean |是否启用取消过时的批准, true: 启用, false: 不启用, 默认为false |
|
||||||
|
|require_signed_commits |boolean |是否需要签名提交, true: 是, false: 否, 默认为false |
|
||||||
|
|block_on_outdated_branch |boolean |如果拉取请求已经过时,是否阻止合并, true: 是, false: 否, 默认为false |
|
||||||
|
|created_at |string|创建时间|
|
||||||
|
|updated_at |string|更新时间|
|
||||||
|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"total_count": 1,
|
||||||
|
"protected_branches": [
|
||||||
|
{
|
||||||
|
"branch_name": "develop",
|
||||||
|
"enable_push": true,
|
||||||
|
"required_approvals": 0,
|
||||||
|
"enable_status_check": true,
|
||||||
|
"enable_push_whitelist": true,
|
||||||
|
"enable_merge_whitelist": true,
|
||||||
|
"enable_approvals_whitelist": false,
|
||||||
|
"dismiss_stale_approvals": false,
|
||||||
|
"block_on_rejected_reviews": false,
|
||||||
|
"block_on_outdated_branch": false,
|
||||||
|
"require_signed_commits": false,
|
||||||
|
"merge_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"push_whitelist_usernames": [
|
||||||
|
"jasder"
|
||||||
|
],
|
||||||
|
"approvals_whitelist_usernames": [],
|
||||||
|
"created_at": "2020-12-02 17:40",
|
||||||
|
"updated_at": "2020-12-03 11:29"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
### DevOps相关api
|
### DevOps相关api
|
||||||
---
|
---
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
class ProtectedBranchesController < ApplicationController
|
||||||
|
before_action :require_login
|
||||||
|
before_action :load_repository
|
||||||
|
|
||||||
|
def index
|
||||||
|
scope = ProtectedBranch.all
|
||||||
|
@total_count = scope.size
|
||||||
|
@protected_branches = paginate(scope)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@protected_branch = ProtectedBranches::CreateService.call(@repository, @owner, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@protected_branch = ProtectedBranches::UpdateService.call(@repository, @owner, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
ProtectedBranches::DestroyService.call(@repository, @owner, params[:branch_name])
|
||||||
|
|
||||||
|
render_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def render_protected_branch_json
|
||||||
|
if @protected_branch.persisted?
|
||||||
|
render json: Jbuilder.new { |json| json.extract! @protected_branch, :can_push }.target!
|
||||||
|
else
|
||||||
|
render_error('创建失败!')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
class ProtectedBranches::CreateForm < BaseForm
|
||||||
|
attr_accessor :repository, :branch_name, :can_push, :enable_whitelist, :whitelist_user_i_ds,
|
||||||
|
:whitelist_team_i_ds, :enable_merge_whitelist, :whitelist_deploy_keys, :merge_whitelist_user_i_ds,
|
||||||
|
:merge_whitelist_team_i_ds, :enable_status_check, :status_check_contexts, :approvals_whitelist_user_i_ds,
|
||||||
|
:approvals_whitelist_team_i_ds, :required_approvals, :enable_approvals_whitelist, :block_on_rejected_reviews,
|
||||||
|
:dismiss_stale_approvals, :require_signed_commits, :protected_file_patterns, :block_on_outdated_branch
|
||||||
|
|
||||||
|
validates :repo_id, :branch_name, presence: true
|
||||||
|
|
||||||
|
validate do
|
||||||
|
check_branch_name!
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def check_branch_name!
|
||||||
|
protected_branch_exists = repository.protected_branches.exists?(branch_name)
|
||||||
|
raise "Protected branch '#{branch_name}' already exists" if protected_branch_exists
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
module ProtectedBranchesHelper
|
||||||
|
end
|
|
@ -0,0 +1,44 @@
|
||||||
|
module Repositories::ProtectedBranches
|
||||||
|
class DeleteInteractor
|
||||||
|
def self.call(user, identifier, filepath, **args)
|
||||||
|
interactor = new(user, identifier, filepath, **args)
|
||||||
|
interactor.run
|
||||||
|
interactor
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :error, :result
|
||||||
|
|
||||||
|
def initialize(user, identifier, filepath, **args)
|
||||||
|
@user = user
|
||||||
|
@identifier = identifier
|
||||||
|
@filepath = filepath
|
||||||
|
@args = args
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
@error.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def result
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
|
||||||
|
rescue Exception => exception
|
||||||
|
fail!(exception.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_reader :user, :identifier, :filepath, :args
|
||||||
|
|
||||||
|
def fail!(error)
|
||||||
|
@error = error
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_result(response)
|
||||||
|
@result = response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,7 @@ module ProjectOperable
|
||||||
has_many :managers, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
|
has_many :managers, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
|
||||||
has_many :developers, -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member'
|
has_many :developers, -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member'
|
||||||
has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member'
|
has_many :reporters, -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member'
|
||||||
|
has_many :writable_members, -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member'
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_member!(user_id, role_name='Developer')
|
def add_member!(user_id, role_name='Developer')
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: protected_branches
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# repo_id :integer
|
||||||
|
# branch_name :string(255) default("")
|
||||||
|
# can_push :boolean default("0"), not null
|
||||||
|
# enable_whitelist :boolean default("0")
|
||||||
|
# whitelist_user_i_ds :text(65535)
|
||||||
|
# whitelist_team_i_ds :text(65535)
|
||||||
|
# enable_merge_whitelist :boolean default("0"), not null
|
||||||
|
# whitelist_deploy_keys :boolean default("0"), not null
|
||||||
|
# merge_whitelist_user_i_ds :text(65535)
|
||||||
|
# merge_whitelist_team_i_ds :text(65535)
|
||||||
|
# enable_status_check :boolean default("0"), not null
|
||||||
|
# status_check_contexts :text(65535)
|
||||||
|
# approvals_whitelist_user_i_ds :text(65535)
|
||||||
|
# approvals_whitelist_team_i_ds :text(65535)
|
||||||
|
# required_approvals :integer default("0")
|
||||||
|
# enable_approvals_whitelist :boolean default("0"), not null
|
||||||
|
# block_on_rejected_reviews :boolean default("0"), not null
|
||||||
|
# dismiss_stale_approvals :boolean default("0"), not null
|
||||||
|
# require_signed_commits :boolean default("0"), not null
|
||||||
|
# protected_file_patterns :text(65535)
|
||||||
|
# block_on_outdated_branch :boolean default("0"), not null
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_protected_branches_on_repo_id (repo_id)
|
||||||
|
#
|
||||||
|
|
||||||
|
class ProtectedBranch < ApplicationRecord
|
||||||
|
serialize :whitelist_user_i_ds, Array
|
||||||
|
serialize :merge_whitelist_user_i_ds, Array
|
||||||
|
serialize :approvals_whitelist_user_i_ds, Array
|
||||||
|
|
||||||
|
belongs_to :repo, class_name: 'Repository', foreign_key: :repo_id
|
||||||
|
validates :branch_name, presence: true
|
||||||
|
validates :repo, presence: true
|
||||||
|
|
||||||
|
def to_param
|
||||||
|
self.branch_name.parameterize
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def push_whitelist_usernames
|
||||||
|
get_logins_by_ids(whitelist_user_i_ds)
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_whitelist_usernames
|
||||||
|
get_logins_by_ids(merge_whitelist_user_i_ds)
|
||||||
|
end
|
||||||
|
|
||||||
|
def approvals_whitelist_usernames
|
||||||
|
get_logins_by_ids(approvals_whitelist_user_i_ds)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_logins_by_ids(ids)
|
||||||
|
User.where(id: ids).map(&:login)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -37,6 +37,7 @@ class Repository < ApplicationRecord
|
||||||
has_one :mirror, foreign_key: :repo_id
|
has_one :mirror, foreign_key: :repo_id
|
||||||
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :repo_id
|
has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :repo_id
|
||||||
has_many :version_releases, dependent: :destroy
|
has_many :version_releases, dependent: :destroy
|
||||||
|
has_many :protected_branches, class_name: 'ProtectedBranch', foreign_key: :repo_id, dependent: :destroy
|
||||||
|
|
||||||
validates :identifier, presence: true
|
validates :identifier, presence: true
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,10 @@ class Gitea::ClientService < ApplicationService
|
||||||
def post(url, params={})
|
def post(url, params={})
|
||||||
puts "[gitea] request params: #{params}"
|
puts "[gitea] request params: #{params}"
|
||||||
auth_token = authen_params(params[:token])
|
auth_token = authen_params(params[:token])
|
||||||
response = conn(auth_token).post do |req|
|
conn(auth_token).post do |req|
|
||||||
req.url full_url(url)
|
req.url full_url(url)
|
||||||
req.body = params[:data].to_json
|
req.body = params[:data].to_json
|
||||||
end
|
end
|
||||||
render_status(response)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(url, params={})
|
def get(url, params={})
|
||||||
|
@ -164,4 +163,86 @@ class Gitea::ClientService < ApplicationService
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_response(response)
|
||||||
|
status = response.status
|
||||||
|
body = response&.body
|
||||||
|
|
||||||
|
body, message =
|
||||||
|
if body.present?
|
||||||
|
body = JSON.parse(body)
|
||||||
|
fix_body(body)
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
puts "[gitea] status: #{status}"
|
||||||
|
puts "[gitea] message: #{message}"
|
||||||
|
puts "[gitea] body: #{body}"
|
||||||
|
[status, message, body]
|
||||||
|
end
|
||||||
|
|
||||||
|
def fix_body(body)
|
||||||
|
return [body, nil] if body.is_a? Array
|
||||||
|
|
||||||
|
body['message'].blank? ? [body, nil] : [nil, body['message']]
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_json_data(status, message, body, success=true)
|
||||||
|
if success
|
||||||
|
success(body)
|
||||||
|
else
|
||||||
|
error(message, status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def error(message, http_status = nil)
|
||||||
|
result = {
|
||||||
|
message: message,
|
||||||
|
status: :error
|
||||||
|
}
|
||||||
|
|
||||||
|
result[:http_status] = http_status if http_status
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def success(body=nil)
|
||||||
|
{
|
||||||
|
status: :success,
|
||||||
|
body: body
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_body(body)
|
||||||
|
success(body)[:body]
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_200_response(response)
|
||||||
|
extract_statuses(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_200_no_body(response)
|
||||||
|
response.status
|
||||||
|
case response.status
|
||||||
|
when 200
|
||||||
|
{status: 200}
|
||||||
|
else
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_201_response(response)
|
||||||
|
extract_statuses(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_202_response(response)
|
||||||
|
extract_statuses(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
def extract_statuses(response)
|
||||||
|
success_statuses = [200, 201, 202, 204]
|
||||||
|
status, message, body = render_response(response)
|
||||||
|
|
||||||
|
error(message, status) unless success_statuses.include? status
|
||||||
|
|
||||||
|
render_body(body)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,8 @@ class Gitea::Hooks::CreateService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, params)
|
response = post(url, params)
|
||||||
|
render_201_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -27,7 +27,8 @@ class Gitea::Oauth2::CreateService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, request_params)
|
response = post(url, request_params)
|
||||||
|
render_201_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Gitea::Repository::Branches::GetService < Gitea::ClientService
|
||||||
|
|
||||||
def call
|
def call
|
||||||
response = get(url, params)
|
response = get(url, params)
|
||||||
render_data(response)
|
render_200_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Gitea::Repository::Branches::ListService < Gitea::ClientService
|
||||||
|
|
||||||
def call
|
def call
|
||||||
response = get(url, params)
|
response = get(url, params)
|
||||||
render_data(response)
|
render_200_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -18,7 +18,8 @@ class Gitea::Repository::CreateService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, request_params)
|
response = post(url, request_params)
|
||||||
|
render_201_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -29,7 +29,9 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, params)
|
response = post(url, params)
|
||||||
|
|
||||||
|
render_201_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -14,7 +14,9 @@ class Gitea::Repository::ForkService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, request_params)
|
response = post(url, request_params)
|
||||||
|
|
||||||
|
render_202_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -31,7 +31,9 @@ class Gitea::Repository::MigrateService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, request_params)
|
response = post(url, request_params)
|
||||||
|
|
||||||
|
render_201_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Create a branch protections for a repository
|
||||||
|
|
||||||
|
class Gitea::Repository::ProtectedBranches::CreateService < Gitea::ClientService
|
||||||
|
attr_reader :owner, :repo, :body, :token
|
||||||
|
|
||||||
|
# owner: owner of the repo
|
||||||
|
# repo: name of the repo
|
||||||
|
# body:
|
||||||
|
# {
|
||||||
|
# "approvals_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "approvals_whitelist_username": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "block_on_outdated_branch": true,
|
||||||
|
# "block_on_rejected_reviews": true,
|
||||||
|
# "branch_name": "string",
|
||||||
|
# "dismiss_stale_approvals": true,
|
||||||
|
# "enable_approvals_whitelist": true,
|
||||||
|
# "enable_merge_whitelist": true,
|
||||||
|
# "enable_push": true,
|
||||||
|
# "enable_push_whitelist": true,
|
||||||
|
# "enable_status_check": true,
|
||||||
|
# "merge_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "merge_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "protected_file_patterns": "string",
|
||||||
|
# "push_whitelist_deploy_keys": true,
|
||||||
|
# "push_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "push_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "require_signed_commits": true,
|
||||||
|
# "required_approvals": 0,
|
||||||
|
# "status_check_contexts": [
|
||||||
|
# "string"
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
def initialize(owner, repo, body={}, token=nil)
|
||||||
|
@owner = owner
|
||||||
|
@repo = repo
|
||||||
|
@body = body
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
response = post(url, params)
|
||||||
|
status, message, body = render_response(response)
|
||||||
|
json_format(status, message, body)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def params
|
||||||
|
Hash.new.merge(token: token, data: body)
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/repos/#{owner}/#{repo}/branch_protections".freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def json_format(status, message, body)
|
||||||
|
case status
|
||||||
|
when 201 then success(body)
|
||||||
|
else
|
||||||
|
error(message, status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Delete a specific branch protection for the repository
|
||||||
|
|
||||||
|
class Gitea::Repository::ProtectedBranches::DestroyService < Gitea::ClientService
|
||||||
|
attr_reader :owner, :repo, :name, :token
|
||||||
|
|
||||||
|
# owner: owner of the repo
|
||||||
|
# repo: name of the repo
|
||||||
|
# name: name of protected branch
|
||||||
|
# eg:
|
||||||
|
# Gitea::Repository::ProtectedBranches::DestroyService.call(user.login, repo.identifier, branch_name, user.gitea_token)
|
||||||
|
def initialize(owner, repo, name, token=nil)
|
||||||
|
@owner = owner
|
||||||
|
@repo = repo
|
||||||
|
@name = name
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
response = delete(url, params)
|
||||||
|
status, message = render_response(response)
|
||||||
|
json_format(status, message)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def params
|
||||||
|
Hash.new.merge(token: token, data: name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/repos/#{owner}/#{repo}/branch_protections/#{name}".freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def json_format(status, message)
|
||||||
|
case status
|
||||||
|
when 204 then success
|
||||||
|
when 404 then error(message, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Edit a branch protections for a repository. Only fields that are set will be changed
|
||||||
|
|
||||||
|
class Gitea::Repository::ProtectedBranches::UpdateService < Gitea::ClientService
|
||||||
|
attr_reader :owner, :repo, :name, :body, :token
|
||||||
|
|
||||||
|
# owner: owner of the repo
|
||||||
|
# repo: name of the repo
|
||||||
|
# nmae: name of protected branch
|
||||||
|
# body:
|
||||||
|
# {
|
||||||
|
# "approvals_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "approvals_whitelist_username": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "block_on_outdated_branch": true,
|
||||||
|
# "block_on_rejected_reviews": true,
|
||||||
|
# "branch_name": "string",
|
||||||
|
# "dismiss_stale_approvals": true,
|
||||||
|
# "enable_approvals_whitelist": true,
|
||||||
|
# "enable_merge_whitelist": true,
|
||||||
|
# "enable_push": true,
|
||||||
|
# "enable_push_whitelist": true,
|
||||||
|
# "enable_status_check": true,
|
||||||
|
# "merge_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "merge_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "protected_file_patterns": "string",
|
||||||
|
# "push_whitelist_deploy_keys": true,
|
||||||
|
# "push_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "push_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ],
|
||||||
|
# "require_signed_commits": true,
|
||||||
|
# "required_approvals": 0,
|
||||||
|
# "status_check_contexts": [
|
||||||
|
# "string"
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# eq:
|
||||||
|
# Gitea::Repository::ProtectedBranches::UpdateService.call(user.login, repo.identifier, branch_name, body, user.gitea_token)
|
||||||
|
def initialize(owner, repo, name, body, token=nil)
|
||||||
|
@owner = owner
|
||||||
|
@repo = repo
|
||||||
|
@name = name
|
||||||
|
@body = body
|
||||||
|
@token = token
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
response = patch(url, params)
|
||||||
|
status, message, body = render_response(response)
|
||||||
|
json_format(status, message, body)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def params
|
||||||
|
Hash.new.merge(token: token, data: body)
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"/repos/#{owner}/#{repo}/branch_protections/#{name}".freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def json_format(status, message, body)
|
||||||
|
case status
|
||||||
|
when 200 then success(body)
|
||||||
|
else
|
||||||
|
error(message, status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,7 +15,9 @@ class Gitea::Repository::SyncMirroredService < Gitea::ClientService
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
post(url, request_params)
|
response = post(url, request_params)
|
||||||
|
|
||||||
|
render_200_no_body(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -0,0 +1,266 @@
|
||||||
|
module ProtectedBranches
|
||||||
|
class BaseService < ApplicationService
|
||||||
|
attr_accessor :repository, :owner, :params
|
||||||
|
|
||||||
|
def initialize(repository, user = nil, params = {})
|
||||||
|
@repository, @owner, @params = repository, user, params.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
# delegate :repository, to: :project
|
||||||
|
|
||||||
|
def protected_branch_params
|
||||||
|
# {
|
||||||
|
# "approvals_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ], //批准团队(或审查团队)白名单
|
||||||
|
# "approvals_whitelist_username": [
|
||||||
|
# "string"
|
||||||
|
# ], // 批准用户(或审查者)白名单
|
||||||
|
# "block_on_outdated_branch": true, // 如果拉取过时,阻止合并
|
||||||
|
# "block_on_rejected_reviews": true, // 拒绝审核,阻止合并请求
|
||||||
|
# "branch_name": "string", //分支名称
|
||||||
|
# "dismiss_stale_approvals": true, // 取消过时的批准
|
||||||
|
# "enable_approvals_whitelist": true, //是否批准仅限列入白名单的用户或者团队, 主要用户pr的审核批准计数功能
|
||||||
|
# "enable_merge_whitelist": true, // 是否启用合并请求白名单
|
||||||
|
# "enable_push": true, //启用、禁止推送
|
||||||
|
# "enable_push_whitelist": true, // 是否启动推送白名单
|
||||||
|
# "enable_status_check": true, //是否启用状态检查
|
||||||
|
# "merge_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ], // 合并请求团队白名单
|
||||||
|
# "merge_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ], // 合并请求用户白名单
|
||||||
|
# "protected_file_patterns": "string", //保护文件模式
|
||||||
|
# "push_whitelist_deploy_keys": true, // 具有推送权限的部署密钥白名单
|
||||||
|
# "push_whitelist_teams": [
|
||||||
|
# "string"
|
||||||
|
# ], //推送团队白名单
|
||||||
|
# "push_whitelist_usernames": [
|
||||||
|
# "string"
|
||||||
|
# ], //推送用户白名单
|
||||||
|
# "require_signed_commits": true, //是否需要签名提交
|
||||||
|
# "required_approvals": 0, // 所需批准数
|
||||||
|
# "status_check_contexts": [
|
||||||
|
# "string"
|
||||||
|
# ] // 状态检查规则
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
# branch_name :string(255) default("")
|
||||||
|
# can_push :boolean default("0"), not null
|
||||||
|
# enable_whitelist :boolean default("0")
|
||||||
|
# whitelist_user_i_ds :text(65535)
|
||||||
|
# whitelist_team_i_ds :text(65535)
|
||||||
|
# enable_merge_whitelist :boolean default("0"), not null
|
||||||
|
# whitelist_deploy_keys :boolean default("0"), not null
|
||||||
|
# merge_whitelist_user_i_ds :text(65535)
|
||||||
|
# merge_whitelist_team_i_ds :text(65535)
|
||||||
|
# enable_status_check :boolean default("0"), not null
|
||||||
|
# status_check_contexts :text(65535)
|
||||||
|
# approvals_whitelist_user_i_ds :text(65535)
|
||||||
|
# approvals_whitelist_team_i_ds :text(65535)
|
||||||
|
# required_approvals :integer default("0")
|
||||||
|
# enable_approvals_whitelist :boolean default("0"), not null
|
||||||
|
# block_on_rejected_reviews :boolean default("0"), not null
|
||||||
|
# dismiss_stale_approvals :boolean default("0"), not null
|
||||||
|
# require_signed_commits :boolean default("0"), not null
|
||||||
|
# protected_file_patterns :text(65535)
|
||||||
|
# block_on_outdated_branch :boolean default("0"), not null
|
||||||
|
|
||||||
|
{
|
||||||
|
branch_name: params[:branch_name],
|
||||||
|
can_push: can_push_params,
|
||||||
|
enable_whitelist: enable_whitelist_params,
|
||||||
|
whitelist_user_i_ds: whitelist_user_i_ds_params,
|
||||||
|
# whitelist_team_i_ds: whitelist_team_i_ds_params,
|
||||||
|
enable_merge_whitelist: enable_merge_whitelist_params,
|
||||||
|
merge_whitelist_user_i_ds: merge_whitelist_user_i_ds_params,
|
||||||
|
# merge_whitelist_team_i_ds: merge_whitelist_team_i_ds_params,
|
||||||
|
enable_status_check: enable_status_check_params,
|
||||||
|
required_approvals: params[:required_approvals] || 0,
|
||||||
|
enable_approvals_whitelist: enable_approvals_whitelist_params,
|
||||||
|
approvals_whitelist_user_i_ds: approvals_whitelist_user_i_ds_params,
|
||||||
|
# approvals_whitelist_team_i_ds: approvals_whitelist_team_i_ds_params,
|
||||||
|
block_on_rejected_reviews: block_on_rejected_reviews_params,
|
||||||
|
dismiss_stale_approvals: dismiss_stale_approvals_params,
|
||||||
|
require_signed_commits: require_signed_commits_params,
|
||||||
|
block_on_outdated_branch: block_on_outdated_branch_params
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_status_check_params
|
||||||
|
params[:enable_status_check] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_approvals_whitelist_params
|
||||||
|
params[:enable_approvals_whitelist] || false
|
||||||
|
end
|
||||||
|
def block_on_rejected_reviews_params
|
||||||
|
params[:block_on_rejected_reviews] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def dismiss_stale_approvals_params
|
||||||
|
params[:dismiss_stale_approvals] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_signed_commits_params
|
||||||
|
params[:require_signed_commits] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def block_on_outdated_branch_params
|
||||||
|
params[:block_on_outdated_branch] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_push_params
|
||||||
|
return false if !can_push?
|
||||||
|
return true if enable_whitelist?
|
||||||
|
params[:enable_push]
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_whitelist_params
|
||||||
|
return false if !can_push?
|
||||||
|
params[:enable_push_whitelist]
|
||||||
|
end
|
||||||
|
|
||||||
|
def whitelist_user_i_ds_params
|
||||||
|
return [] if !can_push?
|
||||||
|
user_ids(get_push_whitelist_usernames)
|
||||||
|
end
|
||||||
|
|
||||||
|
def whitelist_team_i_ds_params
|
||||||
|
# params[:push_whitelist_usernames]
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_merge_whitelist_params
|
||||||
|
params[:enable_merge_whitelist] || false
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_whitelist_user_i_ds_params
|
||||||
|
returtn [] if !enable_merge_whitelist?
|
||||||
|
user_ids(get_merge_whitelist_usernames)
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_whitelist_team_i_ds_params
|
||||||
|
params[:merge_whitelist_teams]
|
||||||
|
end
|
||||||
|
|
||||||
|
def approvals_whitelist_user_i_ds_params
|
||||||
|
return [] if !enable_approvals_whitelist?
|
||||||
|
user_ids(get_approvals_whitelist_username)
|
||||||
|
end
|
||||||
|
|
||||||
|
def approvals_whitelist_team_i_ds_params
|
||||||
|
params[:approvals_whitelist_teams]
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_ids(names)
|
||||||
|
member_ids & names_by_params(names)
|
||||||
|
end
|
||||||
|
|
||||||
|
def member_ids
|
||||||
|
@repository.project.writable_members.map(&:user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def names_by_params(names)
|
||||||
|
User.where(login: names.to_a).ids
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_push_whitelist_usernames
|
||||||
|
return [] if !can_push? || !enable_whitelist?
|
||||||
|
filter_empty_element Array(params[:push_whitelist_usernames])
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_merge_whitelist_usernames
|
||||||
|
return [] if !enable_merge_whitelist?
|
||||||
|
filter_empty_element Array(params[:merge_whitelist_usernames])
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_approvals_whitelist_username
|
||||||
|
return [] if !enable_approvals_whitelist?
|
||||||
|
filter_empty_element Array(params[:approvals_whitelist_username])
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_users!(names)
|
||||||
|
names.each {|name|
|
||||||
|
check_user!(name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_user!(name)
|
||||||
|
user_exist = User.exists?(login: name)
|
||||||
|
raise Error, "user '#{name}' does not exist" if !user_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_push?
|
||||||
|
params[:enable_push] === true
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_whitelist?
|
||||||
|
params[:enable_push_whitelist] === true
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_merge_whitelist?
|
||||||
|
params[:enable_merge_whitelist] === true
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_approvals_whitelist?
|
||||||
|
params[:enable_approvals_whitelist] === true
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_empty_element(array)
|
||||||
|
array.reject { |e| e.to_s.empty? }
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_gitea_protected_branch!
|
||||||
|
@gitea_protected_branch ||= Gitea::Repository::ProtectedBranches::CreateService.call(@owner.login,
|
||||||
|
@repository.identifier,gitea_protected_branch_params, @owner.gitea_token)
|
||||||
|
|
||||||
|
raise Error, @gitea_protected_branch[:message] if @gitea_protected_branch[:status] != :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def gitea_protected_branch_saved?
|
||||||
|
@gitea_protected_branch[:status] === success
|
||||||
|
end
|
||||||
|
|
||||||
|
def gitea_protected_branch
|
||||||
|
@gitea_protected_branch[:body]
|
||||||
|
end
|
||||||
|
|
||||||
|
def gitea_protected_branch_params
|
||||||
|
{
|
||||||
|
approvals_whitelist_username: get_approvals_whitelist_username,
|
||||||
|
branch_name: params[:branch_name],
|
||||||
|
enable_approvals_whitelist: enable_approvals_whitelist_params,
|
||||||
|
enable_merge_whitelist: enable_merge_whitelist_params,
|
||||||
|
enable_push: can_push_params,
|
||||||
|
enable_push_whitelist: enable_whitelist_params,
|
||||||
|
enable_status_check: enable_status_check_params,
|
||||||
|
# merge_whitelist_teams: [],
|
||||||
|
merge_whitelist_usernames: get_merge_whitelist_usernames,
|
||||||
|
# protected_file_patterns: string,
|
||||||
|
# push_whitelist_deploy_keys: true,
|
||||||
|
# push_whitelist_teams: [],
|
||||||
|
push_whitelist_usernames: get_push_whitelist_usernames,
|
||||||
|
block_on_rejected_reviews: block_on_rejected_reviews_params,
|
||||||
|
dismiss_stale_approvals: dismiss_stale_approvals_params,
|
||||||
|
require_signed_commits: require_signed_commits_params,
|
||||||
|
block_on_outdated_branch: block_on_outdated_branch_params
|
||||||
|
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate!
|
||||||
|
protected_branch_exists = repository.protected_branches.exists?(params[:branch_name])
|
||||||
|
raise Error, "Protected branch '#{branch_name}' already exists" if protected_branch_exists
|
||||||
|
|
||||||
|
check_users!(get_push_whitelist_usernames) if get_push_whitelist_usernames.any?
|
||||||
|
check_users!(get_merge_whitelist_usernames) if get_merge_whitelist_usernames.any?
|
||||||
|
check_users!(get_approvals_whitelist_username) if get_approvals_whitelist_username.any?
|
||||||
|
|
||||||
|
raise Error, '分支名称不能为空' if params[:branch_name].blank?
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
module ProtectedBranches
|
||||||
|
class CreateService < ProtectedBranches::BaseService
|
||||||
|
def call
|
||||||
|
validate!
|
||||||
|
|
||||||
|
save_gitea_protected_branch!
|
||||||
|
|
||||||
|
save_protected_branch!
|
||||||
|
|
||||||
|
protected_branch
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def protected_branch
|
||||||
|
@protected_branch ||= repository.protected_branches.new(protected_branch_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_protected_branch!
|
||||||
|
protected_branch.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
module ProtectedBranches
|
||||||
|
class DestroyService < ProtectedBranches::BaseService
|
||||||
|
def call
|
||||||
|
protected_branch.destroy! if success?
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
raise Error, '404'
|
||||||
|
rescue => ex
|
||||||
|
Rails.logger.info ex
|
||||||
|
raise Error, ex
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def protected_branch
|
||||||
|
@protected_branch ||= @repository.protected_branches.find_by!(branch_name: @params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
result = Gitea::Repository::ProtectedBranches::DestroyService.call(@owner.login,
|
||||||
|
@repository.identifier, protected_branch.branch_name, @owner.gitea_token)
|
||||||
|
|
||||||
|
return true if result[:status] === :success
|
||||||
|
raise Error, result[:message]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,31 @@
|
||||||
|
module ProtectedBranches
|
||||||
|
class UpdateService < ProtectedBranches::BaseService
|
||||||
|
def call
|
||||||
|
validate!
|
||||||
|
protected_branch.update(protected_branch_params) if success?
|
||||||
|
|
||||||
|
protected_branch
|
||||||
|
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
raise Error, '404'
|
||||||
|
rescue => ex
|
||||||
|
Rails.logger.info ex
|
||||||
|
raise Error, ex
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def protected_branch
|
||||||
|
@protected_branch ||= @repository.protected_branches.find_by!(branch_name: params[:branch_name])
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
result = Gitea::Repository::ProtectedBranches::UpdateService.call(@owner.login, @repository.identifier,
|
||||||
|
protected_branch.branch_name, gitea_protected_branch_params, @owner.gitea_token)
|
||||||
|
|
||||||
|
|
||||||
|
return true if result[:status] === :success
|
||||||
|
raise Error, result[:message]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
json.branch_name protected_branch.branch_name
|
||||||
|
json.enable_push protected_branch.can_push
|
||||||
|
json.required_approvals protected_branch.required_approvals
|
||||||
|
json.enable_status_check protected_branch.enable_status_check
|
||||||
|
json.enable_push_whitelist protected_branch.enable_whitelist
|
||||||
|
json.enable_merge_whitelist protected_branch.enable_merge_whitelist
|
||||||
|
json.enable_approvals_whitelist protected_branch.enable_approvals_whitelist
|
||||||
|
json.dismiss_stale_approvals protected_branch.dismiss_stale_approvals
|
||||||
|
json.block_on_rejected_reviews protected_branch.block_on_rejected_reviews
|
||||||
|
json.block_on_outdated_branch protected_branch.block_on_outdated_branch
|
||||||
|
json.require_signed_commits protected_branch.require_signed_commits
|
||||||
|
json.merge_whitelist_usernames protected_branch.merge_whitelist_usernames
|
||||||
|
json.push_whitelist_usernames protected_branch.push_whitelist_usernames
|
||||||
|
json.approvals_whitelist_usernames protected_branch.approvals_whitelist_usernames
|
||||||
|
json.created_at protected_branch.created_at.strftime("%Y-%m-%d %H:%M")
|
||||||
|
json.updated_at protected_branch.updated_at.strftime("%Y-%m-%d %H:%M")
|
|
@ -0,0 +1 @@
|
||||||
|
json.partial! @protected_branch, as: :protected_branch
|
|
@ -0,0 +1,2 @@
|
||||||
|
json.total_count @total_count
|
||||||
|
json.protected_branches @protected_branches, partial: 'protected_branches/protected_branch', as: :protected_branch
|
|
@ -0,0 +1 @@
|
||||||
|
json.partial! @protected_branch, as: :protected_branch
|
|
@ -19,6 +19,10 @@ module Educoderplus
|
||||||
#
|
#
|
||||||
# config.educoder = config_for(:configuration)
|
# config.educoder = config_for(:configuration)
|
||||||
|
|
||||||
|
# Custom directories with classes and modules you want to be autoloadable.
|
||||||
|
# config.eager_load_paths << Rails.root.join('lib')
|
||||||
|
config.eager_load_paths += %W(#{config.root}/lib)
|
||||||
|
|
||||||
config.active_record.default_timezone = :utc
|
config.active_record.default_timezone = :utc
|
||||||
config.time_zone = 'Beijing'
|
config.time_zone = 'Beijing'
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,34 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# protected_branches
|
||||||
|
scope do
|
||||||
|
# get ':protected_branches/:action/:id/:user_id', constraints: { branch_name: Forgeplus::Regex.git_reference_regex }
|
||||||
|
# post '/protected_branches' => 'protected_branches#create'
|
||||||
|
# delete '/protected_branches/:branch_name' => 'protected_branches#destroy',
|
||||||
|
# constraints: { branch_name: Forgeplus::Regex.git_reference_regex }
|
||||||
|
# patch '/protected_branches/:branch_name' => 'protected_branches#update',
|
||||||
|
# constraints: { branch_name: Forgeplus::Regex.git_reference_regex }
|
||||||
|
get(
|
||||||
|
'/protected_branches/',
|
||||||
|
to: 'protected_branches#index'
|
||||||
|
)
|
||||||
|
delete(
|
||||||
|
'/protected_branches/:branch_name',
|
||||||
|
to: 'protected_branches#destroy',
|
||||||
|
constraints: { branch_name: Forgeplus::Regex.git_reference_regex }
|
||||||
|
)
|
||||||
|
post(
|
||||||
|
'/protected_branches',
|
||||||
|
to: 'protected_branches#create'
|
||||||
|
)
|
||||||
|
patch(
|
||||||
|
'/protected_branches/:branch_name',
|
||||||
|
to: 'protected_branches#update',
|
||||||
|
constraints: { branch_name: Forgeplus::Regex.git_reference_regex }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
resources :issues do
|
resources :issues do
|
||||||
collection do
|
collection do
|
||||||
get :commit_issues
|
get :commit_issues
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
class CreateProtectedBranches < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table :protected_branches do |t|
|
||||||
|
t.integer :repo_id
|
||||||
|
t.string :branch_name, default: ""
|
||||||
|
t.boolean :can_push, default: false, null: false
|
||||||
|
t.boolean :enable_whitelist, default: false
|
||||||
|
t.text :whitelist_user_i_ds
|
||||||
|
t.text :whitelist_team_i_ds
|
||||||
|
t.boolean :enable_merge_whitelist, default: false, null: false
|
||||||
|
t.boolean :whitelist_deploy_keys, default: false, null: false
|
||||||
|
t.text :merge_whitelist_user_i_ds
|
||||||
|
t.text :merge_whitelist_team_i_ds
|
||||||
|
t.boolean :enable_status_check, default: false, null: false
|
||||||
|
t.text :status_check_contexts
|
||||||
|
t.text :approvals_whitelist_user_i_ds
|
||||||
|
t.text :approvals_whitelist_team_i_ds
|
||||||
|
t.integer :required_approvals, default: 0
|
||||||
|
t.boolean :enable_approvals_whitelist, default: false, null: false
|
||||||
|
t.boolean :block_on_rejected_reviews, default: false, null: false
|
||||||
|
t.boolean :dismiss_stale_approvals, default: false, null: false
|
||||||
|
t.boolean :require_signed_commits, default: false, null: false
|
||||||
|
t.text :protected_file_patterns
|
||||||
|
t.boolean :block_on_outdated_branch, default: false, null: false
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :protected_branches, :repo_id
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,40 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe ProtectedBranchesController, type: :controller do
|
||||||
|
|
||||||
|
describe "GET #index" do
|
||||||
|
it "returns http success" do
|
||||||
|
get :index
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET #create" do
|
||||||
|
it "returns http success" do
|
||||||
|
get :create
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET #edit" do
|
||||||
|
it "returns http success" do
|
||||||
|
get :edit
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET #update" do
|
||||||
|
it "returns http success" do
|
||||||
|
get :update
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET #destroy" do
|
||||||
|
it "returns http success" do
|
||||||
|
get :destroy
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
# Specs in this file have access to a helper object that includes
|
||||||
|
# the ProtectedBranchesHelper. For example:
|
||||||
|
#
|
||||||
|
# describe ProtectedBranchesHelper do
|
||||||
|
# describe "string concat" do
|
||||||
|
# it "concats two strings with spaces" do
|
||||||
|
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
RSpec.describe ProtectedBranchesHelper, type: :helper do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe ProtectedBranch, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "protected_branches/create.html.erb", type: :view do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "protected_branches/destroy.html.erb", type: :view do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "protected_branches/edit.html.erb", type: :view do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "protected_branches/index.html.erb", type: :view do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "protected_branches/update.html.erb", type: :view do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
Loading…
Reference in New Issue