Convert to typescript
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
+18
-16
@@ -1,17 +1,19 @@
|
||||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
}
|
||||
}
|
||||
"env": { "node": true, "jest": true },
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/typescript",
|
||||
"plugin:prettier/recommended",
|
||||
"prettier/@typescript-eslint"
|
||||
],
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"@typescript-eslint/camelcase": "off"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ jobs:
|
||||
with:
|
||||
node-version: 12.x
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm run format-check
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
- run: npm run package
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
node_modules
|
||||
lib/
|
||||
node_modules/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
import {
|
||||
Inputs,
|
||||
Command,
|
||||
SlashCommandPayload,
|
||||
commandDefaults,
|
||||
getCommandsConfigFromInputs,
|
||||
getCommandsConfigFromJson,
|
||||
actorHasPermission,
|
||||
configIsValid,
|
||||
getSlashCommandPayload
|
||||
} from '../lib/command-helper'
|
||||
|
||||
describe('command-helper tests', () => {
|
||||
test('building config with required inputs only', async () => {
|
||||
const inputs: Inputs = {
|
||||
token: '',
|
||||
reactionToken: '',
|
||||
reactions: true,
|
||||
commands: 'list, of, slash, commands',
|
||||
permission: 'write',
|
||||
issueType: 'both',
|
||||
allowEdits: false,
|
||||
// Should be process.env.GITHUB_REPOSITORY, but '' for tests
|
||||
repository: '',
|
||||
eventTypeSuffix: '-command',
|
||||
namedArgs: false,
|
||||
config: '',
|
||||
configFromFile: ''
|
||||
}
|
||||
const commands = inputs.commands.replace(/\s+/g, '').split(',')
|
||||
const config = getCommandsConfigFromInputs(inputs)
|
||||
expect(config.length).toEqual(4)
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i])
|
||||
expect(config[i].permission).toEqual(commandDefaults.permission)
|
||||
expect(config[i].issue_type).toEqual(commandDefaults.issue_type)
|
||||
expect(config[i].allow_edits).toEqual(commandDefaults.allow_edits)
|
||||
expect(config[i].repository).toEqual(commandDefaults.repository)
|
||||
expect(config[i].event_type_suffix).toEqual(
|
||||
commandDefaults.event_type_suffix
|
||||
)
|
||||
expect(config[i].named_args).toEqual(commandDefaults.named_args)
|
||||
}
|
||||
})
|
||||
|
||||
test('building config with optional inputs', async () => {
|
||||
const inputs: Inputs = {
|
||||
token: '',
|
||||
reactionToken: '',
|
||||
reactions: true,
|
||||
commands: 'list, of, slash, commands',
|
||||
permission: 'admin',
|
||||
issueType: 'pull-request',
|
||||
allowEdits: true,
|
||||
repository: 'owner/repo',
|
||||
eventTypeSuffix: '-cmd',
|
||||
namedArgs: true,
|
||||
config: '',
|
||||
configFromFile: ''
|
||||
}
|
||||
const commands = inputs.commands.replace(/\s+/g, '').split(',')
|
||||
const config = getCommandsConfigFromInputs(inputs)
|
||||
expect(config.length).toEqual(4)
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i])
|
||||
expect(config[i].permission).toEqual(inputs.permission)
|
||||
expect(config[i].issue_type).toEqual(inputs.issueType)
|
||||
expect(config[i].allow_edits).toEqual(inputs.allowEdits)
|
||||
expect(config[i].repository).toEqual(inputs.repository)
|
||||
expect(config[i].event_type_suffix).toEqual(inputs.eventTypeSuffix)
|
||||
expect(config[i].named_args).toEqual(inputs.namedArgs)
|
||||
}
|
||||
})
|
||||
|
||||
test('building config with required JSON only', async () => {
|
||||
const json = `[
|
||||
{
|
||||
"command": "do-stuff"
|
||||
},
|
||||
{
|
||||
"command": "test-all-the-things"
|
||||
}
|
||||
]`
|
||||
const commands = ['do-stuff', 'test-all-the-things']
|
||||
const config = getCommandsConfigFromJson(json)
|
||||
expect(config.length).toEqual(2)
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i])
|
||||
expect(config[i].permission).toEqual(commandDefaults.permission)
|
||||
expect(config[i].issue_type).toEqual(commandDefaults.issue_type)
|
||||
expect(config[i].allow_edits).toEqual(commandDefaults.allow_edits)
|
||||
expect(config[i].repository).toEqual(commandDefaults.repository)
|
||||
expect(config[i].event_type_suffix).toEqual(
|
||||
commandDefaults.event_type_suffix
|
||||
)
|
||||
expect(config[i].named_args).toEqual(commandDefaults.named_args)
|
||||
}
|
||||
})
|
||||
|
||||
test('building config with optional JSON properties', async () => {
|
||||
const json = `[
|
||||
{
|
||||
"command": "do-stuff",
|
||||
"permission": "admin",
|
||||
"issue_type": "pull-request",
|
||||
"allow_edits": true,
|
||||
"repository": "owner/repo",
|
||||
"event_type_suffix": "-cmd",
|
||||
"named_args": true
|
||||
},
|
||||
{
|
||||
"command": "test-all-the-things",
|
||||
"permission": "read"
|
||||
}
|
||||
]`
|
||||
const commands = ['do-stuff', 'test-all-the-things']
|
||||
const config = getCommandsConfigFromJson(json)
|
||||
expect(config.length).toEqual(2)
|
||||
expect(config[0].command).toEqual(commands[0])
|
||||
expect(config[0].permission).toEqual('admin')
|
||||
expect(config[0].issue_type).toEqual('pull-request')
|
||||
expect(config[0].allow_edits).toBeTruthy()
|
||||
expect(config[0].repository).toEqual('owner/repo')
|
||||
expect(config[0].event_type_suffix).toEqual('-cmd')
|
||||
expect(config[0].named_args).toBeTruthy()
|
||||
expect(config[1].command).toEqual(commands[1])
|
||||
expect(config[1].permission).toEqual('read')
|
||||
expect(config[1].issue_type).toEqual(commandDefaults.issue_type)
|
||||
})
|
||||
|
||||
test('valid config', async () => {
|
||||
const config: Command[] = [
|
||||
{
|
||||
command: 'test',
|
||||
permission: 'write',
|
||||
issue_type: 'both',
|
||||
allow_edits: false,
|
||||
repository: 'peter-evans/slash-command-dispatch',
|
||||
event_type_suffix: '-command',
|
||||
named_args: false
|
||||
}
|
||||
]
|
||||
expect(configIsValid(config)).toBeTruthy()
|
||||
})
|
||||
|
||||
test('invalid permission level in config', async () => {
|
||||
const config: Command[] = [
|
||||
{
|
||||
command: 'test',
|
||||
permission: 'test-case-invalid-permission',
|
||||
issue_type: 'both',
|
||||
allow_edits: false,
|
||||
repository: 'peter-evans/slash-command-dispatch',
|
||||
event_type_suffix: '-command',
|
||||
named_args: false
|
||||
}
|
||||
]
|
||||
expect(configIsValid(config)).toBeFalsy()
|
||||
})
|
||||
|
||||
test('invalid issue type in config', async () => {
|
||||
const config: Command[] = [
|
||||
{
|
||||
command: 'test',
|
||||
permission: 'write',
|
||||
issue_type: 'test-case-invalid-issue-type',
|
||||
allow_edits: false,
|
||||
repository: 'peter-evans/slash-command-dispatch',
|
||||
event_type_suffix: '-command',
|
||||
named_args: false
|
||||
}
|
||||
]
|
||||
expect(configIsValid(config)).toBeFalsy()
|
||||
})
|
||||
|
||||
test('actor does not have permission', async () => {
|
||||
expect(actorHasPermission('none', 'read')).toBeFalsy()
|
||||
expect(actorHasPermission('read', 'write')).toBeFalsy()
|
||||
expect(actorHasPermission('write', 'admin')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('actor has permission', async () => {
|
||||
expect(actorHasPermission('read', 'none')).toBeTruthy()
|
||||
expect(actorHasPermission('write', 'read')).toBeTruthy()
|
||||
expect(actorHasPermission('admin', 'write')).toBeTruthy()
|
||||
expect(actorHasPermission('write', 'write')).toBeTruthy()
|
||||
})
|
||||
|
||||
test('slash command payload', async () => {
|
||||
const commandWords = ['test', 'arg1', 'arg2', 'arg3']
|
||||
const namedArgs = false
|
||||
const payload: SlashCommandPayload = {
|
||||
command: 'test',
|
||||
args: 'arg1 arg2 arg3',
|
||||
arg1: 'arg1',
|
||||
arg2: 'arg2',
|
||||
arg3: 'arg3'
|
||||
}
|
||||
expect(getSlashCommandPayload(commandWords, namedArgs)).toEqual(payload)
|
||||
})
|
||||
|
||||
test('slash command payload with named args', async () => {
|
||||
const commandWords = ['test', 'branch=master', 'arg1', 'env=prod', 'arg2']
|
||||
const namedArgs = true
|
||||
const payload: SlashCommandPayload = {
|
||||
command: 'test',
|
||||
args: 'branch=master arg1 env=prod arg2',
|
||||
unnamed_args: 'arg1 arg2',
|
||||
branch: 'master',
|
||||
env: 'prod',
|
||||
arg1: 'arg1',
|
||||
arg2: 'arg2'
|
||||
}
|
||||
expect(getSlashCommandPayload(commandWords, namedArgs)).toEqual(payload)
|
||||
})
|
||||
|
||||
test('slash command payload with malformed named args', async () => {
|
||||
const commandWords = ['test', 'branch=', 'arg1', 'e-nv=prod', 'arg2']
|
||||
const namedArgs = true
|
||||
const payload: SlashCommandPayload = {
|
||||
command: 'test',
|
||||
args: 'branch= arg1 e-nv=prod arg2',
|
||||
unnamed_args: 'branch= arg1 e-nv=prod arg2',
|
||||
arg1: 'branch=',
|
||||
arg2: 'arg1',
|
||||
arg3: 'e-nv=prod',
|
||||
arg4: 'arg2'
|
||||
}
|
||||
expect(getSlashCommandPayload(commandWords, namedArgs)).toEqual(payload)
|
||||
})
|
||||
})
|
||||
@@ -9,21 +9,28 @@ inputs:
|
||||
default: ${{ github.token }}
|
||||
reactions:
|
||||
description: 'Add reactions to comments containing commands.'
|
||||
default: true
|
||||
commands:
|
||||
description: 'A comma separated list of commands.'
|
||||
required: true
|
||||
permission:
|
||||
description: 'The repository permission level required by the user to dispatch commands.'
|
||||
default: write
|
||||
issue-type:
|
||||
description: 'The issue type required for commands.'
|
||||
default: both
|
||||
allow-edits:
|
||||
description: 'Allow edited comments to trigger command dispatches.'
|
||||
default: false
|
||||
repository:
|
||||
description: 'The full name of the repository to send the dispatch events.'
|
||||
default: ${{ github.repository }}
|
||||
event-type-suffix:
|
||||
description: 'The repository dispatch event type suffix for the commands.'
|
||||
default: -command
|
||||
named-args:
|
||||
description: 'Parse named arguments and add them to the command payload.'
|
||||
default: false
|
||||
config:
|
||||
description: 'JSON configuration for commands.'
|
||||
config-from-file:
|
||||
|
||||
Vendored
+3985
-19814
File diff suppressed because it is too large
Load Diff
+11
-3
@@ -1,3 +1,11 @@
|
||||
process.env = Object.assign(process.env, {
|
||||
GITHUB_REPOSITORY: "peter-evans/slash-command-dispatch"
|
||||
});
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
}
|
||||
|
||||
Generated
+2630
-2150
File diff suppressed because it is too large
Load Diff
+29
-9
@@ -1,18 +1,25 @@
|
||||
{
|
||||
"name": "slash-command-dispatch",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Create repository dispatch events for slash commands",
|
||||
"main": "src/index.js",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"lint": "eslint src/index.js",
|
||||
"package": "ncc build src/index.js -o dist",
|
||||
"test": "eslint src/index.js && jest"
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write '**/*.ts'",
|
||||
"format-check": "prettier --check '**/*.ts'",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/peter-evans/slash-command-dispatch.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"keywords": [
|
||||
"slash",
|
||||
"command",
|
||||
"dispatch"
|
||||
],
|
||||
"author": "Peter Evans",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
@@ -21,11 +28,24 @@
|
||||
"homepage": "https://github.com/peter-evans/slash-command-dispatch#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "1.2.4",
|
||||
"@actions/github": "2.1.1"
|
||||
"@actions/github": "4.0.0",
|
||||
"@octokit/core": "3.1.0",
|
||||
"@octokit/plugin-paginate-rest": "2.2.3",
|
||||
"@octokit/plugin-rest-endpoint-methods": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zeit/ncc": "0.22.1",
|
||||
"eslint": "6.8.0",
|
||||
"jest": "26.0.1"
|
||||
"@types/jest": "26.0.4",
|
||||
"@types/node": "14.0.23",
|
||||
"@typescript-eslint/parser": "3.6.1",
|
||||
"@zeit/ncc": "0.22.3",
|
||||
"eslint": "7.4.0",
|
||||
"eslint-plugin-github": "4.0.1",
|
||||
"eslint-plugin-jest": "23.18.0",
|
||||
"jest": "26.1.0",
|
||||
"jest-circus": "26.1.0",
|
||||
"js-yaml": "3.14.0",
|
||||
"prettier": "2.0.5",
|
||||
"ts-jest": "26.1.2",
|
||||
"typescript": "3.9.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as fs from 'fs'
|
||||
import {inspect} from 'util'
|
||||
import {Octokit} from './octokit-client'
|
||||
|
||||
const NAMED_ARG_PATTERN = /^(?<name>[a-zA-Z0-9_]+)=(?<value>[^\s]+)$/
|
||||
|
||||
export const MAX_ARGS = 50
|
||||
|
||||
export interface Inputs {
|
||||
token: string
|
||||
reactionToken: string
|
||||
reactions: boolean
|
||||
commands: string
|
||||
permission: string
|
||||
issueType: string
|
||||
allowEdits: boolean
|
||||
repository: string
|
||||
eventTypeSuffix: string
|
||||
namedArgs: boolean
|
||||
config: string
|
||||
configFromFile: string
|
||||
}
|
||||
|
||||
export interface Command {
|
||||
command: string
|
||||
permission: string
|
||||
issue_type: string
|
||||
allow_edits: boolean
|
||||
repository: string
|
||||
event_type_suffix: string
|
||||
named_args: boolean
|
||||
}
|
||||
|
||||
interface Repo {
|
||||
owner: string
|
||||
repo: string
|
||||
}
|
||||
|
||||
export interface SlashCommandPayload {
|
||||
command: string
|
||||
args: string
|
||||
[k: string]: string
|
||||
}
|
||||
|
||||
export const commandDefaults = Object.freeze({
|
||||
permission: 'write',
|
||||
issue_type: 'both',
|
||||
allow_edits: false,
|
||||
repository: process.env.GITHUB_REPOSITORY || '',
|
||||
event_type_suffix: '-command',
|
||||
named_args: false
|
||||
})
|
||||
|
||||
export function toBool(input: string, defaultVal: boolean): boolean {
|
||||
if (typeof input === 'boolean') {
|
||||
return input
|
||||
} else if (typeof input === 'undefined' || input.length == 0) {
|
||||
return defaultVal
|
||||
} else {
|
||||
return input === 'true'
|
||||
}
|
||||
}
|
||||
|
||||
export function getInputs(): Inputs {
|
||||
// Defaults set in action.yml
|
||||
return {
|
||||
token: core.getInput('token'),
|
||||
reactionToken: core.getInput('reaction-token'),
|
||||
reactions: core.getInput('reactions') === 'true',
|
||||
commands: core.getInput('commands'),
|
||||
permission: core.getInput('permission'),
|
||||
issueType: core.getInput('issue-type'),
|
||||
allowEdits: core.getInput('allow-edits') === 'true',
|
||||
repository: core.getInput('repository'),
|
||||
eventTypeSuffix: core.getInput('event-type-suffix'),
|
||||
namedArgs: core.getInput('named-args') === 'true',
|
||||
config: core.getInput('config'),
|
||||
configFromFile: core.getInput('config-from-file')
|
||||
}
|
||||
}
|
||||
|
||||
export function getCommandsConfig(inputs: Inputs): Command[] {
|
||||
if (inputs.configFromFile) {
|
||||
core.info(`Using JSON configuration from file '${inputs.configFromFile}'.`)
|
||||
const json = fs.readFileSync(inputs.configFromFile, {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
return getCommandsConfigFromJson(json)
|
||||
} else if (inputs.config) {
|
||||
core.info(`Using JSON configuration from 'config' input.`)
|
||||
return getCommandsConfigFromJson(inputs.config)
|
||||
} else {
|
||||
core.info(`Using configuration from yaml inputs.`)
|
||||
return getCommandsConfigFromInputs(inputs)
|
||||
}
|
||||
}
|
||||
|
||||
export function getCommandsConfigFromInputs(inputs: Inputs): Command[] {
|
||||
// Get commands
|
||||
const commands = inputs.commands.replace(/\s+/g, '').split(',')
|
||||
core.debug(`Commands: ${inspect(commands)}`)
|
||||
|
||||
// Build config
|
||||
const config: Command[] = []
|
||||
for (const c of commands) {
|
||||
const cmd: Command = {
|
||||
command: c,
|
||||
permission: inputs.permission,
|
||||
issue_type: inputs.issueType,
|
||||
allow_edits: inputs.allowEdits,
|
||||
repository: inputs.repository,
|
||||
event_type_suffix: inputs.eventTypeSuffix,
|
||||
named_args: inputs.namedArgs
|
||||
}
|
||||
config.push(cmd)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
export function getCommandsConfigFromJson(json: string): Command[] {
|
||||
const jsonConfig = JSON.parse(json)
|
||||
core.debug(`JSON config: ${inspect(jsonConfig)}`)
|
||||
|
||||
const config: Command[] = []
|
||||
for (const jc of jsonConfig) {
|
||||
const cmd: Command = {
|
||||
command: jc.command,
|
||||
permission: jc.permission ? jc.permission : commandDefaults.permission,
|
||||
issue_type: jc.issue_type ? jc.issue_type : commandDefaults.issue_type,
|
||||
allow_edits: toBool(jc.allow_edits, commandDefaults.allow_edits),
|
||||
repository: jc.repository ? jc.repository : commandDefaults.repository,
|
||||
event_type_suffix: jc.event_type_suffix
|
||||
? jc.event_type_suffix
|
||||
: commandDefaults.event_type_suffix,
|
||||
named_args: toBool(jc.named_args, commandDefaults.named_args)
|
||||
}
|
||||
config.push(cmd)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
export function configIsValid(config: Command[]): boolean {
|
||||
for (const command of config) {
|
||||
if (!['none', 'read', 'write', 'admin'].includes(command.permission)) {
|
||||
core.setFailed(`'${command.permission}' is not a valid 'permission'.`)
|
||||
return false
|
||||
}
|
||||
if (!['issue', 'pull-request', 'both'].includes(command.issue_type)) {
|
||||
core.setFailed(`'${command.issue_type}' is not a valid 'issue-type'.`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export function actorHasPermission(
|
||||
actorPermission: string,
|
||||
commandPermission: string
|
||||
): boolean {
|
||||
const permissionLevels = Object.freeze({
|
||||
none: 1,
|
||||
read: 2,
|
||||
write: 3,
|
||||
admin: 4
|
||||
})
|
||||
core.debug(`Actor permission level: ${permissionLevels[actorPermission]}`)
|
||||
core.debug(`Command permission level: ${permissionLevels[commandPermission]}`)
|
||||
return (
|
||||
permissionLevels[actorPermission] >= permissionLevels[commandPermission]
|
||||
)
|
||||
}
|
||||
|
||||
export async function getActorPermission(
|
||||
octokit: InstanceType<typeof Octokit>,
|
||||
repo: Repo,
|
||||
actor: string
|
||||
): Promise<string> {
|
||||
const {
|
||||
data: {permission}
|
||||
} = await octokit.repos.getCollaboratorPermissionLevel({
|
||||
...repo,
|
||||
username: actor
|
||||
})
|
||||
return permission
|
||||
}
|
||||
|
||||
export async function addReaction(
|
||||
octokit: InstanceType<typeof Octokit>,
|
||||
repo: Repo,
|
||||
commentId: number,
|
||||
reaction:
|
||||
| '+1'
|
||||
| '-1'
|
||||
| 'laugh'
|
||||
| 'confused'
|
||||
| 'heart'
|
||||
| 'hooray'
|
||||
| 'rocket'
|
||||
| 'eyes'
|
||||
): Promise<void> {
|
||||
try {
|
||||
await octokit.reactions.createForIssueComment({
|
||||
...repo,
|
||||
comment_id: commentId,
|
||||
content: reaction
|
||||
})
|
||||
} catch (error) {
|
||||
core.debug(inspect(error))
|
||||
core.warning(`Failed to set reaction on comment ID ${commentId}.`)
|
||||
}
|
||||
}
|
||||
|
||||
export function getSlashCommandPayload(
|
||||
commandWords: string[],
|
||||
namedArgs: boolean
|
||||
): SlashCommandPayload {
|
||||
const payload: SlashCommandPayload = {
|
||||
command: commandWords[0],
|
||||
args: ''
|
||||
}
|
||||
if (commandWords.length > 1) {
|
||||
const argWords = commandWords.slice(1, MAX_ARGS + 1)
|
||||
payload.args = argWords.join(' ')
|
||||
// Parse named and unnamed args
|
||||
let unnamedCount = 1
|
||||
const unnamedArgs: string[] = []
|
||||
for (const argWord of argWords) {
|
||||
if (namedArgs && NAMED_ARG_PATTERN.test(argWord)) {
|
||||
const result = NAMED_ARG_PATTERN.exec(argWord)
|
||||
if (result && result.groups) {
|
||||
payload[`${result.groups['name']}`] = result.groups['value']
|
||||
}
|
||||
} else {
|
||||
unnamedArgs.push(argWord)
|
||||
payload[`arg${unnamedCount}`] = argWord
|
||||
unnamedCount += 1
|
||||
}
|
||||
}
|
||||
// Add a string of only the unnamed args
|
||||
if (namedArgs && unnamedArgs.length > 0) {
|
||||
payload['unnamed_args'] = unnamedArgs.join(' ')
|
||||
}
|
||||
}
|
||||
return payload
|
||||
}
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
const { inspect } = require("util");
|
||||
var fs = require("fs");
|
||||
const core = require("@actions/core");
|
||||
|
||||
const MAX_ARGS = 50;
|
||||
const namedArgPattern = /^(?<name>[a-zA-Z0-9_]+)=(?<value>[^\s]+)$/;
|
||||
|
||||
const commandDefaults = Object.freeze({
|
||||
permission: "write",
|
||||
issue_type: "both",
|
||||
allow_edits: false,
|
||||
repository: process.env.GITHUB_REPOSITORY,
|
||||
event_type_suffix: "-command",
|
||||
named_args: false
|
||||
});
|
||||
|
||||
function toBool(input, defaultVal) {
|
||||
if (typeof input === 'boolean') {
|
||||
return input;
|
||||
} else if (typeof input === 'undefined' || input.length == 0) {
|
||||
return defaultVal;
|
||||
} else {
|
||||
return input === "true";
|
||||
}
|
||||
}
|
||||
|
||||
function getInputs() {
|
||||
return {
|
||||
token: core.getInput("token"),
|
||||
reactionToken: core.getInput("reaction-token"),
|
||||
reactions: toBool(core.getInput("reactions"), true),
|
||||
commands: core.getInput("commands"),
|
||||
permission: core.getInput("permission"),
|
||||
issueType: core.getInput("issue-type"),
|
||||
allowEdits: core.getInput("allow-edits"),
|
||||
repository: core.getInput("repository"),
|
||||
eventTypeSuffix: core.getInput("event-type-suffix"),
|
||||
namedArgs: core.getInput("named-args"),
|
||||
config: core.getInput("config"),
|
||||
configFromFile: core.getInput("config-from-file")
|
||||
};
|
||||
}
|
||||
|
||||
function getCommandsConfig(inputs) {
|
||||
if (inputs.configFromFile) {
|
||||
core.info(`Using JSON configuration from file '${inputs.configFromFile}'.`);
|
||||
return getCommandsConfigFromJson(fs.readFileSync(inputs.configFromFile));
|
||||
} else if (inputs.config) {
|
||||
core.info(`Using JSON configuration from 'config' input.`);
|
||||
return getCommandsConfigFromJson(inputs.config);
|
||||
} else {
|
||||
core.info(`Using configuration from yaml inputs.`);
|
||||
return getCommandsConfigFromInputs(inputs);
|
||||
}
|
||||
}
|
||||
|
||||
function extend(obj1, obj2) {
|
||||
var result = {};
|
||||
for (val in obj1) result[val] = obj1[val];
|
||||
for (val in obj2) result[val] = obj2[val];
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCommandsConfigFromInputs(inputs) {
|
||||
// Get commands
|
||||
const commands = inputs.commands.replace(/\s+/g, "").split(",");
|
||||
core.debug(`Commands: ${inspect(commands)}`);
|
||||
|
||||
// Build config
|
||||
var config = [];
|
||||
for (const c of commands) {
|
||||
var cmd = {};
|
||||
cmd.command = c;
|
||||
cmd = extend(commandDefaults, cmd);
|
||||
cmd.permission = inputs.permission ? inputs.permission : cmd.permission;
|
||||
cmd.issue_type = inputs.issueType ? inputs.issueType : cmd.issue_type;
|
||||
cmd.allow_edits = toBool(inputs.allowEdits, cmd.allow_edits);
|
||||
cmd.repository = inputs.repository ? inputs.repository : cmd.repository;
|
||||
cmd.event_type_suffix = inputs.eventTypeSuffix
|
||||
? inputs.eventTypeSuffix
|
||||
: cmd.event_type_suffix;
|
||||
cmd.named_args = toBool(inputs.namedArgs, cmd.named_args);
|
||||
config.push(cmd);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
function getCommandsConfigFromJson(json) {
|
||||
const jsonConfig = JSON.parse(json);
|
||||
core.debug(`JSON config: ${inspect(jsonConfig)}`);
|
||||
|
||||
var config = [];
|
||||
for (const jc of jsonConfig) {
|
||||
var cmd = {};
|
||||
cmd.command = jc.command;
|
||||
cmd = extend(commandDefaults, cmd);
|
||||
cmd.permission = jc.permission ? jc.permission : cmd.permission;
|
||||
cmd.issue_type = jc.issue_type ? jc.issue_type : cmd.issue_type;
|
||||
cmd.allow_edits = toBool(jc.allow_edits, cmd.allow_edits);
|
||||
cmd.repository = jc.repository ? jc.repository : cmd.repository;
|
||||
cmd.event_type_suffix = jc.event_type_suffix
|
||||
? jc.event_type_suffix
|
||||
: cmd.event_type_suffix;
|
||||
cmd.named_args = toBool(jc.named_args, cmd.named_args);
|
||||
config.push(cmd);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
function configIsValid(config) {
|
||||
for (const command of config) {
|
||||
if (!["none", "read", "write", "admin"].includes(command.permission)) {
|
||||
core.setFailed(`'${command.permission}' is not a valid 'permission'.`);
|
||||
return false;
|
||||
}
|
||||
if (!["issue", "pull-request", "both"].includes(command.issue_type)) {
|
||||
core.setFailed(`'${command.issue_type}' is not a valid 'issue-type'.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function actorHasPermission(actorPermission, commandPermission) {
|
||||
const permissionLevels = Object.freeze({
|
||||
none: 1,
|
||||
read: 2,
|
||||
write: 3,
|
||||
admin: 4
|
||||
});
|
||||
core.debug(`Actor permission level: ${permissionLevels[actorPermission]}`);
|
||||
core.debug(
|
||||
`Command permission level: ${permissionLevels[commandPermission]}`
|
||||
);
|
||||
return (
|
||||
permissionLevels[actorPermission] >= permissionLevels[commandPermission]
|
||||
);
|
||||
}
|
||||
|
||||
async function getActorPermission(octokit, repo, actor) {
|
||||
const {
|
||||
data: { permission }
|
||||
} = await octokit.repos.getCollaboratorPermissionLevel({
|
||||
...repo,
|
||||
username: actor
|
||||
});
|
||||
return permission;
|
||||
}
|
||||
|
||||
async function addReaction(octokit, repo, commentId, reaction) {
|
||||
try {
|
||||
await octokit.reactions.createForIssueComment({
|
||||
...repo,
|
||||
comment_id: commentId,
|
||||
content: reaction
|
||||
});
|
||||
} catch (error) {
|
||||
core.debug(inspect(error));
|
||||
core.warning(`Failed to set reaction on comment ID ${commentId}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function getSlashCommandPayload(commandWords, namedArgs) {
|
||||
var payload = {
|
||||
command: commandWords[0],
|
||||
args: ""
|
||||
};
|
||||
if (commandWords.length > 1) {
|
||||
const argWords = commandWords.slice(1, MAX_ARGS + 1);
|
||||
payload.args = argWords.join(" ");
|
||||
// Parse named and unnamed args
|
||||
var unnamedCount = 1;
|
||||
var unnamedArgs = [];
|
||||
for (var argWord of argWords) {
|
||||
if (namedArgs && namedArgPattern.test(argWord)) {
|
||||
const { groups: { name, value } } = namedArgPattern.exec(argWord);
|
||||
payload[`${name}`] = value;
|
||||
} else {
|
||||
unnamedArgs.push(argWord)
|
||||
payload[`arg${unnamedCount}`] = argWord;
|
||||
unnamedCount += 1;
|
||||
}
|
||||
}
|
||||
// Add a string of only the unnamed args
|
||||
if (namedArgs && unnamedArgs.length > 0) {
|
||||
payload["unnamed_args"] = unnamedArgs.join(" ");
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MAX_ARGS,
|
||||
commandDefaults,
|
||||
getInputs,
|
||||
getCommandsConfig,
|
||||
getCommandsConfigFromInputs,
|
||||
getCommandsConfigFromJson,
|
||||
configIsValid,
|
||||
actorHasPermission,
|
||||
getActorPermission,
|
||||
addReaction,
|
||||
getSlashCommandPayload
|
||||
};
|
||||
@@ -1,202 +0,0 @@
|
||||
const {
|
||||
commandDefaults,
|
||||
getCommandsConfigFromInputs,
|
||||
getCommandsConfigFromJson,
|
||||
actorHasPermission,
|
||||
configIsValid,
|
||||
getSlashCommandPayload
|
||||
} = require("./func");
|
||||
|
||||
test("building config with required inputs only", async () => {
|
||||
const inputs = {
|
||||
commands: "list, of, slash, commands"
|
||||
};
|
||||
const commands = inputs.commands.replace(/\s+/g, "").split(",");
|
||||
const config = getCommandsConfigFromInputs(inputs);
|
||||
expect(config.length).toEqual(4);
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i]);
|
||||
expect(config[i].permission).toEqual(commandDefaults.permission);
|
||||
expect(config[i].issue_type).toEqual(commandDefaults.issue_type);
|
||||
expect(config[i].allow_edits).toEqual(commandDefaults.allow_edits);
|
||||
expect(config[i].repository).toEqual(commandDefaults.repository);
|
||||
expect(config[i].event_type_suffix).toEqual(
|
||||
commandDefaults.event_type_suffix
|
||||
);
|
||||
expect(config[i].named_args).toEqual(commandDefaults.named_args);
|
||||
}
|
||||
});
|
||||
|
||||
test("building config with optional inputs", async () => {
|
||||
const inputs = {
|
||||
commands: "list, of, slash, commands",
|
||||
permission: "admin",
|
||||
issueType: "pull-request",
|
||||
allowEdits: true,
|
||||
repository: "owner/repo",
|
||||
eventTypeSuffix: "-cmd",
|
||||
namedArgs: true
|
||||
};
|
||||
const commands = inputs.commands.replace(/\s+/g, "").split(",");
|
||||
const config = getCommandsConfigFromInputs(inputs);
|
||||
expect(config.length).toEqual(4);
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i]);
|
||||
expect(config[i].permission).toEqual(inputs.permission);
|
||||
expect(config[i].issue_type).toEqual(inputs.issueType);
|
||||
expect(config[i].allow_edits).toEqual(inputs.allowEdits);
|
||||
expect(config[i].repository).toEqual(inputs.repository);
|
||||
expect(config[i].event_type_suffix).toEqual(inputs.eventTypeSuffix);
|
||||
expect(config[i].named_args).toEqual(inputs.namedArgs);
|
||||
}
|
||||
});
|
||||
|
||||
test("building config with required JSON only", async () => {
|
||||
const json = `[
|
||||
{
|
||||
"command": "do-stuff"
|
||||
},
|
||||
{
|
||||
"command": "test-all-the-things"
|
||||
}
|
||||
]`;
|
||||
const commands = ["do-stuff", "test-all-the-things"];
|
||||
const config = getCommandsConfigFromJson(json);
|
||||
expect(config.length).toEqual(2);
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
expect(config[i].command).toEqual(commands[i]);
|
||||
expect(config[i].permission).toEqual(commandDefaults.permission);
|
||||
expect(config[i].issue_type).toEqual(commandDefaults.issue_type);
|
||||
expect(config[i].allow_edits).toEqual(commandDefaults.allow_edits);
|
||||
expect(config[i].repository).toEqual(commandDefaults.repository);
|
||||
expect(config[i].event_type_suffix).toEqual(
|
||||
commandDefaults.event_type_suffix
|
||||
);
|
||||
expect(config[i].named_args).toEqual(commandDefaults.named_args);
|
||||
}
|
||||
});
|
||||
|
||||
test("building config with optional JSON properties", async () => {
|
||||
const json = `[
|
||||
{
|
||||
"command": "do-stuff",
|
||||
"permission": "admin",
|
||||
"issue_type": "pull-request",
|
||||
"allow_edits": true,
|
||||
"repository": "owner/repo",
|
||||
"event_type_suffix": "-cmd",
|
||||
"named_args": true
|
||||
},
|
||||
{
|
||||
"command": "test-all-the-things",
|
||||
"permission": "read"
|
||||
}
|
||||
]`;
|
||||
const commands = ["do-stuff", "test-all-the-things"];
|
||||
const config = getCommandsConfigFromJson(json);
|
||||
expect(config.length).toEqual(2);
|
||||
expect(config[0].command).toEqual(commands[0]);
|
||||
expect(config[0].permission).toEqual("admin");
|
||||
expect(config[0].issue_type).toEqual("pull-request");
|
||||
expect(config[0].allow_edits).toBeTruthy();
|
||||
expect(config[0].repository).toEqual("owner/repo");
|
||||
expect(config[0].event_type_suffix).toEqual("-cmd");
|
||||
expect(config[0].named_args).toBeTruthy();
|
||||
expect(config[1].command).toEqual(commands[1]);
|
||||
expect(config[1].permission).toEqual("read");
|
||||
expect(config[1].issue_type).toEqual(commandDefaults.issue_type);
|
||||
});
|
||||
|
||||
test("valid config", async () => {
|
||||
const config = [
|
||||
{
|
||||
command: "test",
|
||||
permission: "write",
|
||||
issue_type: "both",
|
||||
repository: "peter-evans/slash-command-dispatch",
|
||||
event_type_suffix: "-command"
|
||||
}
|
||||
];
|
||||
expect(configIsValid(config)).toBeTruthy();
|
||||
});
|
||||
|
||||
test("invalid permission level in config", async () => {
|
||||
const config = [
|
||||
{
|
||||
command: "test",
|
||||
permission: "test-case-invalid-permission",
|
||||
issue_type: "both",
|
||||
repository: "peter-evans/slash-command-dispatch",
|
||||
event_type_suffix: "-command"
|
||||
}
|
||||
];
|
||||
expect(configIsValid(config)).toBeFalsy();
|
||||
});
|
||||
|
||||
test("invalid issue type in config", async () => {
|
||||
const config = [
|
||||
{
|
||||
command: "test",
|
||||
permission: "write",
|
||||
issue_type: "test-case-invalid-issue-type",
|
||||
repository: "peter-evans/slash-command-dispatch",
|
||||
event_type_suffix: "-command"
|
||||
}
|
||||
];
|
||||
expect(configIsValid(config)).toBeFalsy();
|
||||
});
|
||||
|
||||
test("actor does not have permission", async () => {
|
||||
expect(actorHasPermission("none", "read")).toBeFalsy();
|
||||
expect(actorHasPermission("read", "write")).toBeFalsy();
|
||||
expect(actorHasPermission("write", "admin")).toBeFalsy();
|
||||
});
|
||||
|
||||
test("actor has permission", async () => {
|
||||
expect(actorHasPermission("read", "none")).toBeTruthy();
|
||||
expect(actorHasPermission("write", "read")).toBeTruthy();
|
||||
expect(actorHasPermission("admin", "write")).toBeTruthy();
|
||||
expect(actorHasPermission("write", "write")).toBeTruthy();
|
||||
});
|
||||
|
||||
test("slash command payload", async () => {
|
||||
commandWords = ["test", "arg1", "arg2", "arg3"];
|
||||
payload = {
|
||||
command: "test",
|
||||
args: "arg1 arg2 arg3",
|
||||
arg1: "arg1",
|
||||
arg2: "arg2",
|
||||
arg3: "arg3"
|
||||
};
|
||||
expect(getSlashCommandPayload(commandWords)).toEqual(payload);
|
||||
});
|
||||
|
||||
test("slash command payload with named args", async () => {
|
||||
commandWords = ["test", "branch=master", "arg1", "env=prod", "arg2"];
|
||||
namedArgs = true;
|
||||
payload = {
|
||||
command: "test",
|
||||
args: "branch=master arg1 env=prod arg2",
|
||||
unnamed_args: "arg1 arg2",
|
||||
branch: "master",
|
||||
env: "prod",
|
||||
arg1: "arg1",
|
||||
arg2: "arg2"
|
||||
};
|
||||
expect(getSlashCommandPayload(commandWords, namedArgs)).toEqual(payload);
|
||||
});
|
||||
|
||||
test("slash command payload with malformed named args", async () => {
|
||||
commandWords = ["test", "branch=", "arg1", "e-nv=prod", "arg2"];
|
||||
namedArgs = true;
|
||||
payload = {
|
||||
command: "test",
|
||||
args: "branch= arg1 e-nv=prod arg2",
|
||||
unnamed_args: "branch= arg1 e-nv=prod arg2",
|
||||
arg1: "branch=",
|
||||
arg2: "arg1",
|
||||
arg3: "e-nv=prod",
|
||||
arg4: "arg2"
|
||||
};
|
||||
expect(getSlashCommandPayload(commandWords, namedArgs)).toEqual(payload);
|
||||
});
|
||||
+89
-83
@@ -1,7 +1,7 @@
|
||||
const { inspect } = require("util");
|
||||
const core = require("@actions/core");
|
||||
const github = require("@actions/github");
|
||||
const {
|
||||
import * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {inspect} from 'util'
|
||||
import {
|
||||
getInputs,
|
||||
getCommandsConfig,
|
||||
configIsValid,
|
||||
@@ -9,144 +9,150 @@ const {
|
||||
getActorPermission,
|
||||
addReaction,
|
||||
getSlashCommandPayload
|
||||
} = require("./func");
|
||||
} from './command-helper'
|
||||
import {Octokit} from './octokit-client'
|
||||
|
||||
async function run() {
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
// Check required context properties exist (satisfy type checking)
|
||||
if (
|
||||
!github.context.payload.action ||
|
||||
!github.context.payload.issue ||
|
||||
!github.context.payload.comment
|
||||
) {
|
||||
throw new Error('Required context properties are missing.')
|
||||
}
|
||||
|
||||
// Only handle 'created' and 'edited' event types
|
||||
if (!["created", "edited"].includes(github.context.payload.action)) {
|
||||
if (!['created', 'edited'].includes(github.context.payload.action)) {
|
||||
core.warning(
|
||||
`Event type '${github.context.payload.action}' not supported.`
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Get action inputs
|
||||
const inputs = getInputs();
|
||||
core.debug(`Inputs: ${inspect(inputs)}`);
|
||||
const inputs = getInputs()
|
||||
core.debug(`Inputs: ${inspect(inputs)}`)
|
||||
|
||||
// Check required inputs
|
||||
if (!inputs.token) {
|
||||
core.setFailed("Missing required input 'token'.");
|
||||
return false;
|
||||
throw new Error(`Missing required input 'token'.`)
|
||||
}
|
||||
|
||||
// Get configuration for registered commands
|
||||
const config = getCommandsConfig(inputs);
|
||||
core.debug(`Commands config: ${inspect(config)}`);
|
||||
const config = getCommandsConfig(inputs)
|
||||
core.debug(`Commands config: ${inspect(config)}`)
|
||||
|
||||
// Check the config is valid
|
||||
if (!configIsValid(config)) return;
|
||||
if (!configIsValid(config)) return
|
||||
|
||||
// Get the comment body and id
|
||||
const commentBody = github.context.payload["comment"]["body"];
|
||||
const commentId = github.context.payload["comment"]["id"];
|
||||
core.debug(`Comment body: ${commentBody}`);
|
||||
core.debug(`Comment id: ${commentId}`);
|
||||
const commentBody: string = github.context.payload.comment.body
|
||||
const commentId: number = github.context.payload.comment.id
|
||||
core.debug(`Comment body: ${commentBody}`)
|
||||
core.debug(`Comment id: ${commentId}`)
|
||||
|
||||
// Check if the first line of the comment is a slash command
|
||||
const firstLine = commentBody.split(/\r?\n/)[0].trim();
|
||||
if (firstLine.length < 2 || firstLine.charAt(0) != "/") {
|
||||
console.debug("The first line of the comment is not a valid slash command.");
|
||||
return;
|
||||
const firstLine = commentBody.split(/\r?\n/)[0].trim()
|
||||
if (firstLine.length < 2 || firstLine.charAt(0) != '/') {
|
||||
console.debug(
|
||||
'The first line of the comment is not a valid slash command.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Split the first line into "words"
|
||||
const commandWords = firstLine.slice(1).split(" ");
|
||||
core.debug(`Command words: ${inspect(commandWords)}`);
|
||||
const commandWords = firstLine.slice(1).split(' ')
|
||||
core.debug(`Command words: ${inspect(commandWords)}`)
|
||||
|
||||
// Check if the command is registered for dispatch
|
||||
var configMatches = config.filter(function(cmd) {
|
||||
return cmd.command == commandWords[0];
|
||||
});
|
||||
core.debug(`Config matches on 'command': ${inspect(configMatches)}`);
|
||||
let configMatches = config.filter(function (cmd) {
|
||||
return cmd.command == commandWords[0]
|
||||
})
|
||||
core.debug(`Config matches on 'command': ${inspect(configMatches)}`)
|
||||
if (configMatches.length == 0) {
|
||||
core.info(`Command '${commandWords[0]}' is not registered for dispatch.`);
|
||||
return;
|
||||
core.info(`Command '${commandWords[0]}' is not registered for dispatch.`)
|
||||
return
|
||||
}
|
||||
|
||||
// Filter matching commands by issue type
|
||||
const isPullRequest = "pull_request" in github.context.payload.issue;
|
||||
configMatches = configMatches.filter(function(cmd) {
|
||||
const isPullRequest = 'pull_request' in github.context.payload.issue
|
||||
configMatches = configMatches.filter(function (cmd) {
|
||||
return (
|
||||
cmd.issue_type == "both" ||
|
||||
(cmd.issue_type == "issue" && !isPullRequest) ||
|
||||
(cmd.issue_type == "pull-request" && isPullRequest)
|
||||
);
|
||||
});
|
||||
core.debug(`Config matches on 'issue_type': ${inspect(configMatches)}`);
|
||||
cmd.issue_type == 'both' ||
|
||||
(cmd.issue_type == 'issue' && !isPullRequest) ||
|
||||
(cmd.issue_type == 'pull-request' && isPullRequest)
|
||||
)
|
||||
})
|
||||
core.debug(`Config matches on 'issue_type': ${inspect(configMatches)}`)
|
||||
if (configMatches.length == 0) {
|
||||
const issueType = isPullRequest ? "pull request" : "issue";
|
||||
const issueType = isPullRequest ? 'pull request' : 'issue'
|
||||
core.info(
|
||||
`Command '${commandWords[0]}' is not configured for the issue type '${issueType}'.`
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Filter matching commands by whether or not to allow edits
|
||||
if (github.context.payload.action == "edited") {
|
||||
configMatches = configMatches.filter(function(cmd) {
|
||||
return cmd.allow_edits;
|
||||
});
|
||||
core.debug(`Config matches on 'allow_edits': ${inspect(configMatches)}`);
|
||||
if (github.context.payload.action == 'edited') {
|
||||
configMatches = configMatches.filter(function (cmd) {
|
||||
return cmd.allow_edits
|
||||
})
|
||||
core.debug(`Config matches on 'allow_edits': ${inspect(configMatches)}`)
|
||||
if (configMatches.length == 0) {
|
||||
core.info(
|
||||
`Command '${commandWords[0]}' is not configured to allow edits.`
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Set octokit clients
|
||||
const octokit = new github.GitHub(inputs.token);
|
||||
const reactionOctokit = new github.GitHub(inputs.reactionToken)
|
||||
const octokit = new Octokit({auth: `${inputs.token}`})
|
||||
const reactionOctokit = new Octokit({auth: `${inputs.reactionToken}`})
|
||||
|
||||
// At this point we know the command is registered
|
||||
// Add the "eyes" reaction to the comment
|
||||
if (inputs.reactions)
|
||||
await addReaction(
|
||||
reactionOctokit,
|
||||
github.context.repo,
|
||||
commentId,
|
||||
"eyes"
|
||||
);
|
||||
await addReaction(reactionOctokit, github.context.repo, commentId, 'eyes')
|
||||
|
||||
// Get the actor permission
|
||||
const actorPermission = await getActorPermission(
|
||||
octokit,
|
||||
github.context.repo,
|
||||
github.context.actor
|
||||
);
|
||||
core.debug(`Actor permission: ${actorPermission}`);
|
||||
)
|
||||
core.debug(`Actor permission: ${actorPermission}`)
|
||||
|
||||
// Filter matching commands by the user's permission level
|
||||
configMatches = configMatches.filter(function(cmd) {
|
||||
return actorHasPermission(actorPermission, cmd.permission);
|
||||
});
|
||||
core.debug(`Config matches on 'permission': ${inspect(configMatches)}`);
|
||||
configMatches = configMatches.filter(function (cmd) {
|
||||
return actorHasPermission(actorPermission, cmd.permission)
|
||||
})
|
||||
core.debug(`Config matches on 'permission': ${inspect(configMatches)}`)
|
||||
if (configMatches.length == 0) {
|
||||
core.info(
|
||||
`Command '${commandWords[0]}' is not configured for the user's permission level '${actorPermission}'.`
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Determined that the command should be dispatched
|
||||
core.info(`Command '${commandWords[0]}' to be dispatched.`);
|
||||
core.info(`Command '${commandWords[0]}' to be dispatched.`)
|
||||
|
||||
// Define payload
|
||||
var clientPayload = {
|
||||
const clientPayload = {
|
||||
slash_command: {},
|
||||
github: github.context
|
||||
};
|
||||
}
|
||||
|
||||
// Get the pull request context for the dispatch payload
|
||||
if (isPullRequest) {
|
||||
const { data: pullRequest } = await octokit.pulls.get({
|
||||
const {data: pullRequest} = await octokit.pulls.get({
|
||||
...github.context.repo,
|
||||
pull_number: github.context.payload.issue.number
|
||||
});
|
||||
clientPayload["pull_request"] = pullRequest;
|
||||
})
|
||||
clientPayload['pull_request'] = pullRequest
|
||||
}
|
||||
|
||||
// Dispatch for each matching configuration
|
||||
@@ -155,23 +161,23 @@ async function run() {
|
||||
clientPayload.slash_command = getSlashCommandPayload(
|
||||
commandWords,
|
||||
cmd.named_args
|
||||
);
|
||||
)
|
||||
core.debug(
|
||||
`Slash command payload: ${inspect(clientPayload.slash_command)}`
|
||||
);
|
||||
)
|
||||
// Dispatch the command
|
||||
const dispatchRepo = cmd.repository.split("/");
|
||||
const eventType = cmd.command + cmd.event_type_suffix;
|
||||
const dispatchRepo = cmd.repository.split('/')
|
||||
const eventType = cmd.command + cmd.event_type_suffix
|
||||
await octokit.repos.createDispatchEvent({
|
||||
owner: dispatchRepo[0],
|
||||
repo: dispatchRepo[1],
|
||||
event_type: eventType,
|
||||
client_payload: clientPayload
|
||||
});
|
||||
})
|
||||
core.info(
|
||||
`Command '${cmd.command}' dispatched to '${cmd.repository}' ` +
|
||||
`with event type '${eventType}'.`
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
// Add the "rocket" reaction to the comment
|
||||
@@ -180,12 +186,12 @@ async function run() {
|
||||
reactionOctokit,
|
||||
github.context.repo,
|
||||
commentId,
|
||||
"rocket"
|
||||
);
|
||||
'rocket'
|
||||
)
|
||||
} catch (error) {
|
||||
core.debug(inspect(error));
|
||||
core.setFailed(error.message);
|
||||
core.debug(inspect(error))
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
run()
|
||||
@@ -0,0 +1,7 @@
|
||||
import {Octokit as Core} from '@octokit/core'
|
||||
import {paginateRest} from '@octokit/plugin-paginate-rest'
|
||||
import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods'
|
||||
export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods'
|
||||
export {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||
|
||||
export const Octokit = Core.plugin(paginateRest, restEndpointMethods)
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["__test__", "lib", "node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user