Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0cd52ae4af
commit
528bc84312
31 changed files with 432 additions and 61 deletions
|
@ -1 +1 @@
|
|||
7a6ddce1d044e41ac9234e30cda62d85cbbc2a54
|
||||
d897d27c602d80b247af46a4ce672c2cd9b591ba
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<script>
|
||||
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE, I18N_ADMIN } from '../../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlLink,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
props: {
|
||||
runner: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
cell() {
|
||||
switch (this.runner?.runnerType) {
|
||||
case INSTANCE_TYPE:
|
||||
return {
|
||||
text: I18N_ADMIN,
|
||||
};
|
||||
case GROUP_TYPE: {
|
||||
const { name, fullName, webUrl } = this.runner?.groups?.nodes[0] || {};
|
||||
|
||||
return {
|
||||
text: name,
|
||||
href: webUrl,
|
||||
tooltip: fullName !== name ? fullName : '',
|
||||
};
|
||||
}
|
||||
case PROJECT_TYPE: {
|
||||
const { name, nameWithNamespace, webUrl } = this.runner?.ownerProject || {};
|
||||
|
||||
return {
|
||||
text: name,
|
||||
href: webUrl,
|
||||
tooltip: nameWithNamespace !== name ? nameWithNamespace : '',
|
||||
};
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<gl-link
|
||||
v-if="cell.href"
|
||||
v-gl-tooltip="cell.tooltip"
|
||||
:href="cell.href"
|
||||
class="gl-text-body gl-text-decoration-underline"
|
||||
>
|
||||
{{ cell.text }}
|
||||
</gl-link>
|
||||
<span v-else>{{ cell.text }}</span>
|
||||
</div>
|
||||
</template>
|
|
@ -2,15 +2,18 @@
|
|||
import { GlFormCheckbox, GlTableLite, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { s__ } from '~/locale';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import checkedRunnerIdsQuery from '../graphql/list/checked_runner_ids.query.graphql';
|
||||
import { formatJobCount, tableField } from '../utils';
|
||||
import RunnerStackedSummaryCell from './cells/runner_stacked_summary_cell.vue';
|
||||
import RunnerStatusPopover from './runner_status_popover.vue';
|
||||
import RunnerStatusCell from './cells/runner_status_cell.vue';
|
||||
import RunnerOwnerCell from './cells/runner_owner_cell.vue';
|
||||
|
||||
const defaultFields = [
|
||||
tableField({ key: 'status', label: s__('Runners|Status'), thClasses: ['gl-w-15p'] }),
|
||||
tableField({ key: 'summary', label: s__('Runners|Runner') }),
|
||||
tableField({ key: 'owner', label: s__('Runners|Owner'), thClasses: ['gl-w-20p'] }),
|
||||
tableField({ key: 'actions', label: '', thClasses: ['gl-w-15p'] }),
|
||||
];
|
||||
|
||||
|
@ -19,9 +22,11 @@ export default {
|
|||
GlFormCheckbox,
|
||||
GlTableLite,
|
||||
GlSkeletonLoader,
|
||||
HelpPopover,
|
||||
RunnerStatusPopover,
|
||||
RunnerStackedSummaryCell,
|
||||
RunnerStatusCell,
|
||||
RunnerOwnerCell,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
@ -140,6 +145,21 @@ export default {
|
|||
</runner-stacked-summary-cell>
|
||||
</template>
|
||||
|
||||
<template #head(owner)="{ label }">
|
||||
{{ label }}
|
||||
<help-popover>
|
||||
{{
|
||||
s__(
|
||||
'Runners|The project, group or instance where the runner was registered. Instance runners are always owned by Administrator.',
|
||||
)
|
||||
}}
|
||||
</help-popover>
|
||||
</template>
|
||||
|
||||
<template #cell(owner)="{ item }">
|
||||
<runner-owner-cell :runner="item" />
|
||||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
<slot name="runner-actions-cell" :runner="item"></slot>
|
||||
</template>
|
||||
|
|
|
@ -89,6 +89,7 @@ export const I18N_VERSION_LABEL = s__('Runners|Version %{version}');
|
|||
export const I18N_LAST_CONTACT_LABEL = s__('Runners|Last contact: %{timeAgo}');
|
||||
export const I18N_CREATED_AT_LABEL = s__('Runners|Created %{timeAgo}');
|
||||
export const I18N_SHOW_ONLY_INHERITED = s__('Runners|Show only inherited');
|
||||
export const I18N_ADMIN = s__('Runners|Administrator');
|
||||
|
||||
// Runner details
|
||||
|
||||
|
|
|
@ -16,4 +16,18 @@ fragment ListItemShared on CiRunner {
|
|||
updateRunner
|
||||
deleteRunner
|
||||
}
|
||||
groups(first: 1) {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
fullName
|
||||
webUrl
|
||||
}
|
||||
}
|
||||
ownerProject {
|
||||
id
|
||||
name
|
||||
nameWithNamespace
|
||||
webUrl
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,13 @@ module ProductAnalyticsTracking
|
|||
track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
|
||||
|
||||
if destinations.include?(:snowplow) && event_enabled?(name)
|
||||
Gitlab::Tracking.event(self.class.to_s, name, namespace: tracking_namespace_source, user: current_user)
|
||||
Gitlab::Tracking.event(
|
||||
self.class.to_s,
|
||||
name,
|
||||
namespace: tracking_namespace_source,
|
||||
user: current_user,
|
||||
context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,6 +55,7 @@ module ProductAnalyticsTracking
|
|||
user: current_user,
|
||||
property: name,
|
||||
label: label,
|
||||
context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context],
|
||||
**optional_arguments
|
||||
)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPasswordExpirationMigration < Gitlab::Database::Migration[2.0]
|
||||
def change
|
||||
add_column :application_settings, :password_expiration_enabled, :boolean, default: false, null: false,
|
||||
comment: 'JiHu-specific column'
|
||||
add_column :application_settings, :password_expires_in_days, :integer, default: 90, null: false,
|
||||
comment: 'JiHu-specific column'
|
||||
add_column :application_settings, :password_expires_notice_before_days, :integer, default: 7, null: false,
|
||||
comment: 'JiHu-specific column'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPasswordLastChangedAtToUserDetails < Gitlab::Database::Migration[2.0]
|
||||
enable_lock_retries!
|
||||
|
||||
def change
|
||||
add_column :user_details, :password_last_changed_at, :datetime_with_timezone, comment: 'JiHu-specific column'
|
||||
end
|
||||
end
|
1
db/schema_migrations/20221008032350
Normal file
1
db/schema_migrations/20221008032350
Normal file
|
@ -0,0 +1 @@
|
|||
c5e373b1b416455b67b7bc0affe244295e1f1a2f105fe8ef6efddf8b07da2a86
|
1
db/schema_migrations/20221012033107
Normal file
1
db/schema_migrations/20221012033107
Normal file
|
@ -0,0 +1 @@
|
|||
23252a63b8aab6a062cf22db563f8518213d40110449732866e6d8d5092d369e
|
|
@ -11488,6 +11488,9 @@ CREATE TABLE application_settings (
|
|||
lock_maven_package_requests_forwarding boolean DEFAULT false NOT NULL,
|
||||
lock_pypi_package_requests_forwarding boolean DEFAULT false NOT NULL,
|
||||
lock_npm_package_requests_forwarding boolean DEFAULT false NOT NULL,
|
||||
password_expiration_enabled boolean DEFAULT false NOT NULL,
|
||||
password_expires_in_days integer DEFAULT 90 NOT NULL,
|
||||
password_expires_notice_before_days integer DEFAULT 7 NOT NULL,
|
||||
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
|
||||
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
|
||||
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
|
||||
|
@ -11570,6 +11573,12 @@ COMMENT ON COLUMN application_settings.encrypted_feishu_app_secret IS 'JiHu-spec
|
|||
|
||||
COMMENT ON COLUMN application_settings.encrypted_feishu_app_secret_iv IS 'JiHu-specific column';
|
||||
|
||||
COMMENT ON COLUMN application_settings.password_expiration_enabled IS 'JiHu-specific column';
|
||||
|
||||
COMMENT ON COLUMN application_settings.password_expires_in_days IS 'JiHu-specific column';
|
||||
|
||||
COMMENT ON COLUMN application_settings.password_expires_notice_before_days IS 'JiHu-specific column';
|
||||
|
||||
CREATE SEQUENCE application_settings_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
|
@ -22079,6 +22088,7 @@ CREATE TABLE user_details (
|
|||
registration_objective smallint,
|
||||
phone text,
|
||||
requires_credit_card_verification boolean DEFAULT false NOT NULL,
|
||||
password_last_changed_at timestamp with time zone,
|
||||
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
|
||||
CONSTRAINT check_a73b398c60 CHECK ((char_length(phone) <= 50)),
|
||||
CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)),
|
||||
|
@ -22087,6 +22097,8 @@ CREATE TABLE user_details (
|
|||
|
||||
COMMENT ON COLUMN user_details.phone IS 'JiHu-specific column';
|
||||
|
||||
COMMENT ON COLUMN user_details.password_last_changed_at IS 'JiHu-specific column';
|
||||
|
||||
CREATE SEQUENCE user_details_user_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
|
|
|
@ -5861,6 +5861,7 @@ Input type: `WorkItemUpdateInput`
|
|||
| <a id="mutationworkitemupdatelabelswidget"></a>`labelsWidget` | [`WorkItemWidgetLabelsUpdateInput`](#workitemwidgetlabelsupdateinput) | Input for labels widget. |
|
||||
| <a id="mutationworkitemupdatestartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
|
||||
| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
|
||||
| <a id="mutationworkitemupdatestatuswidget"></a>`statusWidget` | [`StatusInput`](#statusinput) | Input for status widget. |
|
||||
| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
|
||||
| <a id="mutationworkitemupdateweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
|
||||
|
||||
|
@ -23435,6 +23436,14 @@ Represents an action to perform over a snippet file.
|
|||
| <a id="snippetblobactioninputtypefilepath"></a>`filePath` | [`String!`](#string) | Path of the snippet file. |
|
||||
| <a id="snippetblobactioninputtypepreviouspath"></a>`previousPath` | [`String`](#string) | Previous path of the snippet file. |
|
||||
|
||||
### `StatusInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="statusinputstatus"></a>`status` | [`TestReportState!`](#testreportstate) | Status to assign to the work item. |
|
||||
|
||||
### `Timeframe`
|
||||
|
||||
A time-frame defined as a closed inclusive range of two dates.
|
||||
|
|
|
@ -39,6 +39,7 @@ as it can cause the pipeline to behave unexpectedly.
|
|||
| `CI_COMMIT_SHA` | 9.0 | all | The commit revision the project is built for. |
|
||||
| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA`. |
|
||||
| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Available only in pipelines for tags. |
|
||||
| `CI_COMMIT_TAG_MESSAGE` | 15.5 | all | The commit tag message. Avaiable only in pipelines for tags. |
|
||||
| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. |
|
||||
| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit. The full first line of the message. |
|
||||
| `CI_CONCURRENT_ID` | all | 11.10 | The unique ID of build execution in a single executor. |
|
||||
|
@ -60,6 +61,7 @@ as it can cause the pipeline to behave unexpectedly.
|
|||
| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Available if [`environment:url`](../yaml/index.md#environmenturl) is set. |
|
||||
| `CI_ENVIRONMENT_ACTION` | 13.11 | all | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/index.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. |
|
||||
| `CI_ENVIRONMENT_TIER` | 14.0 | all | The [deployment tier of the environment](../environments/index.md#deployment-tier-of-environments) for this job. |
|
||||
| `CI_RELEASE_DESCRIPTION` | 15.5 | all | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters.|
|
||||
| `CI_GITLAB_FIPS_MODE` | 14.10 | all | The configuration setting for whether FIPS mode is enabled in the GitLab instance. |
|
||||
| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/index.md). `true` when available. |
|
||||
| `CI_JOB_ID` | 9.0 | all | The internal ID of the job, unique across all jobs in the GitLab instance. |
|
||||
|
|
|
@ -513,13 +513,16 @@ For example, **Snowplow Guide**. Instead, speak about the feature itself, and ho
|
|||
When writing about the Guest role:
|
||||
|
||||
- Use a capital **G**.
|
||||
- Do not use bold.
|
||||
- Do not use the phrase, **if you are a guest** to mean someone who is assigned the Guest
|
||||
role. Instead, write it out. For example, **if you are assigned the Guest role**.
|
||||
- To describe a situation where the Guest role is the minimum required:
|
||||
- Write it out:
|
||||
- Use: if you are assigned the Guest role
|
||||
- Instead of: if you are a guest
|
||||
|
||||
- When the Guest role is the minimum required role:
|
||||
- Use: at least the Guest role
|
||||
- Instead of: the Guest role or higher
|
||||
|
||||
Do not use bold.
|
||||
|
||||
Do not use **Guest permissions**. A user who is assigned the Guest role has a set of associated permissions.
|
||||
|
||||
## handy
|
||||
|
@ -660,13 +663,16 @@ Instead of:
|
|||
When writing about the Maintainer role:
|
||||
|
||||
- Use a capital **M**.
|
||||
- Do not use bold.
|
||||
- Do not use the phrase, **if you are a maintainer** to mean someone who is assigned the Maintainer
|
||||
role. Instead, write it out. For example, **if you are assigned the Maintainer role**.
|
||||
- To describe a situation where the Maintainer role is the minimum required:
|
||||
- Write it out.
|
||||
- Use: if you are assigned the Maintainer role
|
||||
- Instead of: if you are a maintainer
|
||||
|
||||
- When the Maintainer role is the minimum required role:
|
||||
- Use: at least the Maintainer role
|
||||
- Instead of: the Maintainer role or higher
|
||||
|
||||
Do not use bold.
|
||||
|
||||
Do not use **Maintainer permissions**. A user who is assigned the Maintainer role has a set of associated permissions.
|
||||
|
||||
## mankind
|
||||
|
@ -800,11 +806,14 @@ For example, a log file might overwrite a log file of the same name.
|
|||
When writing about the Owner role:
|
||||
|
||||
- Use a capital **O**.
|
||||
- Do not use bold.
|
||||
- Do not use the phrase, **if you are an owner** to mean someone who is assigned the Owner
|
||||
role. Instead, write it out. For example, **if you are assigned the Owner role**.
|
||||
- Write it out.
|
||||
- Use: if you are assigned the Owner role
|
||||
- Instead of: if you are an owner
|
||||
|
||||
Do not use bold.
|
||||
|
||||
Do not use **Owner permissions**. A user who is assigned the Owner role has a set of associated permissions.
|
||||
An Owner is the highest role a user can have.
|
||||
|
||||
## Package Registry
|
||||
|
||||
|
@ -855,13 +864,16 @@ Use **register** instead of **sign up** when talking about creating an account.
|
|||
When writing about the Reporter role:
|
||||
|
||||
- Use a capital **R**.
|
||||
- Do not use bold.
|
||||
- Do not use the phrase, **if you are a reporter** to mean someone who is assigned the Reporter
|
||||
role. Instead, write it out. For example, **if you are assigned the Reporter role**.
|
||||
- To describe a situation where the Reporter role is the minimum required:
|
||||
- Write it out.
|
||||
- Use: if you are assigned the Reporter role
|
||||
- Instead of: if you are a reporter
|
||||
|
||||
- When the Reporter role is the minimum required role:
|
||||
- Use: at least the Reporter role
|
||||
- Instead of: the Reporter role or higher
|
||||
|
||||
Do not use bold.
|
||||
|
||||
Do not use **Reporter permissions**. A user who is assigned the Reporter role has a set of associated permissions.
|
||||
|
||||
## Repository Mirroring
|
||||
|
|
|
@ -61,7 +61,6 @@ You can create a release:
|
|||
|
||||
- [Using a job in your CI/CD pipeline](#creating-a-release-by-using-a-cicd-job).
|
||||
- [In the Releases page](#create-a-release-in-the-releases-page).
|
||||
- [In the Tags page](#create-a-release-in-the-tags-page).
|
||||
- Using the [Releases API](../../../api/releases/index.md#create-a-release).
|
||||
|
||||
We recommend creating a release as one of the last steps in your CI/CD pipeline.
|
||||
|
@ -93,29 +92,6 @@ To create a release in the Releases page:
|
|||
- [Asset links](release_fields.md#links).
|
||||
1. Select **Create release**.
|
||||
|
||||
### Create a release in the Tags page
|
||||
|
||||
To create a release in the Tags page, add release notes to either an existing or a new Git tag.
|
||||
|
||||
To add release notes to a new Git tag:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository > Tags**.
|
||||
1. Select **New tag**.
|
||||
1. Optional. Enter a tag message in the **Message** text box.
|
||||
1. In the **Release notes** text box, enter the release's description.
|
||||
You can use Markdown and drag and drop files to this text box.
|
||||
1. Select **Create tag**.
|
||||
|
||||
To edit release notes of an existing Git tag:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository > Tags**.
|
||||
1. Select **Edit release notes** (**{pencil}**).
|
||||
1. In the **Release notes** text box, enter the release's description.
|
||||
You can use Markdown and drag and drop files to this text box.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Creating a release by using a CI/CD job
|
||||
|
||||
You can create a release directly as part of the GitLab CI/CD pipeline by using the
|
||||
|
|
25
lib/gitlab/tracking/service_ping_context.rb
Normal file
25
lib/gitlab/tracking/service_ping_context.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Tracking
|
||||
class ServicePingContext
|
||||
SCHEMA_URL = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0'
|
||||
ALLOWED_SOURCES = %i[redis_hll].freeze
|
||||
|
||||
def initialize(data_source:, event:)
|
||||
unless ALLOWED_SOURCES.include?(data_source)
|
||||
raise ArgumentError, "#{data_source} is not acceptable data source for ServicePingContext"
|
||||
end
|
||||
|
||||
@payload = {
|
||||
data_source: data_source,
|
||||
event_name: event
|
||||
}
|
||||
end
|
||||
|
||||
def to_context
|
||||
SnowplowTracker::SelfDescribingJson.new(SCHEMA_URL, @payload)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -34575,6 +34575,9 @@ msgstr ""
|
|||
msgid "Runners|Add your feedback in the issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Administrator"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|All"
|
||||
msgstr ""
|
||||
|
||||
|
@ -34781,6 +34784,9 @@ msgstr ""
|
|||
msgid "Runners|Online:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Owner"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Pause from accepting jobs"
|
||||
msgstr ""
|
||||
|
||||
|
@ -34963,6 +34969,9 @@ msgstr ""
|
|||
msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|The project, group or instance where the runner was registered. Instance runners are always owned by Administrator."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe Admin::CohortsController do
|
|||
let(:target_id) { 'i_analytics_cohorts' }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :index }
|
||||
|
||||
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
|
||||
|
|
|
@ -29,7 +29,7 @@ RSpec.describe Admin::DevOpsReportController do
|
|||
let(:request_params) { { tab: 'devops-score' } }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :show, format: :html }
|
||||
|
||||
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
|
||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe Admin::UsageTrendsController do
|
|||
let(:target_id) { 'i_analytics_instance_statistics' }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :index }
|
||||
|
||||
let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
|
||||
|
|
|
@ -55,11 +55,19 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
|
|||
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to have_received(:track_event)
|
||||
.with('g_analytics_valuestream', values: instance_of(String))
|
||||
|
||||
expect_snowplow_tracking(user)
|
||||
end
|
||||
|
||||
def expect_snowplow_tracking(user)
|
||||
context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'g_analytics_valuestream')
|
||||
.to_context.to_json
|
||||
|
||||
expect_snowplow_event(
|
||||
category: anything,
|
||||
action: 'g_analytics_valuestream',
|
||||
namespace: group,
|
||||
user: user
|
||||
user: user,
|
||||
context: [context]
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -160,12 +168,7 @@ RSpec.describe ProductAnalyticsTracking, :snowplow do
|
|||
get :show, params: { id: 2 }
|
||||
|
||||
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
|
||||
expect_snowplow_event(
|
||||
category: anything,
|
||||
action: 'g_analytics_valuestream',
|
||||
namespace: group,
|
||||
user: nil
|
||||
)
|
||||
expect_snowplow_tracking(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,7 +31,7 @@ RSpec.describe Projects::CycleAnalyticsController do
|
|||
let(:target_id) { 'p_analytics_valuestream' }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :show, params: request_params, format: :html }
|
||||
|
||||
let(:request_params) { { namespace_id: project.namespace, project_id: project } }
|
||||
|
|
|
@ -90,7 +90,7 @@ RSpec.describe Projects::GraphsController do
|
|||
let(:target_id) { 'p_analytics_repo' }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject do
|
||||
sign_in(user)
|
||||
get :charts, params: request_params, format: :html
|
||||
|
|
|
@ -859,7 +859,7 @@ RSpec.describe Projects::PipelinesController do
|
|||
let(:target_id) { ['p_analytics_pipelines', tab[:event]] }
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :charts, params: request_params, format: :html }
|
||||
|
||||
let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
|
||||
|
|
|
@ -218,7 +218,7 @@ RSpec.describe SearchController do
|
|||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'Snowplow event tracking' do
|
||||
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||
subject { get :show, params: { group_id: namespace.id, scope: 'blobs', search: 'term' } }
|
||||
|
||||
let(:project) { nil }
|
||||
|
|
111
spec/frontend/runner/components/cells/runner_owner_cell_spec.js
Normal file
111
spec/frontend/runner/components/cells/runner_owner_cell_spec.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlLink } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
|
||||
import RunnerOwnerCell from '~/runner/components/cells/runner_owner_cell.vue';
|
||||
|
||||
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
|
||||
|
||||
describe('RunnerOwnerCell', () => {
|
||||
let wrapper;
|
||||
|
||||
const findLink = () => wrapper.findComponent(GlLink);
|
||||
const getLinkTooltip = () => getBinding(findLink().element, 'gl-tooltip').value;
|
||||
|
||||
const createComponent = ({ runner } = {}) => {
|
||||
wrapper = shallowMount(RunnerOwnerCell, {
|
||||
directives: {
|
||||
GlTooltip: createMockDirective(),
|
||||
},
|
||||
propsData: {
|
||||
runner,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('When its an instance runner', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
runner: {
|
||||
runnerType: INSTANCE_TYPE,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('shows an administrator label', () => {
|
||||
expect(findLink().exists()).toBe(false);
|
||||
expect(wrapper.text()).toBe(s__('Runners|Administrator'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('When its a group runner', () => {
|
||||
const mockName = 'Group 2';
|
||||
const mockFullName = 'Group 1 / Group 2';
|
||||
const mockWebUrl = '/group-1/group-2';
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
runner: {
|
||||
runnerType: GROUP_TYPE,
|
||||
groups: {
|
||||
nodes: [
|
||||
{
|
||||
name: mockName,
|
||||
fullName: mockFullName,
|
||||
webUrl: mockWebUrl,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Displays a group link', () => {
|
||||
expect(findLink().attributes('href')).toBe(mockWebUrl);
|
||||
expect(wrapper.text()).toBe(mockName);
|
||||
expect(getLinkTooltip()).toBe(mockFullName);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When its a project runner', () => {
|
||||
const mockName = 'Project 1';
|
||||
const mockNameWithNamespace = 'Group 1 / Project 1';
|
||||
const mockWebUrl = '/group-1/project-1';
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
runner: {
|
||||
runnerType: PROJECT_TYPE,
|
||||
ownerProject: {
|
||||
name: mockName,
|
||||
nameWithNamespace: mockNameWithNamespace,
|
||||
webUrl: mockWebUrl,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Displays a project link', () => {
|
||||
expect(findLink().attributes('href')).toBe(mockWebUrl);
|
||||
expect(wrapper.text()).toBe(mockName);
|
||||
expect(getLinkTooltip()).toBe(mockNameWithNamespace);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When its an empty runner', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
runner: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('shows no label', () => {
|
||||
expect(wrapper.text()).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,12 +1,13 @@
|
|||
import { GlTableLite, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import {
|
||||
extendedWrapper,
|
||||
shallowMountExtended,
|
||||
mountExtended,
|
||||
} from 'helpers/vue_test_utils_helper';
|
||||
import { s__ } from '~/locale';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import RunnerList from '~/runner/components/runner_list.vue';
|
||||
import RunnerStatusPopover from '~/runner/components/runner_status_popover.vue';
|
||||
import { I18N_PROJECT_TYPE, I18N_STATUS_NEVER_CONTACTED } from '~/runner/constants';
|
||||
import { allRunnersData, onlineContactTimeoutSecs, staleTimeoutSecs } from '../mock_data';
|
||||
|
||||
|
@ -50,7 +51,7 @@ describe('RunnerList', () => {
|
|||
createComponent(
|
||||
{
|
||||
stubs: {
|
||||
RunnerStatusPopover: {
|
||||
HelpPopover: {
|
||||
template: '<div/>',
|
||||
},
|
||||
},
|
||||
|
@ -60,11 +61,13 @@ describe('RunnerList', () => {
|
|||
|
||||
const headerLabels = findHeaders().wrappers.map((w) => w.text());
|
||||
|
||||
expect(findHeaders().at(0).findComponent(RunnerStatusPopover).exists()).toBe(true);
|
||||
expect(findHeaders().at(0).findComponent(HelpPopover).exists()).toBe(true);
|
||||
expect(findHeaders().at(2).findComponent(HelpPopover).exists()).toBe(true);
|
||||
|
||||
expect(headerLabels).toEqual([
|
||||
'Status',
|
||||
'Runner',
|
||||
s__('Runners|Status'),
|
||||
s__('Runners|Runner'),
|
||||
s__('Runners|Owner'),
|
||||
'', // actions has no label
|
||||
]);
|
||||
});
|
||||
|
|
19
spec/lib/gitlab/tracking/service_ping_context_spec.rb
Normal file
19
spec/lib/gitlab/tracking/service_ping_context_spec.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Tracking::ServicePingContext do
|
||||
describe '#init' do
|
||||
it 'does not accept unsupported data sources' do
|
||||
expect { described_class.new(data_source: :random, event: 'event a') }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_context' do
|
||||
let(:subject) { described_class.new(data_source: :redis_hll, event: 'sample_event') }
|
||||
|
||||
it 'contains event_name' do
|
||||
expect(subject.to_context.to_json.dig(:data, :event_name)).to eq('sample_event')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require_migration!
|
||||
|
||||
RSpec.describe AddPasswordExpirationMigration do
|
||||
let(:application_setting) { table(:application_settings).create! }
|
||||
|
||||
describe "#up" do
|
||||
it 'allows to read password expiration fields' do
|
||||
migrate!
|
||||
|
||||
expect(application_setting.password_expiration_enabled).to eq false
|
||||
expect(application_setting.password_expires_in_days).to eq 90
|
||||
expect(application_setting.password_expires_notice_before_days).to eq 7
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require_migration!
|
||||
|
||||
RSpec.describe AddPasswordLastChangedAtToUserDetails do
|
||||
let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
|
||||
let_it_be(:users) { table(:users) }
|
||||
let_it_be(:user) { create_user! }
|
||||
let(:user_detail) { table(:user_details).create!(user_id: user.id, provisioned_by_group_id: namespace.id) }
|
||||
|
||||
describe "#up" do
|
||||
it 'allows to read password_last_changed_at' do
|
||||
migrate!
|
||||
|
||||
expect(user_detail.password_last_changed_at).to eq nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_user!(name: "Example User", email: "user@example.com", user_type: nil)
|
||||
users.create!(
|
||||
name: name,
|
||||
email: email,
|
||||
username: name,
|
||||
projects_limit: 0,
|
||||
user_type: user_type,
|
||||
confirmed_at: Time.current
|
||||
)
|
||||
end
|
||||
end
|
|
@ -32,7 +32,8 @@ RSpec.shared_examples 'Snowplow event tracking' do |overrides: {}|
|
|||
user: try(:user),
|
||||
project: try(:project),
|
||||
label: try(:label),
|
||||
property: try(:property)
|
||||
property: try(:property),
|
||||
context: try(:context)
|
||||
}.merge(overrides).compact.merge(extra)
|
||||
|
||||
subject
|
||||
|
@ -40,3 +41,12 @@ RSpec.shared_examples 'Snowplow event tracking' do |overrides: {}|
|
|||
expect_snowplow_event(**params)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'Snowplow event tracking with RedisHLL context' do |overrides: {}|
|
||||
it_behaves_like 'Snowplow event tracking', overrides: overrides do
|
||||
let(:context) do
|
||||
event = try(:property) || action
|
||||
[Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue