зеркало из https://github.com/microsoft/AzureTRE.git
Require commit SHA for /test and /test-extended on external PRs (#1731)
* Add `/test <sha` command Add test helpers to improve test readability * Make command tests more consistent * Add comment on running test, update run-test.sh * Extract /test command handling to separate function * Add SHA validation for external PRs for /test-extended * Update maintainers.md with /test sha requirements * Add tests for non-mergeable PRs * Handle extra spaces between /test and sha When copy/pasting SHA in UI, it's easy to add an extra space This change makes the pr-bot tolerant of that * PR feedback
This commit is contained in:
Родитель
143877440d
Коммит
87c73d2424
|
@ -1,3 +1,9 @@
|
|||
//
|
||||
// This file contains functions that are used in GitHub workflows
|
||||
// (e.g. to implement the pr-bot for running tests
|
||||
// There are tests for this code in build.test.js
|
||||
// These tests can be run from the dev container using the run-tests.sh script
|
||||
//
|
||||
const { createHash } = require('crypto');
|
||||
|
||||
async function getCommandFromComment({ core, context, github }) {
|
||||
|
@ -9,6 +15,7 @@ async function getCommandFromComment({ core, context, github }) {
|
|||
const prNumber = context.payload.issue.number;
|
||||
const commentLink = context.payload.comment.html_url;
|
||||
const runId = context.runId;
|
||||
const prAuthorUsername = context.payload.issue.user.login;
|
||||
|
||||
// only allow actions for users with write access
|
||||
if (!await userHasWriteAccessToRepo({ core, github }, commentUsername, repoOwner, repoName)) {
|
||||
|
@ -19,6 +26,7 @@ async function getCommandFromComment({ core, context, github }) {
|
|||
issue_number: prNumber,
|
||||
body: `Sorry, @${commentUsername}, only users with write access to the repo can run pr-bot commands.`
|
||||
});
|
||||
logAndSetOutput(core, "command", "none");
|
||||
return "none";
|
||||
}
|
||||
|
||||
|
@ -57,33 +65,40 @@ async function getCommandFromComment({ core, context, github }) {
|
|||
let command = "none";
|
||||
const trimmedFirstLine = commentFirstLine.trim();
|
||||
if (trimmedFirstLine[0] === "/") {
|
||||
switch (trimmedFirstLine) {
|
||||
const parts = trimmedFirstLine.split(' ').filter(p=>p !== '');
|
||||
const commandText = parts[0];
|
||||
switch (commandText) {
|
||||
case "/test":
|
||||
{
|
||||
if (gotNonDocChanges) {
|
||||
command = "run-tests";
|
||||
const message = `:runner: Running tests: https://github.com/${repoFullName}/actions/runs/${runId} (with refid \`${prRefId}\`)`;
|
||||
await addActionComment({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, message);
|
||||
} else {
|
||||
// Docs only changes don't run tests with secrets so don't require the check for
|
||||
// whether a SHA needs to be supplied
|
||||
if (!gotNonDocChanges) {
|
||||
command = "test-force-approve";
|
||||
const message = `:white_check_mark: PR only contains docs changes - marking tests as complete`;
|
||||
await addActionComment({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, message);
|
||||
break;
|
||||
}
|
||||
|
||||
const runTests = await handleTestCommand({ core, github }, parts, "tests", runId, { number: prNumber, authorUsername: prAuthorUsername, repoOwner, repoName, headSha: prHeadSha, refId: prRefId, details: pr }, { username: commentUsername, link: commentLink });
|
||||
if (runTests) {
|
||||
command = "run-tests";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "/test-extended":
|
||||
{
|
||||
command = "run-tests-extended";
|
||||
const message = `:runner: Running extended tests: https://github.com/${repoFullName}/actions/runs/${runId} (with refid \`${prRefId}\`)`;
|
||||
await addActionComment({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, message);
|
||||
const runTests = await handleTestCommand({ core, github }, parts, "extended tests", runId, { number: prNumber, authorUsername: prAuthorUsername, repoOwner, repoName, headSha: prHeadSha, refId: prRefId, details: pr }, { username: commentUsername, link: commentLink });
|
||||
if (runTests) {
|
||||
command = "run-tests-extended";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "/test-force-approve":
|
||||
{
|
||||
command = "test-force-approve";
|
||||
const message = `:white_check_mark: Marking tests as complete (for commit ${prHeadSha})`;
|
||||
const message = `:white_check_mark: Marking tests as complete (for commit ${prHeadSha})`;
|
||||
await addActionComment({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, message);
|
||||
break;
|
||||
}
|
||||
|
@ -98,8 +113,8 @@ async function getCommandFromComment({ core, context, github }) {
|
|||
break;
|
||||
|
||||
default:
|
||||
core.warning(`'${trimmedFirstLine}' not recognised as a valid command`);
|
||||
await showHelp({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, trimmedFirstLine);
|
||||
core.warning(`'${commandText}' not recognised as a valid command`);
|
||||
await showHelp({ github }, repoOwner, repoName, prNumber, commentUsername, commentLink, commandText);
|
||||
command = "none";
|
||||
break;
|
||||
}
|
||||
|
@ -108,6 +123,47 @@ async function getCommandFromComment({ core, context, github }) {
|
|||
return command;
|
||||
}
|
||||
|
||||
async function handleTestCommand({ core, github }, commandParts, testDescription, runId, pr, comment) {
|
||||
|
||||
if (!pr.details.mergeable) {
|
||||
// Since we use the potential merge commit as the ref to checkout, we can only run if there is such a commit
|
||||
// If the PR isn't mergeable, add a comment indicating that the merge issue needs addressing
|
||||
const message = `:warning: Cannot run tests as PR is not mergeable. Ensure that the PR is open and doesn't have any conflicts.`;
|
||||
await addActionComment({ github }, pr.repoOwner, pr.repoName, pr.number, comment.username, comment.link, message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if this is an external PR (i.e. author not a maintainer)
|
||||
// if so, need to specify the SHA that has been vetted and check that it matches
|
||||
// the latest head SHA for the PR
|
||||
const command = commandParts[0]
|
||||
const prAuthorHasWriteAccess = await userHasWriteAccessToRepo({ core, github }, pr.authorUsername, pr.repoOwner, pr.repoName);
|
||||
const externalPr = !prAuthorHasWriteAccess;
|
||||
if (externalPr) {
|
||||
if (commandParts.length === 1) {
|
||||
const message = `:warning: When using \`${command}\` on external PRs, the SHA of the checked commit must be specified`;
|
||||
await addActionComment({ github }, pr.repoOwner, pr.repoName, pr.number, comment.username, comment.link, message);
|
||||
return false;
|
||||
}
|
||||
const commentSha = commandParts[1];
|
||||
if (commentSha.length < 7) {
|
||||
const message = `:warning: When specifying a commit SHA it must be at least 7 characters (received \`${commentSha}\`)`;
|
||||
await addActionComment({ github }, pr.repoOwner, pr.repoName, pr.number, comment.username, comment.link, message);
|
||||
return false;
|
||||
}
|
||||
if (!pr.headSha.startsWith(commentSha)) {
|
||||
const message = `:warning: The specified SHA \`${commentSha}\` is not the latest commit on the PR. Please validate the latest commit and re-run \`/test\``;
|
||||
await addActionComment({ github }, pr.repoOwner, pr.repoName, pr.number, comment.username, comment.link, message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const message = `:runner: Running ${testDescription}: https://github.com/${pr.repoOwner}/${pr.repoName}/actions/runs/${runId} (with refid \`${pr.refId}\`)`;
|
||||
await addActionComment({ github }, pr.repoOwner, pr.repoName, pr.number, comment.username, comment.link, message);
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
async function prContainsNonDocChanges(github, repoOwner, repoName, prNumber) {
|
||||
const prFilesResponse = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner: repoOwner,
|
||||
|
@ -177,7 +233,7 @@ You can use the following commands:
|
|||
/test-destroy-env - delete the validation environment for a PR (e.g. to enable testing a deployment from a clean start after previous tests)
|
||||
/help - show this help`;
|
||||
|
||||
await addActionComment({github}, repoOwner, repoName, prNumber, commentUser, commentLink, body);
|
||||
await addActionComment({ github }, repoOwner, repoName, prNumber, commentUser, commentLink, body);
|
||||
|
||||
}
|
||||
async function addActionComment({ github }, repoOwner, repoName, prNumber, commentUser, commentLink, message) {
|
||||
|
|
|
@ -1,117 +1,10 @@
|
|||
const { getCommandFromComment, labelAsExternalIfAuthorDoesNotHaveWriteAccess } = require('./build.js')
|
||||
const { createGitHubContext, PR_NUMBER, outputFor, toHaveComment } = require('./test-helpers.js')
|
||||
|
||||
const PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES = 123;
|
||||
const PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES = 125;
|
||||
const PR_NUMBER_FORK_NON_DOCS_CHANGES = 456;
|
||||
expect.extend({
|
||||
toHaveComment
|
||||
})
|
||||
|
||||
function createGitHubContext() {
|
||||
mockGithubRestIssuesAddLabels = jest.fn();
|
||||
mockGithubRestIssuesCreateComment = jest.fn();
|
||||
mockGithubRestPullsListFiles = jest.fn();
|
||||
mockCoreSetOutput = jest.fn();
|
||||
mockCoreNotice = jest.fn();
|
||||
mockCoreInfo = jest.fn();
|
||||
mockCoreWarning = jest.fn();
|
||||
mockCoreError = jest.fn();
|
||||
return {
|
||||
mockGithubRestIssuesAddLabels,
|
||||
mockGithubRestIssuesCreateComment,
|
||||
mockCoreSetOutput,
|
||||
mockCoreInfo,
|
||||
mockCoreNotice,
|
||||
mockCoreWarning,
|
||||
mockCoreError,
|
||||
core: {
|
||||
setOutput: mockCoreSetOutput,
|
||||
info: mockCoreInfo,
|
||||
notice: mockCoreNotice,
|
||||
warning: mockCoreWarning,
|
||||
error: mockCoreError,
|
||||
},
|
||||
github: {
|
||||
paginate: (func, params) => {
|
||||
// thin fake for paginate -> faked function being paginated should return a single page of data!
|
||||
// if you're getting a `func is not a function` error then check that a func is being passed in
|
||||
return func(params);
|
||||
},
|
||||
request: async (route, data) => {
|
||||
if (route === 'GET /repos/{owner}/{repo}/collaborators/{username}') {
|
||||
if (data.username === "admin") {
|
||||
return {
|
||||
status: 204
|
||||
};
|
||||
} else {
|
||||
throw {
|
||||
status: 404,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
rest: {
|
||||
issues: {
|
||||
addLabels: mockGithubRestIssuesAddLabels,
|
||||
createComment: mockGithubRestIssuesCreateComment,
|
||||
},
|
||||
pulls: {
|
||||
get: async (params) => {
|
||||
if (params.owner === 'someOwner'
|
||||
&& params.repo === 'someRepo') {
|
||||
switch (params.pull_number) {
|
||||
case PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES: // PR from the upstream repo with non-docs changes
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '0123456789',
|
||||
repo: { full_name: 'someOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '123456789a',
|
||||
},
|
||||
}
|
||||
case PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES: // PR from the upstream repo with docs-only changes
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '0123456789',
|
||||
repo: { full_name: 'someOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '123456789a',
|
||||
},
|
||||
}
|
||||
case PR_NUMBER_FORK_NON_DOCS_CHANGES: // PR from a forked repo
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '23456789ab',
|
||||
repo: { full_name: 'anotherOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '3456789abc',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
throw 'Unhandled params in fake pulls.get: ' + JSON.stringify(params)
|
||||
},
|
||||
listFiles: async (params) => {
|
||||
if (params.owner === 'someOwner'
|
||||
&& params.repo === 'someRepo') {
|
||||
switch (params.pull_number) {
|
||||
case PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES: // PR from the upstream repo with non-docs changes
|
||||
case PR_NUMBER_FORK_NON_DOCS_CHANGES: // PR from a forked repo
|
||||
return [{ filename: 'test.py' }, { filename: 'test.md' }];
|
||||
case PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES: // PR from the upstream repo with docs-only changes
|
||||
return [{ filename: 'mkdocs.yml' }, { filename: 'test.md' }, { filename: 'docs/README.md' }];
|
||||
}
|
||||
}
|
||||
throw 'Unhandled params in fake pulls.listFiles: ' + JSON.stringify(params)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
describe('getCommandFromComment', () => {
|
||||
|
||||
|
@ -123,12 +16,15 @@ describe('getCommandFromComment', () => {
|
|||
({ core, github, mockCoreSetOutput, mockGithubRestIssuesCreateComment } = createGitHubContext());
|
||||
});
|
||||
|
||||
function createCommentContext({ username, pullRequestNumber, body }) {
|
||||
function createCommentContext({ username, pullRequestNumber, body, authorUsername }) {
|
||||
if (!username) {
|
||||
username = 'admin'; // most tests will assume admin (i.e. user can run commands)
|
||||
}
|
||||
if (!authorUsername) {
|
||||
authorUsername = 'admin'; // most tests will assume admin (i.e. user not external)
|
||||
}
|
||||
if (!pullRequestNumber) {
|
||||
pullRequestNumber = PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES;
|
||||
pullRequestNumber = PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES;
|
||||
}
|
||||
if (!body) {
|
||||
body = "nothing to see here";
|
||||
|
@ -144,6 +40,9 @@ describe('getCommandFromComment', () => {
|
|||
},
|
||||
issue: {
|
||||
number: pullRequestNumber,
|
||||
user: {
|
||||
login: authorUsername,
|
||||
},
|
||||
},
|
||||
repository: {
|
||||
full_name: 'someOwner/someRepo'
|
||||
|
@ -160,23 +59,22 @@ describe('getCommandFromComment', () => {
|
|||
body: '/test',
|
||||
});
|
||||
const command = await getCommandFromComment({ core, context, github });
|
||||
expect(command).toBe('none');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add a comment indicating that the user cannot run commands`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'non-contributor',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toBe('Sorry, @non-contributor, only users with write access to the repo can run pr-bot commands.');
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Sorry, @non-contributor, only users with write access to the repo can run pr-bot commands./
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -188,184 +86,489 @@ describe('getCommandFromComment', () => {
|
|||
body: 'foo',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'none');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
|
||||
describe('and single line comments', () => {
|
||||
|
||||
describe(`for '/test' for PR with non-docs changes`, () => {
|
||||
describe(`for '/test' for non-external PR with non-docs changes`, () => {
|
||||
test(`should set command to 'run-tests'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'run-tests');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests');
|
||||
});
|
||||
|
||||
test(`should set nonDocsChanges to 'true'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('nonDocsChanges', 'true');
|
||||
expect(outputFor(mockCoreSetOutput, 'nonDocsChanges')).toBe('true');
|
||||
});
|
||||
|
||||
test(`should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/Running tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `cbce50da`\)/);
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Running tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `cbce50da`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe(`for '/test' for PR with docs-only changes`, () => {
|
||||
describe(`for '/test' for non-external PR with docs-only changes`, () => {
|
||||
test(`should set command to 'test-force-approve'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'test-force-approve');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('test-force-approve');
|
||||
});
|
||||
|
||||
test(`should set nonDocsChanges to 'false'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('nonDocsChanges', 'false');
|
||||
expect(outputFor(mockCoreSetOutput, 'nonDocsChanges')).toBe('false');
|
||||
});
|
||||
|
||||
test(`should add comment with for skipping checks`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_DOCS_ONLY_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/PR only contains docs changes - marking tests as complete/);
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES,
|
||||
bodyMatcher: /PR only contains docs changes - marking tests as complete/,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`for '/test' for non-mergeable PR`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_MERGEABLE,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with for skipping checks`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_MERGEABLE,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_MERGEABLE,
|
||||
bodyMatcher: /Cannot run tests as PR is not mergeable. Ensure that the PR is open and doesn't have any conflicts./,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`for '/test' for external PR (i.e. without commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt to specify SHA`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /When using `\/test` on external PRs, the SHA of the checked commit must be specified/,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`for '/test 00000000' for external PR (i.e. with non-latest commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 00000000',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt that the SHA is out-dated`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 00000000',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /The specified SHA `00000000` is not the latest commit on the PR. Please validate the latest commit and re-run `\/test`/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
test(`for '/test-extended' should set command to 'run-tests-extended'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
describe(`for '/test 234567' for external PR (i.e. with insufficiently long commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 234567',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt that the SHA is out-dated`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 234567',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /When specifying a commit SHA it must be at least 7 characters \(received `234567`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test 2345678' for external PR (i.e. with latest commit SHA specified)`, () => {
|
||||
test(`should set command to 'run-tests'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests');
|
||||
});
|
||||
|
||||
test(`should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Running tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `6db070b1`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test 2345678' for external PR (i.e. with latest commit SHA specified but extra space after test)`, () => {
|
||||
test(`should set command to 'run-tests'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests');
|
||||
});
|
||||
|
||||
test(`should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Running tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `6db070b1`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test-extended'`, () => {
|
||||
test(`should set command to 'run-tests-extended'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests-extended');
|
||||
});
|
||||
|
||||
test(`should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Running extended tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `cbce50da`\)/,
|
||||
});
|
||||
});
|
||||
const command = await getCommandFromComment({ core, context, github });
|
||||
expect(command).toBe('run-tests-extended');
|
||||
});
|
||||
|
||||
test(`for '/test-extended' should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
describe(`for '/test-extended' for external PR (i.e. without commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt to specify SHA`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /When using `\/test-extended` on external PRs, the SHA of the checked commit must be specified/,
|
||||
});
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/Running extended tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `cbce50da`\)/);
|
||||
});
|
||||
|
||||
test(`for '/test-force-approve' should set command to 'test-force-approve'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-force-approve',
|
||||
describe(`for '/test-extended 00000000' for external PR (i.e. with non-latest commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 00000000',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt that the SHA is out-dated`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 00000000',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /The specified SHA `00000000` is not the latest commit on the PR. Please validate the latest commit and re-run `\/test`/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test-extended 234567' for external PR (i.e. with insufficiently long commit SHA specified)`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 234567',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
|
||||
test(`should add comment with prompt that the SHA is out-dated`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 234567',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /When specifying a commit SHA it must be at least 7 characters \(received `234567`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test-extended 2345678' for external PR (i.e. with latest commit SHA specified)`, () => {
|
||||
test(`should set command to 'run-tests-extended'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests-extended');
|
||||
});
|
||||
|
||||
test(`should add comment with run link`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-extended 2345678',
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
authorUsername: 'non-contributor',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.FORK_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Running extended tests: https:\/\/github.com\/someOwner\/someRepo\/actions\/runs\/11112222 \(with refid `6db070b1`\)/,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe(`for '/test-force-approve'`, () => {
|
||||
test(`should set command to 'test-force-approve'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-force-approve',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('test-force-approve');
|
||||
});
|
||||
|
||||
test(`should add comment`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-force-approve',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Marking tests as complete \(for commit 0123456789\)/,
|
||||
});
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'test-force-approve');
|
||||
});
|
||||
|
||||
test(`for '/test-force-approve' should add comment`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-force-approve',
|
||||
describe(`for '/test-destroy-env'`, () => {
|
||||
test(`should set command to 'test-destroy-env'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-destroy-env',
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('test-destroy-env');
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/Marking tests as complete \(for commit 0123456789\)/);
|
||||
});
|
||||
|
||||
test(`for '/test-destroy-env' should set command to 'test-destroy-env'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/test-destroy-env',
|
||||
describe(`for '/help'`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/help',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
test(`should add help comment`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/help',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /Hello!\n\nYou can use the following commands:/,
|
||||
});
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'test-destroy-env');
|
||||
});
|
||||
|
||||
test(`for '/help' should add help comment and set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/help',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
describe(`for '/not-a-command'`, () => {
|
||||
test(`should set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/not-a-command',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'none');
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/Hello!\n\nYou can use the following commands:/);
|
||||
});
|
||||
|
||||
test(`for '/not-a-command' should add help comment and set command to 'none'`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/not-a-command',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
test(`should add help comment`, async () => {
|
||||
const context = createCommentContext({
|
||||
username: 'admin',
|
||||
body: '/not-a-command',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockGithubRestIssuesCreateComment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
bodyMatcher: /`\/not-a-command` is not recognised as a valid command.\n\nYou can use the following commands:/,
|
||||
});
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'none');
|
||||
expect(mockGithubRestIssuesCreateComment.mock.calls.length).toBe(1);
|
||||
const createCommentCall = mockGithubRestIssuesCreateComment.mock.calls[0];
|
||||
const createCommentParam = createCommentCall[0];
|
||||
expect(createCommentParam.owner).toBe("someOwner");
|
||||
expect(createCommentParam.repo).toBe("someRepo");
|
||||
expect(createCommentParam.issue_number).toBe(PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES);
|
||||
expect(createCommentParam.body).toMatch(/`\/not-a-command` is not recognised as a valid command.\n\nYou can use the following commands:/);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('and multi-line comments', () => {
|
||||
test(`when first line of comment is '/test' should set command to 'run-tests'`, async () => {
|
||||
const context = createCommentContext({
|
||||
|
@ -375,7 +578,7 @@ Other comment content
|
|||
goes here`,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'run-tests');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('run-tests');
|
||||
});
|
||||
|
||||
test(`when comment doesn't start with '/' (even if later lines contain '/test') should set command to 'none' `, async () => {
|
||||
|
@ -387,113 +590,110 @@ Other comment content
|
|||
goes here`,
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('command', 'none');
|
||||
expect(outputFor(mockCoreSetOutput, 'command')).toBe('none');
|
||||
});
|
||||
});
|
||||
|
||||
describe('PR context', () => {
|
||||
test('should set prRef output', async () => {
|
||||
// prRef should be set to the SHA for the potentialMergeCommit for the PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'prRef')).toBe('123456789a');
|
||||
});
|
||||
|
||||
test('should set prRefId output', async () => {
|
||||
// Using a PR number of 123 should give a refid of 'cbce50da'
|
||||
// Based on running `echo "refs/pull/123/merge" | shasum | cut -c1-8` (as per the original bash scripts)
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'prRefId')).toBe('cbce50da');
|
||||
});
|
||||
|
||||
test('should not set branchRefId output for PR from forked repo', async () => {
|
||||
// Using PR 456 which is faked as a PR from a fork
|
||||
// Since branch-based environments are only for upstream branches, the branchRefId
|
||||
// output should not be set for this PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER.FORK_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'branchRefId')).toBe(null);
|
||||
});
|
||||
|
||||
test('should set branchRefId for PR from upstream repo', async () => {
|
||||
// Using PR 123 which is faked as a PR from the upstream repo
|
||||
// The Using a PR number of 123 should give a refid of '71f7c907'
|
||||
// Based on running `echo "refs/heads/pr-head-ref" | shasum | cut -c1-8` (as per the original bash scripts)
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'branchRefId')).toBe('71f7c907');
|
||||
});
|
||||
|
||||
test('should set prHeadSha output', async () => {
|
||||
// prHeadSha should be the SHA for the head commit for the PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(outputFor(mockCoreSetOutput, 'prHeadSha')).toBe('0123456789');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
describe('PR context', () => {
|
||||
test('should set prRef output', async () => {
|
||||
// prRef should be set to the SHA for the potentialMergeCommit for the PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('prRef', '123456789a');
|
||||
describe('labelAsExternalIfAuthorDoesNotHaveWriteAccess', () => {
|
||||
|
||||
var core;
|
||||
var github;
|
||||
var mockGithubRestIssuesAddLabels;
|
||||
beforeEach(() => {
|
||||
({ core, github, mockGithubRestIssuesAddLabels } = createGitHubContext());
|
||||
});
|
||||
|
||||
test('should set prRefId output', async () => {
|
||||
// Using a PR number of 123 should give a refid of 'cbce50da'
|
||||
// Based on running `echo "refs/pull/123/merge" | shasum | cut -c1-8` (as per the original bash scripts)
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('prRefId', 'cbce50da');
|
||||
expect(mockCoreSetOutput.mock.calls.some(c => c[0] == 'prRefId')).toBe(true);
|
||||
});
|
||||
|
||||
test('should not set branchRefId output for PR from forked repo', async () => {
|
||||
// Using PR 456 which is faked as a PR from a fork
|
||||
// Since branch-based environments are only for upstream branches, the branchRefId
|
||||
// output should not be set for this PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER_FORK_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput.mock.calls.some(c => c[0] == 'branchRefId')).toBe(false);
|
||||
});
|
||||
|
||||
test('should set branchRefId for PR from upstream repo', async () => {
|
||||
// Using PR 123 which is faked as a PR from the upstream repo
|
||||
// The Using a PR number of 123 should give a refid of '71f7c907'
|
||||
// Based on running `echo "refs/heads/pr-head-ref" | shasum | cut -c1-8` (as per the original bash scripts)
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('branchRefId', '71f7c907');
|
||||
});
|
||||
|
||||
test('should set prHeadSha output', async () => {
|
||||
// prHeadSha should be the SHA for the head commit for the PR
|
||||
const context = createCommentContext({
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES
|
||||
});
|
||||
await getCommandFromComment({ core, context, github });
|
||||
expect(mockCoreSetOutput).toHaveBeenCalledWith('prHeadSha', '0123456789');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
describe('labelAsExternalIfAuthorDoesNotHaveWriteAccess', () => {
|
||||
|
||||
var core;
|
||||
var github;
|
||||
var mockGithubRestIssuesAddLabels;
|
||||
beforeEach(() => {
|
||||
({ core, github, mockGithubRestIssuesAddLabels } = createGitHubContext());
|
||||
});
|
||||
|
||||
function createPullRequestContext({ username, pullRequestNumber }) {
|
||||
return {
|
||||
payload: {
|
||||
pull_request: {
|
||||
user: {
|
||||
login: username,
|
||||
function createPullRequestContext({ username, pullRequestNumber }) {
|
||||
return {
|
||||
payload: {
|
||||
pull_request: {
|
||||
user: {
|
||||
login: username,
|
||||
},
|
||||
number: pullRequestNumber,
|
||||
},
|
||||
number: pullRequestNumber,
|
||||
repository: {
|
||||
full_name: 'someOwner/SomeRepo'
|
||||
}
|
||||
},
|
||||
repository: {
|
||||
full_name: 'someOwner/SomeRepo'
|
||||
}
|
||||
},
|
||||
repo: {
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo'
|
||||
},
|
||||
};
|
||||
}
|
||||
repo: {
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo'
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test(`should apply the 'external' label for non-contributor author`, async () => {
|
||||
const context = createPullRequestContext({
|
||||
username: 'non-contributor',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
test(`should apply the 'external' label for non-contributor author`, async () => {
|
||||
const context = createPullRequestContext({
|
||||
username: 'non-contributor',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await labelAsExternalIfAuthorDoesNotHaveWriteAccess({ core, context, github });
|
||||
expect(mockGithubRestIssuesAddLabels).toHaveBeenCalled(); // should set the label for non-contributor
|
||||
});
|
||||
await labelAsExternalIfAuthorDoesNotHaveWriteAccess({ core, context, github });
|
||||
expect(mockGithubRestIssuesAddLabels).toHaveBeenCalled(); // should set the label for non-contributor
|
||||
});
|
||||
|
||||
test(`should return not apply the 'external' label for contributor author`, async () => {
|
||||
const context = createPullRequestContext({
|
||||
username: 'admin',
|
||||
pullRequestNumber: PR_NUMBER_UPSTREAM_NON_DOCS_CHANGES,
|
||||
test(`should return not apply the 'external' label for contributor author`, async () => {
|
||||
const context = createPullRequestContext({
|
||||
username: 'admin',
|
||||
pullRequestNumber: PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES,
|
||||
});
|
||||
await labelAsExternalIfAuthorDoesNotHaveWriteAccess({ core, context, github });
|
||||
expect(mockGithubRestIssuesAddLabels).toHaveBeenCalledTimes(0); // shouldn't set the label for contributor
|
||||
});
|
||||
await labelAsExternalIfAuthorDoesNotHaveWriteAccess({ core, context, github });
|
||||
expect(mockGithubRestIssuesAddLabels).toHaveBeenCalledTimes(0); // shouldn't set the label for contributor
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"jest": "^27.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
"test": "jest --verbose",
|
||||
"test-watch": "jest --watchAll --verbose"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,49 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
if [[ $(command -v node > /dev/null; echo $?) == 0 ]]; then
|
||||
echo "node already installed"
|
||||
else
|
||||
echo "node not found - installing..."
|
||||
"$DIR/install-node.sh"
|
||||
function usage() {
|
||||
cat <<USAGE
|
||||
|
||||
This script runs the GitHub action linter and unit tests for build.js
|
||||
Dependencies (e.g. node, actionlint) will be installed if not present
|
||||
|
||||
Usage: $0 [--watch]
|
||||
|
||||
Options:
|
||||
--watch Run tests in watch mode
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
watch_tests=false
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
--watch)
|
||||
watch_tests=true
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected argument: '$1'"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -z "$2" ]]; then
|
||||
# if no more args then stop processing
|
||||
break
|
||||
fi
|
||||
|
||||
shift # remove the current value for `$1` and use the next
|
||||
done
|
||||
test_command="test"
|
||||
if ${watch_tests}
|
||||
then
|
||||
test_command="test-watch"
|
||||
fi
|
||||
|
||||
echo "Running JavaScript build tests..."
|
||||
(cd "$DIR" && yarn test)
|
||||
|
||||
script_temp_dir="$DIR/script_temp"
|
||||
if [[ -x "$script_temp_dir/actionlint" ]]; then
|
||||
|
@ -26,4 +57,16 @@ else
|
|||
fi
|
||||
echo "Running actionlint..."
|
||||
"$script_temp_dir/actionlint"
|
||||
|
||||
|
||||
if [[ $(command -v node > /dev/null; echo $?) == 0 ]]; then
|
||||
echo "node already installed"
|
||||
else
|
||||
echo "node not found - installing..."
|
||||
"$DIR/install-node.sh"
|
||||
fi
|
||||
|
||||
echo "Running JavaScript build tests..."
|
||||
(cd "$DIR" && yarn install && yarn "$test_command")
|
||||
|
||||
echo "Tests complete"
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
function lastCallFor(mock, matcher) {
|
||||
const matches = mock.mock.calls.filter(matcher);
|
||||
const lastMatchIndex = matches.length - 1;
|
||||
if (lastMatchIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return matches[lastMatchIndex];
|
||||
}
|
||||
|
||||
// outputFor returns the last call to mock with the specified key
|
||||
function outputFor(mock, key) {
|
||||
// get last call for mock with first arg matching the key
|
||||
const lastCall = lastCallFor(mock, c => c[0] === key);
|
||||
if (lastCall) {
|
||||
// return second arg (output value)
|
||||
return lastCall[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function toHaveComment(received, { owner, repo, issue_number, bodyMatcher }) {
|
||||
const commentsForIssue = received.mock.calls
|
||||
.map(c => c[0])
|
||||
.filter(arg => arg.owner === owner && arg.repo === repo && arg.issue_number === issue_number);
|
||||
if (commentsForIssue.length === 0) {
|
||||
return { message: () => `No comments found for issue ${JSON.stringify({ owner, repo, issue_number })}`, pass: false };
|
||||
}
|
||||
|
||||
const gotMatchingBody = commentsForIssue.some(c => bodyMatcher.exec(c.body) !== null)
|
||||
if (!gotMatchingBody) {
|
||||
const lastComment = commentsForIssue[commentsForIssue.length - 1]
|
||||
return { message: () => `No comment found with body matching ${bodyMatcher.toString()}. Last comment for issue: '${lastComment.body}'`, pass: false };
|
||||
}
|
||||
return { message: '', pass: true };
|
||||
}
|
||||
|
||||
const PR_NUMBER = {
|
||||
UPSTREAM_NON_DOCS_CHANGES: 123,
|
||||
UPSTREAM_DOCS_ONLY_CHANGES: 125,
|
||||
FORK_NON_DOCS_CHANGES: 456,
|
||||
UPSTREAM_NON_MERGEABLE: 600,
|
||||
}
|
||||
|
||||
function createGitHubContext() {
|
||||
mockGithubRestIssuesAddLabels = jest.fn();
|
||||
mockGithubRestIssuesCreateComment = jest.fn();
|
||||
mockGithubRestPullsListFiles = jest.fn();
|
||||
mockCoreSetOutput = jest.fn();
|
||||
mockCoreNotice = jest.fn();
|
||||
mockCoreInfo = jest.fn();
|
||||
mockCoreWarning = jest.fn();
|
||||
mockCoreError = jest.fn();
|
||||
return {
|
||||
mockGithubRestIssuesAddLabels,
|
||||
mockGithubRestIssuesCreateComment,
|
||||
mockCoreSetOutput,
|
||||
mockCoreInfo,
|
||||
mockCoreNotice,
|
||||
mockCoreWarning,
|
||||
mockCoreError,
|
||||
core: {
|
||||
setOutput: mockCoreSetOutput,
|
||||
info: mockCoreInfo,
|
||||
notice: mockCoreNotice,
|
||||
warning: mockCoreWarning,
|
||||
error: mockCoreError,
|
||||
},
|
||||
github: {
|
||||
paginate: (func, params) => {
|
||||
// thin fake for paginate -> faked function being paginated should return a single page of data!
|
||||
// if you're getting a `func is not a function` error then check that a func is being passed in
|
||||
return func(params);
|
||||
},
|
||||
request: async (route, data) => {
|
||||
if (route === 'GET /repos/{owner}/{repo}/collaborators/{username}') {
|
||||
if (data.username === "admin") {
|
||||
return {
|
||||
status: 204
|
||||
};
|
||||
} else {
|
||||
throw {
|
||||
status: 404,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
rest: {
|
||||
issues: {
|
||||
addLabels: mockGithubRestIssuesAddLabels,
|
||||
createComment: mockGithubRestIssuesCreateComment,
|
||||
},
|
||||
pulls: {
|
||||
get: async (params) => {
|
||||
if (params.owner === 'someOwner'
|
||||
&& params.repo === 'someRepo') {
|
||||
switch (params.pull_number) {
|
||||
case PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES: // PR from the upstream repo with non-docs changes
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '0123456789',
|
||||
repo: { full_name: 'someOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '123456789a',
|
||||
mergeable: true,
|
||||
},
|
||||
}
|
||||
case PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES: // PR from the upstream repo with docs-only changes
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '0123456789',
|
||||
repo: { full_name: 'someOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '123456789a',
|
||||
mergeable: true,
|
||||
},
|
||||
}
|
||||
case PR_NUMBER.FORK_NON_DOCS_CHANGES: // PR from a forked repo
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '23456789ab',
|
||||
repo: { full_name: 'anotherOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '3456789abc',
|
||||
mergeable: true,
|
||||
},
|
||||
}
|
||||
case PR_NUMBER.UPSTREAM_NON_MERGEABLE: // PR with mergable==false
|
||||
return {
|
||||
data: {
|
||||
head: {
|
||||
ref: 'pr-head-ref',
|
||||
sha: '23456789ab',
|
||||
repo: { full_name: 'anotherOwner/someRepo' },
|
||||
},
|
||||
merge_commit_sha: '3456789abc',
|
||||
mergeable: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
throw 'Unhandled params in fake pulls.get: ' + JSON.stringify(params)
|
||||
},
|
||||
listFiles: async (params) => {
|
||||
if (params.owner === 'someOwner'
|
||||
&& params.repo === 'someRepo') {
|
||||
switch (params.pull_number) {
|
||||
case PR_NUMBER.UPSTREAM_NON_DOCS_CHANGES:
|
||||
case PR_NUMBER.FORK_NON_DOCS_CHANGES:
|
||||
case PR_NUMBER.UPSTREAM_NON_MERGEABLE:
|
||||
return [{ filename: 'test.py' }, { filename: 'test.md' }];
|
||||
|
||||
case PR_NUMBER.UPSTREAM_DOCS_ONLY_CHANGES:
|
||||
return [{ filename: 'mkdocs.yml' }, { filename: 'test.md' }, { filename: 'docs/README.md' }];
|
||||
}
|
||||
}
|
||||
throw 'Unhandled params in fake pulls.listFiles: ' + JSON.stringify(params)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
lastCallFor,
|
||||
outputFor,
|
||||
toHaveComment,
|
||||
createGitHubContext,
|
||||
PR_NUMBER,
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
const { lastCallFor, outputFor, toHaveComment } = require('./test-helpers.js')
|
||||
|
||||
describe('helper tests', () => {
|
||||
|
||||
describe('lastCallFor', () => {
|
||||
var testMock;
|
||||
beforeEach(() => {
|
||||
testMock = jest.fn();
|
||||
});
|
||||
|
||||
test('single call matches', () => {
|
||||
testMock('key', 'value');
|
||||
expect(lastCallFor(testMock, c => c[0] === 'key')[1]).toBe('value');
|
||||
})
|
||||
test('multiple calls matches last value', () => {
|
||||
testMock('key', 'value');
|
||||
testMock('key', 'value2');
|
||||
expect(lastCallFor(testMock, c => c[0] === 'key')[1]).toBe('value2');
|
||||
})
|
||||
})
|
||||
|
||||
describe('outputFor', () => {
|
||||
var setOutput;
|
||||
beforeEach(() => {
|
||||
setOutput = jest.fn();
|
||||
});
|
||||
|
||||
test('no calls returns null', () => {
|
||||
expect(outputFor(setOutput, 'key')).toBe(null);
|
||||
})
|
||||
test('single call matches', () => {
|
||||
setOutput('key', 'value');
|
||||
expect(outputFor(setOutput, 'key')).toBe('value');
|
||||
})
|
||||
test('multiple calls matches last value', () => {
|
||||
setOutput('key', 'value');
|
||||
setOutput('key', 'value2');
|
||||
expect(outputFor(setOutput, 'key')).toBe('value2');
|
||||
})
|
||||
})
|
||||
|
||||
describe('toHaveComment', () => {
|
||||
expect.extend({
|
||||
toHaveComment
|
||||
})
|
||||
|
||||
var add_comment;
|
||||
beforeEach(() => {
|
||||
add_comment = jest.fn();
|
||||
});
|
||||
|
||||
test('no calls returns false', () => {
|
||||
expect(add_comment).not.toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
bodyMatcher: /test/,
|
||||
});
|
||||
});
|
||||
|
||||
test('single matching call returns true', () => {
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
expect(add_comment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
bodyMatcher: /test/,
|
||||
});
|
||||
});
|
||||
|
||||
test('single non-matching call returns false', () => {
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 1234,
|
||||
body: 'This is a test',
|
||||
})
|
||||
expect(add_comment).not.toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
bodyMatcher: /test/,
|
||||
});
|
||||
});
|
||||
|
||||
test('multiple calls, none matching, returns false', () => {
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 1234,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOtherOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someOtherRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 1234,
|
||||
body: 'This is a test',
|
||||
})
|
||||
expect(add_comment).not.toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
bodyMatcher: /test/,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('multiple calls, with matching, returns true', () => {
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 1234,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOtherOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
add_comment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someOtherRepo',
|
||||
issue_number: 123,
|
||||
body: 'This is a test',
|
||||
})
|
||||
expect(add_comment).toHaveComment({
|
||||
owner: 'someOwner',
|
||||
repo: 'someRepo',
|
||||
issue_number: 123,
|
||||
bodyMatcher: /test/,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
})
|
|
@ -15,10 +15,15 @@ These commands can only be run when commented by a user who is identified as a r
|
|||
|
||||
This command will cause the pr-comment-bot to respond with a comment listing the available commands.
|
||||
|
||||
### `/test`
|
||||
### `/test [<sha>]`
|
||||
|
||||
This command runs the build, deploy, and smoke tests for a PR.
|
||||
|
||||
For PRs from maintainers (i.e. users with write access to microsoft/AzureTRE), `/test` is sufficient.
|
||||
|
||||
For other PRs, the checks below should be carried out. Once satisfied that the PR is safe to run tests against, you should use `/test <sha>` where `<sha>` is the SHA for the commit that you have verified.
|
||||
You can use the full or short form of the SHA, but it must be at least 7 characters (GitHub UI shows 7 characters).
|
||||
|
||||
**IMPORTANT**
|
||||
|
||||
This command works on PRs from forks, and makes the deployment secrets available.
|
||||
|
@ -30,10 +35,15 @@ Check for changes to anything that is run during the build/deploy/test cycle, in
|
|||
- modifications to scripts
|
||||
- new python packages being installed
|
||||
|
||||
### `/test-extended`
|
||||
### `/test-extended [<sha>]`
|
||||
|
||||
This command runs the build, deploy, and smoke & extended tests for a PR.
|
||||
|
||||
For PRs from maintainers (i.e. users with write access to microsoft/AzureTRE), `/test-extended` is sufficient.
|
||||
|
||||
For other PRs, the checks below should be carried out. Once satisfied that the PR is safe to run tests against, you should use `/test-extended <sha>` where `<sha>` is the SHA for the commit that you have verified.
|
||||
You can use the full or short form of the SHA, but it must be at least 7 characters (GitHub UI shows 7 characters).
|
||||
|
||||
**IMPORTANT**
|
||||
|
||||
As with `/test`, this command works on PRs from forks, and makes the deployment secrets available.
|
||||
|
|
Загрузка…
Ссылка в новой задаче