mirror of
https://github.com/marocchino/sticky-pull-request-comment.git
synced 2025-12-12 11:41:14 +00:00
feat: actual logic
This commit is contained in:
parent
29d48cbb29
commit
cb9470fc12
9 changed files with 108 additions and 147 deletions
13
.github/workflows/comment_on_pull_request.yml
vendored
Normal file
13
.github/workflows/comment_on_pull_request.yml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
name: Comment on Pull Request
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: ./
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
message: |
|
||||
Test ${{ github.sha }} is successfully ended.
|
||||
14
.github/workflows/test.yml
vendored
14
.github/workflows/test.yml
vendored
|
|
@ -1,20 +1,16 @@
|
|||
name: "Test typescript-action"
|
||||
name: test
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'releases/*'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm test
|
||||
- uses: ./
|
||||
with:
|
||||
milliseconds: 1000
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm test
|
||||
|
|
|
|||
74
README.md
74
README.md
|
|
@ -1,28 +1,23 @@
|
|||
# Create a JavaScript Action using TypeScript
|
||||
# Sticky Pull Request Comment
|
||||
|
||||
Use this template to bootstrap the creation of a JavaScript action.:rocket:
|
||||
Create comment on pull request, if exists update that comment.
|
||||
|
||||
This template includes compilication support, tests, a validation workflow, publishing, and versioning guidance.
|
||||
## Development
|
||||
|
||||
If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action)
|
||||
Install the dependencies
|
||||
|
||||
## Create an action from this template
|
||||
|
||||
Click the `Use this Template` and provide the new repo details for your action
|
||||
|
||||
## Code in Master
|
||||
|
||||
Install the dependencies
|
||||
```bash
|
||||
$ npm install
|
||||
```
|
||||
|
||||
Build the typescript
|
||||
|
||||
```bash
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
Run the tests :heavy_check_mark:
|
||||
Run the tests :heavy_check_mark:
|
||||
|
||||
```bash
|
||||
$ npm test
|
||||
|
||||
|
|
@ -34,41 +29,12 @@ $ npm test
|
|||
...
|
||||
```
|
||||
|
||||
## Change action.yml
|
||||
|
||||
The action.yml contains defines the inputs and output for your action.
|
||||
|
||||
Update the action.yml with your name, description, inputs and outputs for your action.
|
||||
|
||||
See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions)
|
||||
|
||||
## Change the Code
|
||||
|
||||
Most toolkit and CI/CD operations involve async operations so the action is run in an async function.
|
||||
|
||||
```javascript
|
||||
import * as core from '@actions/core';
|
||||
...
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
...
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
```
|
||||
|
||||
See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/README.md#packages) for the various packages.
|
||||
|
||||
## Publish to a distribution branch
|
||||
|
||||
Actions are run from GitHub repos. We will create a releases branch and only checkin production modules (core in this case).
|
||||
Actions are run from GitHub repos. We will create a releases branch and only checkin production modules (core in this case).
|
||||
|
||||
Comment out node_modules in .gitignore and create a releases/v1 branch
|
||||
|
||||
```bash
|
||||
# comment out in distribution branches
|
||||
# node_modules/
|
||||
|
|
@ -86,28 +52,16 @@ $ git commit -a -m "prod dependencies"
|
|||
$ git push origin releases/v1
|
||||
```
|
||||
|
||||
Your action is now published! :rocket:
|
||||
Your action is now published! :rocket:
|
||||
|
||||
See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
|
||||
|
||||
## Validate
|
||||
|
||||
You can now validate the action by referencing the releases/v1 branch
|
||||
|
||||
```yaml
|
||||
uses: actions/typescript-action@releases/v1
|
||||
with:
|
||||
milliseconds: 1000
|
||||
```
|
||||
|
||||
See the [actions tab](https://github.com/actions/javascript-action/actions) for runs of this action! :rocket:
|
||||
|
||||
## Usage:
|
||||
|
||||
After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and tested action
|
||||
|
||||
```yaml
|
||||
uses: actions/typescript-action@v1
|
||||
uses: marocchino/sticky-pull-request-comment@v1
|
||||
with:
|
||||
milliseconds: 1000
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
message: |
|
||||
Release ${{ github.sha }} to <https://pr-${{ github.event.number }}.example.com>
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,27 +1,2 @@
|
|||
import {wait} from '../src/wait'
|
||||
import * as process from 'process'
|
||||
import * as cp from 'child_process'
|
||||
import * as path from 'path'
|
||||
|
||||
test('throws invalid number', async() => {
|
||||
const input = parseInt('foo', 10);
|
||||
await expect(wait(input)).rejects.toThrow('milleseconds not a number');
|
||||
});
|
||||
|
||||
test('wait 500 ms', async() => {
|
||||
const start = new Date();
|
||||
await wait(500);
|
||||
const end = new Date();
|
||||
var delta = Math.abs(end.getTime() - start.getTime());
|
||||
expect(delta).toBeGreaterThan(450);
|
||||
});
|
||||
|
||||
// shows how the runner will run a javascript action with env / stdout protocol
|
||||
test('test runs', () => {
|
||||
process.env['INPUT_MILLISECONDS'] = '500';
|
||||
const ip = path.join(__dirname, '..', 'lib', 'main.js');
|
||||
const options: cp.ExecSyncOptions = {
|
||||
env: process.env
|
||||
};
|
||||
console.log(cp.execSync(`node ${ip}`, options).toString());
|
||||
});
|
||||
test("create a comment when no comment", async () => {});
|
||||
test("update a comment when comment is exists", async () => {});
|
||||
|
|
|
|||
17
action.yml
17
action.yml
|
|
@ -1,10 +1,11 @@
|
|||
name: 'Your name here'
|
||||
description: 'Provide a description here'
|
||||
author: 'Your name or organization here'
|
||||
name: "Your name here"
|
||||
description: "Provide a description here"
|
||||
author: "Your name or organization here"
|
||||
inputs:
|
||||
myInput: # change this
|
||||
description: 'input description here'
|
||||
default: 'default value if applicable'
|
||||
message:
|
||||
description: "comment message"
|
||||
GITHUB_TOKEN:
|
||||
description: "set secrets.GITHUB_TOKEN here"
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'lib/main.js'
|
||||
using: "node12"
|
||||
main: "lib/main.js"
|
||||
|
|
|
|||
38
lib/main.js
38
lib/main.js
|
|
@ -1,9 +1,10 @@
|
|||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
|
|
@ -16,19 +17,36 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const wait_1 = require("./wait");
|
||||
const github_1 = require("@actions/github");
|
||||
function run() {
|
||||
var _a, _b, _c;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds');
|
||||
console.log(`Waiting ${ms} milliseconds ...`);
|
||||
core.debug((new Date()).toTimeString());
|
||||
wait_1.wait(parseInt(ms));
|
||||
core.debug((new Date()).toTimeString());
|
||||
core.setOutput('time', new Date().toTimeString());
|
||||
const repo = github_1.context.repo;
|
||||
const issue_number = (_c = (_b = (_a = github_1.context) === null || _a === void 0 ? void 0 : _a.payload) === null || _b === void 0 ? void 0 : _b.pull_request) === null || _c === void 0 ? void 0 : _c.number;
|
||||
if (!issue_number) {
|
||||
core.setFailed("This action only works for pull_request");
|
||||
return;
|
||||
}
|
||||
const body = core.getInput("message");
|
||||
const githubToken = core.getInput("GITHUB_TOKEN");
|
||||
if (!body || !githubToken) {
|
||||
core.setFailed("invalid input: please check your workflow");
|
||||
return;
|
||||
}
|
||||
const octokit = new github_1.GitHub(githubToken);
|
||||
const { data: comments } = yield octokit.issues.listComments(Object.assign(Object.assign({}, repo), { issue_number }));
|
||||
const myComment = comments.find(comment => comment.user.login === "github-actions[bot]");
|
||||
if (myComment) {
|
||||
yield octokit.issues.updateComment(Object.assign(Object.assign({}, repo), { comment_id: myComment.id, body }));
|
||||
}
|
||||
else {
|
||||
yield octokit.issues.createComment(Object.assign(Object.assign({}, repo), { issue_number,
|
||||
body }));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
catch ({ message }) {
|
||||
core.setFailed(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
11
lib/wait.js
11
lib/wait.js
|
|
@ -1,11 +0,0 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
function wait(milliseconds) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof (milliseconds) !== 'number') {
|
||||
throw new Error('milleseconds not a number');
|
||||
}
|
||||
setTimeout(() => resolve("done!"), milliseconds);
|
||||
});
|
||||
}
|
||||
exports.wait = wait;
|
||||
49
src/main.ts
49
src/main.ts
|
|
@ -1,18 +1,43 @@
|
|||
import * as core from '@actions/core';
|
||||
import {wait} from './wait'
|
||||
import * as core from "@actions/core";
|
||||
import { context, GitHub } from "@actions/github";
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
const ms = core.getInput('milliseconds');
|
||||
console.log(`Waiting ${ms} milliseconds ...`)
|
||||
|
||||
core.debug((new Date()).toTimeString())
|
||||
await wait(parseInt(ms, 10));
|
||||
core.debug((new Date()).toTimeString())
|
||||
|
||||
core.setOutput('time', new Date().toTimeString());
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
const repo = context.repo;
|
||||
const issue_number = context?.payload?.pull_request?.number;
|
||||
if (!issue_number) {
|
||||
core.setFailed("This action only works for pull_request");
|
||||
return;
|
||||
}
|
||||
const body = core.getInput("message");
|
||||
const githubToken = core.getInput("GITHUB_TOKEN");
|
||||
if (!body || !githubToken) {
|
||||
core.setFailed("invalid input: please check your workflow");
|
||||
return;
|
||||
}
|
||||
const octokit = new GitHub(githubToken);
|
||||
const { data: comments } = await octokit.issues.listComments({
|
||||
...repo,
|
||||
issue_number
|
||||
});
|
||||
const myComment = comments.find(
|
||||
comment => comment.user.login === "github-actions[bot]"
|
||||
);
|
||||
if (myComment) {
|
||||
await octokit.issues.updateComment({
|
||||
...repo,
|
||||
comment_id: myComment.id,
|
||||
body
|
||||
});
|
||||
} else {
|
||||
await octokit.issues.createComment({
|
||||
...repo,
|
||||
issue_number,
|
||||
body
|
||||
});
|
||||
}
|
||||
} catch ({ message }) {
|
||||
core.setFailed(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
10
src/wait.ts
10
src/wait.ts
|
|
@ -1,10 +0,0 @@
|
|||
export function wait(milliseconds: number) {
|
||||
return new Promise((resolve) => {
|
||||
if (isNaN(milliseconds)) {
|
||||
throw new Error('milleseconds not a number');
|
||||
}
|
||||
|
||||
setTimeout(() => resolve("done!"), milliseconds)
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue