mcpField
S
spree-upgrade-5-to-6

spree-upgrade-5-to-6

github.com/spree開発10102 回インストール4 週間前に更新
リポジトリ

spree-upgrade-5-to-6 について

Spree 5.x から 6.0 への移行手順をまとめた開発者向けガイドです。前提条件、移行とデータ補完、互換性を損なう変更、移行後の確認事項を扱います。

主な機能

  1. 01Spree 6.0 へのアップグレード前提
  2. 02順序に沿った移行とデータ補完
  3. 03破壊的変更の概要
  4. 04コード検索と修正の指針
  5. 05アップグレード後のデータ確認

活用シーン

  1. 01Spree 5.6 から 6.0 への移行計画
  2. 02Rails と拡張機能の依存関係の準備
  3. 03移行後の注文と顧客データの確認
  4. 04アプリ内の旧 API の特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/spree/agent-skills --skill spree-upgrade-5-to-6

インストール後、Claude Code で/spree-upgrade-5-to-6を入力して読み込まれたか確認します。

同梱ファイルreferences/grep-recipes.md

詳細

Spree 5.x から 6.0 へのアップグレード

Spree 6.0 は破壊的変更を含むリリースです。Cart と Order は別々のモデルになり、ステートマシンは廃止されました(ステータス+ワークフロー)。調整項目は型付きの行(TaxLine / Discount / Fee)になり、マスター商品バリエーションは廃止されました。配送はフルフィルメント/配達になり、タクソンはカテゴリー/コレクションになり、ユーザーは Spree::Customer になりました。スタッフの権限はデータになり、Rails 管理画面、Rails ストアフロント、API v2 は削除され、React ダッシュボード(spree_dashboard)と API v3 に置き換わりました。

アップグレードの手順は、前提条件 → gem → マイグレーション → バックフィル → コード修正 → 動作の確認です。最後の2つには十分な時間を確保してください。rake の作業は簡単な部分です。

一般的な仕組み(spree upgrade のフラグ、STEP=、本番環境のリリースフェーズ)については、spree-upgrade スキルを参照してください。このスキルは、6.0 固有の手順書です。

1. 前提条件 — Gemfile に手を加える前に実施してください

  • 5.6.x にアップグレードし、完全に更新してください。 6.0 のマニフェストは 5.6 のスキーマを前提としています。まず 5.6 にアップグレードしてください(spree upgrade --to 5.6 を実行するか、~> 5.6 に引き上げて bundle exec rake spree:upgrade を実行します)。6.0 の実行時にも 5.4→5.5 と 5.5→5.6 のバックフィルが再実行されますが、5.6 にアップグレードしておく必要がなくなるわけではありません。
  • Rails 8.1。 spree_core 6.0 には rails >= 8.1, < 8.2、Ruby ≥ 3.2 が必要です。可能であれば、Rails のアップグレード(および Rails 独自の非推奨機能への対応)は別のコミットで行ってください。
  • データベースをバックアップし、復元したコピーでリハーサルしてください。複数のバックフィルで金額、在庫、顧客のレコードが書き換えられるため、所要時間を計測してください。
  • Gemfile の入れ替え:
    • spree_admin と spree_storefront を削除します(廃止され、React ダッシュボードと Next.js ストアフロントに置き換えられました)。
    • spree_dashboard を追加します(/dashboard で管理画面を提供します)。API のみのデプロイでは追加しないでください。
    • Spree.search_provider が Meilisearch を参照している場合は、spree_meilisearch を追加します。
    • その他すべての spree_* 拡張機能(決済、i18n、独自のものなど)には 6.0 対応リリースが必要です。開始前に確認してください。確認しないと bundle update で依存関係を解決できません。spree_stripe、spree_easypost、spree_meilisearch は現在、Spree モノレポから同じバージョンでリリースされています。
  • Action Text / Action Cable。 spree_core はこれらを必要としなくなりました。独自のコードで has_rich_text、Action Text ヘルパー、または Action Cable を使用している場合は、config/application.rb に require 'action_text/engine' / require 'action_cable/engine' を追加してください。
  • 必要であれば、先にリッチテキストの許可リストを拡張してください。 説明やメモは、ダッシュボードのエディターが出力する形式(段落、見出し、インライン書式、コード、引用、リスト、リンク、画像)に再サニタイズされます。テーブル、div / span、インラインの style、任意のクラスは削除されます。これらが必要な場合は、migrate_rich_text_to_columns の実行前、および 6.0 で何かが保存される前に、イニシャライザーで Spree::RichTextSanitizer.allowed_tags += %w[…] / allowed_attributes += %w[…] を設定してください。
  • スタッフロールをデータとして再作成してください。 権限セットは移行処理なしで削除されます。既存のロールレコードには権限がありません。そのロールを持つスタッフはアクセスできなくなります(フェイルクローズ)。デプロイ前にシードしてください:
    store.roles.find_or_create_by!(name: 'support').update!(permissions: %w[read_orders read_customers])  # roles belong to a store
    
    キーはカタログにある read_<resource> / write_<resource> です(Spree::ApiKey.known_scopes で確認できます)。
  • PermissionSets のイニシャライザーを削除してください。 Spree::PermissionSets::* は NameError を発生させ、Spree.permissions.assign は起動時にエラーになります。拡張機能では Spree.permissions.register_scope(:reviews, group: :catalog, resources: -> { [SpreeReviews::Review] }) でリソースを登録してください。
  • 顧客の移行を確認してください(Devise アプリ)。 spree:upgrade:migrate_users_to_customers は spree_users を spree_customers にコピーし、Devise の encrypted_password を password_digest にマッピングします。これは Devise の pepper が設定されていない場合に限り動作します。Devise が読み込まれなくなると、CONFIRM_NO_PEPPER=true を渡すまで処理が中断されます。メールアドレスが空欄または重複しているレコードがある場合も中断されます(スキップするには SKIP_INVALID_ROWS=true を指定します)。pepper を使用している場合、SSO の場合、または bcrypt 以外を使用している場合は、代わりに独自の Spree.customer_class を引き続き使用してください。
  • ストアに移動したイニシャライザー設定(track_inventory_levels、auto_capture、company など)は、store_settings_backfill_from_config によってコピーされます。このステップが実行されるまでイニシャライザーに残し、実行後に削除してください。
  • Active Record の暗号化を有効にしてください。 Spree 6 では、キーが設定されている場合に限り、Webhook 署名シークレット、ゲートウェイの顧客 ID、OAuth ID トークンが暗号化されます。キーを読み込むように config/application.rb を設定してください(Application クラス内に記述します)。
    %i[primary_key deterministic_key key_derivation_salt].each do |key|
      value = ENV["ACTIVE_RECORD_ENCRYPTION_#{key.upcase}"].presence ||
        credentials.dig(:active_record_encryption, key).presence
      config.active_record.encryption[key] = value if value
    end
    
    キーが認証情報にしかなく、この設定がない場合、Webhook シークレットとゲートウェイの顧客 ID は平文のままです(それらの encrypts は config.active_record.encryption を確認します)。環境ごとに個別のキーセットを生成し(開発環境の .env には spree encryption init、本番環境には spree encryption init --print / bin/rails db:encryption:init)、デプロイ前にホストに設定してバックアップし、決して変更しないでください。暗号化を有効にすると、既存の平文の Webhook シークレットとゲートウェイの顧客 ID が読み取れなくなります。まず config.active_record.encryption.support_unencrypted_data = true と extend_queries = true を設定してデプロイし、[Spree::WebhookEndpoint, Spree::GatewayCustomer, Spree::UserIdentity].each { |m| m.find_each(&:encrypt) } を実行してから、両方の設定を削除してください。spree-security を参照してください。
  • settings で作成されたシークレット API キーでは、/admin_users、/invitations、/roles が使えなくなります。これらには read_staff / write_staff が必要になりました。スタッフを管理するインテグレーションキーを再作成してください。

2. アップグレードを実行する

# create-spree-app (ejected dev stack; Rails app in server/, older projects backend/)
spree upgrade
spree upgrade --plan              # after the gem bump: list every step

# classic Rails app / no CLI
bundle update
bundle exec rake spree:install:migrations && bin/rails db:migrate
DRY_RUN=1 bundle exec rake spree:upgrade
CONFIRM_NO_PEPPER=true bundle exec rake spree:upgrade

本番環境:デプロイで db:migrate を実行し、その後リリースフェーズで bundle exec rake spree:upgrade を実行します(該当する場合は、こちらでも CONFIRM_NO_PEPPER=true を渡してください)。メンテナンス時間を確保してください。バックフィルによって、処理中のチェックアウトはカートに変換されます。

3. 5.6 → 6.0 のマニフェストで実行される処理(順番)

spree_core/lib/spree/upgrades/5_6_to_6_0/manifest.yml を参照してください。すべて冪等です。spree upgrade --step <id> で個別の処理を再実行できます。

#ステップ ID内容
1consolidate_metadataセーフティネット:残っている public_metadata/private_metadata のペアを、単一の metadata カラムに統合します
2migrate_media_class_names保存されている Spree::Asset/Spree::Image のクラス名を Spree::Media に書き換えます
3migrate_master_images_to_product_mediaバリアントに固定された画像を商品ギャラリーに移動します(ジョブをエンキューするため、処理が完了するまで待ちます)
4backfill_media_store_idsすべてのメディア行に store_id を設定します
5remove_master_variantdefault_variant_id をバックフィルし、マスターバリアントを廃止します
6migrate_taxons_to_categories_and_collections自動タクソンを Spree::Collection に移行し、その他は Spree::Category のままにして、Spree::Taxon* 文字列を書き換えます
7backfill_library_media_placementsカテゴリー/コレクションの画像をメディアライブラリに追加します
8migrate_users_to_customersspree_users → spree_customers に移行し、user_type カラムの参照先を変更します(Devise pepper の前提条件を参照)
9migrate_rich_text_to_columnsAction Text の本文をサニタイズしてテキストカラムに移行します
10migrate_shipping_to_deliveryShipment の文字列/ステータスをフルフィルメントに、フルフィルメントプロバイダーを移行し、display_on を storefront_visible に変更します
11migrate_delivery_profiles配送カテゴリーをストア所有の配送プロファイルに移行します
12migrate_fulfillment_statusesunfulfilled/fulfilled/delivered に再マッピングします
13migrate_deliveries追跡番号を spree_deliveries の行に移行します
14migrate_zones_to_delivery_zones配送で参照されるゾーンを Spree::DeliveryZone に移行します
15migrate_country_state_codesISO の country_code/state_code カラムを埋めます(国/州は現在、参照データです)
16migrate_promotion_option_value_rulesオプション値のプロモーションルールを、安定したオプション値 ID に移行します
17migrate_adjustments_to_typed_rowsspree_adjustments を TaxLine/Discount/Fee に移行し、照合できない注文にフラグを設定します
18backfill_reason_store_ids返品/返金理由をストア所有にします
19migrate_returnsReturnAuthorization を Spree::Return/Spree::Exchange に移行します(失敗した行がある場合は中断します。SKIP_FAILED_ROWS=true)
20migrate_stock_movements_to_typed_rows在庫移動を型付きにし、未完了のフルフィルメントを再割り当てします(在庫は出荷時に減るようになりました)
21backfill_delivery_and_stock_store_ids配送方法と在庫ロケーションをストア所有にします
22migrate_tax_zones税率ゾーンを税率の国/州に移行します
23backfill_tax_store_ids税率/税カテゴリーをストア所有にします
24backfill_order_coupon_codes過去に確定した注文の新しい spree_orders.coupon_code を埋めます
25backfill_order_markets注文にデフォルトのマーケットを割り当てます
26migrate_incomplete_orders_to_carts未完了の注文を Spree::Cart に移行します(トークンは同じです)
27migrate_calculator_bounds_to_delivery_method_rulesFlatRate の最小/最大範囲を DeliveryMethodRule に移行します
28store_settings_backfill_from_config移動された Spree::Config 設定をすべてのストアにコピーします
29migrate_capture_methods支払い方法の auto_capture を capture_method に移行します
30product_types_backfill商品タイプをストア所有にします
31search_reindexインデックス検索プロバイダー(Meilisearch)を再構築します。DB プロバイダーでは何も行いません
32fold_store_credit_categoriesストアクレジットカテゴリーをメモに移行します
33migrate_stripe_webhook_keys(任意、spree_stripe のみ) Webhook シークレットをゲートウェイに移行します
34backfill_import_export_tenancyインポートに store_id(および seller_id)を設定します
35backfill_custom_field_definition_storesカスタムフィールド定義をストア所有にします
36package_typesストアのデフォルトボックスをパッケージタイプの行に移行します
37migrate_external_receives_to_purchase_orders5.x のサプライヤー受け取りを発注書に移行し、移送にストア/ステータスを設定します
38backfill_actor_types新しいアクターの *_type カラム(canceler、approver、created_by など)に管理者ユーザークラスを設定します。実行されるまでは、古い行の解決時に非推奨の警告が表示されます
39recount_stock_levelsreserved_count/incoming_count を埋めます
gem bump 後は、必ずこの表よりも spree upgrade --plan の結果を信頼してください。インストールする gem が正しい情報源です。
事後確認:凍結された注文

migrate_adjustments_to_typed_rows は金額を変更しません。型付き行の合計が保存済みの合計と一致しない注文は変更されず、metadata にフラグが付けられます(ガイドでは private_metadata と記載されていますが、現在のカラム名は metadata です)。それぞれ確認してください:

# spree console
Spree::Order.where.not(completed_at: nil).find_each.select { |o| o.metadata['typed_adjustments_frozen'].present? }
  .map { |o| [o.number, o.metadata['typed_adjustments_frozen']] }

理由には totals_do_not_reconcile や、返品承認による凍結(migrate_returns で処理)が含まれます。

4. コードを修正する — grep のレシピ

これらを server/app server/config server/lib server/spec(classic アプリでは app config lib spec)に加え、apps/storefront、apps/dashboard およびすべての連携コードに対して実行してください。パターンから置き換え先までを網羅した表は、references/grep-recipes.md にあります。起動やチェックアウトを妨げる箇所を優先してください:

cd server   # or the app root
grep -rnE "checkout_flow|go_to_state|insert_checkout_step|remove_checkout_step|state_machine|before_transition|after_transition" app config lib
grep -rnE "PermittedAttributes|permitted_[[:alnum:]_]+_attributes" app config lib
grep -rnE "PermissionSets|permissions\.assign|ApiKey::SCOPES" app config lib
grep -rnE "Spree::Adjustment|\.adjustments\b|promo_total|ship_total|item_count" app config lib
grep -rnE "\.master\b|is_master|default_price|DefaultPrice|variant\.price\b|\.price =" app config lib
grep -rnE "finalize!|order\.completed|OrderUpdater|register_update_hook|\bresume!?\b" app config lib
grep -rnE "ReturnAuthorization|CustomerReturn|Reimbursement|ReturnItem" app config lib
grep -rnE "_service\s*=" config

非推奨ですが動作する名前(Shipment、ShippingMethod、Taxon、metafields、firstname、Spree.user_class など)は Spree::Deprecation 警告をログに出します。今のうちに修正してください。これらは 6.1 で削除されます。非推奨機能が見える状態でテストスイートを実行し、各警告を対応事項として扱ってください。

5. 動作の確認チェックリスト

これらはエラーを発生させず、動作を変えます。それぞれ確認してください。

  • 完了したカートは読み取り専用です。 チェックアウト後の編集は Spree::Order に対して行います。カート API を通じて完了後の注文を変更する処理は、注文側の管理サービスに移してください。
  • line_item.order は nil の場合があります。 LineItem、Fulfillment、Payment、TaxLine、Discount、Fee、StockReservation は cart_id と order_id を持ちます(設定されるのはどちらか一方のみです)。#owner を使用してください。
  • ステータスは派生値です。 payment_status / fulfillment_status を書き込むのは Spree::Orders::UpdateStatuses のみです。直接代入しても上書きされます。payment_state/shipment_state/state は 6.1 までは読み取り用のエイリアスです。注文の絞り込みには q[status_eq]=placed を使用してください。
  • 注文確定後の金額は固定されます。 再計算では型付きの行を再集計しますが、再生成はしません。注文確定後の金額編集には Spree::Orders::Discounts::* / Orders::Fees::* を使用してください。
  • 5.x の拡張機能は、カートに対して Order の名前を呼び出します。 カートが未完了の注文だった時期に作成されたゲートウェイ gem は、Spree::Cart に対して promo_total、item_count、shipments、user、available_payment_methods …を呼び出します。これらの非推奨名は、6.1 までは Cart と Order の両方で警告を出して転送されます(grep の例を参照してください)。非推奨警告ログを確認し、gem を更新してください。
  • 無料ギフトはしきい値の計算に含まれません。 create_line_items によるギフトは、item_total ルールや注文割引率の計算基準に含まれなくなりました。ギフト自身のプロモーションのしきい値も同様です。「100 ドルを超えて購入するとギフトを進呈」の場合、有料商品の金額が 100 ドルになるとギフトは取り消されます。
  • キャンセルは取り消せません。 注文やフルフィルメントに resume はありません。order.resumed / fulfillment.resumed イベントも廃止されました。すべての商品が返品された注文は、fulfillment_status: unfulfilled として扱われます。
  • Spree::Store.default は nil になる場合があります。 リクエスト外で実行されるジョブ、rake タスク、シード、テストでは Spree::Current.store を設定してください。ストアに紐付くレコードを作成する前に、デフォルトストアが存在することを確認してください。
  • Spree::Base を継承するすべてのモデルでは、belongs_to はデフォルトで必須です(独自のモデルも含みます)。空の値が正当な場合は optional: true を追加してください。エラーは「can't be blank」ではなく「must exist」となります(アサーションと、422 の details を解析するクライアントを修正してください)。
  • ストアフロントの仕様。 requirements[] の各項目には { step, field, code, message } が含まれます。配送要件は field: 'delivery_method'、code: 'delivery_method_required' です。リッチテキストの読み取り結果はプレーンテキストと *_html(description_html、internal_note_html)を返します。エディターには *_html を読み込んでください。カートの number は、1 リリースの間、接頭辞付きの cart_ ID と同じ値になります。
  • Webhook/イベント。 order.placed を購読してください(order.completed は 6.1 まで非推奨のエイリアスです)。report.*、order.resumed、fulfillment.resumed は削除されました。新しいイベント:return.*、exchange.*、claim.*、digital_asset.*、digital_link.downloaded。
  • リッチテキストの許可リストが縮小されました(前提条件を参照してください)。コンテンツは次回保存時に再サニタイズされます。
  • デジタルダウンロードは、有効期間の短い署名付き URL(最大 1 時間、digital_asset_link_expire_time)への 302 を返します。クライアントはリダイレクトに従う必要があります。顧客には spree_emails からダウンロードリンクのメールが送信されるようになりました。独自に送信している場合は、独自のメール送信を停止してください。
  • カスタムフィールド定義はストアに紐付きます。 マルチストア環境では、すべての定義がデフォルトストアに作成されます。ストアごとに再作成してください。商品 CSV の列では、metafield.(旧名称)ではなく custom_field. の接頭辞を使用し、shipping_category(旧名称)ではなく product_type を使用します。
  • スタッフ API の権限。 スタッフの JWT にも、シークレットキーと同じコントローラー単位のゲートが適用されます(details.required_permission を含む 403)。スタッフ用エンドポイントには read_staff / write_staff が必要です。
  • ストア API の認可では、CanCanCan を参照しなくなりました。顧客アクセスは、所有権によるスコープ設定と Spree::Storefront::AccessPolicy に基づきます。ストアフロントの can ルールは、アクセス・ポリシーのサブクラスまたはワークフローの validate フックに移してください。
  • 国と州は参照データです(countries gem のプレーンオブジェクトであり、.where / .find は使用できません)。レコードでは ISO の country_code / state_code で指定します。
  • 在庫が減るのは注文確定時ではなく、発送時です(未完了のフルフィルメントでは在庫が引き当てられています)。count_on_hand のみを基に構築された在庫レポートは、これまでと異なる値になります。
  • ジョブ。 新規プロジェクトでは Puma 内で Solid Queue が実行されます(Mission Control は /jobs)。アップグレードしたアプリでは、独自の config.active_job.queue_adapter が維持されます。Sidekiq は引き続き動作します。Spree の定期ジョブは、使用しているスケジューラーに移してください。
  • SDK のメジャーバージョン。 ストアフロントの @spree/sdk を 2.x に、インテグレーションの @spree/admin-sdk を 1.x に更新してください。Rails 管理画面のカスタマイズは apps/dashboard プラグイン(spree add dashboard)に置き換えてください。

注意点

  • バックフィルの順序を変更しないでください。 複数の手順はそれ以前の手順に依存しています(メディアはマスターバリアントの削除より前、タクソンと顧客はリッチテキストより前、調整はカートと返品より前、返品は在庫移動より前)。マニフェストの順序は重要です。
  • migrate_users_to_customers は意図的に中断します。 Devise の削除後に CONFIRM_NO_PEPPER=true が設定されていない場合、中断します。無理に続行するのではなく、ペッパーが使用されていないことを確認してください。
  • *_service の DI キーを上書きしても、現在は何も起きません。 Spree::Dependencies.carts_complete_service = 'MyComplete' のような従来の書き込みは適用されず、保留されます。*_workflow キーに移行する(提供されているワークフローをサブクラス化する)か、さらに推奨される方法として Spree.hooks.register ハンドラーを使用してください。詳しくは spree-dependencies と spree-workflows を参照してください。
  • Spree::Product.additional_permitted_attributes << :x は FrozenError を発生させます。 += [:x] を使用してください。
  • レガシーテーブルは 6.1 まで残ります(ロールバック元としての spree_adjustments、返品承認関連テーブル、spree_state_changes、spree_log_entries、spree_users、Action Text の行)。6.1 より前に、保持したいデータをエクスポートしてください。

さらに詳しく読むには

  • node_modules/@spree/docs/dist/developer/upgrades/5.6-to-6.0.md — 公式ガイド(https://spreecommerce.org/docs/developer/upgrades/5.6-to-6.0)
  • references/grep-recipes.md — パターンと置換の完全な一覧
  • 関連スキル:spree-upgrade、spree-workflows、spree-checkout、spree-order-totals、spree-fulfillment、spree-returns、spree-auth-permissions、spree-catalog、spree-pricing、spree-dashboard-plugins、spree-typescript-sdk

コメント