- Rake scripts : synchronize changesets history ( e.g. commit messages ) and reflect issue
references keyword
. - Patch on Redmine.org.
- この記事はRedmine Advent Calendar 2019 の9日目に登録したものです。
- Redmineとリポジトリ(e.g. subversion, git) を連携させて運用している。リポジトリ単体での利用と比較して内容の参照性が向上し、
Refs keyword
によるリビジョン<-->チケット
間のトレーサビリティを多人数で長期間にわたって共有できる点が特に有用である。 - コミットコメントを書き間違えることが良くある。コメント内容を修正して情報の正確さを維持し、
Refs keyword
のチケット番号指定を修正・追加してリビジョン<-->チケット
間のトレーサビリティーの正確さと網羅性 を維持したい。 - 情報の正確さと網羅性が低下した状態が長く続かないように、変更内容はできるだけ遅延無く反映させたい。
Redmineとリポジトリを連携させて運用しているが、コミットコメント等の変更と反映で少し困っている。
- コミットコメントを書き間違えた時、リポジトリ側を修正*1してもRedmineプロジェクトのリポジトリタブ側には反映されない。
- 修正内容を反映させるには、Redmineとリポジトリの連携を一度切断し、再び接続設定を行う必要がある。
- Redmineの画面上でチケットとリビジョンとを紐付けて、
Refs Keyword
を使った時と同じ様に見せる機能がある。しかし、Redmineとリポジトリの連携を切断・再接続
すると紐付けが消えてしまい、元に戻せなくなる。 切断・再接続
を繰り返す方法は、他にも問題がある*2。
- Redmineにコミットコメント等を同期する仕組みが無い。
- Redmineの画面上でチケットとリビジョンとを紐付けた情報はデータベースに保存されているが、
切断・再接続
と共に消去される。 - Redmineとリポジトリの連携機能は、
切断・再接続
を頻繁に繰り返す事を想定した設計ではない。
- コミットコメントへの変更をRedmine側にも反映したい。
Refs keyword
の修正・追記をチケットに反映したい。- 変更を遅延無く反映したい。
- 第三者検証(査察・監査・認証)の要求を満足させる。
(反映処理の仕様)
- 全てのActiveな
リポジトリ<-->Redmine
間連携において、コミットコメントの内容を比較し、差分だけを反映する。 - 差分を反映したら
Refs keyword
を再評価してリビジョン<-->チケット
間の参照を更新する。 - 上記2種をRakeスクリプトとして作成し、lib/tasks に配置してCron等のスケジューラーから定期的に実行する。
cd <redmine-home>/
rake redmine:changesets:reload
- 全てのアクセスログ、コミットコメントの変更ログを保持する。
- リポジトリのコミットコメント変更と
Refs keyword
への修正・追加が任意のタイミングでRedmine側へ反映できるようになった。 - 即時反映ではないものの、運用規模が大きい*2場合でも毎晩処理して翌朝までに反映できるようになった。規模が小さい場合は高頻度に実行できる。
- lib/tasks/changesets.rake
namespace :redmine do
namespace :changesets do
desc 'Sync all revisions in repositories related with all active project.'
task :reload => :environment do
Project.active.has_module(:repository).find_each do |project|
project.repositories.find_each do |repository|
detail = [
"PJ-ID #{repository.project_id}",
"Identifier #{repository.identifier}",
"URL #{repository.url}",
].join(", ")
changesets = repository.changesets
puts("Sync revisions: #{changesets.count}: #{detail}")
latest_changeset = changesets.first
changeset = latest_changeset
while changeset
revisions = repository.scm.revisions(nil,
changeset.identifier,
changeset.identifier)
revisions.each do |revision|
changeset.committer =
Changeset.to_utf8(revision.author,
repository.repo_log_encoding)
changeset.comments =
Changeset.normalize_comments(revision.message,
repository.repo_log_encoding)
changeset.user =
repository.find_committer_user(changeset.committer)
next unless changeset.changed?
changeset.issues = []
changeset.scan_for_issues
if changeset.save
puts("Sync revision: #{changeset.identifier}, #{detail}")
else
puts("Failed to sync revision: " +
"#{changeset.identifier}, #{detail}: " +
"#{changeset.errors}")
end
end
changeset = changeset.previous
end
end
end
end
end
end
- このスクリプトは株式会社クリアコードと株式会社島津製作所の共同開発による Redmine全文検索システムの開発とOSS化 の派生成果である。
- スクリプトの作成にあたって株式会社クリアコードの須藤功平さんから多くの助言を頂いた。
[*1]: Subversionリポジトリでは、コミットコメントを変更できない設定になっている場合がある。
- Subversion管理者に
pre-revprop-change
フックを作成してもらうことで、Subversionクライアントからコミットコメントを編集できるようになる。(e.g. TortoiseSVN, svnクライアントコマンド)
[*2]: その他
- 運用規模が大きい場合。Redmineと連携させているリポジトリのコミット数の合計が数百万を越える規模で切断/再接続を頻繁に繰り返すと、データベースのテーブルの自動採番IDが上限値(約21億件)に到達してしまい、Redmineとリポジトリ連携の通常の同期ができなくなる。これは、Railsの自動Primary-keyと、MySQLのint(11)-AUTO_INCREMENT や PostgreSQLの
serial
自動増分整数型 の仕様に起因している。対策はあるが面倒。 - Redmine全文検索システム導入時に問題となる。Redmineとリポジトリの連携を
切断・再接続
する度に、リポジトリ内容を全文検索するための索引を一旦破棄して、再生成することになる。生成が完了するまでは検索結果が部分的になってしまうので、検索対象のデータ量が大きい場合に問題となる。