Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

自動テストの追加 #9

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9ff02c9
branches, entries のテストを追加
HiroyasuTawara Oct 6, 2023
efec548
entriesメソッドのテストを修正
HiroyasuTawara Oct 10, 2023
0334970
gitjib_adapterの各メソッドの概要説明コメントを追加
HiroyasuTawara Oct 10, 2023
c440d8d
テストを追加・修正, メソッド概要コメントを修正
HiroyasuTawara Oct 10, 2023
c4ff60b
テストを追加・修正,メソッド概要コメントの内容を拡充
HiroyasuTawara Oct 11, 2023
6104ed9
テストを追加
HiroyasuTawara Oct 12, 2023
faa0eca
stubに引数のassertionを追加
HiroyasuTawara Oct 13, 2023
e47c439
githubモデルのメソッド概要コメントを追加,およびテストファイルを作成
HiroyasuTawara Oct 13, 2023
81f5649
githubモデルにテストを追加
HiroyasuTawara Oct 13, 2023
9119cdd
githubモデルのテスト・fixtureを追加
HiroyasuTawara Oct 17, 2023
87516fe
Merge branch 'main' of github.com:NaCl-Ltd/redmine_github_adapter int…
HiroyasuTawara Oct 17, 2023
04a6e88
テストの追加・コメントを含め一部修正
HiroyasuTawara Oct 17, 2023
e300a0f
revisionsメソッドのテストを修正
HiroyasuTawara Oct 17, 2023
e426d52
revisionsメソッドのテストを修正
HiroyasuTawara Oct 18, 2023
2c8309b
github_test.rb の自動テストの修正・他
xketanaka Oct 21, 2023
a2e250e
自動テストの修正
xketanaka Oct 23, 2023
e0b2d25
自動テストの追加 (#22)
xketanaka Oct 23, 2023
004a15d
github actions を自動生成しないようにディレクトリ名をリネーム
xketanaka Oct 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions app/models/repository/github.rb
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ def branches
scm.branches
end

# リモートリポジトリの最新状況を取得し、changesetsに反映する
def fetch_changesets(options = {})
opts = options.merge({
last_committed_date: extra_info&.send(:[], "last_committed_date"),
@@ -56,6 +57,8 @@ def fetch_changesets(options = {})
save(validate: false)
end

# revisionオブジェクトの配列を引数に受け取る
# changesetsテーブルに保存する(すでに保存済みのrevisionはスキップ)
def save_revisions!(revisions, revisions_copy)
limit = 100
offset = 0
@@ -96,13 +99,18 @@ def save_revisions!(revisions, revisions_copy)
end
private :save_revisions!

# nameにコミットのSHA1ハッシュを受け取る
# nameにリビジョン名が一致する、もしくはscmidに先頭一致するchangeset一件を返す
def find_changeset_by_name(name)
if name.present?
changesets.find_by(revision: name.to_s) ||
changesets.where('scmid LIKE ?', "#{name}%").first
end
end

# pathにファイルパス、identifierにコミットのshaを受け取る
# scmから引数に該当するエントリを取得し配列で返す
# pathが空(ルート)でidentifierがdefault_branchの場合は、ファイルセットの参照時キャッシュを使用する
def scm_entries(path=nil, identifier=nil)
is_using_cache = using_root_fileset_cache?(path, identifier)

@@ -120,9 +128,9 @@ def scm_entries(path=nil, identifier=nil)
path: fileset.path,
kind: fileset.size.blank? ? 'dir': 'file',
size: fileset.size,
author: latest_changeset.committer,
lastrev: Redmine::Scm::Adapters::Revision.new(
identifier: latest_changeset.identifier,
author: latest_changeset.committer,
time: latest_changeset.committed_on
),
)
@@ -132,7 +140,6 @@ def scm_entries(path=nil, identifier=nil)
# Not found in cache, get entries from SCM
if entries.blank?
entries = scm.entries(path, identifier, :report_last_commit => report_last_commit)

# Save as cache
if changeset.present?
GithubAdapterRootFileset.where(repository_id: self.id, revision: identifier).delete_all
@@ -152,6 +159,9 @@ def scm_entries(path=nil, identifier=nil)
entries
end

# pathにファイルパス、revにコミットのshaもしくはブランチ名を受け取る
# rev時点のpath以下のファイルに該当するchengesetsを取得し配列で返す
# revがデフォルトブランチ以外の場合、未反映のrevisionを保存しchangesetsテーブルに保存する
def latest_changesets(path, rev, limit = 10)
revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)

@@ -165,6 +175,8 @@ def latest_changesets(path, rev, limit = 10)
changesets.where(:scmid => revisions.map {|c| c.scmid}).to_a
end

# このリポジトリが削除された場合のクリーンアップ処理
# 紐づくGithubAdapterRootFilesetを削除する
def clear_changesets
super
GithubAdapterRootFileset.where(repository_id: self.id).delete_all
@@ -177,6 +189,8 @@ def default_branch
def properties(path, rev)
end

# scm_entries内でキャッシュを使用するかどうかの判定
# pathがルートで、identifierがデフォルトブランチ(またはデフォルトブランチのSHA1ハッシュ)の場合、true を返す
def using_root_fileset_cache?(path, identifier)
return false if path.present?
return false if identifier.blank?
35 changes: 35 additions & 0 deletions dot.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Run plugin Test

on: push

jobs:
test:
runs-on: ubuntu-latest
container:
image: redmine:4.2.10-bullseye
env:
RAILS_ENV: test
steps:
- name: Setup Env
run: |
ln -s /usr/src/redmine ./redmine
git config --global --add safe.directory /usr/src/redmine/plugins/redmine_github_adapter
- uses: actions/checkout@v3
with:
path: ./redmine/plugins/redmine_github_adapter
- name: Run tests
run: |
cd redmine
/docker-entrypoint.sh rails s --help
bundle config unset without --local
bundle install
bundle exec rake redmine:plugins:migrate
bundle exec rake redmine:plugins:test RAILS_ENV=test

38 changes: 33 additions & 5 deletions lib/redmine/scm/adapters/github_adapter.rb
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@ def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
end
end

# レシーバに紐づくGithubBranchオブジェクトを配列にし、ブランチ名でソートして返す
# 対象となるGithubBranchオブジェクトが存在しない場合、空の配列を返す
def branches
return @branches if @branches
@branches = []
@@ -41,6 +43,11 @@ def branches
raise CommandFailed, handle_octokit_error(e)
end

# pathにファイル・ディレクトリのパス, identifierにコミットのSHAを受け取る
# identifierに該当するコミットの、path以下に含まれる各ファイルのエントリを配列にして返す
# pathが空の場合rootディレクトリを、identifierが空の場合HEADコミットを対象とする
# 対象となるファイルが存在しない場合、空の配列を返す
# report_last_commitオプションにtrueが与えられた場合、各エントリにファイルの最新コミット情報を含める
def entries(path=nil, identifier=nil, options={})
identifier = 'HEAD' if identifier.nil?

@@ -67,12 +74,17 @@ def entries(path=nil, identifier=nil, options={})
raise CommandFailed, handle_octokit_error(e)
end

# revにコミットのSHAもしくはブランチ名を受け取る
# 引数に該当するコミットをすべて取得し、その中で最新コミットのSHAを返す
def revision_to_sha(rev)
Octokit.commits(@repos, rev, { per_page: 1 }).map(&:sha).first
rescue Octokit::Error => e
raise CommandFailed, handle_octokit_error(e)
end

# pathにファイル・ディレクトリのパス、revにコミットのSHAもしくはブランチ名を受け取る
# revに該当するコミット以前でpath以下に変更があった最新のコミットを取得し、Revisionオブジェクトとして返す
# 引数pathが与えられなかった場合、もしくは該当するコミットが存在しない場合nilを返す
def lastrev(path, rev)
return if path.nil?

@@ -92,16 +104,20 @@ def lastrev(path, rev)
raise CommandFailed, handle_octokit_error(e)
end

# pathにtreeオブジェクトのshaを受け取る
# treeの最上位に位置するファイル・ディレクトリ名を返す
def get_path_name(path)

Octokit.commits(@repos).map {|c|
Octokit.tree(@repos, c.commit.tree.sha).tree.map{|b| [b.sha, b.path] }
}.flatten.each_slice(2).to_h[path]

rescue Octokit::Error => e
raise CommandFailed, handle_octokit_error(e)
end

# pathにファイル・ディレクトリのパス, identifier_from/identifier_toにコミットのshaを受け取る
# 引数で与えられた条件に合致するコミットをRevisionオブジェクトの配列として返す
# allオプションがtrueの場合、リポジトリの全てのrevisionを取得する
# 配列はコミット日時の降順でソートされる
def revisions(path, identifier_from, identifier_to, options={})
path ||= ''
revs = Revisions.new
@@ -116,7 +132,6 @@ def revisions(path, identifier_from, identifier_to, options={})
0.step do |i|
start_page = i * MAX_PAGES + 1
github_commits = Octokit.commits(@repos, api_opts.merge(page: start_page))

# if fetched latest commit, github_commits.length is 1, and github_commits[0][:sha] == latest_committed_id
return [] if i == 0 && github_commits.none?{ |commit| commit.sha != options[:last_committed_id] }

@@ -165,6 +180,8 @@ def revisions(path, identifier_from, identifier_to, options={})
raise CommandFailed, handle_octokit_error(e)
end

# 複数のrevisionオブジェクトを配列として受け取り、該当コミットの変更状況をhashにする
# 作成したhashを各revisionオブジェクトのpathsパラメータに追記する
def get_filechanges_and_append_to(revisions)
revisions.each do |revision|
commit_diff = Octokit.commit(@repos, revision.identifier)
@@ -191,6 +208,9 @@ def get_filechanges_and_append_to(revisions)
raise CommandFailed, handle_octokit_error(e)
end

# pathにファイルのパス, identifier_from/identifier_toにコミットのSHAを受け取る
# pathで指定されたファイル内容について、identifier~で指定されたコミット間の差分箇所を特定する
# 特定した差分箇所に追記を行い、文字列の配列として返す
def diff(path, identifier_from, identifier_to=nil)
path ||= ''
diff = []
@@ -245,6 +265,8 @@ def annotate(path, identifier=nil)
nil
end

# デフォルトブランチ名を文字列にして返す
# ブランチが1つも無い場合nilを返す
def default_branch
return if branches.blank?

@@ -255,13 +277,17 @@ def default_branch
).to_s
end

# pathにファイル・ディレクトリのパス, identifierにコミットのSHAを受け取る
# identifierに該当するコミットの、pathに指定されたファイル・ディレクトリのエントリを返す
# identifierが空の場合、HEADコミットを対象にする
# pathが空の場合、トップレベルのエントリを返す
def entry(path=nil, identifier=nil)
identifier ||= 'HEAD'
if path.blank?
# Root entry
Entry.new(:path => '', :kind => 'dir')
else
es = entries(path, identifier, {report_last_commit: true })
es = entries(path, identifier, {report_last_commit: false })
content = es&.find {|e| e.name == path} || es&.first

Entry.new({
@@ -273,12 +299,15 @@ def entry(path=nil, identifier=nil)
end
end

# identifierにSHAが該当するコミットの、pathに指定されたファイルの内容を文字列で返す
# identifierが空の場合、HEADコミットを対象にする
def cat(path, identifier=nil)
identifier = 'HEAD' if identifier.nil?

begin
blob = Octokit.contents(@repos, path: path, ref: identifier)
url = blob.download_url

rescue Octokit::NotFound
commit = Octokit.commit(@repos, identifier).files.select{|c| c.filename == path }.first
blob = Octokit.blob(@repos, commit.sha)
@@ -287,7 +316,6 @@ def cat(path, identifier=nil)
Octokit.get(url)
content_type = Octokit.last_response.headers['content-type'].slice(/charset=.+$/)&.gsub("charset=", "")
return '' if content_type == "binary" || content_type.nil?

content = blob.encoding == "base64" ? Base64.decode64(blob.content) : blob.content
content.force_encoding 'utf-8'

10 changes: 10 additions & 0 deletions test/fixtures/changesets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
default:
id: 1
repository_id: 1
revision: 'shashasha'
committer: 'author_name'
committed_on: 2023-01-01
comments: 'message'
commit_date: 2023-01-01
scmid: 'shashasha'
user_id:
14 changes: 14 additions & 0 deletions test/fixtures/repositories.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
default:
id: 1
project_id: 1
url: 'https://github.com/farend/redmine_github_repo.git'
login: ''
password: ''
identifier: 'test_project'
type: 'Repository::Github'
path_encoding: nil
log_encoding: nil
is_default: true
extra_info:
'last_committed_date': ''
'last_committed_id': ''
17 changes: 17 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# Load the Redmine helper
require 'minitest/mock'
require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')

module Redmine
module PluginFixturesLoader
def self.included(base)
base.class_eval do
def self.plugin_fixtures(*symbols)
ActiveRecord::FixtureSet.create_fixtures(File.dirname(__FILE__) + '/fixtures/', symbols)
end
end
end
end
end

## ユニットテスト
unless ActiveSupport::TestCase.included_modules.include?(Redmine::PluginFixturesLoader)
ActiveSupport::TestCase.send :include, Redmine::PluginFixturesLoader
end
579 changes: 573 additions & 6 deletions test/unit/github_adapter_test.rb

Large diffs are not rendered by default.

471 changes: 471 additions & 0 deletions test/unit/github_test.rb

Large diffs are not rendered by default.