diff --git a/.trustie-pipeline.yml b/.trustie-pipeline.yml new file mode 100644 index 00000000..8f326548 --- /dev/null +++ b/.trustie-pipeline.yml @@ -0,0 +1,22 @@ +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: install + image: ruby:2.4.5 + commands: + - gem install bundler + - bundle -v + - bundle install --jobs=1 --retry=1 + +- name: test + image: ruby:2.4.5 + volumes: + - name: bundle + path: /usr/local/bundle + commands: + - rake diff --git a/Gemfile b/Gemfile index 491b512c..cd6c4b91 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,6 @@ source 'https://gems.ruby-china.com' git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby '2.3.7' - gem 'rails', '~> 5.2.0' gem 'mysql2', '>= 0.4.4', '< 0.6.0' gem 'puma', '~> 3.11' @@ -19,8 +17,6 @@ gem 'kaminari', '~> 1.1', '>= 1.1.1' gem 'bootsnap', '>= 1.1.0', require: false -gem 'gitlab', path: 'lib/gitlab-cli' - gem 'chinese_pinyin' gem 'rack-cors' @@ -74,6 +70,7 @@ group :development do gem 'listen', '>= 3.0.5', '< 3.2' gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' + gem "annotate", "~> 2.6.0" end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index c67bcd22..a6beea40 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -PATH - remote: lib/gitlab-cli - specs: - gitlab (3.2.0) - httparty - terminal-table - GEM remote: https://gems.ruby-china.com/ specs: @@ -61,6 +54,9 @@ GEM public_suffix (>= 2.0.2, < 5.0) ancestry (3.0.7) activerecord (>= 3.2.0) + annotate (2.6.5) + activerecord (>= 2.3.0) + rake (>= 0.8.7) archive-zip (0.12.0) io-like (~> 0.3.0) arel (9.0.0) @@ -138,9 +134,6 @@ GEM harmonious_dictionary (0.0.1) hashie (3.6.0) htmlentities (4.3.4) - httparty (0.18.0) - mime-types (~> 3.0) - multi_xml (>= 0.5.2) i18n (1.8.2) concurrent-ruby (~> 1.0) io-like (0.3.1) @@ -177,9 +170,6 @@ GEM mimemagic (~> 0.3.2) maruku (0.7.3) method_source (0.9.2) - mime-types (3.3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2019.1009) mimemagic (0.3.4) mini_mime (1.0.2) mini_portile2 (2.4.0) @@ -402,8 +392,6 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) thor (1.0.1) thread_safe (0.3.6) tilt (2.0.10) @@ -437,6 +425,7 @@ DEPENDENCIES acts-as-taggable-on (~> 6.0) acts_as_list ancestry + annotate (~> 2.6.0) awesome_print axlsx (~> 3.0.0.pre) axlsx_rails (~> 0.5.2) @@ -452,7 +441,6 @@ DEPENDENCIES enumerize faraday (~> 0.15.4) font-awesome-sass (= 4.7.0) - gitlab! grape-entity (~> 0.7.1) groupdate (~> 4.1.0) harmonious_dictionary (~> 0.0.1) @@ -502,8 +490,5 @@ DEPENDENCIES web-console (>= 3.3.0) wkhtmltopdf-binary -RUBY VERSION - ruby 2.3.7p456 - BUNDLED WITH 2.1.4 diff --git a/README.md b/README.md index 8450de92..8f5a897e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,15 @@ +Trustie (确实)是一个以大众化协同开发、开放式资源共享、持续性可信评估为核心机理,面向高校创新实践的在线协作平台。 + +## 特性 + +- 软件创作与生产深度融合的软件开发环境体系结构 软件自由创作和工程生产的高效衔接,适于软件开发中群体智慧的有效汇聚。 + +- 构件化协同开发环境的可扩展运行框架多样化工具的集成和联动,形成了强动态扩展能力的平台框架。 + +- “互联网即资源库”的全新软件复用模式 成长式软件资源管理系统,实现了分散资源的知识融合、资源的可持续增长和有效复用。 + +## 部署 -# 本地开发部署步骤 ### 1. 安装依赖包 @@ -20,7 +30,7 @@ touch config/elasticsearch.yml ### 3. 配置gitea服务(可选) **如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** -**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/6070/coders** +**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary #### 配置gitea服务步骤 1. 部署gitea服务,并注册root账户 @@ -79,4921 +89,37 @@ http://localhost:3000/ ``` ---- +## 页面展示 +- 代码库 -# API文档 +![](docs/figs/code.png) -## 基本介绍 -### 开发API服务地址: +- 任务管理 +![](docs/figs/issue_manage.png) -**https://testgitea.trustie.net/** +- 任务查看 +![](docs/figs/issue_view.png) -响应状态说明: +- 任务指派 -|字段|类型|说明| -|-|-|-| -|status |int |响应状态码,0:请求成功,-1: 请求失败| -|message |string |响应说明 | +![](docs/figs/issue_assign2.png) +- 里程碑 -### API接口 ---- +![](docs/figs/milestone.png) -#### 用户注册(通过其他平台) -``` -POST accounts/remote_register -``` -*示例* -``` -curl -X POST \ --d "email=2456233122@qq.com" \ --d "password=djs_D_00001" \ --d "username=16895620" \ --d "platform=forge" \ -http://localhost:3000/api/accounts/remote_register | jq -``` -*请求参数说明:* +### API +- [API](api_document.md) -|参数名|必选|类型|说明| -|-|-|-|-| -|email |是|string |邮箱 | -|username |是|string |登录名 | -|password |是|string |秘密 | -|platform |否|string |用户来源的相关平台,取值范围['educoder', 'trustie', 'forge'], 默认值为forge | +## 贡献代码 +1. Fork 项目 +2. 创建本地分支(git checkout -b my-new-feature) +3. 提交更改 (git commit -am 'Add some feature') +4. 推送到分支 (git push origin my-new-feature) +5. 向源项目的 **develop** 分支发起 Pull Request -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|user|json object |返回数据| -|-- id |int |用户id | -|-- token |string|用户token| - - -返回值 -``` -{ - "status": 0, - "message": "success", - "user": { - "id": 36400, - "token": "8c87a80d9cfacc92fcb2451845104f35119eda96" - } -} -``` ---- - -#### 获取当前登录用户信息 -``` -GET api/users/me -``` -*示例* -``` -curl -X GET http://localhost:3000/api/users/me | jq -``` - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|user_id |int |用户id | -|username |string|用户名称| -|admin |boolean|是否为管理用户| -|login |string|登录名| -|image_url |string|用户头像| - - -返回值 -``` -{ - "username": "18816895620", - "login": "18816895620", - "user_id": 36401, - "image_url": "avatars/User/b", - "admin": false -} -``` ---- - -#### 用户列表(带搜索功能) -``` -GET api/users/list -``` -*示例* -``` -curl -X GET \ --d "limit=10" \ --d "search=18816895620" -http://localhost:3000/api/users/list | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|page |否|int |页数,第几页 | -|limit |否|int |每页多少条数据,默认15条 | -|search |否|string |用户名、登录名匹配搜索 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count |int |总用户条数 | -|users |array| | -|-- username |string|用户全名| -|-- login |string|用户登录名| -|-- user_id |int|用户id| -|-- image_url |string|用户头像| - -返回值 -``` -{ - "total_count": 1, - "users": [ - { - "username": "18816895620", - "login": "18816895620", - "user_id": 36401, - "image_url": "avatars/User/b" - } - ] -} -``` ---- - -#### 获取项目类别列表(可根据名称搜素) -``` -GET api/project_categories -``` -*示例* -``` -curl -X GET \ --d "name=大数据" \ -http://localhost:3000/api/project_categories/ | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|name |否|string |类别名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|project_categories|array |返回数据| -|-- id |int |类别id | -|-- name |string|类别名称| - - -返回值 -``` -{ - "project_categories": [ - { - "id": 1, - "name": "大数据" - } - ] -} -``` ---- - -#### 获取项目语言列表(可根据名称搜素) -``` -GET api/project_languages -``` -*示例* -``` -curl -X GET \ --d "name=Ruby" \ -http://localhost:3000/api/project_languages/ | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|name |否|string |类别名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|project_languages|array |返回数据| -|-- id |int |语言id | -|-- name |string|语言名称| - - -返回值 -``` -{ - "project_languages": [ - { - "id": 1, - "name": "Ruby" - } - ] -} -``` ---- - -#### 获取.gitignore模板列表(可根据名称搜素) -``` -GET api/ignores -``` -*示例* -``` -curl -X GET \ --d "name=Ada" \ -http://localhost:3000/api/ignores/ | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|name |否|string |gitignore名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|ignores|array |返回数据| -|-- id |int |id | -|-- name |string|gitignore名称| - - -返回值 -``` -{ - "ignores": [ - { - "id": 1, - "name": "Ada" - } - ] -} -``` ---- - -#### 获取开源许可证列表(可根据名称搜素) -``` -GET api/licenses -``` -*示例* -``` -curl -X GET \ --d "name=AFL" \ -http://localhost:3000/api/licenses/ | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|name |否|string |开源许可证名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|licenses|array |返回数据| -|-- id |int |id | -|-- name |string|开源许可证名称| - - -返回值 -``` -{ - "licenses": [ - { - "id": 57, - "name": "AFL-1.2" - }, - { - "id": 76, - "name": "AFL-3.0" - }, - { - "id": 214, - "name": "AFL-1.1" - }, - { - "id": 326, - "name": "AFL-2.1" - }, - { - "id": 350, - "name": "AFL-2.0" - } - ] -} -``` ---- - -#### 创建项目 -``` -POST api/projects -``` -*示例* -``` -curl -X POST \ --d "user_id=36401" \ --d "name=hnfl_demo" \ --d "description=my first project" \ --d "repository_name=hnfl_demo" \ --d "project_category_id=1" \ --d "project_language_id=2" \ --d "ignore_id=2" \ --d "license_id=1" \ -http://localhost:3000/api/projects/ | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|user_id |是|int |用户id或者组织id | -|name |是|string |项目名称 | -|description |是|string |项目描述 | -|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | -|project_category_id|是|int |项目类别id | -|project_language_id|是|int |项目语言id | -|ignore_id |否|int |gitignore相关id | -|license_id |否|int |开源许可证id | -|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |id | -|name |string|项目名称| - - -返回值 -``` -{ - "id": 3240, - "name": "好项目" -} -``` ---- - -#### 新建镜像项目 -``` -POST api/projects/migrate -``` -*示例* -``` -curl -X POST \ --d "user_id=36408" \ --d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ --d "name=golden_mirror1" \ --d "description=golden_mirror" \ --d "repository_name=golden_mirror1" \ --d "project_category_id=1" \ --d "project_language_id=2" \ -http://localhost:3000/api/projects/migrate.json?debug=admin | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|user_id |是|int |用户id或者组织id | -|name |是|string |项目名称 | -|clone_addr |是|string |镜像项目clone地址 | -|description |否|string |项目描述 | -|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | -|project_category_id|是|int |项目类别id | -|project_language_id|是|int |项目语言id | -|is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | -|auth_username |否|string|镜像源仓库的登录用户名 | -|auth_password |否|string|镜像源仓库的登录秘密 | -|private |否|boolean|项目是否私有, true:为私有,false: 非私有,默认为公开 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |id | -|name |string|项目名称| - - -返回值 -``` -{ - "id": 3263, - "name": "ni项目" -} -``` - ---- -#### 手动同步镜像 -``` -POST api/repositories/:id/sync_mirror -``` -*示例* -``` -curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |仓库id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int |状态码, 0:标识请求成功 | -|message |string|服务端返回的信息说明| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` - ---- - -#### 项目详情 -``` -GET /api/:namespace_id/:id -``` -*示例* -``` -curl -X GET http://localhost:3000/api/jasder/jasder_test | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|namespace_id |是|string |用户登录名 | -|id |是|string |项目标识identifier | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |id | -|name |string|项目名称| -|identifier |string|项目标识| -|is_public |boolean|项目是否公开, true:公开,false:私有| -|description |string|项目简介| -|repo_id |int|仓库id| -|repo_identifier|string|仓库标识| - - -返回值 -``` -{ - "name": "ni项目", - "identifier": "mirror_demo", - "is_public": true, - "description": "my first project mirror_demo", - "repo_id": 75073, - "repo_identifier": "mirror_demo" -} -``` ---- - -#### 项目详情(简版) -``` -GET /api/:namespace_id/:id/simple -``` -*示例* -``` -curl -X GET http://localhost:3000/api/jasder/jasder_test/simple | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |id | -|name |string|项目名称| -|identifier |string|项目标识| -|is_public |boolean|项目是否公开, true:公开,false:私有| -|description |string|项目简介| -|repo_id |int|仓库id| -|repo_identifier|string|仓库标识| - - -返回值 -``` -{ - "identifier": "jasder_test", - "name": "jasder的测试项目", - "id": 4967, - "type": 0, - "author": { - "login": "jasder", - "name": "姓名", - "image_url": "avatars/User/b" - } -} -``` ---- - -#### 编辑仓库信息 -``` -GET /api/repositories/:id/edit.json -``` -*示例* -``` -curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq -``` - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|identifier |string |仓库标识 | -|project_id |int|项目id| -|project_name |string|项目名称| -|project_identifier |string|项目标识| -|project_description |string|项目简介| -|project_category_id |int|项目类别id| -|project_language_id |int|项目语言id| -|private |boolean|项目是否私有, true:为私有,false: 公开 | - - -返回值 -``` -{ - "identifier": "mirror_demo", - "project_id": 3263, - "project_name": "ni项目", - "project_identifier": "mirror_demo", - "project_description": "my first project mirror_demo", - "project_category_id": 1, - "project_language_id": 2, - "private": false -} -``` ---- - -#### 修改项目信息 -``` -PATCH api/projects/:id -``` -*示例* -``` -curl -X PATCH \ --d "name=hnfl_demo" \ --d "description=my first project" \ --d "project_category_id=1" \ --d "project_language_id=2" \ --d "private=true" \ -http://localhost:3000/api/projects/3263.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|name |否|string |项目名称 | -|description |否|string |项目描述 | -|project_category_id|否|int |项目类别id | -|project_language_id|否|int |项目语言id | -|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int|id | -|identifier |string|项目标识| -|name |string|项目名称| -|description |string|项目简介| -|project_category_id|int|项目类别id| -|project_language_id|int|项目语言id| -|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | - - -返回值 -``` -{ - "id": 3263, - "identifier": "mirror_demo", - "name": "hnfl_demo", - "description": "my first project", - "project_category_id": 1, - "project_language_id": 2, - "is_public": true -} -``` ---- - -#### 删除项目 -``` -DELETE api/projects/:id -``` -*示例* -``` -curl -X DELETE http://localhost:3000/api/projects/3263.json | jq -``` - -注:只有超级管理员和项目拥有者才能删除仓库 - -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|返回状态, 0: 表示操作成功 | -|message |string|返回信息说明| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -#### 项目添加成员 -``` -POST api/projects/:id/members -``` -*示例* -``` -curl -X POST \ --d "user_id=36406" \ -http://localhost:3000/api/projects/3297/members | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|user_id |是|int |用户id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int |0:添加成功, -1: 添加失败, 1: 表示已经是项目成员 | -|message |string|返回信息说明| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -#### 项目删除成员 -``` -DELETE api/projects/:id/members/remove -``` -*示例* -``` -curl -X DELETE \ --d "user_id=36400" \ -http://localhost:3000/api/projects/3263/members/remove | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|user_id |是|int |用户id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int |0:移除成功, -1: 移除失败, 1: 表示还不是项目成员 | -|message |string|返回信息说明| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -#### 更改项目成员角色/权限 -``` -PUT api/projects/:id/members/change_role -``` -*示例* -``` -curl -X PUT \ --d "user_id=36400" \ --d "role=Developer" \ -http://localhost:3000/api/projects/3263/members/change_role | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|user_id |是|int |用户id | -|role |是|string |取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限) | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int |0:角色更改成功, -1: 更改失败失败, 1: 表示还不是项目成员 | -|message |string|返回信息说明| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - - -#### 项目成员列表 -``` -GET api/projects/:id/members -``` -*示例* -``` -curl -X GET \ --d "page=1" \ --d "limit=5" \ -http://localhost:3000/api/projects/3263/members | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|page |否|string |页数,第几页 | -|limit |否|string |每页多少条数据,默认15条 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count |int |返回记录总条数 | -|members |array|项目成员信息| -|-- id |int|用户id| -|-- name |string|用户名称| -|-- login |string|用户登录名/标识| -|-- image_url |string|用户头像| -|-- is_owner |boolean|是否是项目的拥有者,true:是, false:不是| -|-- role |string|该用户在项目中的角色, Manager: 管理员(拥有操作权限); Developer:开发人员(只拥有读写权限); Reporter:报告人员(只拥有读权限)| - - -返回值 -``` -{ - "total_count": 2, - "members": [ - { - "id": 36401, - "name": "18816895620", - "login": "18816895620", - "image_url": "avatars/User/b", - "is_owner": true, - "role": "Manager" - }, - { - "id": 36399, - "name": "18816365620", - "login": "18816365620", - "image_url": "avatars/User/b", - "is_owner": false, - "role": "Developer" - } - ] -} -``` ---- - -#### Fork项目 -``` -POST /api/projects/:project_id/forks -``` -*示例* -``` -curl -X POST http://localhost:3000/api/projects/3297/forks | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|project_id |是|int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |项目id | -|identifier |string|项目标识| - - -返回值 -``` -{ - "id": 3290, - "identifier": "newadm" -} -``` ---- - -#### 获取代码目录列表 -``` -POST /api/:namespace_id/:project_id/repository/entries -``` -*示例* -``` -curl -X GET \ --d "ref=develop" \ -http://localhost:3000//api/jasder/jasder_test/repository/entries | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|last_commit |object | | -|-- commit |object | | -|id |int |id | -|name |string|文件夹或文件名称| -|path |string|文件夹或文件相对路径| -|type |string|文件类型, file:文件,dir:文件目录| -|size |int|文件夹或文件大小 单位B| -|content |string|文件内容,| -|target |string|标签| - -返回值 -``` -{ - "last_commit": { - "commit": { - "sha": "3f2de4f78d2d7050486535082cd11cdfc9f3679e", - "url": "http://localhost:3003//api/repositories/api-cloud-platform/commits/3f2de4f78d2d7050486535082cd11cdfc9f3679e", - "message": "update README.md.", - "author": { - "name": "Gitee", - "email": "noreply@gitee.com", - "date": "2020-03-02T20:23:18+08:00" - }, - "committer": { - "name": "Gitee", - "email": "noreply@gitee.com", - "date": "2020-03-02T20:23:18+08:00" - }, - "timestamp": 1583151798, - "time_from_now": "3个月前" - }, - "author": null, - "committer": null - }, - "entries": [ - { - "name": "ace-gate", - "path": "ace-gate", - "sha": "c83f85fc63b14edcd6fc502eee9996f5a9993eca", - "type": "dir", - "size": 0, - "content": null, - "target": null, - "commit": { - "message": "v2.9 升级alibaba组件release版本\n", - "sha": "6117eaab86f71115f42f2a46ff1683015cda798d", - "created_at": "1970-01-01 08:00", - "time_from_now": "51年前", - "created_at_unix": null - } - }, - { - "name": "ace-sidecar", - "path": "ace-sidecar", - "sha": "38e41d7810876b464f8f1adcbf998e1b04f710a7", - "type": "dir", - "size": 0, - "content": null, - "target": null, - "commit": { - "message": "[Feature] 升级spring 版本&consul注册中心\n", - "sha": "c0a5dde35cfc87f7dbaf676aac397b184ba0e55b", - "created_at": "1970-01-01 08:00", - "time_from_now": "51年前", - "created_at_unix": null - } - }, - ... - ] -} -``` ---- - -#### 获取子目录代码列表/编辑某个具体的文件 -``` -GET /api/repositories/:id/sub_entries -``` -*示例* -``` -curl -X GET \ --d "ref=master" \ --d "filepath=test1_create_file.rb" \ -http://localhost:3000/api/repositories/87/sub_entries.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|filepath |是|string |文件夹、文件的相对路径 | -|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |id | -|name |string|文件夹或文件名称| -|path |string|文件夹或文件相对路径| -|type |string|文件类型, file:文件,dir:文件目录| -|size |int|文件夹或文件大小 单位KB| -|content |string|文件内容,| -|target |string|标签| -|url |string|文件访问链接,带分支| -|html_url |string|文件访问链接,未标识分支| -|git_url |string|文件夹或文件的git仓库访问链接| -|download_url |string|文件下载、文件内容访问链接| - -返回值 -``` -[ - { - "name": "build.rc", - "path": "lib/build.rc", - "type": "", - "size": 1268, - "content": null, - "target": null, - "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/build.rc?ref=master", - "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/build.rc", - "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/191fcf1a63b3777e2977fcede7dd5309efdd70fe", - "download_url": null - }, - { - "name": "cfg.rc", - "path": "lib/cfg.rc", - "type": "file", - "size": 107, - "content": null, - "target": null, - "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/cfg.rc?ref=master", - "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/cfg.rc", - "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/0b91ba0ed1c00e130c77bb9058af3787fea986a0", - "download_url": "http://localhost:3003/18816895620/mirror_demo/raw/branch/master/lib/cfg.rc" - }, - { - "name": "fn", - "path": "lib/fn", - "type": "dir", - "size": 0, - "content": null, - "target": null, - "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/fn?ref=master", - "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/fn", - "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/e33bd45949ef8f804471d0b6b2c59728eb445989", - "download_url": null - } -] -``` ---- - -#### 项目类别列表(用于项目列表左侧导航中的项目类别列表) -``` -GET api/project_categories/group_list -``` -*示例* -``` -curl -X GET http://localhost:3000/api/project_categories/group_list | jq -``` - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|id |int |项目分类id | -|name |string|项目分类名称| -|projects_count |int |项目数量| - - -返回值 -``` -[ - { - "id": 1, - "name": "大数据", - "projects_count": 30 - }, - { - "id": 2, - "name": "机器学习", - "projects_count": 1 - }, - { - "id": 3, - "name": "深度学习", - "projects_count": 1 - } -] -``` ---- - -#### 项目类型列表(用于项目列表左侧导航上方中的项目类型列表) -``` -GET api/projects/group_type_list -``` -*示例* -``` -curl -X GET http://localhost:3000/api/projects/group_type_list | jq -``` - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|project_type |string|项目类型 | -|name |string|项目类型名称| -|projects_count |int |项目数量| - - -返回值 -``` -[ - { - "project_type": "common", - "name": "开源托管项目", - "projects_count": 2106 - }, - { - "project_type": "mirror", - "name": "开源镜像项目", - "projects_count": 1 - } -] -``` ---- - -#### 项目列表 -``` -GET api/projects -``` -*示例* -``` -curl -X GET \ --d "page=1" \ --d "limit=5" \ -http://localhost:3000/api/projects | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|page |否|string |页数,第几页 | -|limit |否|string |每页多少条数据,默认15条 | -|sort_by |否|string |排序类型, 取值:updated_on \| created_on \| forked_count \| praises_count, updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | -|sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为:desc | -|search |否|string |按照项目名称搜索 | -|category_id |否|int |项目类别id | -|language_id |否|int |项目语言id | -|project_type |否|string |项目类型, 取值为:common \| mirror; common:开源托管项目, mirror:开源镜像项目 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count |int |项目总条数 | -|id |string |项目id | -|name |string|项目名称| -|description |string|项目简介| -|visits |int|流量数| -|forked_count |int|被fork的数量| -|praises_count |int|star数量| -|is_public |boolean|是否公开, true:公开,false:未公开| -|mirror_url |string|镜像url| -|last_update_time|int|最后更新时间,为UNIX格式的时间戳| -|author |object|项目创建者| -|-- name |string|用户名,也是用户标识| -|category |object|项目类别| -|-- id |int|项目类型id| -|-- name |string|项目类型名称| -|language |object|项目语言| -|-- id |int|项目语言id| -|-- name |string|项目语言名称| - - -返回值 -``` -{ - "total_count": 3096, - "projects": [ - { - "id": 1, - "name": "hnfl_demo1", - "description": "my first project", - "visits": 0, - "praises_count": 0, - "forked_count": 0, - "is_public": true, - "mirror_url": null, - "last_update_time": 1577697461, - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - }, - "category": { - "id": 1, - "name": "大数据" - }, - "language": { - "id": 2, - "name": "C" - } - }, - { - "id": 2, - "name": "hnfl_demo", - "description": "my first project", - "visits": 0, - "praises_count": 0, - "forked_count": 0, - "is_public": true, - "mirror_url": null, - "last_update_time": 1577697403, - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - }, - "category": { - "id": 1, - "name": "大数据" - }, - "language": { - "id": 2, - "name": "C" - } - }, - { - "id": 3, - "name": "统计局", - "description": "my first project", - "visits": 0, - "praises_count": 0, - "forked_count": 0, - "is_public": true, - "mirror_url": null, - "last_update_time": 1577415173, - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - }, - "category": { - "id": 1, - "name": "大数据" - }, - "language": { - "id": 2, - "name": "C" - } - }, - { - "id": 5, - "name": "开源同名", - "description": "my first project", - "visits": 0, - "praises_count": 0, - "forked_count": 0, - "is_public": false, - "mirror_url": "https://gitea.com/CasperVector/slew.git", - "last_update_time": 1577346228, - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - }, - "category": { - "id": 1, - "name": "大数据" - }, - "language": { - "id": 2, - "name": "C" - } - }, - { - "id": 7, - "name": "开源支持", - "description": "my first project", - "visits": 0, - "praises_count": 0, - "forked_count": 0, - "is_public": true, - "mirror_url": null, - "last_update_time": 1577341572, - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - }, - "category": { - "id": 1, - "name": "大数据" - }, - "language": { - "id": 2, - "name": "C" - } - } - ] -} -``` ---- - -### 获取分支列表 -``` -GET /api/:namespace_id/:id/branches -``` -*示例* -``` -curl -X GET http://localhost:3000/api/jasder/jasder_test/branches | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|id |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|name |string|分支名称| -|user_can_push |boolean|用户是否可push| -|user_can_merge |boolean|用户是否客merge| -|protected |boolean|是否为保护分支| -|http_url |boolean|http链接| -|zip_url |boolean|zip包下载链接| -|tar_url |boolean|tar.gz下载链接| -|last_commit |object|最后提交记录| -|-- id |string|提交记录id| -|-- message |string|提交的说明信息| -|-- timestamp |int|提交时间,为UNIX时间戳| -|-- time_from_now|string|转换后的时间| -|author |object|提交用户| -|-- login |string|用户名称| -|-- image_url |string|用户头像| - - -返回值 -``` -[ - { - "name": "develop", - "user_can_push": true, - "user_can_merge": true, - "protected": false, - "http_url": "http://localhost:3003/18816895620/mirror_demo.git", - "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", - "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", - "last_commit": { - "id": "735674d6696bddbafa993db9c67b40c41246c77f", - "message": "FIX test branch content\n", - "timestamp": 1577694074, - "time_from_now": "1天前" - }, - "author": { - "login": "18816895620", - "image_url": "avatars/User/b" - } - }, - { - "name": "master", - "user_can_push": true, - "user_can_merge": true, - "protected": false, - "http_url": "http://localhost:3003/18816895620/mirror_demo.git", - "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", - "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", - "last_commit": { - "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", - "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", - "timestamp": 1577244567, - "time_from_now": "6天前" - }, - "author": { - "login": "18816895620", - "image_url": "avatars/User/b" - } - } -] -``` ---- - -### 获取代码库标签列表 -``` -GET /api/repositories/:id/tags -``` -*示例* -``` -curl -X GET \ --d "limit=20" \ --d "page=1" \ -http://localhost:3000/api/repositories/5836/tags.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |仓库id | -|page |否|string |页数,第几页 | -|limit |否|string |每页多少条数据,默认20条 | - - -*返回参数说明:* - -|参数名|类型|说明| --|-|- -|name |string|分支名称| -|user_can_push |boolean|用户是否可push| -|user_can_merge |boolean|用户是否客merge| -|protected |boolean|是否为保护分支| -|http_url |boolean|http链接| -|zip_url |boolean|zip包下载链接| -|tar_url |boolean|tar.gz下载链接| -|last_commit |object|最后提交记录| -|-- id |string|提交记录id| -|-- message |string|提交的说明信息| -|-- timestamp |int|提交时间,为UNIX时间戳| -|-- time_from_now|string|转换后的时间| -|author |object|提交用户| -|-- login |string|用户名称| -|-- image_url |string|用户头像| - - -返回值 -``` -[ - { - "name": "develop", - "user_can_push": true, - "user_can_merge": true, - "protected": false, - "http_url": "http://localhost:3003/18816895620/mirror_demo.git", - "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", - "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", - "last_commit": { - "id": "735674d6696bddbafa993db9c67b40c41246c77f", - "message": "FIX test branch content\n", - "timestamp": 1577694074, - "time_from_now": "1天前" - }, - "author": { - "login": "18816895620", - "image_url": "avatars/User/b" - } - }, - { - "name": "master", - "user_can_push": true, - "user_can_merge": true, - "protected": false, - "http_url": "http://localhost:3003/18816895620/mirror_demo.git", - "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", - "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", - "last_commit": { - "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", - "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", - "timestamp": 1577244567, - "time_from_now": "6天前" - }, - "author": { - "login": "18816895620", - "image_url": "avatars/User/b" - } - } -] -``` ---- - -## 仓库详情 -``` -GET /api/:namespace_id/:project_id/repository -``` -*示例* -``` -curl -X GET \ -http://192.168.2.230:3000/api/jasder/forgeplus/repository | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|namespace_id |是|string |用户登录名 | -|project_id |是|string |项目标识identifier | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|identifier |string|仓库标识| -|project_id |int|项目id| -|project_identifier|string|项目标识| -|praises_count |int|点赞数量| -|forked_count |int|fork数量| -|watchers_count |int|关注数量| -|branches_count |int|分支数量| -|commits_count |int|总提交记录数量| -|issues_count |int|总提交记录数量| -|pull_requests_count |int|总提交记录数量| -|praised |boolean|当前登录用户是否已点赞,true:已点赞,fasle:未点赞, 用户未登录状态为null| -|watched |boolean|当前登录用户是否已关注,true:已关注,fasle:未关注, 用户未登录状态为null| -|permission |string|当前登录用户对该仓库的操作权限, Manager:管理员,可以在线编辑文件、在线新建文件、可以设置仓库的基本信息; Developer:开发人员,可在线编辑文件、在线新建文件、不能设置仓库信息; Reporter: 报告人员,只能查看信息,不能设置仓库信息、不能在线编辑文件、不能在线新建文件;用户未登录时也会返回Reporter, 说明也只有读取文件的权限 | -|size |int|仓库文件大小,单位:KB| -|type |int|项目类型; 2: 表示是一个镜像(具备同步功能), 1: 普通镜像项目(不具同步功能), 0: 普通托管项目, 3: fork项目| -|mirror_status |int|该字段在type字段为2(一个镜像)时才会出现; 0: 表示同步镜像成功;1: 表示正在同步镜像;2: 同步失败| -|mirror_url |string|镜像地址, 只有通过镜像过来的项目才会有这个地址| -|ssh_url |string|仓库ssh地址| -|clone_url |string|仓库克隆地址| -|empty |boolean|仓库是否为空,true: 空仓库;false: 非空仓库| -|private |boolean|仓库是否私有,true: 私有仓库;fasle: 非私有的| -|default_branch |string|仓库默认分支| -|full_name |string|仓库全名(带用户名)| -|author |object|提交用户| -|-- login |string|用户login| -|-- name |string|用户姓名| -|-- image_url |string|用户头像| - - -返回值 -``` -{ - "identifier": "mirror_demo", - "project_id": 3263, - "project_identifier": "mirror_demo", - "praises_count": 1, - "forked_count": 0, - "watchers_count": 1, - "branches_count": 6, - "commits_count": 107, - "issues_count": 0, - "pull_requests_count": 0, - "permission": "Manager", - "mirror_url": "https://gitea.com/CasperVector/slew.git", - "watched": true, - "praised": true, - "size": 446, - "ssh_url": "jasder@localhost:18816895620/mirror_demo.git", - "clone_url": "http://localhost:3003/18816895620/mirror_demo.git", - "default_branch": "master", - "empty": false, - "full_name": "18816895620/mirror_demo", - "mirror": false, - "private": false, - "author": { - "login": "18816895620", - "name": "美女", - "image_url": "avatars/User/b" - } -} -``` ---- - -## 获取提交记录列表 -``` -GET /api/repositories/:id/commits -``` -*示例* -``` -curl -X GET \ --d "sha=develop" \ --d "page=1" \ -http://localhost:3000/api/repositories/89/commits.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|sha |否|string |分支名称、提交记录的sha标识,默认为master分支 | -|page |否|int |页数, 默认为1 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count|int|总记录条数| -|commits |array|提交记录的数组| -|-- sha |string|提交记录sha标识| -|-- message |string|提交的备注说明| -|-- timestamp |int|提交UNIX时间戳| -|-- time_from_now|string|提交距离当前的时间| -|author |object|提交用户| -|-- login |string|用户名称| -|-- image_url |string|用户头像| - - -返回值 -``` -{ - "total_count": 63, - "commits": [ - { - "sha": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", - "message": "合并pull request测试", - "timestamp": 1577244567, - "time_from_now": "7天前", - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - } - }, - { - "sha": "2b33c5f55214db41879936312ee43611406c4dbd", - "message": "FIX .", - "timestamp": 1577244474, - "time_from_now": "7天前", - "author": { - "name": "18816895620", - "image_url": "avatars/User/b" - } - } - ] -} -``` ---- - -## 获取某个提交记录(包含diff) -``` -GET /api/repositories/:id/commits/:sha -``` -*示例* -``` -curl -X GET \ -http://localhost:3000/api/repositories/5845/commits/b0c4a4a1487d53acebf2addc544b29938cad12df.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |仓库repository的id | -|sha |否|string |git的ref或者是提交记录commit的sha标识 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|additions |int|该commit下所有文件增加的总行数| -|deletions |int|该commit下所有文件删除的总行数| -|sha |string|提交记录sha标识| -|url |string|该commit的api访问地址| -|commit |object| | -|-- author |object| commit的作者用户| -|---- login |string|提交commit的用户名称| -|---- email |string|提交commit的用户邮箱| -|---- date |string|提交commit的时间| -|-- committer |object|提交者用户信息| -|---- login |string|committer的用户名称| -|---- email |string|committer的用户邮箱| -|---- date |string|committer的时间| -|-- message |string|提交信息| -|-- tree |object| | -|---- sha |string| tree结构的sha标识| -|author |object|forge平台的提交用户信息| -|-- id |int|用户id| -|-- login |string|用户登录名| -|-- name |string|用户名称| -|-- image_url |string|用户头像| -|committer |object|forge平台的committer用户信息| -|-- id |int|用户id| -|-- login |string|用户登录名| -|-- name |string|用户名称| -|-- image_url |string|用户头像| -|parents |array|父节点| -|-- sha |int|commit父节点的sha标识| -|-- url |string|commit父节点api访问地址| -|author |object|提交用户| -|-- login |string|用户名称| -|-- image_url |string|用户头像| -|files |array|文件数组| -|-- Name |string|文件名称| -|-- OldName |string|旧文件名称| -|-- Addition |string|增加的行数| -|-- Deletion |string|删除的行数| -|-- Type |string|1: 表示是新增加的文件,2:表示是修改的文件, 3: 表示该文件已经被删除| -|-- IsCreated |boolean|是否为新添加的文件,true:是; false:否| -|-- IsDeleted |boolean|是否为删除的文件,true:是;false:否| -|-- IsRenamed |boolean|是否为重命名的文件,true:是,false:否| -|-- IsBin |boolean|是否为二进制文件,true:是,false:否| -|-- IsLFSFile |boolean|是否git lfs操作的大文件,true:是,false:否| -|-- IsSubmodule |boolean|收否为子模块,true:是;false:否| -|-- Sections |array| | -|---- Name |string|文件名称| -|------ Lines |array|行数| -|-------- LeftIdx |int|分列视图时用,左侧开始行号, 0:表示没有行号| -|-------- RightIdx |int|分列视图时用,右侧开始行号| -|-------- Type |int|1: 表示未做修改的源代码,2: 表示增加的代码,3: 表示删除的代码,4: 统计说明,如:@@ -0,0 +1,11 @@| -|-------- Content |string|一行的文件内容| -|-------- Comments |string|评论信息| -|-------- SectionInfo |string|用户头像| -|---------- Path |string|文件路径| -|---------- LastLeftIdx |string| | -|---------- LastRightIdx |string| | -|---------- LeftIdx |string| | -|---------- RightIdx |string| | -|---------- LeftHunkSize |string| | -|---------- RightHunkSize |string| | - - -返回值 -``` -{ - "additions": 243, - "deletions": 32, - "sha": "c6c17ad47d6dbe4369d559847197b37b4090a46e", - "url": "http://localhost:3000/api/repositories/5845/commits/c6c17ad47d6dbe4369d559847197b37b4090a46e.json", - "commit": { - "author": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2020-05-20T20:15:27+08:00" - }, - "committer": { - "name": "GitHub", - "email": "noreply@github.com", - "date": "2020-05-20T20:15:27+08:00" - } - }, - "author": null, - "committer": null, - "parents": [ - { - "sha": "c8b8cfd85e375ad376833d04b9ca499bf9da355b", - "url": "http://localhost:3003//api/repositories/intelligent-test-platform/commits/c8b8cfd85e375ad376833d04b9ca499bf9da355b" - }, - { - "sha": "b0c4a4a1487d53acebf2addc544b29938cad12df", - "url": "http://localhost:3003//api/repositories/intelligent-test-platform/commits/b0c4a4a1487d53acebf2addc544b29938cad12df" - } - ], - "files": [ - { - "Name": "Dockerfile", - "OldName": "Dockerfile", - "Index": 1, - "Addition": 11, - "Deletion": 0, - "Type": 1, - "IsCreated": true, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -0,0 +1,11 @@", - "Comments": null, - "SectionInfo": { - "Path": "Dockerfile", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 0, - "RightIdx": 1, - "LeftHunkSize": 0, - "RightHunkSize": 11 - } - }, - { - "LeftIdx": 0, - "RightIdx": 1, - "Type": 2, - "Content": "+FROM adoptopenjdk/maven-openjdk8:latest", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 2, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 3, - "Type": 2, - "Content": "+ADD ./target/markov-demo-0.0.1-SNAPSHOT.jar /usr/local/markov-demo-0.0.1-SNAPSHOT.jar", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 4, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 5, - "Type": 2, - "Content": "+# Add docker-compose-wait tool -------------------", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 6, - "Type": 2, - "Content": "+ENV WAIT_VERSION 2.7.2", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 7, - "Type": 2, - "Content": "+ADD https://github.com/ufoscout/docker-compose-wait/releases/download/$WAIT_VERSION/wait /wait", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 8, - "Type": 2, - "Content": "+RUN chmod +x /wait", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 9, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 10, - "Type": 2, - "Content": "+EXPOSE 8080", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 11, - "Type": 2, - "Content": "+ENTRYPOINT [ \"java\", \"-jar\", \"/usr/local/markov-demo-0.0.1-SNAPSHOT.jar\" ]", - "Comments": null, - "SectionInfo": null - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "docker-compose.yml", - "OldName": "docker-compose.yml", - "Index": 2, - "Addition": 42, - "Deletion": 0, - "Type": 1, - "IsCreated": true, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -0,0 +1,42 @@", - "Comments": null, - "SectionInfo": { - "Path": "docker-compose.yml", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 0, - "RightIdx": 1, - "LeftHunkSize": 0, - "RightHunkSize": 42 - } - }, - { - "LeftIdx": 0, - "RightIdx": 1, - "Type": 2, - "Content": "+version: '3.6'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 2, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 3, - "Type": 2, - "Content": "+services:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 4, - "Type": 2, - "Content": "+ web:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 5, - "Type": 2, - "Content": "+ build: .", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 6, - "Type": 2, - "Content": "+ command: sh -c \"/wait && java -jar /usr/local/markov-demo-0.0.1-SNAPSHOT.jar\"", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 7, - "Type": 2, - "Content": "+ environment:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 8, - "Type": 2, - "Content": "+ - WAIT_HOSTS=container-mysql:3306", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 9, - "Type": 2, - "Content": "+ - WAIT_HOSTS_TIMEOUT=300", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 10, - "Type": 2, - "Content": "+ - WAIT_SLEEP_INTERVAL=30", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 11, - "Type": 2, - "Content": "+ - WAIT_HOST_CONNECT_TIMEOUT=30", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 12, - "Type": 2, - "Content": "+ - spring.datasource.url=jdbc:mysql://container-mysql:3306/markov_demo?useUnicode=true&characterEncoding=utf-8", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 13, - "Type": 2, - "Content": "+ depends_on:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 14, - "Type": 2, - "Content": "+ - container-mysql", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 15, - "Type": 2, - "Content": "+ ports:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 16, - "Type": 2, - "Content": "+ - '8080:8080'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 17, - "Type": 2, - "Content": "+ expose:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 18, - "Type": 2, - "Content": "+ - '8080'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 19, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 20, - "Type": 2, - "Content": "+ container-mysql:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 21, - "Type": 2, - "Content": "+ image: mysql:5.7", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 22, - "Type": 2, - "Content": "+ restart: always", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 23, - "Type": 2, - "Content": "+ environment:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 24, - "Type": 2, - "Content": "+ MYSQL_DATABASE: 'markov_demo'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 25, - "Type": 2, - "Content": "+ # So you don't have to use root, but you can if you like", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 26, - "Type": 2, - "Content": "+ MYSQL_USER: 'root'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 27, - "Type": 2, - "Content": "+ # You can use whatever password you like", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 28, - "Type": 2, - "Content": "+ MYSQL_PASSWORD: '123'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 29, - "Type": 2, - "Content": "+ # Password for root access", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 30, - "Type": 2, - "Content": "+ MYSQL_ROOT_PASSWORD: '123'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 31, - "Type": 2, - "Content": "+ ports:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 32, - "Type": 2, - "Content": "+ # : < MySQL Port running inside container>", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 33, - "Type": 2, - "Content": "+ - '3306:3306'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 34, - "Type": 2, - "Content": "+ expose:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 35, - "Type": 2, - "Content": "+ # Opens port 3306 on the container", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 36, - "Type": 2, - "Content": "+ - '3306'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 37, - "Type": 2, - "Content": "+ # Where our data will be persisted", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 38, - "Type": 2, - "Content": "+ volumes:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 39, - "Type": 2, - "Content": "+ - my-db:/tmp/mysql", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 40, - "Type": 2, - "Content": "+# Names our volume", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 41, - "Type": 2, - "Content": "+volumes:", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 42, - "Type": 2, - "Content": "+ my-db: {}", - "Comments": null, - "SectionInfo": null - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "pom.xml", - "OldName": "pom.xml", - "Index": 3, - "Addition": 5, - "Deletion": 0, - "Type": 2, - "IsCreated": false, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -26,6 +26,11 @@", - "Comments": null, - "SectionInfo": { - "Path": "pom.xml", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 26, - "RightIdx": 26, - "LeftHunkSize": 6, - "RightHunkSize": 11 - } - }, - { - "LeftIdx": 26, - "RightIdx": 26, - "Type": 1, - "Content": " \t\t\tmybatis-spring-boot-starter", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 27, - "RightIdx": 27, - "Type": 1, - "Content": " \t\t\t2.1.2", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 28, - "RightIdx": 28, - "Type": 1, - "Content": " \t\t", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 29, - "Type": 2, - "Content": "+\t\t", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 30, - "Type": 2, - "Content": "+\t\t\torg.flywaydb", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 31, - "Type": 2, - "Content": "+\t\t\tflyway-core", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 32, - "Type": 2, - "Content": "+\t\t\t6.4.2", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 33, - "Type": 2, - "Content": "+\t\t", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 29, - "RightIdx": 34, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 30, - "RightIdx": 35, - "Type": 1, - "Content": " \t\t", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 31, - "RightIdx": 36, - "Type": 1, - "Content": " \t\t\tmysql", - "Comments": null, - "SectionInfo": null - } - ] - }, - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": " ", - "Comments": null, - "SectionInfo": { - "Path": "pom.xml", - "LastLeftIdx": 31, - "LastRightIdx": 36, - "LeftIdx": 103, - "RightIdx": 108, - "LeftHunkSize": 0, - "RightHunkSize": 0 - } - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "src/main/resources/application.properties", - "OldName": "src/main/resources/application.properties", - "Index": 4, - "Addition": 5, - "Deletion": 4, - "Type": 2, - "IsCreated": false, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -1,10 +1,11 @@", - "Comments": null, - "SectionInfo": { - "Path": "src/main/resources/application.properties", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 1, - "RightIdx": 1, - "LeftHunkSize": 10, - "RightHunkSize": 11 - } - }, - { - "LeftIdx": 1, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 1, - "Type": 2, - "Content": "+# Database configuration", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 2, - "RightIdx": 2, - "Type": 1, - "Content": " spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 3, - "RightIdx": 3, - "Type": 1, - "Content": " spring.datasource.url = jdbc:mysql://127.0.0.1:3306/markov_demo?useUnicode=true&characterEncoding=utf-8", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 4, - "RightIdx": 4, - "Type": 1, - "Content": " spring.datasource.username = root", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 5, - "RightIdx": 5, - "Type": 1, - "Content": " spring.datasource.password = 123", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 6, - "RightIdx": 6, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 7, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 8, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 9, - "RightIdx": 0, - "Type": 3, - "Content": "-mybatis.mapper-locations= classpath:mapping/*Mapper.xml", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 7, - "Type": 2, - "Content": "+mybatis.mapper-locations=classpath:mapping/*Mapper.xml", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 10, - "RightIdx": 8, - "Type": 1, - "Content": " mybatis.type-aliases-package=com.alibaba.markovdemo.entity", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 9, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 10, - "Type": 2, - "Content": "+spring.flyway.default-schema=markov_demo", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 11, - "Type": 2, - "Content": "+spring.flyway.locations=classpath:db/migration", - "Comments": null, - "SectionInfo": null - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "src/main/resources/db/migration/V1__init_ddl.sql", - "OldName": "src/main/resources/db/migration/V1__init_ddl.sql", - "Index": 5, - "Addition": 179, - "Deletion": 0, - "Type": 1, - "IsCreated": true, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -0,0 +1,179 @@", - "Comments": null, - "SectionInfo": { - "Path": "src/main/resources/db/migration/V1__init_ddl.sql", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 0, - "RightIdx": 1, - "LeftHunkSize": 0, - "RightHunkSize": 179 - } - }, - { - "LeftIdx": 0, - "RightIdx": 1, - "Type": 2, - "Content": "+create database if not exists markov_demo;", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 2, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 3, - "Type": 2, - "Content": "+use markov_demo;", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 4, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 5, - "Type": 2, - "Content": "+CREATE TABLE `got_testcase` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 6, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 7, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'scenario id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 8, - "Type": 2, - "Content": "+ `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 9, - "Type": 2, - "Content": "+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 10, - "Type": 2, - "Content": "+ `name` longtext COMMENT 'name',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 11, - "Type": 2, - "Content": "+ `description` longtext COMMENT 'description',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 12, - "Type": 2, - "Content": "+ `long_description` longtext COMMENT '详细描述',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 13, - "Type": 2, - "Content": "+ `content` longtext COMMENT '存储case的阶段数据,比如数据准备阶段,数据执行阶段',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 14, - "Type": 2, - "Content": "+ `case_group` varchar(100) DEFAULT NULL COMMENT 'case分组',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 15, - "Type": 2, - "Content": "+ `is_deleted` int(11) DEFAULT '0' COMMENT '用例是否被删除。0-没有删除;1-已删除,此类case不会展示到页面上',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 16, - "Type": 2, - "Content": "+ `case_template` text COMMENT '用例模板 java/c++',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 17, - "Type": 2, - "Content": "+ `features` text COMMENT '业务特征',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 18, - "Type": 2, - "Content": "+ `is_visible` int DEFAULT '0' COMMENT '是否可见用例',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 19, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 20, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='testcase';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 21, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 22, - "Type": 2, - "Content": "+CREATE TABLE `got_pipeline` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 23, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键(id)',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 24, - "Type": 2, - "Content": "+ `pipeline` longtext COMMENT 'pipeline的json配置',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 25, - "Type": 2, - "Content": "+ `extend` text COMMENT '扩展字段',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 26, - "Type": 2, - "Content": "+ `tag` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '流程定义/自定义\\n',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 27, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 28, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 29, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='存储流程执行的pipeline配置文件';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 30, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 31, - "Type": 2, - "Content": "+CREATE TABLE `got_scenario` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 32, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 33, - "Type": 2, - "Content": "+ `name` varchar(100) DEFAULT NULL COMMENT 'name',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 34, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 35, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='测试场景表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 36, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 37, - "Type": 2, - "Content": "+CREATE TABLE `got_envs` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 38, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 39, - "Type": 2, - "Content": "+ `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 40, - "Type": 2, - "Content": "+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 41, - "Type": 2, - "Content": "+ `host_ip` varchar(20) DEFAULT NULL COMMENT 'host_ip',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 42, - "Type": 2, - "Content": "+ `status` varchar(20) DEFAULT NULL COMMENT '状态',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 43, - "Type": 2, - "Content": "+ `name` varchar(200) DEFAULT NULL COMMENT '环境名称',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 44, - "Type": 2, - "Content": "+ `env_detail` text COMMENT '环境详情',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 45, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 46, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 47, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=6928 DEFAULT CHARSET=utf8 COMMENT='环境列表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 48, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 49, - "Type": 2, - "Content": "+CREATE TABLE `pipeline_ui` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 50, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 51, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 52, - "Type": 2, - "Content": "+ `content` text COMMENT 'pipeline_ui的jsonString\\n',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 53, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 54, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='pipeline_ui表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 55, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 56, - "Type": 2, - "Content": "+CREATE TABLE `got_datasource` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 57, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键/场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 58, - "Type": 2, - "Content": "+ `content` longtext COMMENT '数据源内容',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 59, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 60, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 61, - "Type": 2, - "Content": "+ KEY `idx_scenario_id` (`scenario_id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 62, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='测试数据源表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 63, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 64, - "Type": 2, - "Content": "+CREATE TABLE `got_menu` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 65, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 66, - "Type": 2, - "Content": "+ `content` text COMMENT 'menu的jsonString\\n',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 67, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 68, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='menu表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 69, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 70, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 71, - "Type": 2, - "Content": "+insert into got_menu values(0, \"{ \\\"buinfo\\\": { \\\"buid\\\": 1, \\\"appSecneMap\\\": { \\\"1\\\": \\\"1\\\" }, \\\"menu\\\": [{ \\\"businessId\\\": 1, \\\"businessName\\\": \\\"markov-demo\\\", \\\"appMenuList\\\": [{ \\\"appName\\\": \\\"测试模块\\\", \\\"appId\\\": 1, \\\"scenarioMenuList\\\": [{ \\\"isMember\\\": true, \\\"scenarioId\\\": 1, \\\"scenarioName\\\": \\\"场景1\\\" },{ \\\"isMember\\\": true, \\\"scenarioId\\\": 2, \\\"scenarioName\\\": \\\"场景2\\\" }] }] }, ], \\\"buName\\\": \\\"markov-demo\\\" }}\");", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 72, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 73, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 74, - "Type": 2, - "Content": "+CREATE TABLE `got_reports` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 75, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 76, - "Type": 2, - "Content": "+ `gmt_create` datetime NOT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 77, - "Type": 2, - "Content": "+ `gmt_modified` datetime NOT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 78, - "Type": 2, - "Content": "+ `user` text COMMENT '执行用户',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 79, - "Type": 2, - "Content": "+ `report_name` text COMMENT '报告名称',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 80, - "Type": 2, - "Content": "+ `status` varchar(100) DEFAULT NULL COMMENT '执行状态',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 81, - "Type": 2, - "Content": "+ `message` text COMMENT '信息',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 82, - "Type": 2, - "Content": "+ `app_id` bigint(20) unsigned DEFAULT NULL COMMENT 'appid',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 83, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 84, - "Type": 2, - "Content": "+ `run_type` text COMMENT '执行方式',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 85, - "Type": 2, - "Content": "+ `exec_id` text COMMENT '批次id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 86, - "Type": 2, - "Content": "+ `analysis` text COMMENT '分析报告',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 87, - "Type": 2, - "Content": "+ `task_id` text COMMENT 'zk任务id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 88, - "Type": 2, - "Content": "+ `zk_info` longtext COMMENT 'zk信息',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 89, - "Type": 2, - "Content": "+ `accuracy_report_id` bigint(20) unsigned DEFAULT NULL COMMENT '精准测试报告id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 90, - "Type": 2, - "Content": "+ `case_num` int(10) unsigned DEFAULT '0' COMMENT '回归用例数',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 91, - "Type": 2, - "Content": "+ `image_name` text COMMENT '回归的镜像版本',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 92, - "Type": 2, - "Content": "+ `branch_name` text COMMENT '执行用例的分支',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 93, - "Type": 2, - "Content": "+ `git_branch` text COMMENT '测试源码的分支',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 94, - "Type": 2, - "Content": "+ `git_commit` text COMMENT '测试源码的commit版本',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 95, - "Type": 2, - "Content": "+ `cc_cov_rate` text COMMENT '增量代码覆盖率',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 96, - "Type": 2, - "Content": "+ `is_visible` int DEFAULT '0' COMMENT '是否可见报告',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 97, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 98, - "Type": 2, - "Content": "+ KEY `idx_scenarioid` (`scenario_id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 99, - "Type": 2, - "Content": "+ KEY `idx_appid` (`app_id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 100, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=7858 DEFAULT CHARSET=utf8mb4 COMMENT='回归测试报告表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 101, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 102, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 103, - "Type": 2, - "Content": "+CREATE TABLE `got_testcase_snaps` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 104, - "Type": 2, - "Content": "+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 105, - "Type": 2, - "Content": "+ `gmt_create` datetime NOT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 106, - "Type": 2, - "Content": "+ `gmt_modified` datetime NOT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 107, - "Type": 2, - "Content": "+ `scenario_id` bigint(20) unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 108, - "Type": 2, - "Content": "+ `app_id` bigint(20) unsigned DEFAULT NULL COMMENT 'appid',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 109, - "Type": 2, - "Content": "+ `name` varchar(100) DEFAULT NULL COMMENT '用例名',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 110, - "Type": 2, - "Content": "+ `description` text COMMENT '描述',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 111, - "Type": 2, - "Content": "+ `long_description` longtext COMMENT '详情',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 112, - "Type": 2, - "Content": "+ `content` longtext COMMENT '输入,输出,期望,数据准备',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 113, - "Type": 2, - "Content": "+ `status` varchar(100) DEFAULT NULL COMMENT '用例执行状态',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 114, - "Type": 2, - "Content": "+ `testreport_id` bigint(20) unsigned NOT NULL COMMENT '归属的报告id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 115, - "Type": 2, - "Content": "+ `testcase_id` bigint(20) unsigned NOT NULL COMMENT '归属的用例id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 116, - "Type": 2, - "Content": "+ `case_group` varchar(100) DEFAULT NULL COMMENT '测试用例分组',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 117, - "Type": 2, - "Content": "+ `tag` varchar(100) DEFAULT NULL COMMENT 'case标签,可有有多个值',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 118, - "Type": 2, - "Content": "+ `version` varchar(100) DEFAULT NULL COMMENT 'case版本号',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 119, - "Type": 2, - "Content": "+ `run_time` bigint(20) unsigned DEFAULT NULL COMMENT '执行时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 120, - "Type": 2, - "Content": "+ `run_time_str` text COMMENT '执行时间标准化',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 121, - "Type": 2, - "Content": "+ `retry_num` bigint(20) unsigned DEFAULT NULL COMMENT '重试次数',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 122, - "Type": 2, - "Content": "+ `constancy` text COMMENT '稳定性',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 123, - "Type": 2, - "Content": "+ `env_name` text COMMENT '环境名',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 124, - "Type": 2, - "Content": "+ `conflict_desc` text COMMENT '冲突用例描述',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 125, - "Type": 2, - "Content": "+ `is_parallel` tinyint(1) DEFAULT NULL COMMENT '是否串行',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 126, - "Type": 2, - "Content": "+ `trouble_shoot_box` longtext COMMENT '智能归因',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 127, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 128, - "Type": 2, - "Content": "+ KEY `idx_caseid` (`testcase_id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 129, - "Type": 2, - "Content": "+ KEY `idx_reportid` (`testreport_id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 130, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=303953 DEFAULT CHARSET=utf8mb4 COMMENT='测试报告用例集快照'", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 131, - "Type": 2, - "Content": "+;", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 132, - "Type": 2, - "Content": "+CREATE TABLE `got_features_pool` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 133, - "Type": 2, - "Content": "+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 134, - "Type": 2, - "Content": "+ `gmt_create` datetime NOT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 135, - "Type": 2, - "Content": "+ `gmt_modified` datetime NOT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 136, - "Type": 2, - "Content": "+ `scenario_id` bigint unsigned NULL COMMENT 'scenario_id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 137, - "Type": 2, - "Content": "+ `app_id` bigint unsigned NULL COMMENT 'app_id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 138, - "Type": 2, - "Content": "+ `features` text NULL COMMENT '特征集',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 139, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 140, - "Type": 2, - "Content": "+) DEFAULT CHARACTER SET=utf8mb4 COMMENT='特征池';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 141, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 142, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 143, - "Type": 2, - "Content": "+CREATE TABLE `got_case_generate_task` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 144, - "Type": 2, - "Content": "+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 145, - "Type": 2, - "Content": "+ `gmt_create` datetime NOT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 146, - "Type": 2, - "Content": "+ `gmt_modified` datetime NOT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 147, - "Type": 2, - "Content": "+ `creator` text COMMENT '任务创建者',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 148, - "Type": 2, - "Content": "+ `seed_case_list` text COMMENT '种子用例id列表,以”,“分隔',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 149, - "Type": 2, - "Content": "+ `scenario_id` bigint unsigned DEFAULT NULL COMMENT '场景id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 150, - "Type": 2, - "Content": "+ `env_info` text COMMENT '测试环境信息',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 151, - "Type": 2, - "Content": "+ `feature_conf` longtext COMMENT '任务相关配置,jsonObject',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 152, - "Type": 2, - "Content": "+ `task_name` text COMMENT '任务名',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 153, - "Type": 2, - "Content": "+ `task_snap` longtext COMMENT '任务生成信息',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 154, - "Type": 2, - "Content": "+ `task_result` longtext COMMENT '最终生成用例',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 155, - "Type": 2, - "Content": "+ `task_status` text COMMENT 'crate 、executing、success or fail ',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 156, - "Type": 2, - "Content": "+ `gene_bank_snap` longtext COMMENT 'json格式gene bank',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 157, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 158, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=98 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用例智能生成任务记录表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 159, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 160, - "Type": 2, - "Content": "+CREATE TABLE `got_case_accuracy` (", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 161, - "Type": 2, - "Content": "+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 162, - "Type": 2, - "Content": "+ `gmt_create` datetime NOT NULL COMMENT '创建时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 163, - "Type": 2, - "Content": "+ `gmt_modified` datetime NOT NULL COMMENT '修改时间',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 164, - "Type": 2, - "Content": "+ `case_id` bigint unsigned DEFAULT NULL COMMENT 'case id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 165, - "Type": 2, - "Content": "+ `exe_id` bigint unsigned DEFAULT NULL COMMENT '回归执行id',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 166, - "Type": 2, - "Content": "+ `cov_line` longtext COMMENT 'case覆盖的代码行,json格式',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 167, - "Type": 2, - "Content": "+ `collect_type` text COMMENT 'single : 单case收集;total:任务整体收集',", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 168, - "Type": 2, - "Content": "+ PRIMARY KEY (`id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 169, - "Type": 2, - "Content": "+ KEY `idx_caseid` (`case_id`),", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 170, - "Type": 2, - "Content": "+ KEY `idx_exe_id` (`exe_id`)", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 171, - "Type": 2, - "Content": "+) ENGINE=InnoDB AUTO_INCREMENT=16001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='case精准数据覆盖数据记录表';", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 172, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 173, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 174, - "Type": 2, - "Content": "+INSERT INTO `got_testcase` (`gmt_create`,`gmt_modified`,`scenario_id`,`name`,`description`,`long_description`,`content`,`case_group`,`is_deleted`,`case_template`,`is_visible`) VALUES ('2020-04-28 19:12:55','2020-04-28 19:12:55',1,'case名','用例智能生成-种子用例','种子用例','{\\\"prepareData\\\":[{\\\"Tair\\\":[{\\\"dsName\\\":\\\"table.markovtair.test\\\",\\\"data\\\":[{\\\"key\\\":\\\"testkey\\\",\\\"value\\\":\\\"testvalue\\\",\\\"property\\\":\\\"\\\"}]}]}],\\\"caseRunStage\\\":[{\\\"group_name\\\":\\\"ERPC校验(第一组)\\\",\\\"data\\\":[{\\\"input\\\":\\\"{\\\\n \\\\\\\"ad_id\\\\\\\": \\\\\\\"222\\\\\\\",\\\\n \\\\\\\"search_key\\\\\\\": \\\\\\\"key1\\\\\\\",\\\\n \\\\\\\"match_level\\\\\\\": 2,\\\\n \\\\\\\"user_type\\\\\\\": \\\\\\\"type1\\\\\\\",\\\\n \\\\\\\"top_num\\\\\\\": 10,\\\\n \\\\\\\"use_feature\\\\\\\": false,\\\\n \\\\\\\"other1\\\\\\\": \\\\\\\"1\\\\\\\",\\\\n \\\\\\\"other2\\\\\\\": \\\\\\\"0\\\\\\\"\\\\n}\\\",\\\"expect\\\":\\\"{\\\\n \\\\\\\"result\\\\\\\": \\\\\\\"1\\\\\\\" \\\\n}\\\",\\\"actual\\\":\\\"null\\\"}]}]}','test',0,'c++',0);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 175, - "Type": 2, - "Content": "+INSERT INTO `got_testcase` (`gmt_create`,`gmt_modified`,`scenario_id`,`name`,`description`,`long_description`,`content`,`case_group`,`is_deleted`,`case_template`,`is_visible`) VALUES ('2020-04-28 19:12:55','2020-04-28 19:12:55',1,'case名','用例智能推荐用例1','普通用例','{\\\"prepareData\\\":[{\\\"Tair\\\":[{\\\"dsName\\\":\\\"table.markovtair.test\\\",\\\"data\\\":[{\\\"key\\\":\\\"testkey\\\",\\\"value\\\":\\\"testvalue\\\",\\\"property\\\":\\\"\\\"}]}],\\\"Imock\\\":[{\\\"dsName\\\":\\\"erpc_merger_inner\\\",\\\"data\\\":[{\\\"key\\\":\\\"key1\\\",\\\"value\\\":\\\"value1\\\",\\\"property\\\":\\\"\\\"},{\\\"key\\\":\\\"key2\\\",\\\"value\\\":\\\"value2\\\",\\\"property\\\":\\\"\\\"}],\\\"restartFlag\\\":\\\"0\\\"}]}],\\\"caseRunStage\\\":[{\\\"group_name\\\":\\\"ERPC校验(第一组)\\\",\\\"data\\\":[{\\\"input\\\":\\\"{\\\\n \\\\\\\"param_manager\\\\\\\": {\\\\n \\\\\\\"expand_param\\\\\\\": {\\\\n \\\\\\\"key_value_list\\\\\\\": [\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature1\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"true\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature2\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"3,8;4,16\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature3\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature4\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"one_phase_model_searching,200,166,1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature5\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"false\\\\\\\"\\\\n }\\\\n ]\\\\n }\\\\n }\\\\n}\\\",\\\"expect\\\":\\\"{\\\\n \\\\\\\"result\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n}\\\",\\\"actual\\\":\\\"null\\\"}]}]}','猜你喜欢',0,'c++',0);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 176, - "Type": 2, - "Content": "+INSERT INTO `got_testcase` (`gmt_create`,`gmt_modified`,`scenario_id`,`name`,`description`,`long_description`,`content`,`case_group`,`is_deleted`,`case_template`,`is_visible`) VALUES ('2020-04-28 19:12:55','2020-04-28 19:12:55',1,'case名','用例智能推荐用例2','普通用例','{\\\"prepareData\\\":[{\\\"Tair\\\":[{\\\"dsName\\\":\\\"table.markovtair.test\\\",\\\"data\\\":[{\\\"key\\\":\\\"testkey\\\",\\\"value\\\":\\\"testvalue\\\",\\\"property\\\":\\\"\\\"}]}],\\\"Imock\\\":[{\\\"dsName\\\":\\\"erpc_merger_inner\\\",\\\"data\\\":[{\\\"key\\\":\\\"key1\\\",\\\"value\\\":\\\"confict-value\\\",\\\"property\\\":\\\"\\\"},{\\\"key\\\":\\\"key2\\\",\\\"value\\\":\\\"value2\\\",\\\"property\\\":\\\"\\\"}]}]}],\\\"caseRunStage\\\":[{\\\"group_name\\\":\\\"ERPC校验(第一组)\\\",\\\"data\\\":[{\\\"input\\\":\\\"{\\\\n \\\\\\\"param_manager\\\\\\\": {\\\\n \\\\\\\"expand_param\\\\\\\": {\\\\n \\\\\\\"key_value_list\\\\\\\": [\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature1\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"true\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature2\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"3,8;4,16\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature3\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature4\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"one_phase_model_searching,200,166,1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature5\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"false\\\\\\\"\\\\n }\\\\n ]\\\\n }\\\\n }\\\\n}\\\",\\\"expect\\\":\\\"{\\\\n \\\\\\\"result\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n}\\\"}]}]}','购物车',0,'c++',0);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 177, - "Type": 2, - "Content": "+INSERT INTO `got_testcase` (`gmt_create`,`gmt_modified`,`scenario_id`,`name`,`description`,`long_description`,`content`,`case_group`,`is_deleted`,`case_template`,`is_visible`) VALUES ('2020-04-28 19:12:55','2020-04-28 19:12:55',1,'case名','用例智能推荐用例3','普通用例','{\\\"prepareData\\\":[{\\\"Tair\\\":[{\\\"dsName\\\":\\\"table.markovtair.test\\\",\\\"data\\\":[{\\\"key\\\":\\\"testkey\\\",\\\"value\\\":\\\"testvalue\\\",\\\"property\\\":\\\"\\\"}]}],\\\"Imock\\\":[{\\\"dsName\\\":\\\"erpc_merger_inner\\\",\\\"data\\\":[{\\\"key\\\":\\\"key1\\\",\\\"value\\\":\\\"value1\\\",\\\"property\\\":\\\"\\\"},{\\\"key\\\":\\\"key3\\\",\\\"value\\\":\\\"value3\\\",\\\"property\\\":\\\"\\\"}]}]}],\\\"caseRunStage\\\":[{\\\"group_name\\\":\\\"ERPC校验(第一组)\\\",\\\"data\\\":[{\\\"input\\\":\\\"{\\\\n \\\\\\\"param_manager\\\\\\\": {\\\\n \\\\\\\"expand_param\\\\\\\": {\\\\n \\\\\\\"key_value_list\\\\\\\": [\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature1\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"true\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature2\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"3,8;4,16\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature3\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature4\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"one_phase_model_searching,200,166,1\\\\\\\"\\\\n },\\\\n {\\\\n \\\\\\\"key\\\\\\\": \\\\\\\"feature5\\\\\\\",\\\\n \\\\\\\"value\\\\\\\": \\\\\\\"false\\\\\\\"\\\\n }\\\\n ]\\\\n }\\\\n }\\\\n}\\\",\\\"expect\\\":\\\"{\\\\n \\\\\\\"result\\\\\\\": \\\\\\\"1\\\\\\\"\\\\n}\\\"}]}]}','直播',0,'c++',0);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 178, - "Type": 2, - "Content": "+", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 179, - "Type": 2, - "Content": "+INSERT INTO `got_envs` (`gmt_create`,`gmt_modified`,`scenario_id`,`name`,`status`,`host_ip`,`env_detail`) VALUES ('2020-04-28 19:12:55','2020-04-28 19:12:55',1,'初始测试环境','SUCCESS','11.167.254.210','123');", - "Comments": null, - "SectionInfo": null - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "src/main/resources/static/index.html", - "OldName": "src/main/resources/static/index.html", - "Index": 6, - "Addition": 1, - "Deletion": 1, - "Type": 2, - "IsCreated": false, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -24,7 +24,7 @@", - "Comments": null, - "SectionInfo": { - "Path": "src/main/resources/static/index.html", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 24, - "RightIdx": 24, - "LeftHunkSize": 7, - "RightHunkSize": 7 - } - }, - { - "LeftIdx": 24, - "RightIdx": 24, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 25, - "RightIdx": 25, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 26, - "RightIdx": 26, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 27, - "RightIdx": 0, - "Type": 3, - "Content": "- ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 0, - "RightIdx": 27, - "Type": 2, - "Content": "+ ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 28, - "RightIdx": 28, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 29, - "RightIdx": 29, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 30, - "RightIdx": 30, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - } - ] - }, - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": " ", - "Comments": null, - "SectionInfo": { - "Path": "src/main/resources/static/index.html", - "LastLeftIdx": 30, - "LastRightIdx": 30, - "LeftIdx": 43, - "RightIdx": 43, - "LeftHunkSize": 0, - "RightHunkSize": 0 - } - } - ] - } - ], - "IsIncomplete": false - }, - { - "Name": "src/test/java/com/alibaba/markovdemo/MarkovDemoApplicationTests.java", - "OldName": "src/test/java/com/alibaba/markovdemo/MarkovDemoApplicationTests.java", - "Index": 7, - "Addition": 0, - "Deletion": 27, - "Type": 2, - "IsCreated": false, - "IsDeleted": false, - "IsBin": false, - "IsLFSFile": false, - "IsRenamed": false, - "IsSubmodule": false, - "Sections": [ - { - "Name": "", - "Lines": [ - { - "LeftIdx": 0, - "RightIdx": 0, - "Type": 4, - "Content": "@@ -32,36 +32,9 @@ class MarkovDemoApplicationTests {", - "Comments": null, - "SectionInfo": { - "Path": "src/test/java/com/alibaba/markovdemo/MarkovDemoApplicationTests.java", - "LastLeftIdx": 0, - "LastRightIdx": 0, - "LeftIdx": 32, - "RightIdx": 32, - "LeftHunkSize": 36, - "RightHunkSize": 9 - } - }, - { - "LeftIdx": 32, - "RightIdx": 32, - "Type": 1, - "Content": " \t\treturn df2.format(date1);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 33, - "RightIdx": 33, - "Type": 1, - "Content": " \t}", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 34, - "RightIdx": 34, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 35, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 36, - "RightIdx": 35, - "Type": 1, - "Content": " \t@Test", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 37, - "RightIdx": 36, - "Type": 1, - "Content": " \tvoid wordTest () throws IOException {", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 38, - "RightIdx": 37, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 39, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\t// FileInputStream fis = new FileInputStream(\"199801.txt\");", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 40, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\t// FileOutputStream fos = new FileOutputStream(\"dic.txt\");", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 41, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\t// ImportCorpus readF = new ImportCorpus(fis, fos);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 42, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\t// readF.readDic();", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 43, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\t// System.out.println(\"µ¼Èë½áÊø\");", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 44, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 45, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tString filename = \"dic.txt\";", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 46, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tHashMap hm = new HashMap();", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 47, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tHashMap len = new HashMap();", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 48, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tGenerateDictionary genDic = new GenerateDictionary();", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 49, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tSegmentation seg;", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 50, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 51, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tgenDic.genHashDic(filename, hm, len);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 52, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 53, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tInputStreamReader reader = new InputStreamReader(System.in);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 54, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tBufferedReader br = new BufferedReader(reader);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 55, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tString data = \"\";", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 56, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tdata = br.readLine();", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 57, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 58, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tseg = new Segmentation(hm, len);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 59, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 60, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tString FmmTarget = seg.Fmm(data);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 61, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tString BmmTarget = seg.Bmm(data);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 62, - "RightIdx": 0, - "Type": 3, - "Content": "-", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 63, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tSystem.out.println(\"FmmTarget: \" + FmmTarget);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 64, - "RightIdx": 0, - "Type": 3, - "Content": "-\t\tSystem.out.println(\"BmmTarget: \" + BmmTarget);", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 65, - "RightIdx": 38, - "Type": 1, - "Content": " \t}", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 66, - "RightIdx": 39, - "Type": 1, - "Content": " ", - "Comments": null, - "SectionInfo": null - }, - { - "LeftIdx": 67, - "RightIdx": 40, - "Type": 1, - "Content": " }", - "Comments": null, - "SectionInfo": null - } - ] - } - ], - "IsIncomplete": false - } - ] -} -``` ---- - -### 点赞 -``` -POST /api/projects/:id/praise_tread/like -``` -*示例* -``` -curl -X POST http://localhost:3000/api/projects/3263/praise_tread/like | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是 |int |项目id | - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -### 取消点赞 -``` -DELETE /api/projects/:id/praise_tread/unlike -``` -*示例* -``` -curl -X DELETE http://localhost:3000/api/projects/3263/praise_tread/unlike | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是 |int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -### 用户是否点过赞 -``` -GET /api/projects/:id/praise_tread/check_like -``` -*示例* -``` -curl -X GET http://localhost:3000/api/projects/3263/praise_tread/check_like | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是 |int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|1:已点过赞,0:未点过赞, -1:请求操作失败| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -### 项目的点赞者列表 -``` -GET /api/projects/:id/praise_tread -``` -*示例* -``` -curl -X GET \ --d "page=1" \ --d "limit=5" \ -http://localhost:3000/api/projects/3263/praise_tread | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|page |否|string |页数,第几页 | -|limit |否|string |每页多少条数据,默认15条 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count |int|总条数| -|praises |array|点赞数据| -|-- name |string|用户名称| -|-- login |string|用户标识/登录名(login)| -|-- image_url |string|用户头像| - - - -返回值 -``` -{ - "total_count": 1, - "praises": [ - { - "name": "18816895620", - "login": "18816895620", - "image_url": "avatars/User/b" - } - ] -} -``` ---- - -### 关注(项目) -``` -POST /api/projects/:id/watchers/follow -``` -*示例* -``` -curl -X POST http://localhost:3000/api/projects/3263/watchers/follow | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| - - -返回值 -``` -{ - "status": 0, - "message": "响应成功" -} -``` ---- - -### 取消关注 -``` -DELETE /api/projects/:id/watchers/unfollow -``` -*示例* -``` -curl -X DELETE http://localhost:3000//api/projects/3263/watchers/unfollow | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| - - -返回值 -``` -{ - "status": 0, - "message": "响应成功" -} -``` ---- - -### 用户是否关注过项目 -``` -GET /api/projects/:id/watchers/check_watch -``` -*示例* -``` -curl -X GET http://localhost:3000/api/projects/3263/watchers/check_watch | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是 |int |项目id | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|status |int|1:已关注,0:未关注, -1:请求操作失败| - - -返回值 -``` -{ - "status": 0, - "message": "success" -} -``` ---- - -### 项目的关注者列表 -``` -GET /api/projects/:id/watchers -``` -*示例* -``` -curl -X GET \ --d "page=1" \ --d "limit=5" \ -http://localhost:3000//api/projects/3263/watchers | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|page |否|string |页数,第几页 | -|limit |否|string |每页多少条数据,默认15条 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|total_count |int|总条数| -|watchers |array|关注数据| -|-- name |string|用户名称| -|-- login |string|用户标识/登录名(login)| -|-- image_url |string|用户头像| - - -返回值 -``` -{ - "total_count": 1, - "watchers": [ - { - "name": "18816895620", - "login": "18816895620", - "image_url": "avatars/User/b" - } - ] -} -``` ---- - -### 仓库新建文件 -``` -POST /api/repositories/:id/create_file -``` -*示例* -``` -curl -X POST \ --d 'filepath=test1_create_file1.rb' \ --d 'branch=master' \ --d 'content=提交的内容' \ --d 'message=test commit ' \ -http://localhost:3000/api/18816895620/mirror_demo/contents.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|string |项目id | -|filepath |是|string |文件相对于仓库的路径 | -|content |否|string |内容 | -|message |否|string |提交说明 | -|branch |否|string |分支名称, branch和new_branch必须存在一个 | -|new_branch |否|string |新的分支名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|name |string|文件名| -|sha |string|提交文件的sha值| -|size |int|文件大小, 单位:B| -|content |string|base64编码后的文件内容| -|encoding |string|编码方式| -|commit |object|| -|-- message |string|提交备注说明信息| -|-- committer|object|| -|---- name |string|用户名| -|---- email |string|用户邮箱| -|---- date |string|文件创建时间| - - - -返回值 -``` -{ - "name": "test1_create_file12.rb", - "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", - "size": 12, - "content": "Wm5ObWMyRmtaZz09", - "encoding": "base64", - "commit": { - "message": "good luck\n", - "author": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-07T03:31:20Z" - }, - "committer": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-07T03:31:20Z" - } - } -} -``` ---- - -### 更新仓库中的文件 -``` -PUT /api/repositories/:id/update_file.json -``` -*示例* -``` -curl -X PUT \ --d 'filepath=text1.rb' \ --d 'branch=master' \ --d 'content=ruby code' \ --d 'message=更改提交信息' \ --d 'from_path=text.rb' \ --d "sha=57426eb21e4ceabdf4b206f022077e0040" \ -http://localhost:3000/api/repositories/3938/update_file.json | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|filepath |是|string |文件相对于仓库的路径(或修改后的文件路径) | -|from_path |是|string |原文件相对于仓库的路径, 只有当需要修改原文件名称时,才需要该参数 | -|sha |是|string |文件的sha标识值 | -|content |是|string |内容 | -|message |否|string |提交说明 | -|branch |否|string |分支名称, branch和new_branch必须存在一个,且只能存在一个 | -|new_branch |否|string |新的分支名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|name |string|文件名| -|sha |string|提交文件的sha值| -|size |int|文件大小, 单位:B| -|content |string|base64编码后的文件内容| -|encoding |string|编码方式| -|commit |object|| -|-- message |string|提交备注说明信息| -|-- committer|object|| -|---- name |string|用户名| -|---- email |string|用户邮箱| -|---- date |string|文件创建时间| - - -返回值 -``` -{ - "name": "test1_create_file6.rb", - "sha": "57426eb21e4ceabdf4b206f022257e08077e0040", - "size": 16, - "content": "5o+Q5Lqk55qE5YaF5a65MQ==", - "encoding": "base64", - "commit": { - "message": "更改提交信息\n", - "author": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-08T07:05:15Z" - }, - "committer": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-08T07:05:15Z" - } - } -} -``` ---- - -### 删除仓库中的文件 -``` -DELETE /api/repositories/:id/delete_file -``` -*示例* -``` -curl -X DELETE \ --d 'filepath=test1_create_file12.rb' \ --d 'test delete file' \ --d 'sha=7b70509105b587e71f5692b9e8ab70851e321f64' \ -http://localhost:3000/api//api/repositories/3868/delete_file | jq -``` -*请求参数说明:* - -|参数名|必选|类型|说明| -|-|-|-|-| -|id |是|int |项目id | -|filepath |是|string |文件相对于仓库的路径 | -|message |否|string |提交说明 | -|branch |否|string |分支名称, 默认为master分支| -|new_branch |否|string |新的分支名称 | - - -*返回参数说明:* - -|参数名|类型|说明| -|-|-|-| -|sha |string|提交文件的sha值| -|commit |object|| -|-- message |string|提交备注说明信息| -|-- committer|object|| -|---- name |string|用户名| -|---- email |string|用户邮箱| -|---- date |string|文件创建时间| - - -返回值 -``` -{ - "commit": { - "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", - "message": "Delete 'test1_create_file11.rb'\n", - "author": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-08T07:57:34Z" - }, - "committer": { - "name": "18816895620", - "email": "2456233122@qq.com", - "date": "2020-01-08T07:57:34Z" - } - } -} -``` ---- +## License diff --git a/api_document.md b/api_document.md new file mode 100644 index 00000000..50a45573 --- /dev/null +++ b/api_document.md @@ -0,0 +1,4016 @@ +--- + + +# API文档 + +## 基本介绍 + +### 开发API服务地址: + +**** + + +响应状态说明: + +|字段|类型|说明| +|-|-|-| +|status |int |响应状态码,0:请求成功,-1: 请求失败| +|message |string |响应说明 | + + +### API接口 +--- + +#### 用户注册(通过其他平台) +``` +POST accounts/remote_register +``` +*示例* +```bash +curl -X POST \ +-d "email=2456233122@qq.com" \ +-d "password=djs_D_00001" \ +-d "username=16895620" \ +-d "platform=forge" \ +http://localhost:3000/api/accounts/remote_register | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|email |是|string |邮箱 | +|username |是|string |登录名 | +|password |是|string |秘密 | +|platform |否|string |用户来源的相关平台,取值范围['educoder', 'trustie', 'forge'], 默认值为forge | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|user|json object |返回数据| +|-- id |int |用户id | +|-- token |string|用户token| + + +返回值 +```json +{ + "status": 0, + "message": "success", + "user": { + "id": 36400, + "token": "8c87a80d9cfacc92fcb2451845104f35119eda96" + } +} +``` +--- + +#### 获取当前登录用户信息 +``` +GET api/users/me +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/users/me | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|user_id |int |用户id | +|username |string|用户名称| +|admin |boolean|是否为管理用户| +|login |string|登录名| +|image_url |string|用户头像| + + +返回值 +```json +{ + "username": "18816895620", + "login": "18816895620", + "user_id": 36401, + "image_url": "avatars/User/b", + "admin": false +} +``` +--- + +#### 用户列表(带搜索功能) +``` +GET api/users/list +``` +*示例* +```bash +curl -X GET \ +-d "limit=10" \ +-d "search=18816895620" +http://localhost:3000/api/users/list | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|page |否|int |页数,第几页 | +|limit |否|int |每页多少条数据,默认15条 | +|search |否|string |用户名、登录名匹配搜索 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |总用户条数 | +|users |array| | +|-- username |string|用户全名| +|-- login |string|用户登录名| +|-- user_id |int|用户id| +|-- image_url |string|用户头像| + +返回值 +```json +{ + "total_count": 1, + "users": [ + { + "username": "18816895620", + "login": "18816895620", + "user_id": 36401, + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +#### 获取项目类别列表(可根据名称搜素) +``` +GET api/project_categories +``` +*示例* +```bash +curl -X GET \ +-d "name=大数据" \ +http://localhost:3000/api/project_categories/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |类别名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_categories|array |返回数据| +|-- id |int |类别id | +|-- name |string|类别名称| + + +返回值 +```json +{ + "project_categories": [ + { + "id": 1, + "name": "大数据" + } + ] +} +``` +--- + +#### 获取项目语言列表(可根据名称搜素) +``` +GET api/project_languages +``` +*示例* +```bash +curl -X GET \ +-d "name=Ruby" \ +http://localhost:3000/api/project_languages/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |类别名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_languages|array |返回数据| +|-- id |int |语言id | +|-- name |string|语言名称| + + +返回值 +```json +{ + "project_languages": [ + { + "id": 1, + "name": "Ruby" + } + ] +} +``` +--- + +#### 获取.gitignore模板列表(可根据名称搜素) +``` +GET api/ignores +``` +*示例* +```bash +curl -X GET \ +-d "name=Ada" \ +http://localhost:3000/api/ignores/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |gitignore名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|ignores|array |返回数据| +|-- id |int |id | +|-- name |string|gitignore名称| + + +返回值 +```json +{ + "ignores": [ + { + "id": 1, + "name": "Ada" + } + ] +} +``` +--- + +#### 获取开源许可证列表(可根据名称搜素) +``` +GET api/licenses +``` +*示例* +```bash +curl -X GET \ +-d "name=AFL" \ +http://localhost:3000/api/licenses/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |开源许可证名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|licenses|array |返回数据| +|-- id |int |id | +|-- name |string|开源许可证名称| + + +返回值 +```json +{ + "licenses": [ + { + "id": 57, + "name": "AFL-1.2" + }, + { + "id": 76, + "name": "AFL-3.0" + }, + { + "id": 214, + "name": "AFL-1.1" + }, + { + "id": 326, + "name": "AFL-2.1" + }, + { + "id": 350, + "name": "AFL-2.0" + } + ] +} +``` +--- + +#### 创建项目 +``` +POST api/projects +``` +*示例* +```bash +curl -X POST \ +-d "user_id=36401" \ +-d "name=hnfl_demo" \ +-d "description=my first project" \ +-d "repository_name=hnfl_demo" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +-d "ignore_id=2" \ +-d "license_id=1" \ +http://localhost:3000/api/projects/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|user_id |是|int |用户id或者组织id | +|name |是|string |项目名称 | +|description |是|string |项目描述 | +|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|project_category_id|是|int |项目类别id | +|project_language_id|是|int |项目语言id | +|ignore_id |否|int |gitignore相关id | +|license_id |否|int |开源许可证id | +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| + + +返回值 +```json +{ + "id": 3240, + "name": "好项目" +} +``` +--- + +#### 新建镜像项目 +``` +POST api/projects/migrate +``` +*示例* +```bash +curl -X POST \ +-d "user_id=36408" \ +-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ +-d "name=golden_mirror1" \ +-d "description=golden_mirror" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +http://localhost:3000/api/projects/migrate.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|user_id |是|int |用户id或者组织id | +|name |是|string |项目名称 | +|clone_addr |是|string |镜像项目clone地址 | +|description |否|string |项目描述 | +|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|project_category_id|是|int |项目类别id | +|project_language_id|是|int |项目语言id | +|is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | +|auth_username |否|string|镜像源仓库的登录用户名 | +|auth_password |否|string|镜像源仓库的登录秘密 | +|private |否|boolean|项目是否私有, true:为私有,false: 非私有,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| + + +返回值 +```json +{ + "id": 3263, + "name": "ni项目" +} +``` + +--- +#### 手动同步镜像 +``` +POST api/repositories/:id/sync_mirror +``` +*示例* +```bash +curl -X POST http://localhost:3000/api/repositories/1244/sync_mirror | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |仓库id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |状态码, 0:标识请求成功 | +|message |string|服务端返回的信息说明| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` + +--- + +#### 项目详情 +``` +GET /api/:namespace_id/:id +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/jasder/jasder_test | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|namespace_id |是|string |用户登录名 | +|id |是|string |项目标识identifier | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| +|identifier |string|项目标识| +|is_public |boolean|项目是否公开, true:公开,false:私有| +|description |string|项目简介| +|repo_id |int|仓库id| +|repo_identifier|string|仓库标识| + + +返回值 +```json +{ + "name": "ni项目", + "identifier": "mirror_demo", + "is_public": true, + "description": "my first project mirror_demo", + "repo_id": 75073, + "repo_identifier": "mirror_demo" +} +``` +--- + +#### 项目详情(简版) +``` +GET /api/:namespace_id/:id/simple +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/jasder/jasder_test/simple | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| +|identifier |string|项目标识| +|is_public |boolean|项目是否公开, true:公开,false:私有| +|description |string|项目简介| +|repo_id |int|仓库id| +|repo_identifier|string|仓库标识| + + +返回值 +```json +{ + "identifier": "jasder_test", + "name": "jasder的测试项目", + "id": 4967, + "type": 0, + "author": { + "login": "jasder", + "name": "姓名", + "image_url": "avatars/User/b" + } +} +``` +--- + +#### 编辑仓库信息 +``` +GET /api/repositories/:id/edit.json +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/repositories/:id/edit.json | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string |仓库标识 | +|project_id |int|项目id| +|project_name |string|项目名称| +|project_identifier |string|项目标识| +|project_description |string|项目简介| +|project_category_id |int|项目类别id| +|project_language_id |int|项目语言id| +|private |boolean|项目是否私有, true:为私有,false: 公开 | + + +返回值 +```json +{ + "identifier": "mirror_demo", + "project_id": 3263, + "project_name": "ni项目", + "project_identifier": "mirror_demo", + "project_description": "my first project mirror_demo", + "project_category_id": 1, + "project_language_id": 2, + "private": false +} +``` +--- + +#### 修改项目信息 +``` +PATCH api/projects/:id +``` +*示例* +```bash +curl -X PATCH \ +-d "name=hnfl_demo" \ +-d "description=my first project" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +-d "private=true" \ +http://localhost:3000/api/projects/3263.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|name |否|string |项目名称 | +|description |否|string |项目描述 | +|project_category_id|否|int |项目类别id | +|project_language_id|否|int |项目语言id | +|default_branch |否|string |默认分支名称 | +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|id | +|identifier |string|项目标识| +|name |string|项目名称| +|description |string|项目简介| +|project_category_id|int|项目类别id| +|project_language_id|int|项目语言id| +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +返回值 +```json +{ + "id": 3263, + "identifier": "mirror_demo", + "name": "hnfl_demo", + "description": "my first project", + "project_category_id": 1, + "project_language_id": 2, + "is_public": true +} +``` +--- + +#### 删除项目 +``` +DELETE api/projects/:id +``` +*示例* +```bash +curl -X DELETE http://localhost:3000/api/projects/3263.json | jq +``` + +注:只有超级管理员和项目拥有者才能删除仓库 + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|返回状态, 0: 表示操作成功 | +|message |string|返回信息说明| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 项目添加成员 +``` +POST api/projects/:id/members +``` +*示例* +```bash +curl -X POST \ +-d "user_id=36406" \ +http://localhost:3000/api/projects/3297/members | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:添加成功, -1: 添加失败, 1: 表示已经是项目成员 | +|message |string|返回信息说明| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 项目删除成员 +``` +DELETE api/projects/:id/members/remove +``` +*示例* +```bash +curl -X DELETE \ +-d "user_id=36400" \ +http://localhost:3000/api/projects/3263/members/remove | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:移除成功, -1: 移除失败, 1: 表示还不是项目成员 | +|message |string|返回信息说明| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 更改项目成员角色/权限 +``` +PUT api/projects/:id/members/change_role +``` +*示例* +```bash +curl -X PUT \ +-d "user_id=36400" \ +-d "role=Developer" \ +http://localhost:3000/api/projects/3263/members/change_role | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | +|role |是|string |取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限) | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:角色更改成功, -1: 更改失败失败, 1: 表示还不是项目成员 | +|message |string|返回信息说明| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + + +#### 项目成员列表 +``` +GET api/projects/:id/members +``` +*示例* +```bash +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects/3263/members | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |返回记录总条数 | +|members |array|项目成员信息| +|-- id |int|用户id| +|-- name |string|用户名称| +|-- login |string|用户登录名/标识| +|-- image_url |string|用户头像| +|-- is_owner |boolean|是否是项目的拥有者,true:是, false:不是| +|-- role |string|该用户在项目中的角色, Manager: 管理员(拥有操作权限); Developer:开发人员(只拥有读写权限); Reporter:报告人员(只拥有读权限)| + + +返回值 +```json +{ + "total_count": 2, + "members": [ + { + "id": 36401, + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b", + "is_owner": true, + "role": "Manager" + }, + { + "id": 36399, + "name": "18816365620", + "login": "18816365620", + "image_url": "avatars/User/b", + "is_owner": false, + "role": "Developer" + } + ] +} +``` +--- + +#### Fork项目 +``` +POST /api/projects/:project_id/forks +``` +*示例* +```bash +curl -X POST http://localhost:3000/api/projects/3297/forks | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|project_id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |项目id | +|identifier |string|项目标识| + + +返回值 +```json +{ + "id": 3290, + "identifier": "newadm" +} +``` +--- + +#### 获取代码目录列表 +``` +POST /api/:namespace_id/:project_id/repository/entries +``` +*示例* +```bash +curl -X GET \ +-d "ref=develop" \ +http://localhost:3000//api/jasder/jasder_test/repository/entries | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|last_commit |object | | +|-- commit |object | | +|id |int |id | +|name |string|文件夹或文件名称| +|path |string|文件夹或文件相对路径| +|type |string|文件类型, file:文件,dir:文件目录| +|size |int|文件夹或文件大小 单位B| +|content |string|文件内容,| +|target |string|标签| + +返回值 +```json +{ + "last_commit": { + "commit": { + "sha": "3f2de4f78d2d7050486535082cd11cdfc9f3679e", + "url": "http://localhost:3003//api/repositories/api-cloud-platform/commits/3f2de4f78d2d7050486535082cd11cdfc9f3679e", + "message": "update README.md.", + "author": { + "name": "Gitee", + "email": "noreply@gitee.com", + "date": "2020-03-02T20:23:18+08:00" + }, + "committer": { + "name": "Gitee", + "email": "noreply@gitee.com", + "date": "2020-03-02T20:23:18+08:00" + }, + "timestamp": 1583151798, + "time_from_now": "3个月前" + }, + "author": null, + "committer": null + }, + "entries": [ + { + "name": "ace-gate", + "path": "ace-gate", + "sha": "c83f85fc63b14edcd6fc502eee9996f5a9993eca", + "type": "dir", + "size": 0, + "content": null, + "target": null, + "commit": { + "message": "v2.9 升级alibaba组件release版本\n", + "sha": "6117eaab86f71115f42f2a46ff1683015cda798d", + "created_at": "1970-01-01 08:00", + "time_from_now": "51年前", + "created_at_unix": null + } + }, + { + "name": "ace-sidecar", + "path": "ace-sidecar", + "sha": "38e41d7810876b464f8f1adcbf998e1b04f710a7", + "type": "dir", + "size": 0, + "content": null, + "target": null, + "commit": { + "message": "[Feature] 升级spring 版本&consul注册中心\n", + "sha": "c0a5dde35cfc87f7dbaf676aac397b184ba0e55b", + "created_at": "1970-01-01 08:00", + "time_from_now": "51年前", + "created_at_unix": null + } + }, + ... + ] +} +``` +--- + +#### 获取子目录代码列表/编辑某个具体的文件 +``` +GET /api/repositories/:id/sub_entries +``` +*示例* +```bash +curl -X GET \ +-d "ref=master" \ +-d "filepath=test1_create_file.rb" \ +http://localhost:3000/api/repositories/87/sub_entries.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件夹、文件的相对路径 | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|文件夹或文件名称| +|path |string|文件夹或文件相对路径| +|type |string|文件类型, file:文件,dir:文件目录| +|size |int|文件夹或文件大小 单位KB| +|content |string|文件内容,| +|target |string|标签| +|url |string|文件访问链接,带分支| +|html_url |string|文件访问链接,未标识分支| +|git_url |string|文件夹或文件的git仓库访问链接| +|download_url |string|文件下载、文件内容访问链接| + +返回值 +```json +[ + { + "name": "build.rc", + "path": "lib/build.rc", + "type": "", + "size": 1268, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/build.rc?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/build.rc", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/191fcf1a63b3777e2977fcede7dd5309efdd70fe", + "download_url": null + }, + { + "name": "cfg.rc", + "path": "lib/cfg.rc", + "type": "file", + "size": 107, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/cfg.rc?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/cfg.rc", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/0b91ba0ed1c00e130c77bb9058af3787fea986a0", + "download_url": "http://localhost:3003/18816895620/mirror_demo/raw/branch/master/lib/cfg.rc" + }, + { + "name": "fn", + "path": "lib/fn", + "type": "dir", + "size": 0, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/fn?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/fn", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/e33bd45949ef8f804471d0b6b2c59728eb445989", + "download_url": null + } +] +``` +--- + +#### 项目类别列表(用于项目列表左侧导航中的项目类别列表) +``` +GET api/project_categories/group_list +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/project_categories/group_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |项目分类id | +|name |string|项目分类名称| +|projects_count |int |项目数量| + + +返回值 +```json +[ + { + "id": 1, + "name": "大数据", + "projects_count": 30 + }, + { + "id": 2, + "name": "机器学习", + "projects_count": 1 + }, + { + "id": 3, + "name": "深度学习", + "projects_count": 1 + } +] +``` +--- + +#### 项目类型列表(用于项目列表左侧导航上方中的项目类型列表) +``` +GET api/projects/group_type_list +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/projects/group_type_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_type |string|项目类型 | +|name |string|项目类型名称| +|projects_count |int |项目数量| + + +返回值 +```json +[ + { + "project_type": "common", + "name": "开源托管项目", + "projects_count": 2106 + }, + { + "project_type": "mirror", + "name": "开源镜像项目", + "projects_count": 1 + } +] +``` +--- + +#### 项目列表 +``` +GET api/projects +``` +*示例* +```bash +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | +|sort_by |否|string |排序类型, 取值:updated_on \| created_on \| forked_count \| praises_count, updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | +|sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为:desc | +|search |否|string |按照项目名称搜索 | +|category_id |否|int |项目类别id | +|language_id |否|int |项目语言id | +|project_type |否|string |项目类型, 取值为:common \| mirror; common:开源托管项目, mirror:开源镜像项目 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |项目总条数 | +|id |string |项目id | +|name |string|项目名称| +|description |string|项目简介| +|visits |int|流量数| +|forked_count |int|被fork的数量| +|praises_count |int|star数量| +|is_public |boolean|是否公开, true:公开,false:未公开| +|mirror_url |string|镜像url| +|last_update_time|int|最后更新时间,为UNIX格式的时间戳| +|author |object|项目创建者| +|-- name |string|用户名,也是用户标识| +|category |object|项目类别| +|-- id |int|项目类型id| +|-- name |string|项目类型名称| +|language |object|项目语言| +|-- id |int|项目语言id| +|-- name |string|项目语言名称| + + +返回值 +```json +{ + "total_count": 3096, + "projects": [ + { + "id": 1, + "name": "hnfl_demo1", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577697461, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 2, + "name": "hnfl_demo", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577697403, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 3, + "name": "统计局", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577415173, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 5, + "name": "开源同名", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": false, + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "last_update_time": 1577346228, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 7, + "name": "开源支持", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577341572, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + } + ] +} +``` +--- + +#### 推荐项目 +``` +GET api/projects/recommend +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/projects/recommend | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |项目总条数 | +|id |string |项目id | +|name |string|项目名称| +|description |string|项目简介| +|visits |int|流量数| +|forked_count |int|被fork的数量| +|praises_count |int|star数量| +|is_public |boolean|是否公开, true:公开,false:未公开| +|mirror_url |string|镜像url| +|last_update_time|int|最后更新时间,为UNIX格式的时间戳| +|author |object|项目创建者| +|-- name |string|用户名,也是用户标识| +|category |object|项目类别| +|-- id |int|项目类型id| +|-- name |string|项目类型名称| +|language |object|项目语言| +|-- id |int|项目语言id| +|-- name |string|项目语言名称| + + +返回值 +```json +[ + { + "id": 20, + "repo_id": null, + "identifier": "PNAekinmH", + "name": "FNILL", + "visits": 13567, + "author": { + "name": "王一达", + "login": "wangyida", + "image_url": "avatars/User/b" + }, + "category": { + "id": 8, + "name": "其他" + } + }, + ... +] + +``` +--- + +#### 项目主页 +``` +GET api/:namespace_id/:id/about +``` + +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/:jason/forgeplus/about | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|namespace_id |是|string |用户登录名 | +|id |是|string |项目标识identifier | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string|project's identifier| +|content |string|主页内容| +|attachments |array|附件| +|-- name |string|用户名,也是用户标识| + + +返回值 +```json +{ + "content": "", + "identifier": "forgeplus", + attachments: [ + + ] +} + +``` +--- + +#### 修改项目主页内容 +``` +POST api/:namespace_id/:id/about +``` + +*示例* +```bash +curl -X POST \ +-d "content=内容" \ +-d "attachment_ids=[1, 2, 2]" \ +http://localhost:3000/api/:jasder/forgeplus/about | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|namespace_id |是|string |用户登录名 | +|id |是|string |项目标识identifier | +|content |是|string |内容信息 | +|attachment_ids |是|array |附件id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string|project's identifier| +|content |string|主页内容| +|attachments |array|附件| +|-- name |string|用户名,也是用户标识| + +返回值 +```json +{ + "content": "", + "identifier": "forgeplus", + attachments: [ + + ] +} + +``` +--- + +### 获取分支列表 +``` +GET /api/:namespace_id/:id/branches +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/jasder/jasder_test/branches | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|id |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|分支名称| +|user_can_push |boolean|用户是否可push| +|user_can_merge |boolean|用户是否客merge| +|protected |boolean|是否为保护分支| +|http_url |boolean|http链接| +|zip_url |boolean|zip包下载链接| +|tar_url |boolean|tar.gz下载链接| +|last_commit |object|最后提交记录| +|-- id |string|提交记录id| +|-- message |string|提交的说明信息| +|-- timestamp |int|提交时间,为UNIX时间戳| +|-- time_from_now|string|转换后的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +```json +[ + { + "name": "develop", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", + "last_commit": { + "id": "735674d6696bddbafa993db9c67b40c41246c77f", + "message": "FIX test branch content\n", + "timestamp": 1577694074, + "time_from_now": "1天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "name": "master", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", + "last_commit": { + "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", + "timestamp": 1577244567, + "time_from_now": "6天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + } +] +``` +--- + +### 获取代码库标签列表 +``` +GET /api/repositories/:id/tags +``` +*示例* +```bash +curl -X GET \ +-d "limit=20" \ +-d "page=1" \ +http://localhost:3000/api/repositories/5836/tags.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |仓库id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认20条 | + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|name |string|分支名称| +|user_can_push |boolean|用户是否可push| +|user_can_merge |boolean|用户是否客merge| +|protected |boolean|是否为保护分支| +|http_url |boolean|http链接| +|zip_url |boolean|zip包下载链接| +|tar_url |boolean|tar.gz下载链接| +|last_commit |object|最后提交记录| +|-- id |string|提交记录id| +|-- message |string|提交的说明信息| +|-- timestamp |int|提交时间,为UNIX时间戳| +|-- time_from_now|string|转换后的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +```json +[ + { + "name": "develop", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", + "last_commit": { + "id": "735674d6696bddbafa993db9c67b40c41246c77f", + "message": "FIX test branch content\n", + "timestamp": 1577694074, + "time_from_now": "1天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "name": "master", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", + "last_commit": { + "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", + "timestamp": 1577244567, + "time_from_now": "6天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + } +] +``` +--- + +## 仓库详情 +``` +GET /api/:namespace_id/:project_id/repository +``` +*示例* +```bash +curl -X GET \ +http://192.168.2.230:3000/api/jasder/forgeplus/repository | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|namespace_id |是|string |用户登录名 | +|project_id |是|string |项目标识identifier | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string|仓库标识| +|project_id |int|项目id| +|project_identifier|string|项目标识| +|praises_count |int|点赞数量| +|forked_count |int|fork数量| +|watchers_count |int|关注数量| +|branches_count |int|分支数量| +|commits_count |int|总提交记录数量| +|issues_count |int|总提交记录数量| +|pull_requests_count |int|总提交记录数量| +|praised |boolean|当前登录用户是否已点赞,true:已点赞,fasle:未点赞, 用户未登录状态为null| +|watched |boolean|当前登录用户是否已关注,true:已关注,fasle:未关注, 用户未登录状态为null| +|permission |string|当前登录用户对该仓库的操作权限, Manager:管理员,可以在线编辑文件、在线新建文件、可以设置仓库的基本信息; Developer:开发人员,可在线编辑文件、在线新建文件、不能设置仓库信息; Reporter: 报告人员,只能查看信息,不能设置仓库信息、不能在线编辑文件、不能在线新建文件;用户未登录时也会返回Reporter, 说明也只有读取文件的权限 | +|size |int|仓库文件大小,单位:KB| +|type |int|项目类型; 2: 表示是一个镜像(具备同步功能), 1: 普通镜像项目(不具同步功能), 0: 普通托管项目, 3: fork项目| +|mirror_status |int|该字段在type字段为2(一个镜像)时才会出现; 0: 表示同步镜像成功;1: 表示正在同步镜像;2: 同步失败| +|mirror_url |string|镜像地址, 只有通过镜像过来的项目才会有这个地址| +|ssh_url |string|仓库ssh地址| +|clone_url |string|仓库克隆地址| +|empty |boolean|仓库是否为空,true: 空仓库;false: 非空仓库| +|private |boolean|仓库是否私有,true: 私有仓库;fasle: 非私有的| +|default_branch |string|仓库默认分支| +|full_name |string|仓库全名(带用户名)| +|author |object|提交用户| +|-- login |string|用户login| +|-- name |string|用户姓名| +|-- image_url |string|用户头像| + + +返回值 +```json +{ + "identifier": "mirror_demo", + "project_id": 3263, + "project_identifier": "mirror_demo", + "praises_count": 1, + "forked_count": 0, + "watchers_count": 1, + "branches_count": 6, + "commits_count": 107, + "issues_count": 0, + "pull_requests_count": 0, + "permission": "Manager", + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "watched": true, + "praised": true, + "size": 446, + "ssh_url": "jasder@localhost:18816895620/mirror_demo.git", + "clone_url": "http://localhost:3003/18816895620/mirror_demo.git", + "default_branch": "master", + "empty": false, + "full_name": "18816895620/mirror_demo", + "mirror": false, + "private": false, + "author": { + "login": "18816895620", + "name": "美女", + "image_url": "avatars/User/b" + } +} +``` +--- + +## 获取提交记录列表 +``` +GET /api/repositories/:id/commits +``` +*示例* +```bash +curl -X GET \ +-d "sha=develop" \ +-d "page=1" \ +http://localhost:3000/api/repositories/89/commits.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|sha |否|string |分支名称、提交记录的sha标识,默认为master分支 | +|page |否|int |页数, 默认为1 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count|int|总记录条数| +|commits |array|提交记录的数组| +|-- sha |string|提交记录sha标识| +|-- message |string|提交的备注说明| +|-- timestamp |int|提交UNIX时间戳| +|-- time_from_now|string|提交距离当前的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +```json +{ + "total_count": 63, + "commits": [ + { + "sha": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试", + "timestamp": 1577244567, + "time_from_now": "7天前", + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "sha": "2b33c5f55214db41879936312ee43611406c4dbd", + "message": "FIX .", + "timestamp": 1577244474, + "time_from_now": "7天前", + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + } + } + ] +} +``` +--- + +## 获取某个提交记录(包含diff) +``` +GET /api/:owner/:repo/commits/:sha +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/jasder/repo/commits/b0c4a4a1487d53acebf2addc544b29938cad12df.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |仓库拥有者 | +|repo |是|string |仓库的identifier值 | +|sha |否|string |git的ref或者是提交记录commit的sha标识 | + + +*返回参数说明: 请参考compare接口* + + +返回值 +``` +{ + "files_count": 6, + "total_addition": 447, + "total_deletion": 0, + "commit": { + "sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968", + "message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n", + "author": { + "name": "Jasder", + "email": "2053003901@@qq.com", + "date": "2020-11-03T13:56:22+08:00" + }, + "committer": { + "name": "Jasder", + "email": "2053003901@@qq.com", + "date": "2020-11-03T13:56:22+08:00" + }, + "timestamp": 1604382982, + "time_from_now": "3天前" + }, + "author": null, + "committer": null, + "parents": [ + { + "sha": "c7f5b90725f30d8ad840a026773f9df92debc3af" + }, + "files": [ + { + "name": "build.go", + "old_name": "build.go", + "index": 1, + "addition": 33, + "deletion": 0, + "type": 1, + "isCreated": true, + "isDeleted": false, + "isBin": false, + "isLFSFile": false, + "isRenamed": false, + "isSubmodule": false, + "sections": [ + { + "fileName": "build.go", + "name": "", + "lines": [ + { + "leftIdx": 0, + "rightIdx": 0, + "type": 4, + "content": "@@ -0,0 +1,33 @@", + "sectionInfo": { + "path": "build.go", + "lastLeftIdx": 0, + "lastRightIdx": 0, + "leftIdx": 0, + "rightIdx": 1, + "leftHunkSize": 0, + "rightHunkSize": 33 + } + }, + { + "leftIdx": 0, + "rightIdx": 1, + "type": 2, + "content": "+// Copyright 2020 The Gitea Authors. All rights reserved.", + "sectionInfo": null + } + ] + } + ] + } + ] +} +``` +--- + +### 点赞 +``` +POST /api/projects/:id/praise_tread/like +``` +*示例* +```bash +curl -X POST http://localhost:3000/api/projects/3263/praise_tread/like | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 取消点赞 +``` +DELETE /api/projects/:id/praise_tread/unlike +``` +*示例* +```bash +curl -X DELETE http://localhost:3000/api/projects/3263/praise_tread/unlike | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 用户是否点过赞 +``` +GET /api/projects/:id/praise_tread/check_like +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/projects/3263/praise_tread/check_like | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|1:已点过赞,0:未点过赞, -1:请求操作失败| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 项目的点赞者列表 +``` +GET /api/projects/:id/praise_tread +``` +*示例* +```bash +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects/3263/praise_tread | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int|总条数| +|praises |array|点赞数据| +|-- name |string|用户名称| +|-- login |string|用户标识/登录名(login)| +|-- image_url |string|用户头像| + + + +返回值 +```json +{ + "total_count": 1, + "praises": [ + { + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +### 关注(项目) +``` +POST /api/projects/:id/watchers/follow +``` +*示例* +```bash +curl -X POST http://localhost:3000/api/projects/3263/watchers/follow | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| + + +返回值 +```json +{ + "status": 0, + "message": "响应成功" +} +``` +--- + +### 取消关注 +``` +DELETE /api/projects/:id/watchers/unfollow +``` +*示例* +```bash +curl -X DELETE http://localhost:3000//api/projects/3263/watchers/unfollow | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| + + +返回值 +```json +{ + "status": 0, + "message": "响应成功" +} +``` +--- + +### 用户是否关注过项目 +``` +GET /api/projects/:id/watchers/check_watch +``` +*示例* +```bash +curl -X GET http://localhost:3000/api/projects/3263/watchers/check_watch | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|1:已关注,0:未关注, -1:请求操作失败| + + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 项目的关注者列表 +``` +GET /api/projects/:id/watchers +``` +*示例* +```bash +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000//api/projects/3263/watchers | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int|总条数| +|watchers |array|关注数据| +|-- name |string|用户名称| +|-- login |string|用户标识/登录名(login)| +|-- image_url |string|用户头像| + + +返回值 +```json +{ + "total_count": 1, + "watchers": [ + { + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +### 仓库新建文件 +``` +POST /api/repositories/:id/create_file +``` +*示例* +```bash +curl -X POST \ +-d 'filepath=test1_create_file1.rb' \ +-d 'branch=master' \ +-d 'content=提交的内容' \ +-d 'message=test commit ' \ +http://localhost:3000/api/18816895620/mirror_demo/contents.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|string |项目id | +|filepath |是|string |文件相对于仓库的路径 | +|content |否|string |内容 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, branch和new_branch必须存在一个 | +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件名| +|sha |string|提交文件的sha值| +|size |int|文件大小, 单位:B| +|content |string|base64编码后的文件内容| +|encoding |string|编码方式| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + + +返回值 +```json +{ + "name": "test1_create_file12.rb", + "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", + "size": 12, + "content": "Wm5ObWMyRmtaZz09", + "encoding": "base64", + "commit": { + "message": "good luck\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-07T03:31:20Z" + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-07T03:31:20Z" + } + } +} +``` +--- + +### 更新仓库中的文件 +``` +PUT /api/repositories/:id/update_file.json +``` +*示例* +```bash +curl -X PUT \ +-d 'filepath=text1.rb' \ +-d 'branch=master' \ +-d 'content=ruby code' \ +-d 'message=更改提交信息' \ +-d 'from_path=text.rb' \ +-d "sha=57426eb21e4ceabdf4b206f022077e0040" \ +http://localhost:3000/api/repositories/3938/update_file.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件相对于仓库的路径(或修改后的文件路径) | +|from_path |是|string |原文件相对于仓库的路径, 只有当需要修改原文件名称时,才需要该参数 | +|sha |是|string |文件的sha标识值 | +|content |是|string |内容 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, branch和new_branch必须存在一个,且只能存在一个 | +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件名| +|sha |string|提交文件的sha值| +|size |int|文件大小, 单位:B| +|content |string|base64编码后的文件内容| +|encoding |string|编码方式| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + +返回值 +```json +{ + "name": "test1_create_file6.rb", + "sha": "57426eb21e4ceabdf4b206f022257e08077e0040", + "size": 16, + "content": "5o+Q5Lqk55qE5YaF5a65MQ==", + "encoding": "base64", + "commit": { + "message": "更改提交信息\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:05:15Z" + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:05:15Z" + } + } +} +``` +--- + +### 删除仓库中的文件 +``` +DELETE /api/repositories/:id/delete_file +``` +*示例* +```bash +curl -X DELETE \ +-d 'filepath=test1_create_file12.rb' \ +-d 'test delete file' \ +-d 'sha=7b70509105b587e71f5692b9e8ab70851e321f64' \ +http://localhost:3000/api//api/repositories/3868/delete_file | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件相对于仓库的路径 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, 默认为master分支| +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|sha |string|提交文件的sha值| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + +返回值 +```json +{ + "commit": { + "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", + "message": "Delete 'test1_create_file11.rb'\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:57:34Z"`` + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:57:34Z" + } + } +} +``` +--- + +### 获取pull request文件列表 +``` +GET /api/:owner/:repo/pulls/:id/files.json +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/Jason/test-txt/pulls/1/files.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|id |是|int |pull request's id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|files_count |int|文件更改的总数量| +|total_addition |int|添加代码总行数| +|total_deletion |int|删除代码总行数| +|files |array|| +|-- sha |string|commit's sha value| +|-- name |string|当前文件名| +|-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改| +|-- addition |int|文件添加的行数| +|-- deletion |int|文件删除的行数| +|-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容| +|-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否| +|-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否| +|-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否| +|-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否| +|-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否| +|-- sections |array|| +|---- fileName |string|文件名称| +|---- lines |array|| +|------ leftIdx |string|文件变动之前所在行数| +|------ rightIdx |string|文件更改后所在行数| +|------ type |string|文件变更类型,1: 新增,2: 修改, 3: 删除, 4: diff统计信息| +|------ content |string|文件变更的内容| +|------ sectionInfo |object|| +|-------- path |string|文件相对仓库的路径| +|-------- lastLeftIdx |int|| +|-------- lastRightIdx |int|| +|-------- leftHunkSize |int|文件变更之前的行数| +|-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)| +|-------- leftIdx |int|文件变更之前所在行数| +|-------- rightIdx |int|文件变更之后所在行数(即:页面编辑器开始显示的行数)| + + +返回值 +```json +{ + "files_count": 6, + "total_addition": 447, + "total_deletion": 0, + "files": [ + { + "sha": "xefenisnii", + "name": "文件.txt", + "old_name": "文件.txt", + "index": 6, + "addition": 2, + "deletion": 0, + "type": 1, + "isCreated": true, + "isDeleted": false, + "isBin": false, + "isLFSFile": false, + "isRenamed": false, + "isSubmodule": false, + "sections": [ + { + "fileName": "文件.txt", + "name": "", + "lines": [ + { + "leftIdx": 0, + "rightIdx": 0, + "type": 4, + "content": "@@ -0,0 +1,2 @@", + "sectionInfo": { + "path": null, + "lastLeftIdx": null, + "lastRightIdx": null, + "leftIdx": 0, + "rightIdx": 0, + "leftHunkSize": null, + "rightHunkSize": null + } + }, + { + "leftIdx": 0, + "rightIdx": 1, + "type": 2, + "content": "+用例图一致性更新", + "sectionInfo": null + }, + { + "leftIdx": 0, + "rightIdx": 2, + "type": 2, + "content": "+工程文件直接上传会有文件缺失,现在压缩后上传", + "sectionInfo": null + } + ] + } + ] + } + ] +} +``` +--- + +### 获取pull request的commits列表 +``` +GET /api/:owner/:repo/pulls/:id/commits.json +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/Jason/repo/1/commits.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|id |是|int |pull request's id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|commits_count |int|commits总数量| +|commits |array|| +|-- author |object|项目作者| +|---- login |string|用户login| +|---- name |string|用户姓名| +|---- image_url |string|用户头像| +|-- committer |object|commit提交用户| +|---- login |string|用户login| +|---- name |string|用户姓名| +|---- image_url |string|用户头像| +|-- timestamp |int|commit的unix时间戳| +|-- time_from_now|string|commit’s 提交时间距当前时间的时间值| +|-- message |string|commit说明信息| +|-- sha |string|commit’s sha值| + +返回值 +```json +{ + "commits_count": 1, + "commits": [ + { + "author": { + "id": 36480, + "login": "jasder", + "name": "段甲生", + "image_url": "avatars/User/b" + }, + "committer": { + "id": 36480, + "login": "jasder", + "name": "段甲生", + "image_url": "avatars/User/b" + }, + "timestamp": 1604382982, + "time_from_now": "3小时前", + "message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n", + "sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968" + } + ] +} +``` +--- + +### compare two commits +``` +GET /api/:owner/:repo/compare/{base}...{head}.json +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/Jason/test-txt/compare/master...develop | jq + +curl -X GET \ +http://localhost:3000/api/ysfns/test-txt/compare/master...Jason/test-txt:develop +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|base |是|string |pull request's id | +|head |是|string |pull request's id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|commits_count |int|commits总数量| +|commits |array|| +|-- author |object|项目作者| +|---- login |string|用户login| +|---- name |string|用户姓名| +|---- image_url |string|用户头像| +|-- committer |object|commit提交用户| +|---- login |string|用户login| +|---- name |string|用户姓名| +|---- image_url |string|用户头像| +|-- timestamp |int|commit的unix时间戳| +|-- time_from_now|string|commit’s 提交时间距当前时间的时间值| +|-- message |string|commit说明信息| +|-- sha |string|commit’s sha值| +|diff |object|| +|-- files_count |int|文件更改的总数量| +|-- total_addition |int|添加代码总行数| +|-- total_deletion |int|删除代码总行数| +|-- files |Array|| +|-- sha |string|commit's sha | +|-- name |string|当前文件名| +|-- old_name |string| 修改之前的文件名称,与name相同的话,说明文件名未更改| +|-- addition |int|文件添加的行数| +|-- deletion |int|文件删除的行数| +|-- type |int|文件类型, 1: 表示该文件只添加了内容,2: 表示该文件内容有修改, 3: 表示文件被删除或者改文件只删除了内容| +|-- isCreated |boolean|当前文件是否为新增文件, true: 是, false: 否| +|-- isDeleted |boolean|当前文件是否被删除, true: 是,false: 否| +|-- isBin |boolean|当前文件是否为二进制文件,true: 是,false: 否| +|-- isLFSFile |boolean|当前文件是否为LFS文件,true: 是,false: 否| +|-- isRenamed |boolean|当前文件是否被重命名,true: 是,false: 否| +|-- sections |array|| +|---- fileName |string|文件名称| +|---- lines |array|| +|------ leftIdx |string|文件变动之前所在行数| +|------ rightIdx |string|文件更改后所在行数| +|------ type |string|文件变更类型,1: 内容未改动,2: 添加, 3: 删除, 4: diff统计信息| +|------ content |string|文件变更的内容| +|------ sectionInfo |object|| +|-------- path |string|文件相对仓库的路径| +|-------- lastLeftIdx |int|| +|-------- lastRightIdx |int|| +|-------- leftHunkSize |int|文件变更之前的行数| +|-------- rightHunkSize |int|文件变更之后的行数(及当前页面编辑器显示的总行数)| +|-------- leftIdx |int|文件变更之前所在行数| +|-------- rightIdx |int|文件变更之后所在行数| + +返回值 +```json +{ + "commits_count": 1, + "commits": [ + { + "author": { + "id": 36480, + "login": "jasder", + "name": "段甲生", + "image_url": "avatars/User/b" + }, + "committer": { + "id": 36480, + "login": "jasder", + "name": "段甲生", + "image_url": "avatars/User/b" + }, + "timestamp": 1604382982, + "time_from_now": "4小时前", + "message": "add some file\n* Add the tag list page to the release page\n* Apply suggestions from code review\n* Add the tags list view\n* Add the delete tag way on ui\n* Not delete tag and clear message when delete a release\n", + "sha": "8f5faee0d3b3be1b8063e84da0c79dd75327b968" + } + ], + "diff": { + "files_count": 6, + "total_addition": 447, + "total_deletion": 0, + "files": [ + { + "name": "build.go", + "old_name": "build.go", + "index": 1, + "addition": 33, + "deletion": 0, + "type": 1, + "isCreated": true, + "isDeleted": false, + "isBin": false, + "isLFSFile": false, + "isRenamed": false, + "isSubmodule": false, + "sections": [ + { + "fileName": "build.go", + "name": "", + "lines": [ + { + "leftIdx": 0, + "rightIdx": 0, + "type": 4, + "content": "@@ -0,0 +1,33 @@", + "sectionInfo": { + "path": "build.go", + "lastLeftIdx": 0, + "lastRightIdx": 0, + "leftIdx": 0, + "rightIdx": 1, + "leftHunkSize": 0, + "rightHunkSize": 33 + } + }, + { + "leftIdx": 0, + "rightIdx": 1, + "type": 2, + "content": "+// Copyright 2020 The Gitea Authors. All rights reserved.", + "sectionInfo": null + } + ] + } + ] + } + ] + } +} +``` +--- + +### 创建保护分支 +``` +POST /api/:owner/:repo/protected_branches +``` +*示例* +```bash +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_usernames |否|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_usernames |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" +} +``` +--- + +### 编辑保护分支参数 +``` +GET /api/:owner/:repo/protected_branches/:branch_name/edit +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/trustie/truesite/protected_branches/master/edit.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |项目拥有者登录名 | +|repo |否|boolean |仓库名称 | +|branch_name |是|string |保护分支名称 | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|protected |boolean |是否为保护分支, true: 是; 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_usernames |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|更新时间| + + +返回值 +```json +{ + "branch_name": "master", + "protected": true, + "protected_branch": { + "branch_name": "master", + "enable_push": false, + "required_approvals": 0, + "enable_status_check": true, + "enable_push_whitelist": false, + "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": [], + "approvals_whitelist_usernames": [], + "created_at": "2020-12-03 12:00", + "updated_at": "2020-12-04 10:50" + } +} +``` +--- + +### 修改保护分支参数 +``` +PATCH /api/:owner/:repo/protected_branches/:branch_name +``` +*示例* +```bash +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_usernames |否|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_usernames |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|更新时间| + + +返回值 +```json +{ + "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 +``` +*示例* +```bash +curl -X DELETE \ +http://localhost:3000/api/trustie/truesite/protected_branches/master.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |项目拥有者登录名 | +|repo |否|boolean |仓库名称 | +|branch_name |是|string |保护分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|状态值,0: 请求成功; -1: 请求失败| +|message |string|信息说明| + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 获取保护分支列表 +``` +GET /api/:owner/:repo/protected_branches/ +``` +*示例* +```bash +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_usernames |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" + } + ] +} +``` +--- + +### 获取某个具体的保护分支 +``` +GET /api/:owner/:repo/protected_branches/:branch_name +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/trustie/truesite/protected_branches/master.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |项目拥有者登录名 | +|repo |否|boolean |仓库名称 | +|branch_name |是|string |保护分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|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_usernames |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|更新时间| + +返回值 +```json +{ + "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流程步骤 +``` +GET /api/:owner/:repo/ci_authorize +``` + +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/jasder/forgeplus/ci_authorize.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|step |int|初始化devops流程步骤; 0: 标识未开启devops,1: 标识用户已填写了云服务器相关信息,但并未开启认证, 2: 标识用户已开启了CI服务端的认证| +|account |string|你的云服务器帐号| +|ip |string|你的云服务器帐号ip| +|secret |string|你的云服务器登录密码| +|authenticate_url |string|devops授权认证地址, 只有填写了服务器相关信息后才会有该地址| +|get_drone_token_url |string|获取CI服务端token地址, 只有认证成功后才会有该地址| + +返回值 +```json +{ + "step": 0, + "cloud_account": { + "id": 1, + "account": "xxx", + "ip": "xxx.xxx.xxx.x", + "secret": "11111", + "authenticate_url": "http://localhost:3000/login", + "get_drone_token_url": "http://localhost:3000/account" + } +} +``` +--- + +#### 初始化DevOps流程 +``` +POST /api/:owner/:repo/cloud_accounts +``` + +*示例* +```bash +curl -X POST \ +-d "account=xx" \ +-d "secret=xxx" \ +-d "ip_num=xx.xx.xx.xx" \ +https://localhost:3000/api/jasder/forgeplus/cloud_accounts.json | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|account |是|string |云服务器ssh连接登录用户名 | +|secret |是|string |云服务器ssh连接登录秘密 | +|ip_num |否|string |云服务器公网IP | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |string|服务端返回状态,0: 表示请求成功, -1: 标识请求失败| +|message |string|服务端返回信息说明| +|redirect_url |string|重定向地址,请求成功后,需要调整到该地址进行认证| + +返回值 +```json +{ + "status": 0, + "message": "success", + "redirect_url": "http://192.168.2.59:3003/login/oauth/authorize?client_id=f0c58484-d0f7-46c0-9efd-de3e3218e723&redirect_uri=http://121.36.81.172:80/login&response_type=code" +} +``` +--- + +#### devops用户认证授权 +``` +GET /api/users/ci/oauth_grant +``` +*示例* +```bash +curl -X GET \ +-d "password=123456" \ +http://localhost:3000/api/users/ci/oauth_grant.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|password |是|string |用户密码 | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:成功, -1: 失败| + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 激活项目 +``` +POST /api/:owner/:repo/activate +``` +*示例* +```bash +curl -X POST \ +http://localhost:3000/api/jasder/forgeplus/activate.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:成功, -1: 失败| + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 取消激活项目 +``` +DELETE /api/:owner/:repo/deactivate +``` +*示例* +```bash +curl -X POST \ +http://localhost:3000/api/jasder/forgeplus/deactivate.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:成功, -1: 失败| + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 获取仓库的.trustie-pipeline.yml +``` +GET /api/:owner/:repo/get_trustie_pipeline +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/jasder/forge/get_trustie_pipeline.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件夹或文件名称| +|path |string|文件夹或文件相对路径| +|content |string|文件内容,| + +返回值 +```json +{ + "name": ".trustie-pipeline.yml", + "path": ".trustie-pipeline.yml", + "sha": "548sfefsafef48sf485s4f", + "content": "..jsaf" +} +``` +--- + +#### 更新'.trustie-pipeline.yml'文件 +``` +PUT /api/:owner/:repo/update_trustie_pipeline +``` +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/jasder/forge/update_trustie_pipeline.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |用户登录名 | +|repo |是|string |project's identifier | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | +|filepath |是|string |文件相对于仓库的路径(或修改后的文件路径) | +|from_path |是|string |原文件相对于仓库的路径, 只有当需要修改原文件名称时,才需要该参数 | +|sha |是|string |文件的sha标识值 | +|content |是|string |内容 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, branch和new_branch必须存在一个,且只能存在一个 | +|new_branch |否|string |新的分支名称 | +|ci_language_id |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|接口返回状态, 1: 请求成功, -1: 请求失败| +|message |string|文件夹或文件相对路径| + +``` +{ + "status": 1, + "message": ".trustie-pipeline.yml" +} +``` +--- + +#### 获取语言列表 +``` +GET /api/ci/languages +``` + +*示例* +```bash +curl -X GET http://localhost:3000/api/ci/languages.json | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|id值| +|name |string|语言名称| +|content |string|语言内容| +|cover_url |string|语言的logo链接| + +返回值 +```json +[ + { + "id": 114, + "name": "C", + "cover_url": null, + "content": "kind: pipeline\n name: default\n\n platform:\n os: linux\n arch: arm64\n\n steps:\n - name: test\n image: gcc\n commands:\n - ./configure\n - make\n - make test", + } +] +``` +--- + +#### 获取常用的6大语言 +``` +GET /api/ci/languages/common +``` + +*示例* +```bash +curl -X GET http://localhost:3000/api/ci/languages/common.json | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|id值| +|name |string|语言名称| +|content |string|语言内容| +|cover_url |string|语言的logo链接| + +返回值 +```json +[ + { + "id": 114, + "name": "C", + "cover_url": null, + "content": "kind: pipeline\n name: default\n\n platform:\n os: linux\n arch: arm64\n\n steps:\n - name: test\n image: gcc\n commands:\n - ./configure\n - make\n - make test", + } +] +``` +--- + +#### 获取语言详情 +``` +GET /api/ci/languages/:id +``` + +*示例* +```bash +curl -X GET http://localhost:3000/api/ci/languages/114.json | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |language's id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|id值| +|name |string|语言名称| +|content |string|语言内容| +|cover_url |string|语言的logo链接| + +返回值 +```json +[ + { + "id": 114, + "name": "C", + "cover_url": null, + "content": "kind: pipeline\n name: default\n\n platform:\n os: linux\n arch: arm64\n\n steps:\n - name: test\n image: gcc\n commands:\n - ./configure\n - make\n - make test", + } +] +``` +--- + +#### 获取构建列表 +``` +GET /api/:owner/:repo/builds +``` + +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/Jason/forge/builds | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|owner |是|string |项目拥有者 | +|repo |是|string |项目identifier | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认20条 | +|search |是|string |构建状态条件过滤; 值说明:pending: 准备中,failure: 构建失败,running: 运行中,error:构建失败(.trustie-pipeline.yml文件错误),success: 构建成功,killed: 撤销构建 | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|build's id| +|number |string|build's number| +|status |string|build's result| +|event |string|build's event| + +返回值 +```json +[ + { + "id": 1, + "repo_id": 8, + "trigger": "@hook", + "number": 1, + "status": "success", + "event": "push", + "action": "", + "link": "", + "timestamp": 0, + "message": "更新 '.trustie-pipeline.yml'\n", + "before": "5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324", + "after": "5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "ref": "refs/heads/master", + "source_repo": "", + "source": "master", + "target": "master", + "author_login": "jasder", + "author_name": "jasder", + "author_email": "email.com", + "author_avatar": "", + "sender": "jasder", + "started": "2020-08-19 06:22", + "finished": "2020-08-19 06:22", + "created": "2020-08-19 06:22", + "updated": "2020-08-19 06:22", + "duration_time": 0, + "version": 3 + } +] +``` +--- + +#### 获取某条构建详情信息 +``` +GET /api/:owner/:repo/builds/:build +``` + +*示例* +```bash +curl -X GET \ +http://ocalhost:3000/api/jasder/forge/builds/1 | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|build |是|int |build's number | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|build's id| +|status |string|build's status| +|event |string|build's event| + +返回值 +```json +{ + "id": 1, + "repo_id": 8, + "trigger": "@hook", + "number": 1, + "status": "success", + "event": "push", + "action": "", + "link": "http://localhost:3000/jasder/forgeplus/compare/5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324...5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "timestamp": 0, + "message": "更新 '.trustie-pipeline.yml'\n", + "before": "5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324", + "after": "5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "ref": "refs/heads/master", + "source_repo": "", + "source": "master", + "target": "master", + "author_login": "jasder", + "author_name": "jasder", + "author_email": "2053003901@qq.com", + "author_avatar": "http://localhost:3000/user/avatar/jasder/-1", + "sender": "jasder", + "started": 1595317786, + "finished": 1595318426, + "created": 1595317786, + "updated": 1595317786, + "version": 3, + "stages": [ + { + "id": 1, + "repo_id": 8, + "build_id": 1, + "number": 1, + "name": "default", + "kind": "pipeline", + "type": "docker", + "status": "success", + "errignore": false, + "exit_code": 0, + "machine": "121.36.81.172", + "os": "linux", + "arch": "arm64", + "started": 1595317786, + "stopped": 1595318426, + "created": 1595317786, + "updated": 1595318426, + "version": 4, + "on_success": true, + "on_failure": false, + "steps": [ + { + "id": 1, + "step_id": 1, + "number": 1, + "name": "clone", + "status": "success", + "exit_code": 0, + "started": 1595317786, + "stopped": 1595318373, + "version": 4 + }, + { + "id": 2, + "step_id": 1, + "number": 2, + "name": "test", + "status": "success", + "exit_code": 0, + "started": 1595318373, + "stopped": 1595318426, + "version": 4 + } + ] + } + ] +} +``` +--- + +#### 重启构建/重新构建 +``` +POST /api/:owner/:repo/builds/:build/restart +``` + +*示例* +```bash +curl -X POST \ +http://localhost:3000/api/jasder/forgeplus/builds/1 | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|build |是|int |build's number | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|build's id| +|status |string|build's status| +|event |string|build's event| + +返回值 +```json +{ + "id": 2, + "repo_id": 8, + "trigger": "jasder", + "number": 2, + "status": "pending", + "event": "push", + "action": "", + "link": "http://localhost:3000/jasder/forgeplus/compare/5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324...5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "timestamp": 0, + "message": "更新 '.trustie-pipeline.yml'\n", + "before": "5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324", + "after": "5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "ref": "refs/heads/master", + "source_repo": "", + "source": "master", + "target": "master", + "author_login": "jasder", + "author_name": "jasder", + "author_email": "2053003901@qq.com", + "author_avatar": "http://localhost:3000/user/avatar/jasder/-1", + "sender": "jasder", + "started": 0, + "finished": 0, + "created": 1595321350, + "updated": 1595321350, + "version": 1 +} +``` +--- + +#### 关闭构建 +``` +DELETE /api/:owner/:repo/builds/:build/stop +``` + +*示例* +```bash +curl -X DELETE \ +http://localhost:3000/api/jaser/forge/builds/2 | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|build |是|int |build's number | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|build's id| +|status |string|build's status| +|event |string|build's event| + +返回值 +```json +{ + "id": 2, + "repo_id": 8, + "trigger": "jasder", + "number": 2, + "status": "killed", + "event": "push", + "action": "", + "link": "http://localhost:3000/jasder/forgeplus/compare/5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324...5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "timestamp": 0, + "message": "更新 '.trustie-pipeline.yml'\n", + "before": "5e7c6f7dfd5ce6cc6e287fcbc000dadd9992b324", + "after": "5e52ce51a239f5c8dd0b489a8a71e94f976179b4", + "ref": "refs/heads/master", + "source_repo": "", + "source": "master", + "target": "master", + "author_login": "jasder", + "author_name": "jasder", + "author_email": "2053003901@qq.com", + "author_avatar": "http://localhost:3000/user/avatar/jasder/-1", + "sender": "jasder", + "started": 1595321352, + "finished": 1595321590, + "created": 1595321350, + "updated": 1595321352, + "version": 3, + "stages": [ + { + "id": 2, + "repo_id": 8, + "build_id": 2, + "number": 1, + "name": "default", + "kind": "pipeline", + "type": "docker", + "status": "killed", + "errignore": false, + "exit_code": 0, + "machine": "121.36.81.172", + "os": "linux", + "arch": "arm64", + "started": 1595321352, + "stopped": 1595321590, + "created": 1595321350, + "updated": 1595321352, + "version": 4, + "on_success": true, + "on_failure": false, + "steps": [ + { + "id": 3, + "step_id": 2, + "number": 1, + "name": "clone", + "status": "killed", + "exit_code": 130, + "started": 1595321353, + "stopped": 1595321590, + "version": 3 + }, + { + "id": 4, + "step_id": 2, + "number": 2, + "name": "test", + "status": "skipped", + "exit_code": 130, + "started": 1595321590, + "stopped": 1595321590, + "version": 2 + } + ] + } + ] +} +``` +--- + +#### 获取某条构建的log信息 +``` +GET /api/:owner/:repo/builds/:build/logs/:stage/:step +``` + +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/dev_ops/builds/2/logs/1/1 | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|build |是|int |build's number | +|stage |是|int |build's stage number | +|step |是|int |build's step number | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|build's id| +|status |string|build's status| +|event |string|build's event| + +返回值 +```json +[ + { + "pos": 0, + "out": "+ git fetch origin +refs/heads/master:\n", + "time": 1 + }, + { + "pos": 1, + "out": "Initialized empty Git repository in /drone/src/.git/\n", + "time": 1 + }, + { + "pos": 2, + "out": "warning: redirecting to https://testgitea2.trustie.net/jasder/forgeplus.git/\n", + "time": 1 + }, + { + "pos": 3, + "out": "From http://testgitea2.trustie.net/jasder/forgeplus\n", + "time": 493 + }, + { + "pos": 4, + "out": " * branch master -> FETCH_HEAD\n", + "time": 493 + }, + { + "pos": 5, + "out": " * [new branch] master -> origin/master\n", + "time": 493 + }, + { + "pos": 6, + "out": "+ git checkout 5e52ce51a239f5c8dd0b489a8a71e94f976179b4 -b master\n", + "time": 493 + }, + { + "pos": 7, + "out": "Already on 'master'\n", + "time": 496 + } +] +``` +--- + +#### 获取CI服务器配置信息 +``` +GET /api/users/ci/cloud_account +``` + +*示例* +```bash +curl -X GET \ +http://localhost:3000/api/users/ci/cloud_account | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|step |int|0: 未绑定;1: 未认证(已绑定)| +|ci_certification |boolean|true: 已认证, false: 未认证| +|ip |string|ci服务器ip| +|redirect_url |string|认证地址| + +返回值 +```json +{ + "step": 0, + "ci_certification": false, + "cloud_account": { + "ip": "xxx.xxx.xxx.x", + "redirect_url": "http://localhost:3000/login", + } +} +``` +--- + +#### 绑定CI服务器 +``` +POST /api/users/ci/cloud_account/bind +``` + +*示例* +```bash +curl -X POST \ +-d "account=xx" \ +-d "secret=xxx" \ +-d "ip_num=xx.xx.xx.xx" \ +https://localhost:3000/api/users/ci/cloud_account/bind.json | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|account |是|string |云服务器ssh连接登录用户名 | +|secret |是|string |云服务器ssh连接登录秘密 | +|ip_num |否|string |云服务器公网IP | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|step |int|0: 未绑定;1: 未认证(已绑定),2: 已认证| +|ip |string|ci服务器ip| +|redirect_url |string|认证地址| + +返回值 +```json +{ + "step": 0, + "cloud_account": { + "ip": "xxx.xxx.xxx.x", + "redirect_url": "http://localhost:3000/login", + } +} +``` +--- + + +### 解除CI服务器绑定 +``` +DELETE /api/users/ci/cloud_account/unbind +``` + +*示例* +```bash +curl -X DELETE \ +http://localhost:3000/api/users/ci/cloud_account/unbind.json | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|状态码, 0: 成功,-1: 失败| +|message |string|返回信息说明| + +返回值 +```json +{ + "status": 0, + "message": "success" +} +``` +--- + +### 项目列表 +``` +GET /api/users/:login/projects +``` + +*示例* +```bash +curl -X GET \ +-d "page=1" \ +-d "limit=20" \ +http://localhost:3000/api/users/Jason/projects.json | jq +``` + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|page |否|int |页数,第几页 | +|limit |否|int |每页多少条数据,默认20条 | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |项目总条数 | +|id |string |项目id | +|name |string|项目名称| +|description |string|项目简介| +|open_devops |boolean|激活状态,true: 激活; false:未激活| +|visits |int|流量数| +|forked_count |int|被fork的数量| +|praises_count |int|star数量| +|is_public |boolean|是否公开, true:公开,false:未公开| +|mirror_url |string|镜像url| +|last_update_time|int|最后更新时间,为UNIX格式的时间戳| +|author |object|项目创建者| +|-- name |string|用户名,也是用户标识| +|category |object|项目类别| +|-- id |int|项目类型id| +|-- name |string|项目类型名称| +|language |object|项目语言| +|-- id |int|项目语言id| +|-- name |string|项目语言名称| + + +返回值 +```json +{ + "total_count": 3096, + "projects": [ + { + "id": 1, + "name": "hnfl_demo1", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577697461, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + } + ] +} +``` +--- diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 99de5a64..d1753ff1 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -110,33 +110,33 @@ class AccountsController < ApplicationController # params[:login] 邮箱或者手机号 # params[:code] 验证码 # code_type 1:注册手机验证码 8:邮箱注册验证码 + # 本地forge注册入口 def register begin # 查询验证码是否正确;type只可能是1或者8 type = phone_mail_type(params[:login].strip) - code = params[:code].strip + # code = params[:code].strip if type == 1 uid_logger("start register by phone: type is #{type}") pre = 'p' email = nil phone = params[:login] - verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last + # verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last + # TODO: 暂时限定邮箱注册 + return normal_status(-1, '只支持邮箱注册') else uid_logger("start register by email: type is #{type}") pre = 'm' email = params[:login] phone = nil - verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last + return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login]) + return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL + # verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last end - uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") + # uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}") # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60) # todo 上线前请删除万能验证码"513231" - unless code == "513231" && request.subdomain == "test-newweb" - return normal_status(-2, "验证码不正确") if verifi_code.try(:code) != code.strip - return normal_status(-2, "验证码已失效") if !verifi_code&.effective? - end - return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD code = generate_identifier User, 8, pre @@ -146,23 +146,20 @@ class AccountsController < ApplicationController # 现在因为是验证码,所以在注册的时候就可以激活 @user.activate # 必须要用save操作,密码的保存是在users中 - if @user.save! - # todo user_extension - UserExtension.create!(user_id: @user.id) - # 注册完成,手机号或邮箱想可以奖励500金币 - # RewardGradeService.call( - # @user, - # container_id: @user.id, - # container_type: pre == 'p' ? 'Phone' : 'Mail', - # score: 500 - # ) - # 注册时,记录是否是引流用户 - ip = request.remote_ip - ua = UserAgent.find_by_ip(ip) - ua.update_column(:agent_type, UserAgent::USER_REGISTER) if ua - successful_authentication(@user) - # session[:user_id] = @user.id - normal_status("注册成功") + + interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]}) + if interactor.success? + gitea_user = interactor.result + result = Gitea::User::GenerateTokenService.new(login, params[:password]).call + @user.gitea_token = result['sha1'] + @user.gitea_uid = gitea_user['id'] + if @user.save! + UserExtension.create!(user_id: @user.id) + successful_authentication(@user) + normal_status("注册成功") + end + else + tip_exception(-1, interactor.error) end rescue Exception => e uid_logger_error(e.message) diff --git a/app/controllers/admins/laboratories_controller.rb b/app/controllers/admins/laboratories_controller.rb index 1c314ede..f397b0f3 100644 --- a/app/controllers/admins/laboratories_controller.rb +++ b/app/controllers/admins/laboratories_controller.rb @@ -6,6 +6,12 @@ class Admins::LaboratoriesController < Admins::BaseController @laboratories = paginate laboratories.preload(:laboratory_users) end + def new + respond_to do |format| + format.js + end + end + def create Admins::CreateLaboratoryService.call(create_params) render_ok diff --git a/app/controllers/admins/laboratory_settings_controller.rb b/app/controllers/admins/laboratory_settings_controller.rb index 283afc17..861db50c 100644 --- a/app/controllers/admins/laboratory_settings_controller.rb +++ b/app/controllers/admins/laboratory_settings_controller.rb @@ -1,4 +1,11 @@ class Admins::LaboratorySettingsController < Admins::BaseController + + def new + respond_to do |format| + format.js + end + end + def show @laboratory = current_laboratory end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 293ac6a7..8c552512 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,7 +10,7 @@ class ApplicationController < ActionController::Base include LoggerHelper include LoginHelper include RegisterHelper - + protect_from_forgery prepend: true, unless: -> { request.format.json? } before_action :check_sign @@ -343,7 +343,8 @@ class ApplicationController < ActionController::Base elsif params[:debug] == 'student' User.current = User.find 8686 elsif params[:debug] == 'admin' - user = User.find 1 + logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....." + user = User.find 36480 User.current = user cookies.signed[:user_id] = user.id end @@ -384,11 +385,7 @@ class ApplicationController < ActionController::Base end def current_user - if Rails.env.development? - User.current = User.find 1 - else - User.current - end + User.current end ## 默认输出json @@ -744,12 +741,12 @@ class ApplicationController < ActionController::Base namespace = params[:owner] id = params[:repo] || params[:id] - @project = Project.find_with_namespace(namespace, id) + @project, @owner = Project.find_with_namespace(namespace, id) if @project and current_user.can_read_project?(@project) logger.info "###########: has project and can read project" @project - elsif current_user.is_a?(AnonymousUser) + elsif @project && current_user.is_a?(AnonymousUser) logger.info "###########:This is AnonymousUser" @project = nil if !@project.is_public? render_forbidden and return @@ -762,7 +759,7 @@ class ApplicationController < ActionController::Base end def load_repository - @repository ||= load_project.repository + @repository ||= load_project&.repository end private diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index e01ef774..aeaab0c6 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -2,7 +2,7 @@ # # 文件上传 class AttachmentsController < ApplicationController - before_action :require_login, :check_auth, except: [:show] + before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file] before_action :find_file, only: %i[show destroy] before_action :attachment_candown, only: [:show] skip_before_action :check_sign, only: [:show, :create] @@ -28,6 +28,15 @@ class AttachmentsController < ApplicationController update_downloads(@file) end + + def get_file + normal_status(-1, "参数缺失") if params[:download_url].blank? + url = URI.encode(params[:download_url].to_s.gsub("http:", "https:")) + response = Faraday.get(url) + filename = params[:download_url].to_s.split("/").pop() + send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment') + end + def create # 1. 本地存储 # 2. 上传到云 @@ -107,6 +116,26 @@ class AttachmentsController < ApplicationController end end + # 附件为视频时,点击播放 + def preview_attachment + attachment = Attachment.find_by(id: params[:id]) + dir_path = "#{Rails.root}/public/preview" + Dir.mkdir(dir_path) unless Dir.exist?(dir_path) + if params[:status] == "preview" + if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/") + render json: {status: 1, url: "/preview/#{attachment.disk_filename}"} + else + normal_status(-1, "出现错误,请稍后重试") + end + else + if system("rm -rf #{dir_path}/#{attachment.disk_filename}") + normal_status(1, "操作成功") + else + normal_status(-1, "出现错误,请稍后重试") + end + end + end + private def find_file @file = diff --git a/app/controllers/ci/base_controller.rb b/app/controllers/ci/base_controller.rb new file mode 100644 index 00000000..6f18db04 --- /dev/null +++ b/app/controllers/ci/base_controller.rb @@ -0,0 +1,48 @@ +class Ci::BaseController < ApplicationController + include Ci::DbConnectable + + before_action :require_login + before_action :connect_to_ci_database, if: -> { current_user && !current_user.is_a?(AnonymousUser) && !current_user.devops_uninit? } + before_action :connect_to_ci_database, only: :load_repo + + def load_repo + namespace = params[:owner] + id = params[:repo] || params[:id] + + @ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id) + end + + private + def authorize_access_project! + unless @project.manager?(current_user) + return render_forbidden + end + end + + def authenticate_manager! + unless @project.manager?(current_user) + return render_forbidden + end + end + + def authenticate_admin! + return render_forbidden unless current_user.admin? + end + + def authorize_owner! + unless @project.owner?(current_user) + return render_forbidden + end + end + + def find_cloud_account + @cloud_account ||= current_user.ci_cloud_account + @cloud_account.blank? ? nil : @cloud_account + end + + def load_ci_user + @ci_user ||= Ci::User.find_by(user_login: params[:owner]) + @ci_user.blank? ? raise("未找到相关的记录") : @ci_user + end + +end diff --git a/app/controllers/ci/builds_controller.rb b/app/controllers/ci/builds_controller.rb new file mode 100644 index 00000000..4900a890 --- /dev/null +++ b/app/controllers/ci/builds_controller.rb @@ -0,0 +1,54 @@ +class Ci::BuildsController < Ci::BaseController + include RepositoriesHelper + + before_action :load_project + before_action :authorize_owner!, only: [:restart, :stop] + before_action :load_repo + before_action :find_cloud_account, except: [:index, :show] + + def index + @user = current_user + scope = @repo.builds + + scope = Ci::Builds::ListQuery.call(@repo, params) + + @total_count = scope.map(&:build_id).size + @builds = paginate scope + end + + def show + @build = @repo.builds.includes(stages: [:steps]).find_by(build_number: params[:build]) + end + + def restart + result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).restart + + render json: result + end + + def stop + result = Ci::Drone::API.new(@ci_user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, number: params[:build]).stop + render json: result + end + + def logs + # TODO **待优化** + # 因直接操作ci库,如下查询待优化,可直接根据log id查询即可 + build = @repo.builds.find_by(build_number: params[:build]) + return render_not_found("Couldn't found build with 'number'= #{params[:build]}") if build.blank? + + stage = build.stages.includes(steps: [:log]).find_by(stage_number: params[:stage]) + return render_not_found("Couldn't found build with 'number'= #{params[:stage]}") if stage.blank? + + step = stage.steps.find_by(step_number: params[:step]) + return render_not_found("Couldn't found build with 'number'= #{params[:step]}") if step.blank? + + log = step.log + + result = log.blank? ? nil : (log.log_data[0..5].include?('null') ? nil : JSON.parse(log.log_data)) + + # result = Ci::Drone::API.new(@user.user_hash, @cloud_account.drone_url, @repo.repo_namespace, @repo.repo_name, build: params[:build], stage: params[:stage], step: params[:step]).logs + + render json: result + end +end diff --git a/app/controllers/ci/cloud_accounts_controller.rb b/app/controllers/ci/cloud_accounts_controller.rb new file mode 100644 index 00000000..a1429078 --- /dev/null +++ b/app/controllers/ci/cloud_accounts_controller.rb @@ -0,0 +1,101 @@ +class Ci::CloudAccountsController < Ci::BaseController + include Ci::CloudAccountManageable + + skip_before_action :connect_to_ci_database, only: %i[create bind] + before_action :load_project, only: %i[create activate] + before_action :authorize_owner!, only: %i[create activate] + before_action :load_repo, only: %i[activate] + before_action :find_cloud_account, only: %i[show oauth_grant] + before_action :validate_params!, only: %i[create bind] + before_action only: %i[create bind] do + connect_to_ci_database(master_db: true) + end + + def create + flag, msg = check_bind_cloud_account! + return render_error(msg) if flag === true + + ActiveRecord::Base.transaction do + @cloud_account = bind_account! + if @cloud_account.blank? + render_error('激活失败, 请检查你的云服务器信息是否正确.') + raise ActiveRecord::Rollback + else + current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) + render_ok(redirect_url: @cloud_account.authenticate_url) + end + end + rescue Exception => ex + render_error(ex.message) + end + + def activate + return render_error('请先认证') unless current_user.ci_certification? + + begin + @cloud_account = Ci::CloudAccount.find params[:id] + ActiveRecord::Base.transaction do + if @repo + return render_error('该项目已经激活') if @repo.repo_active? + @repo.activate!(@ci_user.user_id) + else + @repo = Ci::Repo.auto_create!(@ci_user, @project) + @user.update_column(:user_syncing, false) + end + + result = bind_hook!(current_user, @cloud_account, @repo) + @project.update_columns(open_devops: true, gitea_webhook_id: result['id']) + @cloud_account.update_column(:ci_user_id, @ci_user.user_id) + end + render_ok + rescue Exception => ex + render_error(ex.message) + end + end + + def show + end + + def bind + flag, msg = check_bind_cloud_account! + return render_error(msg) if flag === true + + ActiveRecord::Base.transaction do + @cloud_account = bind_account! + if @cloud_account.blank? + render_error('激活失败, 请检查你的云服务器信息是否正确.') + raise ActiveRecord::Rollback + else + current_user.set_drone_step!(User::DEVOPS_UNVERIFIED) + end + end + rescue Exception => ex + render_error(ex.message) + end + + def unbind + ActiveRecord::Base.transaction do + unbind_account! + render_ok + end + rescue Exception => ex + render_error(ex.message) + end + + def oauth_grant + password = params[:password].to_s + return render_error('你输入的密码不正确.') unless current_user.check_password?(password) + + oauth = current_user.oauths.last + return render_error("服务器出小差了.") if oauth.blank? + + result = gitea_oauth_grant!(password, oauth) + return render_error('授权失败.') unless result === true + current_user.set_drone_step!(User::DEVOPS_CERTIFICATION) + end + + private + def validate_params! + Ci::CreateCloudAccountForm.new(devops_params).validate! + end +end diff --git a/app/controllers/ci/languages_controller.rb b/app/controllers/ci/languages_controller.rb new file mode 100644 index 00000000..b4b3e184 --- /dev/null +++ b/app/controllers/ci/languages_controller.rb @@ -0,0 +1,20 @@ +class Ci::LanguagesController < Ci::BaseController + # TODO 需要开启权限认证,只有该项目devops初始化成功后才能获取语言列表 + before_action :find_langugae, only: :show + + def index + @languages = Ci::Language.by_usage_amount_desc + end + + def show + end + + def common + @languages = Ci::Language.six_common + end + + private + def find_langugae + @language = Ci::Language.find params[:id] + end +end diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb new file mode 100644 index 00000000..c7b7338f --- /dev/null +++ b/app/controllers/ci/projects_controller.rb @@ -0,0 +1,73 @@ +class Ci::ProjectsController < Ci::BaseController + include RepositoriesHelper + include Ci::CloudAccountManageable + + before_action :load_project + before_action :load_repo, only: [:update_trustie_pipeline, :activate, :deactivate] + before_action :authorize_owner!, only: [:authorize] + before_action :find_cloud_account, only: [:authorize, :activate, :deactivate] + + def authorize + @user = current_user + end + + # get .trustie-pipeline.yml file + def get_trustie_pipeline + file_path_uri = URI.parse('.trustie-pipeline.yml') + interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: params[:ref] || "master") + if interactor.success? + file = interactor.result + return render json: {} if file[:status] + + json = {name: file['name'], path: file['path'], sha: file['sha'], content: render_decode64_content(file['content'])} + render json: json + end + end + + def update_trustie_pipeline + interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, params[:owner], params.merge(identifier: @project.identifier)) + if interactor.success? + @file = interactor.result + render_result(1, "更新成功") + else + render_error(interactor.error) + end + end + + def activate + return render_error('你还未认证') unless current_user.ci_certification? + + begin + ActiveRecord::Base.transaction do + if @repo + return render_error('该项目已经激活') if @repo.repo_active? + if @project.ci_reactivate? + @project.ci_reactivate!(@repo) + return render_ok + end + @repo.activate!(@ci_user.user_id) + else + @repo = Ci::Repo.auto_create!(@ci_user, @project) + @ci_user.update_column(:user_syncing, false) + end + + result = bind_hook!(current_user, @cloud_account, @repo) + @project.update_columns(open_devops: true, gitea_webhook_id: result['id']) + @project.increment!(:open_devops_count) + @cloud_account.update_column(:ci_user_id, @ci_user.user_id) + end + render_ok + rescue Exception => ex + render_error(ex.message) + end + end + + def deactivate + return render_error('该项目已经取消激活') if !@repo.repo_active? + + @project.update_column(:open_devops, false) + @repo.deactivate! + render_ok + end + +end diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb new file mode 100644 index 00000000..e5e61598 --- /dev/null +++ b/app/controllers/compare_controller.rb @@ -0,0 +1,15 @@ +class CompareController < ApplicationController + # skip_before_action :require_login + before_action :load_repository + + def index + end + + def show + base_ref = Addressable::URI.unescape(params[:base]) + @ref = head_ref = Addressable::URI.unescape(params[:head]&.split('.json')[0]) + @compare_result = Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base_ref, head_ref) + + # render json: @compare_result + end +end diff --git a/app/controllers/concerns/ci/cloud_account_manageable.rb b/app/controllers/concerns/ci/cloud_account_manageable.rb new file mode 100644 index 00000000..5931b31c --- /dev/null +++ b/app/controllers/concerns/ci/cloud_account_manageable.rb @@ -0,0 +1,138 @@ +module Ci::CloudAccountManageable + extend ActiveSupport::Concern + + included do + end + + def bind_account! + # 1. 保存华为云服务器帐号 + create_params = devops_params.merge(ip_num: IPAddr.new(devops_params[:ip_num].strip).to_i, secret: Ci::CloudAccount.encrypted_secret(devops_params[:secret])) + + cloud_account = Ci::CloudAccount.new(create_params) + cloud_account.user = current_user + cloud_account.save! + + # 2. 生成oauth2应用程序的client_id和client_secrete + gitea_oauth = Gitea::Oauth2::CreateService.call(current_user.gitea_token, {name: "pipeline-#{SecureRandom.hex(8)}", redirect_uris: ["#{cloud_account.drone_url}/login"]}) + logger.info "######### gitea_oauth: #{gitea_oauth}" + oauth = Oauth.new(client_id: gitea_oauth['client_id'], + client_secret: gitea_oauth['client_secret'], + redirect_uri: gitea_oauth['redirect_uris'], + gitea_oauth_id: gitea_oauth['id'], + user_id: current_user.id) + oauth.save! + + # 创建数据ci端数据库 + database_result = auto_create_database!(@connection, "#{current_user.login}_drone") + logger.info "[CI::DbConnectable] auto_create_database's result: #{database_result}" + + # 初始化表结构 + sub_connection = connect_to_ci_database + auto_create_table_structure!(sub_connection) + + rpc_secret = SecureRandom.hex 16 + logger.info "######### rpc_secret: #{rpc_secret}" + + # 3. 创建drone server + drone_server_cmd = Ci::Drone::Server.new(current_user.login, oauth.client_id, oauth.client_secret, cloud_account.drone_host, rpc_secret).generate_cmd + logger.info "######### drone_server_cmd: #{drone_server_cmd}" + + # 4. 创建drone client + drone_client_cmd = Ci::Drone::Client.new(oauth.client_id, cloud_account.drone_ip, rpc_secret).generate_cmd + logger.info "######### drone_client_cmd: #{drone_client_cmd}" + + # 5. 登录远程服务器,启动drone服务 + result = Ci::Drone::Start.new(cloud_account.account, cloud_account.visible_secret, cloud_account.drone_ip, drone_server_cmd, drone_client_cmd).run + logger.info "######### result: #{result}" + + + redirect_url = "#{cloud_account.drone_url}/login" + logger.info "######### redirect_url: #{redirect_url}" + + return nil unless result.present? + result && !result.blank? ? cloud_account : nil + end + + def unbind_account! + cloud_account = current_user.ci_cloud_account + return render_error('你未绑定CI服务器') if current_user.devops_step == User::DEVOPS_UNINIT || cloud_account.blank? + + cloud_account.destroy! unless cloud_account.blank? + @connection.execute("DROP DATABASE IF EXISTS #{current_user.login}_drone") # TOTO drop drone database + + current_user.unbind_account! + end + + def bind_hook!(user, cloud_account, repo) + hook_params = { + active: true, + config: { + content_type: "json", + url: cloud_account.drone_url + "/hook?secret=#{repo.repo_signer}" + }, + type: "gitea" + } + result = Gitea::Hooks::CreateService.call(user.gitea_token, user.login, repo.repo_name, hook_params) + + result[:status].present? ? nil : result + end + + def check_bind_cloud_account! + return [true, "你已经绑定了云帐号."] unless current_user.ci_cloud_account.blank? + + ip_num = IPAddr.new(devops_params[:ip_num]).to_i + Ci::CloudAccount.exists?(ip_num: ip_num) ? [true, "#{devops_params[:ip_num]}服务器已被使用."] : [false, nil] + end + + def gitea_auto_create_auth_grant!(gitea_oauth_id) + connection = Gitea::Database.set_connection.connection + unix_time = Time.now.to_i + + # 目前直接操作db,可以建立对应的model进行操作 + sql = "INSERT INTO oauth2_grant ( user_id, application_id, counter, created_unix, updated_unix ) VALUES ( #{current_user.gitea_uid}, #{gitea_oauth_id}, 0, #{unix_time}, #{unix_time} );" + connection.execute(sql) + end + + def gitea_oauth_grant!(password, oauth) + gitea_auto_create_auth_grant!(oauth&.gitea_oauth_id) + + state = SecureRandom.hex(8) + + # redirect_uri eg: + # https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805 + redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login") + grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{oauth&.client_id}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}" + logger.info "[gitea] grant_url: #{grant_url}" + + conn = Faraday.new(url: grant_url) do |req| + req.request :url_encoded + req.adapter Faraday.default_adapter + req.basic_auth(current_user.login, password) + end + + response = conn.get + logger.info "[gitea] response headers: #{response.headers}" + + drone_oauth_user!(response.headers.to_h['location'], state) + end + + def drone_oauth_user!(url, state) + logger.info "[drone] drone_oauth_user url: #{url}" + conn = Faraday.new(url: url) do |req| + req.request :url_encoded + req.adapter Faraday.default_adapter + req.headers["cookie"] = "_session_=#{SecureRandom.hex(28)}; _oauth_state_=#{state}" + end + + response = conn.get + logger.info "[drone] response headers: #{response.headers}" + + response.headers['location'].include?('error') ? false : true + end + + private + def devops_params + params.permit(:account, :secret, :ip_num) + end + +end diff --git a/app/controllers/concerns/ci/db_connectable.rb b/app/controllers/concerns/ci/db_connectable.rb new file mode 100644 index 00000000..2aaff87b --- /dev/null +++ b/app/controllers/concerns/ci/db_connectable.rb @@ -0,0 +1,40 @@ +module Ci::DbConnectable + extend ActiveSupport::Concern + + included do + end + + # Dynamically sets the database connection. + def connect_to_ci_database(options={}) + master_db = options[:master_db] || false + config = Rails.application.config_for(:configuration).symbolize_keys! + db_config = config[:ci_db_server].symbolize_keys! + raise 'ci database config missing' if db_config.blank? + + req_params = { + host: db_config[:host], + username: db_config[:username], + password: db_config[:password], + port: db_config[:port] + } + req_params = req_params.merge(database: "#{current_user.login}_#{db_config[:database]}") unless master_db === true + + db_params = Ci::Database.get_connection_params(req_params) + @connection = Ci::Database.set_connection(db_params).connection + end + + def auto_create_database!(connection, database) + Rails.logger.info "[CI::DbConnectable] auto_create_database's connection: #{connection}" + connection.execute("CREATE DATABASE IF NOT EXISTS #{database}") + end + + def auto_create_table_structure!(connection) + Rails.logger.info "[CI::DbConnectable] auto_create_table_structure's connection: #{connection}" + + sqls = Ci::Schema.statement.split(';').map(&:strip).reject { |e| e.to_s.empty? } + sqls.each do |sql| + con_result = connection.execute(sql) + Rails.logger.info "=============> ci create tabels result: #{con_result}" + end + end +end diff --git a/app/controllers/concerns/login_helper.rb b/app/controllers/concerns/login_helper.rb index ec89fcd7..12cf3bb6 100644 --- a/app/controllers/concerns/login_helper.rb +++ b/app/controllers/concerns/login_helper.rb @@ -17,7 +17,7 @@ module LoginHelper :expires => 1.month.from_now, :path => '/', :secure => false, - :httponly => false + :httponly => true } if edu_setting('cookie_domain').present? cookie_options = cookie_options.merge(domain: edu_setting('cookie_domain')) @@ -51,11 +51,16 @@ module LoginHelper Rails.logger.info("####################__User.current_id______######{current_user.try(:id)}###___#{current_user&.logged?}") if User.current.logged? - if autologin = cookies.delete(autologin_cookie_name) + user = User.current + autologin = + if edu_setting('cookie_domain').present? + cookies.delete(autologin_cookie_name, domain: edu_setting('cookie_domain')) + else + cookies.delete(autologin_cookie_name) + end - User.current.delete_autologin_token(autologin) - end - User.current.delete_session_token(session[:tk]) + user.delete_autologin_token(autologin) + user.delete_session_token(session[:tk]) self.logged_user = nil end @@ -68,7 +73,7 @@ module LoginHelper # Sets the logged in user def logged_user=(user) - # reset_session + reset_session if user && user.is_a?(User) Rails.logger.info("########________logged_user___________###########{user.id}") @@ -111,4 +116,34 @@ module LoginHelper false end end + + # TODO 同步token到trustie平台,保持同步登录状态 + def sync_user_token_to_trustie(login, token_value) + + config = Rails.application.config_for(:configuration).symbolize_keys! + + token = config[:sync_token] + api_host = config[:sync_url] + + return if api_host.blank? + + url = "#{api_host}/api/v1/users/sync_user_token" + sync_json = { + "token": token, + "login": login, + "user_token": token_value + } + uri = URI.parse(url) + + if api_host + http = Net::HTTP.new(uri.hostname, uri.port) + + if api_host.include?("https://") + http.use_ssl = true + end + + http.send_request('POST', uri.path, sync_json.to_json, {'Content-Type' => 'application/json'}) + end + + end end diff --git a/app/controllers/concerns/register_helper.rb b/app/controllers/concerns/register_helper.rb index 2c41952a..441d93de 100644 --- a/app/controllers/concerns/register_helper.rb +++ b/app/controllers/concerns/register_helper.rb @@ -1,7 +1,7 @@ module RegisterHelper extend ActiveSupport::Concern - def autologin_register(username, email, password, platform= '') + def autologin_register(username, email, password, platform= 'forge') result = {message: nil, user: nil} email ||= "#{username@example.org}" diff --git a/app/controllers/hooks_controller.rb b/app/controllers/hooks_controller.rb index 92b1d722..206f7947 100644 --- a/app/controllers/hooks_controller.rb +++ b/app/controllers/hooks_controller.rb @@ -4,18 +4,18 @@ class HooksController < ApplicationController before_action :check_user before_action :set_repository - def index - hooks_response = Gitea::Hooks::ListService.new(@user, @repository.try(:identifier)).call - if hooks_response.status == 200 + def index + hooks_response = Gitea::Hooks::ListService.new(@user.gitea_token, @user.login, @repository.try(:identifier)).call + if hooks_response.status == 200 lists = JSON.parse(hooks_response.body) @hooks_size = lists.size @hooks = paginate(lists) - else + else normal_status(-1, "出现错误") end end - def create + def create #根据gitea的api # hook_params = { # active: true, @@ -36,17 +36,17 @@ class HooksController < ApplicationController # content_type: params[:content_type].to_i, # secret: params[:secret], # events: { - # push_only: params[:push_only] || false, # 是否为推送事件 - # send_everything: params[:send_everything] || false, #是否为所有事件 + # push_only: params[:push_only] || false, # 是否为推送事件 + # send_everything: params[:send_everything] || false, #是否为所有事件 # choose_events: params[:choose_events] || false, #是否为自定义事件 # branch_filter: params[:branch_filter] || "*", # events: { # create: params[:create] || false, #创建分支/标签 - # delete: params[:delete] || false, #删除分支/标签 - # fork: params[:fork] || false, #仓库被派生 + # delete: params[:delete] || false, #删除分支/标签 + # fork: params[:fork] || false, #仓库被派生 # issues: params[:issues] || false, #工单 - # issue_comment: params[:issue_comment] || false, #评论 - # push: params[:push] || false # 推送 + # issue_comment: params[:issue_comment] || false, #评论 + # push: params[:push] || false # 推送 # pull_request: params[:pull_request] || false #合并请求 # repository: params[:repository] || false #仓库 # release: params[:release] || false #版本发布 @@ -58,28 +58,28 @@ class HooksController < ApplicationController Gitea::Hooks::CreateService.new(@user, @repository.try(:identifier), hook_params).call #创建gitea的hook功能 Gitea::Hooks::CreateService.new(user, p.try(:identifier), hook_params).call #创建gitea的hook功能 - end + end - def update + def update hook_params = params[:hook_params] response = Gitea::Hooks::UpdateService.new(@user, @repository.try(:identifier), hook_params, params[:id]).call - if response.status == 200 + if response.status == 200 normal_status(1, "更新成功") - else + else normal_status(-1, "更新失败") end - end + end - def destroy + def destroy response = Gitea::Hooks::DestroyService.new(@user, @repository.try(:identifier), params[:id]).call if response.status == 204 normal_status(1, "删除成功") - else + else normal_status(-1, "删除失败") end - end + end - private + private def set_repository @repository = @project.repository @@ -88,9 +88,9 @@ class HooksController < ApplicationController normal_status(-1, "用户不存在") unless @user.present? end - def check_user - unless @project.user_id == current_user.id - tip_exception(403, "您没有权限进入") + def check_user + unless @project.user_id == current_user.id + tip_exception(403, "您没有权限进入") end end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 7b4ee471..8619cacc 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -105,9 +105,6 @@ class IssuesController < ApplicationController normal_status(-1, "标题不能为空") elsif params[:subject].to_s.size > 255 normal_status(-1, "标题不能超过255个字符") - elsif (params[:issue_type].to_s == "2") - return normal_status(-1, "悬赏的奖金必须大于0") if params[:token].to_i == 0 - else issue_params = issue_send_params(params) @@ -137,17 +134,16 @@ class IssuesController < ApplicationController end @issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") - # normal_status(0, "创建成功",) - render :json => { status: 0, message: "创建成功", id: @issue.id} + render json: {status: 0, message: "创建成", id: @issue.id} else normal_status(-1, @issue.errors.messages.values[0][0]) end + end end def edit - # @all_branches = get_branches # @issue_chosen = issue_left_chosen(@project, @issue.id) @issue_attachments = @issue.attachments end @@ -204,7 +200,6 @@ class IssuesController < ApplicationController else normal_status(-1, @issue.errors.messages.values[0][0]) end - end def show @@ -306,6 +301,9 @@ class IssuesController < ApplicationController if type == 5 @issue&.project_trends&.update_all(action_type: "close") @issue.issue_times.update_all(end_time: Time.now) + if @issue.issue_type.to_s == "2" + post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login)) + end if @issue.issue_classify.to_s == "pull_request" @issue&.pull_request&.update_attribute(:status, 2) end @@ -399,17 +397,6 @@ class IssuesController < ApplicationController tracker_array end - def get_branches - all_branches = [] - get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @project&.repository.try(:identifier)).call - if get_all_branches && get_all_branches.size > 0 - get_all_branches.each do |b| - all_branches.push(b["name"]) - end - end - all_branches - end - def issue_send_params(params) { subject: params[:subject], diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 965ef760..7b7468f9 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -2,7 +2,7 @@ class MainController < ApplicationController protect_from_forgery except: :index skip_before_action :check_sign skip_before_action :user_setup - # skip_before_action :setup_laboratory + skip_before_action :setup_laboratory def first_stamp render :json => { status: 0, message: Time.now.to_i } diff --git a/app/controllers/oauth/educoder_controller.rb b/app/controllers/oauth/educoder_controller.rb index a0b35b66..3ef36e71 100644 --- a/app/controllers/oauth/educoder_controller.rb +++ b/app/controllers/oauth/educoder_controller.rb @@ -7,7 +7,7 @@ class Oauth::EducoderController < Oauth::BaseController token = params[:token] ::OauthEducoderForm.new({login: login, token: token, callback_url: callback_url}).validate! - + open_user= OpenUsers::Educoder.find_by(uid: login) if open_user.present? && open_user.user.present? && open_user.user.email_binded? @@ -17,15 +17,15 @@ class Oauth::EducoderController < Oauth::BaseController redirect_to callback_url else Rails.logger.info "######## open user not exits" - user = User.find_by('login = ? or mail = ?', login, mail) + user = User.find_by(login: login) || User.find_by(mail: mail) - if user.is_a?(User) + if user.is_a?(User) && !user.is_a?(AnonymousUser) OpenUsers::Educoder.create!(user: user, uid: login) successful_authentication(user) redirect_to callback_url else - redirect_to oauth_register_path(login: login, callback_url: callback_url) + redirect_to oauth_register_path(login: login, mail: mail, callback_url: callback_url) end end rescue WechatOauth::Error => ex diff --git a/app/controllers/praise_tread_controller.rb b/app/controllers/praise_tread_controller.rb index 47ea6422..983697e0 100644 --- a/app/controllers/praise_tread_controller.rb +++ b/app/controllers/praise_tread_controller.rb @@ -40,8 +40,5 @@ class PraiseTreadController < ApplicationController end private - def render_result - - end end diff --git a/app/controllers/project_categories_controller.rb b/app/controllers/project_categories_controller.rb index 4b4a9634..c6c2cd21 100644 --- a/app/controllers/project_categories_controller.rb +++ b/app/controllers/project_categories_controller.rb @@ -6,16 +6,6 @@ class ProjectCategoriesController < ApplicationController end def group_list - # if current_user&.logged? - # projects = Project.list_user_projects(current_user.id) - # else - # projects = Project.visible - # end - @project_children_categories = ProjectCategory.descendants - projects = Project.no_anomory_projects.visible - categories = projects.joins(:project_category).where(project_categories: {ancestry: nil}).group("project_categories.name", "project_categories.id").size.keys.to_h - extra_category_id = categories.delete("其他") - categories = categories.merge({"其他": extra_category_id}) if extra_category_id.present? #其他的放在最后面 - @category_group_list = categories + @project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc) end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bfecf81a..31bb0475 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,16 +2,26 @@ class ProjectsController < ApplicationController include ApplicationHelper include OperateProjectAbilityAble include ProjectsHelper - before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users] - before_action :load_project, except: %i[index group_type_list migrate create] + before_action :require_login, except: %i[index branches group_type_list simple show fork_users praise_users watch_users recommend about] + before_action :load_project, except: %i[index group_type_list migrate create recommend] before_action :authorizate_user_can_edit_project!, only: %i[update] before_action :project_public?, only: %i[fork_users praise_users watch_users] def index scope = Projects::ListQuery.call(params) - @projects = kaminari_paginate(scope) - @total_count = @projects.total_count + # @projects = kaminari_paginate(scope) + @projects = paginate scope.includes(:project_category, :project_language, :repository, :project_educoder, owner: :user_extension) + + category_id = params[:category_id] + @total_count = + if category_id.blank? + ps = ProjectStatistic.first + ps.common_projects_count + ps.mirror_projects_count unless ps.blank? + else + cate = ProjectCategory.find_by(id: category_id) + cate&.projects_count || 0 + end end def create @@ -34,7 +44,7 @@ class ProjectsController < ApplicationController end def branches - @branches = Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call + @branches = @project.forge? ? Gitea::Repository::Branches::ListService.new(@owner, @project.identifier).call : [] end def group_type_list @@ -52,9 +62,13 @@ class ProjectsController < ApplicationController ActiveRecord::Base.transaction do # Projects::CreateForm.new(project_params).validate! private = params[:private] + gitea_params = { + private: private, + default_branch: params[:default_branch] + } if [true, false].include? private new_project_params = project_params.merge(is_public: !private) - Gitea::Repository::UpdateService.new(@project.owner, @project.repository.identifier, {private: private}).call + Gitea::Repository::UpdateService.call(@owner, @project.identifier, gitea_params) @project.repository.update_column(:hidden, private) end @project.update_attributes!(new_project_params) @@ -95,13 +109,44 @@ class ProjectsController < ApplicationController end def fork_users - fork_users = @project.fork_users.includes(:user, :project).order("fork_users.created_at desc").distinct + fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct @forks_count = fork_users.size @fork_users = paginate(fork_users) end def simple - json_response(@project) + json_response(@project, current_user) + end + + def recommend + @projects = Project.recommend.includes(:repository, :project_category, owner: :user_extension).limit(5) + end + + def about + @project_detail = @project.project_detail + @attachments = Array(@project_detail&.attachments) if request.get? + ActiveRecord::Base.transaction do + if request.post? + require_login + authorizate_user_can_edit_project! + unless @project_detail.present? + @project_detail = ProjectDetail.new( + content: params[:content], + project_id: @project.id) + else + @project_detail.content = params[:content] + end + if @project_detail.save! + attachment_ids = Array(params[:attachment_ids]) + @attachments = Attachment.where(id: attachment_ids) + @attachments.update_all( + container_id: @project_detail.id, + container_type: @project_detail.model_name.name, + author_id: current_user.id, + description: "") + end + end + end end diff --git a/app/controllers/protected_branches_controller.rb b/app/controllers/protected_branches_controller.rb new file mode 100644 index 00000000..123004a4 --- /dev/null +++ b/app/controllers/protected_branches_controller.rb @@ -0,0 +1,43 @@ +class ProtectedBranchesController < ApplicationController + include OperateProjectAbilityAble + + before_action :require_login + before_action :load_repository + before_action :authorizate_user_can_edit_project! + + def index + scope = @repository.protected_branches + @total_count = scope.size + @protected_branches = paginate(scope) + end + + def create + @protected_branch = ProtectedBranches::CreateService.call(@repository, @owner, params) + + render_protected_branch_json + 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 + + def show + @protected_branch = ProtectedBranches::GetService.call(@repository, @owner, params) + end + + def edit + @branch, @protected_branch = ProtectedBranches::EditService.call(@repository, @owner, params[:branch_name]) + end + + private + def render_protected_branch_json + @protected_branch.persisted? ? @protected_branch : render_error('创建失败!') + end + +end diff --git a/app/controllers/pull_requests_controller.rb b/app/controllers/pull_requests_controller.rb index f6685b77..54873ec3 100644 --- a/app/controllers/pull_requests_controller.rb +++ b/app/controllers/pull_requests_controller.rb @@ -1,9 +1,8 @@ class PullRequestsController < ApplicationController - before_action :require_login, except: [:index, :show] + before_action :require_login, except: [:index, :show, :files, :commits] before_action :load_repository - before_action :set_user, only: [:new, :get_branches] - before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos] - # before_action :get_relatived, only: [:edit] + before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits] + before_action :load_pull_request, only: [:files, :commits] include TagChosenHelper include ApplicationHelper @@ -24,11 +23,11 @@ class PullRequestsController < ApplicationController end def new - @all_branches = PullRequests::BranchesService.new(@user, @project).call + @all_branches = Branches::ListService.call(@owner, @project) @is_fork = @project.forked_from_project_id.present? @projects_names = [{ - project_user_login: @user.try(:login), - project_name: "#{@user.try(:show_real_name)}/#{@repository.try(:identifier)}", + project_user_login: @owner.try(:login), + project_name: "#{@owner.try(:show_real_name)}/#{@repository.try(:identifier)}", project_id: @project.identifier, id: @project.id }] @@ -45,66 +44,20 @@ class PullRequestsController < ApplicationController end def get_branches - branch_result = PullRequests::BranchesService.new(@user, @project).call + branch_result = Branches::ListService.call(@owner, @project) render json: branch_result # return json: branch_result end def create - if params[:title].nil? - normal_status(-1, "名称不能为空") - elsif params[:issue_tag_ids].nil? - normal_status(-1, "标签不能为空") - else - ActiveRecord::Base.transaction do - begin - merge_params - pull_issue = Issue.new(@issue_params) - if pull_issue.save! - pr_params = { - user_id: current_user.try(:id), - project_id: @project.id, - issue_id: pull_issue.id, - fork_project_id: params[:fork_project_id], - is_original: params[:is_original] - } - local_requests = PullRequest.new(@local_params.merge(pr_params)) - if local_requests.save - remote_pr_params = @local_params - remote_pr_params = remote_pr_params.merge(head: "#{params[:merge_user_login]}:#{params[:head]}").compact if local_requests.is_original && params[:merge_user_login] - gitea_request = Gitea::PullRequest::CreateService.call(current_user.try(:gitea_token), @project.owner, @repository.try(:identifier), remote_pr_params.except(:milestone)) - if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"]) - if params[:issue_tag_ids].present? - params[:issue_tag_ids].each do |tag| - IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag) - end - end - - if params[:assigned_to_id].present? - Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id, - container_id: local_requests.id, container_type: 'PullRequest', - parent_container_id: @project.id, parent_container_type: "Project", - tiding_type: 'pull_request', status: 0) - end - local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") - if params[:title].to_s.include?("WIP:") - pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。", current_user&.id) - end - # render :json => { status: 0, message: "PullRequest创建成功", id: pull_issue.id} - normal_status(0, "PullRequest创建成功") - else - normal_status(-1, "PullRequest创建失败") - end - else - normal_status(-1, local_requests.errors.messages.values[0][0]) - end - else - normal_status(-1, pull_issue.errors.messages.values[0][0]) - end - rescue => e - normal_status(-1, e.message) - raise ActiveRecord::Rollback - end + ActiveRecord::Base.transaction do + @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params) + if @gitea_pull_request[:status] == :success + @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"]) + render_ok + else + render_error("create pull request error: #{@gitea_pull_request[:status]}") + raise ActiveRecord::Rollback end end end @@ -226,11 +179,11 @@ class PullRequestsController < ApplicationController elsif target_head === target_base && !is_original normal_status(-2, "分支内容相同,无需创建合并请求") else - can_merge = @project&.pull_requests.where(user_id: current_user&.id, head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id]) + can_merge = @project&.pull_requests.where(head: target_head, base: target_base, status: 0, is_original: is_original, fork_project_id: params[:fork_project_id]) if can_merge.present? render json: { status: -2, - message: "在这些分支之间的合并请求已存在:#{can_merge.first.try(:title)}", + message: "在这些分支之间的合并请求已存在:#{can_merge.first.try(:title)}", } else normal_status(0, "可以合并") @@ -239,9 +192,19 @@ class PullRequestsController < ApplicationController end + def files + @files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gpid) + # render json: @files_result + end + + def commits + @commits_result = Gitea::PullRequest::CommitsService.call(@owner.login, @project.identifier, @pull_request.gpid) + # render json: @commits_result + end + private - def set_user - @user = @project.owner + def load_pull_request + @pull_request = PullRequest.find params[:id] end def find_pull_request diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 2e2711aa..b4d14228 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -13,7 +13,7 @@ class RepositoriesController < ApplicationController def show @user = current_user @repo = @project.repository - @result = Gitea::Repository::GetService.new(@project.owner, @project.identifier).call + @result = @project.forge? ? Gitea::Repository::GetService.new(@owner, @project.identifier).call : nil @project_fork_id = @project.try(:forked_from_project_id) if @project_fork_id.present? @fork_project = Project.find_by(id: @project_fork_id) @@ -26,60 +26,85 @@ class RepositoriesController < ApplicationController def entries @project.increment!(:visits) - @project_owner = @project.owner - @entries = Gitea::Repository::Entries::ListService.new(@project_owner, @project.identifier, ref: @ref).call - @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] - @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" + + if @project.educoder? + @entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name) + else + @entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call + @entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : [] + @path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/" + end end def top_counts - @result = Gitea::Repository::GetService.new(@project.owner, @project.identifier).call + @result = @project.educoder? ? nil : Gitea::Repository::GetService.new(@project.owner, @project.identifier).call end def sub_entries file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip)) - interactor = Repositories::EntriesInteractor.call(@project.owner, @project.identifier, file_path_uri, ref: @ref) - if interactor.success? - @sub_entries = interactor.result - @sub_entries = [] << @sub_entries unless @sub_entries.is_a? Array - @sub_entries = @sub_entries.sort_by{ |hash| hash['type'] } + + if @project.educoder? + if params[:type] === 'file' + @sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri) + logger.info "######### sub_entries: #{@sub_entries}" + return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1 + + tmp_entries = [{ + "content" => @sub_entries['data']['content'], + "type" => "blob" + }] + @sub_entries = { + "trees"=>tmp_entries, + "commits" => [{}] + } + else + @sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri}) + end else - render_error(interactor.error) + interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref) + if interactor.success? + result = interactor.result + @sub_entries = result.is_a?(Array) ? result.sort_by{ |hash| hash['type'] } : result + else + render_error(interactor.error) + end end end def commits - @project_owner = @project.owner - @hash_commit = Gitea::Repository::Commits::ListService.new(@project_owner.login, @project.identifier, + @hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier, sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call end def commit - @commit = Gitea::Repository::Commits::GetService.new(@repository.user.login, @repository.identifier, params[:sha], current_user.gitea_token).call + @sha = params[:sha] + @commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token) + @commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true}) end def tags - @tags = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}).call + @tags = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]}) end def edit end def create_file - interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @project.owner.login, content_params) + interactor = Gitea::CreateFileInteractor.call(current_user.gitea_token, @owner.login, content_params) if interactor.success? @file = interactor.result - create_new_pr(params) + # create_new_pr(params) else render_error(interactor.error) end end def update_file - interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier)) + interactor = Gitea::UpdateFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) if interactor.success? @file = interactor.result - create_new_pr(params) + # TODO: 是否创建pr + # create_new_pr(params) render_result(1, "更新成功") else render_error(interactor.error) @@ -87,7 +112,7 @@ class RepositoriesController < ApplicationController end def delete_file - interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @project.owner.login, params.merge(identifier: @project.identifier)) + interactor = Gitea::DeleteFileInteractor.call(current_user.gitea_token, @owner.login, params.merge(identifier: @project.identifier)) if interactor.success? @file = interactor.result render_result(1, "文件删除成功") @@ -133,8 +158,8 @@ class RepositoriesController < ApplicationController end def get_statistics - @branches_count = Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size - @tags_count = Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size + @branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size + @tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size end def get_ref @@ -142,9 +167,9 @@ class RepositoriesController < ApplicationController end def get_latest_commit - latest_commit = project_commits - @latest_commit = latest_commit[:body][0] if latest_commit.present? - @commits_count = latest_commit[:total_count] if latest_commit.present? + latest_commit = @project.educoder? ? nil : project_commits + @latest_commit = latest_commit.present? ? latest_commit[:body][0] : nil + @commits_count = latest_commit.present? ? latest_commit[:total_count] : 0 end def content_params @@ -154,6 +179,10 @@ class RepositoriesController < ApplicationController new_branch: params[:new_branch], content: params[:content], message: params[:message], + committer: { + email: current_user.mail, + name: current_user.login + }, identifier: @project.identifier } end @@ -208,14 +237,14 @@ class RepositoriesController < ApplicationController issue_type: "1", tracker_id: 2, status_id: 1, - priority_id: 1 + priority_id: params[:priority_id] || "2" } @pull_issue = Issue.new(issue_params) if @pull_issue.save! local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id)) if local_requests.save - gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @project.owner, @project.try(:identifier), requests_params).call - if gitea_request && local_requests.update_attributes(gpid: gitea_request["number"]) + gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call + if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"]) local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create") end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 105bda78..80143eaa 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,8 +1,11 @@ class UsersController < ApplicationController + include Ci::DbConnectable before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users] before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users] before_action :require_login, only: %i[me list] + before_action :connect_to_ci_database, only: :get_user_info, if: -> { current_user && !current_user.is_a?(AnonymousUser) && current_user.devops_certification? } + skip_before_action :check_sign, only: [:attachment_show] def list diff --git a/app/controllers/version_releases_controller.rb b/app/controllers/version_releases_controller.rb index bc6f0303..a9e7fa63 100644 --- a/app/controllers/version_releases_controller.rb +++ b/app/controllers/version_releases_controller.rb @@ -139,7 +139,7 @@ class VersionReleasesController < ApplicationController body: params[:body], draft: params[:draft] || false, name: params[:name], - prerelease: params[:prerelease], + prerelease: params[:prerelease] || false, tag_name: params[:tag_name], target_commitish: params[:target_commitish] || "master" #分支 } diff --git a/app/forms/ci/create_cloud_account_form.rb b/app/forms/ci/create_cloud_account_form.rb new file mode 100644 index 00000000..7da78a05 --- /dev/null +++ b/app/forms/ci/create_cloud_account_form.rb @@ -0,0 +1,10 @@ +class Ci::CreateCloudAccountForm + include ActiveModel::Model + + attr_accessor :ip_num, :account, :secret + + # validates :project_id, :account, :secret, presence: true + validates :account, :secret, presence: true + validates :ip_num, presence: true, format: { with: CustomRegexp::IP, multiline: true, message: 'IP 地址格式不对' } + +end diff --git a/app/forms/protected_branches/create_form.rb b/app/forms/protected_branches/create_form.rb new file mode 100644 index 00000000..ec4d8771 --- /dev/null +++ b/app/forms/protected_branches/create_form.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8a4631e7..f4ffaf1f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -436,4 +436,9 @@ module ApplicationHelper def find_user_by_login(login) User.find_by_login login end + + def render_base64_decoded(str) + return nil if str.blank? + Base64.decode64 str + end end diff --git a/app/helpers/ci/builds_helper.rb b/app/helpers/ci/builds_helper.rb new file mode 100644 index 00000000..c0e59106 --- /dev/null +++ b/app/helpers/ci/builds_helper.rb @@ -0,0 +1,11 @@ +module Ci::BuildsHelper + def format_utc_time(unix_time) + return nil if unix_time == 0 + Time.at(unix_time).strftime("%Y-%m-%d %H:%M") + end + + def render_duartion_time(end_time, start_time) + return nil if end_time == 0 || start_time == 0 + game_spend_time(end_time - start_time) + end +end diff --git a/app/helpers/ci/languages_helper.rb b/app/helpers/ci/languages_helper.rb new file mode 100644 index 00000000..dc4fa897 --- /dev/null +++ b/app/helpers/ci/languages_helper.rb @@ -0,0 +1,2 @@ +module Ci::LanguagesHelper +end diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb new file mode 100644 index 00000000..d920da30 --- /dev/null +++ b/app/helpers/compare_helper.rb @@ -0,0 +1,2 @@ +module CompareHelper +end diff --git a/app/helpers/dev_ops_helper.rb b/app/helpers/dev_ops_helper.rb new file mode 100644 index 00000000..cb4d7e9b --- /dev/null +++ b/app/helpers/dev_ops_helper.rb @@ -0,0 +1,2 @@ +module DevOpsHelper +end diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index e3fa623c..c0960271 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -1,2 +1,18 @@ module MembersHelper + def get_user_token(user_login,reponame) + query_params = { + type: "query", + chain_params: { + reponame: reponame, + username: user_login + } + } + response = Gitea::Chain::ChainGetService.new(query_params).call + + if response.status == 200 + return JSON.parse(response.body)["balance"].to_i + else + return 0 + end + end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f5df048d..c00010b2 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -28,8 +28,10 @@ module ProjectsHelper (User.find_by_login identifier) || (User.find_by_mail identifier) end - def json_response(project) - repo = project.repository + def json_response(project, user) + # repo = project.repository + repo = Repository.includes(:mirror).select(:id, :mirror_url).find_by(project: project) + tmp_json = {} unless project.common? tmp_json = tmp_json.merge({ @@ -41,16 +43,48 @@ module ProjectsHelper end tmp_json = tmp_json.merge({ - identifier: project.identifier, + identifier: render_identifier(project), name: project.name, + platform: project.platform, id: project.id, + repo_id: repo.id, + open_devops: (user.blank? || user.is_a?(AnonymousUser)) ? false : project.open_devops?, type: project.numerical_for_project_type, - author: { - login: project.owner.login, - name: project.owner.real_name, - image_url: url_to_avatar(project.owner) - } + author: render_owner(project) }).compact + render json: tmp_json end + + def render_owner(project) + if project.educoder? + { + login: project.project_educoder.owner, + name: project.project_educoder.owner, + image_url: project.project_educoder.image_url + } + else + { + login: @owner.login, + name: @owner.real_name, + image_url: url_to_avatar(@owner) + } + end + end + + def render_identifier(project) + project.educoder? ? project.project_educoder&.repo_name&.split('/')[1] : project.identifier + end + + def render_author(project) + project.educoder? ? project.project_educoder&.repo_name&.split('/')[0] : project.owner.login + end + + def render_educoder_avatar_url(project_educoder) + [Rails.application.config_for(:configuration)['educoder']['cdn_url'], project_educoder&.image_url].join('/') + end + + def render_avatar_url(owner) + ['images', url_to_avatar(owner)].join('/') + end end diff --git a/app/helpers/protected_branches_helper.rb b/app/helpers/protected_branches_helper.rb new file mode 100644 index 00000000..dce9506f --- /dev/null +++ b/app/helpers/protected_branches_helper.rb @@ -0,0 +1,2 @@ +module ProtectedBranchesHelper +end diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb index 2b6d9d40..10ad1377 100644 --- a/app/helpers/repositories_helper.rb +++ b/app/helpers/repositories_helper.rb @@ -1,11 +1,17 @@ module RepositoriesHelper + def render_permission(user, project) + return "Admin" if user&.admin? + return "Owner" if user === project.owner + project.get_premission(user) + end + def render_decode64_content(str) return nil if str.blank? - Base64.decode64(str).force_encoding('UTF-8') + Base64.decode64(str).force_encoding("UTF-8") end def download_type(str) - default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata) + default_type = %w(xlsx xls ppt pptx pdf zip 7z rar exe pdb obj idb png jpg gif tif psd svg RData rdata doc docx mpp vsdx) default_type.include?(str&.downcase) end @@ -44,7 +50,7 @@ module RepositoriesHelper end if r_content.include?("?") new_r_content = r_content + "&raw=true" - else + else new_r_content = r_content + "?raw=true" end unless r_content.include?("http://") || r_content.include?("https://") || r_content.include?("mailto:") @@ -56,4 +62,14 @@ module RepositoriesHelper return content end + + # unix_time values for example: 1604382982 + def render_format_time_with_unix(unix_time) + Time.at(unix_time).strftime("%Y-%m-%d %H:%M") + end + + # date for example: 2020-11-01T19:57:27+08:00 + def render_format_time_with_date(date) + date.to_time.strftime("%Y-%m-%d %H:%M") + end end diff --git a/app/helpers/tag_chosen_helper.rb b/app/helpers/tag_chosen_helper.rb index 75be474f..afd51170 100644 --- a/app/helpers/tag_chosen_helper.rb +++ b/app/helpers/tag_chosen_helper.rb @@ -1,4 +1,143 @@ module TagChosenHelper + def get_associated_data(project) + issue_comment_users_array = [] + cost_time_array = [] + all_issues = [] + { + "assign_user": render_cache_collaborators(project), + "tracker": render_cache_trackers, + "issue_status": render_cache_issue_statuses, + "priority": render_cache_issue_priorities, + "issue_version": render_cache_milestones(project), + "start_date": "", + "due_date": "", + "joins_users": issue_comment_users_array, + "cost_time_users": cost_time_array, + # "total_cost_time": Time.at(all_cost_time).utc.strftime('%H h %M min %S s'), + # "be_depended_issues": be_depended_issues_array, + # "depended_issues":depended_issues_array, + # "estimated_hours": issue_info[7], + "done_ratio": render_complete_percentage, + "issue_tag": render_issue_tags(project), + "issue_type": render_issue_species, + "all_issues": all_issues + } + end + + def render_cache_trackers + cache_key = "all_trackers/#{Tracker.maximum('id')}" + + Rails.cache.fetch(cache_key) do + Tracker.select(:id, :name, :position).collect do |event| + { + id: event.id, + name: event.name, + position: event.position, + is_chosen: '0' + } + end + end + end + + def render_cache_issue_statuses + cache_key = "all_issue_statuses/#{IssueStatus.maximum('id')}" + + Rails.cache.fetch(cache_key) do + IssueStatus.select(:id, :name, :position).collect do |event| + { + id: event.id, + name: event.name, + position: event.position, + is_chosen: '0' + } + end + end + end + + def render_cache_issue_priorities + cache_key = "all_issue_priorities/#{IssuePriority.maximum('id')}" + + Rails.cache.fetch(cache_key) do + IssuePriority.select(:id, :name, :position).collect do |event| + { + id: event.id, + name: event.name, + position: event.position, + is_chosen: '0' + } + end + end + end + + def render_complete_percentage + completion_nums = %w(0 10 20 30 40 50 60 70 80 90 100) + completion_nums.collect do |event| + { + id: event.to_i, + name: event + "%", + is_chosen: '0' + } + end + end + + def render_issue_species + species = %W(普通 悬赏) + + species.collect do |event| + { + id: event.to_i + 1, + token: nil, + is_chosen: '0' + } + end + end + + def render_issue_tags(project) + # project.issue_tags.last&.cache_key + cache_key = "all_issue_tags/#{project.issue_tags.maximum('updated_at')}" + + Rails.cache.fetch(cache_key) do + project.issue_tags.select(:id, :name, :color).collect do |event| + { + id: event.id, + name: event.name, + color: event.color, + is_chosen: '0' + } + end + end + end + + def render_cache_milestones(project) + cache_key = "all_milestones/#{project.versions.maximum('updated_on')}" + + Rails.cache.fetch(cache_key) do + project.versions.select(:id, :name, :status).collect do |event| + { + id: event.id, + name: event.name, + status: event.status, + is_chosen: '0' + } + end + end + end + + def render_cache_collaborators(project) + cache_key = "all_collaborators/#{project.members.maximum('created_on')}" + + Rails.cache.fetch(cache_key) do + project.members.includes(:user).collect do |event| + { + id: event.user&.id, + name: event.user&.show_real_name, + avatar_url: url_to_avatar(event.user), + is_chosen: '0' + } + end + end + end + def issue_left_chosen(project,issue_id) issue_info = Array.new(11) @@ -205,4 +344,4 @@ module TagChosenHelper # be_depended_issues_array # end -end \ No newline at end of file +end diff --git a/app/interactors/gitea/create_file_interactor.rb b/app/interactors/gitea/create_file_interactor.rb index df159b6c..f18cc4f8 100644 --- a/app/interactors/gitea/create_file_interactor.rb +++ b/app/interactors/gitea/create_file_interactor.rb @@ -9,7 +9,8 @@ module Gitea attr_reader :error, :result def initialize(token, owner, params) - @owner = owner + @token = token + @owner = owner @params = params end @@ -58,6 +59,7 @@ module Gitea file_params = file_params.merge(new_branch: @params[:new_branch]) unless @params[:new_branch].blank? file_params = file_params.merge(content: Base64.encode64(@params[:content])) file_params = file_params.merge(message: @params[:message]) unless @params[:message].blank? + file_params = file_params.merge(committer: @params[:committer]) file_params end end diff --git a/app/interactors/gitea/register_interactor.rb b/app/interactors/gitea/register_interactor.rb index 909a6791..d8dbc6ca 100644 --- a/app/interactors/gitea/register_interactor.rb +++ b/app/interactors/gitea/register_interactor.rb @@ -22,7 +22,7 @@ module Gitea def run Gitea::UserForm.new(params).validate! - response = Gitea::User::RegisterService.new(params).call + response = Gitea::User::RegisterService.call(params.merge(token: token)) render_result(response) rescue Exception => exception Rails.logger.info "Exception ===========> #{exception.message}" @@ -41,5 +41,12 @@ module Gitea def render_result(response) @result = response end + + def token + { + username: Gitea.gitea_config[:access_key_id], + password: Gitea.gitea_config[:access_key_secret] + } + end end end diff --git a/app/interactors/repositories/protected_branches/delete_interactor.rb b/app/interactors/repositories/protected_branches/delete_interactor.rb new file mode 100644 index 00000000..990440b5 --- /dev/null +++ b/app/interactors/repositories/protected_branches/delete_interactor.rb @@ -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 diff --git a/app/jobs/post_chain_job.rb b/app/jobs/post_chain_job.rb new file mode 100644 index 00000000..68aefbae --- /dev/null +++ b/app/jobs/post_chain_job.rb @@ -0,0 +1,24 @@ +class PostChainJob < ApplicationJob + queue_as :default + + def perform(chain_params) + status = false + chain_type = chain_params[:type].to_s + reponame = chain_params[:chain_params][:reponame] + 5.times do |i| + if status + break + else + response = Gitea::Chain::ChainPostService.new(chain_params).call + if response.status == 200 + reponse_body = response&.body + messages = reponse_body.present? ? JSON.parse(reponse_body) : "success" + status = true + Rails.logger.info("################_repository__#{reponame}______create_chain_success_try:_#{i+1}_message__:#{messages}__") + else + Rails.logger.info("########_repository__#{reponame}______create_chain_failed__try:_#{i+1}_") + end + end + end + end +end \ No newline at end of file diff --git a/app/jobs/sync_educoder_shixun_job.rb b/app/jobs/sync_educoder_shixun_job.rb new file mode 100644 index 00000000..d5f78271 --- /dev/null +++ b/app/jobs/sync_educoder_shixun_job.rb @@ -0,0 +1,73 @@ +require 'uri' +require 'net/http' + +class SyncEducoderShixunJob < ApplicationJob + queue_as :default + + def perform(url, private_token, page, per_page) + uri = URI("#{url}?page=#{page}&per_page=#{per_page}&private_token=#{private_token}") + puts "-------url: #{uri}" + response = Net::HTTP.get_response(uri) + + result = JSON.parse(response.body) + + if result['status'] != 0 + puts "======= 接口请求失败!" + return + end + + result['data']['repositories'].each do |re| + next if re['repo_name'].blank? + next if ProjectEducoder.exists?(repo_name: re['repo_name']) + + language = ProjectLanguage.find_by_name re['language'] + language = ProjectLanguage.create!(name: re['language']) if language.blank? + + category = ProjectCategory.find_by_name re['category'] + category = ProjectCategory.create!(name: re['category']) if category.blank? + + project_params = + { + name: re['name'], + # user_id: params[:user_id], + description: re['description'], + project_category_id: category.id, + project_language_id: language.id, + is_public: true, + # ignore_id: params[:ignore_id], + # license_id: params[:license_id], + identifier: re['repo_name'], + platform: Project.platforms[:educoder] + } + + project = Project.new(project_params) + + ActiveRecord::Base.transaction do + if project.save! + repo_params = + { + hidden: false, + project_id: project.id, + identifier: re['repo_name'] + } + + ProjectEducoder.create!( + project_id: project.id, + owner: re['username'], + repo_name: re['repo_name'], + forked_count: re['forked_count'], + commit_count: re['commit_count'], + image_url: re['image_url']) + + repo = Repository.new(repo_params) + repo.save! + + puts "项目: #{re['name']} 同步成功" + else + puts "项目: #{re['name']} 同步失败" + end + end + end + end + +end diff --git a/app/jobs/sync_projects_job.rb b/app/jobs/sync_projects_job.rb index 9e883ed3..4b8339d6 100644 --- a/app/jobs/sync_projects_job.rb +++ b/app/jobs/sync_projects_job.rb @@ -8,7 +8,7 @@ class SyncProjectsJob < ApplicationJob SyncLog.sync_log("==========begin to sync #{sync_params[:type]} to forge============") SyncLog.sync_log("==========sync_params:#{sync_params}============") - begin + begin url = "#{gitea_main}/sync_forges" #trustie上的相关路由 uri = URI.parse(url) http = Net::HTTP.new(uri.hostname, uri.port) @@ -85,7 +85,7 @@ class SyncProjectsJob < ApplicationJob new_target = target_type.constantize.new(re[:target_params].merge(user_id: u_id)) end end - + if !is_exists && new_target.save! SyncLog.sync_log("***【#{target_type}】. create_success---------------") if re[:journals].present? @@ -112,10 +112,8 @@ class SyncProjectsJob < ApplicationJob SyncLog.sync_log("=========***【#{target_type}】creat_had_erros:#{e}===================") next end - end - end def create_journals(target_jsons, target_type,issue_id) @@ -127,7 +125,7 @@ class SyncProjectsJob < ApplicationJob if re[:target_params].present? u_id = User.select(:id, :login).where(login: re[:user_login]).pluck(:id).first is_exists = Journal.exists?(user_id: u_id, journalized_id: re[:target_params][:journalized_id], created_on: re[:target_params][:created_on].to_s.to_time) - + if is_exists SyncLog.sync_log("***00000. Journal:#{re[:target_params][:id]}-is exists--------------") else @@ -142,7 +140,7 @@ class SyncProjectsJob < ApplicationJob end else SyncLog.sync_log("***111222. journal_create failed---------------") - + end end end @@ -181,4 +179,4 @@ class SyncProjectsJob < ApplicationJob SyncLog.sync_log("***111222. end_to_create_target---------------") end -end \ No newline at end of file +end diff --git a/app/libs/ci/database.rb b/app/libs/ci/database.rb new file mode 100644 index 00000000..f3d606f4 --- /dev/null +++ b/app/libs/ci/database.rb @@ -0,0 +1,31 @@ +module Ci + class Database < ActiveRecord::Base + self.abstract_class = true + + # Dynamically sets the database connection. + def self.set_connection(params) + puts "[Ci::Database] set db connection params: #{params}" + establish_connection( + adapter: params[:adapter], + database: params[:database], + port: params[:port].to_i, + host: params[:host], + username: params[:username], + password: params[:password], + encoding: "utf8" + ) + end + + def self.get_connection_params(connect_to) + params = Hash.new + params[:adapter] = "mysql2" + params[:host] = connect_to[:host].to_s + params[:username] = connect_to[:username].to_s + params[:password] = connect_to[:password].to_s + params[:database] = connect_to[:database].to_s + params[:port] = connect_to[:port] || "43306" + params[:encoding] = "utf8" + return params + end + end +end diff --git a/app/libs/ci/drone/api.rb b/app/libs/ci/drone/api.rb new file mode 100644 index 00000000..6891efa9 --- /dev/null +++ b/app/libs/ci/drone/api.rb @@ -0,0 +1,81 @@ +class Ci::Drone::API < Ci::Drone::Request + attr_reader :drone_token, :endpoint, :owner, :repo, :options + + # drone_token: + # owner: repo's owner name or login + # repo: repo's identifier + def initialize(drone_token, endpoint, owner, repo, options={}) + @drone_token = drone_token + @endpoint = endpoint + @owner = owner + @repo = repo + @options = options + end + + # Build List + # GET api/repos/{owner}/{name}/builds + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier) + def builds + get(endpoint, "api/repos/#{owner}/#{repo}/builds", drone_token: drone_token) + end + + # Build Info + # GET api/repos/{owner}/{name}/builds/{number} + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier, number: number).build + def build + get(endpoint, "api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token) + end + + # Update .trustie-pipeline.yml file + # PATCH api/repos/{owner}/{name}\ + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier, config_path: config_path).config_yml + def config_yml + patch(endpoint, "/api/repos/#{owner}/#{repo}", drone_token: drone_token, config_path: options[:config_path]) + end + + # Activate user's project with Drone CI + # POST api/repos/{owner}/{name} + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, project.owner.login, project.identifier).activate + def activate + post(endpoint, "/api/repos/#{owner}/#{repo}", drone_token: drone_token) + end + + # Build Restart + # POST api/repos/{owner}/{name}/builds/{number} + # Restart the specified build. Please note this api requires read and write access to the repository and the request parameter {build} is not the build id but the build number. + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).restart + def restart + post(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token) + end + + # Build Stop + # DELETE api/repos/{owner}/{name}/builds/{number} + # Stop the specified build. Please note this api requires administrative privileges and the request parameter {build} is not the build id but the build number. + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).stop + def stop + delete(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:number]}", drone_token: drone_token) + end + + # Build Logs + # GET /api/repos/{owner}/{repo}/builds/{build}/logs/{stage}/{step} + # Please note this api requires read access to the repository. + # eq: + # Ci::Drone::API.new(cloud_account.drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, build: build, stage: stage, step: step).logs + def logs + get(endpoint, "/api/repos/#{owner}/#{repo}/builds/#{options[:build]}/logs/#{options[:stage]}/#{options[:step]}", drone_token: drone_token) + end + + # Synchronize the currently authenticated user’s repository list. + # POST /api/user/repos + # eq: + # Ci::Drone::API.new(drone_token, cloud_account.drone_url, @repo.user.login, @repo.identifier, number: number).sync + def sync_repos + post(endpoint, "/api/users/repos", drone_token: drone_token) + end +end diff --git a/app/libs/ci/drone/ci.rb b/app/libs/ci/drone/ci.rb new file mode 100644 index 00000000..c47b5396 --- /dev/null +++ b/app/libs/ci/drone/ci.rb @@ -0,0 +1,25 @@ +class Ci::Drone::Ci + attr_reader :host, :username, :password, :gitea_username + + # host: drone server's ip + # username: drone server's account + # password: drone server's password + # eq: + # DevOps::Drone::Ci.new(@cloud_account.drone_ip, @cloud_account.account, @cloud_account.visible_secret, current_user.login).get_token + def initialize(host, username, password, gitea_username) + @host = host + @username = username + @password = password + @gitea_username = gitea_username + end + + def get_token + puts "--------- sshpass -p #{password} ssh -o 'StrictHostKeyChecking no' #{username}@#{host} '#{cmd}'" + `sshpass -p #{password} ssh -o "StrictHostKeyChecking no" #{username}@#{host} "#{cmd}"` + end + + private + def cmd + "cd ..; cd var/lib/drone/; sqlite3 database.sqlite; .dump; select user_hash from users where user_login=#{gitea_username};" + end +end diff --git a/app/libs/ci/drone/client.rb b/app/libs/ci/drone/client.rb new file mode 100644 index 00000000..ebaef5b1 --- /dev/null +++ b/app/libs/ci/drone/client.rb @@ -0,0 +1,25 @@ +class Ci::Drone::Client + attr_reader :client_id, :drone_ip, :rpc_secret + + # client_id: user's client_id from oauth + # drone_ip: 云服务器IP地址, eq: 173.65.32.21 + # eq: + # DevOps::Drone::Client.new(current_user.oauth.client_id, 'drone_ip').generate_cmd + def initialize(client_id, drone_ip, rpc_secret) + @client_id = client_id + @drone_ip = drone_ip + @rpc_secret = rpc_secret + end + + def generate_cmd + "docker run -d \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e DRONE_RPC_HOST=#{drone_ip}:80 \ + -e DRONE_RPC_SECRET=#{rpc_secret} \ + -e DRONE_RUNNER_NAME=#{drone_ip} \ + --restart always \ + --name drone-agent--#{client_id} \ + --net='bridge' \ + drone/drone-runner-docker:1" + end +end diff --git a/app/libs/ci/drone/error.rb b/app/libs/ci/drone/error.rb new file mode 100644 index 00000000..2ddfccd8 --- /dev/null +++ b/app/libs/ci/drone/error.rb @@ -0,0 +1,14 @@ +class Ci::Drone::Error < StandardError + attr_reader :code + + def initialize(code, message) + super message + @code = code + end + + class << self + def parse(result) + new(result['errcode'], result['errmsg']) + end + end +end diff --git a/app/libs/ci/drone/request.rb b/app/libs/ci/drone/request.rb new file mode 100644 index 00000000..5f3e54be --- /dev/null +++ b/app/libs/ci/drone/request.rb @@ -0,0 +1,108 @@ +class Ci::Drone::Request + # Converts the response body to an ObjectifiedHash. + def self.parse(body) + body = decode(body) + + if body.is_a? Hash + ObjectifiedHash.new body + elsif body.is_a? Array + body.collect! { |e| ObjectifiedHash.new(e) } + elsif body == true + body + else + raise Error::Parsing.new "Couldn't parse a response body" + end + end + + # Decodes a JSON response into Ruby object. + def self.decode(response) + begin + JSON.load response + rescue JSON::ParserError + raise Error::Parsing.new "The response is not a valid JSON" + end + end + + def get(endpoint, path, options={}) + validate_request_params!(endpoint) + request(:get, endpoint, path, options) + end + + def post(endpoint, path, options={}) + validate_request_params!(endpoint) + request(:post, endpoint, path, options) + end + + def put(endpoint, path, options={}) + validate_request_params!(endpoint) + request(:put, endpoint, path, options) + end + + def patch(endpoint, path, options={}) + validate_request_params!(endpoint) + request(:patch, endpoint, path, options) + end + + def delete(endpoint, path, options={}) + validate_request_params!(endpoint) + request(:delete, endpoint, path, options) + end + + private + def request(method, endpoint, path, **params) + Rails.logger.info("[drone] request: #{method} #{path} #{params.except(:drone_token).inspect}") + + client ||= begin + Faraday.new(url: endpoint) do |req| + req.request :url_encoded + req.headers['Content-Type'] = 'application/json' + req.response :logger # 显示日志 + req.adapter Faraday.default_adapter + req.authorization :Bearer, params[:drone_token] + req.headers['Authorization'] + end + end + response = client.public_send(method, path) do |req| + req.body = params.except(:drone_token).to_json + end + + json_response(response) + end + + # Checks the response code for common errors. + # Returns parsed response for successful requests. + def validate(response) + # case response.code + # when 400; raise Error::BadRequest.new error_message(response) + # when 401; raise Error::Unauthorized.new error_message(response) + # when 403; raise Error::Forbidden.new error_message(response) + # when 404; raise Error::NotFound.new error_message(response) + # when 405; raise Error::MethodNotAllowed.new error_message(response) + # when 406; raise Error::DataNotAccepted.new error_message(response) + # when 409; raise Error::Conflict.new error_message(response) + # when 500; raise Error::InternalServerError.new error_message(response) + # when 502; raise Error::BadGateway.new error_message(response) + # when 503; raise Error::ServiceUnavailable.new error_message(response) + # end + + response.parsed_response + 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) + "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ + "Request URI: #{response.request.base_uri}#{response.request.path}" + 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 diff --git a/app/libs/ci/drone/server.rb b/app/libs/ci/drone/server.rb new file mode 100644 index 00000000..add2e439 --- /dev/null +++ b/app/libs/ci/drone/server.rb @@ -0,0 +1,62 @@ +class Ci::Drone::Server + attr_reader :user_login, :client_id, :client_secret, :drone_host, :rpc_secret + + # client_id: user's client_id from oauth + # client_secret: user's client_id from oauth + # drone_host: 云服务器地址,eq: 173.53.21.31:80 + # eg: + # DevOps::Drone::Server.new(current_user.login, current_user.oauth.client_id, current_user.oauth.client_secret, 'drone_host').generate_cmd + def initialize(user_login, client_id, client_secret, drone_host, rpc_secret) + @user_login = user_login + @client_id = client_id + @drone_host = drone_host + @rpc_secret = rpc_secret + @client_secret = client_secret + end + + # TODO 一下代码方便测试,正式环境请移除 + # docker rm -f `docker ps -qa` + def generate_cmd + "service docker start; docker run \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -e DRONE_DATABASE_DRIVER=mysql \ + -e DRONE_DATABASE_DATASOURCE=#{database_username}:'#{database_password}'@tcp\\(#{database_host}:#{database_port}\\)/#{user_login}_drone?parseTime=true \ + -e DRONE_GITEA_SERVER=#{gitea_url} \ + -e DRONE_GITEA_CLIENT_ID=#{client_id} \ + -e DRONE_GITEA_CLIENT_SECRET=#{client_secret} \ + -e DRONE_RPC_SECRET=#{rpc_secret} \ + -e DRONE_SERVER_HOST=#{drone_host} \ + -e DRONE_SERVER_PROTO=http \ + -p '80:80' \ + --restart=always \ + --detach=true \ + --name=drone-server-#{client_id} \ + --net='bridge' \ + drone/drone:1" + end + + private + def gitea_url + Gitea.gitea_config[:domain] + end + + def database_username + database_config[Rails.env]["ci_server_db"]["username"] + end + + def database_password + database_config[Rails.env]["ci_server_db"]["password"] + end + + def database_host + database_config[Rails.env]["ci_server_db"]["host"] + end + + def database_port + database_config[Rails.env]["ci_server_db"]["port"] || 3306 + end + + def database_config + Rails.configuration.database_configuration + end +end diff --git a/app/libs/ci/drone/start.rb b/app/libs/ci/drone/start.rb new file mode 100644 index 00000000..19b7d09c --- /dev/null +++ b/app/libs/ci/drone/start.rb @@ -0,0 +1,22 @@ +class Ci::Drone::Start + attr_reader :drone_username, :drone_password, :drone_host, :drone_server_cmd, :drone_client_cmd + + # drone_username="XXXX" 云服务器登录用户名 + # drone_password="XXXXX" 云服务器用户密码 + # drone_host="" 云服务器地址 + # eq: + # drone_server_cmd = DevOps::Drone::Server.new('client_id', 'client_secret', 'drone_url').generate_cmd + # drone_client_cmd = DevOps::Drone::Client.new('client_id', 'server_url').generate_cmd + # DevOps::Drone::Start.new(drone_username, drone_password, 'drone_host', drone_server_cmd, drone_client_cmd).run + def initialize(drone_username, drone_password, drone_host, drone_server_cmd, drone_client_cmd) + @drone_username = drone_username + @drone_password = drone_password + @drone_host = drone_host + @drone_server_cmd = drone_server_cmd + @drone_client_cmd = drone_client_cmd + end + + def run + `sshpass -p #{drone_password} ssh -o "StrictHostKeyChecking no" #{drone_username}@#{drone_host} "#{drone_server_cmd} && #{drone_client_cmd}"` + end +end diff --git a/app/libs/ci/schema.rb b/app/libs/ci/schema.rb new file mode 100644 index 00000000..b510f3a3 --- /dev/null +++ b/app/libs/ci/schema.rb @@ -0,0 +1,260 @@ +module Ci::Schema + class << self + def statement + sqls = <<-SQL + CREATE TABLE IF NOT EXISTS `repos` ( + `repo_id` int(11) NOT NULL AUTO_INCREMENT, + `repo_uid` varchar(250) DEFAULT NULL, + `repo_user_id` int(11) DEFAULT NULL, + `repo_namespace` varchar(250) DEFAULT NULL, + `repo_name` varchar(250) DEFAULT NULL, + `repo_slug` varchar(250) DEFAULT NULL, + `repo_scm` varchar(50) DEFAULT NULL, + `repo_clone_url` varchar(2000) DEFAULT NULL, + `repo_ssh_url` varchar(2000) DEFAULT NULL, + `repo_html_url` varchar(2000) DEFAULT NULL, + `repo_active` tinyint(1) DEFAULT NULL, + `repo_private` tinyint(1) DEFAULT NULL, + `repo_visibility` varchar(50) DEFAULT NULL, + `repo_branch` varchar(250) DEFAULT NULL, + `repo_counter` int(11) DEFAULT NULL, + `repo_config` varchar(500) DEFAULT NULL, + `repo_timeout` int(11) DEFAULT NULL, + `repo_trusted` tinyint(1) DEFAULT NULL, + `repo_protected` tinyint(1) DEFAULT NULL, + `repo_synced` int(11) DEFAULT NULL, + `repo_created` int(11) DEFAULT NULL, + `repo_updated` int(11) DEFAULT NULL, + `repo_version` int(11) DEFAULT NULL, + `repo_signer` varchar(50) DEFAULT NULL, + `repo_secret` varchar(50) DEFAULT NULL, + PRIMARY KEY (`repo_id`), + UNIQUE KEY `repo_slug` (`repo_slug`), + UNIQUE KEY `repo_uid` (`repo_uid`) + ) ENGINE=InnoDB AUTO_INCREMENT=137 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `builds` ( + `build_id` int(11) NOT NULL AUTO_INCREMENT, + `build_repo_id` int(11) DEFAULT NULL, + `build_config_id` int(11) DEFAULT NULL, + `build_trigger` varchar(250) DEFAULT NULL, + `build_number` int(11) DEFAULT NULL, + `build_parent` int(11) DEFAULT NULL, + `build_status` varchar(50) DEFAULT NULL, + `build_error` varchar(500) DEFAULT NULL, + `build_event` varchar(50) DEFAULT NULL, + `build_action` varchar(50) DEFAULT NULL, + `build_link` varchar(1000) DEFAULT NULL, + `build_timestamp` int(11) DEFAULT NULL, + `build_title` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `build_message` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `build_before` varchar(50) DEFAULT NULL, + `build_after` varchar(50) DEFAULT NULL, + `build_ref` varchar(500) DEFAULT NULL, + `build_source_repo` varchar(250) DEFAULT NULL, + `build_source` varchar(500) DEFAULT NULL, + `build_target` varchar(500) DEFAULT NULL, + `build_author` varchar(500) DEFAULT NULL, + `build_author_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `build_author_email` varchar(500) DEFAULT NULL, + `build_author_avatar` varchar(1000) DEFAULT NULL, + `build_sender` varchar(500) DEFAULT NULL, + `build_deploy` varchar(500) DEFAULT NULL, + `build_params` varchar(2000) DEFAULT NULL, + `build_started` int(11) DEFAULT NULL, + `build_finished` int(11) DEFAULT NULL, + `build_created` int(11) DEFAULT NULL, + `build_updated` int(11) DEFAULT NULL, + `build_version` int(11) DEFAULT NULL, + PRIMARY KEY (`build_id`), + UNIQUE KEY `build_repo_id` (`build_repo_id`,`build_number`) + ) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `cron` ( + `cron_id` int(11) NOT NULL AUTO_INCREMENT, + `cron_repo_id` int(11) DEFAULT NULL, + `cron_name` varchar(50) DEFAULT NULL, + `cron_expr` varchar(50) DEFAULT NULL, + `cron_next` int(11) DEFAULT NULL, + `cron_prev` int(11) DEFAULT NULL, + `cron_event` varchar(50) DEFAULT NULL, + `cron_branch` varchar(250) DEFAULT NULL, + `cron_target` varchar(250) DEFAULT NULL, + `cron_disabled` tinyint(1) DEFAULT NULL, + `cron_created` int(11) DEFAULT NULL, + `cron_updated` int(11) DEFAULT NULL, + `cron_version` int(11) DEFAULT NULL, + PRIMARY KEY (`cron_id`), + UNIQUE KEY `cron_repo_id` (`cron_repo_id`,`cron_name`), + CONSTRAINT `cron_ibfk_1` FOREIGN KEY (`cron_repo_id`) REFERENCES `repos` (`repo_id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + CREATE TABLE IF NOT EXISTS `latest` ( + `latest_repo_id` int(11) NOT NULL DEFAULT '0', + `latest_build_id` int(11) DEFAULT NULL, + `latest_type` varchar(50) NOT NULL DEFAULT '', + `latest_name` varchar(500) NOT NULL DEFAULT '', + `latest_created` int(11) DEFAULT NULL, + `latest_updated` int(11) DEFAULT NULL, + `latest_deleted` int(11) DEFAULT NULL, + PRIMARY KEY (`latest_repo_id`,`latest_type`,`latest_name`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `logs` ( + `log_id` int(11) NOT NULL, + `log_data` mediumblob, + PRIMARY KEY (`log_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `migrations` ( + `name` varchar(255) DEFAULT NULL, + UNIQUE KEY `name` (`name`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + CREATE TABLE IF NOT EXISTS `nodes` ( + `node_id` int(11) NOT NULL AUTO_INCREMENT, + `node_uid` varchar(500) DEFAULT NULL, + `node_provider` varchar(50) DEFAULT NULL, + `node_state` varchar(50) DEFAULT NULL, + `node_name` varchar(50) DEFAULT NULL, + `node_image` varchar(500) DEFAULT NULL, + `node_region` varchar(100) DEFAULT NULL, + `node_size` varchar(100) DEFAULT NULL, + `node_os` varchar(50) DEFAULT NULL, + `node_arch` varchar(50) DEFAULT NULL, + `node_kernel` varchar(50) DEFAULT NULL, + `node_variant` varchar(50) DEFAULT NULL, + `node_address` varchar(500) DEFAULT NULL, + `node_capacity` int(11) DEFAULT NULL, + `node_filter` varchar(2000) DEFAULT NULL, + `node_labels` varchar(2000) DEFAULT NULL, + `node_error` varchar(2000) DEFAULT NULL, + `node_ca_key` blob, + `node_ca_cert` blob, + `node_tls_key` blob, + `node_tls_cert` blob, + `node_tls_name` varchar(500) DEFAULT NULL, + `node_paused` tinyint(1) DEFAULT NULL, + `node_protected` tinyint(1) DEFAULT NULL, + `node_created` int(11) DEFAULT NULL, + `node_updated` int(11) DEFAULT NULL, + `node_pulled` int(11) DEFAULT NULL, + PRIMARY KEY (`node_id`), + UNIQUE KEY `node_name` (`node_name`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `orgsecrets` ( + `secret_id` int(11) NOT NULL AUTO_INCREMENT, + `secret_namespace` varchar(50) DEFAULT NULL, + `secret_name` varchar(200) DEFAULT NULL, + `secret_type` varchar(50) DEFAULT NULL, + `secret_data` blob, + `secret_pull_request` tinyint(1) DEFAULT NULL, + `secret_pull_request_push` tinyint(1) DEFAULT NULL, + PRIMARY KEY (`secret_id`), + UNIQUE KEY `secret_namespace` (`secret_namespace`,`secret_name`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `perms` ( + `perm_user_id` int(11) NOT NULL DEFAULT '0', + `perm_repo_uid` varchar(250) NOT NULL DEFAULT '', + `perm_read` tinyint(1) DEFAULT NULL, + `perm_write` tinyint(1) DEFAULT NULL, + `perm_admin` tinyint(1) DEFAULT NULL, + `perm_synced` int(11) DEFAULT NULL, + `perm_created` int(11) DEFAULT NULL, + `perm_updated` int(11) DEFAULT NULL, + PRIMARY KEY (`perm_user_id`,`perm_repo_uid`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `secrets` ( + `secret_id` int(11) NOT NULL AUTO_INCREMENT, + `secret_repo_id` int(11) DEFAULT NULL, + `secret_name` varchar(500) DEFAULT NULL, + `secret_data` blob, + `secret_pull_request` tinyint(1) DEFAULT NULL, + `secret_pull_request_push` tinyint(1) DEFAULT NULL, + PRIMARY KEY (`secret_id`), + UNIQUE KEY `secret_repo_id` (`secret_repo_id`,`secret_name`), + CONSTRAINT `secrets_ibfk_1` FOREIGN KEY (`secret_repo_id`) REFERENCES `repos` (`repo_id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `stages` ( + `stage_id` int(11) NOT NULL AUTO_INCREMENT, + `stage_repo_id` int(11) DEFAULT NULL, + `stage_build_id` int(11) DEFAULT NULL, + `stage_number` int(11) DEFAULT NULL, + `stage_name` varchar(100) DEFAULT NULL, + `stage_kind` varchar(50) DEFAULT NULL, + `stage_type` varchar(50) DEFAULT NULL, + `stage_status` varchar(50) DEFAULT NULL, + `stage_error` varchar(500) DEFAULT NULL, + `stage_errignore` tinyint(1) DEFAULT NULL, + `stage_exit_code` int(11) DEFAULT NULL, + `stage_limit` int(11) DEFAULT NULL, + `stage_os` varchar(50) DEFAULT NULL, + `stage_arch` varchar(50) DEFAULT NULL, + `stage_variant` varchar(10) DEFAULT NULL, + `stage_kernel` varchar(50) DEFAULT NULL, + `stage_machine` varchar(500) DEFAULT NULL, + `stage_started` int(11) DEFAULT NULL, + `stage_stopped` int(11) DEFAULT NULL, + `stage_created` int(11) DEFAULT NULL, + `stage_updated` int(11) DEFAULT NULL, + `stage_version` int(11) DEFAULT NULL, + `stage_on_success` tinyint(1) DEFAULT NULL, + `stage_on_failure` tinyint(1) DEFAULT NULL, + `stage_depends_on` text, + `stage_labels` text, + PRIMARY KEY (`stage_id`), + UNIQUE KEY `stage_build_id` (`stage_build_id`,`stage_number`) + ) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `stages_unfinished` ( + `stage_id` int(11) NOT NULL, + PRIMARY KEY (`stage_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `steps` ( + `step_id` int(11) NOT NULL AUTO_INCREMENT, + `step_stage_id` int(11) DEFAULT NULL, + `step_number` int(11) DEFAULT NULL, + `step_name` varchar(100) DEFAULT NULL, + `step_status` varchar(50) DEFAULT NULL, + `step_error` varchar(500) DEFAULT NULL, + `step_errignore` tinyint(1) DEFAULT NULL, + `step_exit_code` int(11) DEFAULT NULL, + `step_started` int(11) DEFAULT NULL, + `step_stopped` int(11) DEFAULT NULL, + `step_version` int(11) DEFAULT NULL, + PRIMARY KEY (`step_id`), + UNIQUE KEY `step_stage_id` (`step_stage_id`,`step_number`) + ) ENGINE=InnoDB AUTO_INCREMENT=83 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + + CREATE TABLE IF NOT EXISTS `users` ( + `user_id` int(11) NOT NULL AUTO_INCREMENT, + `user_login` varchar(250) DEFAULT NULL, + `user_email` varchar(500) DEFAULT NULL, + `user_admin` tinyint(1) DEFAULT NULL, + `user_machine` tinyint(1) DEFAULT NULL, + `user_active` tinyint(1) DEFAULT NULL, + `user_avatar` varchar(2000) DEFAULT NULL, + `user_syncing` tinyint(1) DEFAULT NULL, + `user_synced` int(11) DEFAULT NULL, + `user_created` int(11) DEFAULT NULL, + `user_updated` int(11) DEFAULT NULL, + `user_last_login` int(11) DEFAULT NULL, + `user_oauth_token` varchar(500) DEFAULT NULL, + `user_oauth_refresh` varchar(500) DEFAULT NULL, + `user_oauth_expiry` int(11) DEFAULT NULL, + `user_hash` varchar(500) DEFAULT NULL, + PRIMARY KEY (`user_id`), + UNIQUE KEY `user_login` (`user_login`), + UNIQUE KEY `user_hash` (`user_hash`) + ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; + SQL + + sqls + end + end +end diff --git a/app/libs/custom_regexp.rb b/app/libs/custom_regexp.rb index 497c26ca..4aa6fac2 100644 --- a/app/libs/custom_regexp.rb +++ b/app/libs/custom_regexp.rb @@ -5,4 +5,5 @@ module CustomRegexp NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/ PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/ -end \ No newline at end of file + IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ +end diff --git a/app/libs/gitea/database.rb b/app/libs/gitea/database.rb new file mode 100644 index 00000000..4698607a --- /dev/null +++ b/app/libs/gitea/database.rb @@ -0,0 +1,12 @@ +module Gitea + class Database < ActiveRecord::Base + self.abstract_class = true + + def self.set_connection + gitea_server_config = Rails.configuration.database_configuration[Rails.env]["gitea_server"] + raise 'gitea database config missing' if gitea_server_config.blank? + + establish_connection gitea_server_config + end + end +end diff --git a/app/models/applied_message.rb b/app/models/applied_message.rb index ed02a544..8098e6e0 100644 --- a/app/models/applied_message.rb +++ b/app/models/applied_message.rb @@ -1,5 +1,23 @@ +# == Schema Information +# +# Table name: applied_messages +# +# id :integer not null, primary key +# user_id :integer +# applied_id :integer +# applied_type :string(255) +# viewed :integer default("0") +# status :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# name :string(255) +# applied_user_id :integer +# role :integer +# project_id :integer +# + class AppliedMessage < ApplicationRecord belongs_to :user belongs_to :applied, polymorphic: true -end \ No newline at end of file +end diff --git a/app/models/applied_project.rb b/app/models/applied_project.rb index 901443e8..68095d0e 100644 --- a/app/models/applied_project.rb +++ b/app/models/applied_project.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: applied_projects +# +# id :integer not null, primary key +# project_id :integer not null +# user_id :integer not null +# role :integer default("0") +# status :integer default("0") +# + class AppliedProject < ApplicationRecord belongs_to :user belongs_to :project diff --git a/app/models/apply_action.rb b/app/models/apply_action.rb index 53fc8d4c..02a14211 100644 --- a/app/models/apply_action.rb +++ b/app/models/apply_action.rb @@ -1,3 +1,26 @@ +# == Schema Information +# +# Table name: apply_actions +# +# id :integer not null, primary key +# user_id :integer +# reason :string(255) +# container_id :integer +# container_type :string(255) +# dealer_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# status :integer default("0") +# apply_reason :text(65535) +# noticed :boolean default("0") +# ip_addr :string(255) +# reject_description :string(255) +# +# Indexes +# +# index_apply_actions_on_user_id (user_id) +# + # 申请消息 class ApplyAction < ApplicationRecord belongs_to :user @@ -27,4 +50,4 @@ class ApplyAction < ApplicationRecord belong_container_id: container_id, belong_container_type: belong_container_type) end end -end \ No newline at end of file +end diff --git a/app/models/apply_user_authentication.rb b/app/models/apply_user_authentication.rb index ad74b026..10522a94 100644 --- a/app/models/apply_user_authentication.rb +++ b/app/models/apply_user_authentication.rb @@ -1,3 +1,23 @@ +# == Schema Information +# +# Table name: apply_user_authentications +# +# id :integer not null, primary key +# user_id :integer +# status :integer +# auth_type :integer +# remarks :string(255) +# dealer :integer +# deal_time :datetime +# created_at :datetime not null +# updated_at :datetime not null +# is_delete :boolean default("0") +# +# Indexes +# +# index_apply_user_authentications_on_user_id (user_id) +# + # status:0 审核中 1 同意 2 拒绝 3 撤销 # auth_type:1 实名认证, 2 职业认证 class ApplyUserAuthentication < ApplicationRecord diff --git a/app/models/attachment.rb b/app/models/attachment.rb index a52158ec..d1e6402f 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -1,3 +1,42 @@ +# == Schema Information +# +# Table name: attachments +# +# id :integer not null, primary key +# container_id :integer +# container_type :string(30) +# filename :string(255) default(""), not null +# disk_filename :string(255) default(""), not null +# filesize :integer default("0"), not null +# content_type :string(255) default("") +# digest :string(60) default(""), not null +# downloads :integer default("0"), not null +# author_id :integer default("0"), not null +# created_on :datetime +# description :text(65535) +# disk_directory :string(255) +# attachtype :integer default("1") +# is_public :integer default("1") +# copy_from :integer +# quotes :integer default("0") +# is_publish :integer default("1") +# publish_time :datetime +# resource_bank_id :integer +# unified_setting :boolean default("1") +# cloud_url :string(255) default("") +# course_second_category_id :integer default("0") +# delay_publish :boolean default("0") +# +# Indexes +# +# index_attachments_on_author_id (author_id) +# index_attachments_on_container_id_and_container_type (container_id,container_type) +# index_attachments_on_course_second_category_id (course_second_category_id) +# index_attachments_on_created_on (created_on) +# index_attachments_on_is_public (is_public) +# index_attachments_on_quotes (quotes) +# + class Attachment < ApplicationRecord include BaseModel include Publicable diff --git a/app/models/attachment_group_setting.rb b/app/models/attachment_group_setting.rb index b7eb707f..3eaecf2b 100644 --- a/app/models/attachment_group_setting.rb +++ b/app/models/attachment_group_setting.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: attachment_group_settings +# +# id :integer not null, primary key +# attachment_id :integer +# course_group_id :integer +# course_id :integer +# publish_time :datetime +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_attachment_group_settings_on_attachment_id (attachment_id) +# index_attachment_group_settings_on_course_group_id (course_group_id) +# index_attachment_group_settings_on_course_id (course_id) +# + class AttachmentGroupSetting < ActiveRecord::Base belongs_to :attachment # belongs_to :course_group diff --git a/app/models/attachment_history.rb b/app/models/attachment_history.rb index c19146b9..86b672de 100644 --- a/app/models/attachment_history.rb +++ b/app/models/attachment_history.rb @@ -1,3 +1,31 @@ +# == Schema Information +# +# Table name: attachment_histories +# +# id :integer not null, primary key +# container_id :integer +# container_type :string(255) +# filename :string(255) default("") +# disk_filename :string(255) default("") +# filesize :integer default("0") +# content_type :string(255) default("") +# digest :string(60) default("") +# downloads :integer default("0") +# author_id :integer +# created_on :datetime +# description :text(65535) +# disk_directory :string(255) +# attachtype :integer +# is_public :integer +# copy_from :integer +# quotes :integer +# version :integer +# attachment_id :integer +# is_publish :integer default("1") +# publish_time :date +# cloud_url :string(255) default("") +# + class AttachmentHistory < ApplicationRecord include Publishable include Publicable diff --git a/app/models/bidding_user.rb b/app/models/bidding_user.rb index 3a427a01..9609e9e6 100644 --- a/app/models/bidding_user.rb +++ b/app/models/bidding_user.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: bidding_users +# +# id :integer not null, primary key +# project_package_id :integer +# user_id :integer +# status :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_bidding_users_on_project_package_id (project_package_id) +# index_bidding_users_on_user_id (user_id) +# + class BiddingUser < ApplicationRecord include AASM @@ -21,4 +38,4 @@ class BiddingUser < ApplicationRecord def status_text I18n.t("bidding_user.status.#{status}") end -end \ No newline at end of file +end diff --git a/app/models/ci.rb b/app/models/ci.rb new file mode 100644 index 00000000..2bce3b85 --- /dev/null +++ b/app/models/ci.rb @@ -0,0 +1,5 @@ +module Ci + # def self.table_name_prefix + # 'ci_' + # end +end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb new file mode 100644 index 00000000..6873f2ed --- /dev/null +++ b/app/models/ci/build.rb @@ -0,0 +1,14 @@ +class Ci::Build < Ci::RemoteBase + self.primary_key = 'build_id' + + belongs_to :repo, foreign_key: :build_repo_id + has_many :stages, foreign_key: "stage_build_id", dependent: :destroy + + scope :successed, ->{ by_status('success') } + scope :failed, -> { by_status('failure') } + scope :running, -> { by_status('running') } + scope :errored, -> { by_status('error') } + scope :pending, -> { by_status('pending') } + scope :killed, -> { by_status('killed') } + scope :by_status, ->(status) { where(build_status: status) } +end diff --git a/app/models/ci/cloud_account.rb b/app/models/ci/cloud_account.rb new file mode 100644 index 00000000..253017dc --- /dev/null +++ b/app/models/ci/cloud_account.rb @@ -0,0 +1,47 @@ +# == Schema Information +# +# Table name: ci_cloud_accounts +# +# id :integer not null, primary key +# user_id :integer not null +# ip_num :integer +# account :string(255) +# secret :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# ci_user_id :integer +# +# Indexes +# +# dev_ops_cloud_accounts_p_u_ip (user_id,ip_num) +# + +class Ci::CloudAccount < Ci::LocalBase + belongs_to :user + belongs_to :ci_user, class_name: 'Ci::User', foreign_key: :ci_user_id, optional: true + + def drone_host + [drone_ip, ":80"].join + end + + def drone_ip + IPAddr.new(self.ip_num, Socket::AF_INET).to_s + end + + def drone_url + ["http://", self.drone_host].join + end + + def visible_secret + Base64.decode64(secret) + end + + def self.encrypted_secret(str) + Base64.encode64(str.strip).gsub(/\n/, '') + end + + def authenticate_url + [drone_url, '/login'].join + end + +end diff --git a/app/models/ci/language.rb b/app/models/ci/language.rb new file mode 100644 index 00000000..3db42f35 --- /dev/null +++ b/app/models/ci/language.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: ci_languages +# +# id :integer not null, primary key +# name :string(255) not null +# content :text(65535) not null +# usage_amount :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# cover_id :integer +# + +class Ci::Language < Ci::LocalBase + # before_save :encode_content + + belongs_to :cover, class_name: "Attachment", foreign_key: :cover_id, optional: true + + scope :six_common, -> { limit(6).by_usage_amount_desc } + scope :without_content, -> { select(column_names - ['content']) } + scope :by_usage_amount_desc, -> { order(usage_amount: :desc) } + + + private + def encode_content + self.content = Base64.encode64 content + end +end diff --git a/app/models/ci/local_base.rb b/app/models/ci/local_base.rb new file mode 100644 index 00000000..2d6bf70f --- /dev/null +++ b/app/models/ci/local_base.rb @@ -0,0 +1,7 @@ +class Ci::LocalBase < ApplicationRecord + self.abstract_class = true + + def self.table_name_prefix + "ci_" + end +end diff --git a/app/models/ci/log.rb b/app/models/ci/log.rb new file mode 100644 index 00000000..b0c8e337 --- /dev/null +++ b/app/models/ci/log.rb @@ -0,0 +1,5 @@ +class Ci::Log < Ci::RemoteBase + self.primary_key = nil + + belongs_to :step, class_name: 'Ci::Step', foreign_key: :log_id +end diff --git a/app/models/ci/perm.rb b/app/models/ci/perm.rb new file mode 100644 index 00000000..e6bc2ebb --- /dev/null +++ b/app/models/ci/perm.rb @@ -0,0 +1,20 @@ +class Ci::Perm < Ci::RemoteBase + self.primary_key = nil + + belongs_to :user, class_name: 'Ci::User', foreign_key: :perm_user_id + belongs_to :repo, class_name: 'Ci::Repo', foreign_key: :perm_repo_uid + + def self.auto_create!(user, repo) + perm = new( + perm_user_id: user.user_id, + perm_repo_uid: repo.repo_id, + perm_read: true, + perm_write: true, + perm_admin: true, + perm_synced: 0, + perm_created: Time.now.to_i, + perm_updated: Time.now.to_i + ) + perm.save! + end +end diff --git a/app/models/ci/remote_base.rb b/app/models/ci/remote_base.rb new file mode 100644 index 00000000..836315ff --- /dev/null +++ b/app/models/ci/remote_base.rb @@ -0,0 +1,8 @@ +class Ci::RemoteBase < Ci::Database + self.abstract_class = true + + def generate_code + [*'a'..'z',*'0'..'9',*'A'..'Z'].sample(32).join + end + +end diff --git a/app/models/ci/repo.rb b/app/models/ci/repo.rb new file mode 100644 index 00000000..8396cfa9 --- /dev/null +++ b/app/models/ci/repo.rb @@ -0,0 +1,64 @@ +class Ci::Repo < Ci::RemoteBase + self.primary_key = 'repo_id' + + belongs_to :user, foreign_key: :repo_user_id + has_one :perm, foreign_key: :perm_repo_uid + has_many :builds, foreign_key: :build_repo_id, dependent: :destroy + + def self.find_with_namespace(namespace_path, identifier) + logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} " + + user = Ci::User.find_by_user_login namespace_path + repo = Ci::Repo.where(repo_namespace: namespace_path, repo_name: identifier).first + + [user, repo] + end + + def activate!(ci_user_id) + update(repo_active: 1, + repo_signer: generate_code, + repo_secret: generate_code, + repo_user_id: ci_user_id, + repo_timeout: 60, + repo_config: '.trustie-pipeline.yml', + repo_updated: Time.now.to_i) + end + + def self.auto_create!(user, project) + repo = new( + repo_user_id: user.user_id, + repo_namespace: project.owner.login, + repo_name: project.identifier, + repo_slug: "#{project.owner.login}/#{project.identifier}", + repo_scm: "git", + repo_ssh_url: "", + repo_html_url: "", + repo_clone_url: project.repository.url, + repo_active: 1, + repo_private: true, + repo_visibility: 'private', + repo_branch: 'master', + repo_counter: 0, + repo_trusted: false, + repo_protected: false, + repo_synced: 0, + repo_version: 1, + repo_timeout: 60, + repo_config: '.trustie-pipeline.yml', + repo_created: Time.now.to_i, + repo_updated: Time.now.to_i + ) + + repo.repo_signer = repo.generate_code + repo.repo_secret = repo.generate_code + if repo.save! + Ci::Perm.auto_create!(user, repo) + repo.update_column(:repo_uid, repo.id) + repo + end + end + + def deactivate! + update_column(:repo_active, 0) + end +end diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb new file mode 100644 index 00000000..2309f05d --- /dev/null +++ b/app/models/ci/stage.rb @@ -0,0 +1,6 @@ +class Ci::Stage < Ci::RemoteBase + self.primary_key = 'stage_id' + + belongs_to :build, foreign_key: :stage_build_id + has_many :steps, foreign_key: "step_stage_id", dependent: :destroy +end diff --git a/app/models/ci/step.rb b/app/models/ci/step.rb new file mode 100644 index 00000000..eed7d6a7 --- /dev/null +++ b/app/models/ci/step.rb @@ -0,0 +1,6 @@ +class Ci::Step < Ci::RemoteBase + self.primary_key = 'step_id' + + belongs_to :stage, foreign_key: :step_stage_id + has_one :log, class_name: 'Ci::Log', foreign_key: :log_id +end diff --git a/app/models/ci/user.rb b/app/models/ci/user.rb new file mode 100644 index 00000000..cd624675 --- /dev/null +++ b/app/models/ci/user.rb @@ -0,0 +1,68 @@ +# == Schema Information +# +# Table name: users +# +# id :integer not null +# login :string(255) default(""), not null +# hashed_password :string(40) default(""), not null +# firstname :string(30) default(""), not null +# lastname :string(255) default(""), not null +# mail :string(60) +# admin :boolean default("0"), not null +# status :integer default("1"), not null +# last_login_on :datetime +# language :string(5) default("") +# auth_source_id :integer +# created_on :datetime +# updated_on :datetime +# type :string(255) +# identity_url :string(255) +# mail_notification :string(255) default(""), not null +# salt :string(64) +# gid :integer +# visits :integer default("0") +# excellent_teacher :integer default("0") +# excellent_student :integer default("0") +# phone :string(255) +# authentication :boolean default("0") +# grade :integer default("0") +# experience :integer default("0") +# nickname :string(255) +# show_realname :boolean default("1") +# professional_certification :boolean default("0") +# ID_number :string(255) +# certification :integer default("0") +# homepage_teacher :boolean default("0") +# homepage_engineer :boolean default("0") +# is_test :integer default("0") +# ecoder_user_id :integer default("0") +# business :boolean default("0") +# profile_completed :boolean default("0") +# laboratory_id :integer +# platform :string(255) default("0") +# gitea_token :string(255) +# gitea_uid :integer +# is_shixun_marker :boolean default("0") +# is_sync_pwd :boolean default("1") +# watchers_count :integer default("0") +# devops_step :integer default("0") +# +# Indexes +# +# index_users_on_ecoder_user_id (ecoder_user_id) +# index_users_on_homepage_engineer (homepage_engineer) +# index_users_on_homepage_teacher (homepage_teacher) +# index_users_on_laboratory_id (laboratory_id) +# index_users_on_login (login) +# index_users_on_mail (mail) +# index_users_on_type (type) +# + +class Ci::User < Ci::RemoteBase + self.primary_key = 'user_id' + + has_many :repos, foreign_key: :repo_user_id, dependent: :destroy + has_many :perms, foreign_key: :perm_user_id, dependent: :delete_all + has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', foreign_key: :ci_user_id + +end diff --git a/app/models/compose.rb b/app/models/compose.rb index 0b373394..8d9467dd 100644 --- a/app/models/compose.rb +++ b/app/models/compose.rb @@ -1,3 +1,23 @@ +# == Schema Information +# +# Table name: composes +# +# id :integer not null, primary key +# user_id :integer +# title :string(255) +# description :text(65535) +# show_mode :integer default("0") +# compose_mode :boolean default("0") +# compose_users_count :integer default("0") +# compose_projects_count :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_composes_on_user_id_and_show_mode_and_compose_mode (user_id,show_mode,compose_mode) +# + class Compose < ApplicationRecord #组织 belongs_to :user diff --git a/app/models/compose_project.rb b/app/models/compose_project.rb index 3c2d099e..1468fb05 100644 --- a/app/models/compose_project.rb +++ b/app/models/compose_project.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: compose_projects +# +# id :integer not null, primary key +# user_id :integer +# project_id :integer +# compose_id :integer +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_compose_projects_on_user_id_and_project_id_and_compose_id (user_id,project_id,compose_id) +# + class ComposeProject < ApplicationRecord #组织的项目记录表 belongs_to :compose diff --git a/app/models/compose_user.rb b/app/models/compose_user.rb index e3b514b3..a4d33440 100644 --- a/app/models/compose_user.rb +++ b/app/models/compose_user.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: compose_users +# +# id :integer not null, primary key +# user_id :integer +# compose_id :integer +# is_manager :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_compose_users_on_user_id_and_compose_id (user_id,compose_id) +# + class ComposeUser < ApplicationRecord belongs_to :compose belongs_to :user diff --git a/app/models/concerns/droneable.rb b/app/models/concerns/droneable.rb new file mode 100644 index 00000000..f91b9f98 --- /dev/null +++ b/app/models/concerns/droneable.rb @@ -0,0 +1,46 @@ +module Droneable + extend ActiveSupport::Concern + + included do + end + + def devops_uninit? + self.devops_step === User::DEVOPS_UNINIT + end + + def devops_unverified? + self.devops_step === User::DEVOPS_UNVERIFIED + end + + def devops_certification? + self.devops_step === User::DEVOPS_CERTIFICATION + end + + def set_drone_step!(step) + self.update_column(:devops_step, step) + end + + def ci_certification? + return false if self.is_a?(AnonymousUser) + devops_certification? && Ci::User.exists?(user_login: self.login) + end + + def unbind_account! + user_projects = self.projects + + user_projects.update_all(open_devops: false, open_devops_count: 0) + set_drone_step!(User::DEVOPS_UNINIT) + + # TODO + # 删除用户项目下的与ci相关的所有webhook + user_projects.select(:id, :identifier, :gitea_webhook_id).each do |project| + if project.gitea_webhook_id + result = Gitea::Hooks::DestroyService.call(self.gitea_token, self.login, project.identifier, project.gitea_webhook_id) + project.update_column(:gitea_webhook_id, nil) if result.status == 204 + end + end + end + + module ClassMethods + end +end diff --git a/app/models/concerns/matchable.rb b/app/models/concerns/matchable.rb index 943fb5ec..aa9fbe81 100644 --- a/app/models/concerns/matchable.rb +++ b/app/models/concerns/matchable.rb @@ -5,6 +5,7 @@ module Matchable scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? } scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? } scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) } + scope :by_name_or_identifier, ->(search) { where("name like :search or identifier LIKE :search", :search => "#{search.split(" ").join('|')}%") unless search.blank? } end end diff --git a/app/models/concerns/project_operable.rb b/app/models/concerns/project_operable.rb index bba65e74..f05ed164 100644 --- a/app/models/concerns/project_operable.rb +++ b/app/models/concerns/project_operable.rb @@ -7,6 +7,7 @@ module ProjectOperable 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 :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 def add_member!(user_id, role_name='Developer') diff --git a/app/models/coo_img.rb b/app/models/coo_img.rb index 0766c072..db96ecbd 100644 --- a/app/models/coo_img.rb +++ b/app/models/coo_img.rb @@ -1,5 +1,18 @@ +# == Schema Information +# +# Table name: coo_imgs +# +# id :integer not null, primary key +# src_states :string(255) +# url_states :string(255) +# img_type :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# position :integer +# + class CooImg < ApplicationRecord extend Enumerize enumerize :img_type, in: %i[com_coop edu_coop alliance_coop] -end \ No newline at end of file +end diff --git a/app/models/diff_record.rb b/app/models/diff_record.rb index afbb9dd9..4b40372a 100644 --- a/app/models/diff_record.rb +++ b/app/models/diff_record.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: diff_records +# +# id :integer not null, primary key +# user_id :integer +# container_type :string(255) +# container_id :integer +# column_name :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_diff_records_on_container_type_and_container_id (container_type,container_id) +# index_diff_records_on_user_id (user_id) +# + class DiffRecord < ApplicationRecord belongs_to :user belongs_to :container, polymorphic: true @@ -5,4 +23,4 @@ class DiffRecord < ApplicationRecord has_one :diff_record_content, dependent: :destroy delegate :content, to: :diff_record_content -end \ No newline at end of file +end diff --git a/app/models/diff_record_content.rb b/app/models/diff_record_content.rb index ce5e1d35..c479469e 100644 --- a/app/models/diff_record_content.rb +++ b/app/models/diff_record_content.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: diff_record_contents +# +# id :integer not null, primary key +# diff_record_id :integer +# content :text(65535) +# +# Indexes +# +# index_diff_record_contents_on_diff_record_id (diff_record_id) +# + class DiffRecordContent < ApplicationRecord belongs_to :diff_record -end \ No newline at end of file +end diff --git a/app/models/edu_setting.rb b/app/models/edu_setting.rb index 835aaec7..6968b008 100644 --- a/app/models/edu_setting.rb +++ b/app/models/edu_setting.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: edu_settings +# +# id :integer not null, primary key +# name :string(255) +# value :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# description :string(255) +# +# Indexes +# +# index_edu_settings_on_name (name) UNIQUE +# + class EduSetting < ApplicationRecord after_commit :expire_value_cache diff --git a/app/models/fork_user.rb b/app/models/fork_user.rb index 10ae3232..d0915f15 100644 --- a/app/models/fork_user.rb +++ b/app/models/fork_user.rb @@ -1,4 +1,23 @@ +# == Schema Information +# +# Table name: fork_users +# +# id :integer not null, primary key +# project_id :integer +# fork_project_id :integer +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_fork_users_on_project_id (project_id) +# index_fork_users_on_user_id (user_id) +# + class ForkUser < ApplicationRecord - belongs_to :project + belongs_to :project belongs_to :user + belongs_to :fork_project, class_name: 'Project', foreign_key: :fork_project_id + end diff --git a/app/models/gitea/base.rb b/app/models/gitea/base.rb new file mode 100644 index 00000000..d14249bf --- /dev/null +++ b/app/models/gitea/base.rb @@ -0,0 +1,4 @@ +class Gitea::Base < Gitea::Database + self.abstract_class = true + +end diff --git a/app/models/ignore.rb b/app/models/ignore.rb index bd75ed08..a6dc9a5a 100644 --- a/app/models/ignore.rb +++ b/app/models/ignore.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: ignores +# +# id :integer not null, primary key +# name :string(255) +# content :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# + class Ignore < ApplicationRecord include Projectable end diff --git a/app/models/issue.rb b/app/models/issue.rb index 7e122827..3595c754 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1,3 +1,53 @@ +# == Schema Information +# +# Table name: issues +# +# id :integer not null, primary key +# tracker_id :integer not null +# project_id :integer not null +# subject :string(255) default(""), not null +# description :text(4294967295) +# due_date :date +# category_id :integer +# status_id :integer not null +# assigned_to_id :integer +# priority_id :integer not null +# fixed_version_id :integer +# author_id :integer not null +# created_on :datetime +# updated_on :datetime +# start_date :date +# done_ratio :integer default("0"), not null +# estimated_hours :float(24) +# parent_id :integer +# root_id :integer +# lft :integer +# rgt :integer +# is_private :boolean default("0"), not null +# closed_on :datetime +# project_issues_index :integer +# issue_type :string(255) +# token :integer default("0") +# issue_tags_value :string(255) +# is_lock :boolean default("0") +# issue_classify :string(255) +# ref_name :string(255) +# branch_name :string(255) +# +# Indexes +# +# index_issues_on_assigned_to_id (assigned_to_id) +# index_issues_on_author_id (author_id) +# index_issues_on_category_id (category_id) +# index_issues_on_created_on (created_on) +# index_issues_on_fixed_version_id (fixed_version_id) +# index_issues_on_priority_id (priority_id) +# index_issues_on_root_id_and_lft_and_rgt (root_id,lft,rgt) +# index_issues_on_status_id (status_id) +# index_issues_on_tracker_id (tracker_id) +# issues_project_id (project_id) +# + class Issue < ApplicationRecord #issue_type 1为普通,2为悬赏 include DunCheckAble diff --git a/app/models/issue_depend.rb b/app/models/issue_depend.rb index 14686e86..8b64dc1f 100644 --- a/app/models/issue_depend.rb +++ b/app/models/issue_depend.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: issue_depends +# +# id :integer not null, primary key +# user_id :integer +# issue_id :integer +# depend_issue_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_issue_depends_on_user_id_and_issue_id_and_depend_issue_id (user_id,issue_id,depend_issue_id) +# + class IssueDepend < ApplicationRecord belongs_to :issue end diff --git a/app/models/issue_priority.rb b/app/models/issue_priority.rb index 6b815f42..27865a70 100644 --- a/app/models/issue_priority.rb +++ b/app/models/issue_priority.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: issue_priorities +# +# id :integer not null, primary key +# name :string(255) +# position :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_issue_priorities_on_name (name) +# + class IssuePriority < ApplicationRecord has_many :issues -end \ No newline at end of file +end diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb index 82bc62ab..a7ec34f8 100644 --- a/app/models/issue_status.rb +++ b/app/models/issue_status.rb @@ -1,4 +1,22 @@ +# == Schema Information +# +# Table name: issue_statuses +# +# id :integer not null, primary key +# name :string(30) default(""), not null +# is_closed :boolean default("0"), not null +# is_default :boolean default("0"), not null +# position :integer default("1") +# default_done_ratio :integer +# +# Indexes +# +# index_issue_statuses_on_is_closed (is_closed) +# index_issue_statuses_on_is_default (is_default) +# index_issue_statuses_on_position (position) +# + class IssueStatus < ApplicationRecord has_many :issues belongs_to :project, optional: true -end \ No newline at end of file +end diff --git a/app/models/issue_tag.rb b/app/models/issue_tag.rb index 7b61f401..bf236865 100644 --- a/app/models/issue_tag.rb +++ b/app/models/issue_tag.rb @@ -1,3 +1,24 @@ +# == Schema Information +# +# Table name: issue_tags +# +# id :integer not null, primary key +# name :string(255) +# description :string(255) +# color :string(255) +# user_id :integer +# project_id :integer +# issues_count :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# gid :integer +# gitea_url :string(255) +# +# Indexes +# +# index_issue_tags_on_user_id_and_name_and_project_id (user_id,name,project_id) +# + class IssueTag < ApplicationRecord has_many :issue_tags_relates, dependent: :destroy diff --git a/app/models/issue_tags_relate.rb b/app/models/issue_tags_relate.rb index bab48d40..df9fd81a 100644 --- a/app/models/issue_tags_relate.rb +++ b/app/models/issue_tags_relate.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: issue_tags_relates +# +# id :integer not null, primary key +# issue_id :integer +# issue_tag_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_issue_tags_relates_on_issue_id_and_issue_tag_id (issue_id,issue_tag_id) +# + class IssueTagsRelate < ApplicationRecord belongs_to :issue belongs_to :issue_tag, counter_cache: :issues_count diff --git a/app/models/issue_time.rb b/app/models/issue_time.rb index 10d7af7b..24425d1e 100644 --- a/app/models/issue_time.rb +++ b/app/models/issue_time.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: issue_times +# +# id :integer not null, primary key +# issue_id :integer +# user_id :integer +# start_time :datetime +# end_time :datetime +# cost_time :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_issue_times_on_issue_id_and_user_id (issue_id,user_id) +# + class IssueTime < ApplicationRecord belongs_to :issue belongs_to :user diff --git a/app/models/journal.rb b/app/models/journal.rb index d7c4f2a4..b833ea13 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -1,3 +1,26 @@ +# == Schema Information +# +# Table name: journals +# +# id :integer not null, primary key +# journalized_id :integer default("0"), not null +# journalized_type :string(30) default(""), not null +# user_id :integer default("0"), not null +# notes :text(65535) +# created_on :datetime not null +# private_notes :boolean default("0"), not null +# parent_id :integer +# comments_count :integer default("0") +# reply_id :integer +# +# Indexes +# +# index_journals_on_created_on (created_on) +# index_journals_on_journalized_id (journalized_id) +# index_journals_on_user_id (user_id) +# journals_journalized_id (journalized_id,journalized_type) +# + class Journal < ApplicationRecord include DunCheckAble belongs_to :user @@ -151,4 +174,4 @@ class Journal < ApplicationRecord end -end \ No newline at end of file +end diff --git a/app/models/journal_detail.rb b/app/models/journal_detail.rb index c97bdf37..f5f21260 100644 --- a/app/models/journal_detail.rb +++ b/app/models/journal_detail.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: journal_details +# +# id :integer not null, primary key +# journal_id :integer default("0"), not null +# property :string(30) default(""), not null +# prop_key :string(30) default(""), not null +# old_value :text(65535) +# value :text(65535) +# +# Indexes +# +# journal_details_journal_id (journal_id) +# + class JournalDetail < ApplicationRecord belongs_to :journal -end \ No newline at end of file +end diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb index 3d0189c9..090edcb8 100644 --- a/app/models/journals_for_message.rb +++ b/app/models/journals_for_message.rb @@ -1,3 +1,32 @@ +# == Schema Information +# +# Table name: journals_for_messages +# +# id :integer not null, primary key +# jour_id :integer +# jour_type :string(255) +# user_id :integer +# notes :text(65535) +# status :integer +# reply_id :integer +# created_on :datetime not null +# updated_on :datetime not null +# m_parent_id :string(255) +# is_readed :boolean +# m_reply_count :integer +# m_reply_id :integer +# is_comprehensive_evaluation :integer +# private :integer default("0") +# root_id :integer +# hidden :boolean default("0") +# praises_count :integer default("0") +# +# Indexes +# +# index_journals_for_messages_on_jour_id (jour_id) +# index_journals_for_messages_on_root_id (root_id) +# + class JournalsForMessage < ApplicationRecord belongs_to :jour, :polymorphic => true belongs_to :user diff --git a/app/models/laboratory.rb b/app/models/laboratory.rb index 7aea4254..1cf5c4ad 100644 --- a/app/models/laboratory.rb +++ b/app/models/laboratory.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: laboratories +# +# id :integer not null, primary key +# school_id :integer +# identifier :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# sync_course :boolean default("0") +# sync_subject :boolean default("0") +# sync_shixun :boolean default("0") +# + class Laboratory < ApplicationRecord belongs_to :school, optional: true diff --git a/app/models/laboratory_setting.rb b/app/models/laboratory_setting.rb index 60356e34..5013dd54 100644 --- a/app/models/laboratory_setting.rb +++ b/app/models/laboratory_setting.rb @@ -1,3 +1,12 @@ +# == Schema Information +# +# Table name: laboratory_settings +# +# id :integer not null, primary key +# laboratory_id :integer +# config :text(65535) +# + class LaboratorySetting < ApplicationRecord belongs_to :laboratory diff --git a/app/models/laboratory_user.rb b/app/models/laboratory_user.rb index be6c0c4d..8658e410 100644 --- a/app/models/laboratory_user.rb +++ b/app/models/laboratory_user.rb @@ -1,4 +1,18 @@ +# == Schema Information +# +# Table name: laboratory_users +# +# id :integer not null, primary key +# laboratory_id :integer +# user_id :integer +# +# Indexes +# +# index_laboratory_users_on_laboratory_id (laboratory_id) +# index_laboratory_users_on_user_id (user_id) +# + class LaboratoryUser < ApplicationRecord belongs_to :laboratory belongs_to :user -end \ No newline at end of file +end diff --git a/app/models/license.rb b/app/models/license.rb index 952c4a13..0a14fb85 100644 --- a/app/models/license.rb +++ b/app/models/license.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: licenses +# +# id :integer not null, primary key +# name :string(255) +# content :text(65535) +# created_at :datetime not null +# updated_at :datetime not null +# + class License < ApplicationRecord include Projectable end diff --git a/app/models/member.rb b/app/models/member.rb index 054a072b..e72ae7c6 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,3 +1,25 @@ +# == Schema Information +# +# Table name: members +# +# id :integer not null, primary key +# user_id :integer default("0"), not null +# project_id :integer default("0") +# created_on :datetime +# mail_notification :boolean default("0"), not null +# course_id :integer default("-1") +# course_group_id :integer default("0") +# is_collect :integer default("1") +# graduation_group_id :integer default("0") +# +# Indexes +# +# index_members_on_course_id (course_id) +# index_members_on_project_id (project_id) +# index_members_on_user_id (user_id) +# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE +# + class Member < ApplicationRecord belongs_to :user # belongs_to :course, optional: true diff --git a/app/models/member_role.rb b/app/models/member_role.rb index 6e51e701..a2011067 100644 --- a/app/models/member_role.rb +++ b/app/models/member_role.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: member_roles +# +# id :integer not null, primary key +# member_id :integer not null +# role_id :integer not null +# inherited_from :integer +# is_current :integer default("1") +# +# Indexes +# +# index_member_roles_on_member_id (member_id) +# index_member_roles_on_role_id (role_id) +# + class MemberRole < ApplicationRecord belongs_to :role belongs_to :member diff --git a/app/models/mirror.rb b/app/models/mirror.rb index a534adf9..67ef7377 100644 --- a/app/models/mirror.rb +++ b/app/models/mirror.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: mirrors +# +# id :integer not null, primary key +# repo_id :integer +# status :integer default("0"), not null +# interval :integer +# next_update_time :datetime +# created_at :datetime not null +# updated_at :datetime not null +# sync_num :integer default("1") +# + class Mirror < ApplicationRecord # 0 - succeeded, 1 - waiting, 2 - failed diff --git a/app/models/oauth.rb b/app/models/oauth.rb new file mode 100644 index 00000000..90d8b61b --- /dev/null +++ b/app/models/oauth.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: oauths +# +# id :integer not null, primary key +# client_id :string(255) +# client_secret :string(255) +# code :string(255) +# redirect_uri :string(255) +# scope :string(255) +# access_token :string(255) +# refresh_token :string(255) +# token_created_at :integer +# token_expires_in :integer +# created_at :datetime not null +# updated_at :datetime not null +# user_id :integer default("0") +# gitea_oauth_id :integer +# project_id :integer +# +# Indexes +# +# index_oauths_on_user_id (user_id) +# + +# for oauth2 application +class Oauth < ApplicationRecord + belongs_to :user +end diff --git a/app/models/onclick_time.rb b/app/models/onclick_time.rb index 588da23f..ac064327 100644 --- a/app/models/onclick_time.rb +++ b/app/models/onclick_time.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: onclick_times +# +# id :integer not null, primary key +# user_id :integer +# onclick_time :datetime +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_onclick_times_on_user_id (user_id) +# + class OnclickTime < ApplicationRecord belongs_to :user diff --git a/app/models/open_user.rb b/app/models/open_user.rb index 45c4ee6b..b7d90e71 100644 --- a/app/models/open_user.rb +++ b/app/models/open_user.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: open_users +# +# id :integer not null, primary key +# user_id :integer +# type :string(255) +# uid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# extra :text(65535) +# +# Indexes +# +# index_open_users_on_type_and_uid (type,uid) UNIQUE +# index_open_users_on_user_id (user_id) +# + class OpenUser < ApplicationRecord belongs_to :user @@ -8,4 +26,4 @@ class OpenUser < ApplicationRecord def can_bind_cache_key "open_user:#{type}:#{uid}:can_bind" end -end \ No newline at end of file +end diff --git a/app/models/open_users/cas.rb b/app/models/open_users/cas.rb index 301a197a..df7fb515 100644 --- a/app/models/open_users/cas.rb +++ b/app/models/open_users/cas.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: open_users +# +# id :integer not null, primary key +# user_id :integer +# type :string(255) +# uid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# extra :text(65535) +# +# Indexes +# +# index_open_users_on_type_and_uid (type,uid) UNIQUE +# index_open_users_on_user_id (user_id) +# + class OpenUsers::Cas < OpenUser def nickname extra&.[]('nickname') @@ -6,4 +24,4 @@ class OpenUsers::Cas < OpenUser def en_type 'cas' end -end \ No newline at end of file +end diff --git a/app/models/open_users/educoder.rb b/app/models/open_users/educoder.rb index 9277b2a1..310cf951 100644 --- a/app/models/open_users/educoder.rb +++ b/app/models/open_users/educoder.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: open_users +# +# id :integer not null, primary key +# user_id :integer +# type :string(255) +# uid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# extra :text(65535) +# +# Indexes +# +# index_open_users_on_type_and_uid (type,uid) UNIQUE +# index_open_users_on_user_id (user_id) +# + class OpenUsers::Educoder < OpenUser def nickname extra&.[]('nickname') diff --git a/app/models/open_users/qq.rb b/app/models/open_users/qq.rb index 9e782712..ef1a4b47 100644 --- a/app/models/open_users/qq.rb +++ b/app/models/open_users/qq.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: open_users +# +# id :integer not null, primary key +# user_id :integer +# type :string(255) +# uid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# extra :text(65535) +# +# Indexes +# +# index_open_users_on_type_and_uid (type,uid) UNIQUE +# index_open_users_on_user_id (user_id) +# + class OpenUsers::QQ < OpenUser def nickname extra&.[]('nickname') @@ -6,4 +24,4 @@ class OpenUsers::QQ < OpenUser def en_type 'qq' end -end \ No newline at end of file +end diff --git a/app/models/open_users/wechat.rb b/app/models/open_users/wechat.rb index 9e7e032b..5cb22126 100644 --- a/app/models/open_users/wechat.rb +++ b/app/models/open_users/wechat.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: open_users +# +# id :integer not null, primary key +# user_id :integer +# type :string(255) +# uid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# extra :text(65535) +# +# Indexes +# +# index_open_users_on_type_and_uid (type,uid) UNIQUE +# index_open_users_on_user_id (user_id) +# + class OpenUsers::Wechat < OpenUser def nickname extra&.[]('nickname') @@ -6,4 +24,4 @@ class OpenUsers::Wechat < OpenUser def en_type 'wechat' end -end \ No newline at end of file +end diff --git a/app/models/praise_tread.rb b/app/models/praise_tread.rb index cdfdbea2..d13c17dd 100644 --- a/app/models/praise_tread.rb +++ b/app/models/praise_tread.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: praise_treads +# +# id :integer not null, primary key +# user_id :integer not null +# praise_tread_object_id :integer +# praise_tread_object_type :string(255) +# praise_or_tread :integer default("1") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# praise_tread (praise_tread_object_id,praise_tread_object_type) +# + class PraiseTread < ApplicationRecord belongs_to :user belongs_to :praise_tread_object, polymorphic: true, counter_cache: :praises_count diff --git a/app/models/praise_tread_cache.rb b/app/models/praise_tread_cache.rb index 5544d185..b6fe0887 100644 --- a/app/models/praise_tread_cache.rb +++ b/app/models/praise_tread_cache.rb @@ -1,2 +1,15 @@ +# == Schema Information +# +# Table name: praise_tread_caches +# +# id :integer not null, primary key +# object_id :integer not null +# object_type :string(255) +# praise_num :integer +# tread_num :integer +# created_at :datetime not null +# updated_at :datetime not null +# + class PraiseTreadCache < ApplicationRecord end diff --git a/app/models/private_message.rb b/app/models/private_message.rb index 640e48db..bb6d1679 100644 --- a/app/models/private_message.rb +++ b/app/models/private_message.rb @@ -1,3 +1,23 @@ +# == Schema Information +# +# Table name: private_messages +# +# id :integer not null, primary key +# user_id :integer +# target_id :integer +# sender_id :integer +# receiver_id :integer +# content :text(65535) +# send_time :datetime +# status :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_private_messages_on_user_id (user_id) +# + class PrivateMessage < ApplicationRecord belongs_to :user belongs_to :target, class_name: "User" diff --git a/app/models/project.rb b/app/models/project.rb index bd2008af..887a6952 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,3 +1,73 @@ +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) default(""), not null +# description :text(4294967295) +# homepage :string(255) default("") +# is_public :boolean default("1"), not null +# parent_id :integer +# created_on :datetime +# updated_on :datetime +# identifier :string(255) +# status :integer default("1"), not null +# lft :integer +# rgt :integer +# inherit_members :boolean default("0"), not null +# project_type :integer default("0") +# hidden_repo :boolean default("0"), not null +# attachmenttype :integer default("1") +# user_id :integer +# dts_test :integer default("0") +# enterprise_name :string(255) +# organization_id :integer +# project_new_type :integer +# gpid :integer +# forked_from_project_id :integer +# forked_count :integer default("0") +# publish_resource :integer default("0") +# visits :integer default("0") +# hot :integer default("0") +# invite_code :string(255) +# qrcode :string(255) +# qrcode_expiretime :integer default("0") +# script :text(65535) +# training_status :integer default("0") +# rep_identifier :string(255) +# project_category_id :integer +# project_language_id :integer +# license_id :integer +# ignore_id :integer +# praises_count :integer default("0") +# watchers_count :integer default("0") +# issues_count :integer default("0") +# pull_requests_count :integer default("0") +# language :string(255) +# versions_count :integer default("0") +# issue_tags_count :integer default("0") +# closed_issues_count :integer default("0") +# open_devops :boolean default("0") +# gitea_webhook_id :integer +# open_devops_count :integer default("0") +# recommend :boolean default("0") +# platform :integer default("0") +# +# Indexes +# +# index_projects_on_forked_from_project_id (forked_from_project_id) +# index_projects_on_identifier (identifier) +# index_projects_on_is_public (is_public) +# index_projects_on_lft (lft) +# index_projects_on_name (name) +# index_projects_on_platform (platform) +# index_projects_on_project_type (project_type) +# index_projects_on_recommend (recommend) +# index_projects_on_rgt (rgt) +# index_projects_on_status (status) +# index_projects_on_updated_on (updated_on) +# + class Project < ApplicationRecord include Matchable include Publicable @@ -10,15 +80,19 @@ class Project < ApplicationRecord # enum project_type: { sync_mirror: 2, mirror: 1, common: 0 } + # forge: trustie平台项目, educoder: educoder平台项目, 默认为forge平台 + enum platform: { forge: 0, educoder: 1 } + belongs_to :ignore, optional: true belongs_to :license, optional: true - belongs_to :owner, class_name: 'User', foreign_key: :user_id + belongs_to :owner, class_name: 'User', foreign_key: :user_id, optional: true belongs_to :project_category, optional: true , :counter_cache => true belongs_to :project_language, optional: true , :counter_cache => true has_many :project_trends, dependent: :destroy has_many :watchers, as: :watchable, dependent: :destroy has_many :fork_users, dependent: :destroy - # has_many :commits, dependent: :destroy + has_many :forked_users, class_name: 'ForkUser', foreign_key: :fork_project_id, dependent: :destroy + has_one :project_educoder, dependent: :destroy has_one :project_score, dependent: :destroy has_one :repository, dependent: :destroy @@ -31,10 +105,13 @@ class Project < ApplicationRecord has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy has_many :praise_treads, as: :praise_tread_object, dependent: :destroy has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" + has_one :project_detail, dependent: :destroy after_save :check_project_members scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)} scope :no_anomory_projects, -> {where("projects.user_id is not null and projects.user_id != ?", 2)} + scope :recommend, -> { visible.project_statics_select.where(recommend: true) } + def self.search_project(search) @@ -172,11 +249,34 @@ class Project < ApplicationRecord logger.info "########namespace_path: #{namespace_path} ########identifier: #{identifier} " user = User.find_by_login namespace_path - return nil if user.blank? - - project = user.projects.find_by(identifier: identifier) - + project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}") return nil if project.blank? - project + + [project, user] end + + def ci_reactivate? + open_devops_count > 0 + end + + def ci_reactivate!(ci_repo) + ci_repo.update_column(:repo_active, 1) + update_column(:open_devops, true) + increment!(:open_devops_count) + end + + def self.sync_educoder_shixun(url, private_token, page, per_page) + SyncEducoderShixunJob.perform_later(url, private_token, page, per_page) + end + + def self.update_common_projects_count! + ps = ProjectStatistic.first + ps.increment!(:common_projects_count) unless ps.blank? + end + + def self.update_mirror_projects_count! + ps = ProjectStatistic.first + ps.increment!(:mirror_projects_count) unless ps.blank? + end + end diff --git a/app/models/project_category.rb b/app/models/project_category.rb index e1c36a30..f58fe12f 100644 --- a/app/models/project_category.rb +++ b/app/models/project_category.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: project_categories +# +# id :integer not null, primary key +# name :string(255) +# position :integer +# projects_count :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# ancestry :string(255) +# +# Indexes +# +# index_project_categories_on_ancestry (ancestry) +# + class ProjectCategory < ApplicationRecord include Projectable has_ancestry diff --git a/app/models/project_detail.rb b/app/models/project_detail.rb new file mode 100644 index 00000000..b7ae215c --- /dev/null +++ b/app/models/project_detail.rb @@ -0,0 +1,19 @@ +# == Schema Information +# +# Table name: project_details +# +# id :integer not null, primary key +# project_id :integer +# content :text(4294967295) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_details_on_project_id (project_id) +# + +class ProjectDetail < ApplicationRecord + belongs_to :project, optional: true + has_many :attachments, as: :container, dependent: :destroy +end diff --git a/app/models/project_educoder.rb b/app/models/project_educoder.rb new file mode 100644 index 00000000..a8146af4 --- /dev/null +++ b/app/models/project_educoder.rb @@ -0,0 +1,23 @@ +# == Schema Information +# +# Table name: project_educoders +# +# id :integer not null, primary key +# owner :string(255) +# repo_name :string(255) +# image_url :string(255) +# project_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# commit_count :integer default("0") +# forked_count :integer default("0") +# +# Indexes +# +# index_project_educoders_on_project_id (project_id) +# index_project_educoders_on_repo_name (repo_name) +# + +class ProjectEducoder < ApplicationRecord + belongs_to :project, optional: true +end diff --git a/app/models/project_language.rb b/app/models/project_language.rb index 386c274e..ced6c5f9 100644 --- a/app/models/project_language.rb +++ b/app/models/project_language.rb @@ -1,3 +1,15 @@ +# == Schema Information +# +# Table name: project_languages +# +# id :integer not null, primary key +# name :string(255) +# position :integer +# projects_count :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# + class ProjectLanguage < ApplicationRecord include Projectable end diff --git a/app/models/project_package.rb b/app/models/project_package.rb index a8e13491..e6584264 100644 --- a/app/models/project_package.rb +++ b/app/models/project_package.rb @@ -1,3 +1,31 @@ +# == Schema Information +# +# Table name: project_packages +# +# id :integer not null, primary key +# creator_id :integer +# status :string(255) +# title :string(255) +# content :text(65535) +# contact_name :string(255) +# contact_phone :string(255) +# min_price :decimal(10, ) +# max_price :decimal(10, ) +# visit_count :integer default("0") +# bidding_users_count :integer default("0") +# deadline_at :datetime +# published_at :datetime +# bidding_finished_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# project_package_category_id :integer +# +# Indexes +# +# index_project_packages_on_creator_id (creator_id) +# index_project_packages_on_published_at (published_at) +# + class ProjectPackage < ApplicationRecord include AASM diff --git a/app/models/project_package_apply.rb b/app/models/project_package_apply.rb index 0dd69c0c..9f0c2b01 100644 --- a/app/models/project_package_apply.rb +++ b/app/models/project_package_apply.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: project_package_applies +# +# id :integer not null, primary key +# project_package_id :integer +# status :string(255) +# reason :string(255) +# refused_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_package_applies_on_project_package_id (project_package_id) +# + class ProjectPackageApply < ApplicationRecord include AASM @@ -16,4 +33,4 @@ class ProjectPackageApply < ApplicationRecord transitions from: :pending, to: :agreed end end -end \ No newline at end of file +end diff --git a/app/models/project_package_category.rb b/app/models/project_package_category.rb index 403fdf4c..9db319dd 100644 --- a/app/models/project_package_category.rb +++ b/app/models/project_package_category.rb @@ -1,3 +1,12 @@ +# == Schema Information +# +# Table name: project_package_categories +# +# id :integer not null, primary key +# name :string(255) +# position :integer +# + class ProjectPackageCategory < ApplicationRecord default_scope { order(position: :asc) } @@ -20,4 +29,4 @@ class ProjectPackageCategory < ApplicationRecord def reset_cache_data Rails.cache.delete(self.class.data_cache_key) end -end \ No newline at end of file +end diff --git a/app/models/project_score.rb b/app/models/project_score.rb index 51ed29a6..24124265 100644 --- a/app/models/project_score.rb +++ b/app/models/project_score.rb @@ -1,3 +1,24 @@ +# == Schema Information +# +# Table name: project_scores +# +# id :integer not null, primary key +# project_id :string(255) +# score :integer +# created_at :datetime not null +# updated_at :datetime not null +# issue_num :integer default("0") +# issue_journal_num :integer default("0") +# news_num :integer default("0") +# documents_num :integer default("0") +# changeset_num :integer default("0") +# board_message_num :integer default("0") +# board_num :integer default("0") +# attach_num :integer default("0") +# commit_time :datetime +# pull_request_num :integer default("0") +# + class ProjectScore < ApplicationRecord belongs_to :project diff --git a/app/models/project_statistic.rb b/app/models/project_statistic.rb new file mode 100644 index 00000000..10eb14a4 --- /dev/null +++ b/app/models/project_statistic.rb @@ -0,0 +1,15 @@ +# == Schema Information +# +# Table name: project_statistics +# +# id :integer not null, primary key +# common_projects_count :integer default("0") +# mirror_projects_count :integer default("0") +# sync_mirror_projects_count :integer default("0") +# commits_total_count :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# + +class ProjectStatistic < ApplicationRecord +end diff --git a/app/models/project_trend.rb b/app/models/project_trend.rb index 28fd0ffa..5858768b 100644 --- a/app/models/project_trend.rb +++ b/app/models/project_trend.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: project_trends +# +# id :integer not null, primary key +# user_id :integer +# project_id :integer +# trend_type :string(255) +# trend_id :integer +# action_type :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_project_trends_on_trend_type_and_trend_id (trend_type,trend_id) +# index_project_trends_on_user_id_and_project_id (user_id,project_id) +# + class ProjectTrend < ApplicationRecord belongs_to :project belongs_to :trend, polymorphic: true, optional: true diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb new file mode 100644 index 00000000..da35f6e7 --- /dev/null +++ b/app/models/protected_branch.rb @@ -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 diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index b2d4dadf..06f702f7 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -1,3 +1,28 @@ +# == Schema Information +# +# Table name: pull_requests +# +# id :integer not null, primary key +# pull_request_id :integer +# gpid :integer +# user_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# status :integer default("0") +# project_id :integer +# title :string(255) +# milestone :integer +# body :text(65535) +# head :string(255) +# base :string(255) +# issue_id :integer +# fork_project_id :integer +# is_original :boolean default("0") +# comments_count :integer default("0") +# commits_count :integer default("0") +# files_count :integer default("0") +# + class PullRequest < ApplicationRecord #status 0 默认未合并, 1表示合并, 2表示请求拒绝 include DunCheckAble @@ -13,4 +38,26 @@ class PullRequest < ApplicationRecord def fork_project Project.find_by(id: self.fork_project_id) end + + def bind_gitea_pull_request!(gitea_pull_number) + update_column(:gpid, gitea_pull_number) + end + + # TODO: sync educoder platform repo's for update some statistics count + def self.update_some_count + PullRequest.includes(:user, :project).select(:id, :user_id, :gpid, :project_id, :fork_project_id).each do |pr| + puts pr.id + next if pr.gpid.blank? + project = pr.project + + next if project.blank? + user = project.owner + next if pr.gpid === 6 || pr.gpid === 7 + files_result = Gitea::PullRequest::FilesService.call(user.login, project.identifier, pr.gpid) + pr.update_column(:files_count, files_result['NumFiles']) unless files_result.blank? + + commits_result = Gitea::PullRequest::CommitsService.call(user.login, project.identifier, pr.gpid) + pr.update_column(:commits_count, commits_result.size) unless commits_result.blank? + end + end end diff --git a/app/models/pull_request_assign.rb b/app/models/pull_request_assign.rb index 0c47cc88..c8e6489b 100644 --- a/app/models/pull_request_assign.rb +++ b/app/models/pull_request_assign.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: pull_request_assigns +# +# id :integer not null, primary key +# pull_request_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# user_login :string(255) +# +# Indexes +# +# index_pull_request_assigns_on_user_id_and_pull_request_id (pull_request_id) +# index_pull_request_assigns_on_user_login (user_login) +# + class PullRequestAssign < ApplicationRecord belongs_to :user belongs_to :pull_request diff --git a/app/models/pull_request_tag.rb b/app/models/pull_request_tag.rb index 58953062..7f2b6d1e 100644 --- a/app/models/pull_request_tag.rb +++ b/app/models/pull_request_tag.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: pull_request_tags +# +# id :integer not null, primary key +# issue_tag_id :integer +# pull_request_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_pull_request_tags_on_issue_tag_id_and_pull_request_id (issue_tag_id,pull_request_id) +# + class PullRequestTag < ApplicationRecord belongs_to :issue_tag belongs_to :pull_request diff --git a/app/models/repository.rb b/app/models/repository.rb index 6d20afce..be6afcb1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,9 +1,43 @@ +# == Schema Information +# +# Table name: repositories +# +# id :integer not null, primary key +# project_id :integer default("0"), not null +# url :string(255) default(""), not null +# login :string(60) default("") +# password :string(255) default("") +# root_url :string(255) default("") +# type :string(255) +# path_encoding :string(64) +# log_encoding :string(64) +# extra_info :text(65535) +# identifier :string(255) +# is_default :boolean default("0") +# hidden :boolean default("0") +# shixun_id :integer +# myshixun_id :integer +# user_id :integer +# mirror_url :string(255) +# version_releases_count :integer default("0") +# fork_url :string(255) +# is_mirror :boolean default("0") +# +# Indexes +# +# index_repositories_on_identifier (identifier) +# index_repositories_on_project_id (project_id) +# index_repositories_on_user_id (user_id) +# + class Repository < ApplicationRecord self.inheritance_column = nil # FIX The single-table inheritance mechanism failed belongs_to :project, :touch => true - belongs_to :user + belongs_to :user, optional: true has_one :mirror, 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 :protected_branches, class_name: 'ProtectedBranch', foreign_key: :repo_id, dependent: :destroy validates :identifier, presence: true @@ -33,4 +67,12 @@ class Repository < ApplicationRecord repo_mirror.set_status!(Mirror.statuses[:waiting]) repo_mirror.increment!(:sync_num) end + + def generate_hex(column) + loop do + hex = SecureRandom.hex + break hex unless self.class.where(column => hex).any? + end + end + end diff --git a/app/models/role.rb b/app/models/role.rb index e60606ff..0767adec 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: roles +# +# id :integer not null, primary key +# name :string(30) default(""), not null +# position :integer default("1") +# assignable :boolean default("1") +# builtin :integer default("0"), not null +# permissions :text(65535) +# issues_visibility :string(30) default("default"), not null +# + class Role < ApplicationRecord has_many :member_roles, dependent: :destroy -end \ No newline at end of file +end diff --git a/app/models/system_update_notice.rb b/app/models/system_update_notice.rb index 44589a40..de4bebfb 100644 --- a/app/models/system_update_notice.rb +++ b/app/models/system_update_notice.rb @@ -1,2 +1,16 @@ +# == Schema Information +# +# Table name: system_update_notices +# +# id :integer not null, primary key +# subject :string(255) +# notes :text(65535) +# start_time :datetime +# end_time :datetime +# created_at :datetime not null +# updated_at :datetime not null +# notice_type :integer +# + class SystemUpdateNotice < ApplicationRecord end diff --git a/app/models/tiding.rb b/app/models/tiding.rb index aa570f5c..01daeb96 100644 --- a/app/models/tiding.rb +++ b/app/models/tiding.rb @@ -1,3 +1,30 @@ +# == Schema Information +# +# Table name: tidings +# +# id :integer not null, primary key +# user_id :integer +# trigger_user_id :integer +# container_id :integer +# container_type :string(255) +# parent_container_id :integer +# parent_container_type :string(255) +# belong_container_id :integer +# belong_container_type :string(255) +# status :integer default("0") +# viewed :boolean +# created_at :datetime not null +# updated_at :datetime not null +# tiding_type :string(255) +# extra :string(255) +# is_delete :boolean default("0") +# +# Indexes +# +# index_tidings_on_container_id (container_id) +# index_tidings_on_user_id (user_id) +# + class Tiding < ApplicationRecord belongs_to :user belongs_to :trigger_user, class_name: 'User', optional: true @@ -29,4 +56,4 @@ class Tiding < ApplicationRecord (container_type == 'StudentWorksScore' && extra.to_i == 3) || (container_type == 'StudentWorksScoresAppeal' && parent_container_type == 'StudentWork' && tiding_type == 'System') end -end \ No newline at end of file +end diff --git a/app/models/token.rb b/app/models/token.rb index af42c57a..140b9fa5 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: tokens +# +# id :integer not null, primary key +# user_id :integer default("0"), not null +# action :string(30) default(""), not null +# value :string(40) default(""), not null +# created_on :datetime not null +# +# Indexes +# +# index_tokens_on_user_id (user_id) +# tokens_value (value) UNIQUE +# + # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License diff --git a/app/models/tracker.rb b/app/models/tracker.rb index a5202b26..c3ceca62 100644 --- a/app/models/tracker.rb +++ b/app/models/tracker.rb @@ -1,4 +1,16 @@ +# == Schema Information +# +# Table name: trackers +# +# id :integer not null, primary key +# name :string(30) default(""), not null +# is_in_chlog :boolean default("0"), not null +# position :integer default("1") +# is_in_roadmap :boolean default("1"), not null +# fields_bits :integer default("0") +# + class Tracker < ApplicationRecord has_many :issues has_and_belongs_to_many :projects -end \ No newline at end of file +end diff --git a/app/models/user.rb b/app/models/user.rb index 41be85f9..6aef70b5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,63 @@ +# == Schema Information +# +# Table name: users +# +# id :integer not null, primary key +# login :string(255) default(""), not null +# hashed_password :string(40) default(""), not null +# firstname :string(30) default(""), not null +# lastname :string(255) default(""), not null +# mail :string(60) +# admin :boolean default("0"), not null +# status :integer default("1"), not null +# last_login_on :datetime +# language :string(5) default("") +# auth_source_id :integer +# created_on :datetime +# updated_on :datetime +# type :string(255) +# identity_url :string(255) +# mail_notification :string(255) default(""), not null +# salt :string(64) +# gid :integer +# visits :integer default("0") +# excellent_teacher :integer default("0") +# excellent_student :integer default("0") +# phone :string(255) +# authentication :boolean default("0") +# grade :integer default("0") +# experience :integer default("0") +# nickname :string(255) +# show_realname :boolean default("1") +# professional_certification :boolean default("0") +# ID_number :string(255) +# certification :integer default("0") +# homepage_teacher :boolean default("0") +# homepage_engineer :boolean default("0") +# is_test :integer default("0") +# ecoder_user_id :integer default("0") +# business :boolean default("0") +# profile_completed :boolean default("0") +# laboratory_id :integer +# platform :string(255) default("0") +# gitea_token :string(255) +# gitea_uid :integer +# is_shixun_marker :boolean default("0") +# is_sync_pwd :boolean default("1") +# watchers_count :integer default("0") +# devops_step :integer default("0") +# +# Indexes +# +# index_users_on_ecoder_user_id (ecoder_user_id) +# index_users_on_homepage_engineer (homepage_engineer) +# index_users_on_homepage_teacher (homepage_teacher) +# index_users_on_laboratory_id (laboratory_id) +# index_users_on_login (login) +# index_users_on_mail (mail) +# index_users_on_type (type) +# + class User < ApplicationRecord extend Enumerize @@ -6,8 +66,15 @@ class User < ApplicationRecord include BaseModel include ProjectOperable include ProjectAbility + include Droneable # include Searchable::Dependents::User + # devops step + # devops_step column: 0: 未填写服务器信息;1: 已填写服务器信息(未认证);2: 已认证 + DEVOPS_UNINIT = 0 + DEVOPS_UNVERIFIED = 1 + DEVOPS_CERTIFICATION = 2 + # Account statuses STATUS_ANONYMOUS = 0 STATUS_ACTIVE = 1 @@ -71,9 +138,10 @@ class User < ApplicationRecord # 关注 has_many :be_watchers, foreign_key: :user_id, dependent: :destroy # 我的关注 has_many :be_watcher_users, through: :be_watchers, dependent: :destroy # 我关注的用户 - has_many :watchers, as: :watchable, dependent: :destroy + has_one :ci_cloud_account, class_name: 'Ci::CloudAccount', dependent: :destroy + # 认证 has_many :apply_user_authentication has_one :process_real_name_apply, -> { processing.real_name_auth.order(created_at: :desc) }, class_name: 'ApplyUserAuthentication' @@ -92,6 +160,7 @@ class User < ApplicationRecord # 教学案例 # has_many :libraries, dependent: :destroy has_many :project_trends, dependent: :destroy + has_many :oauths , dependent: :destroy # Groups and active users scope :active, lambda { where(status: STATUS_ACTIVE) } @@ -503,7 +572,7 @@ class User < ApplicationRecord def self.anonymous anonymous_user = AnonymousUser.unscoped.take if anonymous_user.nil? - anonymous_user = AnonymousUser.unscoped.create(lastname: 'Anonymous', firstname: '', login: '', mail: '358551897@qq.com', phone: '13333333333', status: 0, platform: User.platform[:forge]) + anonymous_user = AnonymousUser.unscoped.create(lastname: 'Anonymous', firstname: '', login: '', mail: '358551897@qq.com', phone: '13333333333', status: 0, platform: User.platform.forge) raise "Unable to create the anonymous user: error_info:#{anonymous_user.errors.messages}" if anonymous_user.new_record? end anonymous_user diff --git a/app/models/user_action.rb b/app/models/user_action.rb index d3d70a66..3ad8010e 100644 --- a/app/models/user_action.rb +++ b/app/models/user_action.rb @@ -1,2 +1,19 @@ +# == Schema Information +# +# Table name: user_actions +# +# id :integer not null, primary key +# user_id :integer +# action_type :string(255) +# action_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# ip :string(255) +# +# Indexes +# +# index_user_actions_on_ip (ip) +# + class UserAction < ApplicationRecord end diff --git a/app/models/user_agent.rb b/app/models/user_agent.rb index ebe7ed03..49d7b35a 100644 --- a/app/models/user_agent.rb +++ b/app/models/user_agent.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: user_agents +# +# id :integer not null, primary key +# agent_type :string(255) +# key :string(255) +# ip :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# register_status :integer default("0") +# action_status :integer default("0") +# +# Indexes +# +# index_user_agents_on_ip (ip) UNIQUE +# + class UserAgent < ApplicationRecord has_many :user_actions, :foreign_key => "ip", :primary_key => "ip" USER_AD = 1 # 广告宣传的引流 diff --git a/app/models/user_day_certification.rb b/app/models/user_day_certification.rb index 18da0fd1..ccf26a2f 100644 --- a/app/models/user_day_certification.rb +++ b/app/models/user_day_certification.rb @@ -1,2 +1,17 @@ +# == Schema Information +# +# Table name: user_day_certifications +# +# id :integer not null, primary key +# user_id :integer +# status :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_user_day_certifications_on_user_id (user_id) +# + class UserDayCertification < ApplicationRecord end diff --git a/app/models/user_extension.rb b/app/models/user_extension.rb index 0a3c7368..20e2b5c4 100644 --- a/app/models/user_extension.rb +++ b/app/models/user_extension.rb @@ -1,3 +1,35 @@ +# == Schema Information +# +# Table name: user_extensions +# +# id :integer not null, primary key +# user_id :integer not null +# birthday :date +# brief_introduction :string(255) +# gender :integer +# location :string(255) +# occupation :string(255) +# work_experience :integer +# zip_code :integer +# created_at :datetime not null +# updated_at :datetime not null +# technical_title :string(255) +# identity :integer +# student_id :string(255) +# teacher_realname :string(255) +# student_realname :string(255) +# location_city :string(255) +# school_id :integer +# description :string(255) default("") +# department_id :integer +# +# Indexes +# +# index_user_extensions_on_department_id (department_id) +# index_user_extensions_on_school_id_and_user_id (school_id,user_id) +# index_user_extensions_on_user_id (user_id) +# + class UserExtension < ApplicationRecord # identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者 enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, enterprise: 4, unselect: -1 } diff --git a/app/models/user_grade.rb b/app/models/user_grade.rb index af7490ed..970392b1 100644 --- a/app/models/user_grade.rb +++ b/app/models/user_grade.rb @@ -1,3 +1,21 @@ +# == Schema Information +# +# Table name: user_grades +# +# id :integer not null, primary key +# user_id :integer not null +# project_id :integer not null +# grade :float(24) default("0") +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_user_grades_on_grade (grade) +# index_user_grades_on_project_id (project_id) +# index_user_grades_on_user_id (user_id) +# + class UserGrade < ApplicationRecord # belongs_to :project # belongs_to :user diff --git a/app/models/user_interest.rb b/app/models/user_interest.rb index 1c2d8bc8..ae553812 100644 --- a/app/models/user_interest.rb +++ b/app/models/user_interest.rb @@ -1,4 +1,18 @@ +# == Schema Information +# +# Table name: user_interests +# +# id :integer not null, primary key +# user_id :integer +# repertoire_id :integer +# +# Indexes +# +# index_user_interests_on_repertoire_id (repertoire_id) +# index_user_interests_on_user_id (user_id) +# + class UserInterest < ApplicationRecord belongs_to :user # belongs_to :repertoire -end \ No newline at end of file +end diff --git a/app/models/verification_code.rb b/app/models/verification_code.rb index 452e637a..a71d9018 100644 --- a/app/models/verification_code.rb +++ b/app/models/verification_code.rb @@ -1,3 +1,22 @@ +# == Schema Information +# +# Table name: verification_codes +# +# id :integer not null, primary key +# code :string(255) +# code_type :integer +# status :integer +# phone :string(255) +# email :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# by_email (email) +# by_phone (phone) +# + class VerificationCode < ApplicationRecord def effective? created_at + 10.minute > Time.current diff --git a/app/models/version.rb b/app/models/version.rb index cff4989c..1bafa2fb 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -1,3 +1,28 @@ +# == Schema Information +# +# Table name: versions +# +# id :integer not null, primary key +# project_id :integer default("0"), not null +# name :string(255) default(""), not null +# description :text(65535) +# effective_date :date +# created_on :datetime +# updated_on :datetime +# wiki_page_title :string(255) +# status :string(255) default("open") +# sharing :string(255) default("none"), not null +# user_id :integer +# issues_count :integer default("0") +# closed_issues_count :integer default("0") +# percent :float(24) default("0") +# +# Indexes +# +# index_versions_on_sharing (sharing) +# versions_project_id (project_id) +# + class Version < ApplicationRecord include DunCheckAble belongs_to :project, counter_cache: true diff --git a/app/models/version_release.rb b/app/models/version_release.rb index 7d733fb1..16b823a7 100644 --- a/app/models/version_release.rb +++ b/app/models/version_release.rb @@ -1,3 +1,28 @@ +# == Schema Information +# +# Table name: version_releases +# +# id :integer not null, primary key +# user_id :integer +# name :string(255) +# body :text(65535) +# tag_name :string(255) +# target_commitish :string(255) +# draft :boolean default("0") +# prerelease :boolean default("0") +# tarball_url :string(255) +# zipball_url :string(255) +# url :string(255) +# version_gid :string(255) +# created_at :datetime not null +# updated_at :datetime not null +# repository_id :integer +# +# Indexes +# +# index_version_releases_on_repository_id (repository_id) +# + class VersionRelease < ApplicationRecord belongs_to :repository, counter_cache: true belongs_to :user diff --git a/app/models/watcher.rb b/app/models/watcher.rb index 50bd7580..76a82702 100644 --- a/app/models/watcher.rb +++ b/app/models/watcher.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: watchers +# +# id :integer not null, primary key +# watchable_type :string(255) default(""), not null +# watchable_id :integer default("0"), not null +# user_id :integer +# created_at :datetime +# +# Indexes +# +# index_watchers_on_user_id (user_id) +# index_watchers_on_watchable_id_and_watchable_type (watchable_id,watchable_type) +# watchers_user_id_type (user_id,watchable_type) +# + class Watcher < ApplicationRecord belongs_to :user diff --git a/app/models/weapp_setting.rb b/app/models/weapp_setting.rb index a4ef86eb..ed80acd0 100644 --- a/app/models/weapp_setting.rb +++ b/app/models/weapp_setting.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: weapp_settings +# +# id :integer not null, primary key +# type :string(255) +# link :string(255) +# online :boolean default("0") +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# + class WeappSetting < ApplicationRecord scope :only_online, -> { where(online: true) } -end \ No newline at end of file +end diff --git a/app/models/weapp_settings/advert.rb b/app/models/weapp_settings/advert.rb index 993b1fd8..209b144e 100644 --- a/app/models/weapp_settings/advert.rb +++ b/app/models/weapp_settings/advert.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: weapp_settings +# +# id :integer not null, primary key +# type :string(255) +# link :string(255) +# online :boolean default("0") +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# + class WeappSettings::Advert < WeappSetting default_scope { order(position: :asc) } -end \ No newline at end of file +end diff --git a/app/models/weapp_settings/carousel.rb b/app/models/weapp_settings/carousel.rb index 71445fd3..4f914882 100644 --- a/app/models/weapp_settings/carousel.rb +++ b/app/models/weapp_settings/carousel.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: weapp_settings +# +# id :integer not null, primary key +# type :string(255) +# link :string(255) +# online :boolean default("0") +# position :integer default("0") +# created_at :datetime not null +# updated_at :datetime not null +# + class WeappSettings::Carousel < WeappSetting default_scope { order(position: :asc) } -end \ No newline at end of file +end diff --git a/app/queries/ci/builds/list_query.rb b/app/queries/ci/builds/list_query.rb new file mode 100644 index 00000000..bfb0b0a5 --- /dev/null +++ b/app/queries/ci/builds/list_query.rb @@ -0,0 +1,29 @@ +class Ci::Builds::ListQuery < ApplicationQuery + include CustomSortable + + attr_reader :params + + sort_columns :build_created, default_by: :build_created, default_direction: :desc + + def initialize(repo, params) + @repo = repo + @params = params + end + + def call + scope = @repo.builds + + builds = + case params[:search] + when 'success' then scope.successed + when 'pending' then scope.pending + when 'error' then scope.errored + when 'running' then scope.running + when 'failure' then scope.failed + when 'killed' then scope.killed + else + scope + end + custom_sort(builds, params[:sort_by], params[:sort_direction]) + end +end diff --git a/app/queries/projects/list_query.rb b/app/queries/projects/list_query.rb index 91a2a762..04f1d168 100644 --- a/app/queries/projects/list_query.rb +++ b/app/queries/projects/list_query.rb @@ -10,10 +10,9 @@ class Projects::ListQuery < ApplicationQuery end def call - q = Project.visible.search_project(params[:search]) + q = Project.visible.by_name_or_identifier(params[:search]) - scope = q.result(distinct: true) - .includes(:project_category, :project_language, :repository, owner: :user_extension) + scope = q .with_project_type(params[:project_type]) .with_project_category(params[:category_id]) .with_project_language(params[:language_id]) @@ -21,7 +20,9 @@ class Projects::ListQuery < ApplicationQuery sort = params[:sort_by] || "updated_on" sort_direction = params[:sort_direction] || "desc" - scope = scope.no_anomory_projects.reorder("projects.#{sort} #{sort_direction}") - scope + custom_sort(scope, sort, sort_direction) + + # scope = scope.reorder("projects.#{sort} #{sort_direction}") + # scope end end diff --git a/app/services/application_service.rb b/app/services/application_service.rb index 81c48de9..2fa59ed2 100644 --- a/app/services/application_service.rb +++ b/app/services/application_service.rb @@ -14,4 +14,8 @@ class ApplicationService def strip(str) str.to_s.strip.presence end -end \ No newline at end of file + + def str_to_boolean str + ActiveModel::Type::Boolean.new.cast str + end +end diff --git a/app/services/pull_requests/branches_service.rb b/app/services/branches/list_service.rb similarity index 93% rename from app/services/pull_requests/branches_service.rb rename to app/services/branches/list_service.rb index 117f1772..a3b77a7b 100644 --- a/app/services/pull_requests/branches_service.rb +++ b/app/services/branches/list_service.rb @@ -1,4 +1,4 @@ -class PullRequests::BranchesService < ApplicationService +class Branches::ListService < ApplicationService attr_reader :user, :project @@ -31,4 +31,4 @@ class PullRequests::BranchesService < ApplicationService return branches_array end -end \ No newline at end of file +end diff --git a/app/services/concerns/protected_branch_params_able.rb b/app/services/concerns/protected_branch_params_able.rb new file mode 100644 index 00000000..3ab0de0b --- /dev/null +++ b/app/services/concerns/protected_branch_params_able.rb @@ -0,0 +1,248 @@ +module ProtectedBranchParamsAble + extend ActiveSupport::Concern + + private + + # { + # "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 + def protected_branch_params + { + 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 + str_to_boolean(params[:enable_status_check] || false) + end + + def enable_approvals_whitelist_params + str_to_boolean(params[:enable_approvals_whitelist] || false) + end + def block_on_rejected_reviews_params + str_to_boolean(params[:block_on_rejected_reviews] || false) + end + + def dismiss_stale_approvals_params + str_to_boolean(params[:dismiss_stale_approvals] || false) + end + + def require_signed_commits_params + str_to_boolean(params[:require_signed_commits] || false) + end + + def block_on_outdated_branch_params + str_to_boolean(params[:block_on_outdated_branch] || false) + end + + def can_push_params + return false if !can_push? + return true if enable_whitelist? + str_to_boolean(params[:enable_push]) + end + + def enable_whitelist_params + return false if !can_push? + str_to_boolean(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 + str_to_boolean(params[:enable_merge_whitelist] || false) + end + + def merge_whitelist_user_i_ds_params + return [] 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_usernames) + 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_usernames + return [] if !enable_approvals_whitelist? + filter_empty_element Array(params[:approvals_whitelist_usernames]) + 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? + str_to_boolean(params[:enable_push]) === true + end + + def enable_whitelist? + str_to_boolean(params[:enable_push_whitelist]) === true + end + + def enable_merge_whitelist? + str_to_boolean(params[:enable_merge_whitelist]) === true + end + + def enable_approvals_whitelist? + str_to_boolean(params[:enable_approvals_whitelist]) === true + end + + def filter_empty_element(array) + array.reject { |e| e.to_s.empty? } + end + + def gitea_protected_branch_saved?(protected_branch) + protected_branch[:status] == :success + end + + def gitea_protected_branch_params + { + approvals_whitelist_username: get_approvals_whitelist_usernames, + 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_usernames) if get_approvals_whitelist_usernames.any? + + raise Error, '分支名称不能为空' if params[:branch_name].blank? + + end +end diff --git a/app/services/educoder/client_service.rb b/app/services/educoder/client_service.rb new file mode 100644 index 00000000..6c5c10d9 --- /dev/null +++ b/app/services/educoder/client_service.rb @@ -0,0 +1,112 @@ +class Educoder::ClientService < ApplicationService + attr_reader :url, :params + + PAGINATE_DEFAULT_PAGE = 1 + PAGINATE_DEFAULT_LIMIT = 20 + + def initialize(options={}) + @url = options[:url] + @params = options[:params] + end + + def post(url, params={}) + puts "[educoder] request params: #{params}" + auth_token = authen_params(params[:token]) + response = conn(auth_token).post do |req| + req.url full_url(url) + req.body = params[:data].to_json + end + render_status(response) + end + + def get(url, params={}) + puts "[educoder] params: #{params}" + conn(api_url(url), params) + end + + def delete(url, params={}) + auth_token = authen_params(params[:token]) + conn(auth_token).delete do |req| + req.url full_url(url) + req.body = params[:data].to_json + end + end + + def patch(url, params={}) + puts "[educoder] request params: #{params}" + auth_token = authen_params(params[:token]) + conn(auth_token).patch do |req| + req.url full_url(url) + req.body = params[:data].to_json + end + end + + def put(url, params={}) + puts "[educoder] put request params: #{params}" + conn(authen_params(params[:token])).put do |req| + req.url full_url(url) + req.body = params[:data].to_json + end + end + + private + def conn(url, hash={}) + par = [] + hash.each do |k,v| + par << "#{k}=#{v}" + end + + uri = URI("#{url}.json?#{par.join('&')}&private_token=#{private_token}") + puts "[educoder] request_url: #{uri}" + response = Net::HTTP.get_response(uri) + puts "[educoder] response code: #{response.code.to_i}" + if response.code.to_i != 200 + puts "======= 接口请求失败!" + raise '接口请求失败.' + return nil + end + JSON.parse(response.body) + end + + def base_url + Rails.application.config_for(:configuration)['educoder']['base_url'] + end + + def domain + Rails.application.config_for(:configuration)['educoder']['main_site'] + end + + def private_token + Rails.application.config_for(:configuration)['educoder']['token'] + end + + def access_key_secret + Gitea.gitea_config[:access_key_secret] + end + + def api_url(url) + [domain, base_url, url].join('/') + end + + def full_url(api_rest, action='post') + url = [api_url, api_rest].join('').freeze + url = action === 'get' ? url : URI.escape(url) + puts "[gitea] request url: #{url}" + return url + end + + + + def authen_params(token) + (token.is_a? String) ? {token: token} : Hash(token) + end + + def render_data(response) + case response.status + when 201, 200 + JSON.parse(response.body) + else + nil + end + end +end diff --git a/app/services/educoder/repository/commits/list_service.rb b/app/services/educoder/repository/commits/list_service.rb new file mode 100644 index 00000000..1a83c260 --- /dev/null +++ b/app/services/educoder/repository/commits/list_service.rb @@ -0,0 +1,29 @@ +class Educoder::Repository::Commits::ListService < Educoder::ClientService + attr_reader :repo_name, :args + + # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) + # repo_name: the name of repository + # Educoder::Repository::Commits::ListService.call('fessf/6hiwcb7o20200917174054') + def initialize(repo_name, **args) + @repo_name = repo_name + @args = {ref: 'master'}.merge(args.compact) + end + + def call + response = get(url, params) + render_result(response) + end + + private + def params + @args.merge(repo_name: repo_name) + end + + def url + "commits".freeze + end + + def render_result(response) + response['commits'] || [] + end +end diff --git a/app/services/educoder/repository/entries/get_service.rb b/app/services/educoder/repository/entries/get_service.rb new file mode 100644 index 00000000..9c4fed92 --- /dev/null +++ b/app/services/educoder/repository/entries/get_service.rb @@ -0,0 +1,30 @@ +class Educoder::Repository::Entries::GetService < Educoder::ClientService + attr_reader :repo_name, :filepath + + # filepath: path of the dir, file, symlink or submodule in the repo + # repo_name: the name of repository + def initialize(repo_name, filepath) + @repo_name = repo_name + @filepath = filepath + end + + def call + get(url, params) + end + + private + def params + Hash.new.merge(repo_name: repo_name, path: filepath) + end + + def url + "file_content".freeze + end + + def render_result(response) + body = JSON.parse(response.body) + if body['status'].to_i === -1 + raise '无权限访问.' + end + end +end diff --git a/app/services/educoder/repository/entries/list_service.rb b/app/services/educoder/repository/entries/list_service.rb new file mode 100644 index 00000000..dd3abea7 --- /dev/null +++ b/app/services/educoder/repository/entries/list_service.rb @@ -0,0 +1,39 @@ +class Educoder::Repository::Entries::ListService < Educoder::ClientService + attr_reader :repo_name, :args + + # ref: The name of the commit/branch/tag. Default the repository’s default branch (usually master) + # repo_name: the name of repository + # args: + # { + # "repo_name": "wmov43ez8/5xahe2t7nv20191022173304", + # "path": 'src' + # } + # Educoder::Repository::Entries::ListService.new('wmov43ez8/5xahe2t7nv20191022173304', {path: 'src'}).call + def initialize(repo_name, args={}) + @repo_name = repo_name + @args = args.compact + end + + def call + get(url, params) + end + + private + def params + @args.merge(repo_name: repo_name) + end + + def url + "repository".freeze + end + + def render_result(response) + body = JSON.parse(response.body) + case response.status + when 200 + body + else + [] + end + end +end diff --git a/app/services/gitea/chain/chain_get_service.rb b/app/services/gitea/chain/chain_get_service.rb new file mode 100644 index 00000000..3ac1bff7 --- /dev/null +++ b/app/services/gitea/chain/chain_get_service.rb @@ -0,0 +1,29 @@ +class Gitea::Chain::ChainGetService < Gitea::ChainService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + get(url, request_params) + end + + private + + def request_params + params[:chain_params] + end + + def url + chain_type = params[:type].to_s + case chain_type + when "query" + "/repos/amount/query".freeze + else + "".freeze + end + end + +end \ No newline at end of file diff --git a/app/services/gitea/chain/chain_post_service.rb b/app/services/gitea/chain/chain_post_service.rb new file mode 100644 index 00000000..3ce1a2cb --- /dev/null +++ b/app/services/gitea/chain/chain_post_service.rb @@ -0,0 +1,31 @@ +class Gitea::Chain::ChainPostService < Gitea::ChainService + + attr_reader :params + + def initialize(params) + @params = params + end + + def call + post(url, request_params) + end + + private + + def request_params + Hash.new.merge(data: params[:chain_params]) + end + + def url + chain_type = params[:type].to_s + case chain_type + when "create" + "/repos/create".freeze + when "upload" + "/repos/commit/upload".freeze + else #由于目前的api文档操作post请求,除了create/upload,都是在/repos/amount/*,所以以下简化了 + "/repos/amount/#{chain_type}".freeze + end + end + +end \ No newline at end of file diff --git a/app/services/gitea/chain_service.rb b/app/services/gitea/chain_service.rb new file mode 100644 index 00000000..9e161226 --- /dev/null +++ b/app/services/gitea/chain_service.rb @@ -0,0 +1,49 @@ +class Gitea::ChainService < ApplicationService + attr_reader :url, :params + + def initialize(options={}) + @url = options[:url] + @params = options[:params] + end + + def post(url, params={}) + Rails.logger.info("######_____api____request_url_______###############{request_url}") + Rails.logger.info("######_____api____request_params_______###############{params}") + + conn.post do |req| + req.url "#{request_url}" + req.body = params[:data].to_json + end + end + + def get(url, params={}) + conn.get do |req| + req.url "#{request_url}" + params.each_pair do |key, value| + req.params["#{key}"] = value + end + end + end + + private + def conn(auth={}) + @client ||= begin + Faraday.new(url: domain) do |req| + req.request :url_encoded + req.headers['Content-Type'] = 'application/json' + req.response :logger # 显示日志 + req.adapter Faraday.default_adapter + end + end + @client + end + + def domain + Rails.application.config_for(:configuration)['chain_base'] + end + + def request_url + [domain, url].join('').freeze + end + +end diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb index 58427637..728a9809 100644 --- a/app/services/gitea/client_service.rb +++ b/app/services/gitea/client_service.rb @@ -20,22 +20,17 @@ class Gitea::ClientService < ApplicationService # } def post(url, params={}) puts "[gitea] request params: #{params}" - request_url = [api_url, url].join('').freeze - Rails.logger.info("######_____api____request_url_______###############{request_url}") - Rails.logger.info("######_____api____request_params_______###############{params}") - auth_token = authen_params(params[:token]) - response = conn(auth_token).post do |req| - req.url "#{request_url}" + conn(auth_token).post do |req| + req.url full_url(url) req.body = params[:data].to_json end - render_status(response) end def get(url, params={}) auth_token = authen_params(params[:token]) conn(auth_token).get do |req| - req.url full_url(url) + req.url full_url(url, 'get') params.except(:token).each_pair do |key, value| req.params["#{key}"] = value end @@ -73,9 +68,10 @@ class Gitea::ClientService < ApplicationService private def conn(auth={}) - username = auth[:username] || access_key_id - secret = auth[:password] || access_key_secret + username = auth[:username] + secret = auth[:password] token = auth[:token] + puts "[gitea] username: #{username}" puts "[gitea] secret: #{secret}" puts "[gitea] token: #{token}" @@ -105,26 +101,19 @@ class Gitea::ClientService < ApplicationService Gitea.gitea_config[:domain] end - def access_key_id - Gitea.gitea_config[:access_key_id] - end - - def access_key_secret - Gitea.gitea_config[:access_key_secret] - end - def api_url [domain, base_url].join('') end - def full_url(api_rest) - [api_url, api_rest].join('').freeze + def full_url(api_rest, action='post') + url = [api_url, api_rest].join('').freeze + url = action === 'get' ? url : URI.escape(url) + puts "[gitea] request url: #{url}" + return url end def render_status(response) - Rails.logger.info("###############____response__#{response}") - Rails.logger.info("###############____response_status_#{response.status}") - Rails.logger.info("###############____response_body_#{response.body}") + puts "[gitea] response status: #{response.status}" mark = "[gitea] " case response.status when 201, 200, 202 @@ -134,13 +123,12 @@ class Gitea::ClientService < ApplicationService {status: 200} end when 401 - "" raise Error, mark + "401" when 422 result = JSON.parse(response&.body) - puts "[gitea] parse body: #{result}" + puts "[gitea] parse body: #{result['message']}" # return {status: -1, message: result[0]} - raise Error, result[0] + raise Error, result['message'] when 204 puts "[gitea] " @@ -150,6 +138,8 @@ class Gitea::ClientService < ApplicationService raise Error, mark + message when 403 {status: 403, message: '你没有权限操作!'} + when 404 + {status: 404, message: '你访问的链接不存在!'} else if response&.body.blank? message = "请求失败" @@ -173,4 +163,102 @@ class Gitea::ClientService < ApplicationService nil end end + + def render_response(response) + status = response.status + body = response&.body + + log_error(status, body) + + body, message = get_body_by_status(status, body) + + [status, message, body] + end + + def get_body_by_status(status, body) + body, message = + case status + when 404 then [nil, "404"] + when 403 then [nil, "403"] + else + if body.present? + body = JSON.parse(body) + fix_body(body) + else + nil + end + end + + [body, message] + end + + def log_error(status, body) + puts "[gitea] status: #{status}" + puts "[gitea] body: #{body&.force_encoding('UTF-8')}" + 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) + + return error(message, status) unless success_statuses.include? status + + render_body(body) + end end diff --git a/app/services/gitea/hooks/create_service.rb b/app/services/gitea/hooks/create_service.rb index 9c66c9a7..6b65a686 100644 --- a/app/services/gitea/hooks/create_service.rb +++ b/app/services/gitea/hooks/create_service.rb @@ -1,23 +1,40 @@ class Gitea::Hooks::CreateService < Gitea::ClientService - attr_reader :user, :repo_name, :body + attr_reader :token, :owner, :repo, :body - def initialize(user, repo_name, body) - @user = user - @repo_name = repo_name - @body = body + # body params: + # { + # "active": false, + # "branch_filter": "string", + # "config": { + # "content_type": "string", + # "url": "string" + # }, + # "events": [ + # "create" + # ], + # "type": "gitea" + # } + # eg: + # Gitea::Hooks::CreateService.call(user.gitea_token, user.login, repo.identifier, body) + def initialize(token, owner, repo, body) + @token = token + @owner = owner + @repo = repo + @body = body end - def call + def call response = post(url, params) + render_201_response(response) end private def params - body.merge(token: user.gitea_token) + Hash.new.merge(token: token, data: body).compact end def url - "/repos/#{user.login}/#{repo_name}/hooks".freeze + "/repos/#{owner}/#{repo}/hooks".freeze end -end \ No newline at end of file +end diff --git a/app/services/gitea/hooks/destroy_service.rb b/app/services/gitea/hooks/destroy_service.rb index 779ebd41..b30178ea 100644 --- a/app/services/gitea/hooks/destroy_service.rb +++ b/app/services/gitea/hooks/destroy_service.rb @@ -1,23 +1,23 @@ class Gitea::Hooks::DestroyService < Gitea::ClientService - attr_reader :user, :repo_name,:hook_id + attr_reader :token, :owner, :repo, :hook_id - def initialize(user, repo_name, hook_id) - @user = user - @repo_name = repo_name + def initialize(token, owner, repo, hook_id) + @token = token + @owner = owner + @repo = repo @hook_id = hook_id end - def call - response = delete(url, params) + def call + delete(url, params) end private def params - Hash.new.merge(token: user.gitea_token) + Hash.new.merge(token: token) end def url - "/repos/#{user.login}/#{repo_name}/hooks/#{hook_id}".freeze + "/repos/#{owner}/#{repo}/hooks/#{hook_id}".freeze end - -end \ No newline at end of file +end diff --git a/app/services/gitea/hooks/list_service.rb b/app/services/gitea/hooks/list_service.rb index 00170073..3bd05ea5 100644 --- a/app/services/gitea/hooks/list_service.rb +++ b/app/services/gitea/hooks/list_service.rb @@ -1,23 +1,27 @@ class Gitea::Hooks::ListService < Gitea::ClientService - attr_reader :user, :repo_name + attr_reader :token, :owner, :repo, :params - def initialize(user, repo_name) - @user = user - @repo_name = repo_name - @body = body + def initialize(token, owner, repo_name, params={}) + @token = token + @owner = owner + @repo = repo + @params = params end - def call - response = get(url, params) + def call + get(url, params) end private def params - Hash.new.merge(token: user.gitea_token) + Hash.new.merge(token: token, + page: params[:page], + limit: params[:limit] + ).compact end def url - "/repos/#{user.login}/#{repo_name}/hooks".freeze + "/repos/#{owner}/#{repo}/hooks".freeze end -end \ No newline at end of file +end diff --git a/app/services/gitea/hooks/update_service.rb b/app/services/gitea/hooks/update_service.rb index d5946758..9086a3a3 100644 --- a/app/services/gitea/hooks/update_service.rb +++ b/app/services/gitea/hooks/update_service.rb @@ -2,14 +2,14 @@ class Gitea::Hooks::UpdateService < Gitea::ClientService attr_reader :user, :repo_name, :body,:hook_id def initialize(user, repo_name, body, hook_id) - @user = user - @repo_name = repo_name - @body = body + @user = user + @repo_name = repo_name + @body = body @hook_id = hook_id end - def call - response = patch(url, params) + def call + patch(url, params) end private @@ -21,4 +21,4 @@ class Gitea::Hooks::UpdateService < Gitea::ClientService "/repos/#{user.login}/#{repo_name}/hooks/#{hook_id}".freeze end -end \ No newline at end of file +end diff --git a/app/services/gitea/oauth2/create_service.rb b/app/services/gitea/oauth2/create_service.rb new file mode 100644 index 00000000..1fa93b7a --- /dev/null +++ b/app/services/gitea/oauth2/create_service.rb @@ -0,0 +1,42 @@ +# creates a new OAuth2 application +class Gitea::Oauth2::CreateService < Gitea::ClientService + attr_reader :token, :params + + # params: + # { + # "name": "string", + # "redirect_uris": [ + # "string" + # ] + # } + # ep: Gitea::OAuth2::CreateService.call(current_user.gitea_token, {name: 'oauth_name', redirect_uris: ['url']}) + # return values example: + # { + # "client_id": "string", + # "client_secret": "string", + # "created": "2020-07-08T03:12:49.960Z", + # "id": 0, + # "name": "string", + # "redirect_uris": [ + # "string" + # ] + # } + def initialize(token, params) + @token = token + @params = params + end + + def call + response = post(url, request_params) + render_201_response(response) + end + + private + def url + "/user/applications/oauth2".freeze + end + + def request_params + params.merge(token: token, data: params).compact + end +end diff --git a/app/services/gitea/pull_request/commits_service.rb b/app/services/gitea/pull_request/commits_service.rb new file mode 100644 index 00000000..aca2067c --- /dev/null +++ b/app/services/gitea/pull_request/commits_service.rb @@ -0,0 +1,40 @@ +# List commits on a pull request +class Gitea::PullRequest::CommitsService < Gitea::ClientService + attr_reader :owner, :repo, :pull_number, :token + + # GET /repos/{owner}/{repo}/pulls/{pull_number}/commits + # owner: 用户 + # repo: 仓库名称/标识 + # pull_number: pull request主键id + # eg: + # Gitea::PullRequest::FilesService.call('jasder', 'repo_identifier', 1) + def initialize(owner, repo, pull_number, token=nil) + @owner = owner + @repo = repo + @token = token + @pull_number = pull_number + end + + def call + response = get(url, params) + render_result(response) + end + + private + def params + Hash.new.merge(token: owner) + end + + def url + "/repos/#{owner}/#{repo}/pulls/#{pull_number}/commits".freeze + end + + def render_result(response) + case response.status + when 200 + JSON.parse(response.body) + else + nil + end + end +end diff --git a/app/services/gitea/pull_request/create_service.rb b/app/services/gitea/pull_request/create_service.rb index 3cf8dde0..a911feae 100644 --- a/app/services/gitea/pull_request/create_service.rb +++ b/app/services/gitea/pull_request/create_service.rb @@ -1,9 +1,9 @@ class Gitea::PullRequest::CreateService < Gitea::ClientService - attr_reader :token, :user, :repo, :params + attr_reader :token, :owner, :repo, :params # 同一个项目下发送pr例子,如下: # 参数说明: - # user: 项目拥有者 + # owner: 项目拥有者 # repo: 项目名称 # params: # { @@ -17,7 +17,7 @@ class Gitea::PullRequest::CreateService < Gitea::ClientService # fork的项目,向源项目发送pr例子,如下: # 参数说明: - # user:源项目拥有者 + # owner:源项目拥有者 # repo:源项目仓库名称 # params: # { @@ -28,24 +28,31 @@ class Gitea::PullRequest::CreateService < Gitea::ClientService # } # 以上例子说明:jasder用户fork的项目master分支向源项目的develop分支发送pr # Gitea::PullRequest::CreateService.call('token', '源项目拥有者', '源项目名称', params) - def initialize(token, user, repo, params={}) - @token = token - @user = user + def initialize(token, owner, repo, params={}) + @token = token + @owner = owner @repo = repo @params = params end def call - post(url, request_params) + response = post(url, request_params) + json_format(response) end private def url - "/repos/#{@user.login}/#{@repo}/pulls".freeze + "/repos/#{@owner}/#{@repo}/pulls".freeze end def request_params Hash.new.merge(token: token, data: @params) end + + def json_format(response) + status, message, body = render_response(response) + + status === 201 ? success(body) : error(message, status) + end end diff --git a/app/services/gitea/pull_request/files_service.rb b/app/services/gitea/pull_request/files_service.rb new file mode 100644 index 00000000..9785588e --- /dev/null +++ b/app/services/gitea/pull_request/files_service.rb @@ -0,0 +1,40 @@ +# List pull requests files +class Gitea::PullRequest::FilesService < Gitea::ClientService + attr_reader :owner, :repo, :pull_number, :token + + # GET /repos/{owner}/{repo}/pulls/{pull_number}/files + # owner: 用户 + # repo: 仓库名称/标识 + # pull_number: pull request主键id + # eg: + # Gitea::PullRequest::FilesService.call('jasder', 'repo_identifier', 1) + def initialize(owner, repo, pull_number, token=nil) + @owner = owner + @repo = repo + @token = token + @pull_number = pull_number + end + + def call + response = get(url, params) + render_result(response) + end + + private + def params + Hash.new.merge(token: token) + end + + def url + "/repos/#{owner}/#{repo}/pulls/#{pull_number}/files".freeze + end + + def render_result(response) + case response.status + when 200 + JSON.parse(response.body) + else + nil + end + end +end diff --git a/app/services/gitea/repository/branches/get_service.rb b/app/services/gitea/repository/branches/get_service.rb index d833b86b..0e84e15d 100644 --- a/app/services/gitea/repository/branches/get_service.rb +++ b/app/services/gitea/repository/branches/get_service.rb @@ -13,7 +13,7 @@ class Gitea::Repository::Branches::GetService < Gitea::ClientService def call response = get(url, params) - render_data(response) + render_200_response(response) end private diff --git a/app/services/gitea/repository/branches/list_service.rb b/app/services/gitea/repository/branches/list_service.rb index 17702259..f4296509 100644 --- a/app/services/gitea/repository/branches/list_service.rb +++ b/app/services/gitea/repository/branches/list_service.rb @@ -8,7 +8,7 @@ class Gitea::Repository::Branches::ListService < Gitea::ClientService def call response = get(url, params) - render_data(response) + render_200_response(response) end private diff --git a/app/services/gitea/repository/commits/compare_service.rb b/app/services/gitea/repository/commits/compare_service.rb new file mode 100644 index 00000000..502f6ce9 --- /dev/null +++ b/app/services/gitea/repository/commits/compare_service.rb @@ -0,0 +1,29 @@ +# Compare two commits +class Gitea::Repository::Commits::CompareService < Gitea::ClientService + attr_reader :owner, :repo, :base, :head, :token + + # sha: the commit hash + # ex: + # Gitea::Repository::Commits::CompareService.call('owner', 'repo_identifier', 'master', 'jasder/repo_identifier:develop') + def initialize(owner, repo, base, head, token=nil) + @token = token + @owner = owner + @base = base + @repo = repo + @head = head + end + + def call + response = get(url, params) + render_status(response) + end + + private + def params + Hash.new.merge(token: token) + end + + def url + "/repos/#{owner}/#{repo}/compare/#{base}...#{head}".freeze + end +end diff --git a/app/services/gitea/repository/commits/get_service.rb b/app/services/gitea/repository/commits/get_service.rb index 019658d1..d497f1e4 100644 --- a/app/services/gitea/repository/commits/get_service.rb +++ b/app/services/gitea/repository/commits/get_service.rb @@ -1,21 +1,21 @@ # Get a single commit from a repository class Gitea::Repository::Commits::GetService < Gitea::ClientService - attr_reader :token, :owner, :repo, :sha, :custom + attr_reader :token, :owner, :repo, :sha, :hash # sha: the commit hash # ex: Gitea::Repository::Commits::GetService.new(@repo.user.login, repo.identifier, params[:sha], current_user.gitea_token) # TODO custom参数用于判断调用哪个api - def initialize(owner, repo, sha, token, custom=false) + def initialize(owner, repo, sha, token, hash={}) @token = token @owner = owner @sha = sha @repo = repo - @custom = custom + @hash = hash end def call response = get(url, params) - render_result(response) + render_status(response) end private @@ -24,22 +24,12 @@ class Gitea::Repository::Commits::GetService < Gitea::ClientService end def url - if custom + if hash[:diff] # TODO # 平台自己编写的gitea接口,后续可能会通过提交pr的形式合并到gitea原有的接口上 - "/repos/#{owner}/#{repo}/commits/diff/#{sha}".freeze + "/repos/#{owner}/#{repo}/commits/#{sha}/diff".freeze else "/repos/#{owner}/#{repo}/git/commits/#{sha}".freeze end end - - def render_result(response) - body = JSON.parse(response.body) - case response.status - when 200 - JSON.parse(response.body) - else - {status: -1, message: "#{body['message']}"} - end - end end diff --git a/app/services/gitea/repository/create_service.rb b/app/services/gitea/repository/create_service.rb index 80d8b440..168aaab2 100644 --- a/app/services/gitea/repository/create_service.rb +++ b/app/services/gitea/repository/create_service.rb @@ -18,7 +18,8 @@ class Gitea::Repository::CreateService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + render_201_response(response) end private diff --git a/app/services/gitea/repository/entries/create_service.rb b/app/services/gitea/repository/entries/create_service.rb index 7f1a6b52..9f5abad2 100644 --- a/app/services/gitea/repository/entries/create_service.rb +++ b/app/services/gitea/repository/entries/create_service.rb @@ -29,7 +29,9 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService end def call - post(url, params) + response = post(url, params) + + render_201_response(response) end private diff --git a/app/services/gitea/repository/entries/get_service.rb b/app/services/gitea/repository/entries/get_service.rb index f0236a07..f8ac2754 100644 --- a/app/services/gitea/repository/entries/get_service.rb +++ b/app/services/gitea/repository/entries/get_service.rb @@ -31,8 +31,10 @@ class Gitea::Repository::Entries::GetService < Gitea::ClientService case response.status when 200 body + when 404 + raise '你访问的文件不存在' else - {status: -1, message: "#{body['message']}"} + raise body['message'] end end end diff --git a/app/services/gitea/repository/fork_service.rb b/app/services/gitea/repository/fork_service.rb index dce925b8..c43a9ddf 100644 --- a/app/services/gitea/repository/fork_service.rb +++ b/app/services/gitea/repository/fork_service.rb @@ -14,7 +14,9 @@ class Gitea::Repository::ForkService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + + render_202_response(response) end private diff --git a/app/services/gitea/repository/migrate_service.rb b/app/services/gitea/repository/migrate_service.rb index 568e4d5c..50881208 100644 --- a/app/services/gitea/repository/migrate_service.rb +++ b/app/services/gitea/repository/migrate_service.rb @@ -31,7 +31,9 @@ class Gitea::Repository::MigrateService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + + render_201_response(response) end private diff --git a/app/services/gitea/repository/protected_branches/create_service.rb b/app/services/gitea/repository/protected_branches/create_service.rb new file mode 100644 index 00000000..79415e09 --- /dev/null +++ b/app/services/gitea/repository/protected_branches/create_service.rb @@ -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 diff --git a/app/services/gitea/repository/protected_branches/destroy_service.rb b/app/services/gitea/repository/protected_branches/destroy_service.rb new file mode 100644 index 00000000..b0e5f0cf --- /dev/null +++ b/app/services/gitea/repository/protected_branches/destroy_service.rb @@ -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 diff --git a/app/services/gitea/repository/protected_branches/update_service.rb b/app/services/gitea/repository/protected_branches/update_service.rb new file mode 100644 index 00000000..2f25d9a2 --- /dev/null +++ b/app/services/gitea/repository/protected_branches/update_service.rb @@ -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 diff --git a/app/services/gitea/repository/sync_mirrored_service.rb b/app/services/gitea/repository/sync_mirrored_service.rb index 6918a6ec..8d167314 100644 --- a/app/services/gitea/repository/sync_mirrored_service.rb +++ b/app/services/gitea/repository/sync_mirrored_service.rb @@ -15,7 +15,9 @@ class Gitea::Repository::SyncMirroredService < Gitea::ClientService end def call - post(url, request_params) + response = post(url, request_params) + + render_200_no_body(response) end private diff --git a/app/services/gitea/repository/update_service.rb b/app/services/gitea/repository/update_service.rb index 37903ec9..0d27922b 100644 --- a/app/services/gitea/repository/update_service.rb +++ b/app/services/gitea/repository/update_service.rb @@ -28,6 +28,6 @@ class Gitea::Repository::UpdateService < Gitea::ClientService end def data_params - Hash.new.merge(token: user.gitea_token, data: params) + Hash.new.merge(token: user.gitea_token, data: params).compact end end diff --git a/app/services/gitea/user/register_service.rb b/app/services/gitea/user/register_service.rb index 4b014de6..ec572930 100644 --- a/app/services/gitea/user/register_service.rb +++ b/app/services/gitea/user/register_service.rb @@ -7,8 +7,7 @@ class Gitea::User::RegisterService < Gitea::ClientService end def call - params = {} - params = params.merge(data: user_params) + params = Hash.new.merge(data: user_params, token: @token) post(API_REST, params) end diff --git a/app/services/gitea/user/update_service.rb b/app/services/gitea/user/update_service.rb index ead483a2..5e6108a9 100644 --- a/app/services/gitea/user/update_service.rb +++ b/app/services/gitea/user/update_service.rb @@ -17,7 +17,7 @@ class Gitea::User::UpdateService < Gitea::ClientService # source_id integer($int64) # website string - def initialize(edit_username, params={}, token=nil) + def initialize(edit_username, params={}, token={username: Gitea.gitea_config[:access_key_id], password: Gitea.gitea_config[:access_key_secret]}) @token = token @params = params @edit_username = edit_username diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index f4297acf..dc14d10d 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -12,6 +12,7 @@ class Projects::CreateService < ApplicationService @project = Project.new(project_params) ActiveRecord::Base.transaction do if @project.save! + Project.update_common_projects_count! Repositories::CreateService.new(user, @project, repository_params).call else Rails.logger.info("#############___________create_project_erros______###########{@project.errors.messages}") diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index 2eb9172c..ff0c0643 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -9,6 +9,7 @@ class Projects::MigrateService < ApplicationService def call @project = Project.new(project_params) if @project.save! + Project.update_mirror_projects_count! Repositories::MigrateService.new(user, @project, repository_params).call else # diff --git a/app/services/protected_branches/base_service.rb b/app/services/protected_branches/base_service.rb new file mode 100644 index 00000000..f56a4e33 --- /dev/null +++ b/app/services/protected_branches/base_service.rb @@ -0,0 +1,23 @@ +module ProtectedBranches + class BaseService < ApplicationService + include ProtectedBranchParamsAble + + Error = Class.new(StandardError) + attr_accessor :repository, :owner, :params + + def initialize(repository, user = nil, params = {}) + @repository, @owner, @params = repository, user, params.dup + end + + # delegate :repository, to: :project + end + + def error(errors, award: nil, status: nil) + errors = Array.wrap(errors) + + super(errors.to_sentence.presence, status).merge({ + award: award, + errors: errors + }) + end +end diff --git a/app/services/protected_branches/create_service.rb b/app/services/protected_branches/create_service.rb new file mode 100644 index 00000000..3b3eca9a --- /dev/null +++ b/app/services/protected_branches/create_service.rb @@ -0,0 +1,31 @@ +module ProtectedBranches + class CreateService < ProtectedBranches::BaseService + def call + validate! + + ProtectedBranch.transaction do + save_gitea_protected_branch! + save_protected_branch! + end + + 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 + + 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] unless gitea_protected_branch_saved?(@gitea_protected_branch) + end + + end +end diff --git a/app/services/protected_branches/destroy_service.rb b/app/services/protected_branches/destroy_service.rb new file mode 100644 index 00000000..503adf9a --- /dev/null +++ b/app/services/protected_branches/destroy_service.rb @@ -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 diff --git a/app/services/protected_branches/edit_service.rb b/app/services/protected_branches/edit_service.rb new file mode 100644 index 00000000..a6373a86 --- /dev/null +++ b/app/services/protected_branches/edit_service.rb @@ -0,0 +1,35 @@ +module ProtectedBranches + class EditService < ProtectedBranches::BaseService + def call + validate_branch_name! + + protected_branch + rescue => ex + Rails.logger.info ex + raise Error, ex + end + + private + def protected_branch + branch = get_common_branch + protected_branch ||= @repository.protected_branches.find_by(branch_name: branch_name) + [branch, protected_branch] + end + + def get_common_branch + result = Gitea::Repository::Branches::GetService.call(@owner.login, + @repository.identifier, branch_name, @owner.gitea_token) + + raise Error, '404' if result[:status] == :error + result + end + + def validate_branch_name! + raise Error, '分支名称不能为空' if branch_name.blank? + end + + def branch_name + params + end + end +end diff --git a/app/services/protected_branches/get_service.rb b/app/services/protected_branches/get_service.rb new file mode 100644 index 00000000..7dcfe9a6 --- /dev/null +++ b/app/services/protected_branches/get_service.rb @@ -0,0 +1,23 @@ +module ProtectedBranches + class GetService < ProtectedBranches::BaseService + def call + validate_branch_name! + + 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 validate_branch_name! + raise Error, '分支名称不能为空' if params[:branch_name].blank? + end + end +end diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb new file mode 100644 index 00000000..53cc56b5 --- /dev/null +++ b/app/services/protected_branches/update_service.rb @@ -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 diff --git a/app/services/pull_requests/create_service.rb b/app/services/pull_requests/create_service.rb new file mode 100644 index 00000000..0d41c340 --- /dev/null +++ b/app/services/pull_requests/create_service.rb @@ -0,0 +1,146 @@ +class PullRequests::CreateService < ApplicationService + + attr_reader :current_user, :owner, :project, :params + + def initialize(current_user, owner, project, params) + @owner = owner + @project = project + @params = params + @current_user = current_user + end + + def call + validate! + save_pull_issue! + save_pull_request! + save_issue_tags_relates! + save_tiding! + save_project_trend! + save_custom_journal_detail! + + [pull_request, gitea_pull_request] + end + + def pull_issue_params + { + user: @current_user, + project: @project, + subject: @params[:title], + description: @params[:body], + assigned_to_id: @params[:assigned_to_id], + fixed_version_id: @params[:fixed_version_id], + issue_tags_value: @params[:issue_tag_ids].present? ? @params[:issue_tag_ids].join(",") : "", + priority_id: @params[:priority_id] || "2", + issue_classify: "pull_request", + issue_type: @params[:issue_type] || "1", + tracker_id: 2, + status_id: 1, + } + end + + def pull_issue + @pull_issue ||= Issue.new(pull_issue_params.compact) + end + + def save_pull_issue! + pull_issue.save + end + + def pull_request + @pull_request ||= @project.pull_requests.new(pull_request_params.compact) + end + + def save_pull_request! + pull_request.save + end + + def save_issue_tags_relates! + issue_tag_ids.each do |tag| + IssueTagsRelate.create!(issue_id: pull_issue.id, issue_tag_id: tag) + end + end + + def issue_tag_ids + Array(@params[:issue_tag_ids]) + end + + def save_tiding! + if @params[:assigned_to_id].present? + Tiding.create!(user_id: @params[:assigned_to_id], + trigger_user: @current_user, + container: pull_request, + parent_container: @project, + tiding_type: 'pull_request', + status: 0) + end + end + + def save_project_trend! + project_trend.save + end + + def project_trend + @project_trend ||= pull_request.project_trends.new( + user: @current_user, + project: @project, + action_type: "create") + end + + def pull_request_params + base_pull_params.merge({ + user: @current_user, + issue: pull_issue, + fork_project_id: @params[:fork_project_id], + is_original: @params[:is_original], + files_count: @params[:files_count] || 0, + commits_count: @params[:commits_count] || 0 + }) + end + + def save_custom_journal_detail! + if @params[:title].to_s.include?("WIP:") + pull_issue.custom_journal_detail("WIP", "", "这个合并请求被标记为尚未完成的工作。完成后请从标题中移除WIP:前缀。", @current_user&.id) + end + end + + def gitea_pull_request + @gitea_pull_request ||= create_gitea_pull_request! + end + + def create_gitea_pull_request! + @gitea_pull_request = + Gitea::PullRequest::CreateService.call( + @current_user&.gitea_token, + @owner.login, + @project&.identifier, + gitea_pull_request_params.compact) + end + + def gitea_pull_request_params + merge_original_pull_params.except(:milestone) + end + + def merge_original_pull_params + if pull_request.is_original && @params[:merge_user_login] + base_pull_params.merge(head: "#{@params[:merge_user_login]}:#{@params[:head]}") + else + base_pull_params + end + end + + def base_pull_params + { + title: @params[:title], #标题 + body: @params[:body], #内容 + head: @params[:head], #源分支 + base: @params[:base], #目标分支 + milestone: 0, #里程碑,未与本地的里程碑关联 + } + end + + def validate! + raise "title参数不能为空" if @params[:title].blank? + raise "head参数不能为空" if @params[:head].blank? + raise "base参数不能为空" if @params[:base].blank? + end +end diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index b506d13a..9458e513 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -14,6 +14,18 @@ class Repositories::CreateService < ApplicationService gitea_repository = Gitea::Repository::CreateService.new(user.gitea_token, gitea_repository_params).call sync_project(@repository, gitea_repository) sync_repository(@repository, gitea_repository) + # if project.project_type == "common" + # chain_params = { + # type: "create", + # chain_params:{ + # username: user.try(:login), + # reponame: @repository.try(:identifier), + # token_name: @repository.try(:identifier), + # total_supply: 1000000 + # } + # } + # PostChainJob.perform_later(chain_params) #创建上链操作 + # end else Rails.logger.info("#############___________create_repository_erros______###########{@repository.errors.messages}") end @@ -26,7 +38,7 @@ class Repositories::CreateService < ApplicationService private - def sync_project(repository, gitea_repository) + def sync_project(repository, gitea_repository) if gitea_repository project.update_columns( gpid: gitea_repository["id"], diff --git a/app/views/admins/laboratory_settings/_add_tr.html.erb b/app/views/admins/laboratory_settings/_add_tr.html.erb new file mode 100644 index 00000000..2d6ff25d --- /dev/null +++ b/app/views/admins/laboratory_settings/_add_tr.html.erb @@ -0,0 +1,12 @@ + + <%= text_field_tag('navbar[][name]', "", id: nil, class: 'form-control', placeholder: "导航名称") %> + <%= text_field_tag('navbar[][link]', "", id: nil, class: 'form-control', placeholder: "导航链接") %> + + <%= check_box_tag('navbar[][hidden]', 0, false, id: nil, class: 'font-16') %> + + +
+ +
+ + \ No newline at end of file diff --git a/app/views/admins/laboratory_settings/new.js.erb b/app/views/admins/laboratory_settings/new.js.erb new file mode 100644 index 00000000..47eb5aa3 --- /dev/null +++ b/app/views/admins/laboratory_settings/new.js.erb @@ -0,0 +1 @@ +$("#laboratories-show-content").append("<%= j render partial: "admins/laboratory_settings/add_tr" %>") \ No newline at end of file diff --git a/app/views/admins/laboratory_settings/show.html.erb b/app/views/admins/laboratory_settings/show.html.erb index f2269955..8905869e 100644 --- a/app/views/admins/laboratory_settings/show.html.erb +++ b/app/views/admins/laboratory_settings/show.html.erb @@ -24,7 +24,7 @@
<% rails_env = EduSetting.get('rails_env') %> <%= rails_env && rails_env != 'production' ? ".#{rails_env}.educoder.net" : '.educoder.net' %> -
+ <% =end%> @@ -147,18 +147,23 @@
-
导航设置
+
+
导航设置 + <%= link_to "".html_safe,new_admins_laboratory_laboratory_setting_path, remote: true, class: "btn btn-primary btn-sm"%> +
+
- + - + + - + <% (setting.navbar || setting.default_navbar).each do |nav| %> @@ -166,6 +171,11 @@ + <% end %> diff --git a/app/views/ci/builds/_author.json.jbuilder b/app/views/ci/builds/_author.json.jbuilder new file mode 100644 index 00000000..280f7ef9 --- /dev/null +++ b/app/views/ci/builds/_author.json.jbuilder @@ -0,0 +1,4 @@ +json.id user.id +json.name user.real_name +json.login user.login +json.image_url url_to_avatar(user) diff --git a/app/views/ci/builds/_build.json.jbuilder b/app/views/ci/builds/_build.json.jbuilder new file mode 100644 index 00000000..1c1afcbf --- /dev/null +++ b/app/views/ci/builds/_build.json.jbuilder @@ -0,0 +1,21 @@ +json.id build.build_id +json.repo_id build.build_repo_id +json.number build.build_number +json.status build.build_status +json.event build.build_event +json.action build.build_action +json.error build.build_error if build.build_status == 'error' +json.message build.build_message +json.author do + json.partial! 'author', user: current_user +end +json.started format_utc_time build.build_started +json.finished format_utc_time build.build_finished +json.created format_utc_time build.build_created +json.updated format_utc_time build.build_updated +json.version build.build_version +json.build_after_sha build.build_after +json.build_before_sha build.build_before +json.branch_source build.build_source +json.branch_target build.build_target +json.duration_time render_duartion_time(build.build_finished, build.build_started) diff --git a/app/views/ci/builds/_stage.json.jbuilder b/app/views/ci/builds/_stage.json.jbuilder new file mode 100644 index 00000000..95c2eff5 --- /dev/null +++ b/app/views/ci/builds/_stage.json.jbuilder @@ -0,0 +1,23 @@ +json.id stage.stage_id +json.repo_id stage.stage_repo_id +json.build_id stage.stage_build_id +json.name stage.stage_name +json.kind stage.stage_kind +json.type stage.stage_type +json.number stage.stage_number +json.status stage.stage_status +json.errignore stage.stage_errignore +json.exit_code stage.stage_exit_code +json.os stage.stage_os +json.arch stage.stage_arch +json.started format_utc_time(stage.stage_started) +json.stopped format_utc_time(stage.stage_stopped) +json.created format_utc_time(stage.stage_created) +json.updated format_utc_time(stage.stage_updated) +json.duration_time render_duartion_time(stage.stage_stopped, stage.stage_started) +json.version stage.stage_version +json.on_success stage.stage_on_success +json.on_failure stage.stage_on_failure +json.steps stage.steps do |step| + json.partial! "/ci/builds/step", step: step +end diff --git a/app/views/ci/builds/_step.json.jbuilder b/app/views/ci/builds/_step.json.jbuilder new file mode 100644 index 00000000..44d5f366 --- /dev/null +++ b/app/views/ci/builds/_step.json.jbuilder @@ -0,0 +1,9 @@ +json.id step.step_id +json.number step.step_number +json.name step.step_name +json.status step.step_status +json.exit_code step.step_exit_code +json.started format_utc_time(step.step_started) +json.stopped format_utc_time(step.step_stopped) +json.duration_time render_duartion_time(step.step_stopped, step.step_started) +json.version step.step_version diff --git a/app/views/ci/builds/index.json.jbuilder b/app/views/ci/builds/index.json.jbuilder new file mode 100644 index 00000000..a4b24d98 --- /dev/null +++ b/app/views/ci/builds/index.json.jbuilder @@ -0,0 +1,4 @@ +json.total_count @total_count +json.builds @builds do |build| + json.partial! "/ci/builds/build", build: build, user: @user +end diff --git a/app/views/ci/builds/show.json.jbuilder b/app/views/ci/builds/show.json.jbuilder new file mode 100644 index 00000000..0c2b21e2 --- /dev/null +++ b/app/views/ci/builds/show.json.jbuilder @@ -0,0 +1,4 @@ +json.partial! "/ci/builds/build", build: @build +json.stages @build.stages do |stage| + json.partial! "/ci/builds/stage", stage: stage +end diff --git a/app/views/ci/cloud_accounts/bind.json.jbuilder b/app/views/ci/cloud_accounts/bind.json.jbuilder new file mode 100644 index 00000000..cff42cef --- /dev/null +++ b/app/views/ci/cloud_accounts/bind.json.jbuilder @@ -0,0 +1,8 @@ +json.step current_user.devops_step +json.cloud_account do + if @cloud_account && !current_user.devops_uninit? + json.ip @cloud_account.drone_ip + else + json.nil! + end +end diff --git a/app/views/ci/cloud_accounts/oauth_grant.json.jbuilder b/app/views/ci/cloud_accounts/oauth_grant.json.jbuilder new file mode 100644 index 00000000..39d2c064 --- /dev/null +++ b/app/views/ci/cloud_accounts/oauth_grant.json.jbuilder @@ -0,0 +1 @@ +json.step current_user.devops_step diff --git a/app/views/ci/cloud_accounts/show.json.jbuilder b/app/views/ci/cloud_accounts/show.json.jbuilder new file mode 100644 index 00000000..efb2d7db --- /dev/null +++ b/app/views/ci/cloud_accounts/show.json.jbuilder @@ -0,0 +1,9 @@ +json.step current_user.devops_step +json.ci_certification current_user.ci_certification? +json.cloud_account do + if @cloud_account && !current_user.devops_uninit? + json.ip @cloud_account.drone_ip + else + json.nil! + end +end diff --git a/app/views/ci/cloud_accounts/unbind.json.jbuilder b/app/views/ci/cloud_accounts/unbind.json.jbuilder new file mode 100644 index 00000000..e69de29b diff --git a/app/views/ci/languages/common.json.jbuilder b/app/views/ci/languages/common.json.jbuilder new file mode 100644 index 00000000..ba0214c8 --- /dev/null +++ b/app/views/ci/languages/common.json.jbuilder @@ -0,0 +1,6 @@ +json.array! @languages do |lang| + json.id lang.id + json.name lang.name + json.content render_base64_decoded lang.content + json.cover_url lang.cover_id.present? ? download_url(lang.cover) : nil +end diff --git a/app/views/ci/languages/index.json.jbuilder b/app/views/ci/languages/index.json.jbuilder new file mode 100644 index 00000000..ba0214c8 --- /dev/null +++ b/app/views/ci/languages/index.json.jbuilder @@ -0,0 +1,6 @@ +json.array! @languages do |lang| + json.id lang.id + json.name lang.name + json.content render_base64_decoded lang.content + json.cover_url lang.cover_id.present? ? download_url(lang.cover) : nil +end diff --git a/app/views/ci/languages/show.json.jbuilder b/app/views/ci/languages/show.json.jbuilder new file mode 100644 index 00000000..2fbef2ba --- /dev/null +++ b/app/views/ci/languages/show.json.jbuilder @@ -0,0 +1,4 @@ +json.id @language.id +json.name @language.name +json.content render_base64_decoded @language.content +json.cover_url @language.cover_id.present? ? download_url(@language.cover) : nil diff --git a/app/views/ci/projects/authorize.json.jbuilder b/app/views/ci/projects/authorize.json.jbuilder new file mode 100644 index 00000000..d57e07fe --- /dev/null +++ b/app/views/ci/projects/authorize.json.jbuilder @@ -0,0 +1,13 @@ +json.step @user.devops_step +json.ci_certification @user.ci_certification? +json.cloud_account do + if @cloud_account && !@user.devops_uninit? + json.id @cloud_account.id + json.account @cloud_account.account + json.ip @cloud_account.drone_ip + json.secret @cloud_account.visible_secret + json.authenticate_url @cloud_account.authenticate_url if @user.devops_unverified? + else + json.nil! + end +end diff --git a/app/views/compare/index.json.jbuilder b/app/views/compare/index.json.jbuilder new file mode 100644 index 00000000..e69de29b diff --git a/app/views/compare/show.json.jbuilder b/app/views/compare/show.json.jbuilder new file mode 100644 index 00000000..8f95bbcb --- /dev/null +++ b/app/views/compare/show.json.jbuilder @@ -0,0 +1,13 @@ +json.commits_count @compare_result['Commits']&.size +json.commits @compare_result['Commits'], partial: 'pull_requests/commit', as: :commit + +json.diff do + if @compare_result['Diff'].blank? + json.nil! + else + json.files_count @compare_result['Diff']['NumFiles'] + json.total_addition @compare_result['Diff']['TotalAddition'] + json.total_deletion @compare_result['Diff']['TotalDeletion'] + json.files @compare_result['Diff']['Files'], partial: 'pull_requests/diff_file', as: :file, locals: {sha: @compare_result['LatestSha']} + end +end diff --git a/app/views/issues/edit.json.jbuilder b/app/views/issues/edit.json.jbuilder index 382dab1b..eae63c3c 100644 --- a/app/views/issues/edit.json.jbuilder +++ b/app/views/issues/edit.json.jbuilder @@ -3,6 +3,8 @@ json.extract! @issue, :id,:subject,:description,:is_private,:assigned_to_id,:tra :start_date,:due_date,:estimated_hours, :issue_type, :token,:issue_classify, :branch_name json.done_ratio @issue.done_ratio.to_s + "%" json.issue_tags @issue.get_issue_tags +json.cannot_edit_tags @cannot_edit_tags +json.issue_current_user @issue.author_id == current_user.try(:id) # json.issue_chosen @issue_chosen # json.branches @all_branches json.attachments do diff --git a/app/views/issues/new.json.jbuilder b/app/views/issues/new.json.jbuilder index f47ce3e7..03c7608a 100644 --- a/app/views/issues/new.json.jbuilder +++ b/app/views/issues/new.json.jbuilder @@ -1,3 +1,2 @@ json.partial! "commons/success" -json.branches @all_branches -json.issue_chosen @issue_chosen \ No newline at end of file +json.issue_chosen @issue_chosen diff --git a/app/views/issues/show.json.jbuilder b/app/views/issues/show.json.jbuilder index 156031f7..be6de14e 100644 --- a/app/views/issues/show.json.jbuilder +++ b/app/views/issues/show.json.jbuilder @@ -1,5 +1,5 @@ json.partial! "commons/success" -json.extract! @issue, :id,:subject,:is_lock,:description,:is_private, :start_date,:due_date,:estimated_hours +json.extract! @issue, :id,:subject,:is_lock,:description,:is_private, :start_date,:due_date,:estimated_hours, :status_id json.user_permission @user_permission json.closed_on @issue.closed_on.present? ? format_time(@issue.closed_on) : "" diff --git a/app/views/members/_member.json.jbuilder b/app/views/members/_member.json.jbuilder index 5a3d3dc0..45a0837e 100644 --- a/app/views/members/_member.json.jbuilder +++ b/app/views/members/_member.json.jbuilder @@ -3,3 +3,4 @@ json.name user.real_name json.login user.login json.image_url url_to_avatar(user) json.email user.try(:mail) +# json.token get_user_token(user.try(:login),@project.try(:identifier)) diff --git a/app/views/oauth/register.html.erb b/app/views/oauth/register.html.erb index 59a3d485..96778fa0 100644 --- a/app/views/oauth/register.html.erb +++ b/app/views/oauth/register.html.erb @@ -11,7 +11,7 @@
邮箱: - <%= text_field_tag :mail, '', placeholder: '请输入绑定邮箱', maxlength: 40, id: 'email' %> + <%= text_field_tag :mail, params[:mail], placeholder: '请输入绑定邮箱', maxlength: 40, id: 'email' %>

diff --git a/app/views/project_categories/group_list.json.jbuilder b/app/views/project_categories/group_list.json.jbuilder index f9fdb75f..5e0695c1 100644 --- a/app/views/project_categories/group_list.json.jbuilder +++ b/app/views/project_categories/group_list.json.jbuilder @@ -6,7 +6,7 @@ json.array! @category_group_list do |k,v| children_category = @project_children_categories.get_children(v) - json.children do + json.children do json.array! children_category do |cate| json.id cate[0] json.name cate[1] @@ -15,4 +15,4 @@ json.array! @category_group_list do |k,v| end json.id v json.name k.to_s -end \ No newline at end of file +end diff --git a/app/views/projects/_project_detail.json.jbuilder b/app/views/projects/_project_detail.json.jbuilder index d7cd196e..fdbd05df 100644 --- a/app/views/projects/_project_detail.json.jbuilder +++ b/app/views/projects/_project_detail.json.jbuilder @@ -1,10 +1,6 @@ -user = project.owner -if user.blank? - nil -else - json.id project.id +json.id project.id json.repo_id project&.repository&.id -json.identifier project.identifier +json.identifier render_identifier(project) json.name project.name json.description Nokogiri::HTML(project.description).text json.visits project.visits @@ -16,11 +12,22 @@ json.type project&.numerical_for_project_type json.last_update_time render_unix_time(project.updated_on) json.time_ago time_from_now(project.updated_on) json.forked_from_project_id project.forked_from_project_id +json.open_devops project.open_devops? +json.platform project.platform json.author do - json.name user.try(:show_real_name) - json.login user.login - json.image_url url_to_avatar(project.owner) + if project.educoder? + project_educoder = project.project_educoder + json.name project_educoder&.owner + json.login project_educoder&.repo_name.split('/')[0] + json.image_url render_educoder_avatar_url(project.project_educoder) + else + user = project.owner + json.name user.try(:show_real_name) + json.login user.login + json.image_url render_avatar_url(user) + end end + json.category do if project.project_category.blank? json.nil! @@ -37,4 +44,3 @@ json.language do json.name project.project_language.name end end -end diff --git a/app/views/projects/about.json.jbuilder b/app/views/projects/about.json.jbuilder new file mode 100644 index 00000000..72041ca6 --- /dev/null +++ b/app/views/projects/about.json.jbuilder @@ -0,0 +1,5 @@ +json.content @project_detail&.content +json.identifier @project.identifier +json.attachments @attachments do |attach| + json.partial! "attachments/attachment_simple", locals: {attachment: attach} +end diff --git a/app/views/projects/ci_authorize.json.jbuilder b/app/views/projects/ci_authorize.json.jbuilder new file mode 100644 index 00000000..8882d26a --- /dev/null +++ b/app/views/projects/ci_authorize.json.jbuilder @@ -0,0 +1,11 @@ +json.step @user.devops_step +json.cloud_account do + if @cloud_account && !@user.devops_uninit? + json.account @cloud_account.account + json.ip @cloud_account.drone_ip + json.secret @cloud_account.visible_secret + json.redirect_url "#{@cloud_account.drone_url}/login" if @user.devops_unverified? + else + json.nil! + end +end diff --git a/app/views/projects/fork_users.json.jbuilder b/app/views/projects/fork_users.json.jbuilder index 3feb31ed..a539797e 100644 --- a/app/views/projects/fork_users.json.jbuilder +++ b/app/views/projects/fork_users.json.jbuilder @@ -2,10 +2,9 @@ json.count @forks_count json.users do json.array! @fork_users.each do |f| user = f.user - fork_project = Project.select(:id,:name, :identifier).find_by(id: f.fork_project_id) - json.id f.fork_project_id - json.identifier fork_project.identifier - json.name "#{user.try(:show_real_name)}/#{fork_project.try(:name)}" + json.id f.fork_project.id + json.identifier f.fork_project.identifier + json.name "#{user.try(:show_real_name)}/#{f.fork_project.try(:name)}" json.login user.try(:login) json.image_url url_to_avatar(user) json.format_time f.created_at.strftime("%Y-%m-%d") diff --git a/app/views/projects/group_type_list.json.jbuilder b/app/views/projects/group_type_list.json.jbuilder index 4676de89..25592371 100644 --- a/app/views/projects/group_type_list.json.jbuilder +++ b/app/views/projects/group_type_list.json.jbuilder @@ -7,4 +7,4 @@ json.array! @project_group_list do |k,v| json.name k json.id v -end \ No newline at end of file +end diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder index 28b7df1b..5556cfe2 100644 --- a/app/views/projects/index.json.jbuilder +++ b/app/views/projects/index.json.jbuilder @@ -1,4 +1,50 @@ json.total_count @total_count json.projects @projects do |project| - json.partial! "/projects/project_detail", project: project + # json.partial! "/projects/project_detail", project: project + json.id project.id + json.repo_id project&.repository&.id + json.identifier render_identifier(project) + json.name project.name + json.description Nokogiri::HTML(project.description).text + json.visits project.visits + json.praises_count project.praises_count.to_i + json.forked_count project.forked_count.to_i + json.is_public project.is_public + json.mirror_url project.repository&.mirror_url + json.type project&.numerical_for_project_type + json.last_update_time render_unix_time(project.updated_on) + json.time_ago time_from_now(project.updated_on) + json.forked_from_project_id project.forked_from_project_id + json.open_devops project.open_devops? + json.platform project.platform + json.author do + if project.educoder? + project_educoder = project.project_educoder + json.name project_educoder&.owner + json.login project_educoder&.repo_name.split('/')[0] + json.image_url render_educoder_avatar_url(project.project_educoder) + else + user = project.owner + json.name user.try(:show_real_name) + json.login user.login + json.image_url render_avatar_url(user) + end + end + + json.category do + if project.project_category.blank? + json.nil! + else + json.id project.project_category.id + json.name project.project_category.name + end + end + json.language do + if project.project_language.blank? + json.nil! + else + json.id project.project_language.id + json.name project.project_language.name + end + end end diff --git a/app/views/projects/recommend.json.jbuilder b/app/views/projects/recommend.json.jbuilder new file mode 100644 index 00000000..1da5be40 --- /dev/null +++ b/app/views/projects/recommend.json.jbuilder @@ -0,0 +1,22 @@ +json.array! @projects do |project| + owner = project.owner + json.id project.id + json.repo_id project&.repository&.id + json.identifier project.identifier + json.name project.name + json.visits project.visits + json.author do + json.name owner.try(:show_real_name) + json.login owner.login + json.image_url url_to_avatar(owner) + end + + json.category do + if project.project_category.blank? + json.nil! + else + json.id project.project_category.id + json.name project.project_category.name + end + end +end diff --git a/app/views/protected_branches/_protected_branch.json.jbuilder b/app/views/protected_branches/_protected_branch.json.jbuilder new file mode 100644 index 00000000..5f1f0428 --- /dev/null +++ b/app/views/protected_branches/_protected_branch.json.jbuilder @@ -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") diff --git a/app/views/protected_branches/create.json.jbuilder b/app/views/protected_branches/create.json.jbuilder new file mode 100644 index 00000000..5354db7c --- /dev/null +++ b/app/views/protected_branches/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! @protected_branch, as: :protected_branch diff --git a/app/views/protected_branches/edit.json.jbuilder b/app/views/protected_branches/edit.json.jbuilder new file mode 100644 index 00000000..fc5e137d --- /dev/null +++ b/app/views/protected_branches/edit.json.jbuilder @@ -0,0 +1,9 @@ +json.branch_name @branch['name'] +json.protected @branch['protected'] +json.protected_branch do + if @protected_branch + json.partial! @protected_branch, as: :protected_branch + else + json.nil! + end +end diff --git a/app/views/protected_branches/index.json.jbuilder b/app/views/protected_branches/index.json.jbuilder new file mode 100644 index 00000000..eed1eb5a --- /dev/null +++ b/app/views/protected_branches/index.json.jbuilder @@ -0,0 +1,2 @@ +json.total_count @total_count +json.protected_branches @protected_branches, partial: 'protected_branches/protected_branch', as: :protected_branch diff --git a/app/views/protected_branches/show.json.jbuilder b/app/views/protected_branches/show.json.jbuilder new file mode 100644 index 00000000..5354db7c --- /dev/null +++ b/app/views/protected_branches/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! @protected_branch, as: :protected_branch diff --git a/app/views/protected_branches/update.json.jbuilder b/app/views/protected_branches/update.json.jbuilder new file mode 100644 index 00000000..5354db7c --- /dev/null +++ b/app/views/protected_branches/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! @protected_branch, as: :protected_branch diff --git a/app/views/pull_requests/_commit.json.jbuilder b/app/views/pull_requests/_commit.json.jbuilder new file mode 100644 index 00000000..0b7db589 --- /dev/null +++ b/app/views/pull_requests/_commit.json.jbuilder @@ -0,0 +1,14 @@ +json.author do + author = User.find_by(login: commit['Author']['Name']) + json.partial! 'repositories/commit_author', locals: { user: author } +end + +json.committer do + author = User.find_by(login: commit['Committer']['Name']) + json.partial! 'repositories/commit_author', locals: { user: author } +end +json.timestamp render_unix_time(commit['Committer']['When']) +json.time_from_now time_from_now(commit['Committer']['When']) +json.created_at render_format_time_with_date(commit['Committer']['When']) +json.message commit['CommitMessage'] +json.sha commit['Sha'] diff --git a/app/views/pull_requests/_diff_file.json.jbuilder b/app/views/pull_requests/_diff_file.json.jbuilder new file mode 100644 index 00000000..faec9065 --- /dev/null +++ b/app/views/pull_requests/_diff_file.json.jbuilder @@ -0,0 +1,41 @@ +json.sha sha +json.name file['Name'] +json.old_name file['OldName'] +json.index file['Index'] +json.addition file['Addition'] +json.deletion file['Deletion'] +json.type file['Type'] +json.isCreated file['IsCreated'] +json.isDeleted file['IsDeleted'] +json.isBin file['IsBin'] +json.isLFSFile file['IsLFSFile'] +json.isRenamed file['IsRenamed'] +json.isSubmodule file['IsSubmodule'] +json.isLFSFile file['IsLFSFile'] +json.sections do + json.array! file['Sections'] do |section| + json.fileName section['FileName'] + json.name section['Name'] + json.lines do + json.array! section['Lines'] do |line| + json.leftIdx line['LeftIdx'] + json.rightIdx line['RightIdx'] + json.type line['Type'] + json.content line['Content'] + json.sectionInfo do + if line['SectionInfo'].blank? + json.nil! + else + json.path line['SectionInfo']['Path'] + json.lastLeftIdx line['SectionInfo']['LastLeftIdx'] + json.lastRightIdx line['SectionInfo']['LastRightIdx'] + json.leftIdx line['SectionInfo']['LeftIdx'] + json.rightIdx line['SectionInfo']['RightIdx'] + json.leftHunkSize line['SectionInfo']['LeftHunkSize'] + json.rightHunkSize line['SectionInfo']['RightHunkSize'] + end + end + end + end + end +end diff --git a/app/views/pull_requests/commits.json.jbuilder b/app/views/pull_requests/commits.json.jbuilder new file mode 100644 index 00000000..57ffa726 --- /dev/null +++ b/app/views/pull_requests/commits.json.jbuilder @@ -0,0 +1,2 @@ +json.commits_count @commits_result.size +json.commits @commits_result, partial: 'commit', as: :commit diff --git a/app/views/pull_requests/edit.json.jbuilder b/app/views/pull_requests/edit.json.jbuilder index 2e91aa53..c6f41559 100644 --- a/app/views/pull_requests/edit.json.jbuilder +++ b/app/views/pull_requests/edit.json.jbuilder @@ -9,3 +9,6 @@ json.project_login @project.owner.try(:login) json.extract! @pull_request, :id, :title, :body, :milestone,:head,:base,:is_original json.extract! @issue, :assigned_to_id, :fixed_version_id, :priority_id json.issue_tag_ids @issue&.issue_tags_value&.split(",") +json.commits_count @pull_request.commits_count +json.files_count @pull_request.files_count +json.comments_count @pull_request.comments_count diff --git a/app/views/pull_requests/files.json.jbuilder b/app/views/pull_requests/files.json.jbuilder new file mode 100644 index 00000000..b40fe606 --- /dev/null +++ b/app/views/pull_requests/files.json.jbuilder @@ -0,0 +1,4 @@ +json.files_count @files_result['NumFiles'] +json.total_addition @files_result['TotalAddition'] +json.total_deletion @files_result['TotalDeletion'] +json.files @files_result['Files'], partial: 'diff_file', as: :file, locals: {sha: @files_result['LatestSha']} diff --git a/app/views/pull_requests/show.json.jbuilder b/app/views/pull_requests/show.json.jbuilder index b525d543..61bbc915 100644 --- a/app/views/pull_requests/show.json.jbuilder +++ b/app/views/pull_requests/show.json.jbuilder @@ -1,6 +1,9 @@ json.partial! "commons/success" json.project_name @project.name json.pr_time time_from_now(@pull_request.updated_at) +json.commits_count @pull_request.commits_count +json.files_count @pull_request.files_count +json.comments_count @pull_request.comments_count json.pull_request do json.extract! @pull_request, :id,:base, :head, :status,:fork_project_id, :is_original @@ -24,8 +27,3 @@ json.issue do json.version @issue.version.try(:name) json.issue_tags @issue.get_issue_tags end - - - - - diff --git a/app/views/repositories/_author.json.jbuilder b/app/views/repositories/_author.json.jbuilder index 0c2a177c..32692022 100644 --- a/app/views/repositories/_author.json.jbuilder +++ b/app/views/repositories/_author.json.jbuilder @@ -1,5 +1,11 @@ json.author do - json.login user.login - json.name user.real_name - json.image_url url_to_avatar(user) + if @project.forge? + json.login user.login + json.name user.real_name + json.image_url url_to_avatar(user) + else + json.login @project.project_educoder&.repo_name&.split('/')[0] + json.name @project.project_educoder&.owner + json.image_url @project.project_educoder&.image_url + end end diff --git a/app/views/repositories/_commit.json.jbuilder b/app/views/repositories/_commit.json.jbuilder index 88850883..079473b3 100644 --- a/app/views/repositories/_commit.json.jbuilder +++ b/app/views/repositories/_commit.json.jbuilder @@ -1,16 +1,34 @@ -json.commit do - json.sha commit['sha'] - # json.url EduSetting.get('host_name') + commit_repository_path(project.repository, commit['sha']) - json.message commit['commit']['message'] - json.author commit['commit']['author'] - json.committer commit['commit']['committer'] - json.timestamp render_unix_time(commit['commit']['committer']['date']) - json.time_from_now time_from_now(commit['commit']['committer']['date']) +if @project.educoder? + json.commit do + json.sha commit[0]['id'] + json.message commit[0]['title'] + json.author {} + json.committer {} + json.timestamp 0 + json.time_from_now commit[0]['time'] + end + json.author do + {} + # json.partial! '/projects/author', user: render_commit_author(commit['author']) + end + json.committer {} end -json.author do - json.partial! 'commit_author', user: render_commit_author(commit['author']) -end -json.committer do - json.partial! 'commit_author', user: render_commit_author(commit['committer']) +if @project.forge? + json.commit do + json.sha commit['sha'] + # json.url EduSetting.get('host_name') + commit_repository_path(project.repository, commit['sha']) + json.message commit['commit']['message'] + json.author commit['commit']['author'] + json.committer commit['commit']['committer'] + json.timestamp render_unix_time(commit['commit']['committer']['date']) + json.time_from_now time_from_now(commit['commit']['committer']['date']) + end + + json.author do + json.partial! 'commit_author', user: render_commit_author(commit['author']) + end + json.committer do + json.partial! 'commit_author', user: render_commit_author(commit['committer']) + end end diff --git a/app/views/repositories/_last_commit.json.jbuilder b/app/views/repositories/_last_commit.json.jbuilder index 9d6bbe34..3c218463 100644 --- a/app/views/repositories/_last_commit.json.jbuilder +++ b/app/views/repositories/_last_commit.json.jbuilder @@ -1,8 +1,7 @@ -created_at = Time.at(entry['latest_commit']['created_at'].to_i).strftime("%Y-%m-%d %H:%M") json.commit do json.message entry['latest_commit']['message'] json.sha entry['latest_commit']['sha'] - json.created_at created_at - json.time_from_now time_from_now(created_at) + json.created_at render_format_time_with_unix(entry['latest_commit']['created_at'].to_i) + json.time_from_now time_from_now(render_format_time_with_unix(entry['latest_commit']['created_at'].to_i)) json.created_at_unix entry['latest_commit']['created_at'] end diff --git a/app/views/repositories/_simple_entry.json.jbuilder b/app/views/repositories/_simple_entry.json.jbuilder index 4890f404..ab9910dd 100644 --- a/app/views/repositories/_simple_entry.json.jbuilder +++ b/app/views/repositories/_simple_entry.json.jbuilder @@ -1,18 +1,44 @@ -file_name = entry['name'] -file_type = file_name.to_s.split(".").last -direct_download = download_type(file_type) -image_type = image_type?(file_type) -json.name file_name -json.sha entry['sha'] -json.path entry['path'] -json.type entry['type'] -json.size entry['size'] -json.content entry['content'].present? && !direct_download ? render_decode64_content(entry['content']).force_encoding('UTF-8') : "" -json.target entry['target'] -json.download_url entry['download_url'] -json.direct_download direct_download -json.image_type image_type -json.is_readme_file is_readme_type?(file_name) -if entry['latest_commit'] - json.partial! 'last_commit', entry: entry +if @project.forge? + file_name = entry['name'] + file_type = file_name.to_s.split(".").last + direct_download = download_type(file_type) + image_type = image_type?(file_type) + json.name file_name + json.sha entry['sha'] + json.path entry['path'] + json.type entry['type'] + json.size entry['size'] + json.content entry['content'].present? && !direct_download ? render_decode64_content(entry['content']) : "" + json.target entry['target'] + json.download_url entry['download_url'] + json.direct_download direct_download + json.image_type image_type + json.is_readme_file is_readme_type?(file_name) + if entry['latest_commit'] + if entry['type'] != 'file' + json.partial! 'last_commit', entry: entry + else + json.commit nil + end + end +end + +if @project.educoder? + file_path = params[:filepath].present? ? [params[:filepath], entry['name']].join('/') : entry['name'] + + json.name entry['name'] + json.sha nil + json.path file_path + json.type entry['type'] === 'blob'? 'file' : 'dir' + json.size 0 + json.content entry['content'] + json.target nil + json.download_url nil + json.direct_download false + json.image_type false + json.is_readme_file false + if entry['latest_commit'] + # json.partial! 'last_commit', entry: entry + json.partial! 'repositories/simple_entry', locals: { entry: entry } + end end diff --git a/app/views/repositories/commit.json.jbuilder b/app/views/repositories/commit.json.jbuilder index 8901cad3..77f6e3f1 100644 --- a/app/views/repositories/commit.json.jbuilder +++ b/app/views/repositories/commit.json.jbuilder @@ -1,27 +1,11 @@ -json.key_format! camelize: :lower -json.additions @commit['commit_diff']['TotalAddition'] -json.deletions @commit['commit_diff']['TotalDeletion'] -json.sha @commit['sha'] -json.url request.url -json.commit do - @commit['commit'].delete('url') - json.author @commit['commit']['author'] - json.committer @commit['commit']['committer'] - json.message @commit['commit']['message'] - json.tree do - @commit['commit']['tree']['sha'] - end -end -json.author do - json.partial! 'commit_author', user: render_commit_author(@commit['author']) -end -json.committer do - json.partial! 'commit_author', user: render_commit_author(@commit['committer']) -end +# json.key_format! camelize: :lower +json.files_count @commit_diff['NumFiles'] +json.total_addition @commit_diff['TotalAddition'] +json.total_deletion @commit_diff['TotalDeletion'] +json.files @commit_diff['Files'], partial: 'pull_requests/diff_file', as: :file, locals: {sha: @sha} +json.partial! 'commit', commit: @commit, project: @project json.parents @commit['parents'] do |parent| json.sha parent['sha'] - json.url EduSetting.get('host_name') + commit_repository_path(@repo, parent['sha']) + # json.url EduSetting.get('host_name') + commit_repository_path(@repo, parent['sha']) end - -json.files @commit['commit_diff']['Files'] diff --git a/app/views/repositories/entries.json.jbuilder b/app/views/repositories/entries.json.jbuilder index 636845ef..20fecec3 100644 --- a/app/views/repositories/entries.json.jbuilder +++ b/app/views/repositories/entries.json.jbuilder @@ -1,36 +1,71 @@ -json.last_commit do - if @latest_commit - json.partial! 'commit', commit: @latest_commit, project: @project - else - json.nil! +if @project.educoder? + json.last_commit do + if @entries['commits'] + json.partial! 'commit', commit: @entries['commits'], project: @project + else + json.nil! + end end -end -#json.tags_count @tags_count -#json.branches_count @branches_count -#json.commits_count @commits_count -json.zip_url render_zip_url(@project, @ref) -json.tar_url render_tar_url(@project, @ref) -json.entries do - json.array! @entries do |entry| - json.name entry['name'] - json.path entry['path'] - json.sha entry['sha'] - json.type entry['type'] - json.size entry['size'] - content = - if is_readme_type?(entry['name']) - is_readme_file = true - content = Gitea::Repository::Entries::GetService.call(@project_owner, @project.identifier, entry['name'], ref: @ref)['content'] - readme_render_decode64_content(content, @path) - else - is_readme_file = false - entry['content'] + json.commits_count @entries['commit_count'] + json.zip_url @entries['git_url'] + json.tar_url '' + json.entries do + json.array! @entries['trees'] do |entry| + json.name entry['name'] + json.path entry['name'] + json.sha nil + json.type entry['type'] === 'blob'? 'file' : 'dir' + json.size 0 + json.is_readme_file false + json.content nil + json.target nil + json.commit do + json.message entry['title'] + json.time_from_now entry['time'] + json.sha nil + json.created_at_unix nil + json.created_at nil + end + end + end +end + + +if @project.forge? + json.last_commit do + if @latest_commit + json.partial! 'commit', commit: @latest_commit, project: @project + else + json.nil! + end + end + #json.tags_count @tags_count + #json.branches_count @branches_count + #json.commits_count @commits_count + json.zip_url render_zip_url(@project, @ref) + json.tar_url render_tar_url(@project, @ref) + json.entries do + json.array! @entries do |entry| + json.name entry['name'] + json.path entry['path'] + json.sha entry['sha'] + json.type entry['type'] + json.size entry['size'] + content = + if is_readme_type?(entry['name']) + is_readme_file = true + content = Gitea::Repository::Entries::GetService.call(@owner, @project.identifier, entry['name'], ref: @ref)['content'] + readme_render_decode64_content(content, @path) + else + is_readme_file = false + entry['content'] + end + json.is_readme_file is_readme_file + json.content content + json.target entry['target'] + if entry['latest_commit'] + json.partial! 'last_commit', entry: entry end - json.is_readme_file is_readme_file - json.content content - json.target entry['target'] - if entry['latest_commit'] - json.partial! 'last_commit', entry: entry end end end diff --git a/app/views/repositories/show.json.jbuilder b/app/views/repositories/show.json.jbuilder index 539f713a..80e833ed 100644 --- a/app/views/repositories/show.json.jbuilder +++ b/app/views/repositories/show.json.jbuilder @@ -1,10 +1,10 @@ -json.identifier @project.identifier +json.identifier render_identifier(@project) json.name @project.name json.project_id @project.id json.repo_id @repo.id json.issues_count @project.issues_count.to_i - @project.pull_requests_count.to_i json.pull_requests_count @project.pull_requests_count -json.project_identifier @project.identifier +json.project_identifier render_identifier(@project) json.praises_count @project.praises_count.to_i json.forked_count @project.forked_count.to_i json.watchers_count @project.watchers_count.to_i @@ -12,10 +12,11 @@ json.versions_count @project.versions_count #里程碑数量 json.version_releases_count @project.releases_size(@user.try(:id), "all") json.version_releasesed_count @project.releases_size(@user.try(:id), "released") #已发行的版本 json.contributor_users_count @project.contributor_users -json.permission User.current&.admin? ? "Manager" : @project.get_premission(@user) +json.permission render_permission(@user, @project) json.mirror_url @project&.repository.mirror_url json.mirror @project&.repository.mirror_url.present? json.type @project.numerical_for_project_type +json.open_devops @project.open_devops? unless @project.common? json.mirror_status @repo.mirror_status diff --git a/app/views/repositories/sub_entries.json.jbuilder b/app/views/repositories/sub_entries.json.jbuilder index 2032df85..3276ed0d 100644 --- a/app/views/repositories/sub_entries.json.jbuilder +++ b/app/views/repositories/sub_entries.json.jbuilder @@ -1,16 +1,31 @@ +if @project.forge? + json.last_commit do + if @latest_commit + json.partial! 'commit', commit: @latest_commit, project: @project + else + json.nil! + end + end + json.entries do + if @sub_entries.is_a?(Array) + json.partial! 'repositories/simple_entry', collection: @sub_entries, as: :entry + elsif @sub_entries.is_a?(Hash) + json.partial! 'repositories/simple_entry', locals: { entry: @sub_entries } + end + end +end -json.last_commit do - if @latest_commit - json.partial! 'commit', commit: @latest_commit, project: @project - else - json.nil! - end -end -#json.tags_count @tags_count -#json.branches_count @branches_count -#json.commits_count @commits_count -json.entries do - json.array! @sub_entries do |entry| - json.partial! 'repositories/simple_entry', locals: { entry: entry } +if @project.educoder? + json.last_commit do + if @sub_entries['commits'] + json.partial! 'commit', commit: @sub_entries['commits'], project: @project + else + json.nil! + end + end + json.entries do + json.array! @sub_entries['trees'] do |entry| + json.partial! 'repositories/simple_entry', locals: { entry: entry } + end end end diff --git a/app/views/settings/show.json.jbuilder b/app/views/settings/show.json.jbuilder index e471ba52..22e7931f 100644 --- a/app/views/settings/show.json.jbuilder +++ b/app/views/settings/show.json.jbuilder @@ -16,7 +16,6 @@ json.setting do # # json.footer setting.footer || default_setting.footer # - # json.main_site current_laboratory.main_site? # end nav_bar = default_setting.navbar diff --git a/app/views/users/devops.json.jbuilder b/app/views/users/devops.json.jbuilder new file mode 100644 index 00000000..5830720e --- /dev/null +++ b/app/views/users/devops.json.jbuilder @@ -0,0 +1,11 @@ +json.step @user.devops_step +json.cloud_account do + if @cloud_account && !@user.devops_uninit? + json.account @cloud_account.account + json.ip @cloud_account.drone_ip + json.secret @cloud_account.visible_secret + json.authenticate_url @cloud_account.authenticate_url if @user.devops_unverified? + else + json.nil! + end +end diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder index 1c83716b..d9aa4402 100644 --- a/app/views/users/get_user_info.json.jbuilder +++ b/app/views/users/get_user_info.json.jbuilder @@ -12,5 +12,5 @@ json.user_phone_binded @user.phone.present? # json.email @user.mail json.profile_completed @user.profile_completed? json.professional_certification @user.professional_certification - - +json.devops_step @user.devops_step +json.ci_certification @user.ci_certification? diff --git a/app/views/users/projects.json.jbuilder b/app/views/users/projects.json.jbuilder index 822402a2..d00ec68b 100644 --- a/app/views/users/projects.json.jbuilder +++ b/app/views/users/projects.json.jbuilder @@ -1,6 +1,4 @@ json.count @total_count json.projects do - json.array! @projects do |project| - json.partial! "/projects/project_detail", project: project - end + json.partial! '/projects/project_detail', collection: @projects, as: :project end diff --git a/config/application.rb b/config/application.rb index fece76eb..a09b08de 100644 --- a/config/application.rb +++ b/config/application.rb @@ -19,6 +19,8 @@ module Educoderplus # # config.educoder = config_for(:configuration) + # Custom directories with classes and modules you want to be autoloadable. + config.active_record.default_timezone = :utc config.time_zone = 'Beijing' diff --git a/config/database.yml.example b/config/database.yml.example index 42dc3df2..26e752e4 100644 --- a/config/database.yml.example +++ b/config/database.yml.example @@ -19,6 +19,7 @@ default: &default development: <<: *default + host: 127.0.0.1 database: forge_development # Warning: The database defined as "test" will be erased and diff --git a/config/routes.rb b/config/routes.rb index df6eae80..145c20a7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - + require 'sidekiq/web' require 'admin_constraint' @@ -8,8 +8,10 @@ Rails.application.routes.draw do # Serve websocket cable requests in-process mount ActionCable.server => '/cable' + get 'attachments/entries/get_file', to: 'attachments#get_file' get 'attachments/download/:id', to: 'attachments#show' get 'attachments/download/:id/:filename', to: 'attachments#show' + get 'auth/qq/callback', to: 'oauth/qq#create' get 'auth/failure', to: 'oauth/base#auth_failure' get 'auth/cas/callback', to: 'oauth/cas#create' @@ -20,7 +22,26 @@ Rails.application.routes.draw do resources :edu_settings + resources :edu_settings scope '/api' do + namespace :ci do + resources :languages, only: [:index, :show] do + collection do + get :common + end + end + + # resources :repos, only: :index do + # collection do + # get 'get_trustie_pipeline', to: 'builds#get_trustie_pipeline', as: 'get_trustie_pipeline' + # get ':number', to: 'builds#detail', as: 'detail' + # post ':number', to: 'builds#restart', as: 'restart' + # delete ':number', to: 'builds#delete', as: 'delete' + # get ':number/logs/:stage/:step', to: 'builds#logs', as: 'logs' + # end + # end + end + resources :sync_forge, only: [:create] do collection do post :sync_users @@ -31,6 +52,9 @@ Rails.application.routes.draw do resources :compose_projects, only: [:create, :destroy] end resources :attachments do + member do + post :preview_attachment + end collection do delete :destroy_files end @@ -84,6 +108,7 @@ Rails.application.routes.draw do collection do post :migrate get :group_type_list + get :recommend end end @@ -128,10 +153,37 @@ Rails.application.routes.draw do post :sync_salt get :trustie_projects get :trustie_related_projects + + scope '/ci', module: :ci do + scope do + post( + '/cloud_account/bind', + to: 'cloud_accounts#bind', + as: :bind_cloud_acclount + ) + + get( + '/cloud_account', + to: 'cloud_accounts#show', + as: :get_cloud_account + ) + + delete( + '/cloud_account/unbind', + to: 'cloud_accounts#unbind', + as: :unbind_cloud_acclount + ) + + get( + 'oauth_grant', + to: 'cloud_accounts#oauth_grant', + as: :ci_oauth_grant + ) + end + end end scope module: :users do - # resources :courses, only: [:index] # resources :projects, only: [:index] # resources :subjects, only: [:index] resources :project_packages, only: [:index] @@ -249,6 +301,7 @@ Rails.application.routes.draw do get :watchers, to: 'projects#watch_users' get :stargazers, to: 'projects#praise_users' get :members, to: 'projects#fork_users' + match :about, :via => [:get, :put, :post] end end @@ -270,6 +323,34 @@ Rails.application.routes.draw do end end + # protected_branches + scope do + get( + '/protected_branches/', + to: 'protected_branches#index' + ) + get( + '/protected_branches/:branch_name', + to: 'protected_branches#show' + ) + get( + '/protected_branches/:branch_name/edit', + to: 'protected_branches#edit' + ) + delete( + '/protected_branches/:branch_name', + to: 'protected_branches#destroy' + ) + post( + '/protected_branches', + to: 'protected_branches#create' + ) + patch( + '/protected_branches/:branch_name', + to: 'protected_branches#update' + ) + end + resources :issues do collection do get :commit_issues @@ -284,11 +365,18 @@ Rails.application.routes.draw do end end + # compare + resources :compare, only: [:index, :create] + get '/compare/:base...:head' => 'compare#show', :as => 'compare', + :constraints => { base: /.+/, head: /.+/ } + resources :pull_requests, :path => :pulls, except: [:destroy] do member do post :pr_merge # post :check_merge post :refuse_merge + get :files + get :commits end collection do post :check_can_merge @@ -316,6 +404,51 @@ Rails.application.routes.draw do resources :issue_tags, :path => :labels, only: [:create, :edit, :update, :destroy, :index] resources :version_releases, :path => :releases, only: [:index,:new, :create, :edit, :update, :destroy] + scope module: :ci do + scope do + match( + 'ci_authorize', + to: 'projects#authorize', + as: :ci_authorize, + :via => [:get, :put] + ) + get( + 'get_trustie_pipeline', + to: 'projects#get_trustie_pipeline', + as: :get_trustie_pipeline + ) + put( + 'update_trustie_pipeline', + to: 'projects#update_trustie_pipeline', + as: :update_trustie_pipeline + ) + post( + 'activate', + to: 'projects#activate', + as: :ci_activate_project + ) + delete( + 'deactivate', + to: 'projects#deactivate', + as: :ci_deactivate_project + ) + end + + resources :cloud_accounts, only: [:create] do + member do + post :activate + delete :deactivate + end + end + resources :builds, param: :build do + member do + post :restart + delete :stop + get '/logs/:stage/:step', to: 'builds#logs', as: 'logs' + end + end + end + scope module: :projects do scope do get( @@ -560,7 +693,7 @@ Rails.application.routes.draw do post :update_sync_course end - resource :laboratory_setting, only: [:show, :update] + resource :laboratory_setting, only: [:show, :update, :new] resource :laboratory_user, only: [:create, :destroy] resources :carousels, only: [:index, :create, :update, :destroy] do diff --git a/db/migrate/20200609100407_change_issue_token.rb b/db/migrate/20200609100407_change_issue_token.rb new file mode 100644 index 00000000..09608dc2 --- /dev/null +++ b/db/migrate/20200609100407_change_issue_token.rb @@ -0,0 +1,5 @@ +class ChangeIssueToken < ActiveRecord::Migration[5.2] + def change + change_column :issues, :token, :integer, default: 0 + end +end diff --git a/db/migrate/20200610071625_remove_issues_lock_version_column.rb b/db/migrate/20200610071625_remove_issues_lock_version_column.rb index 7e63f8df..7af84cc3 100644 --- a/db/migrate/20200610071625_remove_issues_lock_version_column.rb +++ b/db/migrate/20200610071625_remove_issues_lock_version_column.rb @@ -2,4 +2,4 @@ class RemoveIssuesLockVersionColumn < ActiveRecord::Migration[5.2] def change # remove_column :issues, :lock_version end -end \ No newline at end of file +end diff --git a/db/migrate/20200708114354_create_devops_cloud_accounts.rb b/db/migrate/20200708114354_create_devops_cloud_accounts.rb new file mode 100644 index 00000000..3607968f --- /dev/null +++ b/db/migrate/20200708114354_create_devops_cloud_accounts.rb @@ -0,0 +1,14 @@ +class CreateDevopsCloudAccounts < ActiveRecord::Migration[5.2] + def change + create_table :devops_cloud_accounts do |t| + t.integer :project_id, null: false + t.integer :user_id, null: false + t.integer :ip_num, null: false + t.string :account, null: false + t.string :secret, null: false + + t.timestamps + end + add_index :devops_cloud_accounts, [:project_id, :user_id, :ip_num] + end +end diff --git a/db/migrate/20200709061656_add_gitea_oauth_id_and_project_id_to_oauths.rb b/db/migrate/20200709061656_add_gitea_oauth_id_and_project_id_to_oauths.rb new file mode 100644 index 00000000..6208601b --- /dev/null +++ b/db/migrate/20200709061656_add_gitea_oauth_id_and_project_id_to_oauths.rb @@ -0,0 +1,6 @@ +class AddGiteaOauthIdAndProjectIdToOauths < ActiveRecord::Migration[5.2] + def change + add_column :oauths, :gitea_oauth_id, :integer + add_column :oauths, :project_id, :integer + end +end diff --git a/db/migrate/20200710124116_create_dev_ops_languages.rb b/db/migrate/20200710124116_create_dev_ops_languages.rb new file mode 100644 index 00000000..1a899ad0 --- /dev/null +++ b/db/migrate/20200710124116_create_dev_ops_languages.rb @@ -0,0 +1,11 @@ +class CreateDevOpsLanguages < ActiveRecord::Migration[5.2] + def change + create_table :dev_ops_languages do |t| + t.string :name, null: false, comment: 'The name of project language.' + t.text :content, null: false, comment: 'The content of project language.' + t.integer :usage_amount, default: 0, comment: 'number of people Using the language' + + t.timestamps + end + end +end diff --git a/db/migrate/20200713150706_create_dev_ops_cloud_accounts.rb b/db/migrate/20200713150706_create_dev_ops_cloud_accounts.rb new file mode 100644 index 00000000..3351ab39 --- /dev/null +++ b/db/migrate/20200713150706_create_dev_ops_cloud_accounts.rb @@ -0,0 +1,14 @@ +class CreateDevOpsCloudAccounts < ActiveRecord::Migration[5.2] + def change + create_table :dev_ops_cloud_accounts do |t| + t.integer :project_id, null: false + t.integer :user_id, null: false + t.integer :ip_num + t.string :account + t.string :secret + + t.timestamps + end + add_index :dev_ops_cloud_accounts, [:project_id, :user_id, :ip_num], name: 'dev_ops_cloud_accounts_p_u_ip' + end +end diff --git a/db/migrate/20200714014513_add_cover_id_to_dev_ops_languages.rb b/db/migrate/20200714014513_add_cover_id_to_dev_ops_languages.rb new file mode 100644 index 00000000..6e88bfa2 --- /dev/null +++ b/db/migrate/20200714014513_add_cover_id_to_dev_ops_languages.rb @@ -0,0 +1,5 @@ +class AddCoverIdToDevOpsLanguages < ActiveRecord::Migration[5.2] + def change + add_column :dev_ops_languages, :cover_id, :integer + end +end diff --git a/db/migrate/20200714032759_drop_devops_clound_accounts_table.rb b/db/migrate/20200714032759_drop_devops_clound_accounts_table.rb new file mode 100644 index 00000000..d0bfb6f8 --- /dev/null +++ b/db/migrate/20200714032759_drop_devops_clound_accounts_table.rb @@ -0,0 +1,5 @@ +class DropDevopsCloundAccountsTable < ActiveRecord::Migration[5.2] + def change + drop_table(:devops_cloud_accounts) if ActiveRecord::Base.connection.tables.include?('devops_cloud_accounts') + end +end diff --git a/db/migrate/20200714072948_add_open_devops_to_projects.rb b/db/migrate/20200714072948_add_open_devops_to_projects.rb new file mode 100644 index 00000000..0d189aa5 --- /dev/null +++ b/db/migrate/20200714072948_add_open_devops_to_projects.rb @@ -0,0 +1,5 @@ +class AddOpenDevopsToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :open_devops, :boolean, default: false + end +end diff --git a/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb b/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb new file mode 100644 index 00000000..f777fde2 --- /dev/null +++ b/db/migrate/20200714112206_add_drone_token_to_dev_ops_cloud_accounts.rb @@ -0,0 +1,5 @@ +class AddDroneTokenToDevOpsCloudAccounts < ActiveRecord::Migration[5.2] + def change + add_column :dev_ops_cloud_accounts, :drone_token, :string + end +end diff --git a/db/migrate/20200715075831_add_repository_ref_to_dev_ops_cloud_account.rb b/db/migrate/20200715075831_add_repository_ref_to_dev_ops_cloud_account.rb new file mode 100644 index 00000000..af42232e --- /dev/null +++ b/db/migrate/20200715075831_add_repository_ref_to_dev_ops_cloud_account.rb @@ -0,0 +1,7 @@ +class AddRepositoryRefToDevOpsCloudAccount < ActiveRecord::Migration[5.2] + def change + add_column :dev_ops_cloud_accounts, :repo_id, :integer + + add_index :dev_ops_cloud_accounts, :repo_id, name: 'dev_ops_cloud_accounts_repo_id_ix' + end +end diff --git a/db/migrate/20200731073851_add_devops_step_to_users.rb b/db/migrate/20200731073851_add_devops_step_to_users.rb new file mode 100644 index 00000000..6815b797 --- /dev/null +++ b/db/migrate/20200731073851_add_devops_step_to_users.rb @@ -0,0 +1,5 @@ +class AddDevopsStepToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :devops_step, :integer, default: 0, comment: '0: uninit devops; 1: unverified; 2: verified' + end +end diff --git a/db/migrate/20200813144941_rename_dev_ops_cloud_account_to_ci_cloud_account.rb b/db/migrate/20200813144941_rename_dev_ops_cloud_account_to_ci_cloud_account.rb new file mode 100644 index 00000000..2fcc477a --- /dev/null +++ b/db/migrate/20200813144941_rename_dev_ops_cloud_account_to_ci_cloud_account.rb @@ -0,0 +1,5 @@ +class RenameDevOpsCloudAccountToCiCloudAccount < ActiveRecord::Migration[5.2] + def change + rename_table :dev_ops_cloud_accounts, :ci_cloud_accounts + end +end diff --git a/db/migrate/20200813150315_rename_dev_ops_language_to_ci_language.rb b/db/migrate/20200813150315_rename_dev_ops_language_to_ci_language.rb new file mode 100644 index 00000000..47361838 --- /dev/null +++ b/db/migrate/20200813150315_rename_dev_ops_language_to_ci_language.rb @@ -0,0 +1,5 @@ +class RenameDevOpsLanguageToCiLanguage < ActiveRecord::Migration[5.2] + def change + rename_table :dev_ops_languages, :ci_languages + end +end diff --git a/db/migrate/20200828021007_add_ci_user_id_to_ci_cloud_accounts.rb b/db/migrate/20200828021007_add_ci_user_id_to_ci_cloud_accounts.rb new file mode 100644 index 00000000..6fe4f7a6 --- /dev/null +++ b/db/migrate/20200828021007_add_ci_user_id_to_ci_cloud_accounts.rb @@ -0,0 +1,5 @@ +class AddCiUserIdToCiCloudAccounts < ActiveRecord::Migration[5.2] + def change + add_column :ci_cloud_accounts, :ci_user_id, :integer + end +end diff --git a/db/migrate/20200828022021_remove_project_id_from_ci_cloud_accounts.rb b/db/migrate/20200828022021_remove_project_id_from_ci_cloud_accounts.rb new file mode 100644 index 00000000..580083bf --- /dev/null +++ b/db/migrate/20200828022021_remove_project_id_from_ci_cloud_accounts.rb @@ -0,0 +1,7 @@ +class RemoveProjectIdFromCiCloudAccounts < ActiveRecord::Migration[5.2] + def change + remove_column :ci_cloud_accounts, :project_id + remove_column :ci_cloud_accounts, :repo_id + remove_column :ci_cloud_accounts, :drone_token + end +end diff --git a/db/migrate/20200904074907_add_gitea_webhook_id_to_projects.rb b/db/migrate/20200904074907_add_gitea_webhook_id_to_projects.rb new file mode 100644 index 00000000..35ba3e28 --- /dev/null +++ b/db/migrate/20200904074907_add_gitea_webhook_id_to_projects.rb @@ -0,0 +1,5 @@ +class AddGiteaWebhookIdToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :gitea_webhook_id, :integer + end +end diff --git a/db/migrate/20200925090122_add_open_devops_count_to_projects.rb b/db/migrate/20200925090122_add_open_devops_count_to_projects.rb new file mode 100644 index 00000000..9150b267 --- /dev/null +++ b/db/migrate/20200925090122_add_open_devops_count_to_projects.rb @@ -0,0 +1,5 @@ +class AddOpenDevopsCountToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :open_devops_count, :integer, default: 0, comment: '针对同一台ci服务器激活devops流程的次数' + end +end diff --git a/db/migrate/20200927023922_reset_versions_count.rb b/db/migrate/20200927023922_reset_versions_count.rb new file mode 100644 index 00000000..2c121e62 --- /dev/null +++ b/db/migrate/20200927023922_reset_versions_count.rb @@ -0,0 +1,17 @@ +class ResetVersionsCount < ActiveRecord::Migration[5.2] + def change + execute "ALTER TABLE licenses MODIFY COLUMN id INT AUTO_INCREMENT;" + versions = Version.includes(:issues).select(:id, :closed_issues_count, :percent,:issues_count) + versions.each do |v| + Version.reset_counters v.id, :issues + closed_issues = Issue.select(:id, :fixed_version_id, :status_id).where(fixed_version_id: v.id, status_id: 5).size + unless v.closed_issues_count.to_i == closed_issues + percent = v.issues_count.to_i <=0 ? 0.0 : (closed_issues.to_f / v.issues_count.to_i) + v.closed_issues_count = closed_issues + v.percent = percent + v.save + end + puts v.id + end + end +end diff --git a/db/migrate/20200929062837_add_index_to_users_type.rb b/db/migrate/20200929062837_add_index_to_users_type.rb new file mode 100644 index 00000000..d27ca9dd --- /dev/null +++ b/db/migrate/20200929062837_add_index_to_users_type.rb @@ -0,0 +1,5 @@ +class AddIndexToUsersType < ActiveRecord::Migration[5.2] + def change + add_index :users, :type + end +end diff --git a/db/migrate/20201004034434_add_recommend_to_projects.rb b/db/migrate/20201004034434_add_recommend_to_projects.rb new file mode 100644 index 00000000..d00b3eb6 --- /dev/null +++ b/db/migrate/20201004034434_add_recommend_to_projects.rb @@ -0,0 +1,5 @@ +class AddRecommendToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :recommend, :boolean, default: false + end +end diff --git a/db/migrate/20201004070431_create_project_details.rb b/db/migrate/20201004070431_create_project_details.rb new file mode 100644 index 00000000..09b63bd6 --- /dev/null +++ b/db/migrate/20201004070431_create_project_details.rb @@ -0,0 +1,12 @@ +class CreateProjectDetails < ActiveRecord::Migration[5.2] + def change + create_table :project_details do |t| + t.integer :project_id + t.longtext :content + + t.timestamps + end + + add_index :project_details, :project_id + end +end diff --git a/db/migrate/20201019082617_add_platform_to_projects.rb b/db/migrate/20201019082617_add_platform_to_projects.rb new file mode 100644 index 00000000..0301a13c --- /dev/null +++ b/db/migrate/20201019082617_add_platform_to_projects.rb @@ -0,0 +1,5 @@ +class AddPlatformToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :platform, :integer, default: 0 + end +end diff --git a/db/migrate/20201019104433_create_project_educoders.rb b/db/migrate/20201019104433_create_project_educoders.rb new file mode 100644 index 00000000..e80d9711 --- /dev/null +++ b/db/migrate/20201019104433_create_project_educoders.rb @@ -0,0 +1,12 @@ +class CreateProjectEducoders < ActiveRecord::Migration[5.2] + def change + create_table :project_educoders do |t| + t.string :owner + t.string :repo_name + t.string :image_url + t.integer :project_id + + t.timestamps + end + end +end diff --git a/db/migrate/20201020071758_change_description_from_projects.rb b/db/migrate/20201020071758_change_description_from_projects.rb new file mode 100644 index 00000000..9c4e3350 --- /dev/null +++ b/db/migrate/20201020071758_change_description_from_projects.rb @@ -0,0 +1,5 @@ +class ChangeDescriptionFromProjects < ActiveRecord::Migration[5.2] + def change + change_column :projects, :description, :longtext + end +end diff --git a/db/migrate/20201020083709_add_index_to_projects.rb b/db/migrate/20201020083709_add_index_to_projects.rb new file mode 100644 index 00000000..b968a17c --- /dev/null +++ b/db/migrate/20201020083709_add_index_to_projects.rb @@ -0,0 +1,5 @@ +class AddIndexToProjects < ActiveRecord::Migration[5.2] + def change + add_index :projects, :identifier, name: 'index_projects_on_identifier' + end +end diff --git a/db/migrate/20201020093834_add_forked_count_and_commit_count_to_project_educoders.rb b/db/migrate/20201020093834_add_forked_count_and_commit_count_to_project_educoders.rb new file mode 100644 index 00000000..d49b1e39 --- /dev/null +++ b/db/migrate/20201020093834_add_forked_count_and_commit_count_to_project_educoders.rb @@ -0,0 +1,6 @@ +class AddForkedCountAndCommitCountToProjectEducoders < ActiveRecord::Migration[5.2] + def change + add_column :project_educoders, :commit_count, :integer, default: 0 + add_column :project_educoders, :forked_count, :integer, default: 0 + end +end diff --git a/db/migrate/20201021031915_create_project_statistics.rb b/db/migrate/20201021031915_create_project_statistics.rb new file mode 100644 index 00000000..c266816d --- /dev/null +++ b/db/migrate/20201021031915_create_project_statistics.rb @@ -0,0 +1,12 @@ +class CreateProjectStatistics < ActiveRecord::Migration[5.2] + def change + create_table :project_statistics do |t| + t.integer :common_projects_count, :default => 0 + t.integer :mirror_projects_count, :default => 0 + t.integer :sync_mirror_projects_count, :default => 0 + t.integer :commits_total_count, :default => 0 + + t.timestamps + end + end +end diff --git a/db/migrate/20201021033117_add_index_for_project_type_to_projects.rb b/db/migrate/20201021033117_add_index_for_project_type_to_projects.rb new file mode 100644 index 00000000..f86edc38 --- /dev/null +++ b/db/migrate/20201021033117_add_index_for_project_type_to_projects.rb @@ -0,0 +1,5 @@ +class AddIndexForProjectTypeToProjects < ActiveRecord::Migration[5.2] + def change + add_index :projects, :project_type + end +end diff --git a/db/migrate/20201021041202_add_index_for_updated_on_to_projects.rb b/db/migrate/20201021041202_add_index_for_updated_on_to_projects.rb new file mode 100644 index 00000000..43c223a6 --- /dev/null +++ b/db/migrate/20201021041202_add_index_for_updated_on_to_projects.rb @@ -0,0 +1,5 @@ +class AddIndexForUpdatedOnToProjects < ActiveRecord::Migration[5.2] + def change + add_index :projects, :updated_on + end +end diff --git a/db/migrate/20201021070524_add_some_index_to_projects.rb b/db/migrate/20201021070524_add_some_index_to_projects.rb new file mode 100644 index 00000000..47a3c2fd --- /dev/null +++ b/db/migrate/20201021070524_add_some_index_to_projects.rb @@ -0,0 +1,11 @@ +class AddSomeIndexToProjects < ActiveRecord::Migration[5.2] + def change + add_index :projects, :project_category_id + add_index :projects, :project_language_id + add_index :projects, :is_public + add_index :projects, :status + add_index :projects, :forked_from_project_id + add_index :projects, :recommend + add_index :projects, :platform + end +end diff --git a/db/migrate/20201021080638_add_user_id_index_to_projects.rb b/db/migrate/20201021080638_add_user_id_index_to_projects.rb new file mode 100644 index 00000000..63edfbbc --- /dev/null +++ b/db/migrate/20201021080638_add_user_id_index_to_projects.rb @@ -0,0 +1,6 @@ +class AddUserIdIndexToProjects < ActiveRecord::Migration[5.2] + def change + add_index :projects, :user_id + add_index :projects, :name + end +end diff --git a/db/migrate/20201022164823_add_index_for_project_id_to_project_educoders.rb b/db/migrate/20201022164823_add_index_for_project_id_to_project_educoders.rb new file mode 100644 index 00000000..232c8055 --- /dev/null +++ b/db/migrate/20201022164823_add_index_for_project_id_to_project_educoders.rb @@ -0,0 +1,6 @@ +class AddIndexForProjectIdToProjectEducoders < ActiveRecord::Migration[5.2] + def change + add_index :project_educoders, :repo_name + add_index :project_educoders, :project_id + end +end diff --git a/db/migrate/20201023025821_remove_index_from_projects.rb b/db/migrate/20201023025821_remove_index_from_projects.rb new file mode 100644 index 00000000..783b9587 --- /dev/null +++ b/db/migrate/20201023025821_remove_index_from_projects.rb @@ -0,0 +1,7 @@ +class RemoveIndexFromProjects < ActiveRecord::Migration[5.2] + def change + remove_index :projects, :project_language_id + remove_index :projects, :project_category_id + remove_index :projects, :user_id + end +end diff --git a/db/migrate/20201104034658_add_commits_count_and_files_count_to_pull_requests.rb b/db/migrate/20201104034658_add_commits_count_and_files_count_to_pull_requests.rb new file mode 100644 index 00000000..f84da29f --- /dev/null +++ b/db/migrate/20201104034658_add_commits_count_and_files_count_to_pull_requests.rb @@ -0,0 +1,7 @@ +class AddCommitsCountAndFilesCountToPullRequests < ActiveRecord::Migration[5.2] + def change + add_column :pull_requests, :comments_count, :integer, default: 0, comment: 'number of comments for pull request' + add_column :pull_requests, :commits_count, :integer, default: 0, comment: 'number of git commits for pull request' + add_column :pull_requests, :files_count, :integer, default: 0, comment: 'number of git change files for pull request' + end +end diff --git a/db/migrate/20201130081039_create_protected_branches.rb b/db/migrate/20201130081039_create_protected_branches.rb new file mode 100644 index 00000000..26ce2b1b --- /dev/null +++ b/db/migrate/20201130081039_create_protected_branches.rb @@ -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 diff --git a/db/seeds.rb b/db/seeds.rb index 87915959..93bb8f7d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -35,4 +35,4 @@ # projects = Project.where(project_language_id: [nil, ""]) # projects.each_with_index do |p,index| # p.update_attribute(:project_language_id, lan_ids[index]) -# end \ No newline at end of file +# end diff --git a/deploy.md b/deploy.md new file mode 100644 index 00000000..ae644121 --- /dev/null +++ b/deploy.md @@ -0,0 +1,95 @@ + +# 本地开发部署 + +## Depends Versions + +* Ruby 2.4.5 + +* Rails ~> 5.2 + +* MySql ~> 5.6 + +* Redis 5+ + + +## Steps + +### 1. 安装依赖包 + +```bash +bundle install +``` + +### 2. 配置初始化文件 +进入项目根目录执行一下命令: + +```bash +cp config/configuration.yml.example config/configuration.yml +cp config/database.yml.example config/database.yml +touch config/redis.yml +touch config/elasticsearch.yml +``` + +### 3. 配置gitea服务(可选) +**如需要部署自己的gitea平台,请参考gitea官方平台:https://docs.gitea.io/zh-cn/install-from-binary/** + +**因目前gitea平台api受限,暂时推荐从forge平台获取gitea部署文件进行部署:https://forgeplus.trustie.net/projects/jasder/gitea-binary** + +#### 配置gitea服务步骤 +1. 部署gitea服务,并注册root账户 +2. 修改forge平台的 config/configuration.yml中的gitea服务指向地址,如: + +```ruby +gitea: + access_key_id: 'root' + access_key_secret: 'password' + domain: 'http://www.gitea.example.com' + base_url: '/api/v1' +``` + +### 4. 安装redis环境 +**请自行搜索各平台如何安装部署redis环境** + + +### 5. 创建数据库 + +```bash +rails db:create +``` + +### 6. 导入数据表结构 + +```bash +bundle exec rake sync_table_structure:import_csv +``` + +### 7. 执行migrate迁移文件 +**开发环境为development, 生成环境为production** +```bash +rails db:migrate RAILS_ENV=development +``` + +### 8. 启动redis(此处已mac系统为例) +```bash +redis-server& +``` + +### 9. 启动sidekiq +**开发环境为development, 生成环境为production** +```bash +bundle exec sidekiq -C config/sidekiq.yml -e production -d +``` + +### 10. 启动rails服务 +```bash +rails s +``` + +### 11. 浏览器访问 +在浏览器中输入如下地址访问: +```bash +http://localhost:3000/ +``` + + +--- diff --git a/deployment.md b/deployment.md new file mode 100644 index 00000000..e8e510f3 --- /dev/null +++ b/deployment.md @@ -0,0 +1,2004 @@ + +# 本地开发部署步骤 + +#### 1. 安装依赖包 + +```bash +bundle install +``` + +#### 2. 配置初始化文件 +进入项目根目录执行一下命令: + +```bash +cp config/configuration.yml.example config/configuration.yml +cp config/database.yml.example config/database.yml +touch config/redis.yml +touch config/elasticsearch.yml +``` + +#### 3. 创建数据库 + +```bash +rails db:create +``` + +#### 4. 导入数据表结构 + +```bash +bundle exec rake sync_table_structure:import_csv +``` + +#### 5. 执行migrate迁移文件 +```bash +rails db:migrate RAILS_ENV=development +``` + +#### 6. 启动rails服务 +```bash +rails s +``` + +#### 7. 浏览器访问 +在浏览器中输入如下地址访问: +```bash +http://localhost:3000/projects +``` + +--- + + +# API文档 + +## 基本介绍 + +开发API服务地址: + +https://testgitea.trustie.net/ + + +响应状态说明: + +|字段|类型|说明| +|-|-|-| +|status |int |响应状态码,0:请求成功,-1: 请求失败| +|message |string |响应说明 | + + +### API接口 +--- + +#### 用户注册(通过其他平台) +``` +POST accounts/remote_register +``` +*示例* +``` +curl -X POST \ +-d "email=2456233122@qq.com" \ +-d "password=djs_D_00001" \ +-d "username=16895620" \ +-d "platform=forge" \ +http://localhost:3000/api/accounts/remote_register | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|email |是|string |邮箱 | +|username |是|string |登录名 | +|password |是|string |秘密 | +|platform |否|string |用户来源的相关平台,取值范围['educoder', 'trustie', 'forge'], 默认值为forge | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|user|json object |返回数据| +|-- id |int |用户id | +|-- token |string|用户token| + + +返回值 +``` +{ + "status": 0, + "message": "success", + "user": { + "id": 36400, + "token": "8c87a80d9cfacc92fcb2451845104f35119eda96" + } +} +``` +--- + +#### 获取当前登录用户信息 +``` +GET api/users/me +``` +*示例* +``` +curl -X GET http://localhost:3000/api/users/me | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|user_id |int |用户id | +|username |string|用户名称| +|admin |boolean|是否为管理用户| +|login |string|登录名| +|image_url |string|用户头像| + + +返回值 +``` +{ + "username": "18816895620", + "login": "18816895620", + "user_id": 36401, + "image_url": "avatars/User/b", + "admin": false +} +``` +--- + +#### 用户列表(带搜索功能) +``` +GET api/users/list +``` +*示例* +``` +curl -X GET \ +-d "limit=10" \ +-d "search=18816895620" +http://localhost:3000/api/users/list | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|page |否|int |页数,第几页 | +|limit |否|int |每页多少条数据,默认15条 | +|search |否|string |用户名、登录名匹配搜索 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |总用户条数 | +|users |array| | +|-- username |string|用户全名| +|-- login |string|用户登录名| +|-- user_id |int|用户id| +|-- image_url |string|用户头像| + +返回值 +``` +{ + "total_count": 1, + "users": [ + { + "username": "18816895620", + "login": "18816895620", + "user_id": 36401, + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +#### 获取项目类别列表(可根据名称搜素) +``` +GET api/project_categories +``` +*示例* +``` +curl -X GET \ +-d "name=大数据" \ +http://localhost:3000/api/project_categories/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |类别名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_categories|array |返回数据| +|-- id |int |类别id | +|-- name |string|类别名称| + + +返回值 +``` +{ + "project_categories": [ + { + "id": 1, + "name": "大数据" + } + ] +} +``` +--- + +#### 获取项目语言列表(可根据名称搜素) +``` +GET api/project_languages +``` +*示例* +``` +curl -X GET \ +-d "name=Ruby" \ +http://localhost:3000/api/project_languages/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |类别名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_languages|array |返回数据| +|-- id |int |语言id | +|-- name |string|语言名称| + + +返回值 +``` +{ + "project_languages": [ + { + "id": 1, + "name": "Ruby" + } + ] +} +``` +--- + +#### 获取.gitignore模板列表(可根据名称搜素) +``` +GET api/ignores +``` +*示例* +``` +curl -X GET \ +-d "name=Ada" \ +http://localhost:3000/api/ignores/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |gitignore名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|ignores|array |返回数据| +|-- id |int |id | +|-- name |string|gitignore名称| + + +返回值 +``` +{ + "ignores": [ + { + "id": 1, + "name": "Ada" + } + ] +} +``` +--- + +#### 获取开源许可证列表(可根据名称搜素) +``` +GET api/licenses +``` +*示例* +``` +curl -X GET \ +-d "name=AFL" \ +http://localhost:3000/api/licenses/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|name |否|string |开源许可证名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|licenses|array |返回数据| +|-- id |int |id | +|-- name |string|开源许可证名称| + + +返回值 +``` +{ + "licenses": [ + { + "id": 57, + "name": "AFL-1.2" + }, + { + "id": 76, + "name": "AFL-3.0" + }, + { + "id": 214, + "name": "AFL-1.1" + }, + { + "id": 326, + "name": "AFL-2.1" + }, + { + "id": 350, + "name": "AFL-2.0" + } + ] +} +``` +--- + +#### 创建项目 +``` +POST api/projects +``` +*示例* +``` +curl -X POST \ +-d "user_id=36401" \ +-d "name=hnfl_demo" \ +-d "description=my first project" \ +-d "repository_name=hnfl_demo" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +-d "ignore_id=2" \ +-d "license_id=1" \ +http://localhost:3000/api/projects/ | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|user_id |是|int |用户id或者组织id | +|name |是|string |项目名称 | +|description |是|string |项目描述 | +|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|project_category_id|是|int |项目类别id | +|project_language_id|是|int |项目语言id | +|ignore_id |否|int |gitignore相关id | +|license_id |否|int |开源许可证id | +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| + + +返回值 +``` +{ + "id": 3240, + "name": "好项目" +} +``` +--- + +#### 新建镜像项目 +``` +POST api/projects/migrate +``` +*示例* +``` +curl -X POST \ +-d "user_id=36401" \ +-d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ +-d "name=golden" \ +-d "description=golden" \ +-d "repository_name=golden" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +http://localhost:3000/api/projects/migrate | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|user_id |是|int |用户id或者组织id | +|name |是|string |项目名称 | +|clone_addr |是|string |镜像项目clone地址 | +|description |否|string |项目描述 | +|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | +|project_category_id|是|int |项目类别id | +|project_language_id|是|int |项目语言id | +|private |否|boolean|项目是否私有, true:为私有,false: 非私有,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| + + +返回值 +``` +{ + "id": 3263, + "name": "ni项目" +} +``` +--- + +#### 项目详情 +``` +GET api/projects/:id +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/3263 | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|项目名称| +|identifier |string|项目标识| +|is_public |boolean|项目是否公开, true:公开,false:私有| +|description |string|项目简介| +|repo_id |int|仓库id| +|repo_identifier|string|仓库标识| + + +返回值 +``` +{ + "name": "ni项目", + "identifier": "mirror_demo", + "is_public": true, + "description": "my first project mirror_demo", + "repo_id": 75073, + "repo_identifier": "mirror_demo" +} +``` +--- + +#### 编辑仓库信息 +``` +GET /api/:login/:repo_identifier/edit.json +``` +*示例* +``` +curl -X GET http://localhost:3000/api/18816895620/mirror_demo/edit.json | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string |仓库标识 | +|project_id |int|项目id| +|project_name |string|项目名称| +|project_identifier |string|项目标识| +|project_description |string|项目简介| +|project_category_id |int|项目类别id| +|project_language_id |int|项目语言id| +|private |boolean|项目是否私有, true:为私有,false: 公开 | + + +返回值 +``` +{ + "identifier": "mirror_demo", + "project_id": 3263, + "project_name": "ni项目", + "project_identifier": "mirror_demo", + "project_description": "my first project mirror_demo", + "project_category_id": 1, + "project_language_id": 2, + "private": false +} +``` +--- + +#### 修改项目信息 +``` +PATCH api/projects/:id +``` +*示例* +``` +curl -X PATCH \ +-d "name=hnfl_demo" \ +-d "description=my first project" \ +-d "project_category_id=1" \ +-d "project_language_id=2" \ +-d "private=true" \ +http://localhost:3000/api/projects/3263.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|name |否|string |项目名称 | +|description |否|string |项目描述 | +|project_category_id|否|int |项目类别id | +|project_language_id|否|int |项目语言id | +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int|id | +|identifier |string|项目标识| +|name |string|项目名称| +|description |string|项目简介| +|project_category_id|int|项目类别id| +|project_language_id|int|项目语言id| +|private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | + + +返回值 +``` +{ + "id": 3263, + "identifier": "mirror_demo", + "name": "hnfl_demo", + "description": "my first project", + "project_category_id": 1, + "project_language_id": 2, + "is_public": true +} +``` +--- + +#### 删除项目 +``` +DELETE api/projects/:id +``` +*示例* +``` +curl -X DELETE http://localhost:3000/api/projects/3263.json | jq +``` + +注:只有超级管理员和项目拥有者才能删除仓库 + +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|返回状态, 0: 表示操作成功 | +|message |string|返回信息说明| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 项目添加成员 +``` +POST api/projects/:id/members +``` +*示例* +``` +curl -X POST \ +-d "user_id=36406" \ +http://localhost:3000/api/projects/3297/members | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:添加成功, -1: 添加失败, 1: 表示已经是项目成员 | +|message |string|返回信息说明| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 项目删除成员 +``` +DELETE api/projects/:id/members/remove +``` +*示例* +``` +curl -X DELETE \ +-d "user_id=36400" \ +http://localhost:3000/api/projects/3263/members/remove | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:移除成功, -1: 移除失败, 1: 表示还不是项目成员 | +|message |string|返回信息说明| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +#### 更改项目成员角色/权限 +``` +PUT api/projects/:id/members/change_role +``` +*示例* +``` +curl -X PUT \ +-d "user_id=36400" \ +-d "role=Developer" \ +http://localhost:3000/api/projects/3263/members/change_role | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|user_id |是|int |用户id | +|role |是|string |取值范围:"Manager", "Developer", "Reporter";分别为项目管理人员(拥有所有操作权限)、项目开发人员(只拥有读写权限)、项目报告人员(只拥有读权限) | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int |0:角色更改成功, -1: 更改失败失败, 1: 表示还不是项目成员 | +|message |string|返回信息说明| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + + +#### 项目成员列表 +``` +GET api/projects/:id/members +``` +*示例* +``` +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects/3263/members | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |返回记录总条数 | +|members |array|项目成员信息| +|-- id |int|用户id| +|-- name |string|用户名称| +|-- login |string|用户登录名/标识| +|-- image_url |string|用户头像| +|-- is_owner |boolean|是否是项目的拥有者,true:是, false:不是| +|-- role |string|该用户在项目中的角色, Manager: 管理员(拥有操作权限); Developer:开发人员(只拥有读写权限); Reporter:报告人员(只拥有读权限)| + + +返回值 +``` +{ + "total_count": 2, + "members": [ + { + "id": 36401, + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b", + "is_owner": true, + "role": "Manager" + }, + { + "id": 36399, + "name": "18816365620", + "login": "18816365620", + "image_url": "avatars/User/b", + "is_owner": false, + "role": "Developer" + } + ] +} +``` +--- + +#### Fork项目 +``` +POST /api/projects/:project_id/forks +``` +*示例* +``` +curl -X POST http://localhost:3000/api/projects/3297/forks | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|project_id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |项目id | +|identifier |string|项目标识| + + +返回值 +``` +{ + "id": 3290, + "identifier": "newadm" +} +``` +--- + +#### 获取代码目录列表 +``` +POST api/:login/:repo_identifier/entries +``` +*示例* +``` +curl -X GET \ +-d "ref=develop" \ +http://localhost:3000/api/18816895620/mirror_demo/entries | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|文件夹或文件名称| +|path |string|文件夹或文件相对路径| +|type |string|文件类型, file:文件,dir:文件目录| +|size |int|文件夹或文件大小 单位B| +|content |string|文件内容,| +|target |string|标签| + +返回值 +``` +[ + { + "name": "Manual", + "path": "Manual", + "sha": "c2f18765235076b4c835b3e31262b3ee65176a75", + "type": "file", + "size": 12579, + "content": null, + "target": null, + "commit": null + }, + { + "name": "README", + "path": "README", + "sha": "91a29176828eba5c5598f5d4a95458e861f271ec", + "type": "file", + "size": 1767, + "content": null, + "target": null, + "commit": null + }, + { + "name": "base", + "path": "base", + "sha": "7adbe5698e02dba062216333d5e1d16b36ae1cbd", + "type": "dir", + "size": 0, + "content": null, + "target": null, + "commit": null + } +] +``` +--- + +#### 获取子目录代码列表/编辑某个具体的文件 +``` +GET api/:login/:repo_identifier/sub_entries +``` +*示例* +``` +curl -X GET \ +-d "ref=master" \ +-d "filepath=test1_create_file.rb" \ +http://localhost:3000/api/18816895620/mirror_demo/sub_entries | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件夹、文件的相对路径 | +|ref |否|string |分支名称、tag名称或是提交记录id,默认为master分支 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |id | +|name |string|文件夹或文件名称| +|path |string|文件夹或文件相对路径| +|type |string|文件类型, file:文件,dir:文件目录| +|size |int|文件夹或文件大小 单位KB| +|content |string|文件内容,| +|target |string|标签| +|url |string|文件访问链接,带分支| +|html_url |string|文件访问链接,未标识分支| +|git_url |string|文件夹或文件的git仓库访问链接| +|download_url |string|文件下载、文件内容访问链接| + +返回值 +``` +[ + { + "name": "build.rc", + "path": "lib/build.rc", + "type": "", + "size": 1268, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/build.rc?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/build.rc", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/191fcf1a63b3777e2977fcede7dd5309efdd70fe", + "download_url": null + }, + { + "name": "cfg.rc", + "path": "lib/cfg.rc", + "type": "file", + "size": 107, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/cfg.rc?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/cfg.rc", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/0b91ba0ed1c00e130c77bb9058af3787fea986a0", + "download_url": "http://localhost:3003/18816895620/mirror_demo/raw/branch/master/lib/cfg.rc" + }, + { + "name": "fn", + "path": "lib/fn", + "type": "dir", + "size": 0, + "content": null, + "target": null, + "url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/contents/lib/fn?ref=master", + "html_url": "http://localhost:3003/18816895620/mirror_demo/src/branch/master/lib/fn", + "git_url": "http://localhost:3003/api/v1/repos/18816895620/mirror_demo/git/blobs/e33bd45949ef8f804471d0b6b2c59728eb445989", + "download_url": null + } +] +``` +--- + +#### 项目类别列表(用于项目列表左侧导航中的项目类别列表) +``` +GET api/project_categories/group_list +``` +*示例* +``` +curl -X GET http://localhost:3000/api/project_categories/group_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|id |int |项目分类id | +|name |string|项目分类名称| +|projects_count |int |项目数量| + + +返回值 +``` +[ + { + "id": 1, + "name": "大数据", + "projects_count": 30 + }, + { + "id": 2, + "name": "机器学习", + "projects_count": 1 + }, + { + "id": 3, + "name": "深度学习", + "projects_count": 1 + } +] +``` +--- + +#### 项目类型列表(用于项目列表左侧导航上方中的项目类型列表) +``` +GET api/projects/group_type_list +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/group_type_list | jq +``` + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|project_type |string|项目类型 | +|name |string|项目类型名称| +|projects_count |int |项目数量| + + +返回值 +``` +[ + { + "project_type": "common", + "name": "开源托管项目", + "projects_count": 2106 + }, + { + "project_type": "mirror", + "name": "开源镜像项目", + "projects_count": 1 + } +] +``` +--- + +#### 项目列表 +``` +GET api/projects +``` +*示例* +``` +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | +|sort_by |否|string |排序类型, 取值:updated_on \| created_on \| forked_count \| praises_count, updated_on: 更新时间排序,created_on: 创建时间排序,forked_count: fork数据排序,praises_count: 点赞数量排序,默认为updated_on更新时间排序 | +|sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为:desc | +|search |否|string |按照项目名称搜索 | +|category_id |否|int |项目类别id | +|language_id |否|int |项目语言id | +|project_type |否|string |项目类型, 取值为:common \| mirror; common:开源托管项目, mirror:开源镜像项目 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int |项目总条数 | +|id |string |项目id | +|name |string|项目名称| +|description |string|项目简介| +|visits |int|流量数| +|forked_count |int|被fork的数量| +|praises_count |int|star数量| +|is_public |boolean|是否公开, true:公开,false:未公开| +|mirror_url |string|镜像url| +|last_update_time|int|最后更新时间,为UNIX格式的时间戳| +|author |object|项目创建者| +|-- name |string|用户名,也是用户标识| +|category |object|项目类别| +|-- id |int|项目类型id| +|-- name |string|项目类型名称| +|language |object|项目语言| +|-- id |int|项目语言id| +|-- name |string|项目语言名称| + + +返回值 +``` +{ + "total_count": 3096, + "projects": [ + { + "id": 1, + "name": "hnfl_demo1", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577697461, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 2, + "name": "hnfl_demo", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577697403, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 3, + "name": "统计局", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577415173, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 5, + "name": "开源同名", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": false, + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "last_update_time": 1577346228, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + }, + { + "id": 7, + "name": "开源支持", + "description": "my first project", + "visits": 0, + "praises_count": 0, + "forked_count": 0, + "is_public": true, + "mirror_url": null, + "last_update_time": 1577341572, + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + }, + "category": { + "id": 1, + "name": "大数据" + }, + "language": { + "id": 2, + "name": "C" + } + } + ] +} +``` +--- + +### 获取分支列表 +``` +GET /api/projects/:identifier/branches +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/mirror_demo/branches | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|identifier |是|string |项目标识 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|分支名称| +|user_can_push |boolean|用户是否可push| +|user_can_merge |boolean|用户是否客merge| +|protected |boolean|是否为保护分支| +|http_url |boolean|http链接| +|zip_url |boolean|zip包下载链接| +|tar_url |boolean|tar.gz下载链接| +|last_commit |object|最后提交记录| +|-- id |string|提交记录id| +|-- message |string|提交的说明信息| +|-- timestamp |int|提交时间,为UNIX时间戳| +|-- time_from_now|string|转换后的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +``` +[ + { + "name": "develop", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", + "last_commit": { + "id": "735674d6696bddbafa993db9c67b40c41246c77f", + "message": "FIX test branch content\n", + "timestamp": 1577694074, + "time_from_now": "1天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "name": "master", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", + "last_commit": { + "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", + "timestamp": 1577244567, + "time_from_now": "6天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + } +] +``` +--- + +### 获取版本列表 +``` +GET /api/:login/:repo_identifier/tags +``` +*示例* +``` +curl -X GET http://localhost:3000/api/18816895620/mirror_demo/tags | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +-|-|- +|name |string|分支名称| +|user_can_push |boolean|用户是否可push| +|user_can_merge |boolean|用户是否客merge| +|protected |boolean|是否为保护分支| +|http_url |boolean|http链接| +|zip_url |boolean|zip包下载链接| +|tar_url |boolean|tar.gz下载链接| +|last_commit |object|最后提交记录| +|-- id |string|提交记录id| +|-- message |string|提交的说明信息| +|-- timestamp |int|提交时间,为UNIX时间戳| +|-- time_from_now|string|转换后的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +``` +[ + { + "name": "develop", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/develop.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/develop.tar.gz", + "last_commit": { + "id": "735674d6696bddbafa993db9c67b40c41246c77f", + "message": "FIX test branch content\n", + "timestamp": 1577694074, + "time_from_now": "1天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "name": "master", + "user_can_push": true, + "user_can_merge": true, + "protected": false, + "http_url": "http://localhost:3003/18816895620/mirror_demo.git", + "zip_url": "http://localhost:3003/18816895620/mirror_demo/master.zip", + "tar_url": "http://localhost:3003/18816895620/mirror_demo/master.tar.gz", + "last_commit": { + "id": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试\n\n该功能很不错,感谢你的建议\n", + "timestamp": 1577244567, + "time_from_now": "6天前" + }, + "author": { + "login": "18816895620", + "image_url": "avatars/User/b" + } + } +] +``` +--- + +## 仓库详情 +``` +GET /api/:login/:repo_identifier/ +``` +*示例* +``` +curl -X GET \ +http://localhost:3000/api/18816895620/mirror_demo | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|string |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|identifier |string|仓库标识| +|project_id |int|项目id| +|project_identifier|string|项目标识| +|praises_count |int|点赞数量| +|forked_count |int|fork数量| +|watchers_count |int|关注数量| +|branches_count |int|分支数量| +|commits_count |int|总提交记录数量| +|issues_count |int|总提交记录数量| +|pull_requests_count |int|总提交记录数量| +|praised |boolean|当前登录用户是否已点赞,true:已点赞,fasle:未点赞, 用户未登录状态为null| +|watched |boolean|当前登录用户是否已关注,true:已关注,fasle:未关注, 用户未登录状态为null| +|permission |string|当前登录用户对该仓库的操作权限, Manager:管理员,可以在线编辑文件、在线新建文件、可以设置仓库的基本信息; Developer:开发人员,可在线编辑文件、在线新建文件、不能设置仓库信息; Reporter: 报告人员,只能查看信息,不能设置仓库信息、不能在线编辑文件、不能在线新建文件;用户未登录时也会返回Reporter, 说明也只有读取文件的权限 | +|size |int|仓库文件大小,单位:KB| +|mirror_url |string|镜像地址, 只有通过镜像过来的项目才会有这个地址| +|ssh_url |string|仓库ssh地址| +|clone_url |string|仓库克隆地址| +|empty |boolean|仓库是否为空,true: 空仓库;false: 非空仓库| +|private |boolean|仓库是否私有,true: 私有仓库;fasle: 非私有的| +|default_branch |string|仓库默认分支| +|full_name |string|仓库全名(带用户名)| +|author |object|提交用户| +|-- login |string|用户login| +|-- name |string|用户姓名| +|-- image_url |string|用户头像| + + +返回值 +``` +{ + "identifier": "mirror_demo", + "project_id": 3263, + "project_identifier": "mirror_demo", + "praises_count": 1, + "forked_count": 0, + "watchers_count": 1, + "branches_count": 6, + "commits_count": 107, + "issues_count": 0, + "pull_requests_count": 0, + "permission": "Manager", + "mirror_url": "https://gitea.com/CasperVector/slew.git", + "watched": true, + "praised": true, + "size": 446, + "ssh_url": "jasder@localhost:18816895620/mirror_demo.git", + "clone_url": "http://localhost:3003/18816895620/mirror_demo.git", + "default_branch": "master", + "empty": false, + "full_name": "18816895620/mirror_demo", + "mirror": false, + "private": false, + "author": { + "login": "18816895620", + "name": "美女", + "image_url": "avatars/User/b" + } +} +``` +--- + +## 获取提交记录列表 +``` +GET /api/:login/:repo_identifier/commits +``` +*示例* +``` +curl -X GET \ +-d "sha=develop" \ +-d "page=1" \ +http://localhost:3000/api/18816895620/mirror_demo/commits | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|sha |否|string |分支名称、提交记录的sha标识,默认为master分支 | +|page |否|int |页数, 默认为1 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count|int|总记录条数| +|commits |array|提交记录的数组| +|-- sha |string|提交记录sha标识| +|-- message |string|提交的备注说明| +|-- timestamp |int|提交UNIX时间戳| +|-- time_from_now|string|提交距离当前的时间| +|author |object|提交用户| +|-- login |string|用户名称| +|-- image_url |string|用户头像| + + +返回值 +``` +{ + "total_count": 63, + "commits": [ + { + "sha": "19ac3bc45f62cc87a94b8ecce61101d8fd2dafd2", + "message": "合并pull request测试", + "timestamp": 1577244567, + "time_from_now": "7天前", + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + } + }, + { + "sha": "2b33c5f55214db41879936312ee43611406c4dbd", + "message": "FIX .", + "timestamp": 1577244474, + "time_from_now": "7天前", + "author": { + "name": "18816895620", + "image_url": "avatars/User/b" + } + } + ] +} +``` +--- + +### 点赞 +``` +POST /api/projects/:id/praise_tread/like +``` +*示例* +``` +curl -X POST http://localhost:3000/api/projects/3263/praise_tread/like | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +### 取消点赞 +``` +DELETE /api/projects/:id/praise_tread/unlike +``` +*示例* +``` +curl -X DELETE http://localhost:3000/api/projects/3263/praise_tread/unlike | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +### 用户是否点过赞 +``` +GET /api/projects/:id/praise_tread/check_like +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/3263/praise_tread/check_like | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|1:已点过赞,0:未点过赞, -1:请求操作失败| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +### 项目的点赞者列表 +``` +GET /api/projects/:id/praise_tread +``` +*示例* +``` +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000/api/projects/3263/praise_tread | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int|总条数| +|praises |array|点赞数据| +|-- name |string|用户名称| +|-- login |string|用户标识/登录名(login)| +|-- image_url |string|用户头像| + + + +返回值 +``` +{ + "total_count": 1, + "praises": [ + { + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +### 关注(项目) +``` +POST /api/projects/:id/watchers/follow +``` +*示例* +``` +curl -X POST http://localhost:3000/api/projects/3263/watchers/follow | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示已经点过赞了| + + +返回值 +``` +{ + "status": 0, + "message": "响应成功" +} +``` +--- + +### 取消关注 +``` +DELETE /api/projects/:id/watchers/unfollow +``` +*示例* +``` +curl -X DELETE http://localhost:3000//api/projects/3263/watchers/unfollow | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|0:点赞成功,-1:操作失败,2:表示还未点赞| + + +返回值 +``` +{ + "status": 0, + "message": "响应成功" +} +``` +--- + +### 用户是否关注过项目 +``` +GET /api/projects/:id/watchers/check_watch +``` +*示例* +``` +curl -X GET http://localhost:3000/api/projects/3263/watchers/check_watch | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是 |int |项目id | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|status |int|1:已关注,0:未关注, -1:请求操作失败| + + +返回值 +``` +{ + "status": 0, + "message": "success" +} +``` +--- + +### 项目的关注者列表 +``` +GET /api/projects/:id/watchers +``` +*示例* +``` +curl -X GET \ +-d "page=1" \ +-d "limit=5" \ +http://localhost:3000//api/projects/3263/watchers | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|page |否|string |页数,第几页 | +|limit |否|string |每页多少条数据,默认15条 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|total_count |int|总条数| +|watchers |array|关注数据| +|-- name |string|用户名称| +|-- login |string|用户标识/登录名(login)| +|-- image_url |string|用户头像| + + +返回值 +``` +{ + "total_count": 1, + "watchers": [ + { + "name": "18816895620", + "login": "18816895620", + "image_url": "avatars/User/b" + } + ] +} +``` +--- + +### 仓库新建文件 +``` +DELETE /api/:login/:repo_identifier/contents +``` +*示例* +``` +curl -X POST \ +-d 'filepath=test1_create_file1.rb' \ +-d 'branch=master' \ +-d 'content=提交的内容' \ +-d 'message=test commit ' \ +http://localhost:3000/api/18816895620/mirror_demo/contents.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|string |项目id | +|filepath |是|string |文件相对于仓库的路径 | +|content |否|string |内容 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, branch和new_branch必须存在一个 | +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件名| +|sha |string|提交文件的sha值| +|size |int|文件大小, 单位:B| +|content |string|base64编码后的文件内容| +|encoding |string|编码方式| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + + +返回值 +``` +{ + "name": "test1_create_file12.rb", + "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", + "size": 12, + "content": "Wm5ObWMyRmtaZz09", + "encoding": "base64", + "commit": { + "message": "good luck\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-07T03:31:20Z" + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-07T03:31:20Z" + } + } +} +``` +--- + +### 更新仓库中的文件 +``` +PUT /api/:login/:repo_identifier/contents/files/update +``` +*示例* +``` +curl -X PUT \ +-d 'filepath=text1.rb' \ +-d 'branch=master' \ +-d 'content=ruby code' \ +-d 'message=更改提交信息' \ +-d 'from_path=text.rb' \ +-d "sha=57426eb21e4ceabdf4b206f022077e0040" \ +http://localhost:3000/api/18816895620/mirror_demo/contents/files/update.json | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件相对于仓库的路径(或修改后的文件路径) | +|from_path |是|string |原文件相对于仓库的路径, 只有当需要修改原文件名称时,才需要该参数 | +|sha |是|string |文件的sha标识值 | +|content |是|string |内容 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, branch和new_branch必须存在一个,且只能存在一个 | +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|name |string|文件名| +|sha |string|提交文件的sha值| +|size |int|文件大小, 单位:B| +|content |string|base64编码后的文件内容| +|encoding |string|编码方式| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + +返回值 +``` +{ + "name": "test1_create_file6.rb", + "sha": "57426eb21e4ceabdf4b206f022257e08077e0040", + "size": 16, + "content": "5o+Q5Lqk55qE5YaF5a65MQ==", + "encoding": "base64", + "commit": { + "message": "更改提交信息\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:05:15Z" + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:05:15Z" + } + } +} +``` +--- + +### 删除仓库中的文件 +``` +DELETE /api/:login/:repo_identifier/contents/files/delete +``` +*示例* +``` +curl -X DELETE \ +-d 'filepath=test1_create_file12.rb' \ +-d 'test delete file' \ +-d 'sha=7b70509105b587e71f5692b9e8ab70851e321f64' \ +http://localhost:3000/api/18816895620/mirror_demo/contents/files/delete | jq +``` +*请求参数说明:* + +|参数名|必选|类型|说明| +|-|-|-|-| +|id |是|int |项目id | +|filepath |是|string |文件相对于仓库的路径 | +|message |否|string |提交说明 | +|branch |否|string |分支名称, 默认为master分支| +|new_branch |否|string |新的分支名称 | + + +*返回参数说明:* + +|参数名|类型|说明| +|-|-|-| +|sha |string|提交文件的sha值| +|commit |object|| +|-- message |string|提交备注说明信息| +|-- committer|object|| +|---- name |string|用户名| +|---- email |string|用户邮箱| +|---- date |string|文件创建时间| + + +返回值 +``` +{ + "commit": { + "sha": "7b70509105b587e71f5692b9e8ab70851e321f64", + "message": "Delete 'test1_create_file11.rb'\n", + "author": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:57:34Z" + }, + "committer": { + "name": "18816895620", + "email": "2456233122@qq.com", + "date": "2020-01-08T07:57:34Z" + } + } +} +``` +--- diff --git a/docs/figs/code.png b/docs/figs/code.png new file mode 100644 index 00000000..469ee07b Binary files /dev/null and b/docs/figs/code.png differ diff --git a/docs/figs/issue_assign.png b/docs/figs/issue_assign.png new file mode 100644 index 00000000..01798d2e Binary files /dev/null and b/docs/figs/issue_assign.png differ diff --git a/docs/figs/issue_assign2.png b/docs/figs/issue_assign2.png new file mode 100644 index 00000000..ffd22764 Binary files /dev/null and b/docs/figs/issue_assign2.png differ diff --git a/docs/figs/issue_manage.png b/docs/figs/issue_manage.png new file mode 100644 index 00000000..5983daeb Binary files /dev/null and b/docs/figs/issue_manage.png differ diff --git a/docs/figs/issue_view.png b/docs/figs/issue_view.png new file mode 100644 index 00000000..582dc88a Binary files /dev/null and b/docs/figs/issue_view.png differ diff --git a/docs/figs/milestone.png b/docs/figs/milestone.png new file mode 100644 index 00000000..4a78f60b Binary files /dev/null and b/docs/figs/milestone.png differ diff --git a/dump.rdb b/dump.rdb index d12a997b..f32855aa 100644 Binary files a/dump.rdb and b/dump.rdb differ diff --git a/lib/gitlab-cli/Gemfile b/lib/gitlab-cli/Gemfile deleted file mode 100644 index 2b517aca..00000000 --- a/lib/gitlab-cli/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'http://gems.ruby-china.org/' - -# Specify your gem's dependencies in gitlab.gemspec -gemspec diff --git a/lib/gitlab-cli/LICENSE.txt b/lib/gitlab-cli/LICENSE.txt deleted file mode 100644 index d3cbb552..00000000 --- a/lib/gitlab-cli/LICENSE.txt +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2012-2014 Nihad Abbasov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/gitlab-cli/README.md b/lib/gitlab-cli/README.md deleted file mode 100644 index 1a1f0e4b..00000000 --- a/lib/gitlab-cli/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# Gitlab - -[![Build Status](https://travis-ci.org/NARKOZ/gitlab.png)](http://travis-ci.org/NARKOZ/gitlab) - -[website](http://narkoz.github.io/gitlab) | -[documentation](http://rubydoc.info/gems/gitlab/frames) - -Gitlab is a Ruby wrapper and CLI for the [GitLab API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api#gitlab-api). - -## Installation - -Install it from rubygems: - -```sh -gem install gitlab -``` - -Or add to a Gemfile: - -```ruby -gem 'gitlab' -# gem 'gitlab', :git => 'git://github.com/NARKOZ/gitlab.git' -``` - -## Usage - -Configuration example: - -```ruby -Gitlab.configure do |config| - config.endpoint = 'https://example.net/api/v3' # API endpoint URL, default: ENV['GITLAB_API_ENDPOINT'] - config.private_token = 'qEsq1pt6HJPaNciie3MG' # user's private token, default: ENV['GITLAB_API_PRIVATE_TOKEN'] - # Optional - # config.user_agent = 'Custom User Agent' # user agent, default: 'Gitlab Ruby Gem [version]' - # config.sudo = 'user' # username for sudo mode, default: nil -end -``` - -(Note: If you are using Gitlab.com's hosted service, your endpoint will be `https://gitlab.com/api/v3`) - -Usage examples: - -```ruby -# set an API endpoint -Gitlab.endpoint = 'http://example.net/api/v3' -# => "http://example.net/api/v3" - -# set a user private token -Gitlab.private_token = 'qEsq1pt6HJPaNciie3MG' -# => "qEsq1pt6HJPaNciie3MG" - -# list projects -Gitlab.projects(:per_page => 5) -# => [#1, "code"=>"brute", "name"=>"Brute", "description"=>nil, "path"=>"brute", "default_branch"=>nil, "owner"=>#1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:56Z"}>, #2, "code"=>"mozart", "name"=>"Mozart", "description"=>nil, "path"=>"mozart", "default_branch"=>nil, "owner"=>#1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:57Z"}>, #3, "code"=>"gitlab", "name"=>"Gitlab", "description"=>nil, "path"=>"gitlab", "default_branch"=>nil, "owner"=>#1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:58Z"}>] - -# initialize a new client -g = Gitlab.client(:endpoint => 'https://api.example.com', :private_token => 'qEsq1pt6HJPaNciie3MG') -# => # - -# get a user -user = g.user -# => #1, "email"=>"john@example.com", "name"=>"John Smith", "bio"=>nil, "skype"=>"", "linkedin"=>"", "twitter"=>"john", "dark_scheme"=>false, "theme_id"=>1, "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}> - -# get a user's email -user.email -# => "john@example.com" - -# set a sudo mode to perform API calls as another user -Gitlab.sudo = 'other_user' -# => "other_user" - -# disable a sudo mode -Gitlab.sudo = nil -# => nil -``` - -For more information, refer to [documentation](http://rubydoc.info/gems/gitlab/frames). - -## CLI - -Usage examples: - -```sh -# list users -gitlab users - -# get current user -gitlab user - -# get a user -gitlab user 2 - -# filter output -gitlab user --only=id,username - -gitlab user --except=email,bio -``` - -## CLI Shell - -Usage examples: - -```sh -# start shell session -gitlab shell - -# list available commands -gitlab> help - -# list groups -gitlab> groups - -# protect a branch -gitlab> protect_branch 1 master -``` - -For more information, refer to [website](http://narkoz.github.io/gitlab). - -## License - -Released under the BSD 2-clause license. See LICENSE.txt for details. diff --git a/lib/gitlab-cli/Rakefile b/lib/gitlab-cli/Rakefile deleted file mode 100644 index eebc7761..00000000 --- a/lib/gitlab-cli/Rakefile +++ /dev/null @@ -1,9 +0,0 @@ -require "bundler/gem_tasks" - -require 'rspec/core/rake_task' -RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] - spec.rspec_opts = ['--color', '--format d'] -end - -task :default => :spec diff --git a/lib/gitlab-cli/bin/gitlab b/lib/gitlab-cli/bin/gitlab deleted file mode 100755 index 02cc41fc..00000000 --- a/lib/gitlab-cli/bin/gitlab +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift File.expand_path('../../lib', __FILE__) - -require 'gitlab/cli' - -Gitlab::CLI.start(ARGV) diff --git a/lib/gitlab-cli/gitlab.gemspec b/lib/gitlab-cli/gitlab.gemspec deleted file mode 100644 index 11bd093d..00000000 --- a/lib/gitlab-cli/gitlab.gemspec +++ /dev/null @@ -1,26 +0,0 @@ -# -*- encoding: utf-8 -*- -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'gitlab/version' - -Gem::Specification.new do |gem| - gem.name = "gitlab" - gem.version = Gitlab::VERSION - gem.authors = ["Nihad Abbasov"] - gem.email = ["mail@narkoz.me"] - gem.description = %q{Ruby client and CLI for GitLab API} - gem.summary = %q{A Ruby wrapper and CLI for the GitLab API} - gem.homepage = "https://github.com/narkoz/gitlab" - - gem.files = `git ls-files`.split($/) - gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } - gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) - gem.require_paths = ["lib"] - - gem.add_runtime_dependency 'httparty' - gem.add_runtime_dependency 'terminal-table' - - gem.add_development_dependency 'rake' - gem.add_development_dependency 'rspec' - gem.add_development_dependency 'webmock' -end diff --git a/lib/gitlab-cli/lib/gitlab.rb b/lib/gitlab-cli/lib/gitlab.rb deleted file mode 100644 index a203a70a..00000000 --- a/lib/gitlab-cli/lib/gitlab.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'gitlab/version' -require 'gitlab/objectified_hash' -require 'gitlab/configuration' -require 'gitlab/error' -require 'gitlab/request' -require 'gitlab/api' -require 'gitlab/client' - -module Gitlab - extend Configuration - - # Alias for Gitlab::Client.new - # - # @return [Gitlab::Client] - def self.client(options={}) - Gitlab::Client.new(options) - end - - # Delegate to Gitlab::Client - def self.method_missing(method, *args, &block) - return super unless client.respond_to?(method) - client.send(method, *args, &block) - end - - # Delegate to Gitlab::Client - def self.respond_to?(method) - return client.respond_to?(method) || super - end - - # Returns an unsorted array of available client methods. - # - # @return [Array] - def self.actions - hidden = /endpoint|private_token|user_agent|sudo|get|post|put|\Adelete\z|validate|set_request_defaults/ - (Gitlab::Client.instance_methods - Object.methods).reject {|e| e[hidden]} - end -end diff --git a/lib/gitlab-cli/lib/gitlab/api.rb b/lib/gitlab-cli/lib/gitlab/api.rb deleted file mode 100644 index c2dfb7cf..00000000 --- a/lib/gitlab-cli/lib/gitlab/api.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Gitlab - # @private - class API < Request - # @private - attr_accessor(*Configuration::VALID_OPTIONS_KEYS) - - # Creates a new API. - # @raise [Error:MissingCredentials] - def initialize(options={}) - options = Gitlab.options.merge(options) - Configuration::VALID_OPTIONS_KEYS.each do |key| - send("#{key}=", options[key]) - end - set_request_defaults @endpoint, @private_token, @sudo - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/cli.rb b/lib/gitlab-cli/lib/gitlab/cli.rb deleted file mode 100644 index fa6d6d67..00000000 --- a/lib/gitlab-cli/lib/gitlab/cli.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'gitlab' -require 'terminal-table/import' -require_relative 'cli_helpers' -require_relative 'shell' - -class Gitlab::CLI - extend Helpers - - def self.start(args) - command = args.shift.strip rescue 'help' - run(command, args) - end - - def self.run(cmd, args=[]) - case cmd - when 'help' - puts actions_table - when 'info' - endpoint = Gitlab.endpoint ? Gitlab.endpoint : 'not set' - private_token = Gitlab.private_token ? Gitlab.private_token : 'not set' - puts "Gitlab endpoint is #{endpoint}" - puts "Gitlab private token is #{private_token}" - puts "Ruby Version is #{RUBY_VERSION}" - puts "Gitlab Ruby Gem #{Gitlab::VERSION}" - when '-v', '--version' - puts "Gitlab Ruby Gem #{Gitlab::VERSION}" - when 'shell' - Gitlab::Shell.start - else - unless valid_command?(cmd) - puts "Unknown command. Run `gitlab help` for a list of available commands." - exit(1) - end - - if args.any? && (args.last.start_with?('--only=') || args.last.start_with?('--except=')) - command_args = args[0..-2] - else - command_args = args - end - - confirm_command(cmd) - - data = gitlab_helper(cmd, command_args) { exit(1) } - output_table(cmd, args, data) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/cli_helpers.rb b/lib/gitlab-cli/lib/gitlab/cli_helpers.rb deleted file mode 100644 index 93293d38..00000000 --- a/lib/gitlab-cli/lib/gitlab/cli_helpers.rb +++ /dev/null @@ -1,175 +0,0 @@ -class Gitlab::CLI - # Defines methods related to CLI output and formatting. - module Helpers - extend self - - # Returns filtered required fields. - # - # @return [Array] - def required_fields(args) - if args.any? && args.last.start_with?('--only=') - args.last.gsub('--only=', '').split(',') - else - [] - end - end - - # Returns filtered excluded fields. - # - # @return [Array] - def excluded_fields(args) - if args.any? && args.last.start_with?('--except=') - args.last.gsub('--except=', '').split(',') - else - [] - end - end - - # Confirms command is valid. - # - # @return [Boolean] - def valid_command?(cmd) - command = cmd.is_a?(Symbol) ? cmd : cmd.to_sym - Gitlab.actions.include?(command) - end - - # Confirms command with a desctructive action. - # - # @return [String] - def confirm_command(cmd) - if cmd.start_with?('remove_') || cmd.start_with?('delete_') - puts "Are you sure? (y/n)" - if %w(y yes).include?($stdin.gets.to_s.strip.downcase) - puts 'Proceeding..' - else - puts 'Command aborted.' - exit(1) - end - end - end - - # Table with available commands. - # - # @return [String] - def actions_table - client = Gitlab::Client.new(endpoint: '') - actions = Gitlab.actions - methods = [] - - actions.each do |action| - methods << { - name: action, - owner: client.method(action).owner.to_s.gsub('Gitlab::Client::', '') - } - end - - owners = methods.map {|m| m[:owner]}.uniq.sort - methods_c = methods.group_by {|m| m[:owner]} - methods_c = methods_c.map {|_, v| [_, v.sort_by {|hv| hv[:name]}] } - methods_c = Hash[methods_c.sort_by(&:first).map {|k, v| [k, v]}] - max_column_length = methods_c.values.max_by(&:size).size - - rows = max_column_length.times.map do |i| - methods_c.keys.map do |key| - methods_c[key][i] ? methods_c[key][i][:name] : '' - end - end - - table do |t| - t.title = "Available commands (#{actions.size} total)" - t.headings = owners - - rows.each do |row| - t.add_row row - end - end - end - - # Decides which table to use. - # - # @return [String] - def output_table(cmd, args, data) - case data - when Gitlab::ObjectifiedHash - puts single_record_table(data, cmd, args) - when Array - puts multiple_record_table(data, cmd, args) - else - puts data.inspect - end - end - - # Table for a single record. - # - # @return [String] - def single_record_table(data, cmd, args) - hash = data.to_h - keys = hash.keys.sort {|x, y| x.to_s <=> y.to_s } - keys = keys & required_fields(args) if required_fields(args).any? - keys = keys - excluded_fields(args) - - table do |t| - t.title = "Gitlab.#{cmd} #{args.join(', ')}" - - keys.each_with_index do |key, index| - case value = hash[key] - when Hash - value = 'Hash' - when nil - value = 'null' - end - - t.add_row [key, value] - t.add_separator unless keys.size - 1 == index - end - end - end - - # Table for multiple records. - # - # @return [String] - def multiple_record_table(data, cmd, args) - return 'No data' if data.empty? - - arr = data.map(&:to_h) - keys = arr.first.keys.sort {|x, y| x.to_s <=> y.to_s } - keys = keys & required_fields(args) if required_fields(args).any? - keys = keys - excluded_fields(args) - - table do |t| - t.title = "Gitlab.#{cmd} #{args.join(', ')}" - t.headings = keys - - arr.each_with_index do |hash, index| - values = [] - - keys.each do |key| - case value = hash[key] - when Hash - value = 'Hash' - when nil - value = 'null' - end - - values << value - end - - t.add_row values - t.add_separator unless arr.size - 1 == index - end - end - end - - # Helper function to call Gitlab commands with args. - def gitlab_helper(cmd, args=[]) - begin - data = args.any? ? Gitlab.send(cmd, *args) : Gitlab.send(cmd) - rescue => e - puts e.message - yield if block_given? - end - - data - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client.rb b/lib/gitlab-cli/lib/gitlab/client.rb deleted file mode 100644 index a2616391..00000000 --- a/lib/gitlab-cli/lib/gitlab/client.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Gitlab - # Wrapper for the Gitlab REST API. - class Client < API - Dir[File.expand_path('../client/*.rb', __FILE__)].each {|f| require f} - - include Branches - include Groups - include Issues - include MergeRequests - include Milestones - include Notes - include Projects - include Repositories - include Snippets - include SystemHooks - include Users - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/branches.rb b/lib/gitlab-cli/lib/gitlab/client/branches.rb deleted file mode 100644 index bbe55498..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/branches.rb +++ /dev/null @@ -1,79 +0,0 @@ -class Gitlab::Client - # Defines methods related to repositories. - module Branches - # Gets a list of project repositiory branches. - # - # @example - # Gitlab.branches(42) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def branches(project, options={}) - get("/projects/#{project}/repository/branches", :query => options) - end - alias_method :repo_branches, :branches - - # Gets information about a repository branch. - # - # @example - # Gitlab.branch(3, 'api') - # Gitlab.repo_branch(5, 'master') - # - # @param [Integer] project The ID of a project. - # @param [String] branch The name of the branch. - # @return [Gitlab::ObjectifiedHash] - def branch(project, branch) - get("/projects/#{project}/repository/branches/#{branch}") - end - - alias_method :repo_branch, :branch - - # Protects a repository branch. - # - # @example - # Gitlab.protect_branch(3, 'api') - # Gitlab.repo_protect_branch(5, 'master') - # - # @param [Integer] project The ID of a project. - # @param [String] branch The name of the branch. - # @return [Gitlab::ObjectifiedHash] - def protect_branch(project, branch) - put("/projects/#{project}/repository/branches/#{branch}/protect") - end - alias_method :repo_protect_branch, :protect_branch - - # Unprotects a repository branch. - # - # @example - # Gitlab.unprotect_branch(3, 'api') - # Gitlab.repo_unprotect_branch(5, 'master') - # - # @param [Integer] project The ID of a project. - # @param [String] branch The name of the branch. - # @return [Gitlab::ObjectifiedHash] - def unprotect_branch(project, branch) - put("/projects/#{project}/repository/branches/#{branch}/unprotect") - end - alias_method :repo_unprotect_branch, :unprotect_branch - - # Creates a repository branch. Requires Gitlab >= 6.8.x - # - # @example - # Gitlab.create_branch(3, 'api') - # Gitlab.repo_create_branch(5, 'master') - # - # @param [Integer] project The ID of a project. - # @param [String] branch The name of the new branch. - # @param [String] ref Create branch from commit sha or existing branch - # @return [Gitlab::ObjectifiedHash] - def create_branch(project, branch, ref) - post("/projects/#{project}/repository/branches",:body => {:branch_name => branch, :ref => ref}) - end - alias_method :repo_create_branch, :create_branch - - end -end - diff --git a/lib/gitlab-cli/lib/gitlab/client/groups.rb b/lib/gitlab-cli/lib/gitlab/client/groups.rb deleted file mode 100644 index 66f5f5a7..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/groups.rb +++ /dev/null @@ -1,88 +0,0 @@ -class Gitlab::Client - # Defines methods related to groups. - module Groups - # Gets a list of groups. - # - # @example - # Gitlab.groups - # Gitlab.groups(:per_page => 40) - # - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def groups(options={}) - get("/groups", :query => options) - end - - # Gets a single group. - # - # @example - # Gitlab.group(42) - # - # @param [Integer] id The ID of a group. - # @return [Gitlab::ObjectifiedHash] - def group(id) - get("/groups/#{id}") - end - - # Creates a new group. - # - # @param [String] name The name of a group. - # @param [String] path The path of a group. - # @return [Gitlab::ObjectifiedHash] Information about created group. - def create_group(name, path) - body = {:name => name, :path => path} - post("/groups", :body => body) - end - - # Get a list of group members. - # - # @example - # Gitlab.group_members(1) - # Gitlab.group_members(1, :per_page => 40) - # - # @param [Integer] id The ID of a group. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def group_members(id, options={}) - get("/groups/#{id}/members", :query => options) - end - - # Adds a user to group. - # - # @example - # Gitlab.add_group_member(1, 2, 40) - # - # @param [Integer] team_id The group id to add a member to. - # @param [Integer] user_id The user id of the user to add to the team. - # @param [Integer] access_level Project access level. - # @return [Gitlab::ObjectifiedHash] Information about added team member. - def add_group_member(team_id, user_id, access_level) - post("/groups/#{team_id}/members", :body => {:user_id => user_id, :access_level => access_level}) - end - - # Removes user from user group. - # - # @example - # Gitlab.remove_group_member(1, 2) - # - # @param [Integer] team_id The group ID. - # @param [Integer] user_id The ID of a user. - # @return [Gitlab::ObjectifiedHash] Information about removed team member. - def remove_group_member(team_id, user_id) - delete("/groups/#{team_id}/members/#{user_id}") - end - - # Transfers a project to a group - # - # @param [Integer] id The ID of a group. - # @param [Integer] project_id The ID of a project. - def transfer_project_to_group(id, project_id) - body = {:id => id, :project_id => project_id} - post("/groups/#{id}/projects/#{project_id}", :body => body) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/issues.rb b/lib/gitlab-cli/lib/gitlab/client/issues.rb deleted file mode 100644 index 668953d1..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/issues.rb +++ /dev/null @@ -1,92 +0,0 @@ -class Gitlab::Client - # Defines methods related to issues. - module Issues - # Gets a list of user's issues. - # Will return a list of project's issues if project ID passed. - # - # @example - # Gitlab.issues - # Gitlab.issues(5) - # Gitlab.issues(:per_page => 40) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def issues(project=nil, options={}) - if project.to_i.zero? - get("/issues", :query => options) - else - get("/projects/#{project}/issues", :query => options) - end - end - - # Gets a single issue. - # - # @example - # Gitlab.issue(5, 42) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of an issue. - # @return [Gitlab::ObjectifiedHash] - def issue(project, id) - get("/projects/#{project}/issues/#{id}") - end - - # Creates a new issue. - # - # @param [Integer] project The ID of a project. - # @param [String] title The title of an issue. - # @param [Hash] options A customizable set of options. - # @option options [String] :description The description of an issue. - # @option options [Integer] :assignee_id The ID of a user to assign issue. - # @option options [Integer] :milestone_id The ID of a milestone to assign issue. - # @option options [String] :labels Comma-separated label names for an issue. - # @return [Gitlab::ObjectifiedHash] Information about created issue. - def create_issue(project, title, options={}) - body = {:title => title}.merge(options) - post("/projects/#{project}/issues", :body => body) - end - - # Updates an issue. - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of an issue. - # @param [Hash] options A customizable set of options. - # @option options [String] :title The title of an issue. - # @option options [String] :description The description of an issue. - # @option options [Integer] :assignee_id The ID of a user to assign issue. - # @option options [Integer] :milestone_id The ID of a milestone to assign issue. - # @option options [String] :labels Comma-separated label names for an issue. - # @option options [String] :state_event The state event of an issue ('close' or 'reopen'). - # @return [Gitlab::ObjectifiedHash] Information about updated issue. - def edit_issue(project, id, options={}) - put("/projects/#{project}/issues/#{id}", :body => options) - end - - # Closes an issue. - # - # @example - # Gitlab.close_issue(3, 42) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of an issue. - # @return [Gitlab::ObjectifiedHash] Information about closed issue. - def close_issue(project, id) - put("/projects/#{project}/issues/#{id}", :body => {:state_event => 'close'}) - end - - # Reopens an issue. - # - # @example - # Gitlab.reopen_issue(3, 42) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of an issue. - # @return [Gitlab::ObjectifiedHash] Information about reopened issue. - def reopen_issue(project, id) - put("/projects/#{project}/issues/#{id}", :body => {:state_event => 'reopen'}) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/merge_requests.rb b/lib/gitlab-cli/lib/gitlab/client/merge_requests.rb deleted file mode 100644 index e15f7dfa..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/merge_requests.rb +++ /dev/null @@ -1,135 +0,0 @@ -class Gitlab::Client - # Defines methods related to merge requests. - module MergeRequests - # Gets a list of project merge requests. - # - # @example - # Gitlab.merge_requests(5) - # Gitlab.merge_requests(:per_page => 40) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def merge_requests(project, options={}) - get("/projects/#{project}/merge_requests", :query => options) - end - - # Gets a single merge request. - # - # @example - # Gitlab.merge_request(5, 36) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a merge request. - # @return 'source_branch', :target_branch => 'target_branch') - # Gitlab.create_merge_request(5, 'New merge request', - # :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42) - # - # @param [Integer] project The ID of a project. - # @param [String] title The title of a merge request. - # @param [Hash] options A customizable set of options. - # @option options [String] :source_branch (required) The source branch name. - # @option options [String] :target_branch (required) The target branch name. - # @option options [Integer] :assignee_id (optional) The ID of a user to assign merge request. - # @return [Gitlab::ObjectifiedHash] Information about created merge request. - def create_merge_request(project, title, gid, options={}) - check_attributes!(options, [:source_branch, :target_branch]) - - body = {:title => title}.merge(options) - post("/projects/#{project}/merge_requests?user_id=#{gid}", :body => body) - end - - # Updates a merge request. - # - # @example - # Gitlab.update_merge_request(5, 42, :title => 'New title') - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a merge request. - # @param [Hash] options A customizable set of options. - # @option options [String] :title The title of a merge request. - # @option options [String] :source_branch The source branch name. - # @option options [String] :target_branch The target branch name. - # @option options [Integer] :assignee_id The ID of a user to assign merge request. - # @option options [String] :state_event New state (close|reopen|merge). - # @return [Gitlab::ObjectifiedHash] Information about updated merge request. - def update_merge_request(project, id, gid, options={}) - put("/projects/#{project}/merge_request/#{id}?user_id=#{gid}", :body => options) - end - - # Adds a comment to a merge request. - # - # @example - # Gitlab.create_merge_request_comment(5, 1, "Awesome merge!") - # Gitlab.create_merge_request_comment('gitlab', 1, "Awesome merge!") - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a merge request. - # @param [String] note The content of a comment. - # @return [Gitlab::ObjectifiedHash] Information about created merge request comment. - def create_merge_request_comment(project, id, note, gid) - post("/projects/#{project}/merge_request/#{id}/comments?user_id=#{gid}", :body => {:note => note}) - end - - # Get a list of merge request commits. - # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - The ID of MR - def merge_request_commits(project, id) - get("/projects/#{project}/merge_request/#{id}/commits") - end - - # Shows information about the merge request including its files and changes. With GitLab 8.2 the return fields upvotes and downvotes are deprecated and always return 0. - # Parameters: - # id (required) - The ID of a project - # merge_request_id (required) - The ID of MR - def merge_request_changes(project, id) - get("/projects/#{project}/merge_request/#{id}/changes") - end - - # Gets the comments on a merge request. - # - # @example - # Gitlab.merge_request_comments(5, 1) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a merge request. - # @return [Gitlab::ObjectifiedHash] The merge request's comments. - def merge_request_comments(project, id) - get("/projects/#{project}/merge_request/#{id}/comments") - end - - # Accept a merge request. - # - # @example - # Gitlab.accept_pull_rquest(5, 1) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a merge request. - # @return [Gitlab::ObjectifiedHash] - def accept_merge_rquest(project, id, gid) - put("/projects/#{project}/merge_request/#{id}/merge?user_id=#{gid}") - end - - private - - def check_attributes!(options, attrs) - attrs.each do |attr| - unless options.has_key?(attr) || options.has_key?(attr.to_s) - raise Gitlab::Error::MissingAttributes.new("Missing '#{attr}' parameter") - end - end - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/milestones.rb b/lib/gitlab-cli/lib/gitlab/client/milestones.rb deleted file mode 100644 index 197b1f3c..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/milestones.rb +++ /dev/null @@ -1,57 +0,0 @@ -class Gitlab::Client - # Defines methods related to milestones. - module Milestones - # Gets a list of project's milestones. - # - # @example - # Gitlab.milestones(5) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def milestones(project, options={}) - get("/projects/#{project}/milestones", :query => options) - end - - # Gets a single milestone. - # - # @example - # Gitlab.milestone(5, 36) - # - # @param [Integer, String] project The ID of a project. - # @param [Integer] id The ID of a milestone. - # @return [Gitlab::ObjectifiedHash] - def milestone(project, id) - get("/projects/#{project}/milestones/#{id}") - end - - # Creates a new milestone. - # - # @param [Integer] project The ID of a project. - # @param [String] title The title of a milestone. - # @param [Hash] options A customizable set of options. - # @option options [String] :description The description of a milestone. - # @option options [String] :due_date The due date of a milestone. - # @return [Gitlab::ObjectifiedHash] Information about created milestone. - def create_milestone(project, title, options={}) - body = {:title => title}.merge(options) - post("/projects/#{project}/milestones", :body => body) - end - - # Updates a milestone. - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a milestone. - # @param [Hash] options A customizable set of options. - # @option options [String] :title The title of a milestone. - # @option options [String] :description The description of a milestone. - # @option options [String] :due_date The due date of a milestone. - # @option options [String] :state_event The state of a milestone ('close' or 'activate'). - # @return [Gitlab::ObjectifiedHash] Information about updated milestone. - def edit_milestone(project, id, options={}) - put("/projects/#{project}/milestones/#{id}", :body => options) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/notes.rb b/lib/gitlab-cli/lib/gitlab/client/notes.rb deleted file mode 100644 index 9f53f4df..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/notes.rb +++ /dev/null @@ -1,106 +0,0 @@ -class Gitlab::Client - # Defines methods related to notes. - module Notes - # Gets a list of projects notes. - # - # @example - # Gitlab.notes(5) - # - # @param [Integer] project The ID of a project. - # @return [Array] - def notes(project) - get("/projects/#{project}/notes") - end - - # Gets a list of notes for a issue. - # - # @example - # Gitlab.issue_notes(5, 10) - # - # @param [Integer] project The ID of a project. - # @param [Integer] issue The ID of an issue. - # @return [Array] - def issue_notes(project, issue) - get("/projects/#{project}/issues/#{issue}/notes") - end - - # Gets a list of notes for a snippet. - # - # @example - # Gitlab.snippet_notes(5, 1) - # - # @param [Integer] project The ID of a project. - # @param [Integer] snippet The ID of a snippet. - # @return [Array] - def snippet_notes(project, snippet) - get("/projects/#{project}/snippets/#{snippet}/notes") - end - - # Gets a single wall note. - # - # @example - # Gitlab.note(5, 15) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a note. - # @return [Gitlab::ObjectifiedHash] - def note(project, id) - get("/projects/#{project}/notes/#{id}") - end - - # Gets a single issue note. - # - # @example - # Gitlab.issue_note(5, 10, 1) - # - # @param [Integer] project The ID of a project. - # @param [Integer] issue The ID of an issue. - # @param [Integer] id The ID of a note. - # @return [Gitlab::ObjectifiedHash] - def issue_note(project, issue, id) - get("/projects/#{project}/issues/#{issue}/notes/#{id}") - end - - # Gets a single snippet note. - # - # @example - # Gitlab.snippet_note(5, 11, 3) - # - # @param [Integer] project The ID of a project. - # @param [Integer] snippet The ID of a snippet. - # @param [Integer] id The ID of an note. - # @return [Gitlab::ObjectifiedHash] - def snippet_note(project, snippet, id) - get("/projects/#{project}/snippets/#{snippet}/notes/#{id}") - end - - # Creates a new wall note. - # - # @param [Integer] project The ID of a project. - # @param [String] body The body of a note. - # @return [Gitlab::ObjectifiedHash] Information about created note. - def create_note(project, body) - post("/projects/#{project}/notes", :body => {:body => body}) - end - - # Creates a new issue note. - # - # @param [Integer] project The ID of a project. - # @param [Integer] issue The ID of an issue. - # @param [String] body The body of a note. - # @return [Gitlab::ObjectifiedHash] Information about created note. - def create_issue_note(project, issue, body) - post("/projects/#{project}/issues/#{issue}/notes", :body => {:body => body}) - end - - # Creates a new snippet note. - # - # @param [Integer] project The ID of a project. - # @param [Integer] snippet The ID of a snippet. - # @param [String] body The body of a note. - # @return [Gitlab::ObjectifiedHash] Information about created note. - def create_snippet_note(project, snippet, body) - post("/projects/#{project}/snippets/#{snippet}/notes", :body => {:body => body}) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/projects.rb b/lib/gitlab-cli/lib/gitlab/client/projects.rb deleted file mode 100644 index 4fd8851a..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/projects.rb +++ /dev/null @@ -1,328 +0,0 @@ -class Gitlab::Client - # Defines methods related to projects. - module Projects - # Gets a list of projects owned by the authenticated user. - # - # @example - # Gitlab.projects - # - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @option options [String] :scope Scope of projects. 'owned' for list of projects owned by the authenticated user, 'all' to get all projects (admin only) - # @return [Array] - def projects(options={}) - if (options[:scope]) - get("/projects/#{options[:scope]}", :query => options) - else - get("/projects", :query => options) - end - end - - def current_user_project(user_id, project_name) - get("/projects/current_user_projects?user_id=#{user_id}&project_name=#{project_name}") - end - - # Gets information about a project. - # - # @example - # Gitlab.project(3) - # Gitlab.project('gitlab') - # - # @param [Integer, String] id The ID or name of a project. - # @return [Gitlab::ObjectifiedHash] - def project(id) - get("/projects/#{id}") - end - - # Gets a list of project events. - # - # @example - # Gitlab.project_events(42) - # Gitlab.project_events('gitlab') - # - # @param [Integer, String] project The ID or name of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def project_events(project, options={}) - get("/projects/#{project}/events", :query => options) - end - - # Creates a new project. - # - # @example - # Gitlab.create_project('gitlab') - # Gitlab.create_project('viking', :description => 'Awesome project') - # Gitlab.create_project('Red', :wall_enabled => false) - # - # @param [String] name The name of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :description The description of a project. - # @option options [String] :default_branch The default branch of a project. - # @option options [String] :group_id The group in which to create a project. - # @option options [String] :namespace_id The namespace in which to create a project. - # @option options [Boolean] :wiki_enabled The wiki integration for a project (0 = false, 1 = true). - # @option options [Boolean] :wall_enabled The wall functionality for a project (0 = false, 1 = true). - # @option options [Boolean] :issues_enabled The issues integration for a project (0 = false, 1 = true). - # @option options [Boolean] :snippets_enabled The snippets integration for a project (0 = false, 1 = true). - # @option options [Boolean] :merge_requests_enabled The merge requests functionality for a project (0 = false, 1 = true). - # @option options [Boolean] :public The setting for making a project public (0 = false, 1 = true). - # @option options [Integer] :user_id The user/owner id of a project. - # @return [Gitlab::ObjectifiedHash] Information about created project. - def create_project(name, options={}) - url = options[:user_id] ? "/projects/user/#{options[:user_id]}" : "/projects" - post(url, :body => {:name => name}.merge(options)) - end - - # Updates a project team member to a specified access level. - # id (required) - The ID of a project - # name (optional) - project name - # path (optional) - repository name for project - # description (optional) - short project description - # default_branch (optional) - # issues_enabled (optional) - # merge_requests_enabled (optional) - # wiki_enabled (optional) - # snippets_enabled (optional) - # public (optional) - if true same as setting visibility_level = 20 - # visibility_level (optional) - - def edit_project(id, name, path) - put("/projects/#{id}", :body => {:name => name, :path => path}) - end - - # Deletes a project. - # - # @example - # Gitlab.delete_project(4) - # - # @param [Integer, String] id The ID or name of a project. - # @return [Gitlab::ObjectifiedHash] Information about deleted project. - def delete_project(id) - delete("/projects/#{id}") - end - - # Gets a list of project team members. - # - # @example - # Gitlab.team_members(42) - # Gitlab.team_members('gitlab') - # - # @param [Integer, String] project The ID or name of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :query The search query. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def team_members(project, options={}) - get("/projects/#{project}/members", :query => options) - end - - # Gets a project team member. - # - # @example - # Gitlab.team_member('gitlab', 2) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of a project team member. - # @return [Gitlab::ObjectifiedHash] - def team_member(project, id) - get("/projects/#{project}/members/#{id}") - end - - # Adds a user to project team. - # - # @example - # Gitlab.add_team_member('gitlab', 2, 40) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of a user. - # @param [Integer] access_level The access level to project. - # @param [Hash] options A customizable set of options. - # @return [Gitlab::ObjectifiedHash] Information about added team member. - def add_team_member(project, id, access_level) - post("/projects/#{project}/members", :body => {:user_id => id, :access_level => access_level}) - end - - # Updates a team member's project access level. - # - # @example - # Gitlab.edit_team_member('gitlab', 3, 20) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of a user. - # @param [Integer] access_level The access level to project. - # @param [Hash] options A customizable set of options. - # @return [Array] Information about updated team member. - def edit_team_member(project, id, access_level) - put("/projects/#{project}/members/#{id}", :body => {:access_level => access_level}) - end - - # Removes a user from project team. - # - # @example - # Gitlab.remove_team_member('gitlab', 2) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of a user. - # @param [Hash] options A customizable set of options. - # @return [Gitlab::ObjectifiedHash] Information about removed team member. - def remove_team_member(project, id) - delete("/projects/#{project}/members/#{id}") - end - - # Gets a list of project hooks. - # - # @example - # Gitlab.project_hooks(42) - # Gitlab.project_hooks('gitlab') - # - # @param [Integer, String] project The ID or name of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def project_hooks(project, options={}) - get("/projects/#{project}/hooks", :query => options) - end - - # Gets a project hook. - # - # @example - # Gitlab.project_hook(42, 5) - # Gitlab.project_hook('gitlab', 5) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of a hook. - # @return [Gitlab::ObjectifiedHash] - def project_hook(project, id) - get("/projects/#{project}/hooks/#{id}") - end - - # Adds a new hook to the project. - # - # @example - # Gitlab.add_project_hook(42, 'https://api.example.net/v1/webhooks/ci') - # - # @param [Integer, String] project The ID or name of a project. - # @param [String] url The hook URL. - # @param [Hash] options Events list (`{push_events: true, merge_requests_events: false}`). - # @return [Gitlab::ObjectifiedHash] Information about added hook. - def add_project_hook(project, url, options = {}) - available_events = [:push_events, :merge_requests_events, :issues_events] - passed_events = available_events.select { |event| options[event] } - events = Hash[passed_events.map { |event| [event, options[event]] }] - - post("/projects/#{project}/hooks", :body => {:url => url}.merge(events)) - end - - # Updates a project hook URL. - # - # @example - # Gitlab.edit_project_hook(42, 1, 'https://api.example.net/v1/webhooks/ci') - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of the hook. - # @param [String] url The hook URL. - # @return [Gitlab::ObjectifiedHash] Information about updated hook. - def edit_project_hook(project, id, url) - put("/projects/#{project}/hooks/#{id}", :body => {:url => url}) - end - - # Deletes a hook from project. - # - # @example - # Gitlab.delete_project_hook('gitlab', 4) - # - # @param [Integer, String] project The ID or name of a project. - # @param [String] id The ID of the hook. - # @return [Gitlab::ObjectifiedHash] Information about deleted hook. - def delete_project_hook(project, id) - delete("/projects/#{project}/hooks/#{id}") - end - - # Forks a project into the user namespace of the authenticated user. - # @param [Integer] - The ID of the project to be forked - def fork(gpid, gid) - post ("/projects/fork/#{gpid}?user_id=#{gid}") - # post("/projects/fork/#{id}") - end - - # Mark this project as forked from the other - # - # @example - # Gitlab.make_forked(42, 24) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] id The ID of the project it is forked from. - # @return [Gitlab::ObjectifiedHash] Information about the forked project. - def make_forked_from(project, id) - post("/projects/#{project}/fork/#{id}") - end - - # Remove a forked_from relationship for a project. - # - # @example - # Gitlab.remove_forked(42) - # - # @param [Integer, String] project The ID or name of a project. - # @param [Integer] project The ID of the project it is forked from - # @return [Gitlab::ObjectifiedHash] Information about the forked project. - def remove_forked(project) - delete("/projects/#{project}/fork") - end - - # Gets a project deploy keys. - # - # @example - # Gitlab.deploy_keys(42) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def deploy_keys(project, options={}) - get("/projects/#{project}/keys", :query => options) - end - - # Gets a single project deploy key. - # - # @example - # Gitlab.deploy_key(42, 1) - # - # @param [Integer, String] project The ID of a project. - # @param [Integer] id The ID of a deploy key. - # @return [Gitlab::ObjectifiedHash] - def deploy_key(project, id) - get("/projects/#{project}/keys/#{id}") - end - - # Creates a new deploy key. - # - # @example - # Gitlab.create_deploy_key(42, 'My Key', 'Key contents') - # - # @param [Integer] project The ID of a project. - # @param [String] title The title of a deploy key. - # @param [String] key The content of a deploy key. - # @return [Gitlab::ObjectifiedHash] Information about created deploy key. - def create_deploy_key(project, title, key) - post("/projects/#{project}/keys", body: {title: title, key: key}) - end - - # Deletes a deploy key from project. - # - # @example - # Gitlab.delete_deploy_key(42, 1) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a deploy key. - # @return [Gitlab::ObjectifiedHash] Information about deleted deploy key. - def delete_deploy_key(project, id) - delete("/projects/#{project}/keys/#{id}") - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/repositories.rb b/lib/gitlab-cli/lib/gitlab/client/repositories.rb deleted file mode 100644 index c88337f5..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/repositories.rb +++ /dev/null @@ -1,213 +0,0 @@ -class Gitlab::Client - # Defines methods related to repositories. - module Repositories - - def trees(project, options={}) - get "/projects/#{project}/repository/tree", query: options - end - alias_method :repo_trees, :trees - - def files(project, file_path, ref) - get "/projects/#{project}/repository/files", query: {file_path: file_path, ref: ref} - end - alias_method :repo_files, :files - - def file_blob(project, options={}) - get("/projects/#{project}/repository/blobs", query: options) - end - # Gets a list of project repository tags. - # - # @example - # Gitlab.tags(42) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def tags(project, options={}) - get("/projects/#{project}/repository/tags", :query => options) - end - alias_method :repo_tags, :tags - - # Creates a new project repository tag. - # - # @example - # Gitlab.create_tag(42,'new_tag','master') - # - # @param [Integer] project The ID of a project. - # @param [String] tag_name The name of the new tag. - # @param [String] ref The ref (commit sha, branch name, or another tag) the tag will point to. - # @return [Gitlab::ObjectifiedHash] - def create_tag(project, tag_name, ref) - post("/projects/#{project}/repository/tags", body: {tag_name: tag_name, ref: ref}) - end - alias_method :repo_create_tag, :create_tag - - # Gets a list of project commits. - # - # @example - # Gitlab.commits('viking') - # Gitlab.repo_commits('gitlab', :ref_name => 'api') - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :ref_name The branch or tag name of a project repository. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @option options [String] :search The obj of results's search value. - # @return [Array] - def commits(project, options={}) - get("/projects/#{project}/repository/commits", :query => options) - end - alias_method :repo_commits, :commits - - # Gets a list of project commits. - # - # @example - # Gitlab.commits('viking') - # Gitlab.repo_commits('gitlab', :ref_name => 'api') - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :ref_name The branch or tag name of a project repository. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def commits_total_count(project, options={}) - get("/projects/#{project}/repository/commits_total_count", :query => options) - end - alias_method :repo_commits, :commits_total_count - - # Gets total project commits. - # - # @example - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :rev The branch or tag name of a project repository. - # @return [Hash] - def user_static(project, options={}) - get("/projects/#{project}/repository/user_static", :query => options) - end - - def get_branch_commit_id(project, git_tree, ref_name) - get("/projects/#{project}/repository/get_branch_commit_id?git_tree=#{git_tree}&ref_name=#{ref_name}") - end - - - # Gets a specific commit identified by the commit hash or name of a branch or tag. - # - # @example - # Gitlab.commit(42, '6104942438c14ec7bd21c6cd5bd995272b3faff6') - # Gitlab.repo_commit(3, 'ed899a2f4b50b4370feeea94676502b42383c746') - # - # @param [Integer] project The ID of a project. - # @param [String] sha The commit hash or name of a repository branch or tag - # @return [Gitlab::ObjectifiedHash] - def commit(project, sha) - get("/projects/#{project}/repository/commits/#{sha}") - end - alias_method :repo_commit, :commit - - # Gets a statics of project repository. - # - # @example - # Gitlab.commits('viking') - # Gitlab.repo_commits('gitlab', :ref_name => 'api') - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :ref_name The branch or tag name of a project repository. - # @option options [String] :creator The user name of a project repository. - # @option options [Integer] :period Statistics over time. 1:total 2:one month 3:one week - # @return [Array] - def rep_stats(project, options={}) - get("/projects/#{project}/repository/rep_stats", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - def rep_stats_week(project, options={}) - get("/projects/#{project}/repository/rep_stats_week", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - def rep_stats_month(project, options={}) - get("/projects/#{project}/repository/rep_stats_month", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - def rep_user_stats(project, options={}) - get("/projects/#{project}/repository/rep_user_stats", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - # static all users - def admin_rep_stats_week(project, options={}) - get("/projects/#{project}/repository/admin_rep_stats_week", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - def admin_rep_stats_month(project, options={}) - get("/projects/#{project}/repository/admin_rep_stats_month", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - def admin_rep_stats_all(project, options={}) - get("/projects/#{project}/repository/admin_rep_stats_all", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - # Gets a tree activities of project repository. - # - # @example - # Gitlab.commits('viking') - # Gitlab.repo_commits('gitlab', :ref_name => 'api') - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :ref_name The branch or tag name of a project repository. - # @option options [String] :creator The user name of a project repository. - # @option options [Integer] :period Statistics over time. 1:total 2:one month 3:one week - # @return [Array] - def rep_last_changes(project, options={}) - get("/projects/#{project}/repository/rep_last_changes", :query => options) - end - alias_method :repo_rep_stats, :rep_stats - - # Get the diff of a commit in a project. - # - # @example - # Gitlab.commit_diff(42, '6104942438c14ec7bd21c6cd5bd995272b3faff6') - # Gitlab.repo_commit_diff(3, 'ed899a2f4b50b4370feeea94676502b42383c746') - # - # @param [Integer] project The ID of a project. - # @param [String] sha The name of a repository branch or tag or if not given the default branch. - # @return [Gitlab::ObjectifiedHash] - def commit_diff(project, sha) - get("/projects/#{project}/repository/commits/#{sha}/diff") - end - alias_method :repo_commit_diff, :commit_diff - - # Get the commits count of each contributor in a project - # @param [Integer] project the ID fo a project. - # @return [Gitlab::ObjectifiedHash] - def contributors(project) - get("/projects/#{project}/repository/contributors") - end - - # Get an archive of the repository - # @param [Integer] project the ID fo a project. - # sha (optional) - The commit SHA to download defaults to the tip of the default branch - # @return [Gitlab::ObjectifiedHash] - def project_archive(project, sha) - get("/projects/#{project}/repository/archive?sha=#{sha}") - end - - # update file - def edit_file(project, username, options={}) - put("/projects/#{project}/repository/files?username=#{username}", :body => options) - end - - alias_method :repo_project_archive, :project_archive - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/snippets.rb b/lib/gitlab-cli/lib/gitlab/client/snippets.rb deleted file mode 100644 index aac98560..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/snippets.rb +++ /dev/null @@ -1,86 +0,0 @@ -class Gitlab::Client - # Defines methods related to snippets. - module Snippets - # Gets a list of project's snippets. - # - # @example - # Gitlab.snippets(42) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Gitlab::ObjectifiedHash] - def snippets(project, options={}) - get("/projects/#{project}/snippets", :query => options) - end - - # Gets information about a snippet. - # - # @example - # Gitlab.snippet(2, 14) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a snippet. - # @return [Gitlab::ObjectifiedHash] - def snippet(project, id) - get("/projects/#{project}/snippets/#{id}") - end - - # Creates a new snippet. - # - # @example - # Gitlab.create_snippet(42, {:title => 'REST', :file_name => 'api.rb', :code => 'some code'}) - # - # @param [Integer] project The ID of a project. - # @param [Hash] options A customizable set of options. - # @option options [String] :title (required) The title of a snippet. - # @option options [String] :file_name (required) The name of a snippet file. - # @option options [String] :code (required) The content of a snippet. - # @option options [String] :lifetime (optional) The expiration date of a snippet. - # @return [Gitlab::ObjectifiedHash] Information about created snippet. - def create_snippet(project, options={}) - check_attributes!(options, [:title, :file_name, :code]) - post("/projects/#{project}/snippets", :body => options) - end - - # Updates a snippet. - # - # @example - # Gitlab.edit_snippet(42, 34, :file_name => 'README.txt') - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a snippet. - # @param [Hash] options A customizable set of options. - # @option options [String] :title The title of a snippet. - # @option options [String] :file_name The name of a snippet file. - # @option options [String] :code The content of a snippet. - # @option options [String] :lifetime The expiration date of a snippet. - # @return [Gitlab::ObjectifiedHash] Information about updated snippet. - def edit_snippet(project, id, options={}) - put("/projects/#{project}/snippets/#{id}", :body => options) - end - - # Deletes a snippet. - # - # @example - # Gitlab.delete_snippet(2, 14) - # - # @param [Integer] project The ID of a project. - # @param [Integer] id The ID of a snippet. - # @return [Gitlab::ObjectifiedHash] Information about deleted snippet. - def delete_snippet(project, id) - delete("/projects/#{project}/snippets/#{id}") - end - - private - - def check_attributes!(options, attrs) - attrs.each do |attr| - unless options.has_key?(attr) || options.has_key?(attr.to_s) - raise Gitlab::Error::MissingAttributes.new("Missing '#{attr}' parameter") - end - end - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/system_hooks.rb b/lib/gitlab-cli/lib/gitlab/client/system_hooks.rb deleted file mode 100644 index d8903c6d..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/system_hooks.rb +++ /dev/null @@ -1,58 +0,0 @@ -class Gitlab::Client - # Defines methods related to system hooks. - module SystemHooks - # Gets a list of system hooks. - # - # @example - # Gitlab.hooks - # Gitlab.system_hooks - # - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def hooks(options={}) - get("/hooks", query: options) - end - alias_method :system_hooks, :hooks - - # Adds a new system hook. - # - # @example - # Gitlab.add_hook('http://example.com/hook') - # Gitlab.add_system_hook('https://api.example.net/v1/hook') - # - # @param [String] url The hook URL. - # @return [Gitlab::ObjectifiedHash] - def add_hook(url) - post("/hooks", :body => {:url => url}) - end - alias_method :add_system_hook, :add_hook - - # Tests a system hook. - # - # @example - # Gitlab.hook(3) - # Gitlab.system_hook(12) - # - # @param [Integer] id The ID of a system hook. - # @return [Array] - def hook(id) - get("/hooks/#{id}") - end - alias_method :system_hook, :hook - - # Deletes a new system hook. - # - # @example - # Gitlab.delete_hook(3) - # Gitlab.delete_system_hook(12) - # - # @param [Integer] id The ID of a system hook. - # @return [Gitlab::ObjectifiedHash] - def delete_hook(id) - delete("/hooks/#{id}") - end - alias_method :delete_system_hook, :delete_hook - end -end diff --git a/lib/gitlab-cli/lib/gitlab/client/users.rb b/lib/gitlab-cli/lib/gitlab/client/users.rb deleted file mode 100644 index 6eabe097..00000000 --- a/lib/gitlab-cli/lib/gitlab/client/users.rb +++ /dev/null @@ -1,131 +0,0 @@ -class Gitlab::Client - # Defines methods related to users. - module Users - # Gets a list of users. - # - # @example - # Gitlab.users - # - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def users(options={}) - get("/users", :query => options) - end - - # Gets information about a user. - # Will return information about an authorized user if no ID passed. - # - # @example - # Gitlab.user - # Gitlab.user(2) - # - # @param [Integer] id The ID of a user. - # @return [Gitlab::ObjectifiedHash] - def user(id=nil) - id.to_i.zero? ? get("/user") : get("/users/#{id}") - end - - # Creates a new user. - # Requires authentication from an admin account. - # - # @param [String] email The email of a user. - # @param [String] password The password of a user. - # @param [Hash] options A customizable set of options. - # @option options [String] :name The name of a user. Defaults to email. - # @option options [String] :skype The skype of a user. - # @option options [String] :linkedin The linkedin of a user. - # @option options [String] :twitter The twitter of a user. - # @option options [Integer] :projects_limit The limit of projects for a user. - # @return [Gitlab::ObjectifiedHash] Information about created user. - def create_user(email, password, options={}) - body = {:email => email, :password => password, :name => email}.merge(options) - post("/users", :body => body) - end - - # Updates a user. - # - # @param [Integer] id The ID of a user. - # @param [Hash] options A customizable set of options. - # @option options [String] email The email of a user. - # @option options [String] password The password of a user. - # @option options [String] :name The name of a user. Defaults to email. - # @option options [String] :skype The skype of a user. - # @option options [String] :linkedin The linkedin of a user. - # @option options [String] :twitter The twitter of a user. - # @option options [Integer] :projects_limit The limit of projects for a user. - # @return [Gitlab::ObjectifiedHash] Information about created user. - def edit_user(user_id, options={}) - put("/users/#{user_id}", :body => options) - end - - def edit_user_email(user_id, options={}) - put("/users/#{user_id}/email", :body => options) - end - - def delete_user(user_id) - delete("/users/#{user_id}") - end - - # Creates a new user session. - # - # @example - # Gitlab.session('jack@example.com', 'secret12345') - # - # @param [String] email The email of a user. - # @param [String] password The password of a user. - # @return [Gitlab::ObjectifiedHash] - # @note This method doesn't require private_token to be set. - def session(email, password) - post("/session", :body => {:email => email, :password => password}) - end - - # Gets a list of user's SSH keys. - # - # @example - # Gitlab.ssh_keys - # - # @param [Hash] options A customizable set of options. - # @option options [Integer] :page The page number. - # @option options [Integer] :per_page The number of results per page. - # @return [Array] - def ssh_keys(options={}) - get("/user/keys", :query => options) - end - - # Gets information about SSH key. - # - # @example - # Gitlab.ssh_key(1) - # - # @param [Integer] id The ID of a user's SSH key. - # @return [Gitlab::ObjectifiedHash] - def ssh_key(id) - get("/user/keys/#{id}") - end - - # Creates a new SSH key. - # - # @example - # Gitlab.create_ssh_key('key title', 'key body') - # - # @param [String] title The title of an SSH key. - # @param [String] key The SSH key body. - # @return [Gitlab::ObjectifiedHash] Information about created SSH key. - def create_ssh_key(title, key) - post("/user/keys", :body => {:title => title, :key => key}) - end - - # Deletes an SSH key. - # - # @example - # Gitlab.delete_ssh_key(1) - # - # @param [Integer] id The ID of a user's SSH key. - # @return [Gitlab::ObjectifiedHash] Information about deleted SSH key. - def delete_ssh_key(id) - delete("/user/keys/#{id}") - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/configuration.rb b/lib/gitlab-cli/lib/gitlab/configuration.rb deleted file mode 100644 index 30a2d092..00000000 --- a/lib/gitlab-cli/lib/gitlab/configuration.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Gitlab - # Defines constants and methods related to configuration. - module Configuration - # An array of valid keys in the options hash when configuring a Gitlab::API. - VALID_OPTIONS_KEYS = [:endpoint, :private_token, :user_agent, :sudo, :httparty].freeze - - # The user agent that will be sent to the API endpoint if none is set. - DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}".freeze - - # @private - attr_accessor(*VALID_OPTIONS_KEYS) - - # Sets all configuration options to their default values - # when this module is extended. - def self.extended(base) - base.reset - end - - # Convenience method to allow configuration options to be set in a block. - def configure - yield self - end - - # Creates a hash of options and their values. - def options - VALID_OPTIONS_KEYS.inject({}) do |option, key| - option.merge!(key => send(key)) - end - end - - # Resets all configuration options to the defaults. - def reset - self.endpoint = ENV['GITLAB_API_ENDPOINT'] - self.private_token = ENV['GITLAB_API_PRIVATE_TOKEN'] - self.sudo = nil - self.user_agent = DEFAULT_USER_AGENT - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/error.rb b/lib/gitlab-cli/lib/gitlab/error.rb deleted file mode 100644 index 177d261d..00000000 --- a/lib/gitlab-cli/lib/gitlab/error.rb +++ /dev/null @@ -1,45 +0,0 @@ -module Gitlab - module Error - # Custom error class for rescuing from all Gitlab errors. - class Error < StandardError; end - - # Raise when attributes are missing. - class MissingAttributes < Error; end - - # Raised when API endpoint credentials not configured. - class MissingCredentials < Error; end - - # Raised when impossible to parse response body. - class Parsing < Error; end - - # Raised when API endpoint returns the HTTP status code 400. - class BadRequest < Error; end - - # Raised when API endpoint returns the HTTP status code 401. - class Unauthorized < Error; end - - # Raised when API endpoint returns the HTTP status code 403. - class Forbidden < Error; end - - # Raised when API endpoint returns the HTTP status code 404. - class NotFound < Error; end - - # Raised when API endpoint returns the HTTP status code 405. - class MethodNotAllowed < Error; end - - # Raised when API endpoint returns the HTTP status code 406. - class DataNotAccepted < Error; end - - # Raised when API endpoint returns the HTTP status code 409. - class Conflict < Error; end - - # Raised when API endpoint returns the HTTP status code 500. - class InternalServerError < Error; end - - # Raised when API endpoint returns the HTTP status code 502. - class BadGateway < Error; end - - # Raised when API endpoint returns the HTTP status code 503. - class ServiceUnavailable < Error; end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/help.rb b/lib/gitlab-cli/lib/gitlab/help.rb deleted file mode 100644 index ccd2f2ff..00000000 --- a/lib/gitlab-cli/lib/gitlab/help.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'gitlab' -require 'gitlab/cli_helpers' - -module Gitlab::Help - extend Gitlab::CLI::Helpers - - def self.get_help(methods,cmd=nil) - help = '' - - if cmd.nil? || cmd == 'help' - help = actions_table - else - ri_cmd = `which ri`.chomp - - if $? == 0 - namespace = methods.select {|m| m[:name] === cmd }.map {|m| m[:owner]+'.'+m[:name] }.shift - - if namespace - begin - ri_output = `#{ri_cmd} -T #{namespace} 2>&1`.chomp - - if $? == 0 - ri_output.gsub!(/#{cmd}\((.*?)\)/, cmd+' \1') - ri_output.gsub!(/Gitlab\./, 'gitlab> ') - ri_output.gsub!(/Gitlab\..+$/, '') - ri_output.gsub!(/\,\s?/, ' ') - help = ri_output - else - help = "Ri docs not found for #{namespace}, please install the docs to use 'help'" - end - rescue => e - puts e.message - end - else - help = "Unknown command: #{cmd}" - end - else - help = "'ri' tool not found in your PATH, please install it to use the help." - end - end - - puts help - end -end diff --git a/lib/gitlab-cli/lib/gitlab/objectified_hash.rb b/lib/gitlab-cli/lib/gitlab/objectified_hash.rb deleted file mode 100644 index 11436da9..00000000 --- a/lib/gitlab-cli/lib/gitlab/objectified_hash.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Gitlab - # Converts hashes to the objects. - class ObjectifiedHash - # Creates a new ObjectifiedHash object. - def initialize(hash) - @hash = hash - @data = hash.inject({}) do |data, (key,value)| - value = ObjectifiedHash.new(value) if value.is_a? Hash - data[key.to_s] = value - data - end - end - - def to_hash - @hash - end - alias_method :to_h, :to_hash - - # Delegate to ObjectifiedHash. - def method_missing(key) - @data.key?(key.to_s) ? @data[key.to_s] : nil - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/request.rb b/lib/gitlab-cli/lib/gitlab/request.rb deleted file mode 100644 index 49c6ef8e..00000000 --- a/lib/gitlab-cli/lib/gitlab/request.rb +++ /dev/null @@ -1,116 +0,0 @@ -require 'httparty' -require 'json' - -module Gitlab - # @private - class Request - include HTTParty - format :json - headers 'Accept' => 'application/json' - parser Proc.new { |body, _| parse(body) } - - attr_accessor :private_token - - # Converts the response body to an ObjectifiedHash. - def self.parse(body) - body = decode(body) - - if body.is_a? Hash - ObjectifiedHash.new body - elsif body.is_a? Array - body.collect! { |e| ObjectifiedHash.new(e) } - elsif body == true - body - else - raise Error::Parsing.new "Couldn't parse a response body" - end - end - - # Decodes a JSON response into Ruby object. - def self.decode(response) - begin - JSON.load response - rescue JSON::ParserError - raise Error::Parsing.new "The response is not a valid JSON" - end - end - - def get(path, options={}) - set_httparty_config(options) - set_private_token_header(options) - validate self.class.get(path, options) - end - - def post(path, options={}) - set_httparty_config(options) - set_private_token_header(options, path) - validate self.class.post(path, options) - end - - def put(path, options={}) - set_httparty_config(options) - set_private_token_header(options) - validate self.class.put(path, options) - end - - def delete(path, options={}) - set_httparty_config(options) - set_private_token_header(options) - validate self.class.delete(path, options) - end - - # Checks the response code for common errors. - # Returns parsed response for successful requests. - def validate(response) - # case response.code - # when 400; raise Error::BadRequest.new error_message(response) - # when 401; raise Error::Unauthorized.new error_message(response) - # when 403; raise Error::Forbidden.new error_message(response) - # when 404; raise Error::NotFound.new error_message(response) - # when 405; raise Error::MethodNotAllowed.new error_message(response) - # when 406; raise Error::DataNotAccepted.new error_message(response) - # when 409; raise Error::Conflict.new error_message(response) - # when 500; raise Error::InternalServerError.new error_message(response) - # when 502; raise Error::BadGateway.new error_message(response) - # when 503; raise Error::ServiceUnavailable.new error_message(response) - # end - - response.parsed_response - 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 Error::MissingCredentials.new("Please set an endpoint to API") unless endpoint - @private_token = private_token - - self.class.base_uri endpoint - self.class.default_params :sudo => sudo - self.class.default_params.delete(:sudo) if sudo.nil? - end - - private - - # Sets a PRIVATE-TOKEN header for requests. - # @raise [Error::MissingCredentials] if private_token not set. - def set_private_token_header(options, path=nil) - unless path == '/session' - raise Error::MissingCredentials.new("Please set a private_token for user") unless @private_token - options[:headers] = {'PRIVATE-TOKEN' => @private_token} - end - end - - # Set HTTParty configuration - # @see https://github.com/jnunemaker/httparty - def set_httparty_config(options) - if self.httparty - options.merge!(self.httparty) - end - end - - def error_message(response) - "Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \ - "Request URI: #{response.request.base_uri}#{response.request.path}" - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/shell.rb b/lib/gitlab-cli/lib/gitlab/shell.rb deleted file mode 100644 index 58925b64..00000000 --- a/lib/gitlab-cli/lib/gitlab/shell.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'gitlab' -require 'gitlab/help' -require 'gitlab/cli_helpers' -require 'readline' - -class Gitlab::Shell - extend Gitlab::CLI::Helpers - - def self.start - actions = Gitlab.actions - - comp = proc { |s| actions.map(&:to_s).grep(/^#{Regexp.escape(s)}/) } - - Readline.completion_proc = comp - Readline.completion_append_character = ' ' - - client = Gitlab::Client.new(endpoint: '') - - while buf = Readline.readline('gitlab> ', true) - next if buf.nil? || buf.empty? - break if buf == 'exit' - - buf = buf.scan(/["][^"]+["]|\S+/).map { |word| word.gsub(/^['"]|['"]$/,'') } - cmd = buf.shift - args = buf.count > 0 ? buf : [] - - if cmd == 'help' - methods = [] - - actions.each do |action| - methods << { - name: action.to_s, - owner: client.method(action).owner.to_s - } - end - - args[0].nil? ? Gitlab::Help.get_help(methods) : Gitlab::Help.get_help(methods, args[0]) - next - end - - data = if actions.include?(cmd.to_sym) - confirm_command(cmd) - gitlab_helper(cmd, args) - else - "'#{cmd}' is not a valid command. See the 'help' for a list of valid commands." - end - - output_table(cmd, args, data) - end - end -end diff --git a/lib/gitlab-cli/lib/gitlab/version.rb b/lib/gitlab-cli/lib/gitlab/version.rb deleted file mode 100644 index a1783b69..00000000 --- a/lib/gitlab-cli/lib/gitlab/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Gitlab - VERSION = "3.2.0" -end diff --git a/lib/gitlab-cli/spec/fixtures/branch.json b/lib/gitlab-cli/spec/fixtures/branch.json deleted file mode 100644 index 8756f9f6..00000000 --- a/lib/gitlab-cli/spec/fixtures/branch.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected": true} diff --git a/lib/gitlab-cli/spec/fixtures/branches.json b/lib/gitlab-cli/spec/fixtures/branches.json deleted file mode 100644 index 94aa4757..00000000 --- a/lib/gitlab-cli/spec/fixtures/branches.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"}},{"name":"dashboard-feed","commit":{"id":"f8f6ff065eccc6ede4d35ed87a09bb962b84ca25","parents":[{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e"}],"tree":"e17f2157143d550891d4669c10b7446e4739bc6d","message":"add projects atom feed","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-31T23:42:02-07:00","committed_date":"2012-05-31T23:42:02-07:00"}},{"name":"master","commit":{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e","parents":[{"id":"af226ae9c9af406c8a0e0bbdf364563495c2f432"},{"id":"e851cb07762aa464aae10e8b4b28de87c1a6f925"}],"tree":"6c6845838039f01723d91f395a1d2fa1dcc82522","message":"Merge pull request #868 from SaitoWu/bugfix/encoding\n\nBugfix/encoding","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-05-30T00:24:43-07:00","committed_date":"2012-05-30T00:24:43-07:00"}},{"name":"preview_notes","commit":{"id":"3749e0d99ac6bfbc65889b1b7a5310e14e7fe89a","parents":[{"id":"2483181f2c3d4ea7d2c68147b19bc07fc3937b0c"}],"tree":"f8c56161b0d6561568f088df9961362eb1ece88b","message":"pass project_id to notes preview path","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-08-09T23:46:27-07:00","committed_date":"2012-08-09T23:46:27-07:00"}},{"name":"refactoring","commit":{"id":"7c7761099cae83f59fe5780340e100be890847b2","parents":[{"id":"058d80b3363dd4fc4417ca4f60f76119188a2470"}],"tree":"d7d4a94c700dc0e84ee943019213d2358a49c413","message":"fix deprecation warnings","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-29T07:16:28-07:00","committed_date":"2012-05-29T07:16:28-07:00"}}] diff --git a/lib/gitlab-cli/spec/fixtures/comment_merge_request.json b/lib/gitlab-cli/spec/fixtures/comment_merge_request.json deleted file mode 100644 index 742f3337..00000000 --- a/lib/gitlab-cli/spec/fixtures/comment_merge_request.json +++ /dev/null @@ -1 +0,0 @@ -{"note":"Cool Merge Request!","author":{"id":1,"username":"jsmith","email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-07-11T01:32:18Z"}} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/create_branch.json b/lib/gitlab-cli/spec/fixtures/create_branch.json deleted file mode 100644 index a24df91a..00000000 --- a/lib/gitlab-cli/spec/fixtures/create_branch.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"api","commit":{ "id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","message":"API: expose issues project id","parent_ids":["949b1df930bedace1dbd755aaa4a82e8c451a616"],"authored_date":"2012-07-25T04:22:21-07:00","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","committed_date":"2012-07-25T04:22:21-07:00","committer_name":"Nihad Abbasov","committer_email":"narkoz.2008@gmail.com"},"protected": false} diff --git a/lib/gitlab-cli/spec/fixtures/create_merge_request.json b/lib/gitlab-cli/spec/fixtures/create_merge_request.json deleted file mode 100644 index c2743516..00000000 --- a/lib/gitlab-cli/spec/fixtures/create_merge_request.json +++ /dev/null @@ -1 +0,0 @@ -{"id":2,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/error_already_exists.json b/lib/gitlab-cli/spec/fixtures/error_already_exists.json deleted file mode 100644 index d1070f56..00000000 --- a/lib/gitlab-cli/spec/fixtures/error_already_exists.json +++ /dev/null @@ -1 +0,0 @@ -{"message": "409 Already exists"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/group.json b/lib/gitlab-cli/spec/fixtures/group.json deleted file mode 100644 index 16620ad6..00000000 --- a/lib/gitlab-cli/spec/fixtures/group.json +++ /dev/null @@ -1,60 +0,0 @@ -{"id": 10, "name": "GitLab-Group", "path": "gitlab-group", "owner_id": 6, "projects": [ - { - "id": 9, - "name": "mojito", - "description": null, - "default_branch": "master", - "owner": { - "id": 6, - "username": "jose", - "email": "jose@abc.com", - "name": "Jose Jose", - "blocked": false, - "created_at": "2013-02-06T06:54:06Z" - }, - "path": "mojito", - "path_with_namespace": "gitlab-group/mojito", - "issues_enabled": true, - "merge_requests_enabled": true, - "wall_enabled": true, - "wiki_enabled": true, - "created_at": "2013-02-06T16:59:15Z", - "namespace": { - "created_at": "2013-02-06T16:58:22Z", - "id": 10, - "name": "GitLab-Group", - "owner_id": 6, - "path": "gitlab-group", - "updated_at": "2013-02-06T16:58:22Z" - } - }, - { - "id": 10, - "name": "gitlabhq", - "description": null, - "default_branch": null, - "owner": { - "id": 6, - "username": "randx", - "email": "randx@github.com", - "name": "Dmitry Z", - "blocked": false, - "created_at": "2013-02-06T06:54:06Z" - }, - "path": "gitlabhq", - "path_with_namespace": "gitlab-group/gitlabhq", - "issues_enabled": true, - "merge_requests_enabled": true, - "wall_enabled": true, - "wiki_enabled": true, - "created_at": "2013-02-06T17:02:31Z", - "namespace": { - "created_at": "2013-02-06T16:58:22Z", - "id": 10, - "name": "GitLab-Group", - "owner_id": 6, - "path": "gitlab-group", - "updated_at": "2013-02-06T16:58:22Z" - } - } -]} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/group_create.json b/lib/gitlab-cli/spec/fixtures/group_create.json deleted file mode 100644 index 67445f68..00000000 --- a/lib/gitlab-cli/spec/fixtures/group_create.json +++ /dev/null @@ -1 +0,0 @@ -{"id":3,"name":"Gitlab-Group","path":"gitlab-group","owner_id":1} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/group_member.json b/lib/gitlab-cli/spec/fixtures/group_member.json deleted file mode 100644 index feef5432..00000000 --- a/lib/gitlab-cli/spec/fixtures/group_member.json +++ /dev/null @@ -1 +0,0 @@ -{"id":2,"username":"jsmith","email":"jsmith@local.host","name":"John Smith","state":"active","created_at":"2013-09-04T18:15:30Z","access_level":10} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/group_member_delete.json b/lib/gitlab-cli/spec/fixtures/group_member_delete.json deleted file mode 100644 index ff052edf..00000000 --- a/lib/gitlab-cli/spec/fixtures/group_member_delete.json +++ /dev/null @@ -1 +0,0 @@ -{"created_at":"2013-09-04T18:18:15Z","group_access":10,"group_id":3,"id":2,"notification_level":3,"updated_at":"2013-09-04T18:18:15Z","user_id":2} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/group_members.json b/lib/gitlab-cli/spec/fixtures/group_members.json deleted file mode 100644 index 02ddc108..00000000 --- a/lib/gitlab-cli/spec/fixtures/group_members.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"username":"eraymond","email":"eraymond@local.host","name":"Edward Raymond","state":"active","created_at":"2013-08-30T16:16:22Z","access_level":50},{"id":1,"username":"jsmith","email":"jsmith@local.host","name":"John Smith","state":"active","created_at":"2013-08-30T16:16:22Z","access_level":50}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/groups.json b/lib/gitlab-cli/spec/fixtures/groups.json deleted file mode 100644 index 5811774a..00000000 --- a/lib/gitlab-cli/spec/fixtures/groups.json +++ /dev/null @@ -1,2 +0,0 @@ -[{"id": 3,"name": "ThreeGroup","path": "threegroup","owner_id": 1},{"id": 5,"name": "Five-Group","path": "five-group","owner_id": 2},{"id": 8,"name": "Eight Group","path": "eight-group","owner_id": 6} -] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/issue.json b/lib/gitlab-cli/spec/fixtures/issue.json deleted file mode 100644 index 9f70318a..00000000 --- a/lib/gitlab-cli/spec/fixtures/issue.json +++ /dev/null @@ -1 +0,0 @@ -{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/issues.json b/lib/gitlab-cli/spec/fixtures/issues.json deleted file mode 100644 index 62e4cadd..00000000 --- a/lib/gitlab-cli/spec/fixtures/issues.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"project_id":1,"title":"Culpa eius recusandae suscipit autem distinctio dolorum.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":6,"project_id":2,"title":"Ut in dolorum omnis sed sit aliquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":21,"project_id":1,"title":"Vitae ea aliquam et quo eligendi sapiente voluptatum labore hic nihil culpa.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":26,"project_id":2,"title":"Quo enim est nihil atque placeat voluptas neque eos voluptas.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/key.json b/lib/gitlab-cli/spec/fixtures/key.json deleted file mode 100644 index cd21098c..00000000 --- a/lib/gitlab-cli/spec/fixtures/key.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"} diff --git a/lib/gitlab-cli/spec/fixtures/keys.json b/lib/gitlab-cli/spec/fixtures/keys.json deleted file mode 100644 index db3bbea8..00000000 --- a/lib/gitlab-cli/spec/fixtures/keys.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"}] diff --git a/lib/gitlab-cli/spec/fixtures/merge_request.json b/lib/gitlab-cli/spec/fixtures/merge_request.json deleted file mode 100644 index 5278f466..00000000 --- a/lib/gitlab-cli/spec/fixtures/merge_request.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/merge_request_comments.json b/lib/gitlab-cli/spec/fixtures/merge_request_comments.json deleted file mode 100644 index 4e507668..00000000 --- a/lib/gitlab-cli/spec/fixtures/merge_request_comments.json +++ /dev/null @@ -1 +0,0 @@ -[{"note":"this is the 1st comment on the 2merge merge request","author":{"id":11,"username":"admin","email":"admin@example.com","name":"A User","state":"active","created_at":"2014-03-06T08:17:35.000Z"}},{"note":"another discussion point on the 2merge request","author":{"id":12,"username":"admin","email":"admin@example.com","name":"A User","state":"active","created_at":"2014-03-06T08:17:35.000Z"}}] diff --git a/lib/gitlab-cli/spec/fixtures/merge_requests.json b/lib/gitlab-cli/spec/fixtures/merge_requests.json deleted file mode 100644 index 33153c0c..00000000 --- a/lib/gitlab-cli/spec/fixtures/merge_requests.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}}] diff --git a/lib/gitlab-cli/spec/fixtures/milestone.json b/lib/gitlab-cli/spec/fixtures/milestone.json deleted file mode 100644 index 94ea3d36..00000000 --- a/lib/gitlab-cli/spec/fixtures/milestone.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/milestones.json b/lib/gitlab-cli/spec/fixtures/milestones.json deleted file mode 100644 index f9e309af..00000000 --- a/lib/gitlab-cli/spec/fixtures/milestones.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/note.json b/lib/gitlab-cli/spec/fixtures/note.json deleted file mode 100644 index 9cff9072..00000000 --- a/lib/gitlab-cli/spec/fixtures/note.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1201,"body":"The solution is rather tricky","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"created_at":"2012-11-27T19:16:44Z"} diff --git a/lib/gitlab-cli/spec/fixtures/notes.json b/lib/gitlab-cli/spec/fixtures/notes.json deleted file mode 100644 index e8fa27bf..00000000 --- a/lib/gitlab-cli/spec/fixtures/notes.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1201,"body":"The solution is rather tricky","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"created_at":"2012-11-27T19:16:44Z"},{"id":1207,"body":"I know, right?","author":{"id":1,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"created_at":"2012-11-27T19:58:21Z"}] diff --git a/lib/gitlab-cli/spec/fixtures/project.json b/lib/gitlab-cli/spec/fixtures/project.json deleted file mode 100644 index 1f4f9602..00000000 --- a/lib/gitlab-cli/spec/fixtures/project.json +++ /dev/null @@ -1 +0,0 @@ -{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"public":false,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_commit.json b/lib/gitlab-cli/spec/fixtures/project_commit.json deleted file mode 100644 index ab29f6b7..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_commit.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", - "short_id": "6104942438c", - "title": "Sanitize for network graph", - "author_name": "randx", - "author_email": "dmitriy.zaporozhets@gmail.com", - "created_at": "2012-09-20T09:06:12+03:00", - "committed_date": "2012-09-20T09:06:12+03:00", - "authored_date": "2012-09-20T09:06:12+03:00", - "parent_ids": [ - "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" - ] -} diff --git a/lib/gitlab-cli/spec/fixtures/project_commit_diff.json b/lib/gitlab-cli/spec/fixtures/project_commit_diff.json deleted file mode 100644 index 1c3ce017..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_commit_diff.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files", - "new_path": "doc/update/5.4-to-6.0.md", - "old_path": "doc/update/5.4-to-6.0.md", - "a_mode": null, - "b_mode": "100644", - "new_file": false, - "renamed_file": false, - "deleted_file": false -} diff --git a/lib/gitlab-cli/spec/fixtures/project_commits.json b/lib/gitlab-cli/spec/fixtures/project_commits.json deleted file mode 100644 index 58cb5020..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_commits.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","short_id":"f7dd067490f","title":"API: expose issues project id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T04:22:21-07:00"},{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616","short_id":"949b1df930b","title":"API: update docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:35:41-07:00"},{"id":"1b95c8bff351f6718ec31ac1de1e48c57bc95d44","short_id":"1b95c8bff35","title":"API: ability to get project by id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:18:30-07:00"},{"id":"92d98f5a0c28bffd7b070cda190b07ab72667d58","short_id":"92d98f5a0c2","title":"Merge pull request #1118 from patthoyts/pt/ldap-missing-password","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:51:06-07:00"},{"id":"60d3e94874964a626f105d3598e1c122addcf43e","short_id":"60d3e948749","title":"Merge pull request #1122 from patthoyts/pt/missing-log","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:50:34-07:00"},{"id":"b683a71aa1230f17f9df47661c77dfeae27027de","short_id":"b683a71aa12","title":"Merge pull request #1135 from NARKOZ/api","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:48:00-07:00"},{"id":"fbb41100db35cf2def2c8b4d896b7015d56bd15b","short_id":"fbb41100db3","title":"update help section with issues API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:52:43-07:00"},{"id":"eca823c1c7cef45cc18c6ab36d2327650c85bfc3","short_id":"eca823c1c7c","title":"Merge branch 'master' into api","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:46:36-07:00"},{"id":"024e0348904179a8dea81c01e27a5f014cf57499","short_id":"024e0348904","title":"update API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:25:01-07:00"},{"id":"7b33d8cbcab3b0ee5789ec607455ab62130db69f","short_id":"7b33d8cbcab","title":"add issues API","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:19:51-07:00"},{"id":"6035ad7e1fe519d0c6a42731790183889e3ba31d","short_id":"6035ad7e1fe","title":"Create the githost.log file if necessary.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T07:32:04-07:00"},{"id":"a2d244ec062f3348f6cd1c5218c6097402c5f562","short_id":"a2d244ec062","title":"Handle LDAP missing credentials error with a flash message.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T01:04:05-07:00"},{"id":"8b7e404b5b6944e9c92cc270b2e5d0005781d49d","short_id":"8b7e404b5b6","title":"Up to 2.7.0","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:53:55-07:00"},{"id":"11721b0dbe82c35789be3e4fa8e14663934b2ff5","short_id":"11721b0dbe8","title":"Help section for system hooks completed","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:47:57-07:00"},{"id":"9c8a1e651716212cf50a623d98e03b8dbdb2c64a","short_id":"9c8a1e65171","title":"Fix system hook example","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:32:42-07:00"},{"id":"4261acda90ff4c61326d80cba026ae76e8551f8f","short_id":"4261acda90f","title":"move SSH keys tab closer to begining","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:27:09-07:00"},{"id":"a69fc5dd23bd502fd36892a80eec21a4c53891f8","short_id":"a69fc5dd23b","title":"Endless event loading for dsahboard","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:23:05-07:00"},{"id":"860fa1163a5fbdfec2bb01ff2d584351554dee29","short_id":"860fa1163a5","title":"Merge pull request #1117 from patthoyts/pt/user-form","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T14:23:49-07:00"},{"id":"787e5e94acf5e20280416c9fda105ef5b77576b3","short_id":"787e5e94acf","title":"Fix english on the edit user form.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-20T14:18:42-07:00"},{"id":"9267cb04b0b3fdf127899c4b7e636dc27fac06d3","short_id":"9267cb04b0b","title":"Merge branch 'refactoring_controllers' of dev.gitlabhq.com:gitlabhq","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T07:24:56-07:00"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_delete_key.json b/lib/gitlab-cli/spec/fixtures/project_delete_key.json deleted file mode 100644 index 9ff86833..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_delete_key.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "created_at": "2013-10-05T15:05:26Z", - "fingerprint": "5c:b5:e6:b0:f5:31:65:3f:a6:b5:59:86:32:cc:15:e1", - "id": 2, - "key": "ssh-rsa ...", - "updated_at": "2013-10-05T15:05:26Z", - "user_id": null -} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_events.json b/lib/gitlab-cli/spec/fixtures/project_events.json deleted file mode 100644 index e9fa22fe..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_events.json +++ /dev/null @@ -1 +0,0 @@ -[{"title":null,"project_id":2,"action_name":"opened","target_id":null,"target_type":null,"author_id":1,"data":{"before":"ac0c1aa3898d6dea54d7868ea6f9c45fd5e30c59","after":"66350dbb62a221bc619b665aef3e1e7d3b306747","ref":"refs/heads/master","user_id":1,"user_name":"Administrator","project_id":2,"repository":{"name":"gitlab-ci","url":"git@demo.gitlab.com:gitlab/gitlab-ci.git","description":"Continuous integration server for gitlabhq | Coordinator","homepage":"http://demo.gitlab.com/gitlab/gitlab-ci"},"commits":[{"id":"8cf469b039931bab37bbf025e6b69287ea3cfb0e","message":"Modify screenshot\n\nSigned-off-by: Dmitriy Zaporozhets \u003Cdummy@gmail.com\u003E","timestamp":"2014-05-20T10:34:27+00:00","url":"http://demo.gitlab.com/gitlab/gitlab-ci/commit/8cf469b039931bab37bbf025e6b69287ea3cfb0e","author":{"name":"Dummy","email":"dummy@gmail.com"}},{"id":"66350dbb62a221bc619b665aef3e1e7d3b306747","message":"Edit some code\n\nSigned-off-by: Dmitriy Zaporozhets \u003Cdummy@gmail.com\u003E","timestamp":"2014-05-20T10:35:15+00:00","url":"http://demo.gitlab.com/gitlab/gitlab-ci/commit/66350dbb62a221bc619b665aef3e1e7d3b306747","author":{"name":"Dummy","email":"dummy@gmail.com"}}],"total_commits_count":2},"target_title":null,"created_at":"2014-05-20T10:35:26.240Z"},{"title":null,"project_id":2,"action_name":"opened","target_id":2,"target_type":"MergeRequest","author_id":1,"data":null,"target_title":" Morbi et cursus leo. Sed eget vestibulum sapien","created_at":"2014-05-20T10:24:11.917Z"}] diff --git a/lib/gitlab-cli/spec/fixtures/project_for_user.json b/lib/gitlab-cli/spec/fixtures/project_for_user.json deleted file mode 100644 index 5ffc888f..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_for_user.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"code":"brute","name":"Brute","description":null,"path":"brute","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Owner","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:56Z"} diff --git a/lib/gitlab-cli/spec/fixtures/project_fork_link.json b/lib/gitlab-cli/spec/fixtures/project_fork_link.json deleted file mode 100644 index f1490dfa..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_fork_link.json +++ /dev/null @@ -1 +0,0 @@ -{"created_at":"2013-07-03T13:51:48Z","forked_from_project_id":24,"forked_to_project_id":42,"id":1,"updated_at":"2013-07-03T13:51:48Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_hook.json b/lib/gitlab-cli/spec/fixtures/project_hook.json deleted file mode 100644 index 323741cf..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_hook.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"url":"https://api.example.net/v1/webhooks/ci"} diff --git a/lib/gitlab-cli/spec/fixtures/project_hooks.json b/lib/gitlab-cli/spec/fixtures/project_hooks.json deleted file mode 100644 index e70d4122..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_hooks.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"url":"https://api.example.net/v1/webhooks/ci"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_issues.json b/lib/gitlab-cli/spec/fixtures/project_issues.json deleted file mode 100644 index 87fb2fb1..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_issues.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":36,"project_id":3,"title":"Eos ut modi et laudantium quasi porro voluptas sed.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":35,"project_id":3,"title":"Ducimus illo in iure voluptatem dolores labore.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":34,"project_id":3,"title":"Rem tempora voluptatum atque eum sit nihil neque.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":16,"project_id":3,"title":"Numquam earum aut laudantium reprehenderit voluptatem aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":15,"project_id":3,"title":"Qui veritatis voluptas fuga voluptate voluptas cupiditate.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":14,"project_id":3,"title":"In assumenda et ipsa qui debitis voluptatem incidunt.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":13,"project_id":3,"title":"Illo eveniet consequatur enim iste provident facilis rerum voluptatem et architecto aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_key.json b/lib/gitlab-cli/spec/fixtures/project_key.json deleted file mode 100644 index 6dd70d23..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_key.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "id": 2, - "title": "Key Title", - "key": "ssh-rsa ...", - "created_at": "2013-09-22T18:34:32Z" -} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_keys.json b/lib/gitlab-cli/spec/fixtures/project_keys.json deleted file mode 100644 index 0a3869d3..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_keys.json +++ /dev/null @@ -1,6 +0,0 @@ -[{ - "id": 2, - "title": "Key Title", - "key": "ssh-rsa ...", - "created_at": "2013-09-22T18:34:32Z" -}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/project_tags.json b/lib/gitlab-cli/spec/fixtures/project_tags.json deleted file mode 100644 index 1e2fb96c..00000000 --- a/lib/gitlab-cli/spec/fixtures/project_tags.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"v2.8.2","commit":{"id":"a502f67c0b358cc6b391df0c5dca48375c21fcad","parents":[{"id":"4381084af341684240b1a671d368511afcf5774a"}],"tree":"1612068bdd20de5d14b3096cfa4c621e2051ed4c","message":"Up to 2.8.2","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-24T02:03:48-07:00","committed_date":"2012-08-24T02:03:48-07:00"}},{"name":"v2.8.1","commit":{"id":"ed2b53cd1c34c421b23208eeb502a141a6829f9d","parents":[{"id":"7ab587a47791e371f5c109c14097a5d1d7776ea5"}],"tree":"b7393b0b33b777583b285e85b423c4e5ab7f859f","message":"Up to 2.8.1","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-22T23:17:18-07:00","committed_date":"2012-08-22T23:17:18-07:00"}},{"name":"v2.8.0pre","commit":{"id":"b2c6ba97a25d299e83c51493d7bc770c13b8ed1a","parents":[{"id":"05da3801f53f06fdc529b4f3820af1380039f245"},{"id":"66399d558da45fb9cd3ea972a47a4f7bb12bfc8d"}],"tree":"36ad53f35bce1fe3f2a4a5f840e7b1bdbfed9c82","message":"Merge pull request #1230 from tsigo/hooray_apostrophes\n\nCorrect usage of \"Can't\"","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-16T14:11:08-07:00","committed_date":"2012-08-16T14:11:08-07:00"}},{"name":"v2.8.0","commit":{"id":"5c7ed6fa26b47ac71ff6ba04720d85df6d74b200","parents":[{"id":"d1daeba1736ba145fe525ce08a91f29495a3abf1"}],"tree":"4fc230ff2dbc0e75f27321eac2976aba5a6d323d","message":"Up to 2.8","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-08-21T15:15:26-07:00","committed_date":"2012-08-21T15:15:26-07:00"}},{"name":"v2.7.0pre","commit":{"id":"72a571724d84d112f98a5543c971e9b3b9da1383","parents":[{"id":"3ac840ff06e0ee5b349c52b5a8c02e803a17eec3"},{"id":"990b9217d9a55e26a53d4143d4a3c89123384327"}],"tree":"64b104df5d956e21e0749dc8e70849d1989de36f","message":"Merge pull request #1096 from moregeek/show-flash-note-when-destroying-a-project\n\nshow flash notice after deletion of a project","author":{"name":"Valeriy Sizov","email":"vsv2711@gmail.com"},"committer":{"name":"Valeriy Sizov","email":"vsv2711@gmail.com"},"authored_date":"2012-07-18T05:35:42-07:00","committed_date":"2012-07-18T05:35:42-07:00"}},{"name":"v2.7.0","commit":{"id":"8b7e404b5b6944e9c92cc270b2e5d0005781d49d","parents":[{"id":"11721b0dbe82c35789be3e4fa8e14663934b2ff5"}],"tree":"89fe8c5ff58daaedea07a910cffb14b04ebcc828","message":"Up to 2.7.0","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-07-21T00:53:55-07:00","committed_date":"2012-07-21T00:53:55-07:00"}},{"name":"v2.6.3","commit":{"id":"666cdb22792dd955a286b9993d6235b4cdd68b4b","parents":[{"id":"d92446df1fdba87101c92c90b1c34eb2f1eebef4"}],"tree":"888173aa4c12a4920d318c35b950095d3505673d","message":"up to 2.6.3","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-26T09:20:47-07:00","committed_date":"2012-06-26T09:21:28-07:00"}},{"name":"v2.6.2","commit":{"id":"39fecb554f172a0c8ea00316e612e1d37efc7200","parents":[{"id":"68389588d664100590b1a6ca7eedd50860b7e9bc"}],"tree":"53accb25e0b9d038d550cf387753bde15fe4ad19","message":"Up to 2.6.2","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-22T13:50:58-07:00","committed_date":"2012-06-22T13:50:58-07:00"}},{"name":"v2.6.1","commit":{"id":"d92a22c9e627268eca697bbd9b660d8c335df953","parents":[{"id":"193804516b8b0783c850981456e947f888ff51bb"}],"tree":"4ac1b5225f597ab55372cb5e950b121d6f55e386","message":"Up to 2.6.1","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-22T12:49:03-07:00","committed_date":"2012-06-22T12:49:03-07:00"}},{"name":"v2.6.0","commit":{"id":"b32465712becfbcf83d63b1e6eff7d1483fdabea","parents":[{"id":"1903f6ade027df0f10ef96b9439495eeda07482c"}],"tree":"ffbc05fd0f1771c1602c956df9556260048c7167","message":"Up to 2.6","author":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"randx","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-06-21T10:25:23-07:00","committed_date":"2012-06-21T10:25:23-07:00"}},{"name":"v2.5.0","commit":{"id":"cc8369144db2147d2956e8dd7d314e9a7dfd4fbb","parents":[{"id":"1b2068eaa91e5002d01a220c65da21dad8ccb071"}],"tree":"666a442e00689911169e8cc336c5ce60d014854c","message":"Prevent app crash in case if encoding failed","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-05-22T04:57:04-07:00","committed_date":"2012-05-22T04:57:04-07:00"}},{"name":"v2.4.2","commit":{"id":"f18339c26d673c5f8b4c19776036fd42a0de30aa","parents":[{"id":"c937d06c3c98e9ffce8ec1132203eaff6bf7b231"},{"id":"35e602f19c83585d64aa2043ed26eeb8cd7b40e2"}],"tree":"5101f0cd8e395fee1996764298a202437757e85b","message":"Merge branch 'master' of github.com:gitlabhq/gitlabhq","author":{"name":"Zevs","email":"vsv2711@gmail.com"},"committer":{"name":"Zevs","email":"vsv2711@gmail.com"},"authored_date":"2012-04-29T14:24:59-07:00","committed_date":"2012-04-29T14:24:59-07:00"}},{"name":"v2.4.1","commit":{"id":"d97a9aa4a44ff9f452144fad348fd9d7e3b48260","parents":[{"id":"21f3da23589d50038728393f0badc6255b5762ca"}],"tree":"905c33874b064778199f806749d5688e33d64be3","message":"fixed email markdown","author":{"name":"gitlabhq","email":"m@gitlabhq.com"},"committer":{"name":"gitlabhq","email":"m@gitlabhq.com"},"authored_date":"2012-04-23T05:32:56-07:00","committed_date":"2012-04-23T05:32:56-07:00"}},{"name":"v2.4.0pre","commit":{"id":"1845429268364e75bffdeb1075de8f1606e157ec","parents":[{"id":"45b18365d5f409f196a02a4e6e2b77b8ebef909b"}],"tree":"423c70246fa7ffd8804b26628fea34bdb2b22846","message":"Use try for commit prev_commit_id detection","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-04-19T13:35:35-07:00","committed_date":"2012-04-19T13:35:35-07:00"}},{"name":"v2.4.0","commit":{"id":"204c66461ed519eb0078be7e8ac8a6cb56834753","parents":[{"id":"511d07c47c9bf3a18bfa276d452c899369432a22"}],"tree":"9416c777cccf87d348f5705078e82f3f97485e19","message":"corrected exception for automerge","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-04-22T06:49:45-07:00","committed_date":"2012-04-22T06:49:45-07:00"}},{"name":"v2.3.1","commit":{"id":"fa8219e0a753e642a6f1dbdfc010d01ae8a949ee","parents":[{"id":"81da8e46f24913ccf42d3e2644962cbcbc0f9c2e"}],"tree":"5debfcd6d17f9d582aace6ac9b80db27d5c1fe36","message":"better MR list, dashboard pollished","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-22T13:57:04-07:00","committed_date":"2012-03-22T13:57:04-07:00"}},{"name":"v2.3.0pre","commit":{"id":"cadf12c60cc27c5b0b8273c1de4b190a0e88bd7d","parents":[{"id":"724ea16c348bc61cf7cb3dbe362c6f30cff1b2c7"}],"tree":"6f4c22761fd2dee405d3fbf38f9dd835bb3c8694","message":"Merged activities & projects pages","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-19T15:05:35-07:00","committed_date":"2012-03-19T15:05:35-07:00"}},{"name":"v2.3.0","commit":{"id":"b57faf9282d7df6cdd62953d474652a0ae2e6896","parents":[{"id":"cadf12c60cc27c5b0b8273c1de4b190a0e88bd7d"}],"tree":"f0d5b826df373191b4681452fc2ae4c5970cef4a","message":"Push events polished","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-03-20T14:59:35-07:00","committed_date":"2012-03-20T14:59:35-07:00"}},{"name":"v2.2.0pre","commit":{"id":"6a445b42003007cbb6c06f477c4d7a0b175688c1","parents":[{"id":"22f4c1908d0fc2dbce02e74ed03bf65f028d78d6"}],"tree":"9c60577833f6ca717acdebfa66140124c88e8471","message":"fixed forgot password form","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-02-20T10:37:37-08:00","committed_date":"2012-02-20T10:37:37-08:00"}},{"name":"v2.2.0","commit":{"id":"9e6d0710e927aa8ea834b8a9ae9f277be617ac7d","parents":[{"id":"8c40aab120dbc5507ab9cc8d7ad8e2519d6e9f25"},{"id":"6ea87c47f0f8a24ae031c3fff17bc913889ecd00"}],"tree":"86c831ab21236f21ffa5b97c752369612ce41b39","message":"Merge pull request #443 from CedricGatay/fix/incorrectLineNumberingInDiff\n\nIncorrect line numbering in diff","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-02-22T07:14:54-08:00","committed_date":"2012-02-22T07:14:54-08:00"}},{"name":"v2.1.0","commit":{"id":"98d6492582d232ed86525aa31ccbf280f4cbdaef","parents":[{"id":"611c5a87ab0c083a43785323b09cc47f554c3ba4"}],"tree":"1689b3cad580a18fd9b429ee0b33dac21c9f5a48","message":"removed broken migration","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-01-22T10:52:06-08:00","committed_date":"2012-01-22T10:52:06-08:00"}},{"name":"v2.0.0","commit":{"id":"9a2a8612769d472503b367fa35e99f6fb2876704","parents":[{"id":"2f7b67161952fc9ab322eba6878511b5f2dd5cf1"}],"tree":"26cdb4e66b5e664fe4bcd57d011c54c9c9c26ded","message":"Design tab for profile. Colorscheme as db value","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2011-12-20T12:47:09-08:00","committed_date":"2011-12-20T12:47:09-08:00"}},{"name":"v1.2.2","commit":{"id":"139a332293b9d8c4e5436619036e093483d8347f","parents":[{"id":"ade12da9488bea19d12505c371ead35686a1436e"}],"tree":"365d57f4df5c5dcac69b666cf6d2bfd8ef058008","message":"updated readme","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-25T14:30:51-08:00","committed_date":"2011-11-25T14:30:51-08:00"}},{"name":"v1.2.1","commit":{"id":"7ebba27db21719c0035bab65fea92a4780051c73","parents":[{"id":"b56024100d40457a998f83adae3cdc830c997cda"},{"id":"a4fbe13fce87cb6ff2a27a2574ae25bf1dad145c"}],"tree":"b121a7576af1503a96954ce9a94598a68579e053","message":"Merge branch 'master' of dev.gitlabhq.com:gitlabhq","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-22T13:15:09-08:00","committed_date":"2011-11-22T13:15:09-08:00"}},{"name":"v1.2.0pre","commit":{"id":"86829cae50857b5edf74b935380c6f68a19c2282","parents":[{"id":"a6b99319381c2d62ec4b92d64805e8de8965859e"}],"tree":"6aab9d13000584fa96fb3cb34d94f3b122bd1143","message":"fixed min height for menu","author":{"name":"gitlabhq","email":"m@gitlabhq.com"},"committer":{"name":"gitlabhq","email":"m@gitlabhq.com"},"authored_date":"2011-11-22T06:03:27-08:00","committed_date":"2011-11-22T06:03:27-08:00"}},{"name":"v1.2.0","commit":{"id":"b56024100d40457a998f83adae3cdc830c997cda","parents":[{"id":"4451b8df8ad6d4b6d79fbce77687c6c2fd37d0a9"}],"tree":"f402cbb6d54526a32b30968c98410bae97b27c8d","message":"lil style fixes","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-11-22T09:57:25-08:00","committed_date":"2011-11-22T09:57:25-08:00"}},{"name":"v1.1.0pre","commit":{"id":"6b030fd41d697e327d2935b406cba70b6a460504","parents":[{"id":"3a2b273316fb29d63b489906f85d9b5329377258"}],"tree":"63b1fdb2a0f135f7074f6a94da14543b8450dd71","message":"1.1pre1","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-21T10:04:41-07:00","committed_date":"2011-10-21T10:04:41-07:00"}},{"name":"v1.1.0","commit":{"id":"ba8048d71019b5aaa1f92ee5c3415bfddaa9babb","parents":[{"id":"6b030fd41d697e327d2935b406cba70b6a460504"}],"tree":"4db2b5f4f9b374dd1be3579459bc5947c225c9ba","message":"v1.1.0","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-22T06:07:26-07:00","committed_date":"2011-10-22T06:07:26-07:00"}},{"name":"v1.0.2","commit":{"id":"3a2b273316fb29d63b489906f85d9b5329377258","parents":[{"id":"757ea634665e475bf69c1ec962040a0511ee8aeb"},{"id":"c374eb80ff9fb71d37faffc15714bf98b632d3e5"}],"tree":"e0d8170e61a9468a7bb5d4e63305171ec1efa6bf","message":"Merge pull request #40 from vslinko/patch-1\n\nIncrease max key length. Some keys has comment after key string.","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2011-10-18T23:30:06-07:00","committed_date":"2011-10-18T23:30:06-07:00"}},{"name":"v1.0.1","commit":{"id":"7b5799a97998b68416f1b6233ce427135c99165a","parents":[{"id":"0541b3f3c5dcd291d144c83d9731c75ee811b4e0"},{"id":"7b67480c76db8b9a9ccdc80015cc500dc6d26892"}],"tree":"e052185e9dd72a1b1a04d59a5f9efbf3c0369601","message":"Merge branch '1x' of github.com:gitlabhq/gitlabhq into 1x","author":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dzaporozhets@sphereconsultinginc.com"},"authored_date":"2011-10-14T15:16:44-07:00","committed_date":"2011-10-14T15:16:44-07:00"}}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/projects.json b/lib/gitlab-cli/spec/fixtures/projects.json deleted file mode 100644 index deab4c5f..00000000 --- a/lib/gitlab-cli/spec/fixtures/projects.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"code":"brute","name":"Brute","description":null,"path":"brute","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"code":"mozart","name":"Mozart","description":null,"path":"mozart","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:57Z"},{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/protect_branch.json b/lib/gitlab-cli/spec/fixtures/protect_branch.json deleted file mode 100644 index f71ebd5d..00000000 --- a/lib/gitlab-cli/spec/fixtures/protect_branch.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected":true} diff --git a/lib/gitlab-cli/spec/fixtures/session.json b/lib/gitlab-cli/spec/fixtures/session.json deleted file mode 100644 index e4f5ba35..00000000 --- a/lib/gitlab-cli/spec/fixtures/session.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","private_token":"qEsq1pt6HJPaNciie3MG"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/snippet.json b/lib/gitlab-cli/spec/fixtures/snippet.json deleted file mode 100644 index 34e9d994..00000000 --- a/lib/gitlab-cli/spec/fixtures/snippet.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"title":"Rails Console ActionMailer","file_name":"mailer_test.rb","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"expires_at":"2012-09-24T00:00:00Z","updated_at":"2012-09-17T09:51:42Z","created_at":"2012-09-17T09:51:42Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/snippets.json b/lib/gitlab-cli/spec/fixtures/snippets.json deleted file mode 100644 index 106f88f3..00000000 --- a/lib/gitlab-cli/spec/fixtures/snippets.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"title":"Rails Console ActionMailer","file_name":"mailer_test.rb","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"expires_at":"2012-09-24T00:00:00Z","updated_at":"2012-09-17T09:51:42Z","created_at":"2012-09-17T09:51:42Z"}] diff --git a/lib/gitlab-cli/spec/fixtures/system_hook.json b/lib/gitlab-cli/spec/fixtures/system_hook.json deleted file mode 100644 index e2f485be..00000000 --- a/lib/gitlab-cli/spec/fixtures/system_hook.json +++ /dev/null @@ -1 +0,0 @@ -{"id": 3, "url": "http://example.com/hook", "created_at": "2013-10-02T10:15:31Z"} diff --git a/lib/gitlab-cli/spec/fixtures/system_hook_test.json b/lib/gitlab-cli/spec/fixtures/system_hook_test.json deleted file mode 100644 index 2c104c62..00000000 --- a/lib/gitlab-cli/spec/fixtures/system_hook_test.json +++ /dev/null @@ -1 +0,0 @@ -{ "event_name": "project_create", "name": "Ruby", "path": "ruby", "project_id": 1, "owner_name": "Someone", "owner_email": "example@gitlabhq.com" } diff --git a/lib/gitlab-cli/spec/fixtures/system_hooks.json b/lib/gitlab-cli/spec/fixtures/system_hooks.json deleted file mode 100644 index 9c529e6f..00000000 --- a/lib/gitlab-cli/spec/fixtures/system_hooks.json +++ /dev/null @@ -1 +0,0 @@ -[{"id": 3, "url": "http://example.com/hook", "created_at": "2013-10-02T10:15:31Z"}] diff --git a/lib/gitlab-cli/spec/fixtures/tag.json b/lib/gitlab-cli/spec/fixtures/tag.json deleted file mode 100644 index 74584bdf..00000000 --- a/lib/gitlab-cli/spec/fixtures/tag.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "v1.0.0","commit": {"id": "2695effb5807a22ff3d138d593fd856244e155e7","parents": [],"message": "Initial commit","authored_date": "2012-05-28T04:42:42-07:00","author_name": "John Smith","author email": "john@example.com","committer_name": "Jack Smith","committed_date": "2012-05-28T04:42:42-07:00","committer_email": "jack@example.com"},"protected": false} diff --git a/lib/gitlab-cli/spec/fixtures/team_member.json b/lib/gitlab-cli/spec/fixtures/team_member.json deleted file mode 100644 index fd3ac385..00000000 --- a/lib/gitlab-cli/spec/fixtures/team_member.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/team_members.json b/lib/gitlab-cli/spec/fixtures/team_members.json deleted file mode 100644 index a2fe19e3..00000000 --- a/lib/gitlab-cli/spec/fixtures/team_members.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40},{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/unprotect_branch.json b/lib/gitlab-cli/spec/fixtures/unprotect_branch.json deleted file mode 100644 index 307df403..00000000 --- a/lib/gitlab-cli/spec/fixtures/unprotect_branch.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected":false} diff --git a/lib/gitlab-cli/spec/fixtures/update_merge_request.json b/lib/gitlab-cli/spec/fixtures/update_merge_request.json deleted file mode 100644 index 735819ff..00000000 --- a/lib/gitlab-cli/spec/fixtures/update_merge_request.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"A different new feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/user.json b/lib/gitlab-cli/spec/fixtures/user.json deleted file mode 100644 index 4e0daca5..00000000 --- a/lib/gitlab-cli/spec/fixtures/user.json +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"} \ No newline at end of file diff --git a/lib/gitlab-cli/spec/fixtures/users.json b/lib/gitlab-cli/spec/fixtures/users.json deleted file mode 100644 index 14c6388b..00000000 --- a/lib/gitlab-cli/spec/fixtures/users.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"email":"jack@example.com","name":"Jack Smith","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"}] \ No newline at end of file diff --git a/lib/gitlab-cli/spec/gitlab/cli_spec.rb b/lib/gitlab-cli/spec/gitlab/cli_spec.rb deleted file mode 100644 index a23139cb..00000000 --- a/lib/gitlab-cli/spec/gitlab/cli_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -require 'spec_helper' - -describe Gitlab::CLI do - describe ".run" do - context "when command is version" do - it "should show gem version" do - output = capture_output { Gitlab::CLI.run('-v') } - expect(output).to eq("Gitlab Ruby Gem #{Gitlab::VERSION}\n") - end - end - - context "when command is info" do - it "should show environment info" do - output = capture_output { Gitlab::CLI.run('info') } - expect(output).to include("Gitlab endpoint is") - expect(output).to include("Gitlab private token is") - expect(output).to include("Ruby Version is") - expect(output).to include("Gitlab Ruby Gem") - end - end - - context "when command is help" do - it "should show available actions" do - output = capture_output { Gitlab::CLI.run('help') } - expect(output).to include('Available commands') - expect(output).to include('MergeRequests') - expect(output).to include('team_members') - end - end - - context "when command is user" do - before do - stub_get("/user", "user") - @output = capture_output { Gitlab::CLI.run('user') } - end - - it "should show executed command" do - expect(@output).to include('Gitlab.user') - end - - it "should show user data" do - expect(@output).to include('name') - expect(@output).to include('John Smith') - end - end - end - - describe ".start" do - context "when command with excluded fields" do - before do - stub_get("/user", "user") - args = ['user', '--except=id,email,name'] - @output = capture_output { Gitlab::CLI.start(args) } - end - - it "should show user data with excluded fields" do - expect(@output).to_not include('John Smith') - expect(@output).to include('bio') - expect(@output).to include('created_at') - end - end - - context "when command with required fields" do - before do - stub_get("/user", "user") - args = ['user', '--only=id,email,name'] - @output = capture_output { Gitlab::CLI.start(args) } - end - - it "should show user data with required fields" do - expect(@output).to include('id') - expect(@output).to include('name') - expect(@output).to include('email') - expect(@output).to include('John Smith') - expect(@output).to_not include('bio') - expect(@output).to_not include('created_at') - end - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/branches_spec.rb b/lib/gitlab-cli/spec/gitlab/client/branches_spec.rb deleted file mode 100644 index 92c6a9a2..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/branches_spec.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - it { should respond_to :repo_branches } - it { should respond_to :repo_branch } - it { should respond_to :repo_protect_branch } - it { should respond_to :repo_unprotect_branch } - - describe ".branches" do - before do - stub_get("/projects/3/repository/branches", "branches") - @branches = Gitlab.branches(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/branches")).to have_been_made - end - - it "should return an array of repository branches" do - expect(@branches).to be_an Array - expect(@branches.first.name).to eq("api") - end - end - - describe ".branch" do - before do - stub_get("/projects/3/repository/branches/api", "branch") - @branch = Gitlab.branch(3, "api") - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/branches/api")).to have_been_made - end - - it "should return information about a repository branch" do - expect(@branch.name).to eq("api") - end - end - - describe ".protect_branch" do - before do - stub_put("/projects/3/repository/branches/api/protect", "protect_branch") - @branch = Gitlab.protect_branch(3, "api") - end - - it "should get the correct resource" do - expect(a_put("/projects/3/repository/branches/api/protect")).to have_been_made - end - - it "should return information about a protected repository branch" do - expect(@branch.name).to eq("api") - expect(@branch.protected).to eq(true) - end - end - - describe ".unprotect_branch" do - before do - stub_put("/projects/3/repository/branches/api/unprotect", "unprotect_branch") - @branch = Gitlab.unprotect_branch(3, "api") - end - - it "should get the correct resource" do - expect(a_put("/projects/3/repository/branches/api/unprotect")).to have_been_made - end - - it "should return information about an unprotected repository branch" do - expect(@branch.name).to eq("api") - expect(@branch.protected).to eq(false) - end - end - - describe ".create_branch" do - context "with branch name" do - before do - stub_post("/projects/3/repository/branches", "create_branch") - @branch = Gitlab.create_branch(3, "api","master") - end - - it "should get the correct resource" do - expect(a_post("/projects/3/repository/branches")).to have_been_made - end - - it "should return information about a new repository branch" do - expect(@branch.name).to eq("api") - end - end - context "with commit hash" do - before do - stub_post("/projects/3/repository/branches", "create_branch") - @branch = Gitlab.create_branch(3, "api","949b1df930bedace1dbd755aaa4a82e8c451a616") - end - - it "should get the correct resource" do - expect(a_post("/projects/3/repository/branches")).to have_been_made - end - - it "should return information about a new repository branch" do - expect(@branch.name).to eq("api") - end - end - end - -end diff --git a/lib/gitlab-cli/spec/gitlab/client/groups_spec.rb b/lib/gitlab-cli/spec/gitlab/client/groups_spec.rb deleted file mode 100644 index 7336a3bd..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/groups_spec.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".groups" do - before do - stub_get("/groups", "groups") - stub_get("/groups/3", "group") - @group = Gitlab.group(3) - @groups = Gitlab.groups - end - - it "should get the correct resource" do - expect(a_get("/groups")).to have_been_made - expect(a_get("/groups/3")).to have_been_made - end - - it "should return an array of Groups" do - expect(@groups).to be_an Array - expect(@groups.first.path).to eq("threegroup") - end - end - - describe ".create_group" do - before do - stub_post("/groups", "group_create") - @group = Gitlab.create_group('GitLab-Group', 'gitlab-path') - end - - it "should get the correct resource" do - expect(a_post("/groups"). - with(:body => {:path => 'gitlab-path', :name => 'GitLab-Group'})).to have_been_made - end - - it "should return information about a created group" do - expect(@group.name).to eq("Gitlab-Group") - expect(@group.path).to eq("gitlab-group") - end - end - - describe ".transfer_project_to_group" do - before do - stub_post("/projects", "project") - @project = Gitlab.create_project('Gitlab') - stub_post("/groups", "group_create") - @group = Gitlab.create_group('GitLab-Group', 'gitlab-path') - - stub_post("/groups/#{@group.id}/projects/#{@project.id}", "group_create") - @group_transfer = Gitlab.transfer_project_to_group(@group.id,@project.id) - end - - it "should post to the correct resource" do - expect(a_post("/groups/#{@group.id}/projects/#{@project.id}").with(:body => {:id => @group.id.to_s, :project_id => @project.id.to_s})).to have_been_made - end - - it "should return information about the group" do - expect(@group_transfer.name).to eq(@group.name) - expect(@group_transfer.path).to eq(@group.path) - expect(@group_transfer.id).to eq(@group.id) - end - end - - describe ".group_members" do - before do - stub_get("/groups/3/members", "group_members") - @members = Gitlab.group_members(3) - end - - it "should get the correct resource" do - expect(a_get("/groups/3/members")).to have_been_made - end - - it "should return information about a group members" do - expect(@members).to be_an Array - expect(@members.size).to eq(2) - expect(@members[1].name).to eq("John Smith") - end - end - - describe ".add_group_member" do - before do - stub_post("/groups/3/members", "group_member") - @member = Gitlab.add_group_member(3, 1, 40) - end - - it "should get the correct resource" do - expect(a_post("/groups/3/members"). - with(:body => {:user_id => '1', :access_level => '40'})).to have_been_made - end - - it "should return information about an added member" do - expect(@member.name).to eq("John Smith") - end - end - - describe ".remove_group_member" do - before do - stub_delete("/groups/3/members/1", "group_member_delete") - @group = Gitlab.remove_group_member(3, 1) - end - - it "should get the correct resource" do - expect(a_delete("/groups/3/members/1")).to have_been_made - end - - it "should return information about the group the member was removed from" do - expect(@group.group_id).to eq(3) - end - end - - -end diff --git a/lib/gitlab-cli/spec/gitlab/client/issues_spec.rb b/lib/gitlab-cli/spec/gitlab/client/issues_spec.rb deleted file mode 100644 index 1a34699f..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/issues_spec.rb +++ /dev/null @@ -1,122 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".issues" do - context "with project ID passed" do - before do - stub_get("/projects/3/issues", "project_issues") - @issues = Gitlab.issues(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/issues")).to have_been_made - end - - it "should return an array of project's issues" do - expect(@issues).to be_an Array - expect(@issues.first.project_id).to eq(3) - end - end - - context "without project ID passed" do - before do - stub_get("/issues", "issues") - @issues = Gitlab.issues - end - - it "should get the correct resource" do - expect(a_get("/issues")).to have_been_made - end - - it "should return an array of user's issues" do - expect(@issues).to be_an Array - expect(@issues.first.closed).to be_falsey - expect(@issues.first.author.name).to eq("John Smith") - end - end - end - - describe ".issue" do - before do - stub_get("/projects/3/issues/33", "issue") - @issue = Gitlab.issue(3, 33) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/issues/33")).to have_been_made - end - - it "should return information about an issue" do - expect(@issue.project_id).to eq(3) - expect(@issue.assignee.name).to eq("Jack Smith") - end - end - - describe ".create_issue" do - before do - stub_post("/projects/3/issues", "issue") - @issue = Gitlab.create_issue(3, 'title') - end - - it "should get the correct resource" do - expect(a_post("/projects/3/issues"). - with(:body => {:title => 'title'})).to have_been_made - end - - it "should return information about a created issue" do - expect(@issue.project_id).to eq(3) - expect(@issue.assignee.name).to eq("Jack Smith") - end - end - - describe ".edit_issue" do - before do - stub_put("/projects/3/issues/33", "issue") - @issue = Gitlab.edit_issue(3, 33, :title => 'title') - end - - it "should get the correct resource" do - expect(a_put("/projects/3/issues/33"). - with(:body => {:title => 'title'})).to have_been_made - end - - it "should return information about an edited issue" do - expect(@issue.project_id).to eq(3) - expect(@issue.assignee.name).to eq("Jack Smith") - end - end - - describe ".close_issue" do - before do - stub_put("/projects/3/issues/33", "issue") - @issue = Gitlab.close_issue(3, 33) - end - - it "should get the correct resource" do - expect(a_put("/projects/3/issues/33"). - with(:body => {:state_event => 'close'})).to have_been_made - end - - it "should return information about an closed issue" do - expect(@issue.project_id).to eq(3) - expect(@issue.assignee.name).to eq("Jack Smith") - end - end - - describe ".reopen_issue" do - before do - stub_put("/projects/3/issues/33", "issue") - @issue = Gitlab.reopen_issue(3, 33) - end - - it "should get the correct resource" do - expect(a_put("/projects/3/issues/33"). - with(:body => {:state_event => 'reopen'})).to have_been_made - end - - it "should return information about an reopened issue" do - expect(@issue.project_id).to eq(3) - expect(@issue.assignee.name).to eq("Jack Smith") - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/merge_requests_spec.rb b/lib/gitlab-cli/spec/gitlab/client/merge_requests_spec.rb deleted file mode 100644 index 7c2253f7..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/merge_requests_spec.rb +++ /dev/null @@ -1,124 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".merge_requests" do - before do - stub_get("/projects/3/merge_requests", "merge_requests") - @merge_requests = Gitlab.merge_requests(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/merge_requests")).to have_been_made - end - - it "should return an array of project's merge requests" do - expect(@merge_requests).to be_an Array - expect(@merge_requests.first.project_id).to eq(3) - end - end - - describe ".merge_request" do - before do - stub_get("/projects/3/merge_request/1", "merge_request") - @merge_request = Gitlab.merge_request(3, 1) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/merge_request/1")).to have_been_made - end - - it "should return information about a merge request" do - expect(@merge_request.project_id).to eq(3) - expect(@merge_request.assignee.name).to eq("Jack Smith") - end - end - - describe ".create_merge_request" do - before do - stub_post("/projects/3/merge_requests", "create_merge_request") - end - - it "should fail if it doesn't have a source_branch" do - expect { - Gitlab.create_merge_request(3, 'New merge request', :target_branch => 'master') - }.to raise_error Gitlab::Error::MissingAttributes - end - - it "should fail if it doesn't have a target_branch" do - expect { - Gitlab.create_merge_request(3, 'New merge request', :source_branch => 'dev') - }.to raise_error Gitlab::Error::MissingAttributes - end - - it "should return information about a merge request" do - @merge_request = Gitlab.create_merge_request(3, 'New feature', - :source_branch => 'api', - :target_branch => 'master' - ) - expect(@merge_request.project_id).to eq(3) - expect(@merge_request.assignee.name).to eq("Jack Smith") - expect(@merge_request.title).to eq('New feature') - end - end - - describe ".update_merge_request" do - before do - stub_put("/projects/3/merge_request/2", "update_merge_request") - @merge_request = Gitlab.update_merge_request(3, 2, - :assignee_id => '1', - :target_branch => 'master', - :title => 'A different new feature' - ) - end - - it "should return information about a merge request" do - expect(@merge_request.project_id).to eq(3) - expect(@merge_request.assignee.name).to eq("Jack Smith") - expect(@merge_request.title).to eq('A different new feature') - end - end - - describe ".merge_request_comments" do - before do - stub_get("/projects/3/merge_request/2/comments", "merge_request_comments") - @merge_request = Gitlab.merge_request_comments(3, 2) - end - - it "should return merge request's comments" do - expect(@merge_request).to be_an Array - expect(@merge_request.length).to eq(2) - expect(@merge_request[0].note).to eq("this is the 1st comment on the 2merge merge request") - expect(@merge_request[0].author.id).to eq(11) - expect(@merge_request[1].note).to eq("another discussion point on the 2merge request") - expect(@merge_request[1].author.id).to eq(12) - end - end - - describe ".merge_request_comments" do - before do - stub_get("/projects/3/merge_request/2/comments", "merge_request_comments") - @merge_request = Gitlab.merge_request_comments(3, 2) - end - - it "should return merge request's comments" do - expect(@merge_request).to be_an Array - expect(@merge_request.length).to eq(2) - expect(@merge_request[0].note).to eq("this is the 1st comment on the 2merge merge request") - expect(@merge_request[0].author.id).to eq(11) - expect(@merge_request[1].note).to eq("another discussion point on the 2merge request") - expect(@merge_request[1].author.id).to eq(12) - end - end - - describe ".create_merge_request_comment" do - before do - stub_post("/projects/3/merge_request/2/comments", "comment_merge_request") - end - - it "should return information about a merge request" do - @merge_request = Gitlab.create_merge_request_comment(3, 2, 'Cool Merge Request!') - expect(@merge_request.note).to eq('Cool Merge Request!') - @merge_request.author.id == 1 - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/milestones_spec.rb b/lib/gitlab-cli/spec/gitlab/client/milestones_spec.rb deleted file mode 100644 index 5ec7f3e3..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/milestones_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".milestones" do - before do - stub_get("/projects/3/milestones", "milestones") - @milestones = Gitlab.milestones(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/milestones")).to have_been_made - end - - it "should return an array of project's milestones" do - expect(@milestones).to be_an Array - expect(@milestones.first.project_id).to eq(3) - end - end - - describe ".milestone" do - before do - stub_get("/projects/3/milestones/1", "milestone") - @milestone = Gitlab.milestone(3, 1) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/milestones/1")).to have_been_made - end - - it "should return information about a milestone" do - expect(@milestone.project_id).to eq(3) - end - end - - describe ".create_milestone" do - before do - stub_post("/projects/3/milestones", "milestone") - @milestone = Gitlab.create_milestone(3, 'title') - end - - it "should get the correct resource" do - expect(a_post("/projects/3/milestones"). - with(:body => {:title => 'title'})).to have_been_made - end - - it "should return information about a created milestone" do - expect(@milestone.project_id).to eq(3) - end - end - - describe ".edit_milestone" do - before do - stub_put("/projects/3/milestones/33", "milestone") - @milestone = Gitlab.edit_milestone(3, 33, :title => 'title') - end - - it "should get the correct resource" do - expect(a_put("/projects/3/milestones/33"). - with(:body => {:title => 'title'})).to have_been_made - end - - it "should return information about an edited milestone" do - expect(@milestone.project_id).to eq(3) - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/notes_spec.rb b/lib/gitlab-cli/spec/gitlab/client/notes_spec.rb deleted file mode 100644 index 78cd520d..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/notes_spec.rb +++ /dev/null @@ -1,156 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe "notes" do - context "when wall notes" do - before do - stub_get("/projects/3/notes", "notes") - @notes = Gitlab.notes(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/notes")).to have_been_made - end - - it "should return an array of notes" do - expect(@notes).to be_an Array - expect(@notes.first.author.name).to eq("John Smith") - end - end - - context "when issue notes" do - before do - stub_get("/projects/3/issues/7/notes", "notes") - @notes = Gitlab.issue_notes(3, 7) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/issues/7/notes")).to have_been_made - end - - it "should return an array of notes" do - expect(@notes).to be_an Array - expect(@notes.first.author.name).to eq("John Smith") - end - end - - context "when snippet notes" do - before do - stub_get("/projects/3/snippets/7/notes", "notes") - @notes = Gitlab.snippet_notes(3, 7) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/snippets/7/notes")).to have_been_made - end - - it "should return an array of notes" do - expect(@notes).to be_an Array - expect(@notes.first.author.name).to eq("John Smith") - end - end - end - - describe "note" do - context "when wall note" do - before do - stub_get("/projects/3/notes/1201", "note") - @note = Gitlab.note(3, 1201) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/notes/1201")).to have_been_made - end - - it "should return information about a note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - - context "when issue note" do - before do - stub_get("/projects/3/issues/7/notes/1201", "note") - @note = Gitlab.issue_note(3, 7, 1201) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/issues/7/notes/1201")).to have_been_made - end - - it "should return information about a note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - - context "when snippet note" do - before do - stub_get("/projects/3/snippets/7/notes/1201", "note") - @note = Gitlab.snippet_note(3, 7, 1201) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/snippets/7/notes/1201")).to have_been_made - end - - it "should return information about a note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - end - - describe "create note" do - context "when wall note" do - before do - stub_post("/projects/3/notes", "note") - @note = Gitlab.create_note(3, "The solution is rather tricky") - end - - it "should get the correct resource" do - expect(a_post("/projects/3/notes"). - with(:body => {:body => 'The solution is rather tricky'})).to have_been_made - end - - it "should return information about a created note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - - context "when issue note" do - before do - stub_post("/projects/3/issues/7/notes", "note") - @note = Gitlab.create_issue_note(3, 7, "The solution is rather tricky") - end - - it "should get the correct resource" do - expect(a_post("/projects/3/issues/7/notes"). - with(:body => {:body => 'The solution is rather tricky'})).to have_been_made - end - - it "should return information about a created note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - - context "when snippet note" do - before do - stub_post("/projects/3/snippets/7/notes", "note") - @note = Gitlab.create_snippet_note(3, 7, "The solution is rather tricky") - end - - it "should get the correct resource" do - expect(a_post("/projects/3/snippets/7/notes"). - with(:body => {:body => 'The solution is rather tricky'})).to have_been_made - end - - it "should return information about a created note" do - expect(@note.body).to eq("The solution is rather tricky") - expect(@note.author.name).to eq("John Smith") - end - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/projects_spec.rb b/lib/gitlab-cli/spec/gitlab/client/projects_spec.rb deleted file mode 100644 index 754a27c9..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/projects_spec.rb +++ /dev/null @@ -1,357 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".projects" do - before do - stub_get("/projects", "projects") - @projects = Gitlab.projects - end - - it "should get the correct resource" do - expect(a_get("/projects")).to have_been_made - end - - it "should return an array of projects" do - expect(@projects).to be_an Array - expect(@projects.first.name).to eq("Brute") - expect(@projects.first.owner.name).to eq("John Smith") - end - end - - describe ".project" do - before do - stub_get("/projects/3", "project") - @project = Gitlab.project(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3")).to have_been_made - end - - it "should return information about a project" do - expect(@project.name).to eq("Gitlab") - expect(@project.owner.name).to eq("John Smith") - end - end - - describe ".project_events" do - before do - stub_get("/projects/2/events", "project_events") - @events = Gitlab.project_events(2) - end - - it "should get the correct resource" do - expect(a_get("/projects/2/events")).to have_been_made - end - - it "should return an array of events" do - expect(@events).to be_an Array - expect(@events.size).to eq(2) - end - - it "should return the action name of the event" do - expect(@events.first.action_name).to eq("opened") - end - end - - describe ".create_project" do - before do - stub_post("/projects", "project") - @project = Gitlab.create_project('Gitlab') - end - - it "should get the correct resource" do - expect(a_post("/projects")).to have_been_made - end - - it "should return information about a created project" do - expect(@project.name).to eq("Gitlab") - expect(@project.owner.name).to eq("John Smith") - end - end - - describe ".create_project for user" do - before do - stub_post("/users", "user") - @owner = Gitlab.create_user("john@example.com", "pass", {name: 'John Owner'}) - stub_post("/projects/user/#{@owner.id}", "project_for_user") - @project = Gitlab.create_project('Brute', {:user_id => @owner.id}) - end - - it "should return information about a created project" do - expect(@project.name).to eq("Brute") - expect(@project.owner.name).to eq("John Owner") - end - end - - describe ".delete_project" do - before do - stub_delete("/projects/Gitlab", "project") - @project = Gitlab.delete_project('Gitlab') - end - - it "should get the correct resource" do - expect(a_delete("/projects/Gitlab")).to have_been_made - end - - it "should return information about a deleted project" do - expect(@project.name).to eq("Gitlab") - expect(@project.owner.name).to eq("John Smith") - end - end - - describe ".team_members" do - before do - stub_get("/projects/3/members", "team_members") - @team_members = Gitlab.team_members(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/members")).to have_been_made - end - - it "should return an array of team members" do - expect(@team_members).to be_an Array - expect(@team_members.first.name).to eq("John Smith") - end - end - - describe ".team_member" do - before do - stub_get("/projects/3/members/1", "team_member") - @team_member = Gitlab.team_member(3, 1) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/members/1")).to have_been_made - end - - it "should return information about a team member" do - expect(@team_member.name).to eq("John Smith") - end - end - - describe ".add_team_member" do - before do - stub_post("/projects/3/members", "team_member") - @team_member = Gitlab.add_team_member(3, 1, 40) - end - - it "should get the correct resource" do - expect(a_post("/projects/3/members"). - with(:body => {:user_id => '1', :access_level => '40'})).to have_been_made - end - - it "should return information about an added team member" do - expect(@team_member.name).to eq("John Smith") - end - end - - describe ".edit_team_member" do - before do - stub_put("/projects/3/members/1", "team_member") - @team_member = Gitlab.edit_team_member(3, 1, 40) - end - - it "should get the correct resource" do - expect(a_put("/projects/3/members/1"). - with(:body => {:access_level => '40'})).to have_been_made - end - - it "should return information about an edited team member" do - expect(@team_member.name).to eq("John Smith") - end - end - - describe ".remove_team_member" do - before do - stub_delete("/projects/3/members/1", "team_member") - @team_member = Gitlab.remove_team_member(3, 1) - end - - it "should get the correct resource" do - expect(a_delete("/projects/3/members/1")).to have_been_made - end - - it "should return information about a removed team member" do - expect(@team_member.name).to eq("John Smith") - end - end - - describe ".project_hooks" do - before do - stub_get("/projects/1/hooks", "project_hooks") - @hooks = Gitlab.project_hooks(1) - end - - it "should get the correct resource" do - expect(a_get("/projects/1/hooks")).to have_been_made - end - - it "should return an array of hooks" do - expect(@hooks).to be_an Array - expect(@hooks.first.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - - describe ".project_hook" do - before do - stub_get("/projects/1/hooks/1", "project_hook") - @hook = Gitlab.project_hook(1, 1) - end - - it "should get the correct resource" do - expect(a_get("/projects/1/hooks/1")).to have_been_made - end - - it "should return information about a hook" do - expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - - describe ".add_project_hook" do - context "without specified events" do - before do - stub_post("/projects/1/hooks", "project_hook") - @hook = Gitlab.add_project_hook(1, "https://api.example.net/v1/webhooks/ci") - end - - it "should get the correct resource" do - body = {:url => "https://api.example.net/v1/webhooks/ci"} - expect(a_post("/projects/1/hooks").with(:body => body)).to have_been_made - end - - it "should return information about an added hook" do - expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - - context "with specified events" do - before do - stub_post("/projects/1/hooks", "project_hook") - @hook = Gitlab.add_project_hook(1, "https://api.example.net/v1/webhooks/ci", push_events: true, merge_requests_events: true) - end - - it "should get the correct resource" do - body = {:url => "https://api.example.net/v1/webhooks/ci", push_events: "true", merge_requests_events: "true"} - expect(a_post("/projects/1/hooks").with(:body => body)).to have_been_made - end - - it "should return information about an added hook" do - expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - end - - describe ".edit_project_hook" do - before do - stub_put("/projects/1/hooks/1", "project_hook") - @hook = Gitlab.edit_project_hook(1, 1, "https://api.example.net/v1/webhooks/ci") - end - - it "should get the correct resource" do - body = {:url => "https://api.example.net/v1/webhooks/ci"} - expect(a_put("/projects/1/hooks/1").with(:body => body)).to have_been_made - end - - it "should return information about an edited hook" do - expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - - describe ".delete_project_hook" do - before do - stub_delete("/projects/1/hooks/1", "project_hook") - @hook = Gitlab.delete_project_hook(1, 1) - end - - it "should get the correct resource" do - expect(a_delete("/projects/1/hooks/1")).to have_been_made - end - - it "should return information about a deleted hook" do - expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci") - end - end - - describe ".make_forked_from" do - before do - stub_post("/projects/42/fork/24", "project_fork_link") - @forked_project_link = Gitlab.make_forked_from(42, 24) - end - - it "should get the correct resource" do - expect(a_post("/projects/42/fork/24")).to have_been_made - end - - it "should return information about a forked project" do - expect(@forked_project_link.forked_from_project_id).to eq(24) - expect(@forked_project_link.forked_to_project_id).to eq(42) - end - end - - describe ".remove_forked" do - before do - stub_delete("/projects/42/fork", "project_fork_link") - @forked_project_link = Gitlab.remove_forked(42) - end - - it "should be sent to correct resource" do - expect(a_delete("/projects/42/fork")).to have_been_made - end - - it "should return information about an unforked project" do - expect(@forked_project_link.forked_to_project_id).to eq(42) - end - end - - describe ".deploy_keys" do - before do - stub_get("/projects/42/keys", "project_keys") - @deploy_keys = Gitlab.deploy_keys(42) - end - - it "should get the correct resource" do - expect(a_get("/projects/42/keys")).to have_been_made - end - - it "should return project deploy keys" do - expect(@deploy_keys).to be_an Array - expect(@deploy_keys.first.id).to eq 2 - expect(@deploy_keys.first.title).to eq "Key Title" - expect(@deploy_keys.first.key).to match(/ssh-rsa/) - end - end - - describe ".deploy_key" do - before do - stub_get("/projects/42/keys/2", "project_key") - @deploy_key = Gitlab.deploy_key(42, 2) - end - - it "should get the correct resource" do - expect(a_get("/projects/42/keys/2")).to have_been_made - end - - it "should return project deploy key" do - expect(@deploy_key.id).to eq 2 - expect(@deploy_key.title).to eq "Key Title" - expect(@deploy_key.key).to match(/ssh-rsa/) - end - end - - describe ".delete_deploy_key" do - before do - stub_delete("/projects/42/keys/2", "project_delete_key") - @deploy_key = Gitlab.delete_deploy_key(42, 2) - end - - it "should get the correct resource" do - expect(a_delete("/projects/42/keys/2")).to have_been_made - end - - it "should return information about a deleted key" do - expect(@deploy_key.id).to eq(2) - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/repositories_spec.rb b/lib/gitlab-cli/spec/gitlab/client/repositories_spec.rb deleted file mode 100644 index 0bcc8de5..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/repositories_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - it { should respond_to :repo_tags } - it { should respond_to :repo_create_tag } - it { should respond_to :repo_branches } - it { should respond_to :repo_branch } - it { should respond_to :repo_commits } - it { should respond_to :repo_commit } - it { should respond_to :repo_commit_diff } - - describe ".tags" do - before do - stub_get("/projects/3/repository/tags", "project_tags") - @tags = Gitlab.tags(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/tags")).to have_been_made - end - - it "should return an array of repository tags" do - expect(@tags).to be_an Array - expect(@tags.first.name).to eq("v2.8.2") - end - end - - describe ".create_tag" do - before do - stub_post("/projects/3/repository/tags", "tag") - @tag = Gitlab.create_tag(3, 'v1.0.0', '2695effb5807a22ff3d138d593fd856244e155e7') - end - - it "should get the correct resource" do - expect(a_post("/projects/3/repository/tags")).to have_been_made - end - - it "should return information about a new repository tag" do - expect(@tag.name).to eq("v1.0.0") - end - end - - describe ".commits" do - before do - stub_get("/projects/3/repository/commits", "project_commits"). - with(:query => {:ref_name => "api"}) - @commits = Gitlab.commits(3, :ref_name => "api") - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/commits"). - with(:query => {:ref_name => "api"})).to have_been_made - end - - it "should return an array of repository commits" do - expect(@commits).to be_an Array - expect(@commits.first.id).to eq("f7dd067490fe57505f7226c3b54d3127d2f7fd46") - end - end - - describe ".commit" do - before do - stub_get("/projects/3/repository/commits/6104942438c14ec7bd21c6cd5bd995272b3faff6", "project_commit") - @commit = Gitlab.commit(3, '6104942438c14ec7bd21c6cd5bd995272b3faff6') - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/commits/6104942438c14ec7bd21c6cd5bd995272b3faff6")) - .to have_been_made - end - - it "should return a repository commit" do - expect(@commit.id).to eq("6104942438c14ec7bd21c6cd5bd995272b3faff6") - end - end - - describe ".commit_diff" do - before do - stub_get("/projects/3/repository/commits/6104942438c14ec7bd21c6cd5bd995272b3faff6/diff", "project_commit_diff") - @diff = Gitlab.commit_diff(3, '6104942438c14ec7bd21c6cd5bd995272b3faff6') - end - - it "should get the correct resource" do - expect(a_get("/projects/3/repository/commits/6104942438c14ec7bd21c6cd5bd995272b3faff6/diff")) - .to have_been_made - end - - it "should return a diff of a commit" do - expect(@diff.new_path).to eq("doc/update/5.4-to-6.0.md") - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/snippets_spec.rb b/lib/gitlab-cli/spec/gitlab/client/snippets_spec.rb deleted file mode 100644 index 751c4d0b..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/snippets_spec.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".snippets" do - before do - stub_get("/projects/3/snippets", "snippets") - @snippets = Gitlab.snippets(3) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/snippets")).to have_been_made - end - - it "should return an array of project's snippets" do - expect(@snippets).to be_an Array - expect(@snippets.first.file_name).to eq("mailer_test.rb") - end - end - - describe ".snippet" do - before do - stub_get("/projects/3/snippets/1", "snippet") - @snippet = Gitlab.snippet(3, 1) - end - - it "should get the correct resource" do - expect(a_get("/projects/3/snippets/1")).to have_been_made - end - - it "should return information about a snippet" do - expect(@snippet.file_name).to eq("mailer_test.rb") - expect(@snippet.author.name).to eq("John Smith") - end - end - - describe ".create_snippet" do - before do - stub_post("/projects/3/snippets", "snippet") - @snippet = Gitlab.create_snippet(3, {:title => 'API', :file_name => 'api.rb', :code => 'code'}) - end - - it "should get the correct resource" do - body = {:title => 'API', :file_name => 'api.rb', :code => 'code'} - expect(a_post("/projects/3/snippets").with(:body => body)).to have_been_made - end - - it "should return information about a new snippet" do - expect(@snippet.file_name).to eq("mailer_test.rb") - expect(@snippet.author.name).to eq("John Smith") - end - end - - describe ".edit_snippet" do - before do - stub_put("/projects/3/snippets/1", "snippet") - @snippet = Gitlab.edit_snippet(3, 1, :file_name => 'mailer_test.rb') - end - - it "should get the correct resource" do - expect(a_put("/projects/3/snippets/1"). - with(:body => {:file_name => 'mailer_test.rb'})).to have_been_made - end - - it "should return information about an edited snippet" do - expect(@snippet.file_name).to eq("mailer_test.rb") - expect(@snippet.author.name).to eq("John Smith") - end - end - - describe ".delete_snippet" do - before do - stub_delete("/projects/3/snippets/1", "snippet") - @snippet = Gitlab.delete_snippet(3, 1) - end - - it "should get the correct resource" do - expect(a_delete("/projects/3/snippets/1")).to have_been_made - end - - it "should return information about a deleted snippet" do - expect(@snippet.file_name).to eq("mailer_test.rb") - expect(@snippet.author.name).to eq("John Smith") - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/system_hooks_spec.rb b/lib/gitlab-cli/spec/gitlab/client/system_hooks_spec.rb deleted file mode 100644 index 754e8684..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/system_hooks_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - it { should respond_to :system_hooks } - it { should respond_to :add_system_hook } - it { should respond_to :system_hook } - it { should respond_to :delete_system_hook } - - describe ".hooks" do - before do - stub_get("/hooks", "system_hooks") - @hooks = Gitlab.hooks - end - - it "should get the correct resource" do - expect(a_get("/hooks")).to have_been_made - end - - it "should return an array of system hooks" do - expect(@hooks).to be_an Array - expect(@hooks.first.url).to eq("http://example.com/hook") - end - end - - describe ".add_hook" do - before do - stub_post("/hooks", "system_hook") - @hook = Gitlab.add_hook("http://example.com/hook") - end - - it "should get the correct resource" do - expect(a_post("/hooks")).to have_been_made - end - - it "should return information about a added system hook" do - expect(@hook.url).to eq("http://example.com/hook") - end - end - - describe ".hook" do - before do - stub_get("/hooks/3", "system_hook_test") - @hook = Gitlab.hook(3) - end - it "should get the correct resource" do - expect(a_get("/hooks/3")).to have_been_made - end - - it "should return information about a added system hook" do - expect(@hook.event_name).to eq("project_create") - expect(@hook.project_id).to eq(1) - end - end - - describe ".delete_hook" do - before do - stub_delete("/hooks/3", "system_hook") - @hook = Gitlab.delete_hook(3) - end - - it "should get the correct resource" do - expect(a_delete("/hooks/3")).to have_been_made - end - - it "should return information about a deleted system hook" do - expect(@hook.url).to eq("http://example.com/hook") - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/client/users_spec.rb b/lib/gitlab-cli/spec/gitlab/client/users_spec.rb deleted file mode 100644 index cfbc7d50..00000000 --- a/lib/gitlab-cli/spec/gitlab/client/users_spec.rb +++ /dev/null @@ -1,192 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Client do - describe ".users" do - before do - stub_get("/users", "users") - @users = Gitlab.users - end - - it "should get the correct resource" do - expect(a_get("/users")).to have_been_made - end - - it "should return an array of users" do - expect(@users).to be_an Array - expect(@users.first.email).to eq("john@example.com") - end - end - - describe ".user" do - context "with user ID passed" do - before do - stub_get("/users/1", "user") - @user = Gitlab.user(1) - end - - it "should get the correct resource" do - expect(a_get("/users/1")).to have_been_made - end - - it "should return information about a user" do - expect(@user.email).to eq("john@example.com") - end - end - - context "without user ID passed" do - before do - stub_get("/user", "user") - @user = Gitlab.user - end - - it "should get the correct resource" do - expect(a_get("/user")).to have_been_made - end - - it "should return information about an authorized user" do - expect(@user.email).to eq("john@example.com") - end - end - end - - describe ".create_user" do - context "when successful request" do - before do - stub_post("/users", "user") - @user = Gitlab.create_user("email", "pass") - end - - it "should get the correct resource" do - body = {:email => "email", :password => "pass", :name => "email"} - expect(a_post("/users").with(:body => body)).to have_been_made - end - - it "should return information about a created user" do - expect(@user.email).to eq("john@example.com") - end - end - - context "when bad request" do - it "should throw an exception" do - stub_post("/users", "error_already_exists", 409) - expect { - Gitlab.create_user("email", "pass") - }.to raise_error(Gitlab::Error::Conflict, "Server responded with code 409, message: 409 Already exists. Request URI: #{Gitlab.endpoint}/users") - end - end - end - - describe ".edit_user" do - before do - @options = { :name => "Roberto" } - stub_put("/users/1", "user").with(:body => @options) - @user = Gitlab.edit_user(1, @options) - end - - it "should get the correct resource" do - expect(a_put("/users/1").with(:body => @options)).to have_been_made - end - end - - describe ".session" do - after do - Gitlab.endpoint = 'https://api.example.com' - Gitlab.private_token = 'secret' - end - - before do - stub_request(:post, "#{Gitlab.endpoint}/session"). - to_return(:body => load_fixture('session'), :status => 200) - @session = Gitlab.session("email", "pass") - end - - context "when endpoint is not set" do - it "should raise Error::MissingCredentials" do - Gitlab.endpoint = nil - expect { - Gitlab.session("email", "pass") - }.to raise_error(Gitlab::Error::MissingCredentials, 'Please set an endpoint to API') - end - end - - context "when private_token is not set" do - it "should not raise Error::MissingCredentials" do - Gitlab.private_token = nil - expect { Gitlab.session("email", "pass") }.to_not raise_error - end - end - - context "when endpoint is set" do - it "should get the correct resource" do - expect(a_request(:post, "#{Gitlab.endpoint}/session")).to have_been_made - end - - it "should return information about a created session" do - expect(@session.email).to eq("john@example.com") - expect(@session.private_token).to eq("qEsq1pt6HJPaNciie3MG") - end - end - end - - describe ".ssh_keys" do - before do - stub_get("/user/keys", "keys") - @keys = Gitlab.ssh_keys - end - - it "should get the correct resource" do - expect(a_get("/user/keys")).to have_been_made - end - - it "should return an array of SSH keys" do - expect(@keys).to be_an Array - expect(@keys.first.title).to eq("narkoz@helium") - end - end - - describe ".ssh_key" do - before do - stub_get("/user/keys/1", "key") - @key = Gitlab.ssh_key(1) - end - - it "should get the correct resource" do - expect(a_get("/user/keys/1")).to have_been_made - end - - it "should return information about an SSH key" do - expect(@key.title).to eq("narkoz@helium") - end - end - - describe ".create_ssh_key" do - before do - stub_post("/user/keys", "key") - @key = Gitlab.create_ssh_key("title", "body") - end - - it "should get the correct resource" do - body = {:title => "title", :key => "body"} - expect(a_post("/user/keys").with(:body => body)).to have_been_made - end - - it "should return information about a created SSH key" do - expect(@key.title).to eq("narkoz@helium") - end - end - - describe ".delete_ssh_key" do - before do - stub_delete("/user/keys/1", "key") - @key = Gitlab.delete_ssh_key(1) - end - - it "should get the correct resource" do - expect(a_delete("/user/keys/1")).to have_been_made - end - - it "should return information about a deleted SSH key" do - expect(@key.title).to eq("narkoz@helium") - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/objectified_hash_spec.rb b/lib/gitlab-cli/spec/gitlab/objectified_hash_spec.rb deleted file mode 100644 index 5a166dc7..00000000 --- a/lib/gitlab-cli/spec/gitlab/objectified_hash_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' - -describe Gitlab::ObjectifiedHash do - before do - @hash = {a: 1, b: 2} - @oh = Gitlab::ObjectifiedHash.new @hash - end - - it "should objectify hash" do - expect(@oh.a).to eq(@hash[:a]) - expect(@oh.b).to eq(@hash[:b]) - end - - describe "#to_hash" do - it "should return an original hash" do - expect(@oh.to_hash).to eq(@hash) - end - - it "should have an alias #to_h" do - expect(@oh.respond_to?(:to_h)).to be_truthy - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab/request_spec.rb b/lib/gitlab-cli/spec/gitlab/request_spec.rb deleted file mode 100644 index 29125d08..00000000 --- a/lib/gitlab-cli/spec/gitlab/request_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Request do - it { should respond_to :get } - it { should respond_to :post } - it { should respond_to :put } - it { should respond_to :delete } - - describe ".default_options" do - it "should have default values" do - default_options = Gitlab::Request.default_options - expect(default_options).to be_a Hash - expect(default_options[:parser]).to be_a Proc - expect(default_options[:format]).to eq(:json) - expect(default_options[:headers]).to eq({'Accept' => 'application/json'}) - expect(default_options[:default_params]).to be_nil - end - end - - describe ".parse" do - it "should return ObjectifiedHash" do - body = JSON.unparse({a: 1, b: 2}) - expect(Gitlab::Request.parse(body)).to be_an Gitlab::ObjectifiedHash - end - end - - describe "#set_request_defaults" do - context "when endpoint is not set" do - it "should raise Error::MissingCredentials" do - expect { - Gitlab::Request.new.set_request_defaults(nil, 1234000) - }.to raise_error(Gitlab::Error::MissingCredentials, 'Please set an endpoint to API') - end - end - - context "when endpoint is set" do - it "should set base_uri" do - Gitlab::Request.new.set_request_defaults('http://rabbit-hole.example.org', 1234000) - expect(Gitlab::Request.base_uri).to eq("http://rabbit-hole.example.org") - end - - it "should set default_params" do - Gitlab::Request.new.set_request_defaults('http://rabbit-hole.example.org', 1234000, 'sudoer') - expect(Gitlab::Request.default_params).to eq({:sudo => 'sudoer'}) - end - end - end -end diff --git a/lib/gitlab-cli/spec/gitlab_spec.rb b/lib/gitlab-cli/spec/gitlab_spec.rb deleted file mode 100644 index 7a1ada4d..00000000 --- a/lib/gitlab-cli/spec/gitlab_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'spec_helper' - -describe Gitlab do - after { Gitlab.reset } - - describe ".client" do - it "should be a Gitlab::Client" do - expect(Gitlab.client).to be_a Gitlab::Client - end - end - - describe ".actions" do - it "should return an array of client methods" do - actions = Gitlab.actions - expect(actions).to be_an Array - expect(actions.first).to be_a Symbol - expect(actions.sort.first).to match(/add_/) - end - end - - describe ".endpoint=" do - it "should set endpoint" do - Gitlab.endpoint = 'https://api.example.com' - expect(Gitlab.endpoint).to eq('https://api.example.com') - end - end - - describe ".private_token=" do - it "should set private_token" do - Gitlab.private_token = 'secret' - expect(Gitlab.private_token).to eq('secret') - end - end - - describe ".sudo=" do - it "should set sudo" do - Gitlab.sudo = 'user' - expect(Gitlab.sudo).to eq('user') - end - end - - describe ".user_agent" do - it "should return default user_agent" do - expect(Gitlab.user_agent).to eq(Gitlab::Configuration::DEFAULT_USER_AGENT) - end - end - - describe ".user_agent=" do - it "should set user_agent" do - Gitlab.user_agent = 'Custom User Agent' - expect(Gitlab.user_agent).to eq('Custom User Agent') - end - end - - describe ".configure" do - Gitlab::Configuration::VALID_OPTIONS_KEYS.each do |key| - it "should set #{key}" do - Gitlab.configure do |config| - config.send("#{key}=", key) - expect(Gitlab.send(key)).to eq(key) - end - end - end - end -end diff --git a/lib/gitlab-cli/spec/spec_helper.rb b/lib/gitlab-cli/spec/spec_helper.rb deleted file mode 100644 index 06d57c84..00000000 --- a/lib/gitlab-cli/spec/spec_helper.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'rspec' -require 'webmock/rspec' - -require File.expand_path('../../lib/gitlab', __FILE__) -require File.expand_path('../../lib/gitlab/cli', __FILE__) - -def capture_output - out = StringIO.new - $stdout = out - $stderr = out - yield - $stdout = STDOUT - $stderr = STDERR - out.string -end - -def load_fixture(name) - File.new(File.dirname(__FILE__) + "/fixtures/#{name}.json") -end - -RSpec.configure do |config| - config.before(:all) do - Gitlab.endpoint = 'https://api.example.com' - Gitlab.private_token = 'secret' - end -end - -# GET -def stub_get(path, fixture) - stub_request(:get, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}). - to_return(:body => load_fixture(fixture)) -end - -def a_get(path) - a_request(:get, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}) -end - -# POST -def stub_post(path, fixture, status_code=200) - stub_request(:post, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}). - to_return(:body => load_fixture(fixture), :status => status_code) -end - -def a_post(path) - a_request(:post, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}) -end - -# PUT -def stub_put(path, fixture) - stub_request(:put, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}). - to_return(:body => load_fixture(fixture)) -end - -def a_put(path) - a_request(:put, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}) -end - -# DELETE -def stub_delete(path, fixture) - stub_request(:delete, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}). - to_return(:body => load_fixture(fixture)) -end - -def a_delete(path) - a_request(:delete, "#{Gitlab.endpoint}#{path}"). - with(:headers => {'PRIVATE-TOKEN' => Gitlab.private_token}) -end diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake new file mode 100644 index 00000000..356d43fc --- /dev/null +++ b/lib/tasks/auto_annotate_models.rake @@ -0,0 +1,34 @@ +# NOTE: only doing this in development as some production environments (Heroku) +# NOTE: are sensitive to local FS writes, and besides -- it's just not proper +# NOTE: to have a dev-mode tool do its thing in production. +if Rails.env.development? + task :set_annotation_options do + # You can override any of these by setting an environment variable of the + # same name. + Annotate.set_defaults({ + 'position_in_routes' => "before", + 'position_in_class' => "before", + 'position_in_test' => "before", + 'position_in_fixture' => "before", + 'position_in_factory' => "before", + 'show_indexes' => "true", + 'simple_indexes' => "false", + 'model_dir' => "app/models", + 'include_version' => "false", + 'require' => "", + 'exclude_tests' => "true", + 'exclude_fixtures' => "true", + 'exclude_factories' => "false", + 'ignore_model_sub_dir' => "false", + 'skip_on_db_migrate' => "false", + 'format_bare' => "true", + 'format_rdoc' => "false", + 'format_markdown' => "false", + 'sort' => "false", + 'force' => "false", + 'trace' => "false", + }) + end + + Annotate.load_tasks +end diff --git a/lib/tasks/dev_ops_languages.rake b/lib/tasks/dev_ops_languages.rake new file mode 100644 index 00000000..348fb932 --- /dev/null +++ b/lib/tasks/dev_ops_languages.rake @@ -0,0 +1,752 @@ +desc "Initialize the data for dev ops languages" +namespace :dev_ops_languages do + + task init: :environment do + # DevOps::Language.bulk_insert do |worker| + # languages.each do |attrs| + # worker.add(attrs) + # end + # end + + languages.each do |l| + content = Base64.encode64 l[:content] + Ci::Language.create!(name: l[:name], content: content) + end + end + + def languages + [ + { + name: "C", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: gcc + commands: + - ./configure + - make + - make test" + }, + { + name: "C++", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: gcc + commands: + - ./configure + - make + - make test" + }, + { + name: "Docker", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: docker:dind + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - docker ps -a + +volumes: +- name: dockersock + host: + path: /var/run/docker.sock" + }, + { + name: "Java", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: maven:3-jdk-10 + commands: + - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V + - mvn test -B" + }, + { + name: "R", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: r-base + commands: + - R -e 'install.packages(c('package1','package2'))' + - R CMD build ." + }, + { + name: "Ruby", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: ruby + commands: + - bundle install --jobs=3 --retry=3 + - rake" + }, + { + name: "PHP", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: install + image: composer + commands: + - composer install + +- name: test + image: php:7 + commands: + - vendor/bin/phpunit --configuration config.xml" + }, + { + name: "Python", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: python + commands: + - pip install -r requirements.txt + - pytest" + }, + { + name: "MySQL", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: mysql + commands: + - sleep 15 + - mysql -u root -h database --execute='SELECT VERSION();' + +services: +- name: database + image: mysql + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + MYSQL_DATABASE: test" + }, + { + name: "MongoDB", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: ping + image: mongo:4 + commands: + - sleep 5 + - mongo --host mongo --eval 'db.version()' + +services: +- name: mongo + image: mongo:4 + command: [ --smallfiles ]" + }, + { + name: "Clojure", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: clojure + commands: + - lein test" + }, + { + name: "CouchDB", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: couchdb:2.2 + commands: + - sleep 15 + - curl http://database:5984 + +services: +- name: database + image: couchdb:2.2" + }, + { + name: "Crystal", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: crystallang/crystal + commands: + - shards install + - crystal spec.2" + }, + { + name: "D", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: dlanguage/dmd + commands: + - dub test" + }, + { + name: "Dart", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: google/dart + commands: + - pub get + - pub run test" + }, + { + name: "Docker (dind)", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: docker:dind + volumes: + - name: dockersock + path: /var/run + commands: + - sleep 5 # give docker enough time to start + - docker ps -a + +services: +- name: docker + image: docker:dind + privileged: true + volumes: + - name: dockersock + path: /var/run + +volumes: +- name: dockersock + temp: {}" + }, + { + name: "Elasticsearch", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: alpine:3.8 + commands: + - apk add curl + - sleep 45 + - curl http://database:9200 + +services: +- name: database + image: elasticsearch:5-alpine" + }, + { + name: "Elixir", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: elixir:1.5 + commands: + - mix local.rebar --force + - mix local.hex --force + - mix deps.get + - mix test" + }, + { + name: "Erlang", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: erlang:21 + commands: + - rebar get-deps + - rebar compile + - rebar skip_deps=true eunit" + }, + { + name: "20.Go (with Gopath)", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +workspace: + base: /go + path: src/hello-world + +steps: +- name: test + image: golang + commands: + - go get + - go test" + }, + { + name: "21.Go (with Modules)", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: golang + commands: + - go test + - go build" + }, + { + name: "Gradle", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: gradle:jdk10 + commands: + - gradle assemble + - gradle check" + }, + { + name: "Groovy", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: gradle:2.5-jdk8 + commands: + - ./gradlew assemble + - ./gradlew check" + }, + { + name: "Haskell", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: haskell + commands: + - cabal install --only-dependencies --enable-tests + - cabal configure --enable-tests + - cabal build + - cabal test" + }, + { + name: "Haxe", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: haxe + commands: + - haxelib install build.hxml + - haxe build.hxml" + }, + { + name: "MariaDB", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: mariadb + commands: + - sleep 15 + - mysql -u root -h database --execute='SELECT VERSION();' + +services: +- name: database + image: mariadb + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + MYSQL_DATABASE: test" + }, + { + name: "Maven", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: maven:3-jdk-10 + commands: + - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V + - mvn test -B" + }, + { + name: "Memcached", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: ubuntu + commands: + - apt-get update -qq + - apt-get install -y -qq telnet > /dev/null + - (sleep 1; echo 'stats'; sleep 2; echo 'quit';) | telnet cache 11211 || true + +services: +- name: cache + image: memcached:alpine + command: [ -vv ]" + }, + { + name: "Nats", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: ruby:2 + commands: + - gem install nats + - nats-pub -s tcp://nats:4222 greeting 'hello' + - nats-pub -s tcp://nats:4222 greeting 'world' + +services: +- name: nats + image: nats:1.3.0" + }, + { + name: "Node", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: node + commands: + - npm install + - npm test" + }, + { + name: "Perl", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: perl + commands: + - cpanm --quiet --installdeps --notest . + - perl Build.PL + - ./Build test" + }, + { + name: "Postgres", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: postgres:9-alpine + commands: + - psql -U postgres -d test -h database + +services: +- name: database + image: postgres:9-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_DB: test" + }, + { + name: "Redis", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: redis + commands: + - sleep 5 + - redis-cli -h redis ping + - redis-cli -h redis set FOO bar + - redis-cli -h redis get FOO + +services: +- name: redis + image: redis" + }, + { + name: "RethinkDB", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: node:9 + commands: + - npm install -s -g recli + - recli -h database -j 'r.db('rethinkdb').table('stats')' + +services: +- name: database + image: rethinkdb:2 + command: [ rethinkdb, --bind, all ]" + }, + { + name: "Rust", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: rust:1.30 + commands: + - cargo build --verbose --all + - cargo test --verbose --all" + }, + { + name: "Swift", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: swift:4 + commands: + - swift build + - swift test" + }, + { + name: "Vault", + content: " +kind: pipeline +name: default + +platform: + os: linux + arch: arm64 + +steps: +- name: test + image: vault:1.0.0-beta2 + environment: + VAULT_ADDR: http://vault:8200 + VAULT_TOKEN: dummy + commands: + - sleep 5 + - vault kv put secret/my-secret my-value=s3cr3t + - vault kv get secret/my-secret + +services: +- name: vault + image: vault:1.0.0-beta2 + environment: + VAULT_DEV_ROOT_TOKEN_ID: dummy" + } + ] + end +end diff --git a/lib/tasks/sync_table_structure.rake b/lib/tasks/sync_table_structure.rake index e1a775c5..026d5214 100644 --- a/lib/tasks/sync_table_structure.rake +++ b/lib/tasks/sync_table_structure.rake @@ -4,7 +4,17 @@ namespace :sync_table_structure do task import_csv: :environment do puts "init table structure......." - system "mysql -uroot -poracle10g -h127.0.0.1 forge_development < #{Rails.root}/db/structure.sql" + database_config = Rails.configuration.database_configuration + + database = database_config[Rails.env]["database"] + database_username = database_config[Rails.env]["username"] + database_password = database_config[Rails.env]["password"] + database_host = database_config[Rails.env]["host"] + database_port = database_config[Rails.env]["port"] || 3306 + + puts "bash: mysql -u#{database_username} -p#{database_password} -P#{database_port} -h#{database_host} #{database}" + + system "mysql -u#{database_username} -p#{database_password} -P#{database_port} -h#{database_host} #{database} < #{Rails.root}/db/structure.sql" puts "init success" end diff --git a/public/react/build b/public/react/build deleted file mode 160000 index 447edde1..00000000 --- a/public/react/build +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 447edde157092e65f05b36bc41c472659c482c6a diff --git a/spec/controllers/protected_branches_controller_spec.rb b/spec/controllers/protected_branches_controller_spec.rb new file mode 100644 index 00000000..086b746b --- /dev/null +++ b/spec/controllers/protected_branches_controller_spec.rb @@ -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 diff --git a/spec/helpers/protected_branches_helper_spec.rb b/spec/helpers/protected_branches_helper_spec.rb new file mode 100644 index 00000000..54c22c2f --- /dev/null +++ b/spec/helpers/protected_branches_helper_spec.rb @@ -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 diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb new file mode 100644 index 00000000..3246d09e --- /dev/null +++ b/spec/models/ci/build_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Ci::Build, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ci/repo_spec.rb b/spec/models/ci/repo_spec.rb new file mode 100644 index 00000000..40753699 --- /dev/null +++ b/spec/models/ci/repo_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Ci::Repo, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb new file mode 100644 index 00000000..ba43cca2 --- /dev/null +++ b/spec/models/ci/stage_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Ci::Stage, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ci/step_spec.rb b/spec/models/ci/step_spec.rb new file mode 100644 index 00000000..46ab7a4a --- /dev/null +++ b/spec/models/ci/step_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Ci::Step, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb new file mode 100644 index 00000000..751a60c2 --- /dev/null +++ b/spec/models/protected_branch_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProtectedBranch, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end
导航名称导航名称 导航链接是否展示是否展示操作
<%= text_field_tag('navbar[][name]', nav['name'], id: nil, class: 'form-control') %> <%= check_box_tag('navbar[][hidden]', 0, !nav['hidden'], id: nil, class: 'font-16') %> +
+ +
+