Redmineちゃんのバージョンアップ

ハピハピハッピー

というわけでRedmine0.8.7を導入してから1年ちょっと経過したのですが、
バージョンアップをほったらかし過ぎるのもあれなので、
Redmine1.1.1にバージョンアップをしてみますた。

今までの導入期はid:amidaike:20091116からご覧くだせぇ。


で、なぜバージョンアップをしたかったかというと、
去年のFxUG名古屋でRedmineAirを作ろうというLTを聞いて、
おぉすげぇなと思いながらその後は特にWatchしていなかったのですが、
久しぶりにr-labsのページを見ると、
RedmineAirhttp://www.r-labs.org/projects/redmineair/wiki/Wiki
とあるじゃないですか。
で、RedmineAirを使うためにはREST APIを使う必要があり、
Redmineのバージョンが1.0以上じゃないと
REST APIが使えなかっためバージョンアップをしたというわけです。

では早速バージョンアップをしていきまっせ。

今回はサーバ環境などは前回と全く同じで、
Redmineのみバージョンアップとします。

以下は全てrootユーザで実行しましょう。

RedmineのサイトよりRedmine本体をダウンロード
http://rubyforge.org/frs/?group_id=1850
redmine-1.1.1.zipをダウンロードし、
前回インストールしたディレクトリ(/usr/local)に保存をします。


で、Redmine 1.0.5以降、Rubyの国際化ライブラリi18nのバージョン0.4.2が実行時に必要らしいので、
インストールされているかチェックしてみましょう。

# gem list
 *** LOCAL GEMS ***

abstract (1.0.0)
actionmailer (3.0.0, 2.3.5)
actionpack (3.0.0, 2.3.5)
activemodel (3.0.0)
activerecord (3.0.0, 2.3.5)
activeresource (3.0.0, 2.3.5)
activesupport (3.0.0, 2.3.5)
arel (1.0.1)
builder (2.1.2)
erubis (2.6.6)
fastthread (1.0.7)
i18n (0.4.2)
mail (2.2.10)
mime-types (1.16)
mysql (2.8.1)
passenger (2.2.7)
polyglot (0.3.1)
rack (1.2.1, 1.0.1)
rack-mount (0.6.13)
rack-test (0.5.6)
rails (2.3.5)
rake (0.8.7)
rmagick (2.12.2)
treetop (1.4.9)
tzinfo (0.3.23)

既にインストールされていましたね。
もし、バージョンが異なったりインストールされていなければ、

# gem uninstall i18n --all ← これはバージョン異なるものがインストールされてる時のみ実行
# gem install i18n -v=0.4.2

とインストールしましょう。

  • 既存データをバックアップ

既に運用中のため、念のためにバックアップは取っておきませう。
ここからはhttp://redmine.jp/guide/RedmineUpgrade/を参考にするお。

filesディレクトリのバックアップ

/usr/local/redmin/files
にあるファイルをバックアップしてみましょう。

# cp -pr /usr/local/redmin/files ~/redminebk ← ホームディレクトリにredminebkを作っておいてね。
MySQLのバックアップ

これはそのままコマンドをパクリましょう。

# mysqldump -u  -p  | gzip > ~/redminebk/redmine_`date +%y_%m_%d`.gz
既存ディレクトリの名称を変更

/usr/local/redmineと運用中のディレクトリ名を
redmineold0.8.7と変えちゃいましょう。

# cd /usr/local
# mv redmine ./redmineold0.8.7
新しいRedmineの設定

先ほどダウンロードしたRedmineを解凍して設定していきませう。

# unzip unzip redmine-1.1.1.zip
# mv redmine-1.1.1 redmine


既存のデータベース設定ファイルとメール設定ファイルを新しいRedmineディレクトリにコピーどす。

# cp -pr ./redmineold0.8.7/config/database.yml ./redmine/config/
# cp -pr ./redmineold0.8.7/config/email.yml ./redmine/config/


アップロード用のfilesディレクトリを新しいRedmineにコピーどす。

# cp -pr ./redmineold0.8.7/files/* ./redmine/files/


プラグインを新しいRedmineにコピーどす。
これは各自がプラグインをインストールしたなら対象のもののみコピーしてくだちい。
例えばこんな感じ。

# ./redmineold0.8.7/vendor/plugins/hogehoge ./redmine/vendor/plugins


以上が終われば新しいRedmineのインストールディレクトリで以下を実行しましょう。

# cd redmine
# rake generate_session_store

(in /usr/local/redmine)

このコマンドは、セッションデータを安全に扱うための秘密鍵が含まれる
config/initializers/session_store.rb ファイルを生成するんだってさ。何だそりゃ。


もしテーマファイルを作ってる方はテーマファイルも新しいRedmineディレクトリにコピーが必要ですが、
使ってないので割愛します。


データベースの更新

データベースも当然変わっている箇所があるため、以下のコマンドでデータベースの
マイグレーションを行いませう。
新しいRedmineのインストールディレクトリで実行すること。

# rake generate_session_store

(in /usr/local/redmine)
==  AddCustomFieldsEditable: migrating ========================================
    • add_column(:custom_fields, :editable, :boolean, {:default=>true})
-> 0.0776s == AddCustomFieldsEditable: migrated (0.0781s) =============================== == SetCustomFieldsEditable: migrating ======================================== == SetCustomFieldsEditable: migrated (0.0055s) =============================== == AddProjectsLftAndRgt: migrating ===========================================
    • add_column(:projects, :lft, :integer)
-> 0.0441s
    • add_column(:projects, :rgt, :integer)
-> 0.0496s == AddProjectsLftAndRgt: migrated (0.0946s) ================================== == BuildProjectsTree: migrating ============================================== == BuildProjectsTree: migrated (0.0248s) ===================================== == RemoveProjectsProjectsCount: migrating ====================================
    • remove_column(:projects, :projects_count)
-> 0.0120s == RemoveProjectsProjectsCount: migrated (0.0124s) =========================== == AddOpenIdAuthenticationTables: migrating ==================================
    • create_table(:open_id_authentication_associations, {:force=>true})
-> 0.0372s
    • create_table(:open_id_authentication_nonces, {:force=>true})
-> 0.0086s == AddOpenIdAuthenticationTables: migrated (0.0467s) ========================= == AddIdentityUrlToUsers: migrating ==========================================
    • add_column(:users, :identity_url, :string)
-> 0.0475s == AddIdentityUrlToUsers: migrated (0.0481s) ================================= == AddWatchersUserIdTypeIndex: migrating =====================================
    • add_index(:watchers, [:user_id, :watchable_type], {:name=>:watchers_user_id_type})
-> 0.0390s == AddWatchersUserIdTypeIndex: migrated (0.0395s) ============================ == AddQueriesSortCriteria: migrating =========================================
    • add_column(:queries, :sort_criteria, :text)
-> 0.0105s == AddQueriesSortCriteria: migrated (0.0109s) ================================ == AddProjectsTrackersUniqueIndex: migrating =================================
    • add_index(:projects_trackers, [:project_id, :tracker_id], {:unique=>true, :name=>:projects_trackers_unique})
-> 0.0440s == AddProjectsTrackersUniqueIndex: migrated (0.0524s) ======================== == ExtendSettingsName: migrating =============================================
    • change_column(:settings, :name, :string, {:null=>false, :limit=>255, :default=>""})
-> 0.0127s == ExtendSettingsName: migrated (0.0132s) ==================================== == AddTypeToEnumerations: migrating ==========================================
    • add_column(:enumerations, :type, :string)
-> 0.0880s == AddTypeToEnumerations: migrated (0.0885s) ================================= == UpdateEnumerationsToSti: migrating ======================================== == UpdateEnumerationsToSti: migrated (0.0145s) =============================== == AddActiveFieldToEnumerations: migrating ===================================
    • add_column(:enumerations, :active, :boolean, {:null=>false, :default=>true})
-> 0.0112s == AddActiveFieldToEnumerations: migrated (0.0117s) ========================== == AddProjectToEnumerations: migrating =======================================
    • add_column(:enumerations, :project_id, :integer, {:null=>true, :default=>nil})
-> 0.0345s
    • add_index(:enumerations, :project_id)
-> 0.0504s == AddProjectToEnumerations: migrated (0.0858s) ============================== == AddParentIdToEnumerations: migrating ======================================
    • add_column(:enumerations, :parent_id, :integer, {:null=>true, :default=>nil})
-> 0.0517s == AddParentIdToEnumerations: migrated (0.0521s) ============================= == AddQueriesGroupBy: migrating ==============================================
    • add_column(:queries, :group_by, :string)
-> 0.0113s == AddQueriesGroupBy: migrated (0.0117s) ===================================== == CreateMemberRoles: migrating ==============================================
    • create_table(:member_roles)
-> 0.0080s == CreateMemberRoles: migrated (0.0085s) ===================================== == PopulateMemberRoles: migrating ============================================ == PopulateMemberRoles: migrated (0.0853s) =================================== == DropMembersRoleId: migrating ==============================================
    • remove_column(:members, :role_id)
-> 0.0108s == DropMembersRoleId: migrated (0.0113s) ===================================== == FixMessagesStickyNull: migrating ========================================== == FixMessagesStickyNull: migrated (0.0008s) ================================= == PopulateUsersType: migrating ============================================== == PopulateUsersType: migrated (0.0015s) ===================================== == CreateGroupsUsers: migrating ==============================================
    • create_table(:groups_users, {:id=>false})
-> 0.0367s
    • add_index(:groups_users, [:group_id, :user_id], {:name=>:groups_users_ids, :unique=>true})
-> 0.0361s == CreateGroupsUsers: migrated (0.0737s) ===================================== == AddMemberRolesInheritedFrom: migrating ====================================
    • add_column(:member_roles, :inherited_from, :integer)
-> 0.0101s == AddMemberRolesInheritedFrom: migrated (0.0105s) =========================== == FixUsersCustomValues: migrating =========================================== == FixUsersCustomValues: migrated (0.0039s) ================================== == AddMissingIndexesToWorkflows: migrating ===================================
    • add_index(:workflows, :old_status_id)
-> 0.0786s
    • add_index(:workflows, :role_id)
-> 0.0498s
    • add_index(:workflows, :new_status_id)
-> 0.0659s == AddMissingIndexesToWorkflows: migrated (0.1956s) ========================== == AddMissingIndexesToCustomFieldsProjects: migrating ========================
    • add_index(:custom_fields_projects, [:custom_field_id, :project_id])
-> 0.0117s == AddMissingIndexesToCustomFieldsProjects: migrated (0.0122s) =============== == AddMissingIndexesToMessages: migrating ====================================
    • add_index(:messages, :last_reply_id)
-> 0.0767s
    • add_index(:messages, :author_id)
-> 0.0249s == AddMissingIndexesToMessages: migrated (0.1024s) =========================== == AddMissingIndexesToRepositories: migrating ================================
    • add_index(:repositories, :project_id)
-> 0.0549s == AddMissingIndexesToRepositories: migrated (0.0552s) ======================= == AddMissingIndexesToComments: migrating ====================================
    • add_index(:comments, [:commented_id, :commented_type])
-> 0.0228s
    • add_index(:comments, :author_id)
-> 0.0248s == AddMissingIndexesToComments: migrated (0.0480s) =========================== == AddMissingIndexesToEnumerations: migrating ================================
    • add_index(:enumerations, [:id, :type])
-> 0.0540s == AddMissingIndexesToEnumerations: migrated (0.0542s) ======================= == AddMissingIndexesToWikiPages: migrating =================================== -> 0.0132s
    • add_index(:wiki_pages, :parent_id)
-> 0.0193s == AddMissingIndexesToWikiPages: migrated (0.0330s) ========================== == AddMissingIndexesToWatchers: migrating ====================================
    • add_index(:watchers, :user_id)
-> 0.0560s
    • add_index(:watchers, [:watchable_id, :watchable_type])
-> 0.0314s == AddMissingIndexesToWatchers: migrated (0.0878s) =========================== == AddMissingIndexesToAuthSources: migrating =================================
    • add_index(:auth_sources, [:id, :type])
-> 0.0120s == AddMissingIndexesToAuthSources: migrated (0.0123s) ======================== == AddMissingIndexesToDocuments: migrating ===================================
    • add_index(:documents, :category_id)
-> 0.0685s == AddMissingIndexesToDocuments: migrated (0.0688s) ========================== == AddMissingIndexesToTokens: migrating ======================================
    • add_index(:tokens, :user_id)
-> 0.0276s == AddMissingIndexesToTokens: migrated (0.0278s) ============================= == AddMissingIndexesToChangesets: migrating ==================================
    • add_index(:changesets, :user_id)
-> 0.0130s
    • add_index(:changesets, :repository_id)
-> 0.0703s == AddMissingIndexesToChangesets: migrated (0.0838s) ========================= == AddMissingIndexesToIssueCategories: migrating =============================
    • add_index(:issue_categories, :assigned_to_id)
-> 0.0307s == AddMissingIndexesToIssueCategories: migrated (0.0309s) ==================== == AddMissingIndexesToMemberRoles: migrating =================================
    • add_index(:member_roles, :member_id)
-> 0.0322s
    • add_index(:member_roles, :role_id)
-> 0.0743s == AddMissingIndexesToMemberRoles: migrated (0.1070s) ======================== == AddMissingIndexesToBoards: migrating ======================================
    • add_index(:boards, :last_message_id)
-> 0.0282s == AddMissingIndexesToBoards: migrated (0.0284s) ============================= == AddMissingIndexesToUserPreferences: migrating =============================
    • add_index(:user_preferences, :user_id)
-> 0.0341s == AddMissingIndexesToUserPreferences: migrated (0.0344s) ==================== == AddMissingIndexesToIssues: migrating ======================================
    • add_index(:issues, :status_id)
-> 0.0134s
    • add_index(:issues, :category_id)
-> 0.0621s
    • add_index(:issues, :assigned_to_id)
-> 0.0415s
    • add_index(:issues, :fixed_version_id)
-> 0.0658s
    • add_index(:issues, :tracker_id)
-> 0.0347s
    • add_index(:issues, :priority_id)
-> 0.0586s
    • add_index(:issues, :author_id)
-> 0.0421s == AddMissingIndexesToIssues: migrated (0.3197s) ============================= == AddMissingIndexesToMembers: migrating =====================================
    • add_index(:members, :user_id)
-> 0.0619s
    • add_index(:members, :project_id)
-> 0.0346s == AddMissingIndexesToMembers: migrated (0.0970s) ============================ == AddMissingIndexesToCustomFields: migrating ================================
    • add_index(:custom_fields, [:id, :type])
-> 0.0533s == AddMissingIndexesToCustomFields: migrated (0.0536s) ======================= == AddMissingIndexesToQueries: migrating =====================================
    • add_index(:queries, :project_id)
-> 0.0538s
    • add_index(:queries, :user_id)
-> 0.0436s == AddMissingIndexesToQueries: migrated (0.0978s) ============================ == AddMissingIndexesToTimeEntries: migrating =================================
    • add_index(:time_entries, :activity_id)
-> 0.0409s
    • add_index(:time_entries, :user_id)
-> 0.0490s == AddMissingIndexesToTimeEntries: migrated (0.0904s) ======================== == AddMissingIndexesToNews: migrating ========================================
    • add_index(:news, :author_id)
-> 0.0371s == AddMissingIndexesToNews: migrated (0.0374s) =============================== == AddMissingIndexesToUsers: migrating =======================================
    • add_index(:users, [:id, :type])
-> 0.0308s
    • add_index(:users, :auth_source_id)
-> 0.0832s == AddMissingIndexesToUsers: migrated (0.1145s) ============================== == AddMissingIndexesToAttachments: migrating =================================
    • add_index(:attachments, [:container_id, :container_type])
-> 0.0393s
    • add_index(:attachments, :author_id)
-> 0.0132s == AddMissingIndexesToAttachments: migrated (0.0531s) ======================== == AddMissingIndexesToWikiContents: migrating ================================
    • add_index(:wiki_contents, :author_id)
-> 0.0132s == AddMissingIndexesToWikiContents: migrated (0.0134s) ======================= == AddMissingIndexesToCustomValues: migrating ================================
    • add_index(:custom_values, :custom_field_id)
-> 0.0668s == AddMissingIndexesToCustomValues: migrated (0.0670s) ======================= == AddMissingIndexesToJournals: migrating ====================================
    • add_index(:journals, :user_id)
-> 0.0349s
    • add_index(:journals, :journalized_id)
-> 0.0497s == AddMissingIndexesToJournals: migrated (0.0851s) =========================== == AddMissingIndexesToIssueRelations: migrating ==============================
    • add_index(:issue_relations, :issue_from_id)
-> 0.0112s
    • add_index(:issue_relations, :issue_to_id)
-> 0.0271s == AddMissingIndexesToIssueRelations: migrated (0.0388s) ===================== == AddMissingIndexesToWikiRedirects: migrating =============================== -> 0.0475s == AddMissingIndexesToWikiRedirects: migrated (0.0477s) ====================== == AddMissingIndexesToCustomFieldsTrackers: migrating ========================
    • add_index(:custom_fields_trackers, [:custom_field_id, :tracker_id])
-> 0.0117s == AddMissingIndexesToCustomFieldsTrackers: migrated (0.0119s) =============== == AddActivityIndexes: migrating =============================================
    • add_index(:journals, :created_on)
-> 0.0254s
    • add_index(:changesets, :committed_on)
-> 0.0743s
    • add_index(:wiki_content_versions, :updated_on)
-> 0.0129s
    • add_index(:messages, :created_on)
-> 0.0305s
    • add_index(:issues, :created_on)
-> 0.0596s
    • add_index(:news, :created_on)
-> 0.0403s
    • add_index(:attachments, :created_on)
-> 0.0338s
    • add_index(:documents, :created_on)
-> 0.0744s
    • add_index(:time_entries, :created_on)
-> 0.0338s == AddActivityIndexes: migrated (0.3871s) ==================================== == AddVersionsStatus: migrating ==============================================
    • add_column(:versions, :status, :string, {:default=>"open"})
-> 0.0300s == AddVersionsStatus: migrated (0.0312s) ===================================== == AddViewIssuesPermission: migrating ======================================== == AddViewIssuesPermission: migrated (0.0667s) =============================== == AddDefaultDoneRatioToIssueStatus: migrating ===============================
    • add_column(:issue_statuses, :default_done_ratio, :integer)
-> 0.0112s == AddDefaultDoneRatioToIssueStatus: migrated (0.0114s) ====================== == AddVersionsSharing: migrating =============================================
    • add_column(:versions, :sharing, :string, {:null=>false, :default=>"none"})
-> 0.0216s
    • add_index(:versions, :sharing)
-> 0.0582s == AddVersionsSharing: migrated (0.0803s) ==================================== == AddLftAndRgtIndexesToProjects: migrating ==================================
    • add_index(:projects, :lft)
-> 0.0123s
    • add_index(:projects, :rgt)
-> 0.0355s == AddLftAndRgtIndexesToProjects: migrated (0.0482s) ========================= == AddIndexToSettingsName: migrating =========================================
    • add_index(:settings, :name)
-> 0.0636s == AddIndexToSettingsName: migrated (0.0638s) ================================ == AddIndexesToIssueStatus: migrating ========================================
    • add_index(:issue_statuses, :position)
-> 0.0370s
    • add_index(:issue_statuses, :is_closed)
-> 0.0137s
    • add_index(:issue_statuses, :is_default)
-> 0.0634s == AddIndexesToIssueStatus: migrated (0.1148s) =============================== == RemoveEnumerationsOpt: migrating ==========================================
    • remove_column(:enumerations, :opt)
-> 0.0392s == RemoveEnumerationsOpt: migrated (0.0394s) ================================= == ChangeWikiContentsTextLimit: migrating ====================================
    • change_column(:wiki_contents, :text, :text, {:limit=>16777216})
-> 0.0301s
    • change_column(:wiki_content_versions, :data, :binary, {:limit=>16777216})
-> 0.0918s == ChangeWikiContentsTextLimit: migrated (0.1225s) =========================== == ChangeUsersMailNotificationToString: migrating ============================
    • rename_column(:users, :mail_notification, :mail_notification_bool)
-> 0.0069s
    • add_column(:users, :mail_notification, :string, {:null=>false, :default=>""})
-> 0.0240s
    • remove_column(:users, :mail_notification_bool)
-> 0.0832s == ChangeUsersMailNotificationToString: migrated (0.1231s) =================== == UpdateMailNotificationValues: migrating =================================== == UpdateMailNotificationValues: migrated (0.0000s) ========================== == AddIndexOnChangesetsScmid: migrating ======================================
    • add_index(:changesets, [:repository_id, :scmid], {:name=>:changesets_repos_scmid})
-> 0.0281s == AddIndexOnChangesetsScmid: migrated (0.0283s) ============================= == AddIssuesNestedSetsColumns: migrating =====================================
    • add_column(:issues, :parent_id, :integer, {:default=>nil})
-> 0.0946s
    • add_column(:issues, :root_id, :integer, {:default=>nil})
-> 0.0691s
    • add_column(:issues, :lft, :integer, {:default=>nil})
-> 0.0852s
    • add_column(:issues, :rgt, :integer, {:default=>nil})
-> 0.0896s == AddIssuesNestedSetsColumns: migrated (0.3410s) ============================ == AddIndexOnIssuesNestedSet: migrating ======================================
    • add_index(:issues, [:root_id, :lft, :rgt])
-> 0.0398s == AddIndexOnIssuesNestedSet: migrated (0.0401s) ============================= == ChangeChangesPathLengthLimit: migrating ===================================
    • change_column(:changes, :path, :text, {:null=>true, :default=>nil})
-> 0.0788s
    • change_column(:changes, :path, :text, {:null=>false})
-> 0.0306s
    • change_column(:changes, :from_path, :text)
-> 0.0144s == ChangeChangesPathLengthLimit: migrated (0.1245s) ========================== == EnableCalendarAndGanttModulesWhereAppropriate: migrating ================== == EnableCalendarAndGanttModulesWhereAppropriate: migrated (0.0167s) ========= == AddUniqueIndexOnMembers: migrating ========================================
    • add_index(:members, [:user_id, :project_id], {:unique=>true})
-> 0.0557s == AddUniqueIndexOnMembers: migrated (0.0590s) =============================== == AddCustomFieldsVisible: migrating =========================================
    • add_column(:custom_fields, :visible, :boolean, {:null=>false, :default=>true})
-> 0.0138s == AddCustomFieldsVisible: migrated (0.0150s) ================================ == ChangeProjectsNameLimit: migrating ========================================
    • change_column(:projects, :name, :string, {:null=>false, :limit=>nil, :default=>""})
-> 0.0165s == ChangeProjectsNameLimit: migrated (0.0167s) =============================== == ChangeProjectsIdentifierLimit: migrating ==================================
    • change_column(:projects, :identifier, :string, {:limit=>nil})
-> 0.0763s == ChangeProjectsIdentifierLimit: migrated (0.0766s) =========================


と長々と実行されますた。で、プラグインもインストールしている方は以下のコマンドも実行してくだちい。

# rake db:migrate:upgrade_plugin_migrations RAILS_ENV=production
(実行ログは中略)
# rake db:migrate_plugins RAILS_ENV=production
(実行ログは中略)
クリーンナップ

ここまできたらもうあと一息。キャッシュとセッションファイルのクリアを行いませう。

# rake tmp:cache:clear
# rake tmp:sessions:clear

以上が終了すればアプリケーションサーバを再起動してみましょう。
ちなみにこちらではmongrel, thin, passengerとかは使用してませんので、
普通にApacheの再起動のみです。

それが終われば画面の「管理」→「情報」メニューより
Redmine 1.1.1.stable (MySQL)
と表示されていれば無事終了だす。

もしここで警告マークが出ている箇所があれば、パーミッション指定に問題があるので、
変更してあげましょう。
こちらでは、
・デフォルト管理アカウントが変更済
・Plugin assetsディレクトリに書き込み可能
が警告マークが発生したので、問題を解決しようと思ったけど分からんorz

とりあえず動作に支障はないからほっておきましょう。

以上でアップグレードはしゅーりょーー!!!

もっとてこずると思っていたんですけど意外と簡単でしたね。


てなわけで本来の目的であるRedmineAirを使ってみるかな。

追記
REST APIが有効にならない!!!と騒いでしまったけど、
[管理]→[設定]→[認証]

「RESTによるWebサービスを有効にする」
がありますたorz