Created
September 30, 2021 14:55
-
-
Save nathanforce/686d64b2dc4fb2afdb2e00fa2a77151d to your computer and use it in GitHub Desktop.
Sendgrid Github Action
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as core from '@actions/core'; | |
import * as github from '@actions/github'; | |
import client from '@sendgrid/client'; | |
import path from 'path'; | |
import fs from 'fs'; | |
import colors from 'ansi-styles'; | |
// @ts-ignore | |
import HumanHash from 'humanhash'; | |
async function upload(files: string[]) { | |
// Setup | |
const SG_API_KEY = core.getInput('SENDGRID_API_KEY', { required: true }); | |
client.setApiKey(SG_API_KEY); | |
try { | |
const existingTemplatesByName = await getTemplates(); | |
const versionName = humanize(); | |
let promises: Promise<any>[] = []; | |
for (const template of files) { | |
const name = path.basename(template, '.html'); | |
const relativePath = path.relative(process.cwd(), template); | |
const existing = existingTemplatesByName.get(name); | |
const html = await fs.promises.readFile(template, 'utf-8'); | |
let promise; | |
if (existing && existing.activeVersion.html_content === html) { | |
promise = Promise.resolve().then(() => { | |
core.info(`${colors.gray.open}[SKIPPED] ${relativePath}`); | |
}); | |
} else if (existing) { | |
promise = createTemplateVersion(existing.id, versionName, html).then( | |
() => { | |
core.info( | |
`${colors.green.open}[UPDATED] ${relativePath} => ${name}:${versionName}` | |
); | |
} | |
); | |
} else { | |
promise = createTemplate(name).then(template => { | |
return createTemplateVersion(template.id, versionName, html).then( | |
() => { | |
core.info( | |
`${colors.green.open}[CREATED] ${relativePath} => ${name}:${versionName}` | |
); | |
} | |
); | |
}); | |
} | |
promises.push(promise); | |
} | |
await Promise.all(promises); | |
} catch (e) { | |
throw new Error(`Unable to fetch from Sendgrid: ${e.message}`); | |
} | |
} | |
async function activate(files: string[]) { | |
const SG_API_KEY = core.getInput('SENDGRID_API_KEY', { required: true }); | |
client.setApiKey(SG_API_KEY); | |
const existingTemplatesByName = await getTemplates(); | |
try { | |
const versionName = humanize(); | |
let promises: Promise<any>[] = []; | |
for (const file of files) { | |
const templateName = path.basename(file, '.html'); | |
const template = existingTemplatesByName.get(templateName); | |
const version = template.versions.find(v => { | |
return v.name === versionName; | |
}); | |
promises.push( | |
activateTemplateVersion(template.id, version.id).then(() => { | |
core.info( | |
`${colors.green.open}[ACTIVATED] ${versionName} is now the active template for template ${templateName}` | |
); | |
}) | |
); | |
} | |
await Promise.all(promises); | |
} catch (e) { | |
throw new Error( | |
`Error when trying to activate templates with Sendgrid API: ${e.message}` | |
); | |
} | |
} | |
function humanize() { | |
const { sha: VERSION } = github.context; | |
const humanizer = new HumanHash(); | |
return humanizer.humanize(VERSION); | |
} | |
async function createTemplate(name: string) { | |
const [response] = await client.request({ | |
method: 'POST', | |
url: '/v3/templates', | |
body: { | |
generation: 'dynamic', | |
name, | |
}, | |
}); | |
return response.body; | |
} | |
async function createTemplateVersion( | |
template: string, | |
name: string, | |
html: string | |
) { | |
const [response] = await client.request({ | |
method: 'POST', | |
url: `/v3/templates/${template}/versions`, | |
body: { | |
active: 0, // do not activate yet. This happens in a separate step (deployment) | |
html_content: html, | |
name: name, | |
subject: '{{subject}}', | |
generate_plain_content: false, | |
editor: 'code', | |
}, | |
}); | |
return response.body; | |
} | |
async function activateTemplateVersion(template: string, version: string) { | |
const [response] = await client.request({ | |
method: 'POST', | |
url: `/v3/templates/${template}/versions/${version}/activate`, | |
}); | |
return response.body; | |
} | |
async function getTemplates() { | |
const [response] = await client.request({ | |
method: 'GET', | |
url: '/v3/templates?generations=dynamic', | |
}); | |
const { templates } = response.body as { templates: any[] }; | |
let promises: Promise<any>[] = []; | |
for (const template of templates) { | |
const activeVersion = template.versions.find(v => { | |
return v.active === 1; | |
}); | |
const promise = client | |
.request({ | |
method: 'GET', | |
url: `/v3/templates/${template.id}/versions/${activeVersion.id}`, | |
}) | |
.then(([response]) => { | |
template.activeVersion = response.body; | |
}); | |
promises.push(promise); | |
} | |
await Promise.all(promises); | |
const existingTemplatesByName = templates.reduce((all, template) => { | |
all.set(template.name, template); | |
return all; | |
}, new Map<string, any>()); | |
return existingTemplatesByName; | |
} | |
(async () => { | |
try { | |
const action = core.getInput('action', { required: true }); | |
const input = core.getInput('templates'); | |
const templates = JSON.parse(input) || []; | |
if (templates.length < 1) { | |
core.info( | |
`${colors.gray.open}[SKIPPED] No templates provided for action ${action}` | |
); | |
return; | |
} | |
if (action === 'UPLOAD') { | |
await upload(templates); | |
} else if (action === 'ACTIVATE') { | |
await activate(templates); | |
} | |
} catch (error) { | |
core.setFailed(error); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment