1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Makefileで、同一GASコードを本番/開発へ自動デプロイする仕組み

Posted at

はじめに

Google Apps Script(GAS)のコードを Git で管理し、clasp を使ってデプロイする際に、同一のコードベースから本番環境と開発環境の複数のスプレッドシートへデプロイする必要がありました。環境ごとに異なる Script ID が必要で、手動で.clasp.jsonを切り替えるのは煩雑でした。

この記事では、Makefile と設定ファイルを活用して、同一コードベースから複数環境への clasp push を簡単に実行できる仕組みを紹介します。

GAS_Clasp_Deployment_Automation_page-0001.jpg

前提

この仕組みを構築した背景には、以下のような運用環境がありました。

スプレッドシート

WordPress のデータベースサーバーからデータをスプレッドシートにエクスポートし、スプレッドシート上で情報を編集してから WordPress にアップロードすることで、データを更新する仕組みを構築しています。

この一連の処理は Google Apps Script(GAS)× サーバーレスアーキテクチャで実装されており、スプレッドシート上で実行されます。

複数メディア・複数環境の管理

GAS_Clasp_Deployment_Automation_page-0003.jpg

複数の Web メディアを運営しており、各メディアごとに本番用スプレッドシートと開発用スプレッドシートの 2 枚が必要になります。
メディア数が増えるにつれて、管理するスプレッドシートの数は「メディア数 × 2(本番・開発)」と増加していきます。

各スプレッドシートには GAS コードが紐づいており、コードの更新やデプロイを効率的に行う必要がありました。

課題

GAS コードを clasp で管理する際、以下の課題がありました

  1. 同一コードを複数環境にデプロイする必要がある

    • 開発環境(dev)と本番環境(prd)のスプレッドシートが異なる
    • 各環境ごとに異なる Script ID が必要
  2. .clasp.jsonの管理が煩雑

    • 環境ごとに異なる Script ID を持つ.clasp.jsonが必要
    • 手動でファイルを切り替える必要がある
    • ミスで間違った環境に push してしまうリスクがある
  3. 複数メディア・複数環境の管理

    • 複数のメディア(media-a、media-b など)を管理
    • 各メディアごとに dev/prd 環境がある
    • 一括で環境ごとにデプロイしたい

解決策の概要

GAS_Clasp_Deployment_Automation_page-0005.jpg

以下のアプローチで課題を解決しました:

  1. clasp-config.jsonで環境ごとの Script ID を一元管理

    • すべての環境の Script ID を 1 つの JSON ファイルで管理
    • {メディア名}-{環境}をキーとして定義
  2. Makefile で環境を指定して自動的に.clasp.jsonを生成

    • TARGET 変数(例: example-media-dev)を受け取る
    • 環境ごとの Script ID を取得して.clasp.jsonを一時的に生成
    • clasp push実行後に.clasp.jsonを削除
  3. 同一コードベースから複数環境へ push 可能

    • コードを変更せずに、環境指定だけでデプロイ先を切り替え可能

実装詳細

clasp-config.json の構造

環境ごとの Script ID を{メディア名}-{環境}形式のキーで管理します:

clasp/clasp-config.json
{
  "example-media-a-dev": {
    "scriptId": "1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  },
  "example-media-a-prd": {
    "scriptId": "1YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
  },
  "example-media-b-dev": {
    "scriptId": "1ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
  },
  "example-media-b-prd": {
    "scriptId": "1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  }
}

この構造により、すべての環境の Script ID を 1 箇所で管理できます。

Makefile の仕組み

Makefile では以下の流れで処理を実行します:

主要な処理の流れ:

  1. パターンルール push-%で簡潔に実行可能

    13:Makefile
    push-%:
    	@$(MAKE) push TARGET=$*
    

    これにより、make push-example-media-devのような短いコマンドで実行できます。

  2. TARGET 変数の解析

    33:Makefile
    @MEDIA_ENV="$(TARGET)"; \
    if [[ "$$MEDIA_ENV" == *-dev ]]; then \
    	MEDIA="$${MEDIA_ENV%-dev}"; \
    	ENV="dev"; \
    elif [[ "$$MEDIA_ENV" == *-prd ]]; then \
    	MEDIA="$${MEDIA_ENV%-prd}"; \
    	ENV="prd"; \
    else \
    	echo "Error: Invalid TARGET format. Must end with -dev or -prd"; \
    	exit 1; \
    fi; \
    echo "Media: $$MEDIA, Environment: $$ENV"; \
    

    TARGET の末尾が-devまたは-prdかを判定して、メディア名と環境を分離します。

  3. Script ID の取得と.clasp.jsonの生成

    53:Makefile
    SCRIPT_ID=$$(jq -r '.["$(TARGET)"].scriptId' "$(CONFIG_FILE)"); \
    if [ "$$SCRIPT_ID" = "null" ] || [ -z "$$SCRIPT_ID" ]; then \
    	echo "Error: Configuration for $(TARGET) not found in $(CONFIG_FILE)"; \
    	exit 1; \
    fi; \
    ROOT_DIR="$(PROJECT_ROOT)$(CLASP_DIR)/$$MEDIA"; \
    echo "Script ID: $$SCRIPT_ID"; \
    echo "Root Dir: $$ROOT_DIR"; \
    jq -n \
    	--arg scriptId "$$SCRIPT_ID" \
    	--arg rootDir "$$ROOT_DIR" \
    	'{scriptId: $$scriptId, rootDir: $$rootDir}' > "$(PROJECT_ROOT)$(CLASP_DIR)/$$MEDIA/.clasp.json"; \
    

    jqを使ってclasp-config.jsonから Script ID を取得し、.clasp.jsonを動的に生成します。

  4. clasp push の実行とクリーンアップ

    55:Makefile
    cd "$(PROJECT_ROOT)$(CLASP_DIR)/$$MEDIA" && clasp push; \
    rm -f "$(PROJECT_ROOT)$(CLASP_DIR)/$$MEDIA/.clasp.json"; \
    

    clasp pushを実行した後、生成した.clasp.jsonを削除してクリーンアップします。

一括デプロイ機能

GAS_Clasp_Deployment_Automation_page-0012.jpg

開発環境や本番環境のすべてのメディアに対して一括で push する機能も実装しています:

91:Makefile
pushall-dev:
	@echo "=== 全dev環境へのpushを実行します ==="
	@TARGETS=$$(jq -r 'keys[] | select(endswith("-dev"))' "$(CONFIG_FILE)" | sort); \
	if [ -z "$$TARGETS" ]; then \
		echo "Error: No dev targets found"; \
		exit 1; \
	fi; \
	echo ""; \
	echo "以下のターゲットに対してpushを実行します:"; \
	echo "$$TARGETS" | sed 's/^/  - /'; \
	echo ""; \
	read -p "本当に実行して良いですか? (yes/no): " confirm; \
	if [ "$$confirm" != "yes" ]; then \
		echo "キャンセルされました"; \
		exit 1; \
	fi; \
	echo ""; \
	echo "=== pushを開始します ==="; \
	for target in $$TARGETS; do \
		echo ""; \
		echo "--- Pushing to $$target ---"; \
		$(MAKE) push TARGET=$$target || { \
			echo "Error: Failed to push $$target"; \
			exit 1; \
		}; \
	done; \
	echo ""; \
	echo "=== 全てのpushが完了しました ==="

この機能により、確認付きで開発環境または本番環境のすべてのメディアに一括で push できます。

使い方

基本的な使い方

個別の環境に対して push する場合:

# パターンルールを使った短縮形式
make push-example-media-dev

# TARGET変数を使った形式
make push TARGET=example-media-dev

一括デプロイ

開発環境のすべてのメディアに push:

make pushall-dev

本番環境のすべてのメディアに push:

make pushall-prd

利用可能なターゲットの一覧

どのようなターゲットが利用可能か確認する場合:

make list

メリット

GAS_Clasp_Deployment_Automation_page-0014.jpg

  1. 同一コードベースで複数環境を管理

    • コードを環境ごとに分ける必要がない
    • バージョン管理がシンプル
  2. 環境切り替えが簡単

    • コマンド 1 つで環境を指定してデプロイ可能
    • ミスを減らせる
  3. 一括デプロイが可能

    • 開発環境や本番環境全体にまとめて push できる
    • 確認プロセスも組み込まれている
  4. 設定の一元管理

    • すべての Script ID を 1 つの JSON ファイルで管理
    • 設定の変更が容易

注意点

  1. jqが必要

    • JSON のパースにjqコマンドを使用している
    • 事前にインストールが必要
  2. Script ID の管理が重要

    • clasp-config.jsonに誤った Script ID を設定すると、間違った環境に push してしまう
    • 設定ファイルの管理に注意
  3. .clasp.jsonを git 管理しない

    • .clasp.jsonは一時的に生成されるファイル
    • .gitignoreに含めておくこと
  4. clasp の認証が必要

    • clasp pushを実行する前に、clasp loginで認証しておく必要がある

まとめ

この仕組みにより、Git で管理された GAS コードを簡単に複数環境へデプロイできるようになりました。Makefile と設定ファイルを活用することで、環境切り替えが簡単になり、ミスを減らしながら効率的にデプロイ作業を行うことができます。

同一コードベースから本番・開発環境へのデプロイを頻繁に行う場合、このような仕組みを導入することで、作業効率が大幅に向上します。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?