Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4fc8a50352
commit
1fc72cb876
|
|
@ -51,9 +51,9 @@ variables:
|
|||
- echo "$(docker exec gdk bash -c "getent hosts \$HOSTNAME" | awk '{print $1}') gdk.test" >> /etc/hosts
|
||||
- source scripts/utils.sh
|
||||
- cd qa && bundle install
|
||||
script:
|
||||
- retry_exponential test_url ${GDK_URL}/users/sign_in
|
||||
- echo -e "\e[0Ksection_end:`date +%s`:launch_gdk\r\e[0K"
|
||||
script:
|
||||
- echo -e "\e[0Ksection_start:`date +%s`:run_tests\r\e[0KRun E2E tests"
|
||||
- QA_COMMAND="bundle exec bin/qa Test::Instance::All ${GDK_URL} -- ${RSPEC_TAGS} ${RSPEC_REPORT_OPTS}"
|
||||
- echo "Running - '${QA_COMMAND}'"
|
||||
|
|
@ -87,6 +87,21 @@ cache-gems:
|
|||
script:
|
||||
- cd qa && bundle install
|
||||
|
||||
# Take the existing GDK docker image and reconfigure it with Postgres load
|
||||
# balancing. Adding 5s lag to 1 of the replicas to validate robustness of
|
||||
# the load balancer.
|
||||
.gdk-with-load-balancer-setup:
|
||||
before_script:
|
||||
- !reference [".gdk-qa-base", "before_script"]
|
||||
- |
|
||||
docker exec gdk bash -c "
|
||||
gdk config set postgresql.replica.enabled true &&\
|
||||
gdk config set postgresql.replica_2.enabled true &&\
|
||||
gdk config set load_balancing.enabled true &&\
|
||||
gdk reconfigure &&\
|
||||
echo 'recovery_min_apply_delay = 5s' >> postgresql-replica-2/data/postgresql.conf &&\
|
||||
gdk restart"
|
||||
|
||||
gdk-qa-smoke:
|
||||
extends:
|
||||
- .gdk-qa-base
|
||||
|
|
@ -97,6 +112,19 @@ gdk-qa-smoke:
|
|||
rules:
|
||||
- when: always
|
||||
|
||||
gdk-qa-smoke-with-load-balancer:
|
||||
extends:
|
||||
- .gdk-qa-base
|
||||
- .gdk-with-load-balancer-setup
|
||||
variables:
|
||||
TEST_GDK_TAGS: "--tag smoke"
|
||||
QA_RUN_TYPE: gdk-qa-smoke
|
||||
RSPEC_TAGS: --tag smoke
|
||||
rules:
|
||||
- changes:
|
||||
- ".gitlab/ci/test-on-gdk/**"
|
||||
- "lib/gitlab/database/load_balancing/**/*"
|
||||
|
||||
# TODO: set non manual once smoke tests prove to be stable
|
||||
gdk-qa-reliable:
|
||||
extends:
|
||||
|
|
@ -110,6 +138,21 @@ gdk-qa-reliable:
|
|||
rules:
|
||||
- when: manual
|
||||
|
||||
gdk-qa-reliable-with-load-balancer:
|
||||
extends:
|
||||
- .gdk-qa-base
|
||||
- .gdk-with-load-balancer-setup
|
||||
parallel: 5
|
||||
variables:
|
||||
QA_RUN_TYPE: gdk-qa-blocking
|
||||
QA_KNAPSACK_REPORT_NAME: ee-instance-parallel
|
||||
RSPEC_TAGS: --tag smoke --tag reliable
|
||||
allow_failure: true
|
||||
rules:
|
||||
- changes:
|
||||
- ".gitlab/ci/test-on-gdk/**"
|
||||
- "lib/gitlab/database/load_balancing/**/*"
|
||||
|
||||
gdk-qa-non-blocking:
|
||||
extends:
|
||||
- .gdk-qa-base
|
||||
|
|
|
|||
|
|
@ -1957,7 +1957,6 @@ RSpec/ContextWording:
|
|||
- 'spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/basic_health_check_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/compressed_json_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/go_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/multipart_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/request_context_spec.rb'
|
||||
|
|
@ -2390,7 +2389,6 @@ RSpec/ContextWording:
|
|||
- 'spec/requests/api/deploy_tokens_spec.rb'
|
||||
- 'spec/requests/api/deployments_spec.rb'
|
||||
- 'spec/requests/api/environments_spec.rb'
|
||||
- 'spec/requests/api/error_tracking/collector_spec.rb'
|
||||
- 'spec/requests/api/files_spec.rb'
|
||||
- 'spec/requests/api/generic_packages_spec.rb'
|
||||
- 'spec/requests/api/graphql/ci/runner_spec.rb'
|
||||
|
|
|
|||
|
|
@ -4043,7 +4043,6 @@ RSpec/MissingFeatureCategory:
|
|||
- 'spec/lib/gitlab/metrics/web_transaction_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/basic_health_check_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/compressed_json_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/handle_ip_spoof_attack_error_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/memory_report_spec.rb'
|
||||
|
|
|
|||
|
|
@ -501,7 +501,6 @@ Style/ClassAndModuleChildren:
|
|||
- 'ee/lib/ee/gitlab/throttle.rb'
|
||||
- 'ee/lib/gitlab/path_locks_finder.rb'
|
||||
- 'lib/api/error_tracking/client_keys.rb'
|
||||
- 'lib/api/error_tracking/collector.rb'
|
||||
- 'lib/api/error_tracking/project_settings.rb'
|
||||
- 'lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb'
|
||||
- 'lib/gitlab/ci/badge/base.rb'
|
||||
|
|
|
|||
|
|
@ -428,7 +428,6 @@ Style/GuardClause:
|
|||
- 'ee/spec/support/ci/minutes_helpers.rb'
|
||||
- 'haml_lint/linter/documentation_links.rb'
|
||||
- 'lib/api/commits.rb'
|
||||
- 'lib/api/error_tracking/collector.rb'
|
||||
- 'lib/api/feature_flags.rb'
|
||||
- 'lib/api/helpers.rb'
|
||||
- 'lib/api/helpers/packages/conan/api_helpers.rb'
|
||||
|
|
|
|||
|
|
@ -4,7 +4,13 @@ import RunnerFormFields from '~/ci/runner/components/runner_form_fields.vue';
|
|||
import runnerCreateMutation from '~/ci/runner/graphql/new/runner_create.mutation.graphql';
|
||||
import { modelToUpdateMutationVariables } from 'ee_else_ce/ci/runner/runner_update_form_utils';
|
||||
import { captureException } from '../sentry_utils';
|
||||
import { RUNNER_TYPES, DEFAULT_ACCESS_LEVEL, PROJECT_TYPE, GROUP_TYPE } from '../constants';
|
||||
import {
|
||||
RUNNER_TYPES,
|
||||
DEFAULT_ACCESS_LEVEL,
|
||||
PROJECT_TYPE,
|
||||
GROUP_TYPE,
|
||||
I18N_CREATE_ERROR,
|
||||
} from '../constants';
|
||||
|
||||
export default {
|
||||
name: 'RunnerCreateForm',
|
||||
|
|
@ -82,17 +88,30 @@ export default {
|
|||
});
|
||||
|
||||
if (errors?.length) {
|
||||
this.$emit('error', new Error(errors.join(' ')));
|
||||
this.saving = false;
|
||||
} else {
|
||||
this.onSuccess(runner);
|
||||
this.onError(new Error(errors.join(' ')), true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runner?.ephemeralRegisterUrl) {
|
||||
// runner is missing information, report issue and
|
||||
// fail naviation to register page.
|
||||
this.onError(new Error(I18N_CREATE_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
this.onSuccess(runner);
|
||||
} catch (error) {
|
||||
captureException({ error, component: this.$options.name });
|
||||
this.$emit('error', error);
|
||||
this.saving = false;
|
||||
this.onError(error);
|
||||
}
|
||||
},
|
||||
onError(error, isValidationError = false) {
|
||||
if (!isValidationError) {
|
||||
captureException({ error, component: this.$options.name });
|
||||
}
|
||||
|
||||
this.$emit('error', error);
|
||||
this.saving = false;
|
||||
},
|
||||
onSuccess(runner) {
|
||||
this.$emit('saved', runner);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
GROUP_TYPE,
|
||||
PROJECT_TYPE,
|
||||
RUNNER_MANAGERS_HELP_URL,
|
||||
I18N_STATUS_NEVER_CONTACTED,
|
||||
} from '../constants';
|
||||
import RunnerDetail from './runner_detail.vue';
|
||||
import RunnerGroups from './runner_groups.vue';
|
||||
|
|
@ -85,6 +86,7 @@ export default {
|
|||
},
|
||||
ACCESS_LEVEL_REF_PROTECTED,
|
||||
RUNNER_MANAGERS_HELP_URL,
|
||||
I18N_STATUS_NEVER_CONTACTED,
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -99,7 +101,7 @@ export default {
|
|||
<runner-detail :label="s__('Runners|Description')" :value="runner.description" />
|
||||
<runner-detail
|
||||
:label="s__('Runners|Last contact')"
|
||||
:empty-value="s__('Runners|Never contacted')"
|
||||
:empty-value="$options.I18N_STATUS_NEVER_CONTACTED"
|
||||
>
|
||||
<template v-if="runner.contactedAt" #value>
|
||||
<time-ago :time="runner.contactedAt" />
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
<script>
|
||||
import { GlCollapse, GlButton, GlIcon, GlSkeletonLoader, GlTableLite } from '@gitlab/ui';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import { GlCollapse, GlButton, GlIcon, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import { __, s__, formatNumber } from '~/locale';
|
||||
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import { createAlert } from '~/alert';
|
||||
import runnerManagersQuery from '../graphql/show/runner_managers.query.graphql';
|
||||
import { I18N_FETCH_ERROR } from '../constants';
|
||||
import { captureException } from '../sentry_utils';
|
||||
import { tableField } from '../utils';
|
||||
import RunnerManagersTable from './runner_managers_table.vue';
|
||||
|
||||
export default {
|
||||
name: 'RunnerManagersDetail',
|
||||
|
|
@ -16,9 +15,7 @@ export default {
|
|||
GlButton,
|
||||
GlIcon,
|
||||
GlSkeletonLoader,
|
||||
GlTableLite,
|
||||
TimeAgo,
|
||||
HelpPopover,
|
||||
RunnerManagersTable,
|
||||
},
|
||||
props: {
|
||||
runner: {
|
||||
|
|
@ -108,20 +105,7 @@ export default {
|
|||
|
||||
<gl-collapse :visible="expanded" class="gl-mt-5">
|
||||
<gl-skeleton-loader v-if="loading" />
|
||||
<gl-table-lite v-else-if="managers.length" :fields="$options.fields" :items="managers">
|
||||
<template #head(systemId)="{ label }">
|
||||
{{ label }}
|
||||
<help-popover>
|
||||
{{ s__('Runners|The unique ID for each runner that uses this configuration.') }}
|
||||
</help-popover>
|
||||
</template>
|
||||
<template #cell(contactedAt)="{ item = {} }">
|
||||
<template v-if="item.contactedAt">
|
||||
<time-ago :time="item.contactedAt" />
|
||||
</template>
|
||||
<template v-else>{{ s__('Runners|Never contacted') }}</template>
|
||||
</template>
|
||||
</gl-table-lite>
|
||||
<runner-managers-table v-else-if="managers.length" :items="managers" />
|
||||
</gl-collapse>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
|||
import { s__ } from '~/locale';
|
||||
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import { tableField } from '../utils';
|
||||
import { I18N_STATUS_NEVER_CONTACTED } from '../constants';
|
||||
|
||||
export default {
|
||||
name: 'RunnerManagersTable',
|
||||
|
|
@ -20,13 +21,6 @@ export default {
|
|||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
skip: true,
|
||||
expanded: false,
|
||||
managers: [],
|
||||
};
|
||||
},
|
||||
fields: [
|
||||
tableField({ key: 'systemId', label: s__('Runners|System ID') }),
|
||||
tableField({ key: 'version', label: s__('Runners|Version') }),
|
||||
|
|
@ -40,6 +34,7 @@ export default {
|
|||
thClasses: ['gl-text-right'],
|
||||
}),
|
||||
],
|
||||
I18N_STATUS_NEVER_CONTACTED,
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -65,7 +60,7 @@ export default {
|
|||
<template v-if="item.contactedAt">
|
||||
<time-ago :time="item.contactedAt" />
|
||||
</template>
|
||||
<template v-else>{{ s__('Runners|Never contacted') }}</template>
|
||||
<template v-else>{{ $options.I18N_STATUS_NEVER_CONTACTED }}</template>
|
||||
</template>
|
||||
</gl-table-lite>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ export const RUNNER_DETAILS_PROJECTS_PAGE_SIZE = 5;
|
|||
export const RUNNER_DETAILS_JOBS_PAGE_SIZE = 30;
|
||||
|
||||
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
|
||||
export const I18N_CREATE_ERROR = s__(
|
||||
'Runners|An error occurred while creating the runner. Please try again.',
|
||||
);
|
||||
|
||||
export const FILTER_CSS_CLASSES =
|
||||
'gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1';
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ query getRunnerManagers($runnerId: CiRunnerID!) {
|
|||
nodes {
|
||||
id
|
||||
systemId
|
||||
version
|
||||
revision
|
||||
executorName
|
||||
architectureName
|
||||
platformName
|
||||
ipAddress
|
||||
contactedAt
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
<script>
|
||||
import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
|
||||
import {
|
||||
GlLink,
|
||||
GlTable,
|
||||
GlDisclosureDropdownItem,
|
||||
GlDisclosureDropdown,
|
||||
GlButton,
|
||||
} from '@gitlab/ui';
|
||||
import { last } from 'lodash';
|
||||
import { numberToHumanSize } from '~/lib/utils/number_utils';
|
||||
import { __ } from '~/locale';
|
||||
|
|
@ -13,9 +19,8 @@ export default {
|
|||
components: {
|
||||
GlLink,
|
||||
GlTable,
|
||||
GlIcon,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlDisclosureDropdown,
|
||||
GlDisclosureDropdownItem,
|
||||
GlButton,
|
||||
FileIcon,
|
||||
TimeAgoTooltip,
|
||||
|
|
@ -136,14 +141,16 @@ export default {
|
|||
</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>
|
||||
<gl-disclosure-dropdown category="tertiary" right no-caret icon="ellipsis_v">
|
||||
<gl-disclosure-dropdown-item
|
||||
data-testid="delete-file"
|
||||
@action="$emit('delete-file', item)"
|
||||
>
|
||||
<template #list-item>
|
||||
{{ $options.i18n.deleteFile }}
|
||||
</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
</gl-disclosure-dropdown>
|
||||
</template>
|
||||
|
||||
<template #row-details="{ item }">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Achievements
|
||||
class DeleteUserAchievement < BaseMutation
|
||||
graphql_name 'UserAchievementsDelete'
|
||||
|
||||
include Gitlab::Graphql::Authorize::AuthorizeResource
|
||||
|
||||
field :user_achievement,
|
||||
::Types::Achievements::UserAchievementType,
|
||||
null: true,
|
||||
description: 'Deleted user achievement.'
|
||||
|
||||
argument :user_achievement_id, ::Types::GlobalIDType[::Achievements::UserAchievement],
|
||||
required: true,
|
||||
description: 'Global ID of the user achievement being deleted.'
|
||||
|
||||
authorize :destroy_user_achievement
|
||||
|
||||
def resolve(args)
|
||||
user_achievement = authorized_find!(id: args[:user_achievement_id])
|
||||
|
||||
result = ::Achievements::DestroyUserAchievementService.new(current_user, user_achievement).execute
|
||||
{ user_achievement: result.payload, errors: result.errors }
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.object_from_id(id, expected_type: ::Achievements::UserAchievement)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -9,6 +9,7 @@ module Types
|
|||
mount_mutation Mutations::Achievements::Award, alpha: { milestone: '15.10' }
|
||||
mount_mutation Mutations::Achievements::Create, alpha: { milestone: '15.8' }
|
||||
mount_mutation Mutations::Achievements::Delete, alpha: { milestone: '15.11' }
|
||||
mount_mutation Mutations::Achievements::DeleteUserAchievement, alpha: { milestone: '16.1' }
|
||||
mount_mutation Mutations::Achievements::Revoke, alpha: { milestone: '15.10' }
|
||||
mount_mutation Mutations::Achievements::Update, alpha: { milestone: '15.11' }
|
||||
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
|
||||
|
|
|
|||
|
|
@ -163,6 +163,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
enable :award_achievement
|
||||
end
|
||||
|
||||
rule { can?(:owner_access) & achievements_enabled }.policy do
|
||||
enable :destroy_user_achievement
|
||||
end
|
||||
|
||||
rule { ~public_group & ~has_access }.prevent :read_counts
|
||||
|
||||
rule { ~can_read_group_member }.policy do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Achievements
|
||||
class DestroyUserAchievementService
|
||||
attr_reader :current_user, :user_achievement
|
||||
|
||||
def initialize(current_user, user_achievement)
|
||||
@current_user = current_user
|
||||
@user_achievement = user_achievement
|
||||
end
|
||||
|
||||
def execute
|
||||
return error_no_permissions unless allowed?
|
||||
|
||||
user_achievement.delete
|
||||
ServiceResponse.success(payload: user_achievement)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allowed?
|
||||
current_user&.can?(:destroy_user_achievement, user_achievement)
|
||||
end
|
||||
|
||||
def error_no_permissions
|
||||
error('You have insufficient permissions to delete this user achievement')
|
||||
end
|
||||
|
||||
def error(message)
|
||||
ServiceResponse.error(message: Array(message))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Database
|
||||
class MarkMigrationService
|
||||
def initialize(connection:, version:)
|
||||
@connection = connection
|
||||
@version = version
|
||||
end
|
||||
|
||||
def execute
|
||||
return error(reason: :not_found) unless migration.present?
|
||||
return error(reason: :invalid) if all_versions.include?(migration.version)
|
||||
|
||||
if create_version(version)
|
||||
ServiceResponse.success
|
||||
else
|
||||
error(reason: :invalid)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :connection, :version
|
||||
|
||||
def migration
|
||||
@migration ||= connection
|
||||
.migration_context
|
||||
.migrations
|
||||
.find { |migration| migration.version == version }
|
||||
end
|
||||
|
||||
def all_versions
|
||||
all_executed_migrations.map(&:to_i)
|
||||
end
|
||||
|
||||
def all_executed_migrations
|
||||
sm = Arel::SelectManager.new(arel_table)
|
||||
sm.project(arel_table[:version])
|
||||
sm.order(arel_table[:version].asc) # rubocop: disable CodeReuse/ActiveRecord
|
||||
connection.select_values(sm, "#{self.class} Load")
|
||||
end
|
||||
|
||||
def create_version(version)
|
||||
im = Arel::InsertManager.new
|
||||
im.into(arel_table)
|
||||
im.insert(arel_table[:version] => version)
|
||||
connection.insert(im, "#{self.class} Create", :version, version)
|
||||
end
|
||||
|
||||
def arel_table
|
||||
@arel_table ||= Arel::Table.new(:schema_migrations)
|
||||
end
|
||||
|
||||
def error(reason:)
|
||||
ServiceResponse.error(message: 'error', reason: reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -22,7 +22,14 @@ module PersonalAccessTokens
|
|||
|
||||
last_used = @personal_access_token.last_used_at
|
||||
|
||||
last_used.nil? || (last_used <= 1.day.ago)
|
||||
return true if last_used.nil?
|
||||
|
||||
if Feature.enabled?(:update_personal_access_token_usage_information_every_10_minutes) &&
|
||||
last_used <= 10.minutes.ago
|
||||
return true
|
||||
end
|
||||
|
||||
last_used <= 1.day.ago
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: revert_daily_hll_events_to_weekly_aggregation
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114967
|
||||
rollout_issue_url:
|
||||
milestone: '16.0'
|
||||
type: development
|
||||
group: group::analytics instrumentation
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: update_personal_access_token_usage_information_every_10_minutes
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123154
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414945
|
||||
milestone: '16.1'
|
||||
type: development
|
||||
group: group::authentication and authorization
|
||||
default_enabled: true
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. Registration tokens, and support for certain configuration arguments,
|
||||
will be removed in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](../ci/runners/new_creation_workflow.md).
|
||||
will start returning the HTTP `410 Gone` status code in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](../ci/runners/new_creation_workflow.md).
|
||||
|
||||
The configuration arguments disabled for authentication tokens are:
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/383341 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
The support for runner registration tokens is deprecated. As a consequence, the REST API endpoints to reset a registration token are also deprecated and will
|
||||
be removed in GitLab 17.0.
|
||||
return the HTTP `410 Gone` status code in GitLab 17.0.
|
||||
The deprecated endpoints are:
|
||||
|
||||
- `POST /runners/reset_registration_token`
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
class ReMigrateRedisSlotKeys < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
KEY_EXPIRY_LENGTH = 6.weeks
|
||||
|
||||
DAILY_EVENTS =
|
||||
%w[g_edit_by_web_ide
|
||||
g_edit_by_sfe
|
||||
|
|
@ -117,7 +119,7 @@ class ReMigrateRedisSlotKeys < Gitlab::Database::Migration[2.1]
|
|||
end
|
||||
|
||||
def migrate_weekly_aggregated(event)
|
||||
weeks_back = Gitlab::UsageDataCounters::HLLRedisCounter::DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH
|
||||
weeks_back = KEY_EXPIRY_LENGTH
|
||||
start_date = (Date.today - weeks_back).beginning_of_week - 1.day
|
||||
end_date = Date.today.end_of_week + 1.day
|
||||
|
||||
|
|
@ -136,7 +138,7 @@ class ReMigrateRedisSlotKeys < Gitlab::Database::Migration[2.1]
|
|||
|
||||
temp_key = new_key + "_#{Time.current.to_i}"
|
||||
ttl = redis.ttl(old_key)
|
||||
ttl = ttl > 0 ? ttl : Gitlab::UsageDataCounters::HLLRedisCounter.send(:expiry, event)
|
||||
ttl = ttl > 0 ? ttl : KEY_EXPIRY_LENGTH
|
||||
|
||||
redis.multi do |multi|
|
||||
multi.set(temp_key, hll_blob, ex: 1.day.to_i)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DeleteIndexMembersOnSourceIdAndSourceType < Gitlab::Database::Migration[2.1]
|
||||
INDEX_NAME = 'index_members_on_source_id_and_source_type'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name :members, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :members, %i[source_id source_type], name: INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DeleteIndexUniqueProjectAuthorizationsOnProjectIdUserId < Gitlab::Database::Migration[2.1]
|
||||
INDEX_NAME = 'index_unique_project_authorizations_on_project_id_user_id'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name :project_authorizations, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :project_authorizations, %i[project_id user_id], name: INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
cba57f523bb3d233ce1f7a0447ee25e37dafcd4ae3cd8a02ef052136e36b0938
|
||||
|
|
@ -0,0 +1 @@
|
|||
24b2ac86b56c1eb32409d921dfba52dc9f9ba6817c9aa19ae5058d46926e79ce
|
||||
|
|
@ -31589,8 +31589,6 @@ CREATE INDEX index_members_on_requested_at ON members USING btree (requested_at)
|
|||
|
||||
CREATE INDEX index_members_on_source_and_type_and_access_level ON members USING btree (source_id, source_type, type, access_level);
|
||||
|
||||
CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (source_id, source_type);
|
||||
|
||||
CREATE INDEX index_members_on_source_state_type_access_level_and_user_id ON members USING btree (source_id, source_type, state, type, access_level, user_id) WHERE ((requested_at IS NULL) AND (invite_token IS NULL));
|
||||
|
||||
CREATE INDEX index_members_on_user_id_and_access_level_requested_at_is_null ON members USING btree (user_id, access_level) WHERE (requested_at IS NULL);
|
||||
|
|
@ -32967,8 +32965,6 @@ CREATE UNIQUE INDEX index_unique_ci_runner_projects_on_runner_id_and_project_id
|
|||
|
||||
CREATE UNIQUE INDEX index_unique_issue_metrics_issue_id ON issue_metrics USING btree (issue_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_unique_project_authorizations_on_project_id_user_id ON project_authorizations USING btree (project_id, user_id);
|
||||
|
||||
CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING btree (failed_at DESC);
|
||||
|
||||
CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_failures USING btree (unit_test_id, failed_at DESC, build_id);
|
||||
|
|
|
|||
|
|
@ -138,13 +138,13 @@ Example response:
|
|||
"id": 1,
|
||||
"active": true,
|
||||
"public_key": "glet_aa77551d849c083f76d0bc545ed053a3",
|
||||
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5"
|
||||
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@example.com/errortracking/api/v1/projects/5"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"active": true,
|
||||
"public_key": "glet_0ff98b1d849c083f76d0bc545ed053a3",
|
||||
"sentry_dsn": "https://glet_0ff98b1d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5"
|
||||
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@example.com/errortracking/api/v1/projects/5"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
|
@ -173,7 +173,7 @@ Example response:
|
|||
"id": 3,
|
||||
"active": true,
|
||||
"public_key": "glet_0ff98b1d849c083f76d0bc545ed053a3",
|
||||
"sentry_dsn": "https://glet_0ff98b1d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5"
|
||||
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@example.com/errortracking/api/v1/projects/5"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -6755,6 +6755,29 @@ Input type: `UploadDeleteInput`
|
|||
| <a id="mutationuploaddeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationuploaddeleteupload"></a>`upload` | [`FileUpload`](#fileupload) | Deleted upload. |
|
||||
|
||||
### `Mutation.userAchievementsDelete`
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.1.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Input type: `UserAchievementsDeleteInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationuserachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationuserachievementsdeleteuserachievementid"></a>`userAchievementId` | [`AchievementsUserAchievementID!`](#achievementsuserachievementid) | Global ID of the user achievement being deleted. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationuserachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationuserachievementsdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationuserachievementsdeleteuserachievement"></a>`userAchievement` | [`UserAchievement`](#userachievement) | Deleted user achievement. |
|
||||
|
||||
### `Mutation.userCalloutCreate`
|
||||
|
||||
Input type: `UserCalloutCreateInput`
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/index.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/index.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-admin-area.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-admin-area.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-agent-for-kubernetes.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-agent-for-kubernetes.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-backups.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-backups.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-ci-runners.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-ci-runners.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-container-registry.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-container-registry.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-contributions-forks.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-contributions-forks.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-dashboard.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-dashboard.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-data-migration.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-data-migration.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-database-sequences.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-database-sequences.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-git-access.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-git-access.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-gitlab-pages.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-gitlab-pages.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-global-search.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-global-search.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-graphql.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-graphql.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-organizations.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-organizations.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-personal-namespaces.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-personal-namespaces.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-router-endpoints-classification.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-router-endpoints-classification.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-schema-changes.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-schema-changes.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-secrets.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-secrets.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-snippets.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-snippets.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-template.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-template.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/cells-feature-uploads.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/cells-feature-uploads.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/proposal-stateless-router-with-buffering-requests.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/proposal-stateless-router-with-buffering-requests.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../cells/proposal-stateless-router-with-routes-learning.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../cells/proposal-stateless-router-with-routes-learning.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -100,7 +100,7 @@ A major goal is that each member of a development team should have the same deve
|
|||
|
||||
A workspace should allow access to an existing development environment from multiple machines and locations across a single or multiple teams. It should also allow a user to make use of tools or runtimes not available on their local OS or manage multiple versions of them.
|
||||
|
||||
Additionally, remote development workspaces could provide a way to implement disaster recovery if we are able to leverage the capabilities of [Cells](../../../architecture/blueprints/pods/index.md).
|
||||
Additionally, remote development workspaces could provide a way to implement disaster recovery if we are able to leverage the capabilities of [Cells](../../../architecture/blueprints/cells/index.md).
|
||||
|
||||
### Scalability
|
||||
|
||||
|
|
|
|||
|
|
@ -111,3 +111,17 @@ Related topics:
|
|||
- If the VM image does not include the specific software version you need for your job, then the job execution time will increase as the required software needs to be fetched and installed.
|
||||
- At this time, it is not possible to bring your own OS image.
|
||||
- The keychain for user `gitlab` is not publicly available. You must create a keychain instead.
|
||||
|
||||
## Optimizing Homebrew
|
||||
|
||||
By default, Homebrew checks for updates at the start of any operation. Homebrew has a
|
||||
release cycle that may be more frequent than the GitLab MacOS image release cycle. This
|
||||
difference in release cycles may cause steps that call `brew` to take extra time to complete
|
||||
while Homebrew makes updates.
|
||||
|
||||
To reduce build time due to unintended Homebrew updates, set the `HOMEBREW_NO_AUTO_UPDATE` variable in `.gitlab-ci.yml` :
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
```
|
||||
|
|
|
|||
|
|
@ -961,20 +961,20 @@ To open either project or group settings:
|
|||
|
||||
```markdown
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or group.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. Select **Settings > CI/CD**.
|
||||
1. Expand **General pipelines**.
|
||||
```
|
||||
|
||||
To create a project:
|
||||
|
||||
```markdown
|
||||
1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
|
||||
1. On the left sidebar, at the top, select **Create new...** (**{plus}**) and **New project/repository**.
|
||||
```
|
||||
|
||||
To create a group:
|
||||
|
||||
```markdown
|
||||
1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New group**.
|
||||
1. On the left sidebar, at the top, select **Create new...** (**{plus}**) and **New group**.
|
||||
```
|
||||
|
||||
To open the Admin Area:
|
||||
|
|
@ -999,6 +999,20 @@ To save the selection in some dropdown lists:
|
|||
1. Select any area outside the dropdown list.
|
||||
```
|
||||
|
||||
To view all your projects:
|
||||
|
||||
```markdown
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **View all your projects**.
|
||||
```
|
||||
|
||||
To view all your groups:
|
||||
|
||||
```markdown
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **View all your groups**.
|
||||
```
|
||||
|
||||
### Optional steps
|
||||
|
||||
If a step is optional, start the step with the word `Optional` followed by a period.
|
||||
|
|
@ -1029,7 +1043,7 @@ Use the phrase **Complete the fields**.
|
|||
For example:
|
||||
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. On the left sidebar, select **Settings > Repository**.
|
||||
1. Select **Settings > Repository**.
|
||||
1. Expand **Push rules**.
|
||||
1. Complete the fields.
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ The following migration helpers are available in `ee/app/workers/concerns/elasti
|
|||
|
||||
Backfills a specific field in an index. In most cases, the mapping for the field should already be added.
|
||||
|
||||
Requires the `index_name` and `field_name` methods.
|
||||
Requires the `index_name` and `field_name` methods to backfill a single field.
|
||||
|
||||
```ruby
|
||||
class MigrationName < Elastic::Migration
|
||||
|
|
@ -72,6 +72,24 @@ class MigrationName < Elastic::Migration
|
|||
end
|
||||
```
|
||||
|
||||
Requires the `index_name` and `field_names` methods to backfill multiple fields if any field is null.
|
||||
|
||||
```ruby
|
||||
class MigrationName < Elastic::Migration
|
||||
include Elastic::MigrationBackfillHelper
|
||||
|
||||
private
|
||||
|
||||
def index_name
|
||||
Issue.__elasticsearch__.index_name
|
||||
end
|
||||
|
||||
def field_names
|
||||
%w[schema_version visibility_level]
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### `Elastic::MigrationUpdateMappingsHelper`
|
||||
|
||||
Updates a mapping in an index by calling `put_mapping` with the mapping specified.
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../organization/index.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../organization/index.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -25,7 +25,7 @@ If you are unfamiliar with the command line, use the
|
|||
<!-- Original source for this list: doc/user/project/repository/web_editor.md#upload-a-file -->
|
||||
<!-- For why we duplicated the info, see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111072#note_1267429478 -->
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. From the project dashboard or repository, next to the branch name, select the plus icon (**{plus}**).
|
||||
1. From the dropdown list, select **Upload file**.
|
||||
1. Complete the fields. To create a merge request with the uploaded file, ensure the **Start a new merge request with these changes** toggle is turned on.
|
||||
|
|
|
|||
|
|
@ -248,7 +248,8 @@ in this section whenever you need to update GitLab.
|
|||
|
||||
To determine the version of GitLab you're currently running:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Overview > Dashboard**.
|
||||
1. Find the version under the **Components** table.
|
||||
|
||||
|
|
|
|||
|
|
@ -329,7 +329,8 @@ To prepare the new server:
|
|||
```
|
||||
|
||||
1. Disable periodic background jobs:
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Monitoring > Background Jobs**.
|
||||
1. Under the Sidekiq dashboard, select **Cron** tab and then
|
||||
**Disable All**.
|
||||
|
|
@ -409,7 +410,8 @@ To prepare the new server:
|
|||
|
||||
1. [Restore the GitLab backup](#restore-gitlab).
|
||||
1. Verify that the Redis database restored correctly:
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Monitoring > Background Jobs**.
|
||||
1. Under the Sidekiq dashboard, verify that the numbers
|
||||
match with what was shown on the old server.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ web interface.
|
|||
|
||||
## System hooks
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **System hooks**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **System Hooks**.
|
||||
|
||||
In a typical hardened environment, internal information is not transmitted or stored
|
||||
outside of the system. For an offline environment system, this is
|
||||
|
|
@ -32,8 +33,9 @@ encouraged for communications through system hooks.
|
|||
|
||||
## Push rules
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Push rules**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Push Rules**.
|
||||
|
||||
Ensure that the following items are selected:
|
||||
|
||||
|
|
@ -46,8 +48,9 @@ The adjustments help limit pushes to established and authorized users.
|
|||
|
||||
## Deploy keys
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Deploy keys**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Deploy Keys**.
|
||||
|
||||
Public deploy keys at are used to give read or read/write access to
|
||||
**all** projects on the instance, and are intended for remote automation to access
|
||||
|
|
@ -58,9 +61,9 @@ the documentation on [deploy keys](../user/project/deploy_keys/index.md) and
|
|||
|
||||
## General
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings**.
|
||||
1. Select **General**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
|
||||
Hardening adjustments can be made in 4 sections.
|
||||
|
||||
|
|
@ -177,9 +180,9 @@ For more detailed information, see
|
|||
|
||||
## Integrations
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings**.
|
||||
1. Select **Integrations**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Integrations**.
|
||||
|
||||
In general, as long as administrators control and monitor usage, integrations
|
||||
are fine in a hardened environment. Be cautious about integrations that allow
|
||||
|
|
@ -189,9 +192,9 @@ process or authenticated user.
|
|||
|
||||
## Metrics and profiling
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings**.
|
||||
1. Under **Integrations**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Metrics and profiling**.
|
||||
|
||||
The main focus for hardening is **Usage statistics**:
|
||||
|
||||
|
|
@ -207,9 +210,9 @@ help you make an informed decision, see
|
|||
|
||||
## Network
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings**.
|
||||
1. Under **Network**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Network**.
|
||||
|
||||
For any setting that enables rate limiting, make sure it is selected. Default values
|
||||
should be fine. Additionally there are numerous settings that enable access, and all
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ The user password length is set to a minimum of 8 characters by default.
|
|||
|
||||
To change the minimum password length using GitLab UI:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General** and expand **Sign-up restrictions**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Sign-up restrictions**.
|
||||
1. Enter a **Minimum password length** value greater than or equal to `8`.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ The user's new password must meet all [password requirements](../user/profile/us
|
|||
|
||||
To reset a user's password in the UI:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Overview > Users**.
|
||||
1. For the user whose password you want to update, select **Edit** (**{pencil-square}**).
|
||||
1. For the user whose password you want to update, select **Edit**.
|
||||
1. In the **Password** area, type a password and password confirmation.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ limit the allowed SSH key algorithms.
|
|||
GitLab allows you to restrict the allowed SSH key technology as well as specify
|
||||
the minimum key length for each technology:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > General** .
|
||||
1. Expand the **Visibility and access controls** section:
|
||||
|
||||

|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ cannot leave the 2FA configuration area at `/-/profile/two_factor_auth`.
|
|||
|
||||
To enable 2FA for all users:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand the **Sign-in restrictions** section, where you can configure both.
|
||||
|
||||
If you want 2FA enforcement to take effect during the next sign-in attempt,
|
||||
|
|
@ -55,8 +56,8 @@ Prerequisites:
|
|||
|
||||
To enforce 2FA only for certain groups:
|
||||
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Permissions and group features**.
|
||||
1. Select **All users in this group must set up two-factor authentication**.
|
||||
1. Select **Save changes**.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ If 2FA is enabled, users are locked after five failed sign-in attempts within 10
|
|||
|
||||
## Unlock a user from the Admin Area
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Overview > Users**.
|
||||
1. Use the search bar to find the locked user.
|
||||
1. From the **User administration** dropdown list, select **Unlock**.
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ GitLab can be configured to require confirmation of a user's email address when
|
|||
the user signs up. When this setting is enabled, the user is unable to sign in until
|
||||
they confirm their email address.
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
|
||||
1. Expand the **Sign-up restrictions** section and look for the **Email confirmation settings** options.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Sign-up restrictions** and look for the **Email confirmation settings** options.
|
||||
|
||||
## Confirmation token expiry
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ Prerequisite:
|
|||
|
||||
To configure authentication settings for all media files:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Visibility, project features, permissions**.
|
||||
1. Scroll to **Project visibility** and select **Require authentication to view media files**.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ To prevent exploitation of insecure internal web services, all webhook and integ
|
|||
|
||||
To allow access to these addresses:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Network**.
|
||||
1. Expand **Outbound requests**.
|
||||
1. Select the **Allow requests to the local network from webhooks and integrations** checkbox.
|
||||
|
|
@ -63,7 +64,8 @@ Prerequisite:
|
|||
|
||||
[System hooks](../administration/system_hooks.md) can make requests to the local network by default. To prevent system hook requests to the local network:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Network**.
|
||||
1. Expand **Outbound requests**.
|
||||
1. Clear the **Allow requests to the local network from system hooks** checkbox.
|
||||
|
|
@ -78,7 +80,8 @@ Prerequisite:
|
|||
|
||||
To filter requests by blocking many requests:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Network**.
|
||||
1. Expand **Outbound requests**.
|
||||
1. Select the **Block all requests, except for IP addresses, IP ranges, and domain names defined in the allowlist** checkbox.
|
||||
|
|
@ -103,7 +106,8 @@ Prerequisite:
|
|||
|
||||
To allow outbound requests to certain IP addresses and domains:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
|
||||
1. Select **Admin Area**.
|
||||
1. On the left sidebar, select **Settings > Network**.
|
||||
1. Expand **Outbound requests**.
|
||||
1. In **Local IP addresses and domain names that hooks and integrations can access**, enter your IP addresses and domains.
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ While the above approach is recommended for most instances, Sidekiq can also be
|
|||
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. Registration tokens, and support for certain configuration arguments,
|
||||
will be removed in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](../ci/runners/new_creation_workflow.md).
|
||||
will start returning the HTTP `410 Gone` status code in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](../ci/runners/new_creation_workflow.md).
|
||||
|
||||
The configuration arguments disabled for authentication tokens are:
|
||||
|
||||
|
|
@ -576,7 +576,7 @@ we'll be introducing support in [this epic](https://gitlab.com/groups/gitlab-org
|
|||
</div>
|
||||
|
||||
The support for runner registration tokens is deprecated. As a consequence, the REST API endpoints to reset a registration token are also deprecated and will
|
||||
be removed in GitLab 17.0.
|
||||
return the HTTP `410 Gone` status code in GitLab 17.0.
|
||||
The deprecated endpoints are:
|
||||
|
||||
- `POST /runners/reset_registration_token`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
---
|
||||
stage: Analyze
|
||||
group: Product Analytics
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Analytics dashboards (Experiment) **(ULTIMATE)**
|
||||
|
||||
> Introduced in GitLab 15.9 as an [Experiment](../../policy/experiment-beta-support.md#experiment) feature [with a flag](../../administration/feature_flags.md) named `combined_analytics_dashboards`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `combined_analytics_dashboards`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
## Dashboards
|
||||
|
||||
Each project can have an unlimited number of dashboards, only limited by the instances [repository size limits](../project/repository/reducing_the_repo_size_using_git.md#storage-limits).
|
||||
These dashboards are defined using the GitLab YAML schema, and stored in the `.gitlab/analytics/dashboards/` directory of a project repository.
|
||||
The dashboard file name and containing directory should be the same, for example `my_dashboard/my_dashboard.yaml`. For more information see [defining a dashboard](#define-a-dashboard).
|
||||
Each dashboard can reference one or more [visualizations](#define-a-chart-visualization), which are shared across dashboards.
|
||||
|
||||
Project maintainers can enforce approval rules on dashboard changes using features such as [code owners](../project/codeowners/index.md) and [approval rules](../project/merge_requests/approvals/rules.md).
|
||||
Your dashboard files are versioned in source control with the rest of a project's code.
|
||||
|
||||
### Data sources
|
||||
|
||||
A data source is a connection to a database or collection of data which can be used by your dashboard
|
||||
filters and visualizations to query and retrieve results.
|
||||
|
||||
The following data sources are configured for analytics dashboards:
|
||||
|
||||
- [Product analytics](../product_analytics/index.md)
|
||||
|
||||
### View project dashboards
|
||||
|
||||
To view a list of dashboards for a project:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. From the list of available dashboards, select the dashboard you want to view.
|
||||
|
||||
### Change the location of group dashboards
|
||||
|
||||
NOTE:
|
||||
This feature will be connected to group-level dashboards as part of [issue #411572](https://gitlab.com/gitlab-org/gitlab/-/issues/411572).
|
||||
|
||||
To change the location of a group's dashboards:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find the project you want to store your dashboard files in.
|
||||
The project must belong to the group for which you create the dashboards.
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Analytics**.
|
||||
1. In the **Analytics Dashboards** section, select your dashboard files project.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Change the location of project dashboards
|
||||
|
||||
Dashboards are usually defined in the project where the analytics data is being retrieved from.
|
||||
However, you can also have a separate project for dashboards.
|
||||
This is recommended if you want to enforce specific access rules to the dashboard definitions or share dashboards across multiple projects.
|
||||
|
||||
NOTE:
|
||||
You can share dashboards only between projects that are located in the same group.
|
||||
|
||||
To change the location of project dashboards:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find or create the project to store your dashboard files.
|
||||
1. On the top bar, select **Main menu > Projects** and find the analytics project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Analytics**.
|
||||
1. In the **Analytics Dashboards** section, select your dashboard files project.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Define a dashboard
|
||||
|
||||
To define a dashboard:
|
||||
|
||||
1. In `.gitlab/analytics/dashboards/`, create a directory named like the dashboard.
|
||||
|
||||
Each dashboard should have its own directory.
|
||||
1. In the new directory, create a `.yaml` file with the same name as the directory, for example `.gitlab/analytics/dashboards/my_dashboard/my_dashboard.yaml`.
|
||||
|
||||
This file contains the dashboard definition. It must conform to the JSON schema defined in `ee/app/validators/json_schemas/analytics_dashboard.json`.
|
||||
1. Optional. To create new visualizations to add to your dashboard see [defining a chart visualization](#define-a-chart-visualization).
|
||||
|
||||
For [example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/analytics/product_analytics/dashboards/audience.yaml), if you want to create three dashboards (Conversion funnels, Demographic breakdown, and North star metrics)
|
||||
and one visualization (line chart) that applies to all dashboards, the file structure would be:
|
||||
|
||||
```plaintext
|
||||
.gitlab/analytics/dashboards
|
||||
├── conversion_funnels
|
||||
│ └── conversion_funnels.yaml
|
||||
├── demographic_breakdown
|
||||
│ └── demographic_breakdown.yaml
|
||||
├── north_star_metrics
|
||||
| └── north_star_metrics.yaml
|
||||
├── visualizations
|
||||
│ └── example_line_chart.yaml
|
||||
```
|
||||
|
||||
### Define a chart visualization
|
||||
|
||||
You can define different charts, and add visualization options to some of them:
|
||||
|
||||
- Line chart, with the options listed in the [ECharts documentation](https://echarts.apache.org/en/option.html).
|
||||
- Column chart, with the options listed in the [ECharts documentation](https://echarts.apache.org/en/option.html).
|
||||
- Data table, with the only option to render `links` (array of objects, each with `text` and `href` properties to specify the dimensions to be used in links). See [example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/analytics_visualization.json?ref_type=heads#L112)).
|
||||
- Single stat, with the only option to set `decimalPlaces` (number, default value is 0).
|
||||
|
||||
To define a chart for your dashboards:
|
||||
|
||||
1. In the `.gitlab/analytics/dashboards/visualizations/` directory, create a `.yaml` file.
|
||||
The filename should be descriptive of the visualization it defines.
|
||||
1. In the `.yaml` file, define the visualization configuration, according to the schema in
|
||||
`ee/app/validators/json_schemas/analytics_visualization.json`.
|
||||
|
||||
For [example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/analytics/product_analytics/visualizations/events_over_time.yaml), to create a line chart that illustrates event count over time, in the `visualizations` folder
|
||||
create a `line_chart.yaml` file with the following required fields:
|
||||
|
||||
- version
|
||||
- type
|
||||
- data
|
||||
- options
|
||||
|
||||
## Dashboards designer
|
||||
|
||||
> Introduced in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `combined_analytics_dashboards_editor`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `combined_analytics_dashboards_editor`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
NOTE:
|
||||
This feature does not work in conjunction with the `product_analytics_snowplow_support` feature flag.
|
||||
|
||||
You can use the dashboards designer to:
|
||||
|
||||
- Create custom dashboards
|
||||
- Rename custom dashboards
|
||||
- Add visualizations to new and existing custom dashboards
|
||||
- Resize or move panels within custom dashboards
|
||||
|
||||
You cannot edit the built-in dashboards labeled as `By GitLab`.
|
||||
To edit these dashboards you should create a new custom dashboard which uses the same visualizations.
|
||||
|
||||
### Create a custom dashboard
|
||||
|
||||
To create a custom dashboard:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. Select **New dashboard**.
|
||||
1. In the **New dashboard** input, enter the name of the dashboard.
|
||||
1. From the **Add visualizations** list on the right, select the visualizations to add to the dashboard.
|
||||
1. Optional. Drag or resize the selected panel how you prefer.
|
||||
1. Select **Save**.
|
||||
|
||||
### Edit a custom dashboard
|
||||
|
||||
You can edit your custom dashboard's title and add or resize visualizations within the dashboard designer.
|
||||
|
||||
To edit an existing custom dashboard:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. From the list of available dashboards, select a custom dashboard (one without the `By GitLab` label) you want to edit.
|
||||
1. Select **Edit**.
|
||||
1. Optional. Change the title of the dashboard.
|
||||
1. Optional. From the **Add visualizations** list on the right, select other visualizations to add to the dashboard.
|
||||
1. Optional. In the dashboard, select a panel and drag or resize it how you prefer.
|
||||
1. Select **Save**.
|
||||
|
|
@ -33,6 +33,8 @@ GitLab provides several analytics features at the group level. Some of these fea
|
|||
|
||||
You can use GitLab to review analytics at the project level. Some of these features require you to use a higher tier than GitLab Free.
|
||||
|
||||
- [Analytics dashboards](analytics_dashboards.md), enabled with the `combined_analytics_dashboards_editor`
|
||||
[feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development)
|
||||
- [Application Security](../application_security/security_dashboard/index.md)
|
||||
- [CI/CD & DORA](ci_cd_analytics.md)
|
||||
- [Code Review](code_review_analytics.md)
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: '../terraform_module_registry/index.md'
|
||||
remove_date: '2023-06-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](../terraform_module_registry/index.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2023-06-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -83,6 +83,22 @@ Prerequisite:
|
|||
1. Select **Enable product analytics** and enter the configuration values.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Project-level settings
|
||||
|
||||
You can override the instance-level settings defined by the administrator on a per-project basis. This allows you to
|
||||
have a different configured product analytics instance for your project.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Product analytics must be enabled at the instance-level.
|
||||
- You must have at least the Maintainer role for the project or group the project belongs to.
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Product Analytics**.
|
||||
1. In the **Connect to your instance** section, enter the configuration values.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Product analytics dashboards
|
||||
|
||||
> - Introduced in GitLab 15.5 behind the [feature flag](../../administration/feature_flags.md) named `product_analytics_internal_preview`. Disabled by default.
|
||||
|
|
@ -93,129 +109,12 @@ On self-managed GitLab, by default this feature is not available. To make it ava
|
|||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
Each project can have an unlimited number of dashboards.
|
||||
These dashboards are defined using the GitLab YAML schema, and stored in the `.gitlab/analytics/dashboards/` directory of a project repository.
|
||||
The name of the file is the name of the dashboard.
|
||||
Each dashboard can contain one or more visualizations (charts), which are shared across dashboards.
|
||||
Product analytics dashboards are a subset of dashboards under [Analytics dashboards](../analytics/analytics_dashboards.md).
|
||||
|
||||
Project maintainers can enforce approval rules on dashboard changes using features such as code owners and approval rules.
|
||||
Dashboards are versioned in source control with the rest of a project's code.
|
||||
|
||||
### View project dashboards
|
||||
|
||||
> Introduced in GitLab 15.9 behind the [feature flag](../../administration/feature_flags.md) named `combined_analytics_dashboards`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `combined_analytics_dashboards`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
To view a list of product analytics dashboards for a project:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. From the list of available dashboards, select the dashboard you want to view.
|
||||
|
||||
### Define a dashboard
|
||||
|
||||
To define a dashboard:
|
||||
|
||||
1. In `.gitlab/analytics/dashboards/`, create a directory named like the dashboard.
|
||||
|
||||
Each dashboard should have its own directory.
|
||||
1. In the new directory, create a `.yaml` file with the same name as the directory.
|
||||
|
||||
This file contains the dashboard definition. It must conform to the JSON schema defined in `ee/app/validators/json_schemas/product_analytics_dashboard.json`.
|
||||
1. In the `.gitlab/analytics/dashboards/visualizations/` directory, create a `.yaml` file.
|
||||
|
||||
This file defines the visualization type for the dashboard. It must conform to the schema in
|
||||
`ee/app/validators/json_schemas/product_analytics_visualization.json`.
|
||||
|
||||
For example, if you want to create three dashboards (Conversion funnels, Demographic breakdown, and North star metrics)
|
||||
and one visualization (line chart) that applies to all dashboards, the file structure would be:
|
||||
|
||||
```plaintext
|
||||
.gitlab/analytics/dashboards
|
||||
├── conversion_funnels
|
||||
│ └── conversion_funnels.yaml
|
||||
├── demographic_breakdown
|
||||
│ └── demographic_breakdown.yaml
|
||||
├── north_star_metrics
|
||||
| └── north_star_metrics.yaml
|
||||
├── visualizations
|
||||
│ └── example_line_chart.yaml
|
||||
```
|
||||
|
||||
### Define a chart visualization
|
||||
|
||||
You can define different charts, and add visualization options to some of them:
|
||||
|
||||
- Line chart, with the options listed in the [ECharts documentation](https://echarts.apache.org/en/option.html).
|
||||
- Column chart, with the options listed in the [ECharts documentation](https://echarts.apache.org/en/option.html).
|
||||
- Data table, with the only option to render `links` (array of objects, each with `text` and `href` properties to specify the dimensions to be used in links). See [example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/analytics_visualization.json?ref_type=heads#L112)).
|
||||
- Single stat, with the only option to set `decimalPlaces` (number, default value is 0).
|
||||
|
||||
To define a chart for your dashboards:
|
||||
|
||||
1. In the `.gitlab/product_analytics/dashboards/visualizations/` directory, create a `.yaml` file.
|
||||
The filename should be descriptive of the visualization it defines.
|
||||
1. In the `.yaml` file, define the visualization options, according to the schema in
|
||||
`ee/app/validators/json_schemas/analytics_visualization.json`.
|
||||
|
||||
For [example](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/gl_dashboards/product_analytics/visualizations/events_over_time.json), to create a line chart that illustrates event count over time, in the `visualizations` folder
|
||||
create a `line_chart.yaml` file with the following required fields:
|
||||
|
||||
- version
|
||||
- title
|
||||
- type
|
||||
- data
|
||||
- options
|
||||
|
||||
## Dashboards editor
|
||||
|
||||
> Introduced in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `combined_analytics_dashboards_editor`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `combined_analytics_dashboards_editor`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
NOTE:
|
||||
This feature does not work in conjunction with the `product_analytics_snowplow_support` feature flag.
|
||||
|
||||
You can use the dashboards editor to:
|
||||
|
||||
- Create dashboards
|
||||
- Rename dashboards
|
||||
- Add visualizations to new and existing dashboards
|
||||
- Resize or move panels within dashboards
|
||||
|
||||
### Create a dashboard
|
||||
|
||||
To create a dashboard:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. Select **New dashboard**.
|
||||
1. In the **New dashboard** input, enter the name of the dashboard.
|
||||
1. From the **Add visualizations** list on the right, select the visualizations to add to the dashboard.
|
||||
1. Optional. Drag or resize the selected visualizations how you prefer.
|
||||
1. Select **Save**.
|
||||
|
||||
### Edit a dashboard
|
||||
|
||||
You can rename your created dashboards and add or resize visualizations within them.
|
||||
|
||||
To edit an existing dashboard:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Analytics > Dashboards**.
|
||||
1. From the list of available dashboards, select the dashboard you want to edit.
|
||||
1. Select **Edit**.
|
||||
1. Optional. Change the name of the dashboard.
|
||||
1. Optional. From the **Add visualizations** list on the right, select other visualizations to add to the dashboard.
|
||||
1. Optional. In the dashboard, select a visualization and drag or resize it how you prefer.
|
||||
1. Select **Save**.
|
||||
Specifically product analytics dashboards and visualizations make use of the `cube_analytics` data type.
|
||||
The `cube_analytics` data type connects to the Cube instance defined when [product analytics was enabled](#enable-product-analytics).
|
||||
All filters and queries are sent to the Cube instance and the returned data is processed by the
|
||||
product analytics data source to be rendered by the appropriate visualizations.
|
||||
|
||||
## Funnel analysis
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,36 @@ mutation {
|
|||
}
|
||||
```
|
||||
|
||||
## Delete an awarded achievement
|
||||
|
||||
If you awarded an achievement to a user by mistake, you can delete it.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have the Owner role for the namespace.
|
||||
|
||||
To delete an awarded achievement, call the [`userAchievementsDelete` GraphQL mutation](../../api/graphql/reference/index.md#mutationuserachievementsdelete).
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
userAchievementsDelete(input: {
|
||||
userAchievementId: "gid://gitlab/Achievements::UserAchievement/<user achievement id>" }) {
|
||||
userAchievement {
|
||||
id
|
||||
achievement {
|
||||
id
|
||||
name
|
||||
}
|
||||
user {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Delete an achievement
|
||||
|
||||
If you consider you no longer need an achievement, you can delete it.
|
||||
|
|
|
|||
|
|
@ -86,7 +86,12 @@ At any time, you can revoke a personal access token.
|
|||
|
||||
## View the last time a token was used
|
||||
|
||||
Token usage information is updated every 24 hours. GitLab considers a token used when the token is used to:
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/414945) in GitLab 16.1 [with a flag](../../administration/feature_flags.md) named `update_personal_access_token_usage_information_every_10_minutes`. Enabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `update_personal_access_token_usage_information_every_10_minutes`. On GitLab.com, this feature is available.
|
||||
|
||||
Token usage information is updated every 10 minutes. GitLab considers a token used when the token is used to:
|
||||
|
||||
- Authenticate with the [REST](../../api/rest/index.md) or [GraphQL](../../api/graphql/index.md) APIs.
|
||||
- Perform a Git operation.
|
||||
|
|
|
|||
|
|
@ -130,8 +130,8 @@ If you find that you have to add the same badges to several projects, you may wa
|
|||
|
||||
To add a new badge to a project:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Badges**.
|
||||
1. Under **Link**, enter the URL that the badges should point to.
|
||||
1. Under **Badge image URL**, enter the URL of the image that should be displayed.
|
||||
|
|
@ -151,8 +151,8 @@ A common project badge presents the GitLab CI pipeline status.
|
|||
|
||||
To add this badge to a project:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Badges**.
|
||||
1. Under **Name**, enter _Pipeline Status_.
|
||||
1. Under **Link**, enter the following URL:
|
||||
|
|
@ -180,8 +180,8 @@ If you need individual badges for each project, either:
|
|||
|
||||
To add a new badge to a group:
|
||||
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Badges**.
|
||||
1. Under "Link", enter the URL that the badges should point to and under
|
||||
"Badge image URL" the URL of the image that should be displayed.
|
||||
|
|
@ -202,8 +202,8 @@ Badges associated with a group can be edited or deleted only at the [group level
|
|||
You can view the exact link for your badges.
|
||||
Then you can use the link to embed the badge in your HTML or Markdown pages.
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > CI/CD**.
|
||||
1. Expand **General pipelines**.
|
||||
1. In the **Pipeline status**, **Coverage report**, or **Latest release** sections, view the URLs for the images.
|
||||
|
||||
|
|
@ -269,8 +269,9 @@ https://gitlab.example.com/<project_path>/-/raw/<default_branch>/my-image.svg
|
|||
|
||||
To add a new badge with a custom image to a group or project:
|
||||
|
||||
1. On the top bar, select **Main menu** and find your group or project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project or
|
||||
group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Badges**.
|
||||
1. Under **Name**, enter the name for the badge.
|
||||
1. Under **Link**, enter the URL that the badge should point to.
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ directory in your repository.
|
|||
|
||||
To create an issue description template:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Code > Repository**.
|
||||
1. Next to the default branch, select **{plus}**.
|
||||
1. Select **New file**.
|
||||
1. Next to the default branch, in the **File name** text box, enter `.gitlab/issue_templates/mytemplate.md`,
|
||||
|
|
@ -52,8 +52,8 @@ that depend on the contents of commit messages and branch names.
|
|||
|
||||
To create a merge request description template for a project:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Code > Repository**.
|
||||
1. Next to the default branch, select **{plus}**.
|
||||
1. Select **New file**.
|
||||
1. Next to the default branch, in the **File name** text box, enter `.gitlab/merge_request_templates/mytemplate.md`,
|
||||
|
|
@ -124,8 +124,8 @@ As a result, you can use the same templates in issues and merge requests in all
|
|||
|
||||
To re-use templates [you've created](../project/description_templates.md#create-an-issue-template):
|
||||
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Templates**.
|
||||
1. From the dropdown list, select your template project as the template repository at group level.
|
||||
1. Select **Save changes**.
|
||||
|
|
@ -155,8 +155,8 @@ To set a default description template for merge requests, either:
|
|||
This [doesn't overwrite](#priority-of-default-description-templates) the default template if one has been set in the project settings.
|
||||
- Users on GitLab Premium and Ultimate: set the default template in project settings:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > Merge requests**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > Merge requests**.
|
||||
1. In the **Default description template for merge requests** section, fill in the text area.
|
||||
1. Select **Save changes**.
|
||||
|
||||
|
|
@ -167,8 +167,8 @@ To set a default description template for issues, either:
|
|||
This [doesn't overwrite](#priority-of-default-description-templates) the default template if one has been set in the project settings.
|
||||
- Users on GitLab Premium and Ultimate: set the default template in project settings:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Default description template for issues**.
|
||||
1. Fill in the text area.
|
||||
1. Select **Save changes**.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Admin
|
||||
class Migrations < ::API::Base
|
||||
feature_category :database
|
||||
urgency :low
|
||||
|
||||
before do
|
||||
authenticated_as_admin!
|
||||
end
|
||||
|
||||
namespace 'admin' do
|
||||
resources 'migrations/:timestamp/mark' do
|
||||
desc 'Mark the migration as successfully executed' do
|
||||
success [
|
||||
{ code: 201, message: '201 Created' }
|
||||
]
|
||||
failure [
|
||||
{ code: 401, message: '401 Unauthorized' },
|
||||
{ code: 403, message: '403 Forbidden' },
|
||||
{ code: 404, message: '404 Not found' },
|
||||
{ code: 422, message: 'You can mark only pending migrations' }
|
||||
]
|
||||
tags %w[migrations]
|
||||
end
|
||||
params do
|
||||
optional :database,
|
||||
type: String,
|
||||
values: Gitlab::Database.all_database_names,
|
||||
desc: 'The name of the database',
|
||||
default: 'main'
|
||||
requires :timestamp,
|
||||
type: Integer,
|
||||
desc: 'The migration version timestamp'
|
||||
end
|
||||
post do
|
||||
response = Database::MarkMigrationService.new(
|
||||
connection: base_model.connection,
|
||||
version: params[:timestamp]
|
||||
).execute
|
||||
|
||||
if response.success?
|
||||
created!
|
||||
elsif response.reason == :not_found
|
||||
not_found!
|
||||
else
|
||||
render_api_error!('You can mark only pending migrations', 422)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
helpers do
|
||||
def base_model
|
||||
database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME
|
||||
@base_model ||= Gitlab::Database.database_base_models[database]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -182,6 +182,7 @@ module API
|
|||
mount ::API::Admin::BatchedBackgroundMigrations
|
||||
mount ::API::Admin::Ci::Variables
|
||||
mount ::API::Admin::InstanceClusters
|
||||
mount ::API::Admin::Migrations
|
||||
mount ::API::Admin::PlanLimits
|
||||
mount ::API::AlertManagementAlerts
|
||||
mount ::API::Appearance
|
||||
|
|
@ -327,7 +328,6 @@ module API
|
|||
mount ::API::Ci::PipelineSchedules
|
||||
mount ::API::Ci::SecureFiles
|
||||
mount ::API::Discussions
|
||||
mount ::API::ErrorTracking::Collector
|
||||
mount ::API::GroupBoards
|
||||
mount ::API::GroupLabels
|
||||
mount ::API::GroupMilestones
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module API
|
|||
expose :id, documentation: { type: 'integer', example: 1 }
|
||||
expose :active, documentation: { type: 'boolean' }
|
||||
expose :public_key, documentation: { type: 'string', example: 'glet_aa77551d849c083f76d0bc545ed053a3' }
|
||||
expose :sentry_dsn, documentation: { type: 'string', example: 'https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5' }
|
||||
expose :sentry_dsn, documentation: { type: 'string', example: 'https://glet_aa77551d849c083f76d0bc545ed053a3@example.com/errortracking/api/v1/projects/5' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,156 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
# This API is responsible for collecting error tracking information
|
||||
# from sentry client. It allows us to use GitLab as an alternative to
|
||||
# sentry backend. For more details see https://gitlab.com/gitlab-org/gitlab/-/issues/329596.
|
||||
class ErrorTracking::Collector < ::API::Base
|
||||
feature_category :error_tracking
|
||||
urgency :low
|
||||
|
||||
content_type :envelope, 'application/x-sentry-envelope'
|
||||
content_type :json, 'application/json'
|
||||
content_type :txt, 'text/plain'
|
||||
default_format :envelope
|
||||
|
||||
rescue_from Gitlab::ErrorTracking::ErrorRepository::DatabaseError do |e|
|
||||
render_api_error!(e.message, 400)
|
||||
end
|
||||
|
||||
before do
|
||||
not_found!('Project') unless project
|
||||
not_found! unless feature_enabled?
|
||||
not_found! unless active_client_key?
|
||||
end
|
||||
|
||||
helpers do
|
||||
def project
|
||||
@project ||= find_project(params[:id])
|
||||
end
|
||||
|
||||
def feature_enabled?
|
||||
Feature.enabled?(:integrated_error_tracking, project) &&
|
||||
project.error_tracking_setting&.integrated_enabled?
|
||||
end
|
||||
|
||||
def find_client_key(public_key)
|
||||
return unless public_key.present?
|
||||
|
||||
project.error_tracking_client_keys.active.find_by_public_key(public_key)
|
||||
end
|
||||
|
||||
def active_client_key?
|
||||
public_key = extract_public_key
|
||||
|
||||
find_client_key(public_key)
|
||||
end
|
||||
|
||||
def extract_public_key
|
||||
# Some SDK send public_key as a param. In this case we don't need to parse headers.
|
||||
return params[:sentry_key] if params[:sentry_key].present?
|
||||
|
||||
begin
|
||||
::ErrorTracking::Collector::SentryAuthParser.parse(request)[:public_key]
|
||||
rescue StandardError
|
||||
bad_request!('Failed to parse sentry request')
|
||||
end
|
||||
end
|
||||
|
||||
def validate_payload(payload)
|
||||
unless ::ErrorTracking::Collector::PayloadValidator.new.valid?(payload)
|
||||
bad_request!('Unsupported sentry payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Submit error tracking event to the project as envelope' do
|
||||
detail 'This feature was introduced in GitLab 14.1.'
|
||||
end
|
||||
params do
|
||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
||||
end
|
||||
post 'error_tracking/collector/api/:id/envelope' do
|
||||
# There is a reason why we have such uncommon path.
|
||||
# We depend on a client side error tracking software which
|
||||
# modifies URL for its own reasons.
|
||||
#
|
||||
# When we give user a URL like this
|
||||
# HOST/api/v4/error_tracking/collector/123
|
||||
#
|
||||
# Then error tracking software will convert it like this:
|
||||
# HOST/api/v4/error_tracking/collector/api/123/envelope/
|
||||
|
||||
begin
|
||||
parsed_request = ::ErrorTracking::Collector::SentryRequestParser.parse(request)
|
||||
rescue StandardError
|
||||
bad_request!('Failed to parse sentry request')
|
||||
end
|
||||
|
||||
type = parsed_request[:request_type]
|
||||
|
||||
# Sentry sends 2 requests on each exception: transaction and event.
|
||||
# Everything else is not a desired behavior.
|
||||
unless type == 'transaction' || type == 'event'
|
||||
render_api_error!('400 Bad Request', 400)
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
# We don't have use for transaction request yet,
|
||||
# so we record only event one.
|
||||
if type == 'event'
|
||||
validate_payload(parsed_request[:event])
|
||||
|
||||
::ErrorTracking::CollectErrorService
|
||||
.new(project, nil, event: parsed_request[:event])
|
||||
.execute
|
||||
end
|
||||
|
||||
# Collector should never return any information back.
|
||||
# Because DSN and public key are designed for public use,
|
||||
# it is safe only for submission of new events.
|
||||
#
|
||||
# Some clients sdk require status 200 OK to work correctly.
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/343531.
|
||||
status 200
|
||||
end
|
||||
|
||||
desc 'Submit error tracking event to the project' do
|
||||
detail 'This feature was introduced in GitLab 14.1.'
|
||||
end
|
||||
params do
|
||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
||||
end
|
||||
post 'error_tracking/collector/api/:id/store' do
|
||||
# There is a reason why we have such uncommon path.
|
||||
# We depend on a client side error tracking software which
|
||||
# modifies URL for its own reasons.
|
||||
#
|
||||
# When we give user a URL like this
|
||||
# HOST/api/v4/error_tracking/collector/123
|
||||
#
|
||||
# Then error tracking software will convert it like this:
|
||||
# HOST/api/v4/error_tracking/collector/api/123/store/
|
||||
|
||||
begin
|
||||
parsed_body = Gitlab::Json.parse(request.body.read)
|
||||
rescue StandardError
|
||||
bad_request!('Failed to parse sentry request')
|
||||
end
|
||||
|
||||
validate_payload(parsed_body)
|
||||
|
||||
::ErrorTracking::CollectErrorService
|
||||
.new(project, nil, event: parsed_body)
|
||||
.execute
|
||||
|
||||
# Collector should never return any information back.
|
||||
# Because DSN and public key are designed for public use,
|
||||
# it is safe only for submission of new events.
|
||||
#
|
||||
# Some clients sdk require status 200 OK to work correctly.
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/343531.
|
||||
status 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -114,7 +114,6 @@ module Gitlab
|
|||
def known_event_entry
|
||||
<<~YML
|
||||
- name: #{event}
|
||||
aggregation: weekly
|
||||
YML
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::<%= class_name %>Metric do
|
||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::<%= class_name %>Metric, feature_category: :service_ping do
|
||||
let(:expected_value) { 1 }
|
||||
|
||||
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
module Gitlab
|
||||
module Middleware
|
||||
class CompressedJson
|
||||
COLLECTOR_PATH = '/api/v4/error_tracking/collector'
|
||||
INSTANCE_PACKAGES_PATH = %r{
|
||||
\A/api/v4/packages/npm/-/npm/v1/security/
|
||||
(?:(?:advisories/bulk)|(?:audits/quick))\z (?# end)
|
||||
|
|
@ -79,8 +78,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def match_path?(env)
|
||||
env['PATH_INFO'].start_with?((File.join(relative_url, COLLECTOR_PATH))) ||
|
||||
match_packages_path?(env)
|
||||
match_packages_path?(env)
|
||||
end
|
||||
|
||||
def match_packages_path?(env)
|
||||
|
|
|
|||
|
|
@ -3,18 +3,14 @@
|
|||
module Gitlab
|
||||
module UsageDataCounters
|
||||
module HLLRedisCounter
|
||||
DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH = 6.weeks
|
||||
DEFAULT_DAILY_KEY_EXPIRY_LENGTH = 29.days
|
||||
KEY_EXPIRY_LENGTH = 6.weeks
|
||||
REDIS_SLOT = 'hll_counters'
|
||||
|
||||
EventError = Class.new(StandardError)
|
||||
UnknownEvent = Class.new(EventError)
|
||||
UnknownAggregation = Class.new(EventError)
|
||||
AggregationMismatch = Class.new(EventError)
|
||||
InvalidContext = Class.new(EventError)
|
||||
|
||||
KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__)
|
||||
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
|
||||
|
||||
# Track event on entity_id
|
||||
# Increment a Redis HLL counter for unique event_name and entity_id
|
||||
|
|
@ -24,7 +20,6 @@ module Gitlab
|
|||
# Event example:
|
||||
#
|
||||
# - name: g_compliance_dashboard # Unique event name
|
||||
# aggregation: weekly # Aggregation level, keys are stored weekly
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
|
|
@ -63,8 +58,7 @@ module Gitlab
|
|||
# end_date - The end date of the time range.
|
||||
# context - Event context, plan level tracking. Available if set when tracking.
|
||||
def unique_events(event_names:, start_date:, end_date:, context: '')
|
||||
count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date, context: context) do |events|
|
||||
raise AggregationMismatch, events unless events_same_aggregation?(events)
|
||||
count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date, context: context) do
|
||||
raise InvalidContext if context.present? && !context.in?(valid_context_list)
|
||||
end
|
||||
end
|
||||
|
|
@ -78,9 +72,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def calculate_events_union(event_names:, start_date:, end_date:)
|
||||
count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date) do |events|
|
||||
raise AggregationMismatch, events unless events_same_aggregation?(events)
|
||||
end
|
||||
count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -94,12 +86,7 @@ module Gitlab
|
|||
return if event.blank?
|
||||
return unless Feature.enabled?(:redis_hll_tracking, type: :ops)
|
||||
|
||||
if event[:aggregation].to_sym == :daily
|
||||
weekly_event = event.dup.tap { |e| e['aggregation'] = 'weekly' }
|
||||
Gitlab::Redis::HLL.add(key: redis_key(weekly_event, time, context), value: values, expiry: expiry(weekly_event))
|
||||
end
|
||||
|
||||
Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: values, expiry: expiry(event))
|
||||
Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: values, expiry: KEY_EXPIRY_LENGTH)
|
||||
|
||||
rescue StandardError => e
|
||||
# Ignore any exceptions unless is dev or test env
|
||||
|
|
@ -117,25 +104,18 @@ module Gitlab
|
|||
|
||||
yield events if block_given?
|
||||
|
||||
aggregation = events.first[:aggregation]
|
||||
keys = keys_for_aggregation(events: events, start_date: start_date, end_date: end_date, context: context)
|
||||
|
||||
if Feature.disabled?(:revert_daily_hll_events_to_weekly_aggregation)
|
||||
aggregation = 'weekly'
|
||||
events = events.map { |e| e.merge(aggregation: 'weekly') }
|
||||
end
|
||||
|
||||
keys = keys_for_aggregation(aggregation, events: events, start_date: start_date, end_date: end_date, context: context)
|
||||
return FALLBACK unless keys.any?
|
||||
|
||||
redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
|
||||
end
|
||||
|
||||
def keys_for_aggregation(aggregation, events:, start_date:, end_date:, context: '')
|
||||
if aggregation.to_sym == :daily
|
||||
daily_redis_keys(events: events, start_date: start_date, end_date: end_date, context: context)
|
||||
else
|
||||
weekly_redis_keys(events: events, start_date: start_date, end_date: end_date, context: context)
|
||||
end
|
||||
def keys_for_aggregation(events:, start_date:, end_date:, context: '')
|
||||
end_date = end_date.end_of_week - 1.week
|
||||
(start_date.to_date..end_date.to_date).map do |date|
|
||||
events.map { |event| redis_key(event, date, context) }
|
||||
end.flatten.uniq
|
||||
end
|
||||
|
||||
def load_events(wildcard)
|
||||
|
|
@ -152,15 +132,6 @@ module Gitlab
|
|||
known_events.map { |event| event[:name] }
|
||||
end
|
||||
|
||||
def events_same_aggregation?(events)
|
||||
aggregation = events.first[:aggregation]
|
||||
events.all? { |event| event[:aggregation] == aggregation }
|
||||
end
|
||||
|
||||
def expiry(event)
|
||||
event[:aggregation].to_sym == :daily ? DEFAULT_DAILY_KEY_EXPIRY_LENGTH : DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH
|
||||
end
|
||||
|
||||
def event_for(event_name)
|
||||
known_events.find { |event| event[:name] == event_name.to_s }
|
||||
end
|
||||
|
|
@ -173,37 +144,14 @@ module Gitlab
|
|||
def redis_key(event, time, context = '')
|
||||
raise UnknownEvent, "Unknown event #{event[:name]}" unless known_events_names.include?(event[:name].to_s)
|
||||
|
||||
# ToDo: remove during https://gitlab.com/groups/gitlab-org/-/epics/9542 cleanup
|
||||
raise UnknownAggregation, "Use :daily or :weekly aggregation" unless ALLOWED_AGGREGATIONS.include?(event[:aggregation].to_sym)
|
||||
|
||||
key = "{#{REDIS_SLOT}}_#{event[:name]}"
|
||||
key = apply_time_aggregation(key, time, event)
|
||||
|
||||
year_week = time.strftime('%G-%V')
|
||||
key = "#{key}-#{year_week}"
|
||||
|
||||
key = "#{context}_#{key}" if context.present?
|
||||
key
|
||||
end
|
||||
|
||||
def apply_time_aggregation(key, time, event)
|
||||
if event[:aggregation].to_sym == :daily
|
||||
year_day = time.strftime('%G-%j')
|
||||
"#{year_day}-#{key}"
|
||||
else
|
||||
year_week = time.strftime('%G-%V')
|
||||
"#{key}-#{year_week}"
|
||||
end
|
||||
end
|
||||
|
||||
def daily_redis_keys(events:, start_date:, end_date:, context: '')
|
||||
(start_date.to_date..end_date.to_date).map do |date|
|
||||
events.map { |event| redis_key(event, date, context) }
|
||||
end.flatten
|
||||
end
|
||||
|
||||
def weekly_redis_keys(events:, start_date:, end_date:, context: '')
|
||||
end_date = end_date.end_of_week - 1.week
|
||||
(start_date.to_date..end_date.to_date).map do |date|
|
||||
events.map { |event| redis_key(event, date, context) }
|
||||
end.flatten.uniq
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,10 +45,7 @@ namespace :gitlab do
|
|||
events = event_pairs.each_with_object([]) do |(event_type, event_scope), events|
|
||||
Packages::Event::ORIGINATOR_TYPES.excluding(:guest).each do |originator_type|
|
||||
events_definition = Packages::Event.unique_counters_for(event_scope, event_type, originator_type).map do |event_name|
|
||||
{
|
||||
"name" => event_name,
|
||||
"aggregation" => "weekly"
|
||||
}
|
||||
{ "name" => event_name }
|
||||
end
|
||||
|
||||
events.concat(events_definition)
|
||||
|
|
|
|||
|
|
@ -85,12 +85,13 @@ namespace :gitlab do
|
|||
end
|
||||
end
|
||||
|
||||
# rubocop:disable Gitlab/NoCodeCoverageComment
|
||||
# :nocov: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/299453
|
||||
def ci_template_event(event_name)
|
||||
{
|
||||
'name' => event_name,
|
||||
'aggregation' => 'weekly'
|
||||
}
|
||||
{ 'name' => event_name }
|
||||
end
|
||||
# :nocov:
|
||||
# rubocop:enable Gitlab/NoCodeCoverageComment
|
||||
|
||||
def implicit_auto_devops_event(expanded_template_name)
|
||||
event_name = Gitlab::UsageDataCounters::CiTemplateUniqueCounter.ci_template_event_name(expanded_template_name, :auto_devops_source)
|
||||
|
|
|
|||
|
|
@ -39376,6 +39376,9 @@ msgstr ""
|
|||
msgid "Runners|An error has occurred fetching instructions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|An error occurred while creating the runner. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|An error occurred while deleting. Some runners may not have been deleted."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountFooMetric do
|
||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountFooMetric, feature_category: :service_ping do
|
||||
let(:expected_value) { 1 }
|
||||
|
||||
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
INSTANCE_TYPE,
|
||||
GROUP_TYPE,
|
||||
PROJECT_TYPE,
|
||||
I18N_CREATE_ERROR,
|
||||
} from '~/ci/runner/constants';
|
||||
import runnerCreateMutation from '~/ci/runner/graphql/new/runner_create.mutation.graphql';
|
||||
import { captureException } from '~/ci/runner/sentry_utils';
|
||||
|
|
@ -188,5 +189,37 @@ describe('RunnerCreateForm', () => {
|
|||
expect(captureException).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when no runner information is returned', () => {
|
||||
beforeEach(async () => {
|
||||
runnerCreateHandler.mockResolvedValue({
|
||||
data: {
|
||||
runnerCreate: {
|
||||
errors: [],
|
||||
runner: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
findForm().vm.$emit('submit', { preventDefault });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('emits "error" result', () => {
|
||||
expect(wrapper.emitted('error')[0]).toEqual([new TypeError(I18N_CREATE_ERROR)]);
|
||||
});
|
||||
|
||||
it('does not show a saving state', () => {
|
||||
expect(findSubmitBtn().props('loading')).toBe(false);
|
||||
});
|
||||
|
||||
it('reports error', () => {
|
||||
expect(captureException).toHaveBeenCalledTimes(1);
|
||||
expect(captureException).toHaveBeenCalledWith({
|
||||
component: 'RunnerCreateForm',
|
||||
error: new Error(I18N_CREATE_ERROR),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@ import { GlCollapse, GlSkeletonLoader, GlTableLite } from '@gitlab/ui';
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { __ } from '~/locale';
|
||||
import {
|
||||
shallowMountExtended,
|
||||
mountExtended,
|
||||
extendedWrapper,
|
||||
} from 'helpers/vue_test_utils_helper';
|
||||
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
import RunnerManagersDetail from '~/ci/runner/components/runner_managers_detail.vue';
|
||||
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import RunnerManagersTable from '~/ci/runner/components/runner_managers_table.vue';
|
||||
|
||||
import runnerManagersQuery from '~/ci/runner/graphql/show/runner_managers.query.graphql';
|
||||
import { runnerData, runnerManagersData } from '../mock_data';
|
||||
|
|
@ -33,8 +29,7 @@ describe('RunnerJobs', () => {
|
|||
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
|
||||
|
||||
const findCollapse = () => wrapper.findComponent(GlCollapse);
|
||||
const findRows = () => wrapper.findAll('tbody tr');
|
||||
const findCell = ({ field, i }) => extendedWrapper(findRows().at(i)).findByTestId(`td-${field}`);
|
||||
const findRunnerManagersTable = () => wrapper.findComponent(RunnerManagersTable);
|
||||
|
||||
const createComponent = ({ props, mountFn = shallowMountExtended } = {}) => {
|
||||
wrapper = mountFn(RunnerManagersDetail, {
|
||||
|
|
@ -162,21 +157,7 @@ describe('RunnerJobs', () => {
|
|||
|
||||
it('shows rows', () => {
|
||||
expect(findCollapse().attributes('visible')).toBe('true');
|
||||
expect(findRows()).toHaveLength(mockRunnerManagers.length);
|
||||
});
|
||||
|
||||
it('shows system id', () => {
|
||||
expect(findCell({ field: 'systemId', i: 0 }).text()).toBe(mockRunnerManagers[0].systemId);
|
||||
expect(findCell({ field: 'systemId', i: 1 }).text()).toBe(mockRunnerManagers[1].systemId);
|
||||
});
|
||||
|
||||
it('shows contacted at', () => {
|
||||
expect(findCell({ field: 'contactedAt', i: 0 }).findComponent(TimeAgo).props('time')).toBe(
|
||||
mockRunnerManagers[0].contactedAt,
|
||||
);
|
||||
expect(findCell({ field: 'contactedAt', i: 1 }).findComponent(TimeAgo).props('time')).toBe(
|
||||
mockRunnerManagers[1].contactedAt,
|
||||
);
|
||||
expect(findRunnerManagersTable().props('items')).toEqual(mockRunnerManagers);
|
||||
});
|
||||
|
||||
it('collapses when clicked', async () => {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
import { GlTableLite } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { s__ } from '~/locale';
|
||||
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
|
||||
import RunnerManagersTable from '~/ci/runner/components/runner_managers_table.vue';
|
||||
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import { I18N_STATUS_NEVER_CONTACTED } from '~/ci/runner/constants';
|
||||
|
||||
import { runnerManagersData } from '../mock_data';
|
||||
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/ci/runner/sentry_utils');
|
||||
|
||||
const [runnerManager1, runnerManager2] = runnerManagersData.data.runner.managers.nodes;
|
||||
|
||||
Vue.use(VueApollo);
|
||||
const mockItems = runnerManagersData.data.runner.managers.nodes;
|
||||
|
||||
describe('RunnerJobs', () => {
|
||||
let wrapper;
|
||||
|
|
@ -25,9 +22,11 @@ describe('RunnerJobs', () => {
|
|||
const findCellText = (opts) => findCell(opts).text().replace(/\s+/g, ' ');
|
||||
|
||||
const createComponent = ({ item } = {}) => {
|
||||
const [mockItem, ...otherItems] = mockItems;
|
||||
|
||||
wrapper = mountExtended(RunnerManagersTable, {
|
||||
propsData: {
|
||||
items: [{ ...runnerManager1, ...item }, runnerManager2],
|
||||
items: [{ ...mockItem, ...item }, ...otherItems],
|
||||
},
|
||||
stubs: {
|
||||
GlTableLite,
|
||||
|
|
@ -54,8 +53,8 @@ describe('RunnerJobs', () => {
|
|||
|
||||
it('shows system id', () => {
|
||||
createComponent();
|
||||
expect(findCellText({ field: 'systemId', i: 0 })).toBe(runnerManager1.systemId);
|
||||
expect(findCellText({ field: 'systemId', i: 1 })).toBe(runnerManager2.systemId);
|
||||
expect(findCellText({ field: 'systemId', i: 0 })).toBe(mockItems[0].systemId);
|
||||
expect(findCellText({ field: 'systemId', i: 1 })).toBe(mockItems[1].systemId);
|
||||
});
|
||||
|
||||
it('shows version', () => {
|
||||
|
|
@ -74,6 +73,14 @@ describe('RunnerJobs', () => {
|
|||
expect(findCellText({ field: 'version', i: 0 })).toBe('1.0 (123456)');
|
||||
});
|
||||
|
||||
it('shows revision without version', () => {
|
||||
createComponent({
|
||||
item: { version: null, revision: '123456' },
|
||||
});
|
||||
|
||||
expect(findCellText({ field: 'version', i: 0 })).toBe('(123456)');
|
||||
});
|
||||
|
||||
it('shows ip address', () => {
|
||||
createComponent({
|
||||
item: { ipAddress: '127.0.0.1' },
|
||||
|
|
@ -117,7 +124,14 @@ describe('RunnerJobs', () => {
|
|||
it('shows contacted at', () => {
|
||||
createComponent();
|
||||
expect(findCell({ field: 'contactedAt', i: 0 }).findComponent(TimeAgo).props('time')).toBe(
|
||||
runnerManager1.contactedAt,
|
||||
mockItems[0].contactedAt,
|
||||
);
|
||||
});
|
||||
|
||||
it('shows missing contacted at', () => {
|
||||
createComponent({
|
||||
item: { contactedAt: null },
|
||||
});
|
||||
expect(findCellText({ field: 'contactedAt', i: 0 })).toBe(I18N_STATUS_NEVER_CONTACTED);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { GlDropdown, GlButton } from '@gitlab/ui';
|
||||
import { GlDisclosureDropdown, GlButton } from '@gitlab/ui';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue/';
|
||||
import stubChildren from 'helpers/stub_children';
|
||||
|
|
@ -19,7 +19,7 @@ describe('Package Files', () => {
|
|||
const findSecondRowCommitLink = () => findSecondRow().find('[data-testid="commit-link"]');
|
||||
const findFirstRowFileIcon = () => findFirstRow().findComponent(FileIcon);
|
||||
const findFirstRowCreatedAt = () => findFirstRow().findComponent(TimeAgoTooltip);
|
||||
const findFirstActionMenu = () => findFirstRow().findComponent(GlDropdown);
|
||||
const findFirstActionMenu = () => findFirstRow().findComponent(GlDisclosureDropdown);
|
||||
const findActionMenuDelete = () => findFirstActionMenu().find('[data-testid="delete-file"]');
|
||||
const findFirstToggleDetailsButton = () => findFirstRow().findComponent(GlButton);
|
||||
const findFirstRowShaComponent = (id) => wrapper.find(`[data-testid="${id}"]`);
|
||||
|
|
@ -159,7 +159,7 @@ describe('Package Files', () => {
|
|||
it('emits a delete event when clicked', () => {
|
||||
createComponent();
|
||||
|
||||
findActionMenuDelete().vm.$emit('click');
|
||||
findActionMenuDelete().vm.$emit('action');
|
||||
|
||||
const [[{ id }]] = wrapper.emitted('delete-file');
|
||||
expect(id).toBe(npmFiles[0].id);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Mutations::Achievements::DeleteUserAchievement, feature_category: :user_profile do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:maintainer) { create(:user) }
|
||||
let_it_be(:owner) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:achievement) { create(:achievement, namespace: group) }
|
||||
let_it_be(:user_achievement) { create(:user_achievement, achievement: achievement) }
|
||||
|
||||
describe '#resolve' do
|
||||
subject(:resolve_mutation) do
|
||||
described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
|
||||
user_achievement_id: user_achievement&.to_global_id
|
||||
)
|
||||
end
|
||||
|
||||
before_all do
|
||||
group.add_maintainer(maintainer)
|
||||
group.add_owner(owner)
|
||||
end
|
||||
|
||||
context 'when the user does not have permission' do
|
||||
let(:current_user) { maintainer }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
|
||||
.with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user has permission' do
|
||||
let(:current_user) { owner }
|
||||
|
||||
context 'when the params are invalid' do
|
||||
let(:user_achievement) { nil }
|
||||
|
||||
it 'returns the validation error' do
|
||||
expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
|
||||
end
|
||||
end
|
||||
|
||||
it 'deletes user_achievement' do
|
||||
resolve_mutation
|
||||
|
||||
expect(Achievements::UserAchievement.find_by(id: user_achievement.id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:destroy_user_achievement) }
|
||||
end
|
||||
|
|
@ -280,7 +280,7 @@ RSpec.describe Gitlab::Analytics::InternalEventsGenerator, :silence_stdout, feat
|
|||
|
||||
describe 'Creating known event entry' do
|
||||
let(:time_frames) { %w[7d 28d] }
|
||||
let(:expected_known_events) { [{ "name" => event, "aggregation" => "weekly" }] }
|
||||
let(:expected_known_events) { [{ "name" => event }] }
|
||||
|
||||
it 'creates a metric definition file using the template' do
|
||||
described_class.new([], options).invoke_all
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Middleware::CompressedJson do
|
||||
RSpec.describe Gitlab::Middleware::CompressedJson, feature_category: :shared do
|
||||
let_it_be(:decompressed_input) { '{"foo": "bar"}' }
|
||||
let_it_be(:input) { ActiveSupport::Gzip.compress(decompressed_input) }
|
||||
|
||||
|
|
@ -70,24 +70,6 @@ RSpec.describe Gitlab::Middleware::CompressedJson do
|
|||
end
|
||||
|
||||
describe '#call' do
|
||||
context 'with collector route' do
|
||||
let(:path) { '/api/v4/error_tracking/collector/1/store' }
|
||||
|
||||
it_behaves_like 'decompress middleware'
|
||||
|
||||
context 'with no Content-Type' do
|
||||
let(:content_type) { nil }
|
||||
|
||||
it_behaves_like 'decompress middleware'
|
||||
end
|
||||
|
||||
include_context 'with relative url' do
|
||||
let(:path) { "#{relative_url_root}/api/v4/error_tracking/collector/1/store" }
|
||||
|
||||
it_behaves_like 'decompress middleware'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with packages route' do
|
||||
context 'with instance level endpoint' do
|
||||
context 'with npm advisory bulk url' do
|
||||
|
|
@ -192,11 +174,11 @@ RSpec.describe Gitlab::Middleware::CompressedJson do
|
|||
it_behaves_like 'passes input'
|
||||
end
|
||||
|
||||
context 'payload is too large' do
|
||||
context 'when payload is too large' do
|
||||
let(:body_limit) { Gitlab::Middleware::CompressedJson::MAXIMUM_BODY_SIZE }
|
||||
let(:decompressed_input) { 'a' * (body_limit + 100) }
|
||||
let(:input) { ActiveSupport::Gzip.compress(decompressed_input) }
|
||||
let(:path) { '/api/v4/error_tracking/collector/1/envelope' }
|
||||
let(:path) { '/api/v4/packages/npm/-/npm/v1/security/advisories/bulk' }
|
||||
|
||||
it 'reads only limited size' do
|
||||
expect(middleware.call(env))
|
||||
|
|
|
|||
|
|
@ -23,91 +23,10 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
described_class.clear_memoization(:known_events)
|
||||
end
|
||||
|
||||
describe '.track_event' do
|
||||
# ToDo: remove during https://gitlab.com/groups/gitlab-org/-/epics/9542 cleanup
|
||||
describe 'daily to weekly key migration precautions' do
|
||||
let(:event_a_name) { 'example_event_a' }
|
||||
let(:event_b_name) { 'example_event_b' }
|
||||
let(:known_events) do
|
||||
[
|
||||
{ name: event_a_name, aggregation: 'daily' },
|
||||
{ name: event_b_name, aggregation: 'weekly' }
|
||||
].map(&:with_indifferent_access)
|
||||
end
|
||||
|
||||
let(:start_date) { (Date.current - 1.week).beginning_of_week }
|
||||
let(:end_date) { Date.current }
|
||||
|
||||
let(:daily_event) { known_events.first }
|
||||
let(:daily_key) { described_class.send(:redis_key, daily_event, start_date) }
|
||||
let(:weekly_key) do
|
||||
weekly_event = known_events.first.merge(aggregation: 'weekly')
|
||||
described_class.send(:redis_key, weekly_event, start_date)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(described_class).to receive(:load_events).with(described_class::KNOWN_EVENTS_PATH).and_return(known_events)
|
||||
allow(described_class).to receive(:load_events).with(/ee/).and_return([])
|
||||
end
|
||||
|
||||
shared_examples 'writes daily events to daily and weekly keys' do
|
||||
it :aggregate_failures do
|
||||
expect(Gitlab::Redis::HLL).to receive(:add).with(expiry: 29.days, key: daily_key, value: 1).and_call_original
|
||||
expect(Gitlab::Redis::HLL).to receive(:add).with(expiry: 6.weeks, key: weekly_key, value: 1).and_call_original
|
||||
|
||||
described_class.track_event(event_a_name, values: 1, time: start_date)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when revert_daily_hll_events_to_weekly_aggregation FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(revert_daily_hll_events_to_weekly_aggregation: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'writes daily events to daily and weekly keys'
|
||||
|
||||
it 'aggregates weekly for daily keys', :aggregate_failures do
|
||||
expect(Gitlab::Redis::HLL).to receive(:count).with(keys: [weekly_key]).and_call_original
|
||||
expect(Gitlab::Redis::HLL).not_to receive(:count).with(keys: [daily_key]).and_call_original
|
||||
|
||||
described_class.unique_events(event_names: [event_a_name], start_date: start_date, end_date: end_date)
|
||||
end
|
||||
|
||||
it 'does not persists changes to event aggregation attribute' do
|
||||
described_class.unique_events(event_names: [event_a_name], start_date: start_date, end_date: end_date)
|
||||
|
||||
expect(described_class.known_events.find { |e| e[:name] == event_a_name }[:aggregation])
|
||||
.to eql 'daily'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when revert_daily_hll_events_to_weekly_aggregation FF is enabled' do
|
||||
before do
|
||||
stub_feature_flags(revert_daily_hll_events_to_weekly_aggregation: true)
|
||||
end
|
||||
|
||||
# we want to write events no matter of the feature state
|
||||
it_behaves_like 'writes daily events to daily and weekly keys'
|
||||
|
||||
it 'aggregates daily for daily keys', :aggregate_failures do
|
||||
expect(Gitlab::Redis::HLL).to receive(:count).with(keys: [daily_key]).and_call_original
|
||||
expect(Gitlab::Redis::HLL).not_to receive(:count).with(keys: [weekly_key]).and_call_original
|
||||
|
||||
described_class.unique_events(event_names: [event_a_name], start_date: start_date, end_date: start_date)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.known_events' do
|
||||
let(:ce_temp_dir) { Dir.mktmpdir }
|
||||
let(:ce_temp_file) { Tempfile.new(%w[common .yml], ce_temp_dir) }
|
||||
let(:ce_event) do
|
||||
{
|
||||
"name" => "ce_event",
|
||||
"aggregation" => "weekly"
|
||||
}
|
||||
end
|
||||
let(:ce_event) { { "name" => "ce_event" } }
|
||||
|
||||
before do
|
||||
stub_const("#{described_class}::KNOWN_EVENTS_PATH", File.expand_path('*.yml', ce_temp_dir))
|
||||
|
|
@ -144,13 +63,13 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
|
||||
let(:known_events) do
|
||||
[
|
||||
{ name: weekly_event, aggregation: "weekly" },
|
||||
{ name: daily_event, aggregation: "daily" },
|
||||
{ name: category_productivity_event, aggregation: "weekly" },
|
||||
{ name: compliance_slot_event, aggregation: "weekly" },
|
||||
{ name: no_slot, aggregation: "daily" },
|
||||
{ name: different_aggregation, aggregation: "monthly" },
|
||||
{ name: context_event, aggregation: 'weekly' }
|
||||
{ name: weekly_event },
|
||||
{ name: daily_event },
|
||||
{ name: category_productivity_event },
|
||||
{ name: compliance_slot_event },
|
||||
{ name: no_slot },
|
||||
{ name: different_aggregation },
|
||||
{ name: context_event }
|
||||
].map(&:with_indifferent_access)
|
||||
end
|
||||
|
||||
|
|
@ -203,15 +122,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
it 'tracks events with multiple values' do
|
||||
values = [entity1, entity2]
|
||||
expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_analytics_contribution/, value: values,
|
||||
expiry: described_class::DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH)
|
||||
expiry: described_class::KEY_EXPIRY_LENGTH)
|
||||
|
||||
described_class.track_event(:g_analytics_contribution, values: values)
|
||||
end
|
||||
|
||||
it "raise error if metrics don't have same aggregation" do
|
||||
expect { described_class.track_event(different_aggregation, values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownAggregation)
|
||||
end
|
||||
|
||||
it 'raise error if metrics of unknown event' do
|
||||
expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
|
||||
end
|
||||
|
|
@ -248,22 +163,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
expect(keys).not_to be_empty
|
||||
|
||||
keys.each do |key|
|
||||
expect(redis.ttl(key)).to be_within(5.seconds).of(described_class::DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for daily events' do
|
||||
it 'sets the keys in Redis to expire' do
|
||||
described_class.track_event("no_slot", values: entity1)
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
keys = redis.scan_each(match: "*_no_slot").to_a
|
||||
expect(keys).not_to be_empty
|
||||
|
||||
keys.each do |key|
|
||||
expect(redis.ttl(key)).to be_within(5.seconds).of(described_class::DEFAULT_DAILY_KEY_EXPIRY_LENGTH)
|
||||
expect(redis.ttl(key)).to be_within(5.seconds).of(described_class::KEY_EXPIRY_LENGTH)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -285,7 +185,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
values = [entity1, entity2]
|
||||
expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_analytics_contribution/,
|
||||
value: values,
|
||||
expiry: described_class::DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH)
|
||||
expiry: described_class::KEY_EXPIRY_LENGTH)
|
||||
|
||||
described_class.track_event_in_context(:g_analytics_contribution, values: values, context: default_context)
|
||||
end
|
||||
|
|
@ -347,12 +247,6 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
expect(described_class.unique_events(event_names: [weekly_event], start_date: Date.current, end_date: 4.weeks.ago)).to eq(-1)
|
||||
end
|
||||
|
||||
it "raise error if metrics don't have same aggregation" do
|
||||
expect do
|
||||
described_class.unique_events(event_names: [daily_event, weekly_event], start_date: 4.weeks.ago, end_date: Date.current)
|
||||
end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::AggregationMismatch)
|
||||
end
|
||||
|
||||
context 'when data for the last complete week' do
|
||||
it { expect(described_class.unique_events(event_names: [weekly_event], start_date: 1.week.ago, end_date: Date.current)).to eq(1) }
|
||||
end
|
||||
|
|
@ -369,12 +263,6 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
it { expect(described_class.unique_events(event_names: [weekly_event.to_sym], start_date: 4.weeks.ago, end_date: 3.weeks.ago)).to eq(1) }
|
||||
end
|
||||
|
||||
context 'when using daily aggregation' do
|
||||
it { expect(described_class.unique_events(event_names: [daily_event], start_date: 7.days.ago, end_date: Date.current)).to eq(2) }
|
||||
it { expect(described_class.unique_events(event_names: [daily_event], start_date: 28.days.ago, end_date: Date.current)).to eq(3) }
|
||||
it { expect(described_class.unique_events(event_names: [daily_event], start_date: 28.days.ago, end_date: 21.days.ago)).to eq(1) }
|
||||
end
|
||||
|
||||
context 'when no slot is set' do
|
||||
it { expect(described_class.unique_events(event_names: [no_slot], start_date: 7.days.ago, end_date: Date.current)).to eq(1) }
|
||||
end
|
||||
|
|
@ -388,7 +276,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
end
|
||||
end
|
||||
|
||||
describe '.weekly_redis_keys' do
|
||||
describe '.keys_for_aggregation' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:weekly_event) { 'i_search_total' }
|
||||
|
|
@ -398,7 +286,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
let(:week_three) { "{#{described_class::REDIS_SLOT}}_i_search_total-2021-01" }
|
||||
let(:week_four) { "{#{described_class::REDIS_SLOT}}_i_search_total-2021-02" }
|
||||
|
||||
subject(:weekly_redis_keys) { described_class.send(:weekly_redis_keys, events: [redis_event], start_date: DateTime.parse(start_date), end_date: DateTime.parse(end_date)) }
|
||||
subject(:keys_for_aggregation) { described_class.send(:keys_for_aggregation, events: [redis_event], start_date: DateTime.parse(start_date), end_date: DateTime.parse(end_date)) }
|
||||
|
||||
where(:start_date, :end_date, :keys) do
|
||||
'2020-12-21' | '2020-12-21' | []
|
||||
|
|
@ -421,11 +309,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
end
|
||||
|
||||
it 'returns 1 key for last for week' do
|
||||
expect(described_class.send(:weekly_redis_keys, events: [redis_event], start_date: 7.days.ago.to_date, end_date: Date.current).size).to eq 1
|
||||
expect(described_class.send(:keys_for_aggregation, events: [redis_event], start_date: 7.days.ago.to_date, end_date: Date.current).size).to eq 1
|
||||
end
|
||||
|
||||
it 'returns 4 key for last for weeks' do
|
||||
expect(described_class.send(:weekly_redis_keys, events: [redis_event], start_date: 4.weeks.ago.to_date, end_date: Date.current).size).to eq 4
|
||||
expect(described_class.send(:keys_for_aggregation, events: [redis_event], start_date: 4.weeks.ago.to_date, end_date: Date.current).size).to eq 4
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -434,9 +322,9 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
|
||||
let(:known_events) do
|
||||
[
|
||||
{ name: 'event_name_1', aggregation: "weekly" },
|
||||
{ name: 'event_name_2', aggregation: "weekly" },
|
||||
{ name: 'event_name_3', aggregation: "weekly" }
|
||||
{ name: 'event_name_1' },
|
||||
{ name: 'event_name_2' },
|
||||
{ name: 'event_name_3' }
|
||||
].map(&:with_indifferent_access)
|
||||
end
|
||||
|
||||
|
|
@ -475,11 +363,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
let(:time_range) { { start_date: 7.days.ago, end_date: DateTime.current } }
|
||||
let(:known_events) do
|
||||
[
|
||||
{ name: 'event1_slot', aggregation: "weekly" },
|
||||
{ name: 'event2_slot', aggregation: "weekly" },
|
||||
{ name: 'event3_slot', aggregation: "weekly" },
|
||||
{ name: 'event5_slot', aggregation: "daily" },
|
||||
{ name: 'event4', aggregation: "weekly" }
|
||||
{ name: 'event1_slot' },
|
||||
{ name: 'event2_slot' },
|
||||
{ name: 'event3_slot' },
|
||||
{ name: 'event5_slot' },
|
||||
{ name: 'event4' }
|
||||
].map(&:with_indifferent_access)
|
||||
end
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue