0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SupabaseのGitHub連携:SQLファイルをマージするだけでDBを変更する

0
Last updated at Posted at 2026-11-02

対象: データベースの変更を、画面で手作業していて「本番に入ったの?」「誰がいつ変えたの?」が不安な方(エンジニアでなくてもOK)
所要時間: 60分前後 / 使うもの: Supabaseのアカウント(無料でOK)、GitHubのアカウント、ブラウザ
確認日: 2026-10-31(料金や仕様は変わります)
続きの記事(変更の状況が見えるボードにしてみた): https://qiita.com/tomozilla/items/9f175f4869e15c1417e6
ビジネス編(やさしい解説・note): https://note.com/tomozilla/n/n77dc7e7d68dc

データベースの変更を、ダッシュボードで手作業していると、こんな不安が出てきます。「あの変更、本番に入ったんだっけ?」「誰が、いつ、何を変えたの?」

この記事では、変更をSQLのファイルにしてGitHubに置き、マージ(取り込み)するとSupabaseのデータベースに自動で反映される仕組みを、つなぐ作業はダッシュボードの画面だけで試しました。トークンやパスワードをどこかに貼る作業はありません(ひな形ファイルを作るときに、コマンドを1回だけ使いました。0章)。さらに、わざと壊したらどうなるかも確かめました。私は同じように試している一人で、公式の人間ではありません。

0. 先に伝えておきたいこと

  • 実際にやったのは、無料プロジェクトにGitHubのリポジトリをつなぎ、プルリクエスト(変更の提案)を何本かマージすること。この部分の費用は$0でした。
  • 最後に、**有料(Proプラン)**のプロジェクトで「プレビューブランチ」も試しました。短時間(プロジェクトを約15分、ブランチを約2分)だけ動かして、すぐ削除しました。料金の目安は8章に書きます。
  • 試していないこと:GitHub ActionsとSupabase CLIを組み合わせる方法(テスト・承認付き)。ネットで見かける定番の構成ですが、私は動かしていません(9章)。
  • 手元のPCで supabase init を1回だけ使いました(config.tomlというひな形ファイルを作るため)。ほかのSupabase CLIの操作は使っていません。2本目以降のプルリクの作成とマージは、1本目だけブラウザで、残りはghというGitHubのコマンドで行いました(画面での操作と結果は同じです)。
  • 使ったデータはすべて架空です。

用語を1つだけ:この記事で「マイグレーション」と言うのは、データベースの変更を書いた1枚のSQLファイルのことです。ファイル名の頭の数字(日付)が、実行する順番になります。

1. 準備:リポジトリに supabase フォルダを置く

つなぐリポジトリには、次の形で supabase フォルダが必要です。

supabase/
  config.toml          ← 設定ファイル(supabase init で作れる)
  migrations/
    20261031000100_create_notes.sql

1枚目のマイグレーションは、小さな「notes」テーブルを作るだけの内容です。

create table public.notes (
  id bigint generated always as identity primary key,
  body text not null,
  created_at timestamptz not null default now()
);

alter table public.notes enable row level security;

create policy "notes are readable by signed-in users"
  on public.notes for select
  to authenticated
  using (true);

config.toml を手で書いてもよいのか、GitHubの画面から作ってもよいのかは、私は試していません。supabase initで作ったものを使いました。

2. ダッシュボードでGitHubをつなぐ

Project Settings → Integrations → GitHub → 「Choose GitHub repository」 を開きます。

ここで私は少し迷いました。自分のリポジトリが一覧に出てこないのです。一覧の下の 「Add GitHub Repositories」 を押すと、GitHubの「Supabaseアプリをインストールしますか?」画面が開きました。

  • 「All repositories」と「Only select repositories」があります。後者にして、この1つのリポジトリだけを選びました(アプリが求める権限は、コードの読み取りと、Actions・チェック・プルリクエストなどの読み書きでした)。
  • 私の環境では、インストール後に画面が「Completing GitHub Authorization...」のまま止まりました。ダッシュボードを開き直したら、自分のリポジトリが一覧に出ました(別のタブで開いたせいかもしれません)。

リポジトリを選ぶと、次のフォームが出ます。

GitHubの接続フォーム。リポジトリ、作業フォルダ、本番ブランチ、「Deploy to production」

  • Working directory:supabase フォルダがある場所。リポジトリの直下なら . のままでOK。
  • Deploy to production:オンのままにすると、本番ブランチ(main)にマージされたら、本番のデータベースに反映します。
  • 無料プロジェクトでは、下の「Branching」(プルリクごとのお試し環境)は灰色で、Proプランが必要と出ます(7章)。

Enable integration を押すと、「GitHub connection updated」と出ました。ここまでで、設定は終わりです。

ここまで出ていれば成功です:ボタンが「Disable integration」に変わります。

この時点で、データベースはまだ空でした。リポジトリには1枚目のマイグレーションがあるのに、Database → Migrations には何もありません。つなぐ前から置いてあったファイルは、すぐには反映されないようです。

つないだ直後のMigrations画面。まだ何も適用されていない

3. 1本目のプルリクをマージする

2枚目のマイグレーション(author列を足して、架空のサンプル2行を入れる)を、プルリクにしてマージしました。

alter table public.notes add column author text not null default 'unknown';

insert into public.notes (body, author) values
  ('First note written from a migration file', 'sample-user-a'),
  ('Second sample note', 'sample-user-b');

プルリクの画面には、「Supabase Preview」というチェックが出ていて、無料プロジェクトでは**「skipped(スキップ)」**でした。

プルリクの画面。「All checks have passed / 1 skipped check」

「skipped」は失敗ではなく、やっていないという意味です。プレビュー用の環境を作る機能(7章)がオフだからです。ただ、これが後で効いてきます。

Merge pull request を押してマージしました。しばらくしてから Database → Migrations を見ると……

Migrationsに2本が並ぶ。1枚目(つなぐ前からあったもの)も一緒に適用された

2枚目だけでなく、1枚目も一緒に適用されていました。連携は「まだ適用されていないマイグレーションを、ファイル名の順にすべて」反映するようです。

もう1つ、気づいたことがあります。「INSERTED AT」の時刻が 00:02:00 のように、ファイル名の数字そのままでした。実際に反映したのはもっと後なので、この列は「反映した時刻」ではなくファイル名から作られた時刻のようです(私の推測で、公式に確認したわけではありません)。

4. わざと壊してみる:失敗はどこに出る?

次に、すでにある列をもう一度足すという、わざと壊したSQLをマージしました。

alter table public.notes add column author text;

無料プロジェクトでは、プルリクの時点で止めるものはありませんでした(1本目と同じ設定なので、チェックは「skipped」のはずです。ただ、この壊れたプルリクは作ってすぐマージしたので、その画面そのものは見ていません)。マージしたあと、mainのコミットのチェックが**赤(失敗)**になりました。

失敗したチェック。Postgresの本物のエラー文が出ている

エラー文は、column "author" of relation "notes" already exists。何が悪いかは、ちゃんと読めます。

でも、ダッシュボード側には何も出ません。プロジェクトの概要の「LAST MIGRATION」は、前の変更のままで、ステータスは「Healthy」です。

概要画面。ステータスは Healthy で、失敗の表示はない

つまり、無料プロジェクトでは、失敗に気づく場所はGitHubだけで、しかもマージのあとです。「本番は壊れていない(反映されていないだけ)」ですが、気づかないと、変更が入っていないことに誰も気づかないかもしれません。

5. 1つ壊れると、後ろも全部止まる

もう1つ、試しました。壊れたファイルを残したまま、正しいマイグレーション(インデックスを作るだけ)をマージしたのです。

結果は失敗。しかも、さっきと同じ古いエラーでした。

マイグレーションは順番に実行される。3番目が詰まると、4番目・5番目も進めない

順番に実行するので、詰まったファイルより後ろは、正しくても進めません。

直し方は、壊れたファイルを直すだけでした。そのファイルはまだ一度も適用されていなかったので、同じファイルをその場で書き換えて(add column if not exists に変更)マージしました。すると、残りも一緒に適用されました。

4本すべてが適用された

注意:すでに適用されたファイルを書き換えるのは別の話です。適用済みのファイルは直さず、新しいファイルで直すのが基本のはずですが、これは私は試していません。

6. Edge Functionも運ばれる/設定は運ばれない

ドキュメントには、運ばれるのは、マイグレーションと、config.tomlに書いたEdge Functionなどと書かれていました。本当か確かめました。

Edge Function:supabase/functions/applied-migrations/index.ts を置き、config.tomlに次を足してマージしました。

[functions.applied-migrations]
verify_jwt = false

ダッシュボードのEdge Functionsに、関数が自動で現れました。

Edge Functionsの一覧に、連携が自動でデプロイした関数が出ている(URLは伏せています)

呼び出してみると、鍵なしでは関数自身のエラー文が返ったので、verify_jwt = falseも反映されていました。(※ここでverify_jwt = falseにしたのは、デモのためです。注意点はサンプルのREADMEに書きました。)

設定:同じプルリクで、config.tomlの [api] max_rows を 1000 から 7 に変えてみました。ダッシュボードのData API設定を見ると……

Max rows は 1000 のまま。config.tomlの変更は反映されていない

1000のままでした。ダッシュボードで決める設定は、この連携では運ばれないようです。「ファイルに書けば全部運ばれる」と思っていると、ここでつまずきそうです。

7. プルリクの時点で失敗を見たい:プレビューブランチ(有料)

4章で、無料プロジェクトではマージの後にしか失敗が分からないと書きました。マージの前に分かる方法が、プレビューブランチです。

リハーサル場(プレビュー)があると、失敗は本番の前に見つかる

仕組みは、プルリクごとに、使い捨てのお試し環境(本物のデータベースの複製。データは入らない)を自動で作り、そこに新しいマイグレーションを流して試す、というものです。Proプラン以上で使えます。

ダッシュボードのつなぎ方は同じで、Proのプロジェクトだと、フォームに最初からブランチ機能がオンで出ます。

Proプロジェクトのフォーム。「Branching and billing」の注意書き、Automatic branching、Branch limit

注意書きに、**「ブランチのコンピュート(計算)はスペンドキャップ(使いすぎ防止の上限)の対象外」**とあります。上限が効かないので、使い終わったら消すことが大事です。

このProプロジェクトで、**壊れたマイグレーションのプルリク(マージしない)**を作りました。結果は、マージの前、プルリクの画面に出ました。

プルリク上のボットのコメント。Migrationsの行に×、エラー文付き。「All checks have failed」

  • ボットのコメントに、タスクの表が出ます。Configurationsは✅、Migrationsが❌、SeedingとEdge Functionsは一時停止(⏸)でした。
  • 同じエラー文(今度は存在しないテーブル)が、マージの前に読めました。
  • コメントには「新しいマイグレーションのファイルだけが流される」という趣旨の注意書きもありました。

無料プロジェクトとの違いは、失敗に気づくのが、本番の前か後かです。これが私が一番「なるほど」と思った点です。

8. 費用のまとめ

項目 費用 私の実行
GitHub連携(無料プロジェクト) $0(ドキュメントでは全プランで使える) 実測:課金なし
プレビューブランチ ドキュメントでは固定費なし、使った分だけ。Microのブランチは1時間あたり$0.01344から、スペンドキャップの対象外(2026-10-31確認) ブランチは約2分
追加のMicroプロジェクト(Pro) 同じ単価。月約$10 約15分で削除

私の短時間の検証は、ドキュメントの単価で計算すると数セント以下です。ただし、請求書では確認していません。1時間未満が切り上げかどうかも確認していません。長く動かしっぱなしにすると月$10ずつ増えるので、試したら消しましょう。

9. まだ試していないこと/穴(正直に)

  • ルートB:GitHub Actionsで、SQLの検査(supabase db lint)、テスト(supabase test db)、本番に出す前の承認まで組む標準的な構成。私は動かしていません。ネットで見かけた例を読んだだけで、たとえば「検査の前にローカルのデータベースを起動する必要があるのでは」など、動かしてみないと分からない点があります。
  • 複数の文が入ったマイグレーションが途中で失敗したとき、一部だけ反映されるかどうか(私の壊したファイルはどれも1文でした)。
  • プライベートのリポジトリ、supabaseフォルダが深い場所にある場合、プルリクが同時に何本もある場合。
  • 無料プロジェクトで、プルリクの時点で失敗を見る方法は、見つけられませんでした(ブランチ機能が必要でした)。

10. 後片付け

連携を無効にし(Settings → Integrations → Disable integration)、テーブルとマイグレーションの記録、Edge Functionを消し、使い捨てのProプロジェクトも削除しました。GitHubに入れたSupabaseアプリは、不要なら github.com/settings/installations から外せます。

まとめ

  • SQLファイルをマージするだけで、データベースに反映できた(ダッシュボードの設定だけ。費用は無料)。
  • 連携は未適用のものを順番にすべて反映する。1つ壊れると後ろも止まる。
  • 無料だと、失敗に気づくのはマージの後。ダッシュボードには出ず、GitHubだけに出る。
  • 運ばれるのは、マイグレーションとEdge Function。ダッシュボードの設定は運ばれない。
  • マージの前に失敗を見るには、有料のプレビューブランチ。ただし上限が効かないので、消し忘れに注意。

次は、この状況を一目で見られるボードにしてみました(続きの記事)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?