Issue number (#64)

* Major code reorg
* Add issue arg
* Paginate existing comment list
This commit is contained in:
Michael Shick 2022-11-08 10:12:22 -08:00 committed by GitHub
parent e8076c64f7
commit 8645f3f0ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 2187 additions and 1968 deletions

View file

@ -62,5 +62,3 @@ jobs:
**Hello ${{ github.run_number }}**
🌏
!
repo-token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}

View file

@ -1,18 +1,22 @@
# add-pr-comment
> A GitHub Action which adds a comment to a pull request's issue.
A GitHub Action which adds a comment to a pull request's issue.
This actions also works on [issue](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues),
[issue_comment](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issue_comment),
[deployment_status](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#deployment_status),
[push](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push)
and any other event where an issue can be found directly on the payload or via a commit sha.
## Features
- Fast, runs in the GitHub Actions node.js runtime.
- Modify issues for PRs merged to main.
- By default will post "sticky" comments. If on a subsequent run the message text changes the original comment will be updated.
- Multiple sticky comments allowed by setting unique `message-id`s.
- Multiple posts of the same comment optionally allowable.
- Supports emoji 😂😂😂!
- Optional message overrides based on job status.
- Multiple posts to the same conversation optionally allowable.
- Supports a proxy for fork-based PRs. [See below](#proxy-for-fork-based-prs).
- Supports creating a message from a file path.
- Optional message / status overrides.
## Usage
@ -34,9 +38,6 @@ jobs:
**Hello**
🌏
!
repo-token: ${{ secrets.GITHUB_TOKEN }}
allow-repeats: false # This is the default
message-id: 'add-pr-comment' # This is the default
```
You can even use it on PR Issues that are related to PRs that were merged into main, for example:
@ -54,8 +55,6 @@ jobs:
pull-requests: write
steps:
- uses: mshick/add-pr-comment@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
message: |
**Hello MAIN**
@ -63,19 +62,20 @@ jobs:
## Configuration options
| Variable or Argument | Location | Description | Required | Default |
| -------------------- | -------- | ---------------------------------------------------------------------------------------------------- | -------- | ------- |
| message | with | The message you'd like displayed, supports Markdown and all valid Unicode characters. | maybe | |
| message-path | with | Path to a message you'd like displayed. Will be read and displayed just like a normal message. | maybe | |
| message-success | with | A message override, printed in case of success. | maybe | |
| message-failure | with | A message override, printed in case of failure. | maybe | |
| message-cancelled | with | A message override, printed in case of cancelled. | maybe | |
| status | with | Required if you want to use message status overrides. | maybe | |
| repo-token | with | Valid GitHub token, either the temporary token GitHub provides or a personal access token. | maybe | |
| message-id | with | Message id to use when searching existing comments. If found, updates the existing (sticky comment). | no | |
| allow-repeats | with | Boolean flag to allow identical messages to be posted each time this action is run. | no | false |
| proxy-url | with | String for your proxy service URL if you'd like this to work with fork-based PRs. | no | |
| GITHUB_TOKEN | env | Valid GitHub token, can alternatively be defined in the env. | maybe | |
| Input | Location | Description | Required | Default |
| ----------------- | -------- | ---------------------------------------------------------------------------------------------------- | -------- | ------------------ |
| message | with | The message you'd like displayed, supports Markdown and all valid Unicode characters. | maybe | |
| message-path | with | Path to a message you'd like displayed. Will be read and displayed just like a normal message. | maybe | |
| message-success | with | A message override, printed in case of success. | no | |
| message-failure | with | A message override, printed in case of failure. | no | |
| message-cancelled | with | A message override, printed in case of cancelled. | no | |
| status | with | Required if you want to use message status overrides. | no | {{ job.status }} |
| repo-token | with | Valid GitHub token, either the temporary token GitHub provides or a personal access token. | no | {{ github.token }} |
| message-id | with | Message id to use when searching existing comments. If found, updates the existing (sticky comment). | no | |
| allow-repeats | with | Boolean flag to allow identical messages to be posted each time this action is run. | no | false |
| proxy-url | with | String for your proxy service URL if you'd like this to work with fork-based PRs. | no | |
| issue | with | Optional issue number override. | no | |
| GITHUB_TOKEN | env | Valid GitHub token, can alternatively be defined in the env. | no | |
## Advanced Uses
@ -104,7 +104,6 @@ jobs:
message: |
**Howdie!**
proxy-url: https://add-pr-comment-proxy-94idvmwyie-uc.a.run.app
repo-token: ${{ secrets.GITHUB_TOKEN }}
```
### Status Message Overrides
@ -132,6 +131,38 @@ jobs:
**Howdie!**
message-failure: |
Uh oh!
repo-token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
```
### Bring your own issues
You can set an issue id explicitly. Helpful for cases where you want to post
to an issue but for some reason the event would not allow the id to be determined.
**Example**
> In this case `add-pr-comment` should have no problem finding the issue number
> on its own, but for demonstration purposes.
```yaml
on:
deployment_status:
jobs:
pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- id: pr
run: |
issue=$(gh pr list --search "${{ github.sha }}" --state open --json number --jq ".[0].number")
echo "issue=$issue" >>$GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: mshick/add-pr-comment@v2
with:
issue: ${{ steps.pr.outputs.issue }}
message: |
**Howdie!**
```

View file

@ -224,7 +224,7 @@ describe('add-pr-comment action', () => {
const replyBody = [
{
id: commentId,
body: `<!-- ${inputs['message-id']} -->\n\n${simpleMessage}`,
body: `<!-- add-pr-comment:${inputs['message-id']} -->\n\n${simpleMessage}`,
},
]

View file

@ -9,21 +9,23 @@ inputs:
required: false
message-id:
description: "An optional id to use for this message."
required: false
default: "add-pr-comment"
repo-token:
description: "A GitHub token for API access."
required: false
repo-token:
description: "A GitHub token for API access. Defaults to {{ github.token }}."
default: "${{ github.token }}"
required: true
allow-repeats:
description: "Allow messages to be repeated."
required: false
default: "false"
required: false
proxy-url:
description: "Proxy URL for comment creation"
required: false
status:
description: "Provide a job status for status headers."
required: false
description: "A job status for status headers. Defaults to {{ job.status }}."
default: "${{ job.status }}"
required: true
message-success:
description: "Override the message when a run is successful."
required: false
@ -33,13 +35,16 @@ inputs:
message-cancelled:
description: "Override the message when a run is cancelled."
required: false
issue:
description: "Override the message when a run is cancelled."
required: false
outputs:
comment-created:
description: "Whether a comment was created."
comment-updated:
description: "Whether a comment was updated."
comment-id:
description: "If a comment was created or updated, it's id."
description: "If a comment was created or updated, the comment id."
branding:
icon: message-circle
color: purple

2776
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

43
lib/comments.js Normal file
View file

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createComment = exports.updateComment = exports.getExistingCommentId = void 0;
async function getExistingCommentId(octokit, owner, repo, issueNumber, messageId) {
const parameters = {
owner,
repo,
issue_number: issueNumber,
per_page: 100,
};
let found;
for await (const comments of octokit.paginate.iterator(octokit.rest.issues.listComments, parameters)) {
found = comments.data.find(({ body }) => {
var _a;
return ((_a = body === null || body === void 0 ? void 0 : body.search(messageId)) !== null && _a !== void 0 ? _a : -1) > -1;
});
if (found) {
break;
}
}
return found === null || found === void 0 ? void 0 : found.id;
}
exports.getExistingCommentId = getExistingCommentId;
async function updateComment(octokit, owner, repo, existingCommentId, body) {
const updatedComment = await octokit.rest.issues.updateComment({
comment_id: existingCommentId,
owner,
repo,
body,
});
return updatedComment.data;
}
exports.updateComment = updateComment;
async function createComment(octokit, owner, repo, issueNumber, body) {
const createdComment = await octokit.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body,
});
return createdComment.data;
}
exports.createComment = createComment;

89
lib/config.js Normal file
View file

@ -0,0 +1,89 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInputs = void 0;
const core = __importStar(require("@actions/core"));
const github = __importStar(require("@actions/github"));
const promises_1 = __importDefault(require("node:fs/promises"));
async function getInputs() {
var _a, _b, _c;
const messageIdInput = core.getInput('message-id', { required: false });
const messageId = messageIdInput === '' ? 'add-pr-comment' : `add-pr-comment:${messageIdInput}`;
const messageInput = core.getInput('message', { required: false });
const messagePath = core.getInput('message-path', { required: false });
const repoToken = core.getInput('repo-token', { required: true });
const status = core.getInput('status', { required: true });
const issue = core.getInput('issue', { required: false });
const proxyUrl = core.getInput('proxy-url', { required: false }).replace(/\/$/, '');
const allowRepeats = core.getInput('allow-repeats', { required: true }) === 'true';
if (messageInput && messagePath) {
throw new Error('must specify only one, message or message-path');
}
let message;
if (messagePath) {
message = await promises_1.default.readFile(messagePath, { encoding: 'utf8' });
}
else {
message = messageInput;
}
const messageSuccess = core.getInput(`message-success`);
const messageFailure = core.getInput(`message-failure`);
const messageCancelled = core.getInput(`message-cancelled`);
if (status === 'success' && messageSuccess) {
message = messageSuccess;
}
if (status === 'failure' && messageFailure) {
message = messageFailure;
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled;
}
if (!message) {
throw new Error('no message, check your message inputs');
}
const { payload } = github.context;
const repoFullName = (_a = payload.repository) === null || _a === void 0 ? void 0 : _a.full_name;
if (!repoFullName) {
throw new Error('unable to determine repository from request type');
}
const [owner, repo] = repoFullName.split('/');
return {
allowRepeats,
message,
messageId: `<!-- ${messageId} -->`,
proxyUrl,
repoToken,
status,
issue: issue ? Number(issue) : (_b = payload.issue) === null || _b === void 0 ? void 0 : _b.number,
pullRequestNumber: (_c = payload.pull_request) === null || _c === void 0 ? void 0 : _c.number,
commitSha: github.context.sha,
owner,
repo,
};
}
exports.getInputs = getInputs;

13
lib/issues.js Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getIssueNumberFromCommitPullsList = void 0;
async function getIssueNumberFromCommitPullsList(octokit, owner, repo, commitSha) {
var _a;
const commitPullsList = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
owner,
repo,
commit_sha: commitSha,
});
return commitPullsList.data.length ? (_a = commitPullsList.data) === null || _a === void 0 ? void 0 : _a[0].number : null;
}
exports.getIssueNumberFromCommitPullsList = getIssueNumberFromCommitPullsList;

View file

@ -22,134 +22,45 @@ var __importStar = (this && this.__importStar) || function (mod) {
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const github = __importStar(require("@actions/github"));
const http_client_1 = require("@actions/http-client");
const promises_1 = __importDefault(require("node:fs/promises"));
const getIssueNumberFromCommitPullsList = (commitPullsList) => (commitPullsList.length ? commitPullsList[0].number : null);
async function createCommentProxy(params) {
const { repoToken, owner, repo, issueNumber, body, commentId, proxyUrl } = params;
const http = new http_client_1.HttpClient('http-client-add-pr-comment');
const response = await http.postJson(`${proxyUrl}/repos/${owner}/${repo}/issues/${issueNumber}/comments`, { comment_id: commentId, body }, {
['temporary-github-token']: repoToken,
});
return response.result;
}
function getExistingCommentId(comments, messageId) {
const found = comments.find(({ body }) => {
var _a;
return ((_a = body === null || body === void 0 ? void 0 : body.search(messageId)) !== null && _a !== void 0 ? _a : -1) > -1;
});
return found === null || found === void 0 ? void 0 : found.id;
}
async function getInputs() {
const messageId = core.getInput('message-id');
const messageInput = core.getInput('message');
const messagePath = core.getInput('message-path');
const repoToken = core.getInput('repo-token') || process.env['GITHUB_TOKEN'];
const status = core.getInput('status');
if (!repoToken) {
throw new Error('no github token provided, set one with the repo-token input or GITHUB_TOKEN env variable');
}
if (messageInput && messagePath) {
throw new Error('must specify only one, message or message-path');
}
let message;
if (messagePath) {
message = await promises_1.default.readFile(messagePath, { encoding: 'utf8' });
}
else {
message = messageInput;
}
const messageSuccess = core.getInput(`message-success`);
const messageFailure = core.getInput(`message-failure`);
const messageCancelled = core.getInput(`message-cancelled`);
if ((messageSuccess || messageFailure || messageCancelled) && !status) {
throw new Error('to use a status message you must provide a status input');
}
if (status) {
if (status === 'success' && messageSuccess) {
message = messageSuccess;
}
if (status === 'failure' && messageFailure) {
message = messageFailure;
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled;
}
}
if (!message) {
throw new Error('no message, check your message inputs');
}
return {
allowRepeats: Boolean(core.getInput('allow-repeats') === 'true'),
message,
messageId: messageId === '' ? 'add-pr-comment' : messageId,
proxyUrl: core.getInput('proxy-url').replace(/\/$/, ''),
repoToken,
status,
};
}
const comments_1 = require("./comments");
const config_1 = require("./config");
const issues_1 = require("./issues");
const proxy_1 = require("./proxy");
const run = async () => {
try {
const { allowRepeats, message, messageId, repoToken, proxyUrl } = await getInputs();
const messageIdComment = `<!-- ${messageId} -->`;
const { payload: { pull_request: pullRequest, issue, repository }, sha: commitSha, } = github.context;
if (!repository) {
core.info('unable to determine repository from request type');
core.setOutput('comment-created', 'false');
return;
}
const { full_name: repoFullName } = repository;
if (!repoFullName) {
core.info('repository is missing a full_name property... weird');
core.setOutput('comment-created', 'false');
return;
}
const [owner, repo] = repoFullName.split('/');
const { allowRepeats, message, messageId, repoToken, proxyUrl, issue, pullRequestNumber, commitSha, repo, owner, } = await (0, config_1.getInputs)();
const octokit = github.getOctokit(repoToken);
let issueNumber;
if (issue && issue.number) {
issueNumber = issue.number;
if (issue) {
issueNumber = issue;
}
else if (pullRequest && pullRequest.number) {
issueNumber = pullRequest.number;
else if (pullRequestNumber) {
issueNumber = pullRequestNumber;
}
else {
// If this is not a pull request, attempt to find a PR matching the sha
const commitPullsList = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
owner,
repo,
commit_sha: commitSha,
});
issueNumber = commitPullsList.data && getIssueNumberFromCommitPullsList(commitPullsList.data);
issueNumber = await (0, issues_1.getIssueNumberFromCommitPullsList)(octokit, owner, repo, commitSha);
}
if (!issueNumber) {
core.info('this action only works on issues and pull_request events or other commits associated with a pull');
core.info('no issue number found, use a pull_request event, a pull event, or provide an issue input');
core.setOutput('comment-created', 'false');
return;
}
let existingCommentId;
if (!allowRepeats) {
core.debug('repeat comments are disallowed, checking for existing');
const { data: comments } = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: issueNumber,
});
existingCommentId = getExistingCommentId(comments, messageIdComment);
existingCommentId = await (0, comments_1.getExistingCommentId)(octokit, owner, repo, issueNumber, messageId);
if (existingCommentId) {
core.debug(`existing comment found with id: ${existingCommentId}`);
}
}
let comment;
const body = `${messageIdComment}\n\n${message}`;
const body = `${messageId}\n\n${message}`;
if (proxyUrl) {
comment = await createCommentProxy({
comment = await (0, proxy_1.createCommentProxy)({
commentId: existingCommentId,
owner,
repo,
@ -161,23 +72,11 @@ const run = async () => {
core.setOutput(existingCommentId ? 'comment-updated' : 'comment-created', 'true');
}
else if (existingCommentId) {
const updatedComment = await octokit.rest.issues.updateComment({
comment_id: existingCommentId,
owner,
repo,
body,
});
comment = updatedComment.data;
comment = await (0, comments_1.updateComment)(octokit, owner, repo, existingCommentId, body);
core.setOutput('comment-updated', 'true');
}
else {
const createdComment = await octokit.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body,
});
comment = createdComment.data;
comment = await (0, comments_1.createComment)(octokit, owner, repo, issueNumber, body);
core.setOutput('comment-created', 'true');
}
if (comment) {
@ -192,9 +91,6 @@ const run = async () => {
if (err instanceof Error) {
core.setFailed(err.message);
}
else {
core.setFailed('unknown failure');
}
}
};
// Don't auto-execute in the test environment

13
lib/proxy.js Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCommentProxy = void 0;
const http_client_1 = require("@actions/http-client");
async function createCommentProxy(params) {
const { repoToken, owner, repo, issueNumber, body, commentId, proxyUrl } = params;
const http = new http_client_1.HttpClient('http-client-add-pr-comment');
const response = await http.postJson(`${proxyUrl}/repos/${owner}/${repo}/issues/${issueNumber}/comments`, { comment_id: commentId, body }, {
['temporary-github-token']: repoToken,
});
return response.result;
}
exports.createCommentProxy = createCommentProxy;

554
package-lock.json generated
View file

@ -56,6 +56,95 @@
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"dependencies": {
"@octokit/types": "^6.0.3"
}
},
"node_modules/@actions/github/node_modules/@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"dependencies": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"dependencies": {
"@octokit/types": "^6.40.0"
},
"peerDependencies": {
"@octokit/core": ">=2"
}
},
"node_modules/@actions/github/node_modules/@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"dependencies": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
}
},
"node_modules/@actions/http-client": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
@ -356,128 +445,67 @@
}
},
"node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
"peer": true,
"dependencies": {
"@octokit/types": "^6.0.3"
}
},
"node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/auth-token/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
"@octokit/types": "^8.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^5.0.0",
"@octokit/request": "^6.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/core/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
"peer": true,
"dependencies": {
"@octokit/types": "^6.0.3",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
"peer": true,
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"@octokit/request": "^6.0.0",
"@octokit/types": "^8.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/openapi-types": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==",
"dev": true
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"dependencies": {
"@octokit/types": "^6.40.0"
},
"peerDependencies": {
"@octokit/core": ">=2"
}
},
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
}
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
@ -505,59 +533,40 @@
}
},
"node_modules/@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
"peer": true,
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
"peer": true,
"dependencies": {
"@octokit/types": "^6.0.3",
"@octokit/types": "^8.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
}
},
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/request/node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/types": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
"dev": true,
"dependencies": {
"@octokit/openapi-types": "^14.0.0"
}
@ -6995,6 +7004,94 @@
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
},
"dependencies": {
"@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"requires": {
"@octokit/types": "^6.0.3"
}
},
"@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"requires": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"requires": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"requires": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"requires": {
"@octokit/types": "^6.40.0"
}
},
"@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"requires": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"requires": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@actions/http-client": {
@ -7222,135 +7319,55 @@
}
},
"@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
"peer": true,
"requires": {
"@octokit/types": "^6.0.3"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
"@octokit/types": "^8.0.0"
}
},
"@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
"peer": true,
"requires": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^5.0.0",
"@octokit/request": "^6.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
"peer": true,
"requires": {
"@octokit/types": "^6.0.3",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
"peer": true,
"requires": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"@octokit/request": "^6.0.0",
"@octokit/types": "^8.0.0",
"universal-user-agent": "^6.0.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@octokit/openapi-types": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==",
"dev": true
},
"@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"requires": {
"@octokit/types": "^6.40.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
},
"@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
@ -7377,63 +7394,34 @@
}
},
"@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
"peer": true,
"requires": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
"peer": true,
"requires": {
"@octokit/types": "^6.0.3",
"@octokit/types": "^8.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
},
"dependencies": {
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
}
}
},
"@octokit/types": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
"dev": true,
"requires": {
"@octokit/openapi-types": "^14.0.0"
}

71
src/comments.ts Normal file
View file

@ -0,0 +1,71 @@
import { GitHub } from '@actions/github/lib/utils'
import { Endpoints } from '@octokit/types'
export type CreateIssueCommentResponseData =
Endpoints['POST /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data']
export async function getExistingCommentId(
octokit: InstanceType<typeof GitHub>,
owner: string,
repo: string,
issueNumber: number,
messageId: string,
): Promise<number | undefined> {
const parameters = {
owner,
repo,
issue_number: issueNumber,
per_page: 100,
}
let found
for await (const comments of octokit.paginate.iterator(
octokit.rest.issues.listComments,
parameters,
)) {
found = comments.data.find(({ body }) => {
return (body?.search(messageId) ?? -1) > -1
})
if (found) {
break
}
}
return found?.id
}
export async function updateComment(
octokit: InstanceType<typeof GitHub>,
owner: string,
repo: string,
existingCommentId: number,
body: string,
): Promise<CreateIssueCommentResponseData> {
const updatedComment = await octokit.rest.issues.updateComment({
comment_id: existingCommentId,
owner,
repo,
body,
})
return updatedComment.data
}
export async function createComment(
octokit: InstanceType<typeof GitHub>,
owner: string,
repo: string,
issueNumber: number,
body: string,
): Promise<CreateIssueCommentResponseData> {
const createdComment = await octokit.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body,
})
return createdComment.data
}

89
src/config.ts Normal file
View file

@ -0,0 +1,89 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import fs from 'node:fs/promises'
interface Inputs {
allowRepeats: boolean
message?: string
messageId: string
messagePath?: string
messageSuccess?: string
messageFailure?: string
messageCancelled?: string
proxyUrl?: string
repoToken: string
status?: string
issue?: number
commitSha: string
pullRequestNumber?: number
repo: string
owner: string
}
export async function getInputs(): Promise<Inputs> {
const messageIdInput = core.getInput('message-id', { required: false })
const messageId = messageIdInput === '' ? 'add-pr-comment' : `add-pr-comment:${messageIdInput}`
const messageInput = core.getInput('message', { required: false })
const messagePath = core.getInput('message-path', { required: false })
const repoToken = core.getInput('repo-token', { required: true })
const status = core.getInput('status', { required: true })
const issue = core.getInput('issue', { required: false })
const proxyUrl = core.getInput('proxy-url', { required: false }).replace(/\/$/, '')
const allowRepeats = core.getInput('allow-repeats', { required: true }) === 'true'
if (messageInput && messagePath) {
throw new Error('must specify only one, message or message-path')
}
let message
if (messagePath) {
message = await fs.readFile(messagePath, { encoding: 'utf8' })
} else {
message = messageInput
}
const messageSuccess = core.getInput(`message-success`)
const messageFailure = core.getInput(`message-failure`)
const messageCancelled = core.getInput(`message-cancelled`)
if (status === 'success' && messageSuccess) {
message = messageSuccess
}
if (status === 'failure' && messageFailure) {
message = messageFailure
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled
}
if (!message) {
throw new Error('no message, check your message inputs')
}
const { payload } = github.context
const repoFullName = payload.repository?.full_name
if (!repoFullName) {
throw new Error('unable to determine repository from request type')
}
const [owner, repo] = repoFullName.split('/')
return {
allowRepeats,
message,
messageId: `<!-- ${messageId} -->`,
proxyUrl,
repoToken,
status,
issue: issue ? Number(issue) : payload.issue?.number,
pullRequestNumber: payload.pull_request?.number,
commitSha: github.context.sha,
owner,
repo,
}
}

16
src/issues.ts Normal file
View file

@ -0,0 +1,16 @@
import { GitHub } from '@actions/github/lib/utils'
export async function getIssueNumberFromCommitPullsList(
octokit: InstanceType<typeof GitHub>,
owner: string,
repo: string,
commitSha: string,
): Promise<number | null> {
const commitPullsList = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
owner,
repo,
commit_sha: commitSha,
})
return commitPullsList.data.length ? commitPullsList.data?.[0].number : null
}

View file

@ -1,179 +1,46 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import { HttpClient } from '@actions/http-client'
import { Endpoints } from '@octokit/types'
import fs from 'node:fs/promises'
type ListCommitPullsResponseData =
Endpoints['GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls']['response']['data']
type CreateIssueCommentResponseData =
Endpoints['POST /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data']
type IssuesListCommentsResponseData =
Endpoints['GET /repos/{owner}/{repo}/issues/comments']['response']['data']
const getIssueNumberFromCommitPullsList = (
commitPullsList: ListCommitPullsResponseData,
): number | null => (commitPullsList.length ? commitPullsList[0].number : null)
interface CreateCommentProxyParams {
repoToken: string
commentId?: number
body: string
owner: string
repo: string
issueNumber: number
proxyUrl: string
}
async function createCommentProxy(
params: CreateCommentProxyParams,
): Promise<CreateIssueCommentResponseData | null> {
const { repoToken, owner, repo, issueNumber, body, commentId, proxyUrl } = params
const http = new HttpClient('http-client-add-pr-comment')
const response = await http.postJson<CreateIssueCommentResponseData>(
`${proxyUrl}/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
{ comment_id: commentId, body },
{
['temporary-github-token']: repoToken,
},
)
return response.result
}
function getExistingCommentId(
comments: IssuesListCommentsResponseData,
messageId: string,
): number | undefined {
const found = comments.find(({ body }) => {
return (body?.search(messageId) ?? -1) > -1
})
return found?.id
}
interface AddPrCommentInputs {
allowRepeats: boolean
message?: string
messageId: string
messagePath?: string
messageSuccess?: string
messageFailure?: string
messageCancelled?: string
proxyUrl?: string
repoToken: string
status?: string
}
async function getInputs(): Promise<AddPrCommentInputs> {
const messageId = core.getInput('message-id')
const messageInput = core.getInput('message')
const messagePath = core.getInput('message-path')
const repoToken = core.getInput('repo-token') || process.env['GITHUB_TOKEN']
const status = core.getInput('status')
if (!repoToken) {
throw new Error(
'no github token provided, set one with the repo-token input or GITHUB_TOKEN env variable',
)
}
if (messageInput && messagePath) {
throw new Error('must specify only one, message or message-path')
}
let message
if (messagePath) {
message = await fs.readFile(messagePath, { encoding: 'utf8' })
} else {
message = messageInput
}
const messageSuccess = core.getInput(`message-success`)
const messageFailure = core.getInput(`message-failure`)
const messageCancelled = core.getInput(`message-cancelled`)
if ((messageSuccess || messageFailure || messageCancelled) && !status) {
throw new Error('to use a status message you must provide a status input')
}
if (status) {
if (status === 'success' && messageSuccess) {
message = messageSuccess
}
if (status === 'failure' && messageFailure) {
message = messageFailure
}
if (status === 'cancelled' && messageCancelled) {
message = messageCancelled
}
}
if (!message) {
throw new Error('no message, check your message inputs')
}
return {
allowRepeats: Boolean(core.getInput('allow-repeats') === 'true'),
message,
messageId: messageId === '' ? 'add-pr-comment' : messageId,
proxyUrl: core.getInput('proxy-url').replace(/\/$/, ''),
repoToken,
status,
}
}
import {
createComment,
CreateIssueCommentResponseData,
getExistingCommentId,
updateComment,
} from './comments'
import { getInputs } from './config'
import { getIssueNumberFromCommitPullsList } from './issues'
import { createCommentProxy } from './proxy'
const run = async (): Promise<void> => {
try {
const { allowRepeats, message, messageId, repoToken, proxyUrl } = await getInputs()
const messageIdComment = `<!-- ${messageId} -->`
const {
payload: { pull_request: pullRequest, issue, repository },
sha: commitSha,
} = github.context
allowRepeats,
message,
messageId,
repoToken,
proxyUrl,
issue,
pullRequestNumber,
commitSha,
repo,
owner,
} = await getInputs()
if (!repository) {
core.info('unable to determine repository from request type')
core.setOutput('comment-created', 'false')
return
}
const { full_name: repoFullName } = repository
if (!repoFullName) {
core.info('repository is missing a full_name property... weird')
core.setOutput('comment-created', 'false')
return
}
const [owner, repo] = repoFullName.split('/')
const octokit = github.getOctokit(repoToken)
let issueNumber
if (issue && issue.number) {
issueNumber = issue.number
} else if (pullRequest && pullRequest.number) {
issueNumber = pullRequest.number
if (issue) {
issueNumber = issue
} else if (pullRequestNumber) {
issueNumber = pullRequestNumber
} else {
// If this is not a pull request, attempt to find a PR matching the sha
const commitPullsList = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
owner,
repo,
commit_sha: commitSha,
})
issueNumber = commitPullsList.data && getIssueNumberFromCommitPullsList(commitPullsList.data)
issueNumber = await getIssueNumberFromCommitPullsList(octokit, owner, repo, commitSha)
}
if (!issueNumber) {
core.info(
'this action only works on issues and pull_request events or other commits associated with a pull',
'no issue number found, use a pull_request event, a pull event, or provide an issue input',
)
core.setOutput('comment-created', 'false')
return
@ -184,13 +51,7 @@ const run = async (): Promise<void> => {
if (!allowRepeats) {
core.debug('repeat comments are disallowed, checking for existing')
const { data: comments } = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: issueNumber,
})
existingCommentId = getExistingCommentId(comments, messageIdComment)
existingCommentId = await getExistingCommentId(octokit, owner, repo, issueNumber, messageId)
if (existingCommentId) {
core.debug(`existing comment found with id: ${existingCommentId}`)
@ -198,7 +59,8 @@ const run = async (): Promise<void> => {
}
let comment: CreateIssueCommentResponseData | null | undefined
const body = `${messageIdComment}\n\n${message}`
const body = `${messageId}\n\n${message}`
if (proxyUrl) {
comment = await createCommentProxy({
@ -212,22 +74,10 @@ const run = async (): Promise<void> => {
})
core.setOutput(existingCommentId ? 'comment-updated' : 'comment-created', 'true')
} else if (existingCommentId) {
const updatedComment = await octokit.rest.issues.updateComment({
comment_id: existingCommentId,
owner,
repo,
body,
})
comment = updatedComment.data
comment = await updateComment(octokit, owner, repo, existingCommentId, body)
core.setOutput('comment-updated', 'true')
} else {
const createdComment = await octokit.rest.issues.createComment({
issue_number: issueNumber,
owner,
repo,
body,
})
comment = createdComment.data
comment = await createComment(octokit, owner, repo, issueNumber, body)
core.setOutput('comment-created', 'true')
}
@ -240,8 +90,6 @@ const run = async (): Promise<void> => {
} catch (err) {
if (err instanceof Error) {
core.setFailed(err.message)
} else {
core.setFailed('unknown failure')
}
}
}

33
src/proxy.ts Normal file
View file

@ -0,0 +1,33 @@
import { HttpClient } from '@actions/http-client'
import { Endpoints } from '@octokit/types'
type CreateIssueCommentResponseData =
Endpoints['POST /repos/{owner}/{repo}/issues/{issue_number}/comments']['response']['data']
export interface CreateCommentProxyParams {
repoToken: string
commentId?: number
body: string
owner: string
repo: string
issueNumber: number
proxyUrl: string
}
export async function createCommentProxy(
params: CreateCommentProxyParams,
): Promise<CreateIssueCommentResponseData | null> {
const { repoToken, owner, repo, issueNumber, body, commentId, proxyUrl } = params
const http = new HttpClient('http-client-add-pr-comment')
const response = await http.postJson<CreateIssueCommentResponseData>(
`${proxyUrl}/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
{ comment_id: commentId, body },
{
['temporary-github-token']: repoToken,
},
)
return response.result
}