From 26fd836f96f46625de24663c4dc2b84c8408fcb1 Mon Sep 17 00:00:00 2001 From: dessant Date: Mon, 27 Sep 2021 20:38:48 +0300 Subject: [PATCH] feat: add new filtering and labeling options, update input parameter names BREAKING CHANGE: input parameter names have changed --- README.md | 231 ++++++++++++++++++++++++++++++++++++++--------- action.yml | 79 +++++++++++++--- src/index.js | 128 +++++++++++++++++++++----- src/schema.js | 246 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 503 insertions(+), 181 deletions(-) diff --git a/README.md b/README.md index cb96853..c6745c0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ please consider contributing with ## Usage -Create a `lock.yml` workflow file in the `.github/workflows` directory, +Create the `lock.yml` workflow file in the `.github/workflows` directory, use one of the [example workflows](#examples) to get started. ### Inputs @@ -28,44 +28,118 @@ The action can be configured using [input parameters](https://docs.github.com/en - GitHub access token, value must be `${{ github.token }}` or an encrypted secret that contains a [personal access token](#using-a-personal-access-token) - Optional, defaults to `${{ github.token }}` -- **`issue-lock-inactive-days`** +- **`issue-inactive-days`** - Number of days of inactivity before a closed issue is locked - Optional, defaults to `365` -- **`issue-exclude-created-before`** - - Do not lock issues created before a given timestamp, +- **`exclude-issue-created-before`** + - Do not lock issues created before a given date, + value must follow ISO 8601, ignored + when `exclude-issue-created-between` is set + - Optional, defaults to `''` +- **`exclude-issue-created-after`** + - Do not lock issues created after a given date, + value must follow ISO 8601, ignored + when `exclude-issue-created-between` is set + - Optional, defaults to `''` +- **`exclude-issue-created-between`** + - Do not lock issues created in a given time interval, value must follow ISO 8601 - Optional, defaults to `''` -- **`issue-exclude-labels`** - - Do not lock issues with these labels, value must be +- **`exclude-issue-closed-before`** + - Do not lock issues closed before a given date, + value must follow ISO 8601, ignored + when `exclude-issue-closed-between` is set + - Optional, defaults to `''` +- **`exclude-issue-closed-after`** + - Do not lock issues closed after a given date, + value must follow ISO 8601, ignored + when `exclude-issue-closed-between` is set + - Optional, defaults to `''` +- **`exclude-issue-closed-between`** + - Do not lock issues closed in a given time interval, + value must follow ISO 8601 + - Optional, defaults to `''` +- **`include-any-issue-labels`** + - Only lock issues with any of these labels, value must be + a comma separated list of labels or `''`, ignored + when `include-all-issue-labels` is set + - Optional, defaults to `''` +- **`include-all-issue-labels`** + - Only lock issues with all these labels, value must be a comma separated list of labels or `''` - Optional, defaults to `''` -- **`issue-lock-labels`** +- **`exclude-any-issue-labels`** + - Do not lock issues with any of these labels, value must be + a comma separated list of labels or `''` + - Optional, defaults to `''` +- **`add-issue-labels`** - Labels to add before locking an issue, value must be a comma separated list of labels or `''` - Optional, defaults to `''` -- **`issue-lock-comment`** +- **`remove-issue-labels`** + - Labels to remove before locking an issue, value must be + a comma separated list of labels or `''` + - Optional, defaults to `''` +- **`issue-comment`** - Comment to post before locking an issue - Optional, defaults to `''` - **`issue-lock-reason`** - Reason for locking an issue, value must be one of `resolved`, `off-topic`, `too heated`, `spam` or `''` - Optional, defaults to `resolved` -- **`pr-lock-inactive-days`** +- **`pr-inactive-days`** - Number of days of inactivity before a closed pull request is locked - Optional, defaults to `365` -- **`pr-exclude-created-before`** - - Do not lock pull requests created before a given timestamp, +- **`exclude-pr-created-before`** + - Do not lock pull requests created before a given date, + value must follow ISO 8601, ignored + when `exclude-pr-created-between` is set + - Optional, defaults to `''` +- **`exclude-pr-created-after`** + - Do not lock pull requests created after a given date, + value must follow ISO 8601, ignored + when `exclude-pr-created-between` is set + - Optional, defaults to `''` +- **`exclude-pr-created-between`** + - Do not lock pull requests created in a given time interval, + value must follow ISO 8601 + - Optional, defaults to `''` +- **`exclude-pr-closed-before`** + - Do not lock pull requests closed before a given date, + value must follow ISO 8601, ignored + when `exclude-pr-closed-between` is set + - Optional, defaults to `''` +- **`exclude-pr-closed-after`** + - Do not lock pull requests closed after a given date, + value must follow ISO 8601, ignored + when `exclude-pr-closed-between` is set + - Optional, defaults to `''` +- **`exclude-pr-closed-between`** + - Do not lock pull requests closed in a given time interval, value must follow ISO 8601 - Optional, defaults to `''` -- **`pr-exclude-labels`** - - Do not lock pull requests with these labels, value must - be a comma separated list of labels or `''` +- **`include-any-pr-labels`** + - Only lock pull requests with any of these labels, value must be + a comma separated list of labels or `''`, ignored + when `include-all-pr-labels` is set + - Optional, defaults to `''` +- **`include-all-pr-labels`** + - Only lock pull requests with all these labels, value must be + a comma separated list of labels or `''` + - Optional, defaults to `''` +- **`exclude-any-pr-labels`** + - Do not lock pull requests with any of these labels, value must be + a comma separated list of labels or `''` - Optional, defaults to `''` -- **`pr-lock-labels`** +- **`add-pr-labels`** - Labels to add before locking a pull request, value must be a comma separated list of labels or `''` - Optional, defaults to `''` -- **`pr-lock-comment`** +- **`remove-pr-labels`** + - Labels to remove before locking a pull request, value must be + a comma separated list of labels or `''` + - Optional, defaults to `''` +- **`pr-comment`** - Comment to post before locking a pull request - Optional, defaults to `''` - **`pr-lock-reason`** @@ -76,6 +150,9 @@ The action can be configured using [input parameters](https://docs.github.com/en - Limit locking to only issues or pull requests, value must be one of `issues`, `prs` or `''` - Optional, defaults to `''` +- **`log-output`** + - Log output parameters, value must be either `true` or `false` + - Optional, defaults to `false` ### Outputs @@ -92,7 +169,8 @@ The action can be configured using [input parameters](https://docs.github.com/en ## Examples The following workflow will search once an hour for closed issues -and pull requests that can be locked. +and pull requests that have not had any activity +in the past year and can be locked. ```yaml @@ -114,7 +192,7 @@ jobs: action: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 ``` Edit the workflow after the initial backlog of issues and pull requests @@ -153,25 +231,42 @@ jobs: action: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: github-token: ${{ github.token }} - issue-lock-inactive-days: '365' - issue-exclude-created-before: '' - issue-exclude-labels: '' - issue-lock-labels: '' - issue-lock-comment: '' + issue-inactive-days: '365' + exclude-issue-created-before: '' + exclude-issue-created-after: '' + exclude-issue-created-between: '' + exclude-issue-closed-before: '' + exclude-issue-closed-after: '' + exclude-issue-closed-between: '' + include-any-issue-labels: '' + include-all-issue-labels: '' + exclude-any-issue-labels: '' + add-issue-labels: '' + remove-issue-labels: '' + issue-comment: '' issue-lock-reason: 'resolved' - pr-lock-inactive-days: '365' - pr-exclude-created-before: '' - pr-exclude-labels: '' - pr-lock-labels: '' - pr-lock-comment: '' + pr-inactive-days: '365' + exclude-pr-created-before: '' + exclude-pr-created-after: '' + exclude-pr-created-between: '' + exclude-pr-closed-before: '' + exclude-pr-closed-after: '' + exclude-pr-closed-between: '' + include-any-pr-labels: '' + include-all-pr-labels: '' + exclude-any-pr-labels: '' + add-pr-labels: '' + remove-pr-labels: '' + pr-comment: '' pr-lock-reason: 'resolved' process-only: '' + log-output: false ``` -### Excluding issues and pull requests +### Filtering issues and pull requests This step will lock only issues, and exclude issues created before 2018, or those with the `upstream` or `help-wanted` labels applied. @@ -179,10 +274,10 @@ or those with the `upstream` or `help-wanted` labels applied. ```yaml steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: - issue-exclude-created-before: '2018-01-01T00:00:00Z' - issue-exclude-labels: 'upstream, help-wanted' + exclude-issue-created-before: '2018-01-01T00:00:00Z' + exclude-any-issue-labels: 'upstream, help-wanted' process-only: 'issues' ``` @@ -192,12 +287,51 @@ with the `wip` label applied. ```yaml steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: - pr-exclude-labels: 'wip' + exclude-any-pr-labels: 'wip' process-only: 'prs' ``` +This step will lock only issues, and exclude issues closed before 2018, +or those created in 2018 and 2019. + + +```yaml + steps: + - uses: dessant/lock-threads@v3 + with: + exclude-issue-created-between: '2018-01-01T00:00:00Z/2019-12-31T23:59:59.999Z' + exclude-issue-closed-before: '2018-01-01T00:00:00Z' + process-only: 'issues' +``` + +This step will lock issues that have the `incomplete` _or_ `invalid` +labels applied, and pull requests that have the `qa: done` _and_ `published` +labels applied. + + +```yaml + steps: + - uses: dessant/lock-threads@v3 + with: + include-any-issue-labels: 'incomplete, invalid' + include-all-pr-labels: 'qa: done, published' + +``` + +This step will lock issues that have not had any activity in the past 180 days. + + +```yaml + steps: + - uses: dessant/lock-threads@v3 + with: + issue-inactive-days: '180' + process-only: 'issues' + +``` + ### Commenting and labeling This step will post a comment on issues and pull requests before locking them, @@ -206,19 +340,32 @@ and apply the `outdated` label to issues. ```yaml steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: - issue-lock-labels: 'outdated' - issue-lock-comment: > + add-issue-labels: 'outdated' + issue-comment: > This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. - pr-lock-comment: > + pr-comment: > This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. ``` +This step will apply the `qa: done` and `archived` labels, +and remove the `qa: primary` and `needs: user feedback` labels +before locking issues. + + +```yaml + steps: + - uses: dessant/lock-threads@v3 + with: + add-issue-labels: 'qa: done, archived' + remove-issue-labels: 'qa: primary, needs: user feedback' +``` + ### Using a personal access token The action uses an installation access token by default to interact with GitHub. @@ -234,7 +381,7 @@ using the `github-token` input parameter. ```yaml steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v3 with: github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} ``` @@ -248,9 +395,9 @@ applying or removing milestones, or pushing commits. An easy way to check and see which issues or pull requests will initially be locked is to add the `updated` search qualifier to either the issue -or pull request page filter for your repository: +or pull request search field for your repository: `is:closed is:unlocked updated:<2018-12-20`. -Adjust the date to be 365 days ago (or whatever you set for `*-lock-inactive-days`) +Adjust the date to be 365 days ago (or whatever you set for `*-inactive-days`) to see which issues or pull requests will be locked. ## Why are only some issues and pull requests processed? diff --git a/action.yml b/action.yml index d3db927..d6974f3 100644 --- a/action.yml +++ b/action.yml @@ -5,37 +5,85 @@ inputs: github-token: description: 'GitHub access token' default: '${{ github.token }}' - issue-lock-inactive-days: + issue-inactive-days: description: 'Number of days of inactivity before a closed issue is locked' default: '365' - issue-exclude-created-before: - description: 'Do not lock issues created before a given timestamp, value must follow ISO 8601' + exclude-issue-created-before: + description: 'Do not lock issues created before a given date, value must follow ISO 8601' default: '' - issue-exclude-labels: - description: 'Do not lock issues with these labels, value must be a comma separated list of labels' + exclude-issue-created-after: + description: 'Do not lock issues created after a given date, value must follow ISO 8601' default: '' - issue-lock-labels: + exclude-issue-created-between: + description: 'Do not lock issues created in a given time interval, value must follow ISO 8601' + default: '' + exclude-issue-closed-before: + description: 'Do not lock issues closed before a given date, value must follow ISO 8601' + default: '' + exclude-issue-closed-after: + description: 'Do not lock issues closed after a given date, value must follow ISO 8601' + default: '' + exclude-issue-closed-between: + description: 'Do not lock issues closed in a given time interval, value must follow ISO 8601' + default: '' + include-any-issue-labels: + description: 'Only lock issues with any of these labels, value must be a comma separated list of labels' + default: '' + include-all-issue-labels: + description: 'Only lock issues with all these labels, value must be a comma separated list of labels' + default: '' + exclude-any-issue-labels: + description: 'Do not lock issues with any of these labels, value must be a comma separated list of labels' + default: '' + add-issue-labels: description: 'Labels to add before locking an issue, value must be a comma separated list of labels' default: '' - issue-lock-comment: + remove-issue-labels: + description: 'Labels to remove before locking an issue, value must be a comma separated list of labels' + default: '' + issue-comment: description: 'Comment to post before locking an issue' default: '' issue-lock-reason: description: 'Reason for locking an issue, value must be one of `resolved`, `off-topic`, `too heated` or `spam`' default: 'resolved' - pr-lock-inactive-days: + pr-inactive-days: description: 'Number of days of inactivity before a closed pull request is locked' default: '365' - pr-exclude-created-before: - description: 'Do not lock pull requests created before a given timestamp, value must follow ISO 8601' + exclude-pr-created-before: + description: 'Do not lock pull requests created before a given date, value must follow ISO 8601' default: '' - pr-exclude-labels: - description: 'Do not lock pull requests with these labels, value must be a comma separated list of labels' + exclude-pr-created-after: + description: 'Do not lock pull requests created after a given date, value must follow ISO 8601' default: '' - pr-lock-labels: + exclude-pr-created-between: + description: 'Do not lock pull requests created in a given time interval, value must follow ISO 8601' + default: '' + exclude-pr-closed-before: + description: 'Do not lock pull requests closed before a given date, value must follow ISO 8601' + default: '' + exclude-pr-closed-after: + description: 'Do not lock pull requests closed after a given date, value must follow ISO 8601' + default: '' + exclude-pr-closed-between: + description: 'Do not lock pull requests closed in a given time interval, value must follow ISO 8601' + default: '' + include-any-pr-labels: + description: 'Only lock pull requests with any of these labels, value must be a comma separated list of labels' + default: '' + include-all-pr-labels: + description: 'Only lock pull requests with all these labels, value must be a comma separated list of labels' + default: '' + exclude-any-pr-labels: + description: 'Do not lock pull requests with any of these labels, value must be a comma separated list of labels' + default: '' + add-pr-labels: description: 'Labels to add before locking a pull request, value must be a comma separated list of labels' default: '' - pr-lock-comment: + remove-pr-labels: + description: 'Labels to remove before locking a pull request, value must be a comma separated list of labels' + default: '' + pr-comment: description: 'Comment to post before locking a pull request' default: '' pr-lock-reason: @@ -44,6 +92,9 @@ inputs: process-only: description: 'Limit locking to only issues or pull requests, value must be one of `issues` or `prs`' default: '' + log-output: + description: 'Log output parameters, value must be either `true` or `false`' + default: false outputs: issues: description: 'Issues that have been locked, value is a JSON string' diff --git a/src/index.js b/src/index.js index 7fa48f6..14aca2e 100644 --- a/src/index.js +++ b/src/index.js @@ -23,19 +23,31 @@ class App { async lockThreads() { const type = this.config['process-only']; - const threadTypes = type ? [type] : ['issue', 'pr']; + const logOutput = this.config['log-output']; + const threadTypes = type ? [type] : ['issue', 'pr']; for (const item of threadTypes) { const threads = await this.lock(item); + core.debug(`Setting output (${item}s)`); - core.setOutput(`${item}s`, threads.length ? JSON.stringify(threads) : ''); + if (threads.length) { + core.setOutput(`${item}s`, JSON.stringify(threads)); + + if (logOutput) { + core.info(`Output (${item}s):`); + core.info(JSON.stringify(threads, null, 2)); + } + } else { + core.setOutput(`${item}s`, ''); + } } } async lock(type) { const repo = github.context.repo; - const lockLabels = this.config[`${type}-lock-labels`]; - const lockComment = this.config[`${type}-lock-comment`]; + const addLabels = this.config[`add-${type}-labels`]; + const removeLabels = this.config[`remove-${type}-labels`]; + const comment = this.config[`${type}-comment`]; const lockReason = this.config[`${type}-lock-reason`]; const threads = []; @@ -44,12 +56,12 @@ class App { for (const result of results) { const issue = {...repo, issue_number: result.number}; - if (lockComment) { + if (comment) { core.debug(`Commenting (${type}: ${issue.issue_number})`); try { await this.client.rest.issues.createComment({ ...issue, - body: lockComment + body: comment }); } catch (err) { if (!/cannot be modified.*discussion/i.test(err.message)) { @@ -58,12 +70,39 @@ class App { } } - if (lockLabels) { - core.debug(`Labeling (${type}: ${issue.issue_number})`); - await this.client.rest.issues.addLabels({ - ...issue, - labels: lockLabels - }); + if (addLabels || removeLabels) { + const {data: issueData} = await this.client.rest.issues.get({...issue}); + + if (addLabels) { + const currentLabels = issueData.labels.map(label => label.name); + const newLabels = addLabels.filter( + label => !currentLabels.includes(label) + ); + + if (newLabels.length) { + core.debug(`Labeling (${type}: ${issue.issue_number})`); + await this.client.rest.issues.addLabels({ + ...issue, + labels: newLabels + }); + } + } + + if (removeLabels) { + const currentLabels = issueData.labels.map(label => label.name); + const matchingLabels = currentLabels.filter(label => + removeLabels.includes(label) + ); + if (matchingLabels.length) { + core.debug(`Unlabeling (${type}: ${issue.issue_number})`); + for (const label of matchingLabels) { + await this.client.rest.issues.removeLabel({ + ...issue, + name: label + }); + } + } + } } core.debug(`Locking (${type}: ${issue.issue_number})`); @@ -89,22 +128,41 @@ class App { async search(type) { const {owner, repo} = github.context.repo; - const timestamp = this.getUpdatedTimestamp( - this.config[`${type}-lock-inactive-days`] + const updatedTime = this.getUpdatedTimestamp( + this.config[`${type}-inactive-days`] ); - let query = `repo:${owner}/${repo} updated:<${timestamp} is:closed is:unlocked`; - - const excludeLabels = this.config[`${type}-exclude-labels`]; - if (excludeLabels) { - const queryPart = excludeLabels - .map(label => `-label:"${label}"`) - .join(' '); - query += ` ${queryPart}`; + let query = `repo:${owner}/${repo} updated:<${updatedTime} is:closed is:unlocked`; + + const includeAnyLabels = this.config[`include-any-${type}-labels`]; + const includeAllLabels = this.config[`include-all-${type}-labels`]; + + if (includeAllLabels) { + query += ` ${includeAllLabels + .map(label => `label:"${label}"`) + .join(' ')}`; + } else if (includeAnyLabels) { + query += ` label:${includeAnyLabels.join(',')}`; + } + + const excludeAnyLabels = this.config[`exclude-any-${type}-labels`]; + if (excludeAnyLabels) { + query += ` -label:${excludeAnyLabels.join(',')}`; } - const excludeCreatedBefore = this.config[`${type}-exclude-created-before`]; - if (excludeCreatedBefore) { - query += ` created:>${this.getISOTimestamp(excludeCreatedBefore)}`; + const excludeCreatedQuery = this.getFilterByDateQuery({ + type, + qualifier: 'created' + }); + if (excludeCreatedQuery) { + query += ` ${excludeCreatedQuery}`; + } + + const excludeClosedQuery = this.getFilterByDateQuery({ + type, + qualifier: 'closed' + }); + if (excludeClosedQuery) { + query += ` ${excludeClosedQuery}`; } if (type === 'issue') { @@ -127,6 +185,26 @@ class App { return results.filter(issue => !issue.locked); } + getFilterByDateQuery({type, qualifier = 'created'} = {}) { + const beforeDate = this.config[`exclude-${type}-${qualifier}-before`]; + const afterDate = this.config[`exclude-${type}-${qualifier}-after`]; + const betweenDates = this.config[`exclude-${type}-${qualifier}-between`]; + + if (betweenDates) { + return `-${qualifier}:${betweenDates + .map(date => this.getISOTimestamp(date)) + .join('..')}`; + } else if (beforeDate && afterDate) { + return `${qualifier}:${this.getISOTimestamp( + beforeDate + )}..${this.getISOTimestamp(afterDate)}`; + } else if (beforeDate) { + return `${qualifier}:>${this.getISOTimestamp(beforeDate)}`; + } else if (afterDate) { + return `${qualifier}:<${this.getISOTimestamp(afterDate)}`; + } + } + getUpdatedTimestamp(days) { const ttl = days * 24 * 60 * 60 * 1000; const date = new Date(new Date() - ttl); diff --git a/src/schema.js b/src/schema.js index 1847079..db9cd00 100644 --- a/src/schema.js +++ b/src/schema.js @@ -1,134 +1,180 @@ const Joi = require('joi'); -const extendedJoi = Joi.extend({ - type: 'stringList', - base: Joi.array(), - coerce: { - from: 'string', - method(value) { - value = value.trim(); - if (value) { - value = value - .split(',') - .map(item => item.trim()) - .filter(Boolean); +const extendedJoi = Joi.extend(joi => { + return { + type: 'stringList', + base: joi.array(), + coerce: { + from: 'string', + method(value, helpers) { + value = value.trim(); + if (value) { + value = value + .split(',') + .map(item => item.trim()) + .filter(Boolean); + } + + return {value}; } - - return {value}; } - } -}).extend({ - type: 'processOnly', - base: Joi.string(), - coerce: { - from: 'string', - method(value) { - value = value.trim(); - if (['issues', 'prs'].includes(value)) { - value = value.slice(0, -1); + }; +}) + .extend(joi => { + return { + type: 'timeInterval', + base: joi.array(), + messages: { + 'timeInterval.asc': + '{{#label}} the start date must be earlier than the end date' + }, + coerce: { + from: 'string', + method(value, helpers) { + value = value.trim(); + if (value) { + value = value + .split('/') + .map(item => item.trim()) + .filter(Boolean); + } + + return {value}; + } + }, + rules: { + asc: { + validate(value, helpers, args, options) { + if (value[0] < value[1]) { + return value; + } + + return helpers.error('timeInterval.asc'); + } + } } - - return {value}; - } - } -}); + }; + }) + .extend(joi => { + return { + type: 'processOnly', + base: joi.string(), + coerce: { + from: 'string', + method(value, helpers) { + value = value.trim(); + if (['issues', 'prs'].includes(value)) { + value = value.slice(0, -1); + } + + return {value}; + } + } + }; + }); + +const joiDate = Joi.alternatives().try( + Joi.date() + // .iso() + .min('1970-01-01T00:00:00Z') + .max('2970-12-31T23:59:59Z'), + Joi.string().trim().valid('') +); + +const joiTimeInterval = Joi.alternatives().try( + extendedJoi + .timeInterval() + .items( + Joi.date().iso().min('1970-01-01T00:00:00Z').max('2970-12-31T23:59:59Z') + ) + .length(2) + .asc(), + Joi.string().trim().valid('') +); + +const joiLabels = Joi.alternatives().try( + extendedJoi + .stringList() + .items(Joi.string().trim().max(50)) + .min(1) + .max(30) + .unique(), + Joi.string().trim().valid('') +); const schema = Joi.object({ 'github-token': Joi.string().trim().max(100), - 'issue-lock-inactive-days': Joi.number() + 'issue-inactive-days': Joi.number() .min(0) .max(3650) .precision(9) .default(365), - 'issue-exclude-created-before': Joi.alternatives() - .try( - Joi.date() - // .iso() - .min('1970-01-01T00:00:00Z') - .max('2970-12-31T23:59:59Z'), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-issue-created-before': joiDate.default(''), - 'issue-exclude-labels': Joi.alternatives() - .try( - extendedJoi - .stringList() - .items(Joi.string().trim().max(50)) - .min(1) - .max(30) - .unique(), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-issue-created-after': joiDate.default(''), - 'issue-lock-labels': Joi.alternatives() - .try( - extendedJoi - .stringList() - .items(Joi.string().trim().max(50)) - .min(1) - .max(30) - .unique(), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-issue-created-between': joiTimeInterval.default(''), + + 'exclude-issue-closed-before': joiDate.default(''), + + 'exclude-issue-closed-after': joiDate.default(''), + + 'exclude-issue-closed-between': joiTimeInterval.default(''), + + 'include-any-issue-labels': joiLabels.default(''), + + 'include-all-issue-labels': joiLabels.default(''), + + 'exclude-any-issue-labels': joiLabels.default(''), + + 'add-issue-labels': joiLabels.default(''), + + 'remove-issue-labels': joiLabels.default(''), - 'issue-lock-comment': Joi.string().trim().max(10000).allow('').default(''), + 'issue-comment': Joi.string().trim().max(10000).allow('').default(''), 'issue-lock-reason': Joi.string() .valid('resolved', 'off-topic', 'too heated', 'spam', '') .default('resolved'), - 'pr-lock-inactive-days': Joi.number() - .min(0) - .max(3650) - .precision(9) - .default(365), + 'pr-inactive-days': Joi.number().min(0).max(3650).precision(9).default(365), - 'pr-exclude-created-before': Joi.alternatives() - .try( - Joi.date() - // .iso() - .min('1970-01-01T00:00:00Z') - .max('2970-12-31T23:59:59Z'), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-pr-created-before': joiDate.default(''), - 'pr-exclude-labels': Joi.alternatives() - .try( - extendedJoi - .stringList() - .items(Joi.string().trim().max(50)) - .min(1) - .max(30) - .unique(), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-pr-created-after': joiDate.default(''), - 'pr-lock-labels': Joi.alternatives() - .try( - extendedJoi - .stringList() - .items(Joi.string().trim().max(50)) - .min(1) - .max(30) - .unique(), - Joi.string().trim().valid('') - ) - .default(''), + 'exclude-pr-created-between': joiTimeInterval.default(''), - 'pr-lock-comment': Joi.string().trim().max(10000).allow('').default(''), + 'exclude-pr-closed-before': joiDate.default(''), + + 'exclude-pr-closed-after': joiDate.default(''), + + 'exclude-pr-closed-between': joiTimeInterval.default(''), + + 'include-any-pr-labels': joiLabels.default(''), + + 'include-all-pr-labels': joiLabels.default(''), + + 'exclude-any-pr-labels': joiLabels.default(''), + + 'add-pr-labels': joiLabels.default(''), + + 'remove-pr-labels': joiLabels.default(''), + + 'pr-comment': Joi.string().trim().max(10000).allow('').default(''), 'pr-lock-reason': Joi.string() .valid('resolved', 'off-topic', 'too heated', 'spam', '') .default('resolved'), - 'process-only': extendedJoi.processOnly().valid('issue', 'pr', '').default('') + 'process-only': extendedJoi + .processOnly() + .valid('issue', 'pr', '') + .default(''), + + 'log-output': Joi.boolean().default(false) }); module.exports = schema;