👏 First off, thank you for taking the time to contribute. 👏
- Fork the repository
- Create a new branch
- Commit your changes
- Create a pull request against the
main
branch
auto-me-bot was created around the concept of handlers and config types.
A config type is the type of GitHub event, i.e. pr, a handler represents an operation supported for a config type.
At the time of writing this, we have handlers only for the pr config type, exemplified best in the configuration YAML:
pr:
conventionalCommits:
conventionalTitle:
lifecycleLabels:
signedCommits:
tasksList:
npm install
install all dependenciesnpm test
run the unit tests and verify code coveragenpm run tests
run the tests with no code coverage verificationnpm run tests:rep
run the tests with no code coverage verification and create unit-tests-result.jsonnpm run lint
lint the project
All handlers are located in src/handlers/.
Handlers MUST export 2 functions (snippets source is the pr-conventional-title handler):
A match function that will be used for matching incoming events, it takes probot's context and expected to return a boolean indicating whether or not the handler can handle the current request, typically based on the event type and supported actions:
module.exports.match = function(context) {
let event = 'pull_request';
let actions = ['opened', 'edited'];
return event in context.payload ? actions.includes(context.payload.action) : false;
}
A run function that will be used for handling a request, it will be invoked only if the aforementioned match function returns true, it takes probot's context, the configuration for handler, and an ISO8601 timestamp marking the start timestamp of the handler run:
Note that config contains the running handler configuration only and nothing above it, so other handlers configuration will not available.
module.exports.run = async function(context, config, startedAt) {
// ...
}
For pull requests, the run function is expected to create a check-run right off its invocation, and mark its status as in_progress:
module.exports.run = async function(context, config, startedAt) {
let checkRun = await context.octokit.checks.create(context.repo({
head_sha: context.payload.pull_request.head.sha,
name: CHECK_NAME,
details_url: BOT_CHECK_URL,
started_at: startedAt,
status: 'in_progress'
}));
// ...
}
The run function, is also expected, as a final stage, to update the previously created check-run, and mark its status as completed, use the conclusion and output keys to relay the check-run result:
module.exports.run = async function(context, config, startedAt) {
let checkRun = await context.octokit.checks.create(context.repo({
head_sha: context.payload.pull_request.head.sha,
name: CHECK_NAME,
details_url: BOT_CHECK_URL,
started_at: startedAt,
status: 'in_progress'
}));
// HANDLER OPERATIONS GOES HERE
await context.octokit.checks.update(context.repo({
check_run_id: checkRun.data.id,
name: CHECK_NAME,
details_url: BOT_CHECK_URL,
started_at: startedAt,
status: 'completed',
completed_at: new Date().toISOString(),
conclusion: 'success',
output: {
title: 'Nice!',
summary: 'Good job, the PR title is conventional'
}
}));
}
All handler unit tests are located in tests/handlers/, test the match and run functions individually, you can inject fakes and stubs into these and verify their behavior.
Take note of pr-conventional-title test cases which can be used as a template for future test cases as it's quite short, simple, and has full coverage.
NOTE: registering handlers requires modifying existing code, the snippets in this section are meant to help you get around the code, and to be used as boiler-plate code.
Registration of new handler is done in src/auto-me-bot.js.
Add an import for the new handler, look for the CONFIG_SPEC constant, add your configuration key, and point it the imported handler:
const CONFIG_SPEC = Object.freeze({
pr: {
conventionalCommits: prConventionalCommitsHandler,
conventionalTitle: prConventionalTitleHandler,
lifecycleLabels: prLifecycleLabelsHandler,
signedCommits: prSignedCommitsHandler,
tasksList: prTasksListHandler,
}
});
Handlers registration is already tested, you only need to instruct it to also include the new handler when doing invocation testing in 3 simple steps, all done in tests/auto-me-bot.test.js.
Look for the beforeEach
function, instantiate your stub and create the patch, i.e.:
// patch the conventionalTitle handler's run function to a stub
conventionalTitleHandlerStub = sinon.stub();
let conventionalTitleHandlerPatch = {
match: require('../src/handlers/pr-conventional-title').match,
run: conventionalTitleHandlerStub
};
Look for the allHandlers list variable, add the new handler to this list:
// all handlers should be listed here for testing purposes
allHandlers = [
conventionalCommitsHandlerStub,
conventionalTitleHandlerStub,
lifecycleLabelsHandlerStub,
signedCommitsHandlerStub,
tasksListHandlerStub,
];
Look for the patchedConfigSpec object and add the handler's configuration key pointing to the patch you created:
// create a patched config spec for injecting the patched handlers into the application
patchedConfigSpec = {
pr: {
conventionalCommits: conventionalCommitsHandlerPatch,
conventionalTitle: conventionalTitleHandlerPatch,
lifecycleLabels: lifecycleLabelHandlerPatch,
signedCommits: signedCommitsHandlerPatch,
tasksList: tasksListHandlerPatch,
}
};
If you need to add extra events/actions for triggering your handler, this is done with ON_EVENTS constant in src/auto-me-bot.js:
const ON_EVENTS = Object.freeze([
'pull_request.opened',
'pull_request.edited',
'pull_request.synchronize',
'pull_request.closed',
'pull_request.ready_for_review',
'pull_request.reopened',
'pull_request_review.submitted',
'pull_request_review.edited',
'pull_request_review.dismissed',
]);
Note that adding events also requires updating the running application settings and requesting existing users approval, please contact the maintainers if this is required.
The documentation is built with Python's MkDocs. The sources are in docs/, and the configuration file is mkdocs.yml.
Useful commands:
pip install -r requirements.txt
install dependencies required for building/serving the documentation sitemkdocs build
build the documentation site in a folder named site (gitignored)mkdocs serve
serve the documentation site locally while watching the sources and auto loading for modifications
Using venv is highly recommended.