Browse Source

SONAR-13101 Configure URL and Project IDs for GitLab MR decoration

tags/8.2.0.32929
Wouter Admiraal 4 years ago
parent
commit
01f2398ff5
18 changed files with 323 additions and 38 deletions
  1. 6
    1
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx
  2. 5
    3
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
  3. 4
    1
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx
  4. 4
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx
  5. 19
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
  6. 6
    1
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx
  7. 4
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx
  8. 4
    3
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
  9. 39
    14
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap
  10. 40
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
  11. 16
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap
  12. 9
    4
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx
  13. 14
    2
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
  14. 18
    8
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx
  15. 12
    0
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx
  16. 115
    1
      server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap
  17. 2
    0
      server/sonar-web/src/main/js/types/alm-settings.ts
  18. 6
    0
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 6
- 1
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx View File

@@ -40,6 +40,7 @@ interface Props<B> {
onDelete?: (definitionKey: string) => void;
onEdit?: (definitionKey: string) => void;
onSubmit: (data: B, originalKey: string) => void;
optionalFields?: Array<keyof B>;
readOnly?: boolean;
showInModal?: boolean;
success?: boolean;
@@ -98,7 +99,7 @@ export default class AlmBindingDefinitionForm<
};

canSubmit = () => {
const { hideKeyField } = this.props;
const { hideKeyField, optionalFields } = this.props;
const { formData, touched } = this.state;

let values;
@@ -108,6 +109,10 @@ export default class AlmBindingDefinitionForm<
values = { ...formData };
}

if (optionalFields && optionalFields.length > 0) {
values = omit(values, optionalFields);
}

return touched && !Object.values(values).some(v => !v);
};


+ 5
- 3
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx View File

@@ -29,6 +29,7 @@ export interface AlmBindingDefinitionFormFieldProps<B extends AlmBindingDefiniti
isTextArea?: boolean;
maxLength?: number;
onFieldChange: (id: keyof B, value: string) => void;
optional?: boolean;
propKey: keyof B;
readOnly?: boolean;
value: string;
@@ -44,6 +45,7 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
isTextArea,
maxLength,
onFieldChange,
optional,
propKey,
readOnly = false,
value
@@ -53,8 +55,8 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
<div className="modal-field">
<label className="display-flex-center" htmlFor={id}>
{translate('settings.almintegration.form', id)}
<em className="mandatory spacer-right">*</em>
{help && <HelpTooltip overlay={help} placement="right" />}
{!optional && <em className="mandatory">*</em>}
{help && <HelpTooltip className="spacer-left" overlay={help} placement="right" />}
</label>
{isTextArea ? (
<textarea
@@ -63,7 +65,7 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
id={id}
maxLength={maxLength || 2000}
onChange={e => onFieldChange(propKey, e.currentTarget.value)}
required={true}
required={!optional}
rows={5}
value={value}
/>

+ 4
- 1
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx View File

@@ -38,6 +38,7 @@ interface Props<B> {
multipleAlmEnabled: boolean;
onDelete: (definitionKey: string) => void;
onUpdateDefinitions: () => void;
optionalFields?: Array<keyof B>;
updateConfiguration: (data: B & { newKey?: string }) => Promise<void>;
}

@@ -112,7 +113,8 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo
form,
help,
loading,
multipleAlmEnabled
multipleAlmEnabled,
optionalFields
} = this.props;
const { editedDefinition, submitting, success } = this.state;

@@ -135,6 +137,7 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo
onDelete={this.props.onDelete}
onEdit={this.handleEdit}
onSubmit={this.handleSubmit}
optionalFields={optionalFields}
success={success}
/>
);

+ 4
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx View File

@@ -49,6 +49,7 @@ export interface AlmTabRendererProps<B> {
onDelete: (definitionKey: string) => void;
onEdit: (definitionKey: string) => void;
onSubmit: (config: B, originalKey: string) => void;
optionalFields?: Array<keyof B>;
success: boolean;
}

@@ -67,6 +68,7 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
form,
loading,
multipleAlmEnabled,
optionalFields,
success,
help = (
<FormattedMessage
@@ -123,6 +125,7 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
help={help}
onCancel={props.onCancel}
onSubmit={props.onSubmit}
optionalFields={optionalFields}
showInModal={true}>
{form}
</AlmBindingDefinitionForm>
@@ -138,6 +141,7 @@ export default function AlmTabRenderer<B extends AlmBindingDefinition>(
onDelete={definition ? props.onDelete : undefined}
onEdit={showEdit ? props.onEdit : undefined}
onSubmit={props.onSubmit}
optionalFields={optionalFields}
readOnly={showEdit}
success={success}>
{form}

+ 19
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx View File

@@ -45,6 +45,25 @@ export default function GitlabForm(props: GitlabFormProps) {
value={formData.key}
/>
)}
<AlmBindingDefinitionFormField
help={
<>
{translate('settings.almintegration.form.url.gitlab.help1')}
<br />
<br />
{translate('settings.almintegration.form.url.gitlab.help2')}
<br />
<em>https://gitlab.com/api/v4</em>
</>
}
id="url.gitlab"
maxLength={2000}
onFieldChange={onFieldChange}
optional={true}
propKey="url"
readOnly={readOnly}
value={formData.url || ''}
/>
<AlmBindingDefinitionFormField
help={translate('settings.almintegration.form.personal_access_token.gitlab.help')}
id="personal_access_token"

+ 6
- 1
server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx View File

@@ -44,9 +44,13 @@ export default function GitlabTab(props: GitlabTabProps) {
{branchesEnabled && (
<>
<AlmTab
additionalColumnsHeaders={[
translate('settings.almintegration.table.column.gitlab.url')
]}
additionalColumnsKeys={['url']}
alm={AlmKeys.GitLab}
createConfiguration={createGitlabConfiguration}
defaultBinding={{ key: '', personalAccessToken: '' }}
defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
definitions={definitions}
features={[
{
@@ -61,6 +65,7 @@ export default function GitlabTab(props: GitlabTabProps) {
multipleAlmEnabled={multipleAlmEnabled}
onDelete={props.onDelete}
onUpdateDefinitions={props.onUpdateDefinitions}
optionalFields={['url']}
updateConfiguration={updateGitlabConfiguration}
/>


+ 4
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx View File

@@ -119,6 +119,10 @@ it('should (dis)allow submit by validating its state', () => {
wrapper.setState({ formData: mockGithubDefinition({ key: '' }), touched: true });
wrapper.setProps({ hideKeyField: true });
expect(wrapper.instance().canSubmit()).toBe(true);

wrapper.setState({ formData: mockGithubDefinition({ url: '' }), touched: true });
wrapper.setProps({ optionalFields: ['url'] });
expect(wrapper.instance().canSubmit()).toBe(true);
});

function shallowRender(

+ 4
- 3
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx View File

@@ -26,9 +26,10 @@ import {
} from '../AlmBindingDefinitionFormField';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ help: 'help' })).toMatchSnapshot();
expect(shallowRender({ isTextArea: true })).toMatchSnapshot();
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ help: 'help' })).toMatchSnapshot('with help');
expect(shallowRender({ isTextArea: true })).toMatchSnapshot('textarea');
expect(shallowRender({ optional: true })).toMatchSnapshot('optional');
});

it('should call onFieldChange', () => {

+ 39
- 14
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
exports[`should render correctly: default 1`] = `
<div
className="modal-field"
>
@@ -10,7 +10,7 @@ exports[`should render correctly 1`] = `
>
settings.almintegration.form.key
<em
className="mandatory spacer-right"
className="mandatory"
>
*
</em>
@@ -29,7 +29,7 @@ exports[`should render correctly 1`] = `
</div>
`;

exports[`should render correctly 2`] = `
exports[`should render correctly: optional 1`] = `
<div
className="modal-field"
>
@@ -38,15 +38,6 @@ exports[`should render correctly 2`] = `
htmlFor="key"
>
settings.almintegration.form.key
<em
className="mandatory spacer-right"
>
*
</em>
<HelpTooltip
overlay="help"
placement="right"
/>
</label>
<input
className="input-super-large"
@@ -62,7 +53,7 @@ exports[`should render correctly 2`] = `
</div>
`;

exports[`should render correctly 3`] = `
exports[`should render correctly: textarea 1`] = `
<div
className="modal-field"
>
@@ -72,7 +63,7 @@ exports[`should render correctly 3`] = `
>
settings.almintegration.form.key
<em
className="mandatory spacer-right"
className="mandatory"
>
*
</em>
@@ -89,3 +80,37 @@ exports[`should render correctly 3`] = `
/>
</div>
`;

exports[`should render correctly: with help 1`] = `
<div
className="modal-field"
>
<label
className="display-flex-center"
htmlFor="key"
>
settings.almintegration.form.key
<em
className="mandatory"
>
*
</em>
<HelpTooltip
className="spacer-left"
overlay="help"
placement="right"
/>
</label>
<input
className="input-super-large"
disabled={false}
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</div>
`;

+ 40
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap View File

@@ -10,6 +10,26 @@ exports[`should render correctly 1`] = `
propKey="key"
value=""
/>
<AlmBindingDefinitionFormField
help={
<React.Fragment>
settings.almintegration.form.url.gitlab.help1
<br />
<br />
settings.almintegration.form.url.gitlab.help2
<br />
<em>
https://gitlab.com/api/v4
</em>
</React.Fragment>
}
id="url.gitlab"
maxLength={2000}
onFieldChange={[MockFunction]}
optional={true}
propKey="url"
value=""
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.personal_access_token.gitlab.help"
id="personal_access_token"
@@ -31,6 +51,26 @@ exports[`should render correctly 2`] = `
propKey="key"
value="foo"
/>
<AlmBindingDefinitionFormField
help={
<React.Fragment>
settings.almintegration.form.url.gitlab.help1
<br />
<br />
settings.almintegration.form.url.gitlab.help2
<br />
<em>
https://gitlab.com/api/v4
</em>
</React.Fragment>
}
id="url.gitlab"
maxLength={2000}
onFieldChange={[MockFunction]}
optional={true}
propKey="url"
value=""
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.personal_access_token.gitlab.help"
id="personal_access_token"

+ 16
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap View File

@@ -5,12 +5,23 @@ exports[`should render correctly: with branch support 1`] = `
className="bordered"
>
<AlmTab
additionalColumnsHeaders={
Array [
"settings.almintegration.table.column.gitlab.url",
]
}
additionalColumnsKeys={
Array [
"url",
]
}
alm="gitlab"
createConfiguration={[Function]}
defaultBinding={
Object {
"key": "",
"personalAccessToken": "",
"url": "",
}
}
definitions={
@@ -36,6 +47,11 @@ exports[`should render correctly: with branch support 1`] = `
multipleAlmEnabled={true}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
optionalFields={
Array [
"url",
]
}
updateConfiguration={[Function]}
/>
<div

+ 9
- 4
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx View File

@@ -45,7 +45,9 @@ interface State {
success: boolean;
}

const FIELDS_BY_ALM: { [almKey in AlmKeys]: Array<keyof T.Omit<ProjectAlmBinding, 'key'>> } = {
const REQUIRED_FIELDS_BY_ALM: {
[almKey in AlmKeys]: Array<keyof T.Omit<ProjectAlmBinding, 'key'>>;
} = {
[AlmKeys.Azure]: [],
[AlmKeys.Bitbucket]: ['repository', 'slug'],
[AlmKeys.GitHub]: ['repository'],
@@ -170,11 +172,14 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
});
}

case AlmKeys.GitLab:
case AlmKeys.GitLab: {
const repository = almSpecificFields && almSpecificFields.repository;
return setProjectGitlabBinding({
almSetting,
project
project,
repository
});
}

default:
return Promise.reject();
@@ -228,7 +233,7 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat
if (!key || !selected) {
return false;
}
return FIELDS_BY_ALM[selected.alm].reduce(
return REQUIRED_FIELDS_BY_ALM[selected.alm].reduce(
(result: boolean, field) => result && Boolean(additionalFields[field]),
true
);

+ 14
- 2
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx View File

@@ -58,17 +58,19 @@ function renderField(props: {
helpParams?: { [key: string]: string | JSX.Element };
id: string;
onFieldChange: (id: keyof ProjectAlmBinding, value: string) => void;
optional?: boolean;
propKey: keyof ProjectAlmBinding;
value: string;
}) {
const { help, helpParams, id, propKey, value, onFieldChange } = props;
const { help, helpParams, id, propKey, optional, value, onFieldChange } = props;
return (
<div className="form-field">
<label className="display-flex-center" htmlFor={id}>
{translate('settings.pr_decoration.binding.form', id)}
<em className="mandatory spacer-right">*</em>
{!optional && <em className="mandatory">*</em>}
{help && (
<HelpTooltip
className="spacer-left"
overlay={
<FormattedMessage
defaultMessage={translate('settings.pr_decoration.binding.form', id, 'help')}
@@ -226,6 +228,16 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
value: repository || ''
})}

{alm === AlmKeys.GitLab &&
renderField({
help: true,
id: 'gitlab.repository',
onFieldChange: props.onFieldChange,
optional: true,
propKey: 'repository',
value: repository || ''
})}

<div className="display-flex-center">
<DeferredSpinner className="spacer-right" loading={saving} />
{isChanged && (

+ 18
- 8
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx View File

@@ -69,15 +69,15 @@ it('should fill selects and fill formdata', async () => {
expect(wrapper.state().originalData).toEqual(formdata);
});

const formData = {
key: 'whatever',
repository: 'something/else'
};

it('should handle reset', async () => {
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
wrapper.setState({ formData });
wrapper.setState({
formData: {
key: 'whatever',
repository: 'something/else'
}
});

wrapper.instance().handleReset();
await waitAndUpdate(wrapper);
@@ -153,7 +153,12 @@ it('should handle failures gracefully', async () => {

const wrapper = shallowRender();
await waitAndUpdate(wrapper);
wrapper.setState({ formData });
wrapper.setState({
formData: {
key: 'whatever',
repository: 'something/else'
}
});

wrapper.instance().handleSubmit();
await waitAndUpdate(wrapper);
@@ -197,9 +202,11 @@ it('should validate form', async () => {
instances: [
{ key: 'azure', alm: AlmKeys.Azure },
{ key: 'bitbucket', alm: AlmKeys.Bitbucket },
{ key: 'github', alm: AlmKeys.GitHub }
{ key: 'github', alm: AlmKeys.GitHub },
{ key: 'gitlab', alm: AlmKeys.GitLab }
]
});

expect(wrapper.instance().validateForm({ key: 'azure' })).toBe(true);

expect(wrapper.instance().validateForm({ key: 'github', repository: '' })).toBe(false);
@@ -209,6 +216,9 @@ it('should validate form', async () => {
expect(
wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key', slug: 'slug' })
).toBe(true);

expect(wrapper.instance().validateForm({ key: 'gitlab' })).toBe(true);
expect(wrapper.instance().validateForm({ key: 'gitlab', repository: 'key' })).toBe(true);
});

function shallowRender(props: Partial<PRDecorationBinding['props']> = {}) {

+ 12
- 0
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx View File

@@ -131,6 +131,18 @@ it('should render select options correctly', async () => {
expect(optionRenderer!(instances[1])).toMatchSnapshot();
});

it('should render optional fields correctly', () => {
expect(
shallowRender({
formData: {
key: 'key'
},
instances: [{ key: 'key', url: 'http://example.com', alm: AlmKeys.GitLab }],
loading: false
})
).toMatchSnapshot();
});

function shallowRender(props: Partial<PRDecorationBindingRendererProps> = {}) {
return shallow(
<PRDecorationBindingRenderer

+ 115
- 1
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap View File

@@ -428,11 +428,12 @@ exports[`should render multiple instances correctly 2`] = `
>
settings.pr_decoration.binding.form.github.repository
<em
className="mandatory spacer-right"
className="mandatory"
>
*
</em>
<HelpTooltip
className="spacer-left"
overlay={
<FormattedMessage
defaultMessage="settings.pr_decoration.binding.form.github.repository.help"
@@ -480,6 +481,119 @@ exports[`should render multiple instances correctly 2`] = `
</div>
`;

exports[`should render optional fields correctly 1`] = `
<div>
<header
className="page-header"
>
<h1
className="page-title"
>
settings.pr_decoration.binding.title
</h1>
</header>
<div
className="markdown small spacer-top big-spacer-bottom"
>
settings.pr_decoration.binding.description
</div>
<form
onSubmit={[Function]}
>
<div
className="form-field"
>
<label
htmlFor="name"
>
settings.pr_decoration.binding.form.name
<em
className="mandatory spacer-right"
>
*
</em>
</label>
<Select
autosize={true}
className="abs-width-400"
clearable={false}
id="name"
menuContainerStyle={
Object {
"maxWidth": "210%",
"width": "auto",
}
}
onChange={[Function]}
optionRenderer={[Function]}
options={
Array [
Object {
"alm": "gitlab",
"key": "key",
"url": "http://example.com",
},
]
}
searchable={false}
value="key"
valueKey="key"
valueRenderer={[Function]}
/>
</div>
<div
className="form-field"
>
<label
className="display-flex-center"
htmlFor="gitlab.repository"
>
settings.pr_decoration.binding.form.gitlab.repository
<HelpTooltip
className="spacer-left"
overlay={
<FormattedMessage
defaultMessage="settings.pr_decoration.binding.form.gitlab.repository.help"
id="settings.pr_decoration.binding.form.gitlab.repository.help"
values={Object {}}
/>
}
placement="right"
/>
</label>
<input
className="input-super-large"
id="gitlab.repository"
maxLength={256}
name="gitlab.repository"
onChange={[Function]}
type="text"
value=""
/>
</div>
<div
className="display-flex-center"
>
<DeferredSpinner
className="spacer-right"
loading={false}
timeout={100}
/>
<SubmitButton
className="spacer-right button-success"
disabled={true}
>
<span
data-test="project-settings__alm-save"
>
save
</span>
</SubmitButton>
</div>
</form>
</div>
`;

exports[`should render select options correctly 1`] = `
<span>
azure

+ 2
- 0
server/sonar-web/src/main/js/types/alm-settings.ts View File

@@ -45,6 +45,7 @@ export interface GithubBindingDefinition extends AlmBindingDefinition {

export interface GitlabBindingDefinition extends AlmBindingDefinition {
personalAccessToken: string;
url?: string;
}

export interface ProjectAlmBinding {
@@ -74,6 +75,7 @@ export interface GithubProjectAlmBinding {
export interface GitlabProjectAlmBinding {
almSetting: string;
project: string;
repository?: string;
}

export interface AlmSettingsInstance {

+ 6
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -1035,6 +1035,7 @@ settings.almintegration.table.create=Create configuration
settings.almintegration.table.column.name=Name
settings.almintegration.table.column.bitbucket.url=Bitbucket Server URL
settings.almintegration.table.column.github.url=GitHub Enterprise or GitHub.com URL
settings.almintegration.table.column.gitlab.url=GitLab Self-Managed or GitLab.com URL
settings.almintegration.table.column.app_id=App ID
settings.almintegration.table.column.edit=Edit
settings.almintegration.table.column.delete=Delete
@@ -1057,6 +1058,9 @@ settings.almintegration.form.url.bitbucket.help=Example: {example}
settings.almintegration.form.url.github=GitHub URL
settings.almintegration.form.url.github.help1=Example for Github Enterprise:
settings.almintegration.form.url.github.help2=If using GitHub.com:
settings.almintegration.form.url.gitlab=GitLab URL
settings.almintegration.form.url.gitlab.help1=You do not have to provide this value if you're using GitLab CI.
settings.almintegration.form.url.gitlab.help2=If you're using another CI, provide the GitLab API URL. For example:
settings.almintegration.form.app_id=GitHub App ID
settings.almintegration.form.private_key=Private Key
settings.almintegration.form.personal_access_token=Personal Access token
@@ -1088,6 +1092,8 @@ settings.pr_decoration.binding.form.bitbucket.repository=Project Key
settings.pr_decoration.binding.form.bitbucket.repository.help=The project key is part of your Bitbucket Server repository URL. Example: ({example})
settings.pr_decoration.binding.form.bitbucket.slug=Repository SLUG
settings.pr_decoration.binding.form.bitbucket.slug.help=The Repository Slug is part of your Bitbucket Server repository URL. Example: ({example})
settings.pr_decoration.binding.form.gitlab.repository=Project ID
settings.pr_decoration.binding.form.gitlab.repository.help=If you are using GitLab CI, you do not have to provide this value. For any other CI, provide the project's numerical ID.

property.category.general=General
property.category.general.email=Email

Loading…
Cancel
Save