Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-13 03:09:36 +00:00
parent 0cd52ae4af
commit 528bc84312
31 changed files with 432 additions and 61 deletions

View File

@ -1 +1 @@
7a6ddce1d044e41ac9234e30cda62d85cbbc2a54
d897d27c602d80b247af46a4ce672c2cd9b591ba

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -16,4 +16,18 @@ fragment ListItemShared on CiRunner {
updateRunner
deleteRunner
}
groups(first: 1) {
nodes {
id
name
fullName
webUrl
}
}
ownerProject {
id
name
nameWithNamespace
webUrl
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
c5e373b1b416455b67b7bc0affe244295e1f1a2f105fe8ef6efddf8b07da2a86

View File

@ -0,0 +1 @@
23252a63b8aab6a062cf22db563f8518213d40110449732866e6d8d5092d369e

View File

@ -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

View File

@ -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.

View File

@ -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. |

View File

@ -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

View File

@ -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

View 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

View File

@ -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 ""

View File

@ -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 }

View File

@ -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 }

View File

@ -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 }

View File

@ -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

View File

@ -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 } }

View File

@ -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

View File

@ -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] } }

View File

@ -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 }

View 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('');
});
});
});

View File

@ -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
]);
});

View 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

View File

@ -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

View File

@ -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

View File

@ -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