@actions/github#getOctokit TypeScript Examples
The following examples show how to use
@actions/github#getOctokit.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getContextIssueComments = (): Promise<IssueComments> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.issues
.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
})
.then((res) => res.data);
}
Example #2
Source File: get-changed-files.ts From action-eslint with MIT License | 6 votes |
getChangedFiles = async (token: string): Promise<FileNamesList> => {
const octokit = getOctokit(token);
const pullRequest = context.payload.pull_request;
let filenames: FileNamesList = [];
if (!pullRequest?.number) {
const getCommitEndpointOptions = octokit.rest.repos.getCommit.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
});
type ReposGetCommitResponse = GetResponseDataTypeFromEndpointMethod<typeof octokit.rest.repos.getCommit>;
const response: ReposGetCommitResponse[] = await octokit.paginate(getCommitEndpointOptions);
const filesArr = response.map((data) => data.files);
const filesChangedInCommit = filesArr.reduce((acc, val) => acc?.concat(val || []), []);
filenames = getFileNames(filesChangedInCommit as File[]);
} else {
const listFilesEndpointOptions = octokit.rest.pulls.listFiles.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullRequest.number,
});
type PullsListFilesResponse = GetResponseDataTypeFromEndpointMethod<typeof octokit.rest.pulls.listFiles>;
const filesChangedInPR: PullsListFilesResponse = await octokit.paginate(listFilesEndpointOptions);
filenames = getFileNames(filesChangedInPR as File[]);
}
return filenames;
}
Example #3
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
removeLabels = async (labels: string[]) => {
const Github = getOctokit(GITHUB_TOKEN).rest;
// makes it easy to maintain the integration tests and the
// responses from this are not used
if (isMock() || isTest()) return;
await Promise.all(
// this will submit a max of three requests which is not enough to
// rate limit
labels.map((label) =>
Github.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: label
})
)
);
}
Example #4
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
addLabels = async (labels: string[]): Promise<void> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
// makes it easy to maintain the integration tests and the
// responses from this are not used
if (isMock() || isTest()) return;
// because of a weird type issue
const { addLabels: _addLabels } = Github.issues;
await _addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels
});
}
Example #5
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
setLabels = async (labels: string[]): Promise<void> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
await Github.issues
.setLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
// @ts-expect-error the expected type is (string[] & {name: string}[]) | undefined
// but string[] and {name: string}[] cannot simultaneously coincide
labels
})
.then((res) => res);
}
Example #6
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getContextLabels = async (): Promise<ChangeTypes[]> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
const { data: issue } = await Github.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const labels = issue.labels;
return labels
.map((label) => {
if (typeof label === "string") {
return label;
}
return label.name;
// this will make it so that the only labels considered are ChangeTypes
})
.filter(isDefined)
.filter(isChangeType);
}
Example #7
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
createCommentOnContext = (message: string): Promise<any> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: message
});
}
Example #8
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
updateComment = (commentId: number, message: string): Promise<any> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.issues
.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: commentId,
body: message
})
.catch((err) => {
if (err?.request?.body) {
err.request.body = JSON.parse(err.request.body).body;
}
throw err;
});
}
Example #9
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
resolveUserByEmail = async (email: string) => {
const Github = getOctokit(GITHUB_TOKEN).rest;
// @ts-ignore
const { data: rawEmailSearch } = await Github.search.users({
q: email
});
if (rawEmailSearch.total_count > 0 && rawEmailSearch.items[0] !== undefined) {
return "@" + rawEmailSearch.items[0].login;
}
const { data: emailSearch } = await Github.search.users({
q: `${email} in:email`
});
if (emailSearch.total_count === 1 && isDefined(emailSearch.items[0])) {
return "@" + emailSearch.items[0].login;
}
const local = email.split("@")[0];
if (!local) return;
const firstName = local.split(".")[0];
const lastName = local.split(".")[1];
if (!firstName || !lastName) return;
const { data: nameSearch } = await Github.search.users({
q: `fullname:${firstName} ${lastName} type:users`
});
if (nameSearch.total_count === 1 && isDefined(nameSearch.items[0])) {
return "@" + nameSearch.items[0].login;
}
return;
}
Example #10
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
requestReview = (pr: PR, reviewer: string) => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return (
Github.pulls
.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
reviewers: [reviewer]
})
// if an error occurs return undefined
.catch((err) => {})
);
}
Example #11
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getRepoFilenameContent = (
filename: string,
sha: string
): Promise<ContentData> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.repos
.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: filename,
ref: sha
})
.then((res) => res.data);
}
Example #12
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getPullRequestFiles = (pullNumber: number) => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.pulls
.listFiles({
pull_number: pullNumber,
repo: context.repo.repo,
owner: context.repo.owner
})
.then((res) => res.data);
}
Example #13
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getPullRequestReviews = async (
pullNumber: number,
page = 1
): Promise<Review[]> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
const { data: reviews }: { data: Review[] } = await Github.pulls.listReviews({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullNumber,
per_page: 100,
page
});
if (_.isEmpty(reviews)) {
return reviews;
}
return getPullRequestReviews(pullNumber, page + 1).then((res) =>
reviews.concat(res)
);
}
Example #14
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 6 votes |
getPullRequestFromNumber = (pullNumber: number) => {
const github = getOctokit(GITHUB_TOKEN).rest;
return github.pulls
.get({
repo: context.repo.repo,
owner: context.repo.owner,
pull_number: pullNumber
})
.then((res) => {
return res.data;
});
}
Example #15
Source File: github.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 5 votes |
getSelf = (): Promise<GithubSelf> => {
const Github = getOctokit(GITHUB_TOKEN).rest;
return Github.users.getAuthenticated().then((res) => {
return res.data;
});
}
Example #16
Source File: octokit.ts From github-action with Apache License 2.0 | 5 votes |
octokitUsingPAT = isPersonalAccessTokenPresent() ? getOctokit(personalAcessToken as string) : octokit
Example #17
Source File: octokit.ts From github-action with Apache License 2.0 | 5 votes |
octokit = getOctokit(githubActionsDefaultToken as string)
Example #18
Source File: index.ts From auto-changelog with MIT License | 5 votes |
async function run() {
const inputs = await getInputs();
const octokit = getOctokit(getToken());
const {
repo: { owner, repo },
sha,
} = context;
let semver: SemVer.SemVer | null = null;
if (inputs.semver) {
semver = SemVer.parse(inputs.releaseName, { includePrerelease: true });
if (semver == null)
return setFailed(
`Expected a semver compatible releaseName, got "${inputs.releaseName}" instead.`,
);
}
let prerelease = false;
if (semver != null) prerelease = semver.prerelease.length > 0;
const { sha: tagRef, name: tagName } = await getTagSha({
octokit,
owner,
repo,
sha,
semver,
prerelease,
});
let changelog = await generate({
octokit,
owner,
repo,
sha,
tagRef,
inputs,
});
if (inputs.mentionNewContributors) {
const { data } = await octokit.rest.repos.generateReleaseNotes({
owner,
repo,
tag_name: inputs.releaseName,
previous_tag_name: tagName,
});
const tokens = marked.lexer(data.body);
const index = tokens.findIndex(
(token) => token.type === "heading" && token.text === "New Contributors",
);
const token = tokens[index + 1];
if (token.type === "list")
changelog += `\n\n## New Contributors\n${token.raw}\n`;
}
if (inputs.includeCompare && tagName != null) {
changelog += `\n\n**Full Changelog**: https://github.com/${owner}/${repo}/compare/${tagName}...${inputs.releaseName}`;
}
info(`-> prerelease: ${prerelease}`);
setOutput("prerelease", prerelease);
info(`-> changelog: "${changelog}"`);
setOutput("changelog", changelog);
}
Example #19
Source File: mockPR.ts From EIP-Bot with Creative Commons Zero v1.0 Universal | 5 votes |
fetchAndCreateRecord = async (
url: string,
method: MockMethods,
body?: string
) => {
console.error("failed request", method, url, "\nmocking request...");
const isMock = process.env.NODE_ENV === NodeEnvs.mock;
if (!isMock) return;
nock.cleanAll();
nock.enableNetConnect();
const github = getOctokit(GITHUB_TOKEN).request;
const res = await github({
method,
url,
...JSON.parse(body || "{}")
}).catch((err) => {
nock.disableNetConnect();
return err;
});
console.log("successfully fetched data");
nock.disableNetConnect();
const fileName = `records/${process.env.PULL_NUMBER?.replace("_", "/")}.json`;
const mockedRecord: MockRecord[] = (await import("./" + fileName)).default;
requireMockMethod(method);
const handleResData = (res) => {
const status = res.status;
if ([HttpStatus.OK, HttpStatus.CREATED].includes(status)) {
// when successful it returns the response in a res.data format
return res.data;
}
if ([HttpStatus.NOT_FOUND].includes(status)) {
// when it returns a not found or other types of failures
return res.response.data;
}
throw new UnexpectedError(`status code ${status} is not a handled status`);
};
mockedRecord.push({
req: {
url,
method
},
res: {
status: res.status,
data: handleResData(res)
}
});
console.log(process.cwd() + "/src/tests/assets/" + fileName);
fs.writeFile(
process.cwd() + "/src/tests/assets/" + fileName,
JSON.stringify(mockedRecord, null, 2),
() => {
console.log(mockedRecord);
console.log("wrote file");
}
);
}
Example #20
Source File: main.ts From checkstyle-github-action with MIT License | 5 votes |
async function createCheck(
name: string,
title: string,
annotations: Annotation[],
numErrors: number,
conclusion: 'success' | 'failure' | 'neutral'
): Promise<void> {
core.info(
`Uploading ${annotations.length} / ${numErrors} annotations to GitHub as ${name} with conclusion ${conclusion}`
)
const octokit = getOctokit(core.getInput(Inputs.Token))
let sha = context.sha
if (context.payload.pull_request) {
sha = context.payload.pull_request.head.sha
}
const req = {
...context.repo,
ref: sha
}
const res = await octokit.checks.listForRef(req)
const existingCheckRun = res.data.check_runs.find(
check => check.name === name
)
if (!existingCheckRun) {
const createRequest = {
...context.repo,
head_sha: sha,
conclusion,
name,
status: <const>'completed',
output: {
title,
summary: `${numErrors} violation(s) found`,
annotations
}
}
await octokit.checks.create(createRequest)
} else {
const check_run_id = existingCheckRun.id
const update_req = {
...context.repo,
conclusion,
check_run_id,
status: <const>'completed',
output: {
title,
summary: `${numErrors} violation(s) found`,
annotations
}
}
await octokit.checks.update(update_req)
}
}
Example #21
Source File: main.ts From spotbugs-github-action with MIT License | 5 votes |
async function createCheck(
name: string,
title: string,
annotations: Annotation[],
numErrors: number
): Promise<void> {
const octokit = getOctokit(core.getInput(Inputs.Token))
let sha = context.sha
if (context.payload.pull_request) {
sha = context.payload.pull_request.head.sha
}
const req = {
...context.repo,
ref: sha
}
const res = await octokit.checks.listForRef(req)
const existingCheckRun = res.data.check_runs.find(
check => check.name === name
)
if (!existingCheckRun) {
const createRequest = {
...context.repo,
head_sha: sha,
name,
status: <const>'completed',
conclusion: numErrors === 0 ? <const>'success' : <const>'neutral',
output: {
title,
summary: `${numErrors} violation(s) found`,
annotations
}
}
await octokit.checks.create(createRequest)
} else {
const check_run_id = existingCheckRun.id
const update_req = {
...context.repo,
check_run_id,
status: <const>'completed',
conclusion: <const>'neutral',
output: {
title,
summary: `${numErrors} violation(s) found`,
annotations
}
}
await octokit.checks.update(update_req)
}
}
Example #22
Source File: mappingConfig.ts From actions-mention-to-slack with MIT License | 5 votes |
MappingConfigRepositoryImpl = {
downloadFromUrl: async (url: string) => {
const response = await axios.get<string>(url);
return response.data;
},
loadYaml: (data: string) => {
const configObject = load(data);
if (configObject === undefined) {
throw new Error(
["failed to load yaml", JSON.stringify({ data }, null, 2)].join("\n")
);
}
return configObject as MappingFile;
},
loadFromUrl: async (url: string) => {
const data = await MappingConfigRepositoryImpl.downloadFromUrl(url);
return MappingConfigRepositoryImpl.loadYaml(data);
},
loadFromGithubPath: async (
repoToken: string,
owner: string,
repo: string,
configurationPath: string,
sha: string
) => {
const githubClient = getOctokit(repoToken);
const response = await githubClient.rest.repos.getContent({
owner,
repo,
path: configurationPath,
ref: sha,
});
if (!("content" in response.data)) {
throw new Error(
["Unexpected response", JSON.stringify({ response }, null, 2)].join(
"\n"
)
);
}
const data = Buffer.from(response.data.content, "base64").toString();
return MappingConfigRepositoryImpl.loadYaml(data);
},
}
Example #23
Source File: main.ts From slack-workflow-status with MIT License | 4 votes |
// eslint-disable-line github/no-then
// Action entrypoint
async function main(): Promise<void> {
// Collect Action Inputs
const webhook_url = core.getInput('slack_webhook_url', {
required: true
})
const github_token = core.getInput('repo_token', {required: true})
const include_jobs = core.getInput('include_jobs', {
required: true
}) as IncludeJobs
const include_commit_message =
core.getInput('include_commit_message', {
required: true
}) === 'true'
const slack_channel = core.getInput('channel')
const slack_name = core.getInput('name')
const slack_icon = core.getInput('icon_url')
const slack_emoji = core.getInput('icon_emoji') // https://www.webfx.com/tools/emoji-cheat-sheet/
// Force as secret, forces *** when trying to print or log values
core.setSecret(github_token)
core.setSecret(webhook_url)
// Auth github with octokit module
const octokit = getOctokit(github_token)
// Fetch workflow run data
const {data: workflow_run} = await octokit.actions.getWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
})
// Fetch workflow job information
const {data: jobs_response} = await octokit.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
})
const completed_jobs = jobs_response.jobs.filter(
job => job.status === 'completed'
)
// Configure slack attachment styling
let workflow_color // can be good, danger, warning or a HEX colour (#00FF00)
let workflow_msg
let job_fields: SlackMessageAttachementFields
if (
completed_jobs.every(job => ['success', 'skipped'].includes(job.conclusion))
) {
workflow_color = 'good'
workflow_msg = 'Success:'
if (include_jobs === 'on-failure') {
job_fields = []
}
} else if (completed_jobs.some(job => job.conclusion === 'cancelled')) {
workflow_color = 'warning'
workflow_msg = 'Cancelled:'
if (include_jobs === 'on-failure') {
job_fields = []
}
} else {
// (jobs_response.jobs.some(job => job.conclusion === 'failed')
workflow_color = 'danger'
workflow_msg = 'Failed:'
}
if (include_jobs === 'false') {
job_fields = []
}
// Build Job Data Fields
job_fields ??= completed_jobs.map(job => {
let job_status_icon
switch (job.conclusion) {
case 'success':
job_status_icon = '✓'
break
case 'cancelled':
case 'skipped':
job_status_icon = '⃠'
break
default:
// case 'failure'
job_status_icon = '✗'
}
const job_duration = compute_duration({
start: new Date(job.started_at),
end: new Date(job.completed_at)
})
return {
title: '', // FIXME: it's required in slack type, we should workaround that somehow
short: true,
value: `${job_status_icon} <${job.html_url}|${job.name}> (${job_duration})`
}
})
// Payload Formatting Shortcuts
const workflow_duration = compute_duration({
start: new Date(workflow_run.created_at),
end: new Date(workflow_run.updated_at)
})
const repo_url = `<${workflow_run.repository.html_url}|*${workflow_run.repository.full_name}*>`
const branch_url = `<${workflow_run.repository.html_url}/tree/${workflow_run.head_branch}|*${workflow_run.head_branch}*>`
const workflow_run_url = `<${workflow_run.html_url}|#${workflow_run.run_number}>`
// Example: Success: AnthonyKinson's `push` on `master` for pull_request
let status_string = `${workflow_msg} ${context.actor}'s \`${context.eventName}\` on \`${branch_url}\``
// Example: Workflow: My Workflow #14 completed in `1m 30s`
const details_string = `Workflow: ${context.workflow} ${workflow_run_url} completed in \`${workflow_duration}\``
// Build Pull Request string if required
const pull_requests = (workflow_run.pull_requests as PullRequest[])
.map(
pull_request =>
`<${workflow_run.repository.html_url}/pull/${pull_request.number}|#${pull_request.number}> from \`${pull_request.head.ref}\` to \`${pull_request.base.ref}\``
)
.join(', ')
if (pull_requests !== '') {
status_string = `${workflow_msg} ${context.actor}'s \`pull_request\` ${pull_requests}`
}
const commit_message = `Commit: ${workflow_run.head_commit.message}`
// We're using old style attachments rather than the new blocks because:
// - Blocks don't allow colour indicators on messages
// - Block are limited to 10 fields. >10 jobs in a workflow results in payload failure
// Build our notification attachment
const slack_attachment = {
mrkdwn_in: ['text' as const],
color: workflow_color,
text: [status_string, details_string]
.concat(include_commit_message ? [commit_message] : [])
.join('\n'),
footer: repo_url,
footer_icon: 'https://github.githubassets.com/favicon.ico',
fields: job_fields
}
// Build our notification payload
const slack_payload_body = {
attachments: [slack_attachment],
...(slack_name && {username: slack_name}),
...(slack_channel && {channel: slack_channel}),
...(slack_emoji && {icon_emoji: slack_emoji}),
...(slack_icon && {icon_url: slack_icon})
}
const slack_webhook = new IncomingWebhook(webhook_url)
try {
await slack_webhook.send(slack_payload_body)
} catch (err) {
if (err instanceof Error) {
core.setFailed(err.message)
}
}
}
Example #24
Source File: index.ts From ticket-check-action with MIT License | 4 votes |
async function run(): Promise<void> {
try {
// Provide complete context object right away if debugging
debug('context', JSON.stringify(context));
// Check for a ticket reference in the title
const title: string = context?.payload?.pull_request?.title;
const titleRegexBase = getInput('titleRegex', { required: true });
const titleRegexFlags = getInput('titleRegexFlags', {
required: true
});
const ticketLink = getInput('ticketLink', { required: false });
const titleRegex = new RegExp(titleRegexBase, titleRegexFlags);
const titleCheck = titleRegex.exec(title);
// Instantiate a GitHub Client instance
const token = getInput('token', { required: true });
const client = getOctokit(token);
const { owner, repo, number } = context.issue;
const login = context.payload.pull_request?.user.login as string;
const senderType = context.payload.pull_request?.user.type as string;
const sender: string = senderType === 'Bot' ? login.replace('[bot]', '') : login;
const linkTicket = async (matchArray: RegExpMatchArray): Promise<void> => {
debug('match array for linkTicket', JSON.stringify(matchArray));
debug('match array groups for linkTicket', JSON.stringify(matchArray.groups));
if (!ticketLink) {
return;
}
const ticketNumber = matchArray.groups?.ticketNumber;
if (!ticketNumber) {
debug('ticketNumber not found', 'ticketNumber group not found in match array.');
return;
}
if (!ticketLink.includes('%ticketNumber%')) {
debug('invalid ticketLink', 'ticketLink must include "%ticketNumber%" variable to post ticket link.');
return;
}
const linkToTicket = ticketLink.replace('%ticketNumber%', ticketNumber);
const currentReviews = await client.pulls.listReviews({
owner,
repo,
pull_number: number
});
debug('current reviews', JSON.stringify(currentReviews));
if (
currentReviews?.data?.length &&
currentReviews?.data.some((review: { body?: string }) => review?.body?.includes(linkToTicket))
) {
debug('already posted ticketLink', 'found an existing review that contains the ticket link');
return;
}
client.pulls.createReview({
owner,
repo,
pull_number: number,
body: `See the ticket for this pull request: ${linkToTicket}`,
event: 'COMMENT'
});
};
debug('title', title);
// Return and approve if the title includes a Ticket ID
if (titleCheck !== null) {
debug('success', 'Title includes a ticket ID');
await linkTicket(titleCheck);
return;
}
const quiet = getInput('quiet', { required: false }) === 'true';
// Exempt Users
const exemptUsers = getInput('exemptUsers', { required: false })
.split(',')
.map(user => user.trim());
// Debugging Entries
debug('sender', sender);
debug('sender type', senderType);
debug('quiet mode', quiet.toString());
debug('exempt users', exemptUsers.join(','));
debug('ticket link', ticketLink);
if (sender && exemptUsers.includes(sender)) {
debug('success', 'User is listed as exempt');
return;
}
// get the title format and ticket prefix
const ticketPrefix = getInput('ticketPrefix');
const titleFormat = getInput('titleFormat', { required: true });
// Check for a ticket reference in the branch
const branch: string = context.payload.pull_request?.head.ref;
const branchRegexBase = getInput('branchRegex', { required: true });
const branchRegexFlags = getInput('branchRegexFlags', {
required: true
});
const branchRegex = new RegExp(branchRegexBase, branchRegexFlags);
const branchCheck = branchRegex.exec(branch);
if (branchCheck !== null) {
debug('success', 'Branch name contains a reference to a ticket, updating title');
const id = extractId(branch);
if (id === null) {
setFailed('Could not extract a ticket ID reference from the branch');
return;
}
client.pulls.update({
owner,
repo,
pull_number: number,
title: titleFormat
.replace('%prefix%', ticketPrefix)
.replace('%id%', id)
.replace('%title%', title)
});
if (!quiet) {
client.pulls.createReview({
owner,
repo,
pull_number: number,
body:
"Hey! I noticed that your PR contained a reference to the ticket in the branch name but not in the title. I went ahead and updated that for you. Hope you don't mind! ☺️",
event: 'COMMENT'
});
}
await linkTicket(branchCheck);
return;
}
// Retrieve the pull request body and verify it's not empty
const body = context?.payload?.pull_request?.body;
if (body === undefined) {
debug('failure', 'Body is undefined');
setFailed('Could not retrieve the Pull Request body');
return;
}
debug('body contents', body);
// Check for a ticket reference number in the body
const bodyRegexBase = getInput('bodyRegex', { required: true });
const bodyRegexFlags = getInput('bodyRegexFlags', { required: true });
const bodyRegex = new RegExp(bodyRegexBase, bodyRegexFlags);
const bodyCheck = bodyRegex.exec(body);
if (bodyCheck !== null) {
debug('success', 'Body contains a reference to a ticket, updating title');
const id = extractId(bodyCheck[0]);
if (id === null) {
setFailed('Could not extract a ticket shorthand reference from the body');
return;
}
client.pulls.update({
owner,
repo,
pull_number: number,
title: titleFormat
.replace('%prefix%', ticketPrefix)
.replace('%id%', id)
.replace('%title%', title)
});
if (!quiet) {
client.pulls.createReview({
owner,
repo,
pull_number: number,
body:
"Hey! I noticed that your PR contained a reference to the ticket in the body but not in the title. I went ahead and updated that for you. Hope you don't mind! ☺️",
event: 'COMMENT'
});
}
await linkTicket(bodyCheck);
return;
}
// Last ditch effort, check for a ticket reference URL in the body
const bodyURLRegexBase = getInput('bodyURLRegex', { required: false });
if (!bodyURLRegexBase) {
debug('failure', 'Title, branch, and body do not contain a reference to a ticket, and no body URL regex was set');
setFailed('No ticket was referenced in this pull request');
return;
}
const bodyURLRegexFlags = getInput('bodyURLRegexFlags', {
required: true
});
const bodyURLRegex = new RegExp(bodyURLRegexBase, bodyURLRegexFlags);
const bodyURLCheck = bodyURLRegex.exec(body);
if (bodyURLCheck !== null) {
debug('success', 'Body contains a ticket URL, updating title');
const id = extractId(bodyURLCheck[0]);
if (id === null) {
setFailed('Could not extract a ticket URL from the body');
return;
}
client.pulls.update({
owner,
repo,
pull_number: number,
title: titleFormat
.replace('%prefix%', ticketPrefix)
.replace('%id%', id)
.replace('%title%', title)
});
if (!quiet) {
client.pulls.createReview({
owner,
repo,
pull_number: number,
body:
"Hey! I noticed that your PR contained a reference to the ticket URL in the body but not in the title. I went ahead and updated that for you. Hope you don't mind! ☺️",
event: 'COMMENT'
});
}
}
if (titleCheck === null && branchCheck === null && bodyCheck === null && bodyURLCheck === null) {
debug('failure', 'Title, branch, and body do not contain a reference to a ticket');
setFailed('No ticket was referenced in this pull request');
return;
}
} catch (error) {
setFailed(error.message);
}
}