Google系のAPIはOAuth認証、サービスアカウント、APIキーの利用の3パターンあると認識してますが、簡単な読み書きくらいのやりとりだとサービスアカウント利用は手ごろです。
前提
以下ができてる前提になります。
- Google SheetsのAPIを許可してサービスアカウント作成
- 作成したサービスアカウントを対象のシートに権限付与
- サービスアカウントの鍵ファイルをJSON形式で取得
鍵ファイルをDLすると以下のような雰囲気の中身となります。
{
"type": "service_account",
"project_id": "xxxxxxxx",
"private_key_id": "xxxxx",
"private_key": "-----BEGIN PRIVATE KEY----○-----END PRIVATE KEY-----\n",
"client_email": "hogehoge@hogehoge.iam.gserviceaccount.com",
"client_id": "1111111111111111111111111111",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/xxxxxxxxxxxxx"
}
↑はあくまでもサンプルです。
とりあえず情報を取得するコピペサンプル
この場合必要ライブラリはgoogleapisのみです。
$ npm i googleapis
以下のコードで、サービスアカウントを追加してアクセスを許可したシートのID
と範囲
を変更しつつ、鍵ファイルをkeyfile.json
として同一フォルダに置いておけば動くと思います。
'use strict';
const {google} = require('googleapis');
const KEYFILE_NAME = `keyfile.json`;
const KEYFILE_PATH = `./${KEYFILE_NAME}`;
const main = async () => {
console.log(`--Google SpreadSheet認証`);
let sheets = {};
try {
const auth = new google.auth.GoogleAuth({
keyFile: KEYFILE_PATH,
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
sheets = google.sheets({version: 'v4', auth});
console.log(`認証done--`);
} catch (error) {
console.log(error);
}
console.log(`--sheetアクセス`);
try {
const res = await sheets.spreadsheets.values.get({
spreadsheetId: `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`, //シートのIDを指定
range: `Form1!A:H`, //取得する範囲を指定
});
console.log(res.data);
} catch (error) {
console.log(error);
}
}
main();
これで実行すると以下のように情報が取れると思います。
$ node ss.js
--Google SpreadSheet認証
認証done--
--sheetアクセス
--sheetアクセス
{
range: 'Form1!A1:H104',
majorDimension: 'ROWS',
values: [
[
'hoge',
'お名前',
'所属',
'GitHubのマイページURL',
'GitHubに登録したメールアドレス',
'ステータス',
'追加team',
'担任チェック'
],
・・・省略
CIで動かしたいver
CIで動かす時にkeyfileを直接GitHubなどに載せるのはしたくないので環境変数に設定したいです。
ただ以下のようにGoogleAuthの関数がKeyFileの指定をしてくるので(これ別のオプションありますかね...?)
const auth = new google.auth.GoogleAuth({
keyFile: KEYFILE_PATH,
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
環境変数から情報取得してファイルに書き出し -> 認証 -> 1番最後に消すという処理も加えてみました。
手元でも試したいのでdotenvも追加してます。
npm i dotenv
ローカルだと.envファイルに詰め込みつつ
GOOGLE_PRIVATE_KEY='{ "type": "service_account", ・・・省略
SHEET_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
実行する際にfs.writeFileSyncでファイルを作っています。
'use strict';
const {google} = require('googleapis');
const fs = require('fs');
require('dotenv').config();
const KEYFILE_NAME = `keyfile.json`;
const KEYFILE_PATH = `./${KEYFILE_NAME}`;
const main = async () => {
try {
console.log(`--keyfile作成`);
fs.writeFileSync(KEYFILE_NAME, process.env.GOOGLE_PRIVATE_KEY);
console.log(`作成done--`);
} catch (error) {
console.log(error);
}
console.log(`--Google SpreadSheet認証`);
let sheets = {};
try {
const auth = new google.auth.GoogleAuth({
keyFile: KEYFILE_PATH,
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
sheets = google.sheets({version: 'v4', auth});
console.log(`認証done--`);
} catch (error) {
console.log(error);
}
console.log(`--sheetアクセス`);
try {
const res = await sheets.spreadsheets.values.get({
spreadsheetId: process.env.SHEET_ID,
range: `Form1!A:H`,
});
console.log(res.data);
} catch (error) {
console.log(error);
}
console.log('---Keyファイル削除');
try {
fs.unlinkSync(KEYFILE_PATH);
console.log('削除しました。--');
return;
} catch (error) {
throw error;
}
}
main();
これでCIでも動くはず...だったんですが、CircleCIだと何故かうまくいかずGitHub Actionsではうまくいきました。ファイルを作成して書き込みあたりの何かの不具合があるのかも...?