Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
00a889ea7a
commit
ab8eecd62c
|
|
@ -104,28 +104,6 @@ Graphql/OldTypes:
|
|||
- 'app/graphql/types/container_repository_type.rb'
|
||||
- 'app/graphql/types/countable_connection_type.rb'
|
||||
- 'app/graphql/types/custom_emoji_type.rb'
|
||||
- 'app/graphql/types/query_complexity_type.rb'
|
||||
- 'app/graphql/types/release_asset_link_shared_input_arguments.rb'
|
||||
- 'app/graphql/types/release_asset_link_type.rb'
|
||||
- 'app/graphql/types/release_assets_type.rb'
|
||||
- 'app/graphql/types/release_links_type.rb'
|
||||
- 'app/graphql/types/release_source_type.rb'
|
||||
- 'app/graphql/types/release_type.rb'
|
||||
- 'app/graphql/types/repository/blob_type.rb'
|
||||
- 'app/graphql/types/repository_type.rb'
|
||||
- 'app/graphql/types/resolvable_interface.rb'
|
||||
- 'app/graphql/types/snippet_type.rb'
|
||||
- 'app/graphql/types/snippets/blob_action_input_type.rb'
|
||||
- 'app/graphql/types/snippets/blob_type.rb'
|
||||
- 'app/graphql/types/task_completion_status.rb'
|
||||
- 'app/graphql/types/terraform/state_type.rb'
|
||||
- 'app/graphql/types/terraform/state_version_type.rb'
|
||||
- 'app/graphql/types/timelog_type.rb'
|
||||
- 'app/graphql/types/todo_type.rb'
|
||||
- 'app/graphql/types/tree/blob_type.rb'
|
||||
- 'app/graphql/types/tree/entry_type.rb'
|
||||
- 'app/graphql/types/tree/tree_entry_type.rb'
|
||||
- 'app/graphql/types/user_status_type.rb'
|
||||
- 'ee/app/graphql/ee/mutations/ci/ci_cd_settings_update.rb'
|
||||
- 'ee/app/graphql/ee/resolvers/issues_resolver.rb'
|
||||
- 'ee/app/graphql/ee/resolvers/namespace_projects_resolver.rb'
|
||||
|
|
@ -2750,45 +2728,9 @@ Style/RegexpLiteralMixedPreserve:
|
|||
- 'spec/support/helpers/require_migration.rb'
|
||||
- 'spec/views/layouts/_head.html.haml_spec.rb'
|
||||
|
||||
# WIP see: https://gitlab.com/gitlab-org/gitlab/-/issues/335808
|
||||
Database/MultipleDatabases:
|
||||
Exclude:
|
||||
- 'app/mailers/previews/notify_preview.rb'
|
||||
- 'app/models/application_setting.rb'
|
||||
- 'app/models/internal_id.rb'
|
||||
- 'app/services/auto_merge/base_service.rb'
|
||||
- 'app/services/ci/delete_unit_tests_service.rb'
|
||||
- 'app/services/ci/unlock_artifacts_service.rb'
|
||||
- 'app/services/deployments/update_environment_service.rb'
|
||||
- 'app/services/design_management/copy_design_collection/copy_service.rb'
|
||||
- 'app/services/feature_flags/create_service.rb'
|
||||
- 'app/services/feature_flags/destroy_service.rb'
|
||||
- 'app/services/feature_flags/update_service.rb'
|
||||
- 'app/services/issuable/clone/base_service.rb'
|
||||
- 'app/services/issuable/common_system_notes_service.rb'
|
||||
- 'app/services/issuable/destroy_label_links_service.rb'
|
||||
- 'app/services/packages/create_dependency_service.rb'
|
||||
- 'app/services/packages/go/create_package_service.rb'
|
||||
- 'app/services/packages/npm/create_package_service.rb'
|
||||
- 'app/services/packages/terraform_module/create_package_service.rb'
|
||||
- 'app/services/projects/cleanup_service.rb'
|
||||
- 'app/services/projects/fetch_statistics_increment_service.rb'
|
||||
- 'app/services/releases/update_service.rb'
|
||||
- 'app/services/todos/destroy/destroyed_issuable_service.rb'
|
||||
- 'ee/app/models/dora/daily_metrics.rb'
|
||||
- 'ee/app/services/analytics/devops_adoption/enabled_namespaces/bulk_delete_service.rb'
|
||||
- 'ee/app/services/approval_rules/finalize_service.rb'
|
||||
- 'ee/app/services/approval_rules/project_rule_destroy_service.rb'
|
||||
- 'ee/app/services/app_sec/dast/site_profiles/create_service.rb'
|
||||
- 'ee/app/services/app_sec/dast/site_profiles/update_service.rb'
|
||||
- 'ee/app/services/ci/minutes/update_build_minutes_service.rb'
|
||||
- 'ee/app/services/ee/issuable/common_system_notes_service.rb'
|
||||
- 'ee/app/services/group_saml/group_managed_accounts/transfer_membership_service.rb'
|
||||
- 'ee/app/services/group_saml/sign_up_service.rb'
|
||||
- 'ee/app/services/iterations/roll_over_issues_service.rb'
|
||||
- 'ee/app/services/security/store_scan_service.rb'
|
||||
- 'ee/app/services/timebox_report_service.rb'
|
||||
- 'ee/app/services/vulnerability_feedback/create_service.rb'
|
||||
- 'ee/lib/ee/gitlab/checks/push_rule_check.rb'
|
||||
- 'ee/lib/ee/gitlab/database.rb'
|
||||
- 'ee/lib/gitlab/geo/database_tasks.rb'
|
||||
- 'ee/lib/gitlab/geo/geo_tasks.rb'
|
||||
|
|
@ -2804,14 +2746,7 @@ Database/MultipleDatabases:
|
|||
- 'lib/after_commit_queue.rb'
|
||||
- 'lib/api/rubygem_packages.rb'
|
||||
- 'lib/backup/manager.rb'
|
||||
- 'lib/gitlab/analytics/cycle_analytics/stage_query_helpers.rb'
|
||||
- 'lib/gitlab/chaos.rb'
|
||||
- 'lib/gitlab/current_settings.rb'
|
||||
- 'lib/gitlab/database/batch_count.rb'
|
||||
- 'lib/gitlab/database/batch_counter.rb'
|
||||
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
|
||||
- 'lib/gitlab/database/count/tablesample_count_strategy.rb'
|
||||
- 'lib/gitlab/database/grant.rb'
|
||||
- 'lib/gitlab/database/load_balancing/load_balancer.rb'
|
||||
- 'lib/gitlab/database/load_balancing.rb'
|
||||
- 'lib/gitlab/database/load_balancing/sticking.rb'
|
||||
|
|
@ -2833,7 +2768,6 @@ Database/MultipleDatabases:
|
|||
- 'lib/gitlab/database/schema_cache_with_renamed_table.rb'
|
||||
- 'lib/gitlab/database/schema_migrations/context.rb'
|
||||
- 'lib/gitlab/database/schema_version_files.rb'
|
||||
- 'lib/gitlab/database/similarity_score.rb'
|
||||
- 'lib/gitlab/database/unidirectional_copy_trigger.rb'
|
||||
- 'lib/gitlab/database/with_lock_retries.rb'
|
||||
- 'lib/gitlab/gitlab_import/importer.rb'
|
||||
|
|
@ -2842,13 +2776,8 @@ Database/MultipleDatabases:
|
|||
- 'lib/gitlab/import_export/relation_tree_restorer.rb'
|
||||
- 'lib/gitlab/legacy_github_import/importer.rb'
|
||||
- 'lib/gitlab/metrics/samplers/database_sampler.rb'
|
||||
- 'lib/gitlab/optimistic_locking.rb'
|
||||
- 'lib/gitlab/otp_key_rotator.rb'
|
||||
- 'lib/gitlab/profiler.rb'
|
||||
- 'lib/gitlab/seeder.rb'
|
||||
- 'lib/gitlab/sherlock/query.rb'
|
||||
- 'lib/gitlab/sql/glob.rb'
|
||||
- 'lib/gitlab/sql/set_operator.rb'
|
||||
- 'lib/system_check/orphans/repository_check.rb'
|
||||
- 'spec/db/schema_spec.rb'
|
||||
- 'spec/features/admin/dashboard_spec.rb'
|
||||
|
|
@ -2864,9 +2793,6 @@ Database/MultipleDatabases:
|
|||
- 'spec/lib/gitlab/profiler_spec.rb'
|
||||
- 'spec/lib/gitlab/query_limiting/active_support_subscriber_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/sql/cte_spec.rb'
|
||||
- 'spec/lib/gitlab/sql/glob_spec.rb'
|
||||
- 'spec/lib/gitlab/sql/recursive_cte_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_metrics_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_queries_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/constraints_spec.rb'
|
||||
|
|
@ -2874,11 +2800,6 @@ Database/MultipleDatabases:
|
|||
- 'spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb'
|
||||
- 'spec/lib/gitlab/utils/usage_data_spec.rb'
|
||||
- 'spec/models/application_setting_spec.rb'
|
||||
- 'spec/models/concerns/case_sensitivity_spec.rb'
|
||||
- 'spec/models/concerns/sortable_spec.rb'
|
||||
- 'spec/models/concerns/where_composite_spec.rb'
|
||||
- 'spec/models/experiment_spec.rb'
|
||||
- 'spec/models/internal_id_spec.rb'
|
||||
- 'spec/models/project_feature_usage_spec.rb'
|
||||
- 'spec/models/users_statistics_spec.rb'
|
||||
- 'spec/requests/api/statistics_spec.rb'
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default {
|
|||
};
|
||||
},
|
||||
update(data) {
|
||||
return data?.projects?.nodes.filter((project) => !project.repository.empty) ?? [];
|
||||
return data?.projects?.nodes.filter((project) => !project.repository?.empty) ?? [];
|
||||
},
|
||||
result() {
|
||||
this.initialProjectsLoading = false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import { PackageType } from '~/packages/shared/constants';
|
||||
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
sourceText: s__('PackageRegistry|Source project located at %{link}'),
|
||||
licenseText: s__('PackageRegistry|License information located at %{link}'),
|
||||
recipeText: s__('PackageRegistry|Recipe: %{recipe}'),
|
||||
appGroup: s__('PackageRegistry|App group: %{group}'),
|
||||
appName: s__('PackageRegistry|App name: %{name}'),
|
||||
},
|
||||
components: {
|
||||
DetailsRow,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
props: {
|
||||
packageEntity: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showMetadata() {
|
||||
const visibilityConditions = {
|
||||
[PackageType.NUGET]: this.packageEntity.nuget_metadatum,
|
||||
[PackageType.CONAN]: this.packageEntity.conan_metadatum,
|
||||
[PackageType.MAVEN]: this.packageEntity.maven_metadatum,
|
||||
};
|
||||
return visibilityConditions[this.packageEntity.package_type];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="showMetadata">
|
||||
<h3 class="gl-font-lg" data-testid="title">{{ __('Additional Metadata') }}</h3>
|
||||
|
||||
<div class="gl-bg-gray-50 gl-inset-border-1-gray-100 gl-rounded-base" data-testid="main">
|
||||
<template v-if="packageEntity.nuget_metadatum">
|
||||
<details-row icon="project" padding="gl-p-4" dashed data-testid="nuget-source">
|
||||
<gl-sprintf :message="$options.i18n.sourceText">
|
||||
<template #link>
|
||||
<gl-link :href="packageEntity.nuget_metadatum.project_url" target="_blank">{{
|
||||
packageEntity.nuget_metadatum.project_url
|
||||
}}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</details-row>
|
||||
<details-row icon="license" padding="gl-p-4" data-testid="nuget-license">
|
||||
<gl-sprintf :message="$options.i18n.licenseText">
|
||||
<template #link>
|
||||
<gl-link :href="packageEntity.nuget_metadatum.license_url" target="_blank">{{
|
||||
packageEntity.nuget_metadatum.license_url
|
||||
}}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</details-row>
|
||||
</template>
|
||||
|
||||
<details-row
|
||||
v-else-if="packageEntity.conan_metadatum"
|
||||
icon="information-o"
|
||||
padding="gl-p-4"
|
||||
data-testid="conan-recipe"
|
||||
>
|
||||
<gl-sprintf :message="$options.i18n.recipeText">
|
||||
<template #recipe>{{ packageEntity.name }}</template>
|
||||
</gl-sprintf>
|
||||
</details-row>
|
||||
|
||||
<template v-else-if="packageEntity.maven_metadatum">
|
||||
<details-row icon="information-o" padding="gl-p-4" dashed data-testid="maven-app">
|
||||
<gl-sprintf :message="$options.i18n.appName">
|
||||
<template #name>
|
||||
<strong>{{ packageEntity.maven_metadatum.app_name }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</details-row>
|
||||
<details-row icon="information-o" padding="gl-p-4" data-testid="maven-group">
|
||||
<gl-sprintf :message="$options.i18n.appGroup">
|
||||
<template #group>
|
||||
<strong>{{ packageEntity.maven_metadatum.app_group }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</details-row>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'ComposerInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['composerHelpPath']),
|
||||
...mapGetters(['composerRegistryInclude', 'composerPackageInclude', 'groupExists']),
|
||||
},
|
||||
i18n: {
|
||||
registryInclude: s__('PackageRegistry|Add composer registry'),
|
||||
copyRegistryInclude: s__('PackageRegistry|Copy registry include'),
|
||||
packageInclude: s__('PackageRegistry|Install package version'),
|
||||
copyPackageInclude: s__('PackageRegistry|Copy require package include'),
|
||||
infoLine: s__(
|
||||
'PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [{ value: 'composer', label: s__('PackageRegistry|Show Composer commands') }],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="groupExists" data-testid="root-node">
|
||||
<installation-title package-type="composer" :options="$options.installOptions" />
|
||||
|
||||
<code-instruction
|
||||
:label="$options.i18n.registryInclude"
|
||||
:instruction="composerRegistryInclude"
|
||||
:copy-text="$options.i18n.copyRegistryInclude"
|
||||
:tracking-action="$options.trackingActions.COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
data-testid="registry-include"
|
||||
/>
|
||||
|
||||
<code-instruction
|
||||
:label="$options.i18n.packageInclude"
|
||||
:instruction="composerPackageInclude"
|
||||
:copy-text="$options.i18n.copyPackageInclude"
|
||||
:tracking-action="$options.trackingActions.COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
data-testid="package-include"
|
||||
/>
|
||||
<span data-testid="help-text">
|
||||
<gl-sprintf :message="$options.i18n.infoLine">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="composerHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'ConanInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['conanHelpPath']),
|
||||
...mapGetters(['conanInstallationCommand', 'conanSetupCommand']),
|
||||
},
|
||||
i18n: {
|
||||
helpText: s__(
|
||||
'PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}.',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [{ value: 'conan', label: s__('PackageRegistry|Show Conan commands') }],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<installation-title package-type="conan" :options="$options.installOptions" />
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Conan Command')"
|
||||
:instruction="conanInstallationCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Conan Command')"
|
||||
:tracking-action="$options.trackingActions.COPY_CONAN_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Add Conan Remote')"
|
||||
:instruction="conanSetupCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Conan Setup Command')"
|
||||
:tracking-action="$options.trackingActions.COPY_CONAN_SETUP_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<gl-sprintf :message="$options.i18n.helpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="conanHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'DependencyRow',
|
||||
props: {
|
||||
dependency: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showVersion() {
|
||||
return Boolean(this.dependency.version_pattern);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gl-responsive-table-row">
|
||||
<div class="table-section section-50">
|
||||
<strong class="gl-text-body">{{ dependency.name }}</strong>
|
||||
<span v-if="dependency.target_framework" data-testid="target-framework"
|
||||
>({{ dependency.target_framework }})</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="showVersion"
|
||||
class="table-section section-50 gl-display-flex gl-md-justify-content-end"
|
||||
data-testid="version-pattern"
|
||||
>
|
||||
<span class="gl-text-body">{{ dependency.version_pattern }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<script>
|
||||
import { s__ } from '~/locale';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
|
||||
|
||||
export default {
|
||||
name: 'FileSha',
|
||||
components: {
|
||||
DetailsRow,
|
||||
ClipboardButton,
|
||||
},
|
||||
props: {
|
||||
sha: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
copyButtonTitle: s__('PackageRegistry|Copy SHA'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<details-row dashed>
|
||||
<div class="gl-px-4">
|
||||
{{ title }}:
|
||||
{{ sha }}
|
||||
<clipboard-button
|
||||
:text="sha"
|
||||
:title="$options.i18n.copyButtonTitle"
|
||||
category="tertiary"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</details-row>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<script>
|
||||
import { PackageType, TERRAFORM_PACKAGE_TYPE } from '~/packages/shared/constants';
|
||||
import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/components/terraform_installation.vue';
|
||||
import ComposerInstallation from './composer_installation.vue';
|
||||
import ConanInstallation from './conan_installation.vue';
|
||||
import MavenInstallation from './maven_installation.vue';
|
||||
import NpmInstallation from './npm_installation.vue';
|
||||
import NugetInstallation from './nuget_installation.vue';
|
||||
import PypiInstallation from './pypi_installation.vue';
|
||||
|
||||
export default {
|
||||
name: 'InstallationCommands',
|
||||
components: {
|
||||
[PackageType.CONAN]: ConanInstallation,
|
||||
[PackageType.MAVEN]: MavenInstallation,
|
||||
[PackageType.NPM]: NpmInstallation,
|
||||
[PackageType.NUGET]: NugetInstallation,
|
||||
[PackageType.PYPI]: PypiInstallation,
|
||||
[PackageType.COMPOSER]: ComposerInstallation,
|
||||
[TERRAFORM_PACKAGE_TYPE]: TerraformInstallation,
|
||||
},
|
||||
props: {
|
||||
packageEntity: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
npmPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
npmHelpPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
installationComponent() {
|
||||
return this.$options.components[this.packageEntity.package_type];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="installationComponent">
|
||||
<component
|
||||
:is="installationComponent"
|
||||
:name="packageEntity.name"
|
||||
:registry-url="npmPath"
|
||||
:help-url="npmHelpPath"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<script>
|
||||
import PersistedDropdownSelection from '~/vue_shared/components/registry/persisted_dropdown_selection.vue';
|
||||
|
||||
export default {
|
||||
name: 'InstallationTitle',
|
||||
components: {
|
||||
PersistedDropdownSelection,
|
||||
},
|
||||
props: {
|
||||
packageType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
storageKey() {
|
||||
return `package_${this.packageType}_installation_instructions`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
|
||||
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
|
||||
<div>
|
||||
<persisted-dropdown-selection
|
||||
:storage-key="storageKey"
|
||||
:options="options"
|
||||
@change="$emit('change', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'MavenInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
instructionType: 'maven',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['mavenHelpPath']),
|
||||
...mapGetters([
|
||||
'mavenInstallationXml',
|
||||
'mavenInstallationCommand',
|
||||
'mavenSetupXml',
|
||||
'gradleGroovyInstalCommand',
|
||||
'gradleGroovyAddSourceCommand',
|
||||
'gradleKotlinInstalCommand',
|
||||
'gradleKotlinAddSourceCommand',
|
||||
]),
|
||||
showMaven() {
|
||||
return this.instructionType === 'maven';
|
||||
},
|
||||
showGroovy() {
|
||||
return this.instructionType === 'groovy';
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
xmlText: s__(
|
||||
`PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block.`,
|
||||
),
|
||||
setupText: s__(
|
||||
`PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file.`,
|
||||
),
|
||||
helpText: s__(
|
||||
'PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}.',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [
|
||||
{ value: 'maven', label: s__('PackageRegistry|Maven XML') },
|
||||
{ value: 'groovy', label: s__('PackageRegistry|Gradle Groovy DSL') },
|
||||
{ value: 'kotlin', label: s__('PackageRegistry|Gradle Kotlin DSL') },
|
||||
],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<installation-title
|
||||
package-type="maven"
|
||||
:options="$options.installOptions"
|
||||
@change="instructionType = $event"
|
||||
/>
|
||||
|
||||
<template v-if="showMaven">
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.xmlText">
|
||||
<template #code="{ content }">
|
||||
<code>{{ content }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
|
||||
<code-instruction
|
||||
:instruction="mavenInstallationXml"
|
||||
:copy-text="s__('PackageRegistry|Copy Maven XML')"
|
||||
:tracking-action="$options.trackingActions.COPY_MAVEN_XML"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
multiline
|
||||
/>
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Maven Command')"
|
||||
:instruction="mavenInstallationCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Maven command')"
|
||||
:tracking-action="$options.trackingActions.COPY_MAVEN_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<h3 class="gl-font-lg">{{ s__('PackageRegistry|Registry setup') }}</h3>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.setupText">
|
||||
<template #code="{ content }">
|
||||
<code>{{ content }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<code-instruction
|
||||
:instruction="mavenSetupXml"
|
||||
:copy-text="s__('PackageRegistry|Copy Maven registry XML')"
|
||||
:tracking-action="$options.trackingActions.COPY_MAVEN_SETUP"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
multiline
|
||||
/>
|
||||
<gl-sprintf :message="$options.i18n.helpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="mavenHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</template>
|
||||
<template v-else-if="showGroovy">
|
||||
<code-instruction
|
||||
class="gl-mb-5"
|
||||
:label="s__('PackageRegistry|Gradle Groovy DSL install command')"
|
||||
:instruction="gradleGroovyInstalCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Gradle Groovy DSL install command')"
|
||||
:tracking-action="$options.trackingActions.COPY_GRADLE_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Add Gradle Groovy DSL repository command')"
|
||||
:instruction="gradleGroovyAddSourceCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy add Gradle Groovy DSL repository command')"
|
||||
:tracking-action="$options.trackingActions.COPY_GRADLE_ADD_TO_SOURCE_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
multiline
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<code-instruction
|
||||
class="gl-mb-5"
|
||||
:label="s__('PackageRegistry|Gradle Kotlin DSL install command')"
|
||||
:instruction="gradleKotlinInstalCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Gradle Kotlin DSL install command')"
|
||||
:tracking-action="$options.trackingActions.COPY_KOTLIN_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Add Gradle Kotlin DSL repository command')"
|
||||
:instruction="gradleKotlinAddSourceCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy add Gradle Kotlin DSL repository command')"
|
||||
:tracking-action="$options.trackingActions.COPY_KOTLIN_ADD_TO_SOURCE_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
multiline
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { NpmManager, TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'NpmInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
instructionType: 'npm',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['npmHelpPath']),
|
||||
...mapGetters(['npmInstallationCommand', 'npmSetupCommand']),
|
||||
npmCommand() {
|
||||
return this.npmInstallationCommand(NpmManager.NPM);
|
||||
},
|
||||
npmSetup() {
|
||||
return this.npmSetupCommand(NpmManager.NPM);
|
||||
},
|
||||
yarnCommand() {
|
||||
return this.npmInstallationCommand(NpmManager.YARN);
|
||||
},
|
||||
yarnSetupCommand() {
|
||||
return this.npmSetupCommand(NpmManager.YARN);
|
||||
},
|
||||
showNpm() {
|
||||
return this.instructionType === 'npm';
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
helpText: s__(
|
||||
'PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more.',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [
|
||||
{ value: 'npm', label: s__('PackageRegistry|Show NPM commands') },
|
||||
{ value: 'yarn', label: s__('PackageRegistry|Show Yarn commands') },
|
||||
],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<installation-title
|
||||
package-type="npm"
|
||||
:options="$options.installOptions"
|
||||
@change="instructionType = $event"
|
||||
/>
|
||||
|
||||
<code-instruction
|
||||
v-if="showNpm"
|
||||
:instruction="npmCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy npm command')"
|
||||
:tracking-action="$options.trackingActions.COPY_NPM_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<code-instruction
|
||||
v-else
|
||||
:instruction="yarnCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy yarn command')"
|
||||
:tracking-action="$options.trackingActions.COPY_YARN_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
|
||||
|
||||
<code-instruction
|
||||
v-if="showNpm"
|
||||
:instruction="npmSetup"
|
||||
:copy-text="s__('PackageRegistry|Copy npm setup command')"
|
||||
:tracking-action="$options.trackingActions.COPY_NPM_SETUP_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<code-instruction
|
||||
v-else
|
||||
:instruction="yarnSetupCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy yarn setup command')"
|
||||
:tracking-action="$options.trackingActions.COPY_YARN_SETUP_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<gl-sprintf :message="$options.i18n.helpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="npmHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'NugetInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['nugetHelpPath']),
|
||||
...mapGetters(['nugetInstallationCommand', 'nugetSetupCommand']),
|
||||
},
|
||||
i18n: {
|
||||
helpText: s__(
|
||||
'PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}.',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [{ value: 'nuget', label: s__('PackageRegistry|Show Nuget commands') }],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<installation-title package-type="nuget" :options="$options.installOptions" />
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|NuGet Command')"
|
||||
:instruction="nugetInstallationCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy NuGet Command')"
|
||||
:tracking-action="$options.trackingActions.COPY_NUGET_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Add NuGet Source')"
|
||||
:instruction="nugetSetupCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy NuGet Setup Command')"
|
||||
:tracking-action="$options.trackingActions.COPY_NUGET_SETUP_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<gl-sprintf :message="$options.i18n.helpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="nugetHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
<script>
|
||||
import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
|
||||
import { last } from 'lodash';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { __ } from '~/locale';
|
||||
import FileSha from '~/packages_and_registries/package_registry/components/details/file_sha.vue';
|
||||
import Tracking from '~/tracking';
|
||||
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
||||
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
export default {
|
||||
name: 'PackageFiles',
|
||||
components: {
|
||||
GlLink,
|
||||
GlTable,
|
||||
GlIcon,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlButton,
|
||||
FileIcon,
|
||||
TimeAgoTooltip,
|
||||
FileSha,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
props: {
|
||||
packageFiles: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
canDelete: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
filesTableRows() {
|
||||
return this.packageFiles.map((pf) => ({
|
||||
...pf,
|
||||
size: this.formatSize(pf.size),
|
||||
pipeline: last(pf.pipelines),
|
||||
}));
|
||||
},
|
||||
showCommitColumn() {
|
||||
return this.filesTableRows.some((row) => Boolean(row.pipeline?.id));
|
||||
},
|
||||
filesTableHeaderFields() {
|
||||
return [
|
||||
{
|
||||
key: 'name',
|
||||
label: __('Name'),
|
||||
},
|
||||
{
|
||||
key: 'commit',
|
||||
label: __('Commit'),
|
||||
hide: !this.showCommitColumn,
|
||||
},
|
||||
{
|
||||
key: 'size',
|
||||
label: __('Size'),
|
||||
},
|
||||
{
|
||||
key: 'created',
|
||||
label: __('Created'),
|
||||
class: 'gl-text-right',
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
label: '',
|
||||
hide: !this.canDelete,
|
||||
class: 'gl-text-right',
|
||||
tdClass: 'gl-w-4',
|
||||
},
|
||||
].filter((c) => !c.hide);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatSize(size) {
|
||||
return numberToHumanSize(size);
|
||||
},
|
||||
hasDetails(item) {
|
||||
return item.file_sha256 || item.file_md5 || item.file_sha1;
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
deleteFile: __('Delete file'),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3>
|
||||
<gl-table
|
||||
:fields="filesTableHeaderFields"
|
||||
:items="filesTableRows"
|
||||
:tbody-tr-attr="{ 'data-testid': 'file-row' }"
|
||||
>
|
||||
<template #cell(name)="{ item, toggleDetails, detailsShowing }">
|
||||
<gl-button
|
||||
v-if="hasDetails(item)"
|
||||
:icon="detailsShowing ? 'angle-up' : 'angle-down'"
|
||||
:aria-label="detailsShowing ? __('Collapse') : __('Expand')"
|
||||
category="tertiary"
|
||||
size="small"
|
||||
@click="toggleDetails"
|
||||
/>
|
||||
<gl-link
|
||||
:href="item.download_path"
|
||||
class="gl-text-gray-500"
|
||||
data-testid="download-link"
|
||||
@click="$emit('download-file')"
|
||||
>
|
||||
<file-icon
|
||||
:file-name="item.file_name"
|
||||
css-classes="gl-relative file-icon"
|
||||
class="gl-mr-1 gl-relative"
|
||||
/>
|
||||
<span>{{ item.file_name }}</span>
|
||||
</gl-link>
|
||||
</template>
|
||||
|
||||
<template #cell(commit)="{ item }">
|
||||
<gl-link
|
||||
v-if="item.pipeline && item.pipeline.project"
|
||||
:href="item.pipeline.project.commit_url"
|
||||
class="gl-text-gray-500"
|
||||
data-testid="commit-link"
|
||||
>{{ item.pipeline.git_commit_message }}</gl-link
|
||||
>
|
||||
</template>
|
||||
|
||||
<template #cell(created)="{ item }">
|
||||
<time-ago-tooltip :time="item.created_at" />
|
||||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
<gl-dropdown category="tertiary" right>
|
||||
<template #button-content>
|
||||
<gl-icon name="ellipsis_v" />
|
||||
</template>
|
||||
<gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
|
||||
{{ $options.i18n.deleteFile }}
|
||||
</gl-dropdown-item>
|
||||
</gl-dropdown>
|
||||
</template>
|
||||
|
||||
<template #row-details="{ item }">
|
||||
<div
|
||||
class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100"
|
||||
>
|
||||
<file-sha
|
||||
v-if="item.file_sha256"
|
||||
data-testid="sha-256"
|
||||
title="SHA-256"
|
||||
:sha="item.file_sha256"
|
||||
/>
|
||||
<file-sha v-if="item.file_md5" data-testid="md5" title="MD5" :sha="item.file_md5" />
|
||||
<file-sha v-if="item.file_sha1" data-testid="sha-1" title="SHA-1" :sha="item.file_sha1" />
|
||||
</div>
|
||||
</template>
|
||||
</gl-table>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { first } from 'lodash';
|
||||
import { truncateSha } from '~/lib/utils/text_utility';
|
||||
import { s__, n__ } from '~/locale';
|
||||
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
|
||||
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
|
||||
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
export default {
|
||||
name: 'PackageHistory',
|
||||
i18n: {
|
||||
createdOn: s__('PackageRegistry|%{name} version %{version} was first created %{datetime}'),
|
||||
createdByCommitText: s__('PackageRegistry|Created by commit %{link} on branch %{branch}'),
|
||||
createdByPipelineText: s__(
|
||||
'PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}',
|
||||
),
|
||||
publishText: s__('PackageRegistry|Published to the %{project} Package Registry %{datetime}'),
|
||||
combinedUpdateText: s__(
|
||||
'PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}',
|
||||
),
|
||||
archivedPipelineMessageSingular: s__('PackageRegistry|Package has %{number} archived update'),
|
||||
archivedPipelineMessagePlural: s__('PackageRegistry|Package has %{number} archived updates'),
|
||||
},
|
||||
components: {
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
HistoryItem,
|
||||
TimeAgoTooltip,
|
||||
},
|
||||
props: {
|
||||
packageEntity: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
projectName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showDescription: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pipelines() {
|
||||
return this.packageEntity.pipelines || [];
|
||||
},
|
||||
firstPipeline() {
|
||||
return first(this.pipelines);
|
||||
},
|
||||
lastPipelines() {
|
||||
return this.pipelines.slice(1).slice(-HISTORY_PIPELINES_LIMIT);
|
||||
},
|
||||
showPipelinesInfo() {
|
||||
return Boolean(this.firstPipeline?.id);
|
||||
},
|
||||
archiviedLines() {
|
||||
return Math.max(this.pipelines.length - HISTORY_PIPELINES_LIMIT - 1, 0);
|
||||
},
|
||||
archivedPipelineMessage() {
|
||||
return n__(
|
||||
this.$options.i18n.archivedPipelineMessageSingular,
|
||||
this.$options.i18n.archivedPipelineMessagePlural,
|
||||
this.archiviedLines,
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
truncate(value) {
|
||||
return truncateSha(value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="issuable-discussion">
|
||||
<h3 class="gl-font-lg" data-testid="title">{{ __('History') }}</h3>
|
||||
<ul class="timeline main-notes-list notes gl-mb-4" data-testid="timeline">
|
||||
<history-item icon="clock" data-testid="created-on">
|
||||
<gl-sprintf :message="$options.i18n.createdOn">
|
||||
<template #name>
|
||||
<strong>{{ packageEntity.name }}</strong>
|
||||
</template>
|
||||
<template #version>
|
||||
<strong>{{ packageEntity.version }}</strong>
|
||||
</template>
|
||||
<template #datetime>
|
||||
<time-ago-tooltip :time="packageEntity.created_at" />
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
|
||||
<template v-if="showPipelinesInfo">
|
||||
<!-- FIRST PIPELINE BLOCK -->
|
||||
<history-item icon="commit" data-testid="first-pipeline-commit">
|
||||
<gl-sprintf :message="$options.i18n.createdByCommitText">
|
||||
<template #link>
|
||||
<gl-link :href="firstPipeline.project.commit_url"
|
||||
>#{{ truncate(firstPipeline.sha) }}</gl-link
|
||||
>
|
||||
</template>
|
||||
<template #branch>
|
||||
<strong>{{ firstPipeline.ref }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
<history-item icon="pipeline" data-testid="first-pipeline-pipeline">
|
||||
<gl-sprintf :message="$options.i18n.createdByPipelineText">
|
||||
<template #link>
|
||||
<gl-link :href="firstPipeline.project.pipeline_url">#{{ firstPipeline.id }}</gl-link>
|
||||
</template>
|
||||
<template #datetime>
|
||||
<time-ago-tooltip :time="firstPipeline.created_at" />
|
||||
</template>
|
||||
<template #author>{{ firstPipeline.user.name }}</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
</template>
|
||||
|
||||
<!-- PUBLISHED LINE -->
|
||||
<history-item icon="package" data-testid="published">
|
||||
<gl-sprintf :message="$options.i18n.publishText">
|
||||
<template #project>
|
||||
<strong>{{ projectName }}</strong>
|
||||
</template>
|
||||
<template #datetime>
|
||||
<time-ago-tooltip :time="packageEntity.created_at" />
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
|
||||
<history-item v-if="archiviedLines" icon="history" data-testid="archived">
|
||||
<gl-sprintf :message="archivedPipelineMessage">
|
||||
<template #number>
|
||||
<strong>{{ archiviedLines }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
|
||||
<!-- PIPELINES LIST ENTRIES -->
|
||||
<history-item
|
||||
v-for="pipeline in lastPipelines"
|
||||
:key="pipeline.id"
|
||||
icon="pencil"
|
||||
data-testid="pipeline-entry"
|
||||
>
|
||||
<gl-sprintf :message="$options.i18n.combinedUpdateText">
|
||||
<template #link>
|
||||
<gl-link :href="pipeline.project.commit_url">#{{ truncate(pipeline.sha) }}</gl-link>
|
||||
</template>
|
||||
<template #branch>
|
||||
<strong>{{ pipeline.ref }}</strong>
|
||||
</template>
|
||||
<template #pipeline>
|
||||
<gl-link :href="pipeline.project.pipeline_url">#{{ pipeline.id }}</gl-link>
|
||||
</template>
|
||||
<template #datetime>
|
||||
<time-ago-tooltip :time="pipeline.created_at" />
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</history-item>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { TrackingActions, TrackingLabels } from '~/packages/details/constants';
|
||||
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
|
||||
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
|
||||
|
||||
export default {
|
||||
name: 'PyPiInstallation',
|
||||
components: {
|
||||
InstallationTitle,
|
||||
CodeInstruction,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['pypiHelpPath']),
|
||||
...mapGetters(['pypiPipCommand', 'pypiSetupCommand']),
|
||||
},
|
||||
i18n: {
|
||||
setupText: s__(
|
||||
`PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file.`,
|
||||
),
|
||||
helpText: s__(
|
||||
'PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}.',
|
||||
),
|
||||
},
|
||||
trackingActions: { ...TrackingActions },
|
||||
TrackingLabels,
|
||||
installOptions: [{ value: 'pypi', label: s__('PackageRegistry|Show PyPi commands') }],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<installation-title package-type="pypi" :options="$options.installOptions" />
|
||||
|
||||
<code-instruction
|
||||
:label="s__('PackageRegistry|Pip Command')"
|
||||
:instruction="pypiPipCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy Pip command')"
|
||||
data-testid="pip-command"
|
||||
:tracking-action="$options.trackingActions.COPY_PIP_INSTALL_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
|
||||
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.setupText">
|
||||
<template #code="{ content }">
|
||||
<code>{{ content }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
|
||||
<code-instruction
|
||||
:instruction="pypiSetupCommand"
|
||||
:copy-text="s__('PackageRegistry|Copy .pypirc content')"
|
||||
data-testid="pypi-setup-content"
|
||||
multiline
|
||||
:tracking-action="$options.trackingActions.COPY_PYPI_SETUP_COMMAND"
|
||||
:tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
|
||||
/>
|
||||
<gl-sprintf :message="$options.i18n.helpText">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="pypiHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import initJiraConnectBranches from '~/jira_connect/branches';
|
||||
|
||||
initJiraConnectBranches();
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<script>
|
||||
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlAlert,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
inject: ['autoDevopsHelpPagePath'],
|
||||
i18n: {
|
||||
body: s__(
|
||||
'AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}',
|
||||
),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-alert variant="success" @dismiss="$emit('dismiss')">
|
||||
<gl-sprintf :message="$options.i18n.body">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="autoDevopsHelpPagePath">
|
||||
{{ content }}
|
||||
</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</gl-alert>
|
||||
</template>
|
||||
|
|
@ -305,3 +305,6 @@ export const featureToMutationMap = {
|
|||
}),
|
||||
},
|
||||
};
|
||||
|
||||
export const AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY =
|
||||
'security_configuration_auto_devops_enabled_dismissed_projects';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
<script>
|
||||
import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
|
||||
import { __, s__ } from '~/locale';
|
||||
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
|
||||
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
|
||||
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
|
||||
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
|
||||
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants';
|
||||
import FeatureCard from './feature_card.vue';
|
||||
import SectionLayout from './section_layout.vue';
|
||||
import UpgradeBanner from './upgrade_banner.vue';
|
||||
|
|
@ -25,16 +28,19 @@ export const i18n = {
|
|||
export default {
|
||||
i18n,
|
||||
components: {
|
||||
GlTab,
|
||||
GlLink,
|
||||
GlTabs,
|
||||
GlSprintf,
|
||||
AutoDevOpsAlert,
|
||||
AutoDevOpsEnabledAlert,
|
||||
FeatureCard,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
GlTab,
|
||||
GlTabs,
|
||||
LocalStorageSync,
|
||||
SectionLayout,
|
||||
UpgradeBanner,
|
||||
AutoDevOpsAlert,
|
||||
UserCalloutDismisser,
|
||||
},
|
||||
inject: ['projectPath'],
|
||||
props: {
|
||||
augmentedSecurityFeatures: {
|
||||
type: Array,
|
||||
|
|
@ -70,6 +76,11 @@ export default {
|
|||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
autoDevopsEnabledAlertDismissedProjects: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canUpgrade() {
|
||||
return [...this.augmentedSecurityFeatures, ...this.augmentedComplianceFeatures].some(
|
||||
|
|
@ -82,12 +93,32 @@ export default {
|
|||
shouldShowDevopsAlert() {
|
||||
return !this.autoDevopsEnabled && !this.gitlabCiPresent && this.canEnableAutoDevops;
|
||||
},
|
||||
shouldShowAutoDevopsEnabledAlert() {
|
||||
return (
|
||||
this.autoDevopsEnabled &&
|
||||
!this.autoDevopsEnabledAlertDismissedProjects.includes(this.projectPath)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
dismissAutoDevopsEnabledAlert() {
|
||||
const dismissedProjects = new Set(this.autoDevopsEnabledAlertDismissedProjects);
|
||||
dismissedProjects.add(this.projectPath);
|
||||
this.autoDevopsEnabledAlertDismissedProjects = Array.from(dismissedProjects);
|
||||
},
|
||||
},
|
||||
autoDevopsEnabledAlertStorageKey: AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article>
|
||||
<local-storage-sync
|
||||
v-model="autoDevopsEnabledAlertDismissedProjects"
|
||||
:storage-key="$options.autoDevopsEnabledAlertStorageKey"
|
||||
as-json
|
||||
/>
|
||||
|
||||
<user-callout-dismisser
|
||||
v-if="shouldShowDevopsAlert"
|
||||
feature-name="security_configuration_devops_alert"
|
||||
|
|
@ -105,8 +136,14 @@ export default {
|
|||
</template>
|
||||
</user-callout-dismisser>
|
||||
|
||||
<gl-tabs content-class="gl-pt-6">
|
||||
<gl-tabs content-class="gl-pt-0">
|
||||
<gl-tab data-testid="security-testing-tab" :title="$options.i18n.securityTesting">
|
||||
<auto-dev-ops-enabled-alert
|
||||
v-if="shouldShowAutoDevopsEnabledAlert"
|
||||
class="gl-mt-3"
|
||||
@dismiss="dismissAutoDevopsEnabledAlert"
|
||||
/>
|
||||
|
||||
<section-layout :heading="$options.i18n.securityTesting">
|
||||
<template #description>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row gl-line-height-20">
|
||||
<div class="row gl-line-height-20 gl-pt-6">
|
||||
<div class="col-lg-4">
|
||||
<h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2>
|
||||
<slot name="description"></slot>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
|
|||
include DependencyProxy::Auth
|
||||
include DependencyProxy::GroupAccess
|
||||
include SendFileUpload
|
||||
include ::PackagesHelper # for event tracking
|
||||
|
||||
before_action :ensure_token_granted!
|
||||
before_action :ensure_feature_enabled!
|
||||
|
|
@ -22,6 +23,8 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
|
|||
response.headers['Etag'] = "\"#{result[:manifest].digest}\""
|
||||
content_type = result[:manifest].content_type
|
||||
|
||||
event_name = tracking_event_name(object_type: :manifest, from_cache: result[:from_cache])
|
||||
track_package_event(event_name, :dependency_proxy, namespace: group, user: current_user)
|
||||
send_upload(
|
||||
result[:manifest].file,
|
||||
proxy: true,
|
||||
|
|
@ -38,6 +41,8 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
|
|||
.new(group, image, token, params[:sha]).execute
|
||||
|
||||
if result[:status] == :success
|
||||
event_name = tracking_event_name(object_type: :blob, from_cache: result[:from_cache])
|
||||
track_package_event(event_name, :dependency_proxy, namespace: group, user: current_user)
|
||||
send_upload(result[:blob].file)
|
||||
else
|
||||
head result[:http_status]
|
||||
|
|
@ -54,6 +59,13 @@ class Groups::DependencyProxyForContainersController < Groups::ApplicationContro
|
|||
params[:tag]
|
||||
end
|
||||
|
||||
def tracking_event_name(object_type:, from_cache:)
|
||||
event_name = "pull_#{object_type}"
|
||||
event_name = "#{event_name}_from_cache" if from_cache
|
||||
|
||||
event_name
|
||||
end
|
||||
|
||||
def dependency_proxy
|
||||
@dependency_proxy ||=
|
||||
group.dependency_proxy_setting || group.create_dependency_proxy_setting
|
||||
|
|
|
|||
|
|
@ -44,27 +44,14 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
|||
|
||||
def modules
|
||||
modules = {
|
||||
jiraDevelopmentTool: {
|
||||
key: 'gitlab-development-tool',
|
||||
application: {
|
||||
value: 'GitLab'
|
||||
},
|
||||
name: {
|
||||
value: 'GitLab'
|
||||
},
|
||||
url: HOME_URL,
|
||||
logoUrl: logo_url,
|
||||
capabilities: %w(branch commit pull_request)
|
||||
},
|
||||
postInstallPage: {
|
||||
key: 'gitlab-configuration',
|
||||
name: {
|
||||
value: 'GitLab Configuration'
|
||||
},
|
||||
name: { value: 'GitLab Configuration' },
|
||||
url: relative_to_base_path(jira_connect_subscriptions_path)
|
||||
}
|
||||
}
|
||||
|
||||
modules.merge!(development_tool_module)
|
||||
modules.merge!(build_information_module)
|
||||
modules.merge!(deployment_information_module)
|
||||
modules.merge!(feature_flag_module)
|
||||
|
|
@ -76,6 +63,29 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
|||
view_context.image_url('gitlab_logo.png')
|
||||
end
|
||||
|
||||
# See https://developer.atlassian.com/cloud/jira/software/modules/development-tool/
|
||||
def development_tool_module
|
||||
actions = {}
|
||||
|
||||
if JiraConnect::BranchesController.feature_enabled?(current_user)
|
||||
actions[:createBranch] = {
|
||||
templateUrl: new_jira_connect_branch_url + '?issue_key={issue.key}&issue_summary={issue.summary}'
|
||||
}
|
||||
end
|
||||
|
||||
{
|
||||
jiraDevelopmentTool: {
|
||||
actions: actions,
|
||||
key: 'gitlab-development-tool',
|
||||
application: { value: 'GitLab' },
|
||||
name: { value: 'GitLab' },
|
||||
url: HOME_URL,
|
||||
logoUrl: logo_url,
|
||||
capabilities: %w(branch commit pull_request)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
# See: https://developer.atlassian.com/cloud/jira/software/modules/deployment/
|
||||
def deployment_information_module
|
||||
{
|
||||
|
|
@ -92,9 +102,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
|||
{
|
||||
jiraFeatureFlagInfoProvider: common_module_properties.merge(
|
||||
actions: {}, # TODO: create, link and list feature flags https://gitlab.com/gitlab-org/gitlab/-/issues/297386
|
||||
name: {
|
||||
value: 'GitLab Feature Flags'
|
||||
},
|
||||
name: { value: 'GitLab Feature Flags' },
|
||||
key: 'gitlab-feature-flags'
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# NOTE: This controller does not inherit from JiraConnect::ApplicationController
|
||||
# because we don't receive a JWT for this action, so we rely on standard GitLab authentication.
|
||||
class JiraConnect::BranchesController < ApplicationController
|
||||
before_action :feature_enabled!
|
||||
|
||||
feature_category :integrations
|
||||
|
||||
def new
|
||||
return unless params[:issue_key].present?
|
||||
|
||||
@branch_name = Issue.to_branch_name(
|
||||
params[:issue_key],
|
||||
params[:issue_summary]
|
||||
)
|
||||
end
|
||||
|
||||
def self.feature_enabled?(user)
|
||||
Feature.enabled?(:jira_connect_create_branch, user, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def feature_enabled!
|
||||
render_404 unless self.class.feature_enabled?(current_user)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Packages
|
||||
class DestroyFile < ::Mutations::BaseMutation
|
||||
graphql_name 'DestroyPackageFile'
|
||||
|
||||
authorize :destroy_package
|
||||
|
||||
argument :id,
|
||||
::Types::GlobalIDType[::Packages::PackageFile],
|
||||
required: true,
|
||||
description: 'ID of the Package file.'
|
||||
|
||||
def resolve(id:)
|
||||
package_file = authorized_find!(id: id)
|
||||
|
||||
if package_file.destroy
|
||||
return { errors: [] }
|
||||
end
|
||||
|
||||
{ errors: package_file.errors.full_messages }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
# TODO: remove this line when the compatibility layer is removed
|
||||
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
|
||||
id = ::Types::GlobalIDType[::Packages::PackageFile].coerce_isolated_input(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -107,6 +107,7 @@ module Types
|
|||
mount_mutation Mutations::Namespace::PackageSettings::Update
|
||||
mount_mutation Mutations::UserCallouts::Create
|
||||
mount_mutation Mutations::Packages::Destroy
|
||||
mount_mutation Mutations::Packages::DestroyFile
|
||||
mount_mutation Mutations::Echo
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module Types
|
|||
|
||||
alias_method :query, :object
|
||||
|
||||
field :limit, GraphQL::INT_TYPE,
|
||||
field :limit, GraphQL::Types::Int,
|
||||
null: true,
|
||||
method: :max_complexity,
|
||||
see: {
|
||||
|
|
@ -18,7 +18,7 @@ module Types
|
|||
},
|
||||
description: 'GraphQL query complexity limit.'
|
||||
|
||||
field :score, GraphQL::INT_TYPE,
|
||||
field :score, GraphQL::Types::Int,
|
||||
null: true,
|
||||
description: 'GraphQL query complexity score.'
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ module Types
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
argument :name, GraphQL::STRING_TYPE,
|
||||
argument :name, GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Name of the asset link.'
|
||||
|
||||
argument :url, GraphQL::STRING_TYPE,
|
||||
argument :url, GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'URL of the asset link.'
|
||||
|
||||
argument :direct_asset_path, GraphQL::STRING_TYPE,
|
||||
argument :direct_asset_path, GraphQL::Types::String,
|
||||
required: false, as: :filepath,
|
||||
description: 'Relative path for a direct asset link.'
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,20 @@ module Types
|
|||
|
||||
authorize :read_release
|
||||
|
||||
field :id, GraphQL::ID_TYPE, null: false,
|
||||
field :id, GraphQL::Types::ID, null: false,
|
||||
description: 'ID of the link.'
|
||||
field :name, GraphQL::STRING_TYPE, null: true,
|
||||
field :name, GraphQL::Types::String, null: true,
|
||||
description: 'Name of the link.'
|
||||
field :url, GraphQL::STRING_TYPE, null: true,
|
||||
field :url, GraphQL::Types::String, null: true,
|
||||
description: 'URL of the link.'
|
||||
field :link_type, Types::ReleaseAssetLinkTypeEnum, null: true,
|
||||
description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.'
|
||||
field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?,
|
||||
field :external, GraphQL::Types::Boolean, null: true, method: :external?,
|
||||
description: 'Indicates the link points to an external resource.'
|
||||
|
||||
field :direct_asset_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :direct_asset_url, GraphQL::Types::String, null: true,
|
||||
description: 'Direct asset URL of the link.'
|
||||
field :direct_asset_path, GraphQL::STRING_TYPE, null: true, method: :filepath,
|
||||
field :direct_asset_path, GraphQL::Types::String, null: true, method: :filepath,
|
||||
description: 'Relative path for the direct asset link.'
|
||||
|
||||
def direct_asset_url
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module Types
|
|||
|
||||
present_using ReleasePresenter
|
||||
|
||||
field :count, GraphQL::INT_TYPE, null: true, method: :assets_count,
|
||||
field :count, GraphQL::Types::Int, null: true, method: :assets_count,
|
||||
description: 'Number of assets of the release.'
|
||||
field :links, Types::ReleaseAssetLinkType.connection_type, null: true, method: :sorted_links,
|
||||
description: 'Asset links of the release.'
|
||||
|
|
|
|||
|
|
@ -10,20 +10,20 @@ module Types
|
|||
|
||||
present_using ReleasePresenter
|
||||
|
||||
field :self_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :self_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the release.'
|
||||
field :edit_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :edit_url, GraphQL::Types::String, null: true,
|
||||
description: "HTTP URL of the release's edit page.",
|
||||
authorize: :update_release
|
||||
field :opened_merge_requests_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :opened_merge_requests_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.'
|
||||
field :merged_merge_requests_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :merged_merge_requests_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.'
|
||||
field :closed_merge_requests_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :closed_merge_requests_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.'
|
||||
field :opened_issues_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :opened_issues_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the issues page, filtered by this release and `state=open`.'
|
||||
field :closed_issues_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :closed_issues_url, GraphQL::Types::String, null: true,
|
||||
description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ module Types
|
|||
|
||||
authorize :download_code
|
||||
|
||||
field :format, GraphQL::STRING_TYPE, null: true,
|
||||
field :format, GraphQL::Types::String, null: true,
|
||||
description: 'Format of the source.'
|
||||
field :url, GraphQL::STRING_TYPE, null: true,
|
||||
field :url, GraphQL::Types::String, null: true,
|
||||
description: 'Download URL of the source.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,22 +13,22 @@ module Types
|
|||
|
||||
present_using ReleasePresenter
|
||||
|
||||
field :tag_name, GraphQL::STRING_TYPE, null: true, method: :tag,
|
||||
field :tag_name, GraphQL::Types::String, null: true, method: :tag,
|
||||
description: 'Name of the tag associated with the release.',
|
||||
authorize: :download_code
|
||||
field :tag_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :tag_path, GraphQL::Types::String, null: true,
|
||||
description: 'Relative web path to the tag associated with the release.',
|
||||
authorize: :download_code
|
||||
field :description, GraphQL::STRING_TYPE, null: true,
|
||||
field :description, GraphQL::Types::String, null: true,
|
||||
description: 'Description (also known as "release notes") of the release.'
|
||||
markdown_field :description_html, null: true
|
||||
field :name, GraphQL::STRING_TYPE, null: true,
|
||||
field :name, GraphQL::Types::String, null: true,
|
||||
description: 'Name of the release.'
|
||||
field :created_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of when the release was created.'
|
||||
field :released_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of when the release was released.'
|
||||
field :upcoming_release, GraphQL::BOOLEAN_TYPE, null: true, method: :upcoming_release?,
|
||||
field :upcoming_release, GraphQL::Types::Boolean, null: true, method: :upcoming_release?,
|
||||
description: 'Indicates the release is an upcoming release.'
|
||||
field :assets, Types::ReleaseAssetsType, null: true, method: :itself,
|
||||
description: 'Assets of the release.'
|
||||
|
|
|
|||
|
|
@ -8,67 +8,67 @@ module Types
|
|||
|
||||
graphql_name 'RepositoryBlob'
|
||||
|
||||
field :id, GraphQL::ID_TYPE, null: false,
|
||||
field :id, GraphQL::Types::ID, null: false,
|
||||
description: 'ID of the blob.'
|
||||
|
||||
field :oid, GraphQL::STRING_TYPE, null: false, method: :id,
|
||||
field :oid, GraphQL::Types::String, null: false, method: :id,
|
||||
description: 'OID of the blob.'
|
||||
|
||||
field :path, GraphQL::STRING_TYPE, null: false,
|
||||
field :path, GraphQL::Types::String, null: false,
|
||||
description: 'Path of the blob.'
|
||||
|
||||
field :name, GraphQL::STRING_TYPE,
|
||||
field :name, GraphQL::Types::String,
|
||||
description: 'Blob name.',
|
||||
null: true
|
||||
|
||||
field :mode, type: GraphQL::STRING_TYPE,
|
||||
field :mode, type: GraphQL::Types::String,
|
||||
description: 'Blob mode.',
|
||||
null: true
|
||||
|
||||
field :lfs_oid, GraphQL::STRING_TYPE, null: true,
|
||||
field :lfs_oid, GraphQL::Types::String, null: true,
|
||||
calls_gitaly: true,
|
||||
description: 'LFS OID of the blob.'
|
||||
|
||||
field :web_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :web_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path of the blob.'
|
||||
|
||||
field :ide_edit_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :ide_edit_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to edit this blob in the Web IDE.'
|
||||
|
||||
field :fork_and_edit_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :fork_and_edit_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to edit this blob using a forked project.'
|
||||
|
||||
field :ide_fork_and_edit_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :ide_fork_and_edit_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to edit this blob in the Web IDE using a forked project.'
|
||||
|
||||
field :size, GraphQL::INT_TYPE, null: true,
|
||||
field :size, GraphQL::Types::Int, null: true,
|
||||
description: 'Size (in bytes) of the blob.'
|
||||
|
||||
field :raw_size, GraphQL::INT_TYPE, null: true,
|
||||
field :raw_size, GraphQL::Types::Int, null: true,
|
||||
description: 'Size (in bytes) of the blob, or the blob target if stored externally.'
|
||||
|
||||
field :raw_blob, GraphQL::STRING_TYPE, null: true, method: :data,
|
||||
field :raw_blob, GraphQL::Types::String, null: true, method: :data,
|
||||
description: 'The raw content of the blob.'
|
||||
|
||||
field :raw_text_blob, GraphQL::STRING_TYPE, null: true, method: :text_only_data,
|
||||
field :raw_text_blob, GraphQL::Types::String, null: true, method: :text_only_data,
|
||||
description: 'The raw content of the blob, if the blob is text data.'
|
||||
|
||||
field :stored_externally, GraphQL::BOOLEAN_TYPE, null: true, method: :stored_externally?,
|
||||
field :stored_externally, GraphQL::Types::Boolean, null: true, method: :stored_externally?,
|
||||
description: "Whether the blob's content is stored externally (for instance, in LFS)."
|
||||
|
||||
field :edit_blob_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :edit_blob_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to edit the blob in the old-style editor.'
|
||||
|
||||
field :raw_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :raw_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to download the raw blob.'
|
||||
|
||||
field :external_storage_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :external_storage_url, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to download the raw blob via external storage, if enabled.'
|
||||
|
||||
field :replace_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :replace_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path to replace the blob content.'
|
||||
|
||||
field :file_type, GraphQL::STRING_TYPE, null: true,
|
||||
field :file_type, GraphQL::Types::String, null: true,
|
||||
description: 'The expected format of the blob based on the extension.'
|
||||
|
||||
field :simple_viewer, type: Types::BlobViewerType,
|
||||
|
|
@ -79,12 +79,12 @@ module Types
|
|||
description: 'Blob content rich viewer.',
|
||||
null: true
|
||||
|
||||
field :plain_data, GraphQL::STRING_TYPE,
|
||||
field :plain_data, GraphQL::Types::String,
|
||||
description: 'Blob plain highlighted data.',
|
||||
null: true,
|
||||
calls_gitaly: true
|
||||
|
||||
field :can_modify_blob, GraphQL::BOOLEAN_TYPE, null: true, method: :can_modify_blob?,
|
||||
field :can_modify_blob, GraphQL::Types::Boolean, null: true, method: :can_modify_blob?,
|
||||
calls_gitaly: true,
|
||||
description: 'Whether the current user can modify the blob.'
|
||||
|
||||
|
|
|
|||
|
|
@ -6,20 +6,20 @@ module Types
|
|||
|
||||
authorize :download_code
|
||||
|
||||
field :root_ref, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
|
||||
field :root_ref, GraphQL::Types::String, null: true, calls_gitaly: true,
|
||||
description: 'Default branch of the repository.'
|
||||
field :empty, GraphQL::BOOLEAN_TYPE, null: false, method: :empty?, calls_gitaly: true,
|
||||
field :empty, GraphQL::Types::Boolean, null: false, method: :empty?, calls_gitaly: true,
|
||||
description: 'Indicates repository has no visible content.'
|
||||
field :exists, GraphQL::BOOLEAN_TYPE, null: false, method: :exists?, calls_gitaly: true,
|
||||
field :exists, GraphQL::Types::Boolean, null: false, method: :exists?, calls_gitaly: true,
|
||||
description: 'Indicates a corresponding Git repository exists on disk.'
|
||||
field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver, calls_gitaly: true,
|
||||
description: 'Tree of the repository.'
|
||||
field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
|
||||
description: 'Blobs contained within the repository'
|
||||
field :branch_names, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
|
||||
field :branch_names, [GraphQL::Types::String], null: true, calls_gitaly: true,
|
||||
complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
|
||||
resolver: Resolvers::RepositoryBranchNamesResolver
|
||||
field :disk_path, GraphQL::STRING_TYPE,
|
||||
field :disk_path, GraphQL::Types::String,
|
||||
description: 'Shows a disk path of the repository.',
|
||||
null: true,
|
||||
authorize: :read_storage_disk_path
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ module Types
|
|||
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.resolved_by_id).find
|
||||
end
|
||||
|
||||
field :resolved, GraphQL::BOOLEAN_TYPE, null: false,
|
||||
field :resolved, GraphQL::Types::Boolean, null: false,
|
||||
description: 'Indicates if the object is resolved.',
|
||||
method: :resolved?
|
||||
field :resolvable, GraphQL::BOOLEAN_TYPE, null: false,
|
||||
field :resolvable, GraphQL::Types::Boolean, null: false,
|
||||
description: 'Indicates if the object can be resolved.',
|
||||
method: :resolvable?
|
||||
field :resolved_at, Types::TimeType, null: true,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module Types
|
|||
description: 'ID of the snippet.',
|
||||
null: false
|
||||
|
||||
field :title, GraphQL::STRING_TYPE,
|
||||
field :title, GraphQL::Types::String,
|
||||
description: 'Title of the snippet.',
|
||||
null: false
|
||||
|
||||
|
|
@ -33,11 +33,11 @@ module Types
|
|||
description: 'The owner of the snippet.',
|
||||
null: true
|
||||
|
||||
field :file_name, GraphQL::STRING_TYPE,
|
||||
field :file_name, GraphQL::Types::String,
|
||||
description: 'File Name of the snippet.',
|
||||
null: true
|
||||
|
||||
field :description, GraphQL::STRING_TYPE,
|
||||
field :description, GraphQL::Types::String,
|
||||
description: 'Description of the snippet.',
|
||||
null: true
|
||||
|
||||
|
|
@ -53,11 +53,11 @@ module Types
|
|||
description: 'Timestamp this snippet was updated.',
|
||||
null: false
|
||||
|
||||
field :web_url, type: GraphQL::STRING_TYPE,
|
||||
field :web_url, type: GraphQL::Types::String,
|
||||
description: 'Web URL of the snippet.',
|
||||
null: false
|
||||
|
||||
field :raw_url, type: GraphQL::STRING_TYPE,
|
||||
field :raw_url, type: GraphQL::Types::String,
|
||||
description: 'Raw URL of the snippet.',
|
||||
null: false
|
||||
|
||||
|
|
@ -67,12 +67,12 @@ module Types
|
|||
null: true,
|
||||
resolver: Resolvers::Snippets::BlobsResolver
|
||||
|
||||
field :ssh_url_to_repo, type: GraphQL::STRING_TYPE,
|
||||
field :ssh_url_to_repo, type: GraphQL::Types::String,
|
||||
description: 'SSH URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
|
||||
field :http_url_to_repo, type: GraphQL::STRING_TYPE,
|
||||
field :http_url_to_repo, type: GraphQL::Types::String,
|
||||
description: 'HTTP URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@ module Types
|
|||
description: 'Type of input action.',
|
||||
required: true
|
||||
|
||||
argument :previous_path, GraphQL::STRING_TYPE,
|
||||
argument :previous_path, GraphQL::Types::String,
|
||||
description: 'Previous path of the snippet file.',
|
||||
required: false
|
||||
|
||||
argument :file_path, GraphQL::STRING_TYPE,
|
||||
argument :file_path, GraphQL::Types::String,
|
||||
description: 'Path of the snippet file.',
|
||||
required: true
|
||||
|
||||
argument :content, GraphQL::STRING_TYPE,
|
||||
argument :content, GraphQL::Types::String,
|
||||
description: 'Snippet file content.',
|
||||
required: false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,36 +8,36 @@ module Types
|
|||
description 'Represents the snippet blob'
|
||||
present_using SnippetBlobPresenter
|
||||
|
||||
field :rich_data, GraphQL::STRING_TYPE,
|
||||
field :rich_data, GraphQL::Types::String,
|
||||
description: 'Blob highlighted data.',
|
||||
null: true
|
||||
|
||||
field :plain_data, GraphQL::STRING_TYPE,
|
||||
field :plain_data, GraphQL::Types::String,
|
||||
description: 'Blob plain highlighted data.',
|
||||
null: true
|
||||
|
||||
field :raw_plain_data, GraphQL::STRING_TYPE,
|
||||
field :raw_plain_data, GraphQL::Types::String,
|
||||
description: 'The raw content of the blob, if the blob is text data.',
|
||||
null: true
|
||||
|
||||
field :raw_path, GraphQL::STRING_TYPE,
|
||||
field :raw_path, GraphQL::Types::String,
|
||||
description: 'Blob raw content endpoint path.',
|
||||
null: false
|
||||
|
||||
field :size, GraphQL::INT_TYPE,
|
||||
field :size, GraphQL::Types::Int,
|
||||
description: 'Blob size.',
|
||||
null: false
|
||||
|
||||
field :binary, GraphQL::BOOLEAN_TYPE,
|
||||
field :binary, GraphQL::Types::Boolean,
|
||||
description: 'Shows whether the blob is binary.',
|
||||
method: :binary?,
|
||||
null: false
|
||||
|
||||
field :name, GraphQL::STRING_TYPE,
|
||||
field :name, GraphQL::Types::String,
|
||||
description: 'Blob name.',
|
||||
null: true
|
||||
|
||||
field :path, GraphQL::STRING_TYPE,
|
||||
field :path, GraphQL::Types::String,
|
||||
description: 'Blob path.',
|
||||
null: true
|
||||
|
||||
|
|
@ -49,15 +49,15 @@ module Types
|
|||
description: 'Blob content rich viewer.',
|
||||
null: true
|
||||
|
||||
field :mode, type: GraphQL::STRING_TYPE,
|
||||
field :mode, type: GraphQL::Types::String,
|
||||
description: 'Blob mode.',
|
||||
null: true
|
||||
|
||||
field :external_storage, type: GraphQL::STRING_TYPE,
|
||||
field :external_storage, type: GraphQL::Types::String,
|
||||
description: 'Blob external storage.',
|
||||
null: true
|
||||
|
||||
field :rendered_as_text, type: GraphQL::BOOLEAN_TYPE,
|
||||
field :rendered_as_text, type: GraphQL::Types::Boolean,
|
||||
description: 'Shows whether the blob is rendered as text.',
|
||||
method: :rendered_as_text?,
|
||||
null: false
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ module Types
|
|||
graphql_name 'TaskCompletionStatus'
|
||||
description 'Completion status of tasks'
|
||||
|
||||
field :count, GraphQL::INT_TYPE, null: false,
|
||||
field :count, GraphQL::Types::Int, null: false,
|
||||
description: 'Number of total tasks.'
|
||||
field :completed_count, GraphQL::INT_TYPE, null: false,
|
||||
field :completed_count, GraphQL::Types::Int, null: false,
|
||||
description: 'Number of completed tasks.'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ module Types
|
|||
|
||||
connection_type_class(Types::CountableConnectionType)
|
||||
|
||||
field :id, GraphQL::ID_TYPE,
|
||||
field :id, GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the Terraform state.'
|
||||
|
||||
field :name, GraphQL::STRING_TYPE,
|
||||
field :name, GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Name of the Terraform state.'
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module Types
|
|||
|
||||
authorize :read_terraform_state
|
||||
|
||||
field :id, GraphQL::ID_TYPE,
|
||||
field :id, GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the Terraform state version.'
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ module Types
|
|||
null: true,
|
||||
description: 'The user that created this version.'
|
||||
|
||||
field :download_path, GraphQL::STRING_TYPE,
|
||||
field :download_path, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: "URL for downloading the version's JSON file."
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ module Types
|
|||
null: true,
|
||||
description: 'The job that created this version.'
|
||||
|
||||
field :serial, GraphQL::INT_TYPE,
|
||||
field :serial, GraphQL::Types::Int,
|
||||
null: true,
|
||||
description: 'Serial number of the version.',
|
||||
method: :version
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module Types
|
|||
description: 'Timestamp of when the time tracked was spent at.'
|
||||
|
||||
field :time_spent,
|
||||
GraphQL::INT_TYPE,
|
||||
GraphQL::Types::Int,
|
||||
null: false,
|
||||
description: 'The time spent displayed in seconds.'
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module Types
|
|||
|
||||
authorize :read_todo
|
||||
|
||||
field :id, GraphQL::ID_TYPE,
|
||||
field :id, GraphQL::Types::ID,
|
||||
description: 'ID of the to-do item.',
|
||||
null: false
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ module Types
|
|||
description: 'Target type of the to-do item.',
|
||||
null: false
|
||||
|
||||
field :body, GraphQL::STRING_TYPE,
|
||||
field :body, GraphQL::Types::String,
|
||||
description: 'Body of the to-do item.',
|
||||
null: false,
|
||||
calls_gitaly: true # TODO This is only true when `target_type` is `Commit`. See https://gitlab.com/gitlab-org/gitlab/issues/34757#note_234752665
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ module Types
|
|||
|
||||
graphql_name 'Blob'
|
||||
|
||||
field :web_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :web_url, GraphQL::Types::String, null: true,
|
||||
description: 'Web URL of the blob.'
|
||||
field :web_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :web_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path of the blob.'
|
||||
field :lfs_oid, GraphQL::STRING_TYPE, null: true,
|
||||
field :lfs_oid, GraphQL::Types::String, null: true,
|
||||
calls_gitaly: true,
|
||||
description: 'LFS ID of the blob.'
|
||||
field :mode, GraphQL::STRING_TYPE, null: true,
|
||||
field :mode, GraphQL::Types::String, null: true,
|
||||
description: 'Blob mode in numeric format.'
|
||||
|
||||
def lfs_oid
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ module Types
|
|||
module EntryType
|
||||
include Types::BaseInterface
|
||||
|
||||
field :id, GraphQL::ID_TYPE, null: false,
|
||||
field :id, GraphQL::Types::ID, null: false,
|
||||
description: 'ID of the entry.'
|
||||
field :sha, GraphQL::STRING_TYPE, null: false,
|
||||
field :sha, GraphQL::Types::String, null: false,
|
||||
description: 'Last commit SHA for the entry.', method: :id
|
||||
field :name, GraphQL::STRING_TYPE, null: false,
|
||||
field :name, GraphQL::Types::String, null: false,
|
||||
description: 'Name of the entry.'
|
||||
field :type, Tree::TypeEnum, null: false,
|
||||
description: 'Type of tree entry.'
|
||||
field :path, GraphQL::STRING_TYPE, null: false,
|
||||
field :path, GraphQL::Types::String, null: false,
|
||||
description: 'Path of the entry.'
|
||||
field :flat_path, GraphQL::STRING_TYPE, null: false,
|
||||
field :flat_path, GraphQL::Types::String, null: false,
|
||||
description: 'Flat path of the entry.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ module Types
|
|||
|
||||
graphql_name 'Submodule'
|
||||
|
||||
field :web_url, type: GraphQL::STRING_TYPE, null: true,
|
||||
field :web_url, type: GraphQL::Types::String, null: true,
|
||||
description: 'Web URL for the sub-module.'
|
||||
field :tree_url, type: GraphQL::STRING_TYPE, null: true,
|
||||
field :tree_url, type: GraphQL::Types::String, null: true,
|
||||
description: 'Tree URL for the sub-module.'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ module Types
|
|||
graphql_name 'TreeEntry'
|
||||
description 'Represents a directory'
|
||||
|
||||
field :web_url, GraphQL::STRING_TYPE, null: true,
|
||||
field :web_url, GraphQL::Types::String, null: true,
|
||||
description: 'Web URL for the tree entry (directory).'
|
||||
field :web_path, GraphQL::STRING_TYPE, null: true,
|
||||
field :web_path, GraphQL::Types::String, null: true,
|
||||
description: 'Web path for the tree entry (directory).'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
|
|
|
|||
|
|
@ -14,20 +14,20 @@ module Types
|
|||
method: :itself
|
||||
|
||||
field :id,
|
||||
type: GraphQL::ID_TYPE,
|
||||
type: GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the user.'
|
||||
field :bot,
|
||||
type: GraphQL::BOOLEAN_TYPE,
|
||||
type: GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
description: 'Indicates if the user is a bot.',
|
||||
method: :bot?
|
||||
field :username,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Username of the user. Unique within this instance of GitLab.'
|
||||
field :name,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Human-readable name of the user.'
|
||||
field :state,
|
||||
|
|
@ -35,24 +35,24 @@ module Types
|
|||
null: false,
|
||||
description: 'State of the user.'
|
||||
field :email,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'User email.', method: :public_email,
|
||||
deprecated: { reason: :renamed, replacement: 'User.publicEmail', milestone: '13.7' }
|
||||
field :public_email,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: true,
|
||||
description: "User's public email."
|
||||
field :avatar_url,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: true,
|
||||
description: "URL of the user's avatar."
|
||||
field :web_url,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Web URL of the user.'
|
||||
field :web_path,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Web path of the user.'
|
||||
field :todos,
|
||||
|
|
@ -70,7 +70,7 @@ module Types
|
|||
null: true,
|
||||
description: 'User status.'
|
||||
field :location,
|
||||
type: ::GraphQL::STRING_TYPE,
|
||||
type: ::GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'The location of the user.'
|
||||
field :project_memberships,
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ module Types
|
|||
authorize :read_merge_request
|
||||
|
||||
field :can_merge,
|
||||
type: ::GraphQL::BOOLEAN_TYPE,
|
||||
type: ::GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
calls_gitaly: true,
|
||||
method: :can_merge?,
|
||||
description: 'Whether this user can merge this merge request.'
|
||||
|
||||
field :can_update,
|
||||
type: ::GraphQL::BOOLEAN_TYPE,
|
||||
type: ::GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
method: :can_update?,
|
||||
description: 'Whether this user can update this merge request.'
|
||||
|
|
@ -31,13 +31,13 @@ module Types
|
|||
description: 'The state of the review by this user.'
|
||||
|
||||
field :reviewed,
|
||||
type: ::GraphQL::BOOLEAN_TYPE,
|
||||
type: ::GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
method: :reviewed?,
|
||||
description: 'Whether this user has provided a review for this merge request.'
|
||||
|
||||
field :approved,
|
||||
type: ::GraphQL::BOOLEAN_TYPE,
|
||||
type: ::GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
method: :approved?,
|
||||
description: 'Whether this user has approved this merge request.'
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ module Types
|
|||
|
||||
markdown_field :message_html, null: true,
|
||||
description: 'HTML of the user status message'
|
||||
field :message, GraphQL::STRING_TYPE, null: true,
|
||||
field :message, GraphQL::Types::String, null: true,
|
||||
description: 'User status message.'
|
||||
field :emoji, GraphQL::STRING_TYPE, null: true,
|
||||
field :emoji, GraphQL::Types::String, null: true,
|
||||
description: 'String representation of emoji.'
|
||||
field :availability, Types::AvailabilityEnum, null: false,
|
||||
description: 'User availability status.'
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
def cleanup
|
||||
email = nil
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
email = yield
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
# prevent this from happening, we do a sanity check that the
|
||||
# primary key constraint is present before inserting a new entry.
|
||||
def self.check_schema!
|
||||
return if ActiveRecord::Base.connection.primary_key(self.table_name).present?
|
||||
return if connection.primary_key(self.table_name).present?
|
||||
|
||||
raise "The `#{self.table_name}` table is missing a primary key constraint in the database schema"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class InternalId < ApplicationRecord
|
|||
self.internal_id_transactions_total.increment(
|
||||
operation: operation,
|
||||
usage: usage.to_s,
|
||||
in_transaction: ActiveRecord::Base.connection.transaction_open?.to_s
|
||||
in_transaction: ActiveRecord::Base.connection.transaction_open?.to_s # rubocop: disable Database/MultipleDatabases
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -317,7 +317,7 @@ class InternalId < ApplicationRecord
|
|||
stmt.set(arel_table[:last_value] => new_value)
|
||||
stmt.wheres = InternalId.filter_by(scope, usage).arel.constraints
|
||||
|
||||
ActiveRecord::Base.connection.insert(stmt, 'Update InternalId', 'last_value')
|
||||
ActiveRecord::Base.connection.insert(stmt, 'Update InternalId', 'last_value') # rubocop: disable Database/MultipleDatabases
|
||||
end
|
||||
|
||||
def create_record!(subject, scope, usage, init)
|
||||
|
|
|
|||
|
|
@ -317,6 +317,21 @@ class Issue < ApplicationRecord
|
|||
)
|
||||
end
|
||||
|
||||
def self.to_branch_name(*args)
|
||||
branch_name = args.map(&:to_s).each_with_index.map do |arg, i|
|
||||
arg.parameterize(preserve_case: i == 0).presence
|
||||
end.compact.join('-')
|
||||
|
||||
if branch_name.length > 100
|
||||
truncated_string = branch_name[0, 100]
|
||||
# Delete everything dangling after the last hyphen so as not to risk
|
||||
# existence of unintended words in the branch name due to mid-word split.
|
||||
branch_name = truncated_string.sub(/-[^-]*\Z/, '')
|
||||
end
|
||||
|
||||
branch_name
|
||||
end
|
||||
|
||||
# Temporary disable moving null elements because of performance problems
|
||||
# For more information check https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4321
|
||||
def check_repositioning_allowed!
|
||||
|
|
@ -384,16 +399,7 @@ class Issue < ApplicationRecord
|
|||
if self.confidential?
|
||||
"#{iid}-confidential-issue"
|
||||
else
|
||||
branch_name = "#{iid}-#{title.parameterize}"
|
||||
|
||||
if branch_name.length > 100
|
||||
truncated_string = branch_name[0, 100]
|
||||
# Delete everything dangling after the last hyphen so as not to risk
|
||||
# existence of unintended words in the branch name due to mid-word split.
|
||||
branch_name = truncated_string[0, truncated_string.rindex("-")]
|
||||
end
|
||||
|
||||
branch_name
|
||||
self.class.to_branch_name(iid, title)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class Packages::Event < ApplicationRecord
|
|||
belongs_to :package, optional: true
|
||||
|
||||
UNIQUE_EVENTS_ALLOWED = %i[push_package delete_package pull_package pull_symbol_package push_symbol_package].freeze
|
||||
EVENT_SCOPES = ::Packages::Package.package_types.merge(container: 1000, tag: 1001).freeze
|
||||
EVENT_SCOPES = ::Packages::Package.package_types.merge(container: 1000, tag: 1001, dependency_proxy: 1002).freeze
|
||||
|
||||
EVENT_PREFIX = "i_package"
|
||||
|
||||
|
|
@ -23,7 +23,11 @@ class Packages::Event < ApplicationRecord
|
|||
list_tags: 9,
|
||||
cli_metadata: 10,
|
||||
pull_symbol_package: 11,
|
||||
push_symbol_package: 12
|
||||
push_symbol_package: 12,
|
||||
pull_manifest: 13,
|
||||
pull_manifest_from_cache: 14,
|
||||
pull_blob: 15,
|
||||
pull_blob_from_cache: 16
|
||||
}
|
||||
|
||||
enum originator_type: { user: 0, deploy_token: 1, guest: 2 }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module AutoMerge
|
|||
include MergeRequests::AssignsMergeParams
|
||||
|
||||
def execute(merge_request)
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
register_auto_merge_parameters!(merge_request)
|
||||
yield if block_given?
|
||||
end
|
||||
|
|
@ -29,7 +29,7 @@ module AutoMerge
|
|||
end
|
||||
|
||||
def cancel(merge_request)
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
clear_auto_merge_parameters!(merge_request)
|
||||
yield if block_given?
|
||||
end
|
||||
|
|
@ -41,7 +41,7 @@ module AutoMerge
|
|||
end
|
||||
|
||||
def abort(merge_request, reason)
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
clear_auto_merge_parameters!(merge_request)
|
||||
yield if block_given?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ module Ci
|
|||
def delete_batch!(klass)
|
||||
deleted = 0
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
klass.transaction do
|
||||
ids = klass.deletable.lock('FOR UPDATE SKIP LOCKED').limit(BATCH_SIZE).pluck(:id)
|
||||
break if ids.empty?
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module Ci
|
|||
SQL
|
||||
|
||||
loop do
|
||||
break if ActiveRecord::Base.connection.exec_query(query).empty?
|
||||
break if Ci::Pipeline.connection.exec_query(query).empty?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ module DependencyProxy
|
|||
end
|
||||
|
||||
def execute
|
||||
from_cache = true
|
||||
file_name = @blob_sha.sub('sha256:', '') + '.gz'
|
||||
blob = @group.dependency_proxy_blobs.find_or_build(file_name)
|
||||
|
||||
unless blob.persisted?
|
||||
from_cache = false
|
||||
result = DependencyProxy::DownloadBlobService
|
||||
.new(@image, @blob_sha, @token).execute
|
||||
|
||||
|
|
@ -28,7 +30,7 @@ module DependencyProxy
|
|||
blob.save!
|
||||
end
|
||||
|
||||
success(blob: blob)
|
||||
success(blob: blob, from_cache: from_cache)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ module DependencyProxy
|
|||
|
||||
head_result = DependencyProxy::HeadManifestService.new(@image, @tag, @token).execute
|
||||
|
||||
return success(manifest: @manifest) if cached_manifest_matches?(head_result)
|
||||
return success(manifest: @manifest, from_cache: true) if cached_manifest_matches?(head_result)
|
||||
|
||||
pull_new_manifest
|
||||
respond
|
||||
respond(from_cache: false)
|
||||
rescue Timeout::Error, *Gitlab::HTTP::HTTP_ERRORS
|
||||
respond
|
||||
end
|
||||
|
|
@ -44,9 +44,9 @@ module DependencyProxy
|
|||
@manifest && @manifest.digest == head_result[:digest] && @manifest.content_type == head_result[:content_type]
|
||||
end
|
||||
|
||||
def respond
|
||||
def respond(from_cache: true)
|
||||
if @manifest.persisted?
|
||||
success(manifest: @manifest)
|
||||
success(manifest: @manifest, from_cache: from_cache)
|
||||
else
|
||||
error('Failed to download the manifest from the external registry', 503)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ module Deployments
|
|||
end
|
||||
|
||||
def update_environment(deployment)
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
# Renew attributes at update
|
||||
renew_external_url
|
||||
renew_auto_stop_in
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ module DesignManagement
|
|||
with_temporary_branch do
|
||||
copy_commits!
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
design_ids = copy_designs!
|
||||
version_ids = copy_versions!
|
||||
copy_actions!(design_ids, version_ids)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module FeatureFlags
|
|||
return error('Access Denied', 403) unless can_create?
|
||||
return error('Version is invalid', :bad_request) unless valid_version?
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
feature_flag = project.operations_feature_flags.new(params)
|
||||
|
||||
if feature_flag.save
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module FeatureFlags
|
|||
def destroy_feature_flag(feature_flag)
|
||||
return error('Access Denied', 403) unless can_destroy?(feature_flag)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
if feature_flag.destroy
|
||||
save_audit_event(audit_event(feature_flag))
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module FeatureFlags
|
|||
return error('Access Denied', 403) unless can_update?(feature_flag)
|
||||
return error('Not Found', 404) unless valid_user_list_ids?(feature_flag, user_list_ids(params))
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
feature_flag.assign_attributes(params)
|
||||
|
||||
feature_flag.strategies.each do |strategy|
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module Issuable
|
|||
# Using transaction because of a high resources footprint
|
||||
# on rewriting notes (unfolding references)
|
||||
#
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
@new_entity = create_new_entity
|
||||
|
||||
update_new_entity
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module Issuable
|
|||
|
||||
# We disable touch so that created system notes do not update
|
||||
# the noteable's updated_at field
|
||||
ActiveRecord::Base.no_touching do
|
||||
ApplicationRecord.no_touching do
|
||||
if is_update
|
||||
if issuable.previous_changes.include?('title')
|
||||
create_title_change_note(issuable.previous_changes['title'].first)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ module Issuable
|
|||
SQL
|
||||
|
||||
loop do
|
||||
result = ActiveRecord::Base.connection.execute(delete_query)
|
||||
result = LabelLink.connection.execute(delete_query)
|
||||
|
||||
break if result.cmd_tuples == 0
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ module Packages
|
|||
dependencies_to_insert = names_and_version_patterns.reject { |k, _| k.in?(existing_names) }
|
||||
end
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
inserted_ids = bulk_insert_package_dependencies(dependencies_to_insert)
|
||||
bulk_insert_package_dependency_links(type, (existing_ids + inserted_ids))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ module Packages
|
|||
files[:mod] = prepare_file(version, :mod, version.gomod)
|
||||
files[:zip] = prepare_file(version, :zip, version.archive.string)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
# create new package and files
|
||||
package = create_package
|
||||
files.each { |type, (file, digests)| create_file(package, type, file, digests) }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module Packages
|
|||
return error('Package already exists.', 403) if current_package_exists?
|
||||
return error('File is too large.', 400) if file_size_exceeded?
|
||||
|
||||
ActiveRecord::Base.transaction { create_npm_package! }
|
||||
ApplicationRecord.transaction { create_npm_package! }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module Packages
|
|||
return error('Package version already exists.', 403) if current_package_version_exists?
|
||||
return error('File is too large.', 400) if file_size_exceeded?
|
||||
|
||||
ActiveRecord::Base.transaction { create_terraform_module_package! }
|
||||
ApplicationRecord.transaction { create_terraform_module_package! }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ module Projects
|
|||
def cleanup_diffs(response)
|
||||
old_commit_shas = extract_old_commit_shas(response.entries)
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
cleanup_merge_request_diffs(old_commit_shas)
|
||||
cleanup_note_diff_files(old_commit_shas)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module Projects
|
|||
ON CONFLICT (project_id, date) DO UPDATE SET fetch_count = #{table_name}.fetch_count + 1
|
||||
SQL
|
||||
|
||||
ActiveRecord::Base.connection.execute(increment_fetch_count_sql)
|
||||
ProjectDailyStatistic.connection.execute(increment_fetch_count_sql)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module Releases
|
|||
# when it does assign_attributes instead of actual saving
|
||||
# this leads to the validation error being raised
|
||||
# see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43385
|
||||
ActiveRecord::Base.transaction do
|
||||
ApplicationRecord.transaction do
|
||||
if release.update(params)
|
||||
execute_hooks(release, 'update')
|
||||
success(tag: existing_tag, release: release, milestones_updated: milestones_updated?(previous_milestones))
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module Todos
|
|||
SQL
|
||||
|
||||
loop do
|
||||
result = ActiveRecord::Base.connection.execute(delete_query)
|
||||
result = Todo.connection.execute(delete_query)
|
||||
|
||||
break if result.cmd_tuples == 0
|
||||
|
||||
|
|
|
|||
|
|
@ -8,20 +8,20 @@
|
|||
= f.label :email_author_in_body, class: 'form-check-label' do
|
||||
= _('Include author name in notification email body')
|
||||
.form-text.text-muted
|
||||
= _('Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead.')
|
||||
= _("Include the name of the author of the issue, merge request or comment in the email body. By default, GitLab overrides the email sender's name. Some email servers don't support that option.")
|
||||
.form-group
|
||||
.form-check
|
||||
= f.check_box :html_emails_enabled, class: 'form-check-input'
|
||||
= f.label :html_emails_enabled, class: 'form-check-label' do
|
||||
= _('Enable HTML emails')
|
||||
= _('Enable multipart emails')
|
||||
.form-text.text-muted
|
||||
= _('By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format.')
|
||||
= _('Send email in multipart format (HTML and plain text). Uncheck to send email messages in plain text only.')
|
||||
.form-group
|
||||
= f.label :commit_email_hostname, _('Custom hostname (for private commit emails)'), class: 'label-bold'
|
||||
= f.text_field :commit_email_hostname, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
- commit_email_hostname_docs_link = link_to _('Learn more'), help_page_path('user/admin_area/settings/email.md', anchor: 'custom-hostname-for-private-commit-emails'), target: '_blank'
|
||||
= _("This setting will update the hostname that is used to generate private commit emails. %{learn_more}").html_safe % { learn_more: commit_email_hostname_docs_link }
|
||||
= _("Hostname used in private commit emails. %{learn_more}").html_safe % { learn_more: commit_email_hostname_docs_link }
|
||||
|
||||
= render_if_exists 'admin/application_settings/email_additional_text_setting', form: f
|
||||
|
||||
|
|
@ -31,6 +31,6 @@
|
|||
= f.label :in_product_marketing_emails_enabled, class: 'form-check-label' do
|
||||
= _('Enable in-product marketing emails')
|
||||
.form-text.text-muted
|
||||
= _('By default, GitLab sends emails to help guide users through the onboarding process.')
|
||||
= _('Send emails to help guide new users through the onboarding process.')
|
||||
|
||||
= f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
- @hide_breadcrumbs = true
|
||||
- @hide_top_links = true
|
||||
- page_title _('New branch')
|
||||
|
||||
.js-jira-connect-create-branch{ data: { initial_branch_name: @branch_name } }
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: jira_connect_create_branch
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336191
|
||||
milestone: '14.2'
|
||||
type: development
|
||||
group: group::ecosystem
|
||||
default_enabled: false
|
||||
|
|
@ -13,4 +13,5 @@ namespace :jira_connect do
|
|||
end
|
||||
|
||||
resources :subscriptions, only: [:index, :create, :destroy]
|
||||
resources :branches, only: [:new]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1923,6 +1923,24 @@ Input type: `DestroyPackageInput`
|
|||
| <a id="mutationdestroypackageclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationdestroypackageerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.destroyPackageFile`
|
||||
|
||||
Input type: `DestroyPackageFileInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationdestroypackagefileclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationdestroypackagefileid"></a>`id` | [`PackagesPackageFileID!`](#packagespackagefileid) | ID of the Package file. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationdestroypackagefileclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationdestroypackagefileerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.destroySnippet`
|
||||
|
||||
Input type: `DestroySnippetInput`
|
||||
|
|
|
|||
|
|
@ -133,20 +133,24 @@ For example, `app/graphql/types/issue_type.rb`:
|
|||
```ruby
|
||||
graphql_name 'Issue'
|
||||
|
||||
field :iid, GraphQL::ID_TYPE, null: true
|
||||
field :title, GraphQL::STRING_TYPE, null: true
|
||||
field :iid, GraphQL::Types::ID, null: true
|
||||
field :title, GraphQL::Types::String, null: true
|
||||
|
||||
# we also have a method here that we've defined, that extends `field`
|
||||
markdown_field :title_html, null: true
|
||||
field :description, GraphQL::STRING_TYPE, null: true
|
||||
field :description, GraphQL::Types::String, null: true
|
||||
markdown_field :description_html, null: true
|
||||
```
|
||||
|
||||
We give each type a name (in this case `Issue`).
|
||||
|
||||
The `iid`, `title` and `description` are _scalar_ GraphQL types.
|
||||
`iid` is a `GraphQL::ID_TYPE`, a special string type that signifies a unique ID.
|
||||
`title` and `description` are regular `GraphQL::STRING_TYPE` types.
|
||||
`iid` is a `GraphQL::Types::ID`, a special string type that signifies a unique ID.
|
||||
`title` and `description` are regular `GraphQL::Types::String` types.
|
||||
|
||||
Note that the old scalar types `GraphQL:ID`, `GraphQL::INT_TYPE`, `GraphQL::STRING_TYPE`,
|
||||
and `GraphQL:BOOLEAN_TYPE` are no longer allowed. Please use `GraphQL::Types::ID`,
|
||||
`GraphQL::Types::Int`, `GraphQL::Types::String`, and `GraphQL::Types::Boolean`.
|
||||
|
||||
When exposing a model through the GraphQL API, we do so by creating a
|
||||
new type in `app/graphql/types`. You can also declare custom GraphQL data types
|
||||
|
|
@ -225,7 +229,7 @@ Using an example from
|
|||
[`Types::Notes::DiscussionType`](https://gitlab.com/gitlab-org/gitlab/-/blob/3c95bd9/app/graphql/types/notes/discussion_type.rb#L24-26):
|
||||
|
||||
```ruby
|
||||
field :reply_id, GraphQL::ID_TYPE
|
||||
field :reply_id, GraphQL::Types::ID
|
||||
|
||||
def reply_id
|
||||
::Gitlab::GlobalId.build(object, id: object.reply_id)
|
||||
|
|
@ -402,7 +406,7 @@ class BranchResolver < BaseResolver
|
|||
type ::Types::BranchType, null: true
|
||||
calls_gitaly!
|
||||
|
||||
argument name: ::GraphQL::STRING_TYPE, required: true
|
||||
argument name: ::GraphQL::Types::String, required: true
|
||||
|
||||
def resolve(name:)
|
||||
object.branch(name)
|
||||
|
|
@ -499,7 +503,7 @@ everyone.
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
field :test_field, type: GraphQL::STRING_TYPE,
|
||||
field :test_field, type: GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Some test field.',
|
||||
feature_flag: :my_feature_flag
|
||||
|
|
@ -523,7 +527,7 @@ When applying a feature flag to toggle the value of a field, the
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
field :foo, GraphQL::STRING_TYPE,
|
||||
field :foo, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Some test field. Will always return `null`' \
|
||||
'if `my_feature_flag` feature flag is disabled.'
|
||||
|
|
@ -553,7 +557,7 @@ The value of the property is a `Hash` of:
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
field :token, GraphQL::STRING_TYPE, null: true,
|
||||
field :token, GraphQL::Types::String, null: true,
|
||||
deprecated: { reason: 'Login via token has been removed', milestone: '10.0' },
|
||||
description: 'Token for login.'
|
||||
```
|
||||
|
|
@ -795,15 +799,15 @@ We can use GraphQL types like this:
|
|||
```ruby
|
||||
module Types
|
||||
class ChartType < BaseObject
|
||||
field :title, GraphQL::STRING_TYPE, null: true, description: 'Title of the chart.'
|
||||
field :title, GraphQL::Types::String, null: true, description: 'Title of the chart.'
|
||||
field :data, [Types::ChartDatumType], null: true, description: 'Data of the chart.'
|
||||
end
|
||||
end
|
||||
|
||||
module Types
|
||||
class ChartDatumType < BaseObject
|
||||
field :x, GraphQL::INT_TYPE, null: true, description: 'X-axis value of the chart datum.'
|
||||
field :y, GraphQL::INT_TYPE, null: true, description: 'Y-axis value of the chart datum.'
|
||||
field :x, GraphQL::Types::Int, null: true, description: 'X-axis value of the chart datum.'
|
||||
field :y, GraphQL::Types::Int, null: true, description: 'Y-axis value of the chart datum.'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
|
@ -817,7 +821,7 @@ A description of a field or argument is given using the `description:`
|
|||
keyword. For example:
|
||||
|
||||
```ruby
|
||||
field :id, GraphQL::ID_TYPE, description: 'ID of the resource.'
|
||||
field :id, GraphQL::Types::ID, description: 'ID of the resource.'
|
||||
```
|
||||
|
||||
Descriptions of fields and arguments are viewable to users through:
|
||||
|
|
@ -834,7 +838,7 @@ descriptions:
|
|||
`'Labels of the issue'` (issue being the resource).
|
||||
- Use `"{x} of the {y}"` where possible. Example: `'Title of the issue'`.
|
||||
Do not start descriptions with `The`.
|
||||
- Descriptions of `GraphQL::BOOLEAN_TYPE` fields should answer the question: "What does
|
||||
- Descriptions of `GraphQL::Types::Boolean` fields should answer the question: "What does
|
||||
this field do?". Example: `'Indicates project has a Git repository'`.
|
||||
- Always include the word `"timestamp"` when describing an argument or
|
||||
field of type `Types::TimeType`. This lets the reader know that the
|
||||
|
|
@ -844,8 +848,8 @@ descriptions:
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
field :id, GraphQL::ID_TYPE, description: 'ID of the issue.'
|
||||
field :confidential, GraphQL::BOOLEAN_TYPE, description: 'Indicates the issue is confidential.'
|
||||
field :id, GraphQL::Types::ID, description: 'ID of the issue.'
|
||||
field :confidential, GraphQL::Types::Boolean, description: 'Indicates the issue is confidential.'
|
||||
field :closed_at, Types::TimeType, description: 'Timestamp of when the issue was closed.'
|
||||
```
|
||||
|
||||
|
|
@ -861,7 +865,7 @@ passing it the type, and field name to copy the description of.
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
argument :title, GraphQL::STRING_TYPE,
|
||||
argument :title, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: copy_field_description(Types::MergeRequestType, :title)
|
||||
```
|
||||
|
|
@ -874,7 +878,7 @@ provide a `see` property on fields. For example:
|
|||
|
||||
```ruby
|
||||
field :genus,
|
||||
type: GraphQL::STRING_TYPE,
|
||||
type: GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'A taxonomic genus.'
|
||||
see: { 'Wikipedia page on genera' => 'https://wikipedia.org/wiki/Genus' }
|
||||
|
|
@ -923,7 +927,7 @@ class PostResolver < BaseResolver
|
|||
authorize :read_blog
|
||||
description 'Blog posts, optionally filtered by name'
|
||||
|
||||
argument :name, [::GraphQL::STRING_TYPE], required: false, as: :slug
|
||||
argument :name, [::GraphQL::Types::String], required: false, as: :slug
|
||||
|
||||
alias_method :blog, :object
|
||||
|
||||
|
|
@ -1015,10 +1019,10 @@ class JobsResolver < BaseResolver
|
|||
type JobType.connection_type, null: true
|
||||
authorize :read_pipeline
|
||||
|
||||
argument :name, [::GraphQL::STRING_TYPE], required: false
|
||||
argument :name, [::GraphQL::Types::String], required: false
|
||||
|
||||
when_single do
|
||||
argument :name, ::GraphQL::STRING_TYPE, required: true
|
||||
argument :name, ::GraphQL::Types::String, required: true
|
||||
end
|
||||
|
||||
def resolve(**args)
|
||||
|
|
@ -1039,13 +1043,13 @@ class JobsResolver < BaseResolver
|
|||
type JobType.connection_type, null: true
|
||||
authorize :read_pipeline
|
||||
|
||||
argument :name, [::GraphQL::STRING_TYPE], required: false
|
||||
argument :name, [::GraphQL::Types::String], required: false
|
||||
argument :id, [::Types::GlobalIDType[::Job]],
|
||||
required: false,
|
||||
prepare: ->(ids, ctx) { ids.map(&:model_id) }
|
||||
|
||||
when_single do
|
||||
argument :name, ::GraphQL::STRING_TYPE, required: false
|
||||
argument :name, ::GraphQL::Types::String, required: false
|
||||
argument :id, ::Types::GlobalIDType[::Job],
|
||||
required: false
|
||||
prepare: ->(id, ctx) { id.model_id }
|
||||
|
|
@ -1357,7 +1361,7 @@ Arguments for a mutation are defined using `argument`.
|
|||
Example:
|
||||
|
||||
```ruby
|
||||
argument :my_arg, GraphQL::STRING_TYPE,
|
||||
argument :my_arg, GraphQL::Types::String,
|
||||
required: true,
|
||||
description: "A description of the argument."
|
||||
```
|
||||
|
|
@ -1382,16 +1386,16 @@ defines these arguments (some
|
|||
[through inheritance](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/base.rb)):
|
||||
|
||||
```ruby
|
||||
argument :project_path, GraphQL::ID_TYPE,
|
||||
argument :project_path, GraphQL::Types::ID,
|
||||
required: true,
|
||||
description: "The project the merge request to mutate is in."
|
||||
|
||||
argument :iid, GraphQL::STRING_TYPE,
|
||||
argument :iid, GraphQL::Types::String,
|
||||
required: true,
|
||||
description: "The IID of the merge request to mutate."
|
||||
|
||||
argument :draft,
|
||||
GraphQL::BOOLEAN_TYPE,
|
||||
GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: <<~DESC
|
||||
Whether or not to set the merge request as a draft.
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ module EE
|
|||
|
||||
prepended do
|
||||
argument :name,
|
||||
GraphQL::STRING_TYPE,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Tanuki name'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ to view the `secretName` field:
|
|||
```ruby
|
||||
module Types
|
||||
class ProjectType < BaseObject
|
||||
field :secret_name, ::GraphQL::STRING_TYPE, null: true, authorize: :owner_access
|
||||
field :secret_name, ::GraphQL::Types::String, null: true, authorize: :owner_access
|
||||
end
|
||||
end
|
||||
```
|
||||
|
|
@ -179,7 +179,7 @@ as an array instead of as a single value:
|
|||
```ruby
|
||||
module Types
|
||||
class MyType < BaseObject
|
||||
field :hidden_field, ::GraphQL::INT_TYPE,
|
||||
field :hidden_field, ::GraphQL::Types::Int,
|
||||
null: true,
|
||||
authorize: [:owner_access, :another_ability]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ For example, to load a `User` by `username`, we can add batching as follows:
|
|||
```ruby
|
||||
class UserResolver < BaseResolver
|
||||
type UserType, null: true
|
||||
argument :username, ::GraphQL::STRING_TYPE, required: true
|
||||
argument :username, ::GraphQL::Types::String, required: true
|
||||
|
||||
def resolve(**args)
|
||||
BatchLoader::GraphQL.for(username).batch do |usernames, loader|
|
||||
|
|
|
|||
|
|
@ -13,27 +13,40 @@ You can customize some of the content in emails sent from your GitLab instance.
|
|||
|
||||
The logo in the header of some emails can be customized, see the [logo customization section](../appearance.md#navigation-bar).
|
||||
|
||||
## Custom additional text **(PREMIUM SELF)**
|
||||
## Include author name in email notification email body **(PREMIUM SELF)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7.
|
||||
By default, GitLab overrides the email address in notification emails with the email address
|
||||
of the issue, merge request, or comment author. Enable this setting to include the author's email
|
||||
address in the body of the email instead.
|
||||
|
||||
The additional text appears at the bottom of any email and can be used for
|
||||
legal/auditing/compliance reasons.
|
||||
To include the author's email address in the email body:
|
||||
|
||||
1. On the top bar, select **Menu >** **{admin}** **Admin**.
|
||||
1. On the left sidebar, select **Settings > Preferences** (`/admin/application_settings/preferences`).
|
||||
1. Expand **Email**.
|
||||
1. Enter your text in the **Additional text** field.
|
||||
1. Click **Save**.
|
||||
1. Select the **Include author name in email notification email body** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Custom hostname for private commit emails
|
||||
## Enable multipart email **(PREMIUM SELF)**
|
||||
|
||||
GitLab can send email in multipart format (HTML and plain text) or plain text only.
|
||||
|
||||
To enable multipart email:
|
||||
|
||||
1. On the top bar, select **Menu >** **{admin}** **Admin**.
|
||||
1. On the left sidebar, select **Settings > Preferences** (`/admin/application_settings/preferences`).
|
||||
1. Expand **Email**.
|
||||
1. Select **Enable multipart email**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Custom hostname for private commit emails **(PREMIUM SELF)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22560) in GitLab 11.5.
|
||||
|
||||
This configuration option sets the email hostname for [private commit emails](../../profile/index.md#use-an-automatically-generated-private-commit-email).
|
||||
By default it is set to `users.noreply.YOUR_CONFIGURED_HOSTNAME`.
|
||||
|
||||
In order to change this option:
|
||||
To change the hostname used in private commit emails:
|
||||
|
||||
1. On the top bar, select **Menu >** **{admin}** **Admin**.
|
||||
1. On the left sidebar, select **Settings > Preferences** (`/admin/application_settings/preferences`).
|
||||
|
|
@ -42,10 +55,23 @@ In order to change this option:
|
|||
1. Select **Save changes**.
|
||||
|
||||
NOTE:
|
||||
After the hostname gets configured, every private commit email using the previous hostname is not
|
||||
After the hostname is configured, every private commit email using the previous hostname is not
|
||||
recognized by GitLab. This can directly conflict with certain [Push rules](../../../push_rules/push_rules.md) such as
|
||||
`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`.
|
||||
|
||||
## Custom additional text **(PREMIUM SELF)**
|
||||
|
||||
You can add additional text at the bottom of any email that GitLab sends. This additional text
|
||||
can be used for legal, auditing, or compliance reasons, for example.
|
||||
|
||||
To add additional text to emails:
|
||||
|
||||
1. On the top bar, select **Menu >** **{admin}** **Admin**.
|
||||
1. On the left sidebar, select **Settings > Preferences** (`/admin/application_settings/preferences`).
|
||||
1. Expand **Email**.
|
||||
1. Enter your text in the **Additional text** field.
|
||||
1. Select **Save changes**.
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ module API
|
|||
path = params[:path]
|
||||
before = params[:until]
|
||||
after = params[:since]
|
||||
ref = params[:ref_name].presence || user_project.try(:default_branch) || 'master' unless params[:all]
|
||||
ref = params[:ref_name].presence || user_project.default_branch unless params[:all]
|
||||
offset = (params[:page] - 1) * params[:per_page]
|
||||
all = params[:all]
|
||||
with_stats = params[:with_stats]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ module API
|
|||
optional :mentions_disabled, type: Boolean, desc: 'Disable a group from getting mentioned'
|
||||
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
|
||||
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
|
||||
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
|
||||
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to default branch'
|
||||
optional :shared_runners_setting, type: String, values: ::Namespace::SHARED_RUNNERS_SETTINGS, desc: 'Enable/disable shared runners for the group and its subgroups and projects'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ module API
|
|||
use :pagination
|
||||
end
|
||||
get ':id/repository/tree' do
|
||||
ref = params[:ref] || user_project.try(:default_branch) || 'master'
|
||||
ref = params[:ref] || user_project.default_branch
|
||||
path = params[:path] || nil
|
||||
|
||||
commit = user_project.commit(ref)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ module API
|
|||
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
|
||||
optional :default_ci_config_path, type: String, desc: 'The instance default CI/CD configuration file and path for new projects'
|
||||
optional :default_project_creation, type: Integer, values: ::Gitlab::Access.project_creation_values, desc: 'Determine if developers can create projects in the group'
|
||||
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
|
||||
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to default branch'
|
||||
optional :default_group_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default group visibility'
|
||||
optional :default_project_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default project visibility'
|
||||
optional :default_projects_limit, type: Integer, desc: 'The maximum number of personal projects'
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ module Atlassian
|
|||
end
|
||||
|
||||
def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil, update_sequence_id: nil)
|
||||
repo = Serializers::RepositoryEntity.represent(
|
||||
repo = ::Atlassian::JiraConnect::Serializers::RepositoryEntity.represent(
|
||||
project,
|
||||
commits: commits,
|
||||
branches: branches,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module Gitlab
|
|||
module CycleAnalytics
|
||||
module StageQueryHelpers
|
||||
def execute_query(query)
|
||||
ActiveRecord::Base.connection.execute(query.to_sql)
|
||||
ApplicationRecord.connection.execute(query.to_sql)
|
||||
end
|
||||
|
||||
def zero_interval
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ module Gitlab
|
|||
expected_end_time = Time.now + duration_s
|
||||
|
||||
while Time.now < expected_end_time
|
||||
ActiveRecord::Base.connection.execute("SELECT 1")
|
||||
ApplicationRecord.connection.execute("SELECT 1")
|
||||
|
||||
end_interval_time = Time.now + [duration_s, interval_s].min
|
||||
rand while Time.now < end_interval_time
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ module Gitlab
|
|||
def empty_project_push_message
|
||||
<<~MESSAGE
|
||||
|
||||
A default branch (e.g. master) does not yet exist for #{project.full_path}
|
||||
A default branch (e.g. main) does not yet exist for #{project.full_path}
|
||||
Ask a project Owner or Maintainer to create a default branch:
|
||||
|
||||
#{project_members_url}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
# This template is on early stage of development.
|
||||
# Use it with caution. For usage instruction please read
|
||||
# https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/v2.3.0/README.md
|
||||
# https://gitlab.com/gitlab-org/5-minute-production-app/deploy-template/-/blob/v3.0.0/README.md
|
||||
|
||||
include:
|
||||
# workflow rules to prevent duplicate detached pipelines
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def count(batch_size: nil, mode: :itself, start: nil, finish: nil)
|
||||
raise 'BatchCount can not be run inside a transaction' if ActiveRecord::Base.connection.transaction_open?
|
||||
raise 'BatchCount can not be run inside a transaction' if @relation.connection.transaction_open?
|
||||
|
||||
check_mode!(mode)
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ module Gitlab
|
|||
|
||||
# Querying tuple stats only works on the primary. Due to load balancing, the
|
||||
# easiest way to do this is to start a transaction.
|
||||
ActiveRecord::Base.transaction do
|
||||
ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
|
||||
get_statistics(non_sti_table_names, check_statistics: check_statistics).each_with_object({}) do |row, data|
|
||||
model = table_to_model[row.table_name]
|
||||
data[model] = row.estimate
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ module Gitlab
|
|||
#{where_clause(model)}
|
||||
SQL
|
||||
|
||||
rows = ActiveRecord::Base.connection.select_all(query)
|
||||
rows = ActiveRecord::Base.connection.select_all(query) # rubocop: disable Database/MultipleDatabases
|
||||
|
||||
Integer(rows.first['count'])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module Gitlab
|
|||
# We _must not_ use quote_table_name as this will produce double
|
||||
# quotes on PostgreSQL and for "has_table_privilege" we need single
|
||||
# quotes.
|
||||
connection = ActiveRecord::Base.connection
|
||||
connection = ActiveRecord::Base.connection # rubocop: disable Database/MultipleDatabases
|
||||
quoted_table = connection.quote(table)
|
||||
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ module Gitlab
|
|||
# @param finish final pkey range
|
||||
# @return [Gitlab::Database::PostgresHll::Buckets] HyperLogLog data structure instance that can estimate number of unique elements
|
||||
def execute(batch_size: nil, start: nil, finish: nil)
|
||||
raise 'BatchCount can not be run inside a transaction' if ActiveRecord::Base.connection.transaction_open?
|
||||
raise 'BatchCount can not be run inside a transaction' if ActiveRecord::Base.connection.transaction_open? # rubocop: disable Database/MultipleDatabases
|
||||
|
||||
batch_size ||= DEFAULT_BATCH_SIZE
|
||||
start = actual_start(start)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue