diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..d4fb64a --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +# Ignore everything in the root except some files +/* + +# Unignore all files in the src directory +!src/ diff --git a/.eslintrc.json b/.eslintrc.json index ecd22c6..996a3b6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,16 +1,37 @@ { - "plugins": ["jest", "jest-formatting", "@typescript-eslint", "prettier"], + "plugins": [ + "jest", + "jest-formatting", + "@typescript-eslint", + "import", + "prettier", + "deprecation" + ], "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended-type-checked", "plugin:jest/recommended", - "plugin:prettier/recommended", - "plugin:github/recommended" + "plugin:prettier/recommended" + ], + "env": { + "node": true + }, + "ignorePatterns": [ + "node_modules", + "dist", + "lib", + "build", + "__test__", + "**/*.spec.ts", + "**/*.test.ts" ], "parser": "@typescript-eslint/parser", "parserOptions": { - "ecmaVersion": 2022, + "ecmaVersion": 13, "project": "./tsconfig.json" }, "rules": { + "deprecation/deprecation": "error", "prettier/prettier": [ "error", { @@ -20,10 +41,46 @@ "arrowParens": "always", "endOfLine": "auto" } + ], + "@typescript-eslint/no-namespaces": "off", + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/naming-convention": [ + "warn", + { + "selector": "default", + "format": [ + "camelCase" + ] + }, + { + "selector": "variable", + "format": [ + "camelCase", + "UPPER_CASE" + ] + }, + { + "selector": "parameter", + "format": [ + "camelCase", + "snake_case" + ], + "leadingUnderscore": "allow" + }, + { + "selector": "typeLike", + "format": [ + "PascalCase" + ] + }, + { + "selector": "property", + "format": [ + "camelCase", + "snake_case", + "PascalCase" + ] + } ] - }, - "env": { - "node": true, - "jest/globals": true } } diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..2ddcaba --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,17 @@ +test: + - "src/*.test.ts" + - "src/**/*.test.ts" + - "src/*.spec.ts" + - "src/**/*.spec.ts" + +documentation: + - "**/*.md" + - "**/*.txt" + +dependencies: + - "**/package.json" + - "**/yarn.lock" + +infrastructure: + - "**/Dockerfile" + - "**/compose.yml" diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..3a71e06 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,35 @@ +changelog: + categories: + - title: "πŸš€ Features" + labels: + - enhancement + - feature + + - title: "πŸ› Bug Fixes" + labels: + - bug + - fix + - hotfix + - bugfix + + - title: "🧰 Maintenance" + labels: + - maintenance + - refactor + - chore + + - title: "πŸ“ Documentation" + labels: + - documentation + + - title: "πŸ—οΈ Infrastructure" + labels: + - infrastructure + + - title: "πŸ§ͺ Tests" + labels: + - test + + - title: "πŸ“¦ Dependencies" + labels: + - dependencies diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..7d7330f --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,42 @@ +name: 'CodeQL' + +on: + schedule: + - cron: '0 0 * * 0' # Run at 00:00 UTC on Sunday + push: + branches: [main] + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ['javascript'] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/delete-cache.yml b/.github/workflows/delete-cache.yml new file mode 100644 index 0000000..a93cbd7 --- /dev/null +++ b/.github/workflows/delete-cache.yml @@ -0,0 +1,39 @@ +name: cleanup caches by a branch + +on: + pull_request: + types: + - closed + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge" + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + if [ -z "$cacheKeysForPR" ] + then + echo "No cache keys found for $BRANCH" + exit 0 + fi + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..d53b925 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,14 @@ +name: Pull Request Labeler + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml new file mode 100644 index 0000000..1058e38 --- /dev/null +++ b/.github/workflows/metrics.yml @@ -0,0 +1,43 @@ +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + # Run on the first day of every month at 00:00 JST (UTC+9) + - cron: '0 15 1 * *' + +permissions: + issues: write + pull-requests: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + + steps: + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + first_day=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "$first_day..$last_day" + echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" + + - name: Run issue-metrics tool + uses: github/issue-metrics@v2 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:Okabe-Junya/issue-validator is:issue is:pr created:${{ env.last_month }} -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v4 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md + assignees: diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml new file mode 100644 index 0000000..62a0c75 --- /dev/null +++ b/.github/workflows/reviewdog.yml @@ -0,0 +1,19 @@ +name: reviewdog eslint +on: + pull_request: + branches: + - main + +jobs: + lint: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + - uses: reviewdog/action-eslint@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + reporter: github-pr-review + eslint_flags: "--ext .ts" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..083e5e9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,58 @@ +name: jest test +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + setup: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install Dependencies with Yarn + run: yarn install + + - name: Cache Dependencies + uses: actions/cache@v3 + with: + path: node/ci-dependency/node_modules + key: ${{ runner.os }}-node-${{ hashFiles('yarn.lock') }} + + test: + needs: setup + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + node: [18, 20] + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + + - name: Install Dependencies + run: yarn install + + - name: Cache Dependencies + uses: actions/cache@v3 + with: + path: node/ci-dependency/node_modules + key: ${{ runner.os }}-node-${{ hashFiles('yarn.lock') }} + + - name: Run Tests + run: yarn test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d4fb64a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Ignore everything in the root except some files +/* + +# Unignore all files in the src directory +!src/ diff --git a/dist/index.js b/dist/index.js index 81eabfb..bb73c12 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9629,127 +9629,24 @@ function wrappy (fn, cb) { } -/***/ }), - -/***/ 6144: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"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; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.run = void 0; -const core = __importStar(__nccwpck_require__(2186)); -const validate_1 = __nccwpck_require__(4953); -const github = __importStar(__nccwpck_require__(5438)); -async function run() { - try { - const title = core.getInput('title') || ''; - const title_regex_flags = core.getInput('title-regex-flags') || ''; - const title_regex = new RegExp(title, title_regex_flags); - const body = core.getInput('body') || ''; - const body_regex_flags = core.getInput('body-regex-flags') || ''; - const body_regex = new RegExp(body, body_regex_flags); - const issue_type = core.getInput('issue-type') || ''; - const issue_number = core.getInput('issue-number') || ''; - const is_auto_close = core.getInput('is-auto-close') || ''; - const octokit = github.getOctokit(core.getInput('github-token')); - const result = await (0, validate_1.validateIssueTitleAndBody)(issue_type, parseInt(issue_number), title_regex, body_regex); - if (result === true) { - core.setOutput('result', 'true'); - } - else { - if (is_auto_close === 'true') { - core.warning(`Issue #${issue_number} is not valid. Auto closing issue...`); - // Add comment - await octokit.rest.issues.createComment({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number: parseInt(issue_number), - body: `Issue #${issue_number} is not valid: Reason: ${result}: auto closing issue...`, - }); - // Close issue - await octokit.rest.issues.update({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number: parseInt(issue_number), - state: 'closed', - }); - } - core.setOutput('result', 'false'); - } - } - catch (error) { - core.setFailed(error.message); - } -} -exports.run = run; -run(); - - /***/ }), /***/ 1314: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "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; -}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getPullRequestTitleAndBody = exports.getIssueTitleAndBody = void 0; -const core = __importStar(__nccwpck_require__(2186)); -const github = __importStar(__nccwpck_require__(5438)); -async function getIssueTitleAndBody(issue_number) { - const token = core.getInput('token', { required: true }); - const octokit = github.getOctokit(token); +const core_1 = __nccwpck_require__(2186); +const github_1 = __nccwpck_require__(5438); +async function getIssueTitleAndBody(issueNumber) { + const token = (0, core_1.getInput)('token', { required: true }); + const octokit = (0, github_1.getOctokit)(token); const { data: issue } = await octokit.rest.issues.get({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number, + owner: github_1.context.repo.owner, + repo: github_1.context.repo.repo, + issue_number: issueNumber, }); issue.body = issue.body || ''; return { @@ -9758,13 +9655,13 @@ async function getIssueTitleAndBody(issue_number) { }; } exports.getIssueTitleAndBody = getIssueTitleAndBody; -async function getPullRequestTitleAndBody(pull_number) { - const token = core.getInput('token', { required: true }); - const octokit = github.getOctokit(token); +async function getPullRequestTitleAndBody(pullNumber) { + const token = (0, core_1.getInput)('token', { required: true }); + const octokit = (0, github_1.getOctokit)(token); const { data: pullRequest } = await octokit.rest.pulls.get({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - pull_number, + owner: github_1.context.repo.owner, + repo: github_1.context.repo.repo, + pull_number: pullNumber, }); pullRequest.body = pullRequest.body || ''; return { @@ -9785,28 +9682,31 @@ exports.getPullRequestTitleAndBody = getPullRequestTitleAndBody; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.validateIssueTitleAndBody = void 0; const utils_1 = __nccwpck_require__(1314); -async function validateIssueTitleAndBody(issue_type, issue_number, title_regex, body_regex) { - if (issue_type === 'issue') { - const { title, body } = await (0, utils_1.getIssueTitleAndBody)(issue_number); - if (title_regex && !title_regex.test(title)) { +async function validateIssueTitleAndBody(issueType, issueNumber, titleRegex, bodyRegex) { + if (!titleRegex && !bodyRegex) { + return true; + } + if (issueType === 'issue') { + const { title, body } = await (0, utils_1.getIssueTitleAndBody)(issueNumber); + if (titleRegex && !titleRegex.test(title)) { return false; } - if (body_regex && !body_regex.test(body)) { + if (bodyRegex && !bodyRegex.test(body)) { return false; } return true; } - if (issue_type === 'pull_request') { - const { title, body } = await (0, utils_1.getPullRequestTitleAndBody)(issue_number); - if (title_regex && !title_regex.test(title)) { + if (issueType === 'pull_request') { + const { title, body } = await (0, utils_1.getPullRequestTitleAndBody)(issueNumber); + if (titleRegex && !titleRegex.test(title)) { return false; } - if (body_regex && !body_regex.test(body)) { + if (bodyRegex && !bodyRegex.test(body)) { return false; } return true; } - throw new Error(`Invalid issue type: ${issue_type}`); + throw new Error(`Invalid issue type: ${issueType}`); } exports.validateIssueTitleAndBody = validateIssueTitleAndBody; @@ -9987,13 +9887,65 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; /******/ /************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(6144); -/******/ module.exports = __webpack_exports__; -/******/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be in strict mode. +(() => { +"use strict"; +var exports = __webpack_exports__; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.run = void 0; +const core_1 = __nccwpck_require__(2186); +const validate_1 = __nccwpck_require__(4953); +const github_1 = __nccwpck_require__(5438); +async function run() { + try { + const title = (0, core_1.getInput)('title') || ''; + const titleRegexFlags = (0, core_1.getInput)('title-regex-flags') || ''; + const titleRegex = new RegExp(title, titleRegexFlags); + const body = (0, core_1.getInput)('body') || ''; + const bodyRegexFlags = (0, core_1.getInput)('body-regex-flags') || ''; + const bodyRegex = new RegExp(body, bodyRegexFlags); + const issueType = (0, core_1.getInput)('issue-type') || ''; + const issueNumber = (0, core_1.getInput)('issue-number') || ''; + const isAutoClose = (0, core_1.getInput)('is-auto-close') || ''; + const octokit = (0, github_1.getOctokit)((0, core_1.getInput)('github-token')); + const result = await (0, validate_1.validateIssueTitleAndBody)(issueType, parseInt(issueNumber), titleRegex, bodyRegex); + if (result === true) { + (0, core_1.setOutput)('result', 'true'); + } + else { + if (isAutoClose === 'true') { + (0, core_1.warning)(`Issue #${issueNumber} is not valid. Auto closing issue...`); + // Add comment + await octokit.rest.issues.createComment({ + owner: github_1.context.repo.owner, + repo: github_1.context.repo.repo, + issue_number: parseInt(issueNumber), + body: `Issue #${issueNumber} is not valid: Reason: ${result}: auto closing issue...`, + }); + // Close issue + await octokit.rest.issues.update({ + owner: github_1.context.repo.owner, + repo: github_1.context.repo.repo, + issue_number: parseInt(issueNumber), + state: 'closed', + }); + } + (0, core_1.setOutput)('result', 'false'); + } + /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unsafe-argument: 0, @typescript-eslint/no-unsafe-member-access: 0, @typescript-eslint/no-floating-promises: 0 */ + } + catch (error) { + (0, core_1.setFailed)(error.message); + } +} +exports.run = run; +run(); + +})(); + +module.exports = __webpack_exports__; /******/ })() ; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/jest.config.json b/jest.config.json index 6db68ab..9d5146d 100644 --- a/jest.config.json +++ b/jest.config.json @@ -2,5 +2,7 @@ "bail": 1, "verbose": true, "reporters": ["default", "jest-failure-reporter"], - "rootDir": "src" + "rootDir": "src", + "preset": "ts-jest", + "resetMocks": true } diff --git a/package.json b/package.json index 7dde049..c543b74 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,17 @@ "@actions/tool-cache": "^2.0.1" }, "devDependencies": { + "@babel/preset-typescript": "^7.22.15", "@types/jest": "^29.5.5", "@vercel/ncc": "^0.38.0", "eslint": "^8.50.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin": "^1.0.1", + "eslint-plugin-deprecation": "^2.0.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-eslint-plugin": "^5.1.1", "eslint-plugin-github": "^4.10.0", + "eslint-plugin-import": "^2.28.1", "eslint-plugin-jest": "^27.4.0", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-prettier": "^5.0.0", @@ -23,11 +29,13 @@ "jest-failure-reporter": "^1.0.1", "prettier": "^3.0.3", "ts-jest": "^29.1.1", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "typescript-eslint": "^0.0.1-alpha.0" }, "scripts": { "build": "ncc build src/index.ts -o dist --source-map --license licenses.txt", "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", "test": "jest", "prettier": "prettier --write ." } diff --git a/src/index.ts b/src/index.ts index 3606920..e203dd6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,53 +1,47 @@ -import * as core from '@actions/core'; +import { getInput, setOutput, warning, setFailed } from '@actions/core'; import { validateIssueTitleAndBody } from './validate'; -import * as github from '@actions/github'; +import { getOctokit, context } from '@actions/github'; export async function run() { try { - const title = core.getInput('title') || ''; - const title_regex_flags = core.getInput('title-regex-flags') || ''; - const title_regex = new RegExp(title, title_regex_flags); - const body = core.getInput('body') || ''; - const body_regex_flags = core.getInput('body-regex-flags') || ''; - const body_regex = new RegExp(body, body_regex_flags); - const issue_type = core.getInput('issue-type') || ''; - const issue_number = core.getInput('issue-number') || ''; - const is_auto_close = core.getInput('is-auto-close') || ''; + const title = getInput('title') || ''; + const titleRegexFlags = getInput('title-regex-flags') || ''; + const titleRegex = new RegExp(title, titleRegexFlags); + const body = getInput('body') || ''; + const bodyRegexFlags = getInput('body-regex-flags') || ''; + const bodyRegex = new RegExp(body, bodyRegexFlags); + const issueType = getInput('issue-type') || ''; + const issueNumber = getInput('issue-number') || ''; + const isAutoClose = getInput('is-auto-close') || ''; - const octokit = github.getOctokit(core.getInput('github-token')); - const result = await validateIssueTitleAndBody( - issue_type, - parseInt(issue_number), - title_regex, - body_regex, - ); + const octokit = getOctokit(getInput('github-token')); + const result = await validateIssueTitleAndBody(issueType, parseInt(issueNumber), titleRegex, bodyRegex); if (result === true) { - core.setOutput('result', 'true'); + setOutput('result', 'true'); } else { - if (is_auto_close === 'true') { - core.warning( - `Issue #${issue_number} is not valid. Auto closing issue...`, - ); + if (isAutoClose === 'true') { + warning(`Issue #${issueNumber} is not valid. Auto closing issue...`); // Add comment await octokit.rest.issues.createComment({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number: parseInt(issue_number), - body: `Issue #${issue_number} is not valid: Reason: ${result}: auto closing issue...`, + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: parseInt(issueNumber), + body: `Issue #${issueNumber} is not valid: Reason: ${result}: auto closing issue...`, }); // Close issue await octokit.rest.issues.update({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number: parseInt(issue_number), + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: parseInt(issueNumber), state: 'closed', }); } - core.setOutput('result', 'false'); + setOutput('result', 'false'); } + /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unsafe-argument: 0, @typescript-eslint/no-unsafe-member-access: 0, @typescript-eslint/no-floating-promises: 0 */ } catch (error: any) { - core.setFailed(error.message); + setFailed(error.message); } } diff --git a/src/utils.test.ts b/src/utils.test.ts new file mode 100644 index 0000000..8794f59 --- /dev/null +++ b/src/utils.test.ts @@ -0,0 +1,94 @@ +import { expect, jest } from '@jest/globals'; +import { getIssueTitleAndBody, getPullRequestTitleAndBody } from './utils'; + +describe('getIssueTitleAndBody', () => { + it('returns title and body', async () => { + // mock implementation of getInput + const mockGetInput = jest.fn().mockReturnValue('token'); + + // mock implementation of getOctokit + const mockGetOctokit = jest.fn().mockReturnValue({ + rest: { + issues: { + get: jest.fn().mockReturnValue({ + data: { + title: 'sample issue title', + body: 'sample issue body', + }, + }), + }, + }, + }); + + // mock implementation of context + const mockContext = { + repo: { + owner: 'sample owner', + repo: 'sample repo', + }, + }; + + // set mock implementations + const core = require('@actions/core'); + const github = require('@actions/github'); + core.getInput = mockGetInput; + github.getOctokit = mockGetOctokit; + github.context = mockContext; + + // run the test + const mockIssueNumber = 1; + const { title, body } = await getIssueTitleAndBody(mockIssueNumber); + + // assert the results + expect(title).toBe('sample issue title'); + expect(body).toBe('sample issue body'); + expect(mockGetInput).toHaveBeenCalledWith('token', { required: true }); + expect(mockGetOctokit).toHaveBeenCalledWith('token'); + }); +}); + +describe('getPullRequestTitleAndBody', () => { + it('returns title and body', async () => { + // mock implementation of getInput + const mockGetInput = jest.fn().mockReturnValue('token'); + + // mock implementation of getOctokit + const mockGetOctokit = jest.fn().mockReturnValue({ + rest: { + pulls: { + get: jest.fn().mockReturnValue({ + data: { + title: 'sample pull request title', + body: 'sample pull request body', + }, + }), + }, + }, + }); + + // mock implementation of context + const mockContext = { + repo: { + owner: 'sample owner', + repo: 'sample repo', + }, + }; + + // set mock implementations + const core = require('@actions/core'); + const github = require('@actions/github'); + core.getInput = mockGetInput; + github.getOctokit = mockGetOctokit; + github.context = mockContext; + + // run the test + const mockPullNumber = 1; + const { title, body } = await getPullRequestTitleAndBody(mockPullNumber); + + // assert the results + expect(title).toBe('sample pull request title'); + expect(body).toBe('sample pull request body'); + expect(mockGetInput).toHaveBeenCalledWith('token', { required: true }); + expect(mockGetOctokit).toHaveBeenCalledWith('token'); + }); +}); diff --git a/src/utils.ts b/src/utils.ts index 88f5b06..7f9109f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,15 +1,13 @@ -import * as core from '@actions/core'; -import * as github from '@actions/github'; +import { getInput } from '@actions/core'; +import { getOctokit, context } from '@actions/github'; -export async function getIssueTitleAndBody( - issue_number: number, -): Promise<{ title: string; body: string }> { - const token = core.getInput('token', { required: true }); - const octokit = github.getOctokit(token); +export async function getIssueTitleAndBody(issueNumber: number): Promise<{ title: string; body: string }> { + const token = getInput('token', { required: true }); + const octokit = getOctokit(token); const { data: issue } = await octokit.rest.issues.get({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - issue_number, + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, }); issue.body = issue.body || ''; return { @@ -18,15 +16,13 @@ export async function getIssueTitleAndBody( }; } -export async function getPullRequestTitleAndBody( - pull_number: number, -): Promise<{ title: string; body: string }> { - const token = core.getInput('token', { required: true }); - const octokit = github.getOctokit(token); +export async function getPullRequestTitleAndBody(pullNumber: number): Promise<{ title: string; body: string }> { + const token = getInput('token', { required: true }); + const octokit = getOctokit(token); const { data: pullRequest } = await octokit.rest.pulls.get({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - pull_number, + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pullNumber, }); pullRequest.body = pullRequest.body || ''; return { diff --git a/src/validate.test.ts b/src/validate.test.ts new file mode 100644 index 0000000..56315cf --- /dev/null +++ b/src/validate.test.ts @@ -0,0 +1,84 @@ +import { expect } from '@jest/globals'; +import { validateIssueTitleAndBody } from './validate'; + +describe('validateIssueTitleAndBody', () => { + it('returns true if only title_regex is set and title matches', async () => { + // mock implementation of getIssueTitleAndBody + const mockGetIssueTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample issue title', + body: 'sample issue body', + }); + + // mock implementation of getPullRequestTitleAndBody + const mockGetPullRequestTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample pull request title', + body: 'sample pull request body', + }); + + const utils = require('./utils'); + utils.getIssueTitleAndBody = mockGetIssueTitleAndBody; + utils.getPullRequestTitleAndBody = mockGetPullRequestTitleAndBody; + + // run the test + // 'sample' γ¨γ„γ†ζ–‡ε­—εˆ—γŒ title γ«ε«γΎγ‚Œγ¦γ„γ‚‹γ‹γ©γ†γ‹ζ€œθ¨Όγ™γ‚‹ + const result = await validateIssueTitleAndBody('issue', 1, /sample/, null); + expect(result).toBe(true); + expect(mockGetIssueTitleAndBody).toHaveBeenCalledWith(1); + expect(mockGetPullRequestTitleAndBody).not.toHaveBeenCalled(); + }); + + it('returns true if only body_regex is set and body matches', async () => { + // mock implementation of getIssueTitleAndBody + const mockGetIssueTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample issue title', + body: 'sample issue body', + }); + + // mock implementation of getPullRequestTitleAndBody + const mockGetPullRequestTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample pull request title', + body: 'sample pull request body', + }); + + const utils = require('./utils'); + utils.getIssueTitleAndBody = mockGetIssueTitleAndBody; + utils.getPullRequestTitleAndBody = mockGetPullRequestTitleAndBody; + + // run the test + // 'sample' γ¨γ„γ†ζ–‡ε­—εˆ—γŒ body γ«ε«γΎγ‚Œγ¦γ„γ‚‹γ‹γ©γ†γ‹ζ€œθ¨Όγ™γ‚‹ + const result = await validateIssueTitleAndBody('issue', 1, null, /sample/); + expect(result).toBe(true); + expect(mockGetIssueTitleAndBody).toHaveBeenCalledWith(1); + expect(mockGetPullRequestTitleAndBody).not.toHaveBeenCalled(); + }); + + it('returns true if both title_regex and body_regex are set and both match', async () => { + // mock implementation of getIssueTitleAndBody + const mockGetIssueTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample issue title', + body: 'sample issue body', + }); + + // mock implementation of getPullRequestTitleAndBody + const mockGetPullRequestTitleAndBody = jest.fn().mockReturnValue({ + title: 'sample pull request title', + body: 'sample pull request body', + }); + + const utils = require('./utils'); + utils.getIssueTitleAndBody = mockGetIssueTitleAndBody; + utils.getPullRequestTitleAndBody = mockGetPullRequestTitleAndBody; + + // run the test + // 'sample' γ¨γ„γ†ζ–‡ε­—εˆ—γŒ title と body γ«ε«γΎγ‚Œγ¦γ„γ‚‹γ‹γ©γ†γ‹ζ€œθ¨Όγ™γ‚‹ + const result = await validateIssueTitleAndBody( + 'issue', + 1, + /sample/, + /sample/, + ); + expect(result).toBe(true); + expect(mockGetIssueTitleAndBody).toHaveBeenCalledWith(1); + expect(mockGetPullRequestTitleAndBody).not.toHaveBeenCalled(); + }); +}); diff --git a/src/validate.ts b/src/validate.ts index 4d77f43..1182145 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -1,30 +1,33 @@ import { getIssueTitleAndBody, getPullRequestTitleAndBody } from './utils'; export async function validateIssueTitleAndBody( - issue_type: string, - issue_number: number, - title_regex: RegExp, - body_regex: RegExp, -): Promise { - if (issue_type === 'issue') { - const { title, body } = await getIssueTitleAndBody(issue_number); - if (title_regex && !title_regex.test(title)) { + issueType: string, + issueNumber: number, + titleRegex: RegExp | null, + bodyRegex: RegExp | null, +): Promise { + if (!titleRegex && !bodyRegex) { + return true; + } + if (issueType === 'issue') { + const { title, body } = await getIssueTitleAndBody(issueNumber); + if (titleRegex && !titleRegex.test(title)) { return false; } - if (body_regex && !body_regex.test(body)) { + if (bodyRegex && !bodyRegex.test(body)) { return false; } return true; } - if (issue_type === 'pull_request') { - const { title, body } = await getPullRequestTitleAndBody(issue_number); - if (title_regex && !title_regex.test(title)) { + if (issueType === 'pull_request') { + const { title, body } = await getPullRequestTitleAndBody(issueNumber); + if (titleRegex && !titleRegex.test(title)) { return false; } - if (body_regex && !body_regex.test(body)) { + if (bodyRegex && !bodyRegex.test(body)) { return false; } return true; } - throw new Error(`Invalid issue type: ${issue_type}`); + throw new Error(`Invalid issue type: ${issueType}`); } diff --git a/yarn.lock b/yarn.lock index 79b4328..fb28ab7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -108,6 +108,13 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-compilation-targets@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" @@ -119,7 +126,22 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.22.20": +"@babel/helper-create-class-features-plugin@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== @@ -139,6 +161,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz#b95a144896f6d491ca7863576f820f3628818621" + integrity sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-module-imports@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" @@ -146,7 +175,7 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-module-transforms@^7.22.20": +"@babel/helper-module-transforms@^7.22.15", "@babel/helper-module-transforms@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz#da9edc14794babbe7386df438f3768067132f59e" integrity sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A== @@ -157,11 +186,27 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== +"@babel/helper-replace-supers@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -169,6 +214,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" @@ -249,7 +301,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== @@ -305,13 +357,43 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.7.2": +"@babel/plugin-syntax-typescript@^7.22.5", "@babel/plugin-syntax-typescript@^7.7.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-modules-commonjs@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz#b11810117ed4ee7691b29bd29fd9f3f98276034f" + integrity sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg== + dependencies: + "@babel/helper-module-transforms" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-typescript@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz#15adef906451d86349eb4b8764865c960eb54127" + integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.22.5" + +"@babel/preset-typescript@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz#43db30516fae1d417d748105a0bc95f637239d48" + integrity sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.15" + "@babel/plugin-transform-typescript" "^7.22.15" + "@babel/runtime@^7.20.7": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" @@ -986,7 +1068,7 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.7.2": +"@typescript-eslint/utils@6.7.2", "@typescript-eslint/utils@^6.0.0": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.2.tgz#b9ef0da6f04932167a9222cb4ac59cb187165ebf" integrity sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ== @@ -1729,6 +1811,15 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" +eslint-plugin-deprecation@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-deprecation/-/eslint-plugin-deprecation-2.0.0.tgz#9804707a4c19f3a53615c6babc0ced3d429d69cf" + integrity sha512-OAm9Ohzbj11/ZFyICyR5N6LbOIvQMp7ZU2zI7Ej0jIc8kiGUERXPNMfw2QqqHD1ZHtjMub3yPZILovYEYucgoQ== + dependencies: + "@typescript-eslint/utils" "^6.0.0" + tslib "^2.3.1" + tsutils "^3.21.0" + eslint-plugin-escompat@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/eslint-plugin-escompat/-/eslint-plugin-escompat-3.4.0.tgz#cfd8d3b44fd0bc3d07b8ca15e4b0c15de88a0192" @@ -1744,6 +1835,14 @@ eslint-plugin-eslint-comments@^3.2.0: escape-string-regexp "^1.0.5" ignore "^5.0.5" +eslint-plugin-eslint-plugin@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-5.1.1.tgz#1de9f0511b0300bf85b3ddb29e9f7653fa684bf0" + integrity sha512-4MGDsG505Ot2TSDSYxFL0cpDo4Y+t6hKB8cfZw9Jx484VjXWDfiYC/A6cccWFtWoOOC0j+wGgQIIb11cdIAMBg== + dependencies: + eslint-utils "^3.0.0" + estraverse "^5.3.0" + eslint-plugin-filenames@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz#7094f00d7aefdd6999e3ac19f72cea058e590cf7" @@ -1782,7 +1881,7 @@ eslint-plugin-i18n-text@^1.0.1: resolved "https://registry.yarnpkg.com/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz#69ce14f9af7d135cbe8114b1b144a57bb83291dc" integrity sha512-3G3UetST6rdqhqW9SfcfzNYMpQXS7wNkJvp6dsXnjzGiku6Iu5hl3B0kmk6lIcFPwYjhQIY+tXVRtK9TlGT7RA== -eslint-plugin-import@^2.25.2: +eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.28.1: version "2.28.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== @@ -1852,6 +1951,13 @@ eslint-plugin-prettier@^5.0.0: prettier-linter-helpers "^1.0.0" synckit "^0.8.5" +eslint-plugin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin/-/eslint-plugin-1.0.1.tgz#24bf3136d167c90ed0d4d5702d8b9b1ed2beef79" + integrity sha512-ervp8C09On0fLA258TvE08AqAr/bhRYgHVZd3BrJjD4JfOA2JGANDLGs06j51oWqfPd7Feoo3OoqHD+fuI2sFQ== + dependencies: + requireindex "~1.1.0" + eslint-rule-documentation@>=1.0.0: version "1.0.23" resolved "https://registry.yarnpkg.com/eslint-rule-documentation/-/eslint-rule-documentation-1.0.23.tgz#4e0886145597a78d24524ec7e0cf18c6fedc23a8" @@ -1873,6 +1979,18 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" @@ -1954,7 +2072,7 @@ estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0, estraverse@^5.2.0: +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== @@ -3509,6 +3627,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +requireindex@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162" + integrity sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -3857,7 +3980,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.5.0, tslib@^2.6.0: +tslib@^2.3.1, tslib@^2.5.0, tslib@^2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -3935,6 +4058,11 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" +typescript-eslint@^0.0.1-alpha.0: + version "0.0.1-alpha.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-0.0.1-alpha.0.tgz#285d68a4e96588295cd436278801bcb6a6b916c1" + integrity sha512-1hNKM37dAWML/2ltRXupOq2uqcdRQyDFphl+341NTPXFLLLiDhErXx8VtaSLh3xP7SyHZdcCgpt9boYYVb3fQg== + typescript@^5.2.2: version "5.2.2" resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"