fix(calendar): GOOGLE_SA_JSON_B64 поддержка (env-file friendly)
All checks were successful
Deploy / deploy (push) Successful in 2m7s

docker --env-file не поддерживает многострочные значения и не парсит
кавычки. Сырой JSON service-account ломается на newline'ах в private_key
поле → docker пытается парсить '-----END PRIVATE KEY-----' как имя
переменной и валится с 'contains whitespaces'.

Решение: base64 GOOGLE_SA_JSON_B64 (одна строка ASCII, никаких кавычек).
Старая GOOGLE_SA_JSON оставлена как fallback. Третий fallback на файл —
для локальной разработки.
This commit is contained in:
Cosmo
2026-04-27 12:59:17 +00:00
parent be377e377f
commit 96fa78bd5c

View File

@@ -15,20 +15,32 @@ function getAuth(readonly = true) {
? ['https://www.googleapis.com/auth/calendar.readonly'] ? ['https://www.googleapis.com/auth/calendar.readonly']
: ['https://www.googleapis.com/auth/calendar'] : ['https://www.googleapis.com/auth/calendar']
// 1) Предпочтительно — base64. docker --env-file не парсит кавычки и не
// поддерживает многострочные значения, а private_key в JSON ломается
// на переводах строк → base64 это решает (одна строка ASCII).
const saB64 = process.env.GOOGLE_SA_JSON_B64
if (saB64) {
try {
const sa = JSON.parse(Buffer.from(saB64, 'base64').toString('utf-8'))
return new google.auth.GoogleAuth({ credentials: sa, scopes })
} catch (e) {
console.error('[calendar] GOOGLE_SA_JSON_B64 decode failed:', e)
}
}
// 2) Сырая JSON-строка (legacy).
const saJson = process.env.GOOGLE_SA_JSON const saJson = process.env.GOOGLE_SA_JSON
if (saJson) { if (saJson) {
const sa = JSON.parse(saJson) try {
return new google.auth.GoogleAuth({ const sa = JSON.parse(saJson)
credentials: sa, return new google.auth.GoogleAuth({ credentials: sa, scopes })
scopes, } catch (e) {
}) console.error('[calendar] GOOGLE_SA_JSON parse failed:', e)
}
} }
// 3) Fallback на файл (для локальной разработки).
const saPath = path.join(process.cwd(), 'google-sa.json') const saPath = path.join(process.cwd(), 'google-sa.json')
if (fs.existsSync(saPath)) { if (fs.existsSync(saPath)) {
return new google.auth.GoogleAuth({ return new google.auth.GoogleAuth({ keyFile: saPath, scopes })
keyFile: saPath,
scopes,
})
} }
return null return null
} }