dev_forge
caicai8 5 years ago
commit 3ca6f8c57d

@ -1078,10 +1078,11 @@ DELETE /api/:login/:repo_identifier/contents
*示例* *示例*
``` ```
curl -X POST \ curl -X POST \
-d 'filepath=test_create_file.rb' \ -d 'filepath=test1_create_file1.rb' \
-d 'branch=master' \ -d 'branch=develop' \
-d 'content=ZnNmc2FkZg==' \ -d 'content=ZnNmc2FkZg==' \
http://localhost:3000/api/18816895620/mirror_demo/contents | jq -d 'message=test commit ' \
http://localhost:3000/api/18816895620/mirror_demo/contents.json | jq
``` ```
*请求参数说明:* *请求参数说明:*
@ -1100,14 +1101,41 @@ http://localhost:3000/api/18816895620/mirror_demo/contents | jq
|参数名|类型|说明| |参数名|类型|说明|
-|-|- -|-|-
|status |int|0:点赞成功,-1:操作失败2:表示还未点赞| |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|文件创建时间|
返回值 返回值
``` ```
{ {
"status": 0, "name": "test1_create_file12.rb",
"message": "响应成功" "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"
}
}
} }
``` ```
--- ---

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

@ -0,0 +1,3 @@
// Place all the styles related to the version_releases controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@ -328,7 +328,7 @@ class ApplicationController < ActionController::Base
def current_user def current_user
# User.current # User.current
User.find_by_id 36401 User.find_by_id 1
end end
## 默认输出json ## 默认输出json

@ -0,0 +1,31 @@
class ContentsController < ApplicationController
before_action :find_user, :find_repository
before_action :require_login, only: %i[create]
def create
# request_params = {user: @user, repo_name: @repo.identifier, filepath: params[:filepath]}
logger.info "current_user ----> #{current_user.login}"
@user = current_user
interactor = Gitea::CreateFileInteractor.call(@user, content_params)
if interactor.success?
@file = interactor.result
logger.info "@file ========> #{@file}"
else
render_error(interactor.error)
end
end
def update_file
end
def delete_file
end
private
def content_params
params.permit(:login, :repo_identifier, :filepath, :branch, :content, :message, :new_branch)
end
end

@ -49,7 +49,7 @@ class IssuesController < ApplicationController
order_name = params[:order_name] || "created_on" #或者"updated_on" order_name = params[:order_name] || "created_on" #或者"updated_on"
@page = params[:page] @page = params[:page]
@limit = params[:limit] || "15" @limit = params[:limit] || 15
@issues = issues.order("#{order_name} #{order_type}") @issues = issues.order("#{order_name} #{order_type}")
@issues_size = issues.size @issues_size = issues.size
@issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit) @issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit)
@ -175,6 +175,7 @@ class IssuesController < ApplicationController
parent_container_id: @project.id, parent_container_type: "Project", parent_container_id: @project.id, parent_container_type: "Project",
tiding_type: 'issue', status: 0) tiding_type: 'issue', status: 0)
end end
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
normal_status(0, "创建成功") normal_status(0, "创建成功")
else else
normal_status(-1, "创建失败") normal_status(-1, "创建失败")
@ -300,6 +301,7 @@ class IssuesController < ApplicationController
end end
if @issue.update_attribute(:status_id, type) if @issue.update_attribute(:status_id, type)
if type == 5 if type == 5
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "close")
@issue.issue_times.update_all(end_time: Time.now) @issue.issue_times.update_all(end_time: Time.now)
end end
@issue.create_journal_detail(false, [], []) @issue.create_journal_detail(false, [], [])

@ -35,6 +35,8 @@ class JournalsController < ApplicationController
end end
end end
end end
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "journal")
normal_status(0, "评论成功") normal_status(0, "评论成功")
else else
normal_status(-1, "评论失败") normal_status(-1, "评论失败")

@ -0,0 +1,49 @@
class ProjectTrendsController < ApplicationController
before_action :set_project
before_action :check_project_public
def index
@project_issues_count = @project.get_issues_count(nil)
@project_open_issues_count = @project.get_issues_count([1,2,3,4,6])
@project_close_issues_count = @project.get_issues_count(5)
project_trends = @project.project_trends.includes(:user, trend: :user)
check_time = params[:time] #时间的筛选
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
check_status = params[:status] #类型的选择 "create", "close", "journal",
if check_time.present?
check_time = check_time.to_i
project_trends = project_trends.where("created_at between ? and ?",(Time.now.beginning_of_day - check_time.days), Time.now.end_of_day)
end
if check_type.present?
project_trends = project_trends.where(trend_type: check_type.to_s.titleize)
end
if check_status.present?
project_trends = project_trends.where(action_type: check_status.to_s)
end
project_trends = project_trends.order("created_at desc")
@page = params[:page]
@limit = params[:limit] || 15
@project_trends_size = project_trends.size
@project_trends = project_trends.page(@page).per(@limit)
end
private
def set_project
@project = Project.find_by_id(params[:project_id])
unless @project.present?
normal_status(-1, "项目不存在")
end
end
def check_project_public
unless @project.is_public || @project.member?(current_user) || current_user.admin?
normal_status(-1, "您没有权限")
end
end
end

@ -0,0 +1,146 @@
class VersionReleasesController < ApplicationController
before_action :set_user_and_project
before_action :require_login, except: [:index]
before_action :find_version , only: [:edit, :update, :destroy]
def index
version_releases = @repository.version_releases.includes(:user)
version_releases = version_releases.where(draft: false) unless current_user.present? && (current_user == @user || current_user.admin?)
@version_releases_size = version_releases.size
page = params[:page]
@limit = params[:limit] || 15
@version_releases = version_releases.order("created_at desc").page(page).limit(@limit)
end
def new
#获取所有的分支
@all_branches = []
get_all_branches = Gitea::Repository::BranchesService.new(@user, @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
end
def create
if params[:name].nil?
normal_status(-1, "名称不能为空")
elsif params[:tag_name].blank?
normal_status(-1, "标签名称不能为空")
else
ActiveRecord::Base.transaction do
begin
version_params = {
body: params[:body],
draft: params[:draft] || false,
name: params[:name],
prerelease: params[:prerelease],
tag_name: params[:tag_name],
target_commitish: params[:target_commitish] || "master" #分支
}
version_release = VersionRelease.new(version_params.merge(user_id: current_user.id, repository_id: @repository.id))
if version_release.save!
git_version_release = Gitea::Versions::CreateService.new(@user.gitea_token, @repository.try(:login), @repository.try(:identifier), version_params).call
if git_version_release
update_params = {
tarball_url: git_version_release["tarball_url"],
zipball_url: git_version_release["zipball_url"],
url: git_version_release["url"],
version_gid: git_version_release["id"],
}
version_release.update_attributes!(update_params)
normal_status(0, "发布成功")
else
normal_status(-1, "发布失败")
end
else
normal_status(-1, "发布失败")
end
rescue => e
puts "create version release error: #{e.message}"
raise Error, e.message
end
end
end
end
def edit
end
def update
if params[:name].nil?
normal_status(-1, "名称不能为空")
elsif params[:tag_name].blank?
normal_status(-1, "标签名称不能为空")
else
ActiveRecord::Base.transaction do
begin
version_params = {
body: params[:body],
draft: params[:draft] || false,
name: params[:name],
prerelease: params[:prerelease],
tag_name: params[:tag_name],
target_commitish: params[:target_commitish] || "master" #分支
}
if @version.update_attributes!(version_params)
git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @repository.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
unless git_version_release
raise Error, "更新失败"
end
normal_status(0, "更新成功")
else
normal_status(-1, "更新失败")
end
rescue => e
puts "update version release error: #{e.message}"
raise Error, e.message
end
end
end
end
def destroy
ActiveRecord::Base.transaction do
begin
if @version.destroy
git_version_release = Gitea::Versions::UpdateService.new(@user.gitea_token, @repository.try(:login), @repository.try(:identifier), version_params, @version.try(:version_gid)).call
unless git_version_release
raise Error, "删除失败"
end
normal_status(0, "删除成功")
else
normal_status(-1, "删除失败")
end
rescue => e
puts "destroy version release error: #{e.message}"
raise Error, e.message
end
end
end
private
def set_user_and_project
@project = Project.find_by_id(params[:project_id])
@repository = @project.repository #项目的仓库
@user = @project.owner
unless @user.present? && @project.present? && @repository.present?
normal_status(-1, "仓库不存在")
end
end
def find_version
@version = VersionRelease.find_by_id(params[:id])
unless @version.present?
normal_status(-1, "版本不存在")
end
end
end

@ -0,0 +1,13 @@
class Contents::CreateForm < BaseForm
attr_accessor :login, :repo_identifier, :filepath, :branch, :new_branch
validates :login, :repo_identifier, :filepath, presence: true
validate :check_branch
def check_branch
raise "branch和new_branch必须存在一个 " if branch.blank? && new_branch.blank?
raise "branch和new_branch只能存在一个" if !branch.blank? && !new_branch.blank?
end
end

@ -0,0 +1,2 @@
module ContentsHelper
end

@ -0,0 +1,2 @@
module VersionReleasesHelper
end

@ -0,0 +1,64 @@
module Gitea
class CreateFileInteractor
def self.call(user, params={})
interactor = new(user, params)
interactor.run
interactor
end
attr_reader :error, :result
def initialize(user, params)
@user = user
@params = params
end
def success?
@error.nil?
end
def result
@result
end
def run
Contents::CreateForm.new(valid_params).validate!
response = Gitea::Repository::Entries::CreateService.new(user, @params[:repo_identifier], @params[:filepath], file_params).call
render_result(response)
rescue Exception => exception
Rails.logger.info "Exception ===========> #{exception.message}"
fail!(exception.message)
end
private
attr_reader :params, :user
def fail!(error)
@error = error
end
def render_result(response)
@result = response
end
def valid_params
{
login: @params[:login],
repo_identifier: @params[:repo_identifier],
filepath: @params[:filepath],
branch: @params[:branch],
new_branch: @params[:new_branch]
}
end
def file_params
file_params = {}
file_params = file_params.merge(branch: @params[:branch]) unless @params[:branch].blank?
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?
end
end
end

@ -2,6 +2,7 @@ class Issue < ApplicationRecord
#issue_type 1为普通2为悬赏 #issue_type 1为普通2为悬赏
belongs_to :project belongs_to :project
belongs_to :tracker belongs_to :tracker
has_many :project_trends, as: :trend, dependent: :destroy
# belongs_to :issue_tag,optional: true # belongs_to :issue_tag,optional: true
belongs_to :priority, :class_name => 'IssuePriority', foreign_key: :priority_id,optional: true # belongs_to :priority, :class_name => 'IssuePriority', foreign_key: :priority_id,optional: true #
belongs_to :version, foreign_key: :fixed_version_id,optional: true belongs_to :version, foreign_key: :fixed_version_id,optional: true
@ -17,6 +18,7 @@ class Issue < ApplicationRecord
has_many :issue_times, dependent: :destroy has_many :issue_times, dependent: :destroy
has_many :issue_depends, dependent: :destroy has_many :issue_depends, dependent: :destroy
scope :issue_includes, ->{includes(:user)} scope :issue_includes, ->{includes(:user)}
scope :issue_many_includes, ->{includes(journals: :user)}
def get_assign_user def get_assign_user
@ -78,4 +80,8 @@ class Issue < ApplicationRecord
end end
end end
def only_reply_journals
journals.where.not(notes: [nil, ""]).journal_includes.limit(2)
end
end end

@ -10,6 +10,7 @@ class Project < ApplicationRecord
belongs_to :owner, class_name: 'User', foreign_key: :user_id belongs_to :owner, class_name: 'User', foreign_key: :user_id
belongs_to :project_category , :counter_cache => true belongs_to :project_category , :counter_cache => true
belongs_to :project_language , :counter_cache => true belongs_to :project_language , :counter_cache => true
has_many :project_trends, dependent: :destroy
has_many :commits has_many :commits
@ -52,4 +53,13 @@ class Project < ApplicationRecord
self.identifier.parameterize self.identifier.parameterize
end end
def get_issues_count(status_id)
if status_id.present?
self&.issues.select(:id, :status_id).where(status_id: status_id)&.pluck(:id).size
else
self&.issues.select(:id)&.pluck(:id).size
end
end
end end

@ -0,0 +1,5 @@
class ProjectTrend < ApplicationRecord
belongs_to :project
belongs_to :trend, polymorphic: true, optional: true
belongs_to :user
end

@ -2,6 +2,7 @@ class Repository < ApplicationRecord
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
belongs_to :project, :touch => true belongs_to :project, :touch => true
belongs_to :user belongs_to :user
has_many :version_releases, dependent: :destroy
validates :identifier, presence: true, uniqueness: true validates :identifier, presence: true, uniqueness: true

@ -166,6 +166,8 @@ class User < ApplicationRecord
has_many :composes, dependent: :destroy has_many :composes, dependent: :destroy
has_many :compose_users, dependent: :destroy has_many :compose_users, dependent: :destroy
has_many :project_trends, dependent: :destroy
# Groups and active users # Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) } scope :active, lambda { where(status: STATUS_ACTIVE) }

@ -0,0 +1,4 @@
class VersionRelease < ApplicationRecord
belongs_to :repository
belongs_to :user
end

@ -50,6 +50,18 @@ class Gitea::ClientService < ApplicationService
render_status(response) render_status(response)
end end
def update(url, params={})
puts "[gitea] request params: #{params}"
request_url = [api_url, url].join('').freeze
auth_token = authen_params(params[:token])
response = conn(auth_token).put do |req|
req.url "#{request_url}"
req.body = params[:data].to_json
end
render_status(response)
end
private private
def conn(auth={}) def conn(auth={})
username = auth[:username] || access_key_id username = auth[:username] || access_key_id

@ -0,0 +1,43 @@
class Gitea::Repository::Entries::CreateService < Gitea::ClientService
attr_reader :user, :repo_name, :filepath, :body
# ref: The name of the commit/branch/tag. Default the repositorys default branch (usually master)
# filepath: path of the dir, file, symlink or submodule in the repo
# repo_name: the name of repository
# body:
# {
# "author": {
# "email": "user@example.com",
# "name": "string"
# },
# "branch": "string",
# "committer": {
# "email": "user@example.com",
# "name": "string"
# },
# "content": "string", # content must be base64 encoded
# "message": "string",
# "new_branch": "string"
# }
#
def initialize(user, repo_name, filepath, body)
@user = user
@repo_name = repo_name
@filepath = filepath
@body = body
end
def call
post(url, params)
end
private
def params
Hash.new.merge(token: user.gitea_token, data: body)
end
def url
"/repos/#{user.login}/#{repo_name}/contents/#{filepath}".freeze
end
end

@ -0,0 +1,33 @@
class Gitea::Repository::Tags::ListService < Gitea::ClientService
attr_reader :user, :repo_name
# ref: The name of the commit/branch/tag. Default the repositorys default branch (usually master)
# repo_name: the name of repository
def initialize(user, repo_name)
@user = user
@repo_name = repo_name
end
def call
response = get(url, params)
render_result(response)
end
private
def params
Hash.new.merge(token: user.gitea_token)
end
def url
"/repos/#{user.login}/#{repo_name}/tags".freeze
end
def render_result(response)
body = JSON.parse(response.body)
case response.status
when 200 then body
else
{status: -1, message: "#{body['message']}"}
end
end
end

@ -0,0 +1,34 @@
class Gitea::Versions::CreateService < Gitea::ClientService
attr_reader :token, :user_name, :repo, :params
# params EX:
# {
# "body": "sylor", #user_name
# "draft": false,
# "name": "string",
# "prerelease": true,
# "tag_name": "string",
# "target_commitish": "string"
# }
def initialize(token, user_name, repo, params)
@token = token
@params = params
@user_name = user_name
@repo = repo
end
def call
post(url, request_params)
end
private
def request_params
Hash.new.merge(token: token, data: params)
end
def url
"/repos/#{@user}/#{@repo}/releases".freeze
end
end

@ -0,0 +1,24 @@
class Gitea::Versions::DeleteService < Gitea::ClientService
attr_reader :token, :user_name, :repo,:version_gid
def initialize(token, user_name, repo,version_gid)
@token = token
@user_name = user_name
@repo = repo
@version_gid = version_gid
end
def call
delete(url, params)
end
private
def params
Hash.new.merge(token: @token)
end
def url
"/repos/#{@user}/#{@repo}/releases/#{@version_gid}".freeze
end
end

@ -0,0 +1,35 @@
class Gitea::Versions::UpdateService < Gitea::ClientService
attr_reader :token, :user_name, :repo, :params, :version_gid
# params EX:
# {
# "body": "sylor", #user_name
# "draft": false,
# "name": "string",
# "prerelease": true,
# "tag_name": "string",
# "target_commitish": "string"
# }
def initialize(token, user_name, repo, params,version_gid)
@token = token
@params = params
@user_name = user_name
@repo = repo
@version_gid = version_gid
end
def call
update(url, request_params)
end
private
def request_params
Hash.new.merge(token: token, data: params)
end
def url
"/repos/#{@user}/#{@repo}/releases/#{@version_gid}".freeze
end
end

@ -0,0 +1,10 @@
json.name @file['content']['name']
json.sha @file['content']['sha']
json.size @file['content']['size']
json.content @file['content']['content']
json.encoding @file['content']['encoding']
json.commit do
json.message @file['commit']['message']
json.author @file['commit']['author']
json.committer @file['commit']['committer']
end

@ -0,0 +1,18 @@
json.name issue.subject
json.created_at format_time(issue.created_on)
json.updated_at format_time(issue.updated_on)
json.assign_user_name issue.get_assign_user.try(:show_real_name)
json.assign_user_login issue.get_assign_user.try(:login)
json.issue_journal_size issue.get_journals_size
journals = issue.only_reply_journals
json.issue_journals do
json.array! journals.to_a.each do |j|
json.user_name j.user.try(:show_real_name)
json.user_login j.user.try(:login)
json.user_picture url_to_avatar(j.user)
json.content j.try(:notes)
json.created_at time_from_now(j.created_on)
end
end

@ -0,0 +1,24 @@
json.partial! "commons/success"
json.issues_count @project_issues_count
json.open_issues_count @project_open_issues_count
json.close_issues_count @project_close_issues_count
json.limit @limit
json.project_trends_size @project_trends_size
json.project_trends do
json.array! @project_trends.to_a.each do |trend|
json.id trend.id
json.trend_type trend.trend_type
json.action_type l("trend.#{trend.action_type}") + l("trend.#{trend.trend_type}")
json.trend_id trend.trend_id
json.user_login trend.user.login
json.user_avatar url_to_avatar(trend.user)
if trend.trend_type == "Issue"
json.partial! "issues/simple_issue_item", locals: {issue: trend.trend}
end
#后续需要天际pullrequest 和 版本的内容
end
end

@ -0,0 +1,9 @@
json.array! @tags do |tag|
json.name tag['name']
json.id tag['id']
json.zipball_url tag['zipball_url']
json.tarball_url tag['tarball_url']
json.commit do
json.sha tag['commit']['sha']
end
end

@ -0,0 +1 @@
json.extract! @version, :id, :name, :body, :tag_name, :target_commitish, :draft, :prerelease,:version_gid

@ -0,0 +1,21 @@
json.partial! "commons/success"
json.all_count @version_releases_size
json.limit @limit
json.version_releases do
json.array! @version_releases.to_a.each do |re|
json.id re.id
json.version_gid re.version_gid
json.name re.name
json.body re.body
json.tag_name re.tag_name
json.target_commitish re.target_commitish
json.release_type re.draft ? "草稿" : (re.prerelease ? "预发行" : "稳定")
json.tarball_url re.tarball_url
json.zipball_url re.zipball_url
json.url re.zipball_url
json.user_login re.user.try(:login)
json.user_avatar url_to_avatar(re.user)
json.created_at format_time(re.created_at)
json.format_created time_from_now(re.created_at)
end
end

@ -0,0 +1,2 @@
json.partial! "commons/success"
json.branches @all_branches

@ -14,6 +14,18 @@ zh-CN:
'processed': '已审批' 'processed': '已审批'
'refused': '已拒绝' 'refused': '已拒绝'
'agreed': '已同意' 'agreed': '已同意'
trend:
Issue: 工单
PullRequest: 合并请求
Version: 版本发布
create: 创建了
journal: 回复了
close: 关闭了
merge: 合并了
push: 发布了
version:
draft: 草稿
journal_detail: journal_detail:
issue_tags_value: 标签 issue_tags_value: 标签

@ -1,5 +1,5 @@
Rails.application.routes.draw do Rails.application.routes.draw do
require 'sidekiq/web' require 'sidekiq/web'
require 'admin_constraint' require 'admin_constraint'
mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new
@ -46,6 +46,8 @@ Rails.application.routes.draw do
resources :licenses, only: [:index, :show] resources :licenses, only: [:index, :show]
resources :projects, only: [:index, :create, :show] do resources :projects, only: [:index, :create, :show] do
resources :version_releases, only: [:index,:new, :create, :edit, :update, :destroy]
resources :project_trends, only: [:index, :create]
resources :issues do resources :issues do
collection do collection do
get :commit_issues get :commit_issues

@ -0,0 +1,12 @@
class CreateProjectTrends < ActiveRecord::Migration[5.2]
def change
create_table :project_trends do |t|
t.integer :user_id
t.integer :project_id
t.references :trend, polymorphic: true, index: true
t.string :action_type
t.timestamps
end
add_index :project_trends, [:user_id, :project_id]
end
end

@ -0,0 +1,18 @@
class CreateVersionReleases < ActiveRecord::Migration[5.2]
def change
create_table :version_releases do |t|
t.integer :user_id
t.string :name
t.text :body
t.string :tag_name
t.string :target_commitish
t.boolean :draft, default: false
t.boolean :prerelease, default: false
t.string :tarball_url
t.string :zipball_url
t.string :url
t.string :version_gid
t.timestamps
end
end
end

@ -0,0 +1,6 @@
class AddProjectIdToVersionRelease < ActiveRecord::Migration[5.2]
def change
add_column :version_releases, :repository_id, :integer
add_index :version_releases, [:repository_id]
end
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe VersionReleasesController, type: :controller do
end

@ -0,0 +1,15 @@
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the VersionReleasesHelper. For example:
#
# describe VersionReleasesHelper 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 VersionReleasesHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ProjectTrend, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe VersionRelease, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save