Default author and committer to actions.yml defaults
This commit is contained in:
parent
2f62e00e1b
commit
76c09b178c
6 changed files with 35 additions and 256 deletions
17
README.md
17
README.md
|
@ -43,8 +43,8 @@ All inputs are **optional**. If not set, sensible defaults will be used.
|
||||||
| `token` | `GITHUB_TOKEN` or a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | `GITHUB_TOKEN` |
|
| `token` | `GITHUB_TOKEN` or a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). | `GITHUB_TOKEN` |
|
||||||
| `path` | Relative path under `GITHUB_WORKSPACE` to the repository. | `GITHUB_WORKSPACE` |
|
| `path` | Relative path under `GITHUB_WORKSPACE` to the repository. | `GITHUB_WORKSPACE` |
|
||||||
| `commit-message` | The message to use when committing changes. | `[create-pull-request] automated change` |
|
| `commit-message` | The message to use when committing changes. | `[create-pull-request] automated change` |
|
||||||
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user if an identity is not found in git config. See [Committer and author](#committer-and-author) for details. |
|
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. Defaults to the GitHub Actions bot user. | `GitHub <noreply@github.com>` |
|
||||||
| `author` | The author name and email address in the format `Display Name <email@address.com>`. | Defaults to the GitHub Actions bot user if an identity is not found in git config. See [Committer and author](#committer-and-author) for details. |
|
| `author` | The author name and email address in the format `Display Name <email@address.com>`. Defaults to the user who triggered the workflow run. | `${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>` |
|
||||||
| `branch` | The pull request branch name. | `create-pull-request/patch` |
|
| `branch` | The pull request branch name. | `create-pull-request/patch` |
|
||||||
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
|
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
|
||||||
| `push-to-fork` | A fork of the checked out parent repository to which the pull request branch will be pushed. e.g. `owner/repo-fork`. The pull request will be created to merge the fork's branch into the parent's base. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | |
|
| `push-to-fork` | A fork of the checked out parent repository to which the pull request branch will be pushed. e.g. `owner/repo-fork`. The pull request will be created to merge the fork's branch into the parent's base. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | |
|
||||||
|
@ -97,19 +97,6 @@ How the action behaves:
|
||||||
|
|
||||||
For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
|
For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
|
||||||
|
|
||||||
### Committer and author
|
|
||||||
|
|
||||||
If neither `committer` or `author` inputs are supplied the action will look for an existing identity in git config. If found, that identity will be used. If not found, the action will default to making commits by the GitHub Actions bot user.
|
|
||||||
|
|
||||||
The following configuration can be used to have commits authored by the user who triggered the workflow event.
|
|
||||||
```yml
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@v3
|
|
||||||
with:
|
|
||||||
committer: GitHub <noreply@github.com>
|
|
||||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlling commits
|
### Controlling commits
|
||||||
|
|
||||||
As well as relying on the action to handle uncommitted changes, you can additionally make your own commits before the action runs.
|
As well as relying on the action to handle uncommitted changes, you can additionally make your own commits before the action runs.
|
||||||
|
|
|
@ -14,11 +14,13 @@ inputs:
|
||||||
committer:
|
committer:
|
||||||
description: >
|
description: >
|
||||||
The committer name and email address in the format `Display Name <email@address.com>`.
|
The committer name and email address in the format `Display Name <email@address.com>`.
|
||||||
Defaults to the GitHub Actions bot user if an identity is not found in git config.
|
Defaults to the GitHub Actions bot user.
|
||||||
|
default: 'GitHub <noreply@github.com>'
|
||||||
author:
|
author:
|
||||||
description: >
|
description: >
|
||||||
The author name and email address in the format `Display Name <email@address.com>`.
|
The author name and email address in the format `Display Name <email@address.com>`.
|
||||||
Defaults to the GitHub Actions bot user if an identity is not found in git config.
|
Defaults to the user who triggered the workflow run.
|
||||||
|
default: '${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>'
|
||||||
branch:
|
branch:
|
||||||
description: 'The pull request branch name.'
|
description: 'The pull request branch name.'
|
||||||
default: 'create-pull-request/patch'
|
default: 'create-pull-request/patch'
|
||||||
|
|
137
dist/index.js
vendored
137
dist/index.js
vendored
|
@ -8237,124 +8237,6 @@ class GitHubHelper {
|
||||||
exports.GitHubHelper = GitHubHelper;
|
exports.GitHubHelper = GitHubHelper;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 723:
|
|
||||||
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
||||||
}) : (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 (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.GitIdentityHelper = void 0;
|
|
||||||
const core = __importStar(__webpack_require__(470));
|
|
||||||
const utils = __importStar(__webpack_require__(611));
|
|
||||||
// Default the committer and author to the GitHub Actions bot
|
|
||||||
const DEFAULT_COMMITTER = 'GitHub <noreply@github.com>';
|
|
||||||
const DEFAULT_AUTHOR = 'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>';
|
|
||||||
class GitIdentityHelper {
|
|
||||||
constructor(git) {
|
|
||||||
this.git = git;
|
|
||||||
}
|
|
||||||
getGitIdentityFromConfig() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if ((yield this.git.configExists('user.name')) &&
|
|
||||||
(yield this.git.configExists('user.email'))) {
|
|
||||||
const userName = yield this.git.getConfigValue('user.name');
|
|
||||||
const userEmail = yield this.git.getConfigValue('user.email');
|
|
||||||
return {
|
|
||||||
authorName: userName,
|
|
||||||
authorEmail: userEmail,
|
|
||||||
committerName: userName,
|
|
||||||
committerEmail: userEmail
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if ((yield this.git.configExists('committer.name')) &&
|
|
||||||
(yield this.git.configExists('committer.email')) &&
|
|
||||||
(yield this.git.configExists('author.name')) &&
|
|
||||||
(yield this.git.configExists('author.email'))) {
|
|
||||||
const committerName = yield this.git.getConfigValue('committer.name');
|
|
||||||
const committerEmail = yield this.git.getConfigValue('committer.email');
|
|
||||||
const authorName = yield this.git.getConfigValue('author.name');
|
|
||||||
const authorEmail = yield this.git.getConfigValue('author.email');
|
|
||||||
return {
|
|
||||||
authorName: authorName,
|
|
||||||
authorEmail: authorEmail,
|
|
||||||
committerName: committerName,
|
|
||||||
committerEmail: committerEmail
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
getIdentity(author, committer) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
// If either committer or author is supplied they will be cross used
|
|
||||||
if (!committer && author) {
|
|
||||||
core.info('Supplied author will also be used as the committer.');
|
|
||||||
committer = author;
|
|
||||||
}
|
|
||||||
if (!author && committer) {
|
|
||||||
core.info('Supplied committer will also be used as the author.');
|
|
||||||
author = committer;
|
|
||||||
}
|
|
||||||
// If no committer/author has been supplied, try and fetch identity
|
|
||||||
// configuration already existing in git config.
|
|
||||||
if (!committer && !author) {
|
|
||||||
const identity = yield this.getGitIdentityFromConfig();
|
|
||||||
if (identity) {
|
|
||||||
core.info('Retrieved a pre-configured git identity.');
|
|
||||||
return identity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Set defaults if no committer/author has been supplied and no
|
|
||||||
// existing identity configuration was found.
|
|
||||||
if (!committer && !author) {
|
|
||||||
core.info('Action defaults set for the author and committer.');
|
|
||||||
committer = DEFAULT_COMMITTER;
|
|
||||||
author = DEFAULT_AUTHOR;
|
|
||||||
}
|
|
||||||
const parsedAuthor = utils.parseDisplayNameEmail(author);
|
|
||||||
const parsedCommitter = utils.parseDisplayNameEmail(committer);
|
|
||||||
return {
|
|
||||||
authorName: parsedAuthor.name,
|
|
||||||
authorEmail: parsedAuthor.email,
|
|
||||||
committerName: parsedCommitter.name,
|
|
||||||
committerEmail: parsedCommitter.email
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.GitIdentityHelper = GitIdentityHelper;
|
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 733:
|
/***/ 733:
|
||||||
|
@ -10590,7 +10472,6 @@ const create_or_update_branch_1 = __webpack_require__(159);
|
||||||
const github_helper_1 = __webpack_require__(718);
|
const github_helper_1 = __webpack_require__(718);
|
||||||
const git_command_manager_1 = __webpack_require__(289);
|
const git_command_manager_1 = __webpack_require__(289);
|
||||||
const git_auth_helper_1 = __webpack_require__(287);
|
const git_auth_helper_1 = __webpack_require__(287);
|
||||||
const git_identity_helper_1 = __webpack_require__(723);
|
|
||||||
const utils = __importStar(__webpack_require__(611));
|
const utils = __importStar(__webpack_require__(611));
|
||||||
function createPullRequest(inputs) {
|
function createPullRequest(inputs) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
@ -10656,22 +10537,22 @@ function createPullRequest(inputs) {
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
// Output head branch
|
// Output head branch
|
||||||
core.info(`Pull request branch to create or update set to '${inputs.branch}'`);
|
core.info(`Pull request branch to create or update set to '${inputs.branch}'`);
|
||||||
// Determine the committer and author
|
// Configure the committer and author
|
||||||
core.startGroup('Configuring the committer and author');
|
core.startGroup('Configuring the committer and author');
|
||||||
const gitIdentityHelper = new git_identity_helper_1.GitIdentityHelper(git);
|
const parsedAuthor = utils.parseDisplayNameEmail(inputs.author);
|
||||||
const identity = yield gitIdentityHelper.getIdentity(inputs.author, inputs.committer);
|
const parsedCommitter = utils.parseDisplayNameEmail(inputs.committer);
|
||||||
git.setIdentityGitOptions([
|
git.setIdentityGitOptions([
|
||||||
'-c',
|
'-c',
|
||||||
`author.name=${identity.authorName}`,
|
`author.name=${parsedAuthor.name}`,
|
||||||
'-c',
|
'-c',
|
||||||
`author.email=${identity.authorEmail}`,
|
`author.email=${parsedAuthor.email}`,
|
||||||
'-c',
|
'-c',
|
||||||
`committer.name=${identity.committerName}`,
|
`committer.name=${parsedCommitter.name}`,
|
||||||
'-c',
|
'-c',
|
||||||
`committer.email=${identity.committerEmail}`
|
`committer.email=${parsedCommitter.email}`
|
||||||
]);
|
]);
|
||||||
core.info(`Configured git committer as '${identity.committerName} <${identity.committerEmail}>'`);
|
core.info(`Configured git committer as '${parsedCommitter.name} <${parsedCommitter.email}>'`);
|
||||||
core.info(`Configured git author as '${identity.authorName} <${identity.authorEmail}>'`);
|
core.info(`Configured git author as '${parsedAuthor.name} <${parsedAuthor.email}>'`);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
// Create or update the pull request branch
|
// Create or update the pull request branch
|
||||||
core.startGroup('Create or update the pull request branch');
|
core.startGroup('Create or update the pull request branch');
|
||||||
|
|
|
@ -2,6 +2,17 @@
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|
||||||
|
- The `author` input now defaults to the user who triggered the workflow run. This default is set via [action.yml](action.yml) as `${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>`, where `github.actor` is the GitHub user account associated with the run. For example, `peter-evans <peter-evans@users.noreply.github.com>`.
|
||||||
|
|
||||||
|
The behavior of `v2` can be kept by setting the `author` input as follows.
|
||||||
|
```yaml
|
||||||
|
- uses: peter-evans/create-pull-request@v3
|
||||||
|
with:
|
||||||
|
author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
||||||
|
```
|
||||||
|
|
||||||
|
- The `author` and `committer` inputs are no longer cross-used if only one is supplied. Additionally, when neither input is set, the `author` and `committer` are no longer determined from an existing identity set in git config. In both cases, the inputs will fall back to their default set in [action.yml](action.yml).
|
||||||
|
|
||||||
- Deprecated inputs `project` and `project-column` have been removed in favour of an additional action step. See [Create a project card](https://github.com/peter-evans/create-pull-request#create-a-project-card) for details.
|
- Deprecated inputs `project` and `project-column` have been removed in favour of an additional action step. See [Create a project card](https://github.com/peter-evans/create-pull-request#create-a-project-card) for details.
|
||||||
|
|
||||||
- Deprecated output `pr_number` has been removed in favour of `pull-request-number`.
|
- Deprecated output `pr_number` has been removed in favour of `pull-request-number`.
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {createOrUpdateBranch} from './create-or-update-branch'
|
||||||
import {GitHubHelper} from './github-helper'
|
import {GitHubHelper} from './github-helper'
|
||||||
import {GitCommandManager} from './git-command-manager'
|
import {GitCommandManager} from './git-command-manager'
|
||||||
import {GitAuthHelper} from './git-auth-helper'
|
import {GitAuthHelper} from './git-auth-helper'
|
||||||
import {GitIdentityHelper} from './git-identity-helper'
|
|
||||||
import * as utils from './utils'
|
import * as utils from './utils'
|
||||||
|
|
||||||
export interface Inputs {
|
export interface Inputs {
|
||||||
|
@ -113,28 +112,25 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
||||||
`Pull request branch to create or update set to '${inputs.branch}'`
|
`Pull request branch to create or update set to '${inputs.branch}'`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Determine the committer and author
|
// Configure the committer and author
|
||||||
core.startGroup('Configuring the committer and author')
|
core.startGroup('Configuring the committer and author')
|
||||||
const gitIdentityHelper = new GitIdentityHelper(git)
|
const parsedAuthor = utils.parseDisplayNameEmail(inputs.author)
|
||||||
const identity = await gitIdentityHelper.getIdentity(
|
const parsedCommitter = utils.parseDisplayNameEmail(inputs.committer)
|
||||||
inputs.author,
|
|
||||||
inputs.committer
|
|
||||||
)
|
|
||||||
git.setIdentityGitOptions([
|
git.setIdentityGitOptions([
|
||||||
'-c',
|
'-c',
|
||||||
`author.name=${identity.authorName}`,
|
`author.name=${parsedAuthor.name}`,
|
||||||
'-c',
|
'-c',
|
||||||
`author.email=${identity.authorEmail}`,
|
`author.email=${parsedAuthor.email}`,
|
||||||
'-c',
|
'-c',
|
||||||
`committer.name=${identity.committerName}`,
|
`committer.name=${parsedCommitter.name}`,
|
||||||
'-c',
|
'-c',
|
||||||
`committer.email=${identity.committerEmail}`
|
`committer.email=${parsedCommitter.email}`
|
||||||
])
|
])
|
||||||
core.info(
|
core.info(
|
||||||
`Configured git committer as '${identity.committerName} <${identity.committerEmail}>'`
|
`Configured git committer as '${parsedCommitter.name} <${parsedCommitter.email}>'`
|
||||||
)
|
)
|
||||||
core.info(
|
core.info(
|
||||||
`Configured git author as '${identity.authorName} <${identity.authorEmail}>'`
|
`Configured git author as '${parsedAuthor.name} <${parsedAuthor.email}>'`
|
||||||
)
|
)
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
|
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
import * as core from '@actions/core'
|
|
||||||
import {GitCommandManager} from './git-command-manager'
|
|
||||||
import * as utils from './utils'
|
|
||||||
|
|
||||||
// Default the committer and author to the GitHub Actions bot
|
|
||||||
const DEFAULT_COMMITTER = 'GitHub <noreply@github.com>'
|
|
||||||
const DEFAULT_AUTHOR =
|
|
||||||
'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>'
|
|
||||||
|
|
||||||
interface GitIdentity {
|
|
||||||
authorName: string
|
|
||||||
authorEmail: string
|
|
||||||
committerName: string
|
|
||||||
committerEmail: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GitIdentityHelper {
|
|
||||||
private git: GitCommandManager
|
|
||||||
|
|
||||||
constructor(git: GitCommandManager) {
|
|
||||||
this.git = git
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getGitIdentityFromConfig(): Promise<GitIdentity | undefined> {
|
|
||||||
if (
|
|
||||||
(await this.git.configExists('user.name')) &&
|
|
||||||
(await this.git.configExists('user.email'))
|
|
||||||
) {
|
|
||||||
const userName = await this.git.getConfigValue('user.name')
|
|
||||||
const userEmail = await this.git.getConfigValue('user.email')
|
|
||||||
return {
|
|
||||||
authorName: userName,
|
|
||||||
authorEmail: userEmail,
|
|
||||||
committerName: userName,
|
|
||||||
committerEmail: userEmail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(await this.git.configExists('committer.name')) &&
|
|
||||||
(await this.git.configExists('committer.email')) &&
|
|
||||||
(await this.git.configExists('author.name')) &&
|
|
||||||
(await this.git.configExists('author.email'))
|
|
||||||
) {
|
|
||||||
const committerName = await this.git.getConfigValue('committer.name')
|
|
||||||
const committerEmail = await this.git.getConfigValue('committer.email')
|
|
||||||
const authorName = await this.git.getConfigValue('author.name')
|
|
||||||
const authorEmail = await this.git.getConfigValue('author.email')
|
|
||||||
return {
|
|
||||||
authorName: authorName,
|
|
||||||
authorEmail: authorEmail,
|
|
||||||
committerName: committerName,
|
|
||||||
committerEmail: committerEmail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
async getIdentity(author: string, committer: string): Promise<GitIdentity> {
|
|
||||||
// If either committer or author is supplied they will be cross used
|
|
||||||
if (!committer && author) {
|
|
||||||
core.info('Supplied author will also be used as the committer.')
|
|
||||||
committer = author
|
|
||||||
}
|
|
||||||
if (!author && committer) {
|
|
||||||
core.info('Supplied committer will also be used as the author.')
|
|
||||||
author = committer
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no committer/author has been supplied, try and fetch identity
|
|
||||||
// configuration already existing in git config.
|
|
||||||
if (!committer && !author) {
|
|
||||||
const identity = await this.getGitIdentityFromConfig()
|
|
||||||
if (identity) {
|
|
||||||
core.info('Retrieved a pre-configured git identity.')
|
|
||||||
return identity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set defaults if no committer/author has been supplied and no
|
|
||||||
// existing identity configuration was found.
|
|
||||||
if (!committer && !author) {
|
|
||||||
core.info('Action defaults set for the author and committer.')
|
|
||||||
committer = DEFAULT_COMMITTER
|
|
||||||
author = DEFAULT_AUTHOR
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedAuthor = utils.parseDisplayNameEmail(author)
|
|
||||||
const parsedCommitter = utils.parseDisplayNameEmail(committer)
|
|
||||||
return {
|
|
||||||
authorName: parsedAuthor.name,
|
|
||||||
authorEmail: parsedAuthor.email,
|
|
||||||
committerName: parsedCommitter.name,
|
|
||||||
committerEmail: parsedCommitter.email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue