lambot-snippets
const yaml = require('js-yaml'); | |
const tasks = require('./tasks'); // An object of supported tasks (functions) | |
// Helper function that attempts to run a task | |
function runTask(name, taskData) { | |
// Ensure valid task provided | |
if (!tasks[name]) return Promise.reject(`Invalid task name of '${name}' provided.`); | |
return tasks[name].call(null, taskData); | |
} | |
// This is our lambda function | |
module.exports = async (event, context, callback) => { | |
const response = JSON.parse(event.body); | |
const repoOwner = response.repository.owner.login; | |
const repoName = response.repository.name; | |
// Retrieve lambot.yml | |
// If missing, hook failure (lambot.yml is required) | |
// Else, load and execute tasks | |
const pendingTasks = await githubClient.get('config', { repoOwner, repoName }) | |
.then((res) => yaml.safeLoad(Buffer.from(res.data.content, 'base64'))) | |
.then((config) => | |
Object.keys(config.hooks).reduce((acc, hook) => { | |
// If hook is enabled, attempt to run it and push to pending task queue | |
if (config.hooks[hook]) { | |
acc.push(runTask(hook, { githubEvent, response, config: config.hooks[hook] })); | |
} | |
return acc; | |
}, [])) | |
.catch(() => { | |
callback(null, respond(500, 'Missing or invalid lambot.yml.')); | |
process.exit(0); | |
}) | |
// Wait for all tasks to run | |
await Promise.all(pendingTasks); | |
return callback(null, respond(200, 'Success')); | |
} |
// Newly opened pull-requests without labels will receive a friendly notice | |
async function labelTask({ githubEvent, response }) { | |
if (githubEvent === 'pull_request' && response.action === 'opened' && response.pull_request.labels.length === 0) { | |
const repoName = response.repository.name; | |
const repoOwner = response.repository.owner.login; | |
const prNumber = response.number; | |
// Post comment using the GitHub API | |
await githubClient.post('comment', { | |
repoOwner, | |
repoName, | |
prNumber, | |
message: '_Hi :wave:, it\'s Lambot!_\n\n' + | |
'I noticed this pull request has no assigned labels. :cry:\n\n' + | |
'Please remember to label your pull requests. That helps keep things organized around here. :slightly_smiling_face:' | |
}) | |
} | |
return Promise.resolve(); | |
}; |
hooks: | |
# Automatic versioning & publishing | |
semver: true | |
# Prefer labels on pull requests; notify if missing. | |
labels: true | |
# Run commands on each push and sends a Github status | |
codereview: | |
commands: | |
- echo Installing node modules... | |
- npm i | |
- echo Running tests... | |
- npm test |
const BOT_NAME = 'lambot'; | |
// Automatically version and publish repositories that are npm packages | |
async function semverTask({ githubEvent, response }) { | |
// Only listen to push events on master (we don't want to version + publish every branch!), | |
// ignore commits from our bot (to avoid an infinite loop of versioning + publishing) | |
// ignore [ci skip] commits | |
if (githubEvent !== 'push' || | |
response.head_commit.author.username === BOT_NAME || | |
response.head_commit.message.includes('[ci skip]') || | |
response.ref !== 'refs/heads/master' | |
) { | |
return Promise.resolve(); | |
} | |
// get_version and push_changes are helper functions baked into our Docker image | |
const commands = [ | |
'echo "Installing node modules..."', | |
'npm ci', | |
// Determine next version | |
'increment=$(get_version)', | |
// Create versioned commit; publish package; push versioned commit & tag | |
'echo "Bumping version (type: $increment), publishing, and pushing..."', | |
'npm version $increment', | |
'npm publish', | |
'push_changes' | |
]; | |
// Run the semver utility in our custom docker image | |
return spawnDockerTask({ | |
GIT_REPO: response.repository.clone_url, | |
GIT_BRANCH: response.ref, | |
DOCKER_COMMANDS: commands.join('&&') | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment