Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
feb7a8f326
commit
e2c044cf3f
|
|
@ -603,7 +603,7 @@ ee:importers:
|
|||
extends: .qa
|
||||
variables:
|
||||
QA_SCENARIO: Test::Integration::Import
|
||||
QA_MOCK_GITHUB: "false"
|
||||
QA_MOCK_GITHUB: "true"
|
||||
GITLAB_QA_OPTS: --set-feature-flags bulk_import_projects=enabled
|
||||
rules:
|
||||
- !reference [.rules:test:qa, rules]
|
||||
|
|
|
|||
|
|
@ -4,4 +4,3 @@ Database/MultipleDatabases:
|
|||
- 'db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb'
|
||||
- 'db/post_migrate/20210811122206_update_external_project_bots.rb'
|
||||
- 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb'
|
||||
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { sortBy } from 'lodash';
|
||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
|
||||
import { isScopedLabel } from '~/lib/utils/common_utils';
|
||||
import { updateHistory } from '~/lib/utils/url_utility';
|
||||
|
|
@ -43,7 +43,7 @@ export default {
|
|||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
mixins: [boardCardInner],
|
||||
inject: ['rootPath', 'scopedLabelsAvailable', 'isEpicBoard', 'issuableType'],
|
||||
inject: ['rootPath', 'scopedLabelsAvailable', 'isEpicBoard', 'issuableType', 'isGroupBoard'],
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
|
|
@ -78,7 +78,6 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState(['isShowingLabels', 'allowSubEpics']),
|
||||
...mapGetters(['isProjectBoard']),
|
||||
cappedAssignees() {
|
||||
// e.g. maxRender is 4,
|
||||
// Render up to all 4 assignees if there are only 4 assigness
|
||||
|
|
@ -158,7 +157,7 @@ export default {
|
|||
return Math.round((this.item.descendantWeightSum.closedIssues / this.totalWeight) * 100);
|
||||
},
|
||||
showReferencePath() {
|
||||
return !this.isProjectBoard && this.itemReferencePath;
|
||||
return this.isGroupBoard && this.itemReferencePath;
|
||||
},
|
||||
avatarSize() {
|
||||
return { default: 16, lg: 24 };
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { s__ } from '~/locale';
|
|||
import { formatBoardLists } from 'ee_else_ce/boards/boards_util';
|
||||
import BoardAddNewColumn from 'ee_else_ce/boards/components/board_add_new_column.vue';
|
||||
import { defaultSortableOptions } from '~/sortable/constants';
|
||||
import { DraggableItemTypes, BoardType, listsQuery } from 'ee_else_ce/boards/constants';
|
||||
import { DraggableItemTypes, listsQuery } from 'ee_else_ce/boards/constants';
|
||||
import BoardColumn from './board_column.vue';
|
||||
|
||||
export default {
|
||||
|
|
@ -35,6 +35,7 @@ export default {
|
|||
'issuableType',
|
||||
'isIssueBoard',
|
||||
'isEpicBoard',
|
||||
'isGroupBoard',
|
||||
'isApolloBoard',
|
||||
],
|
||||
props: {
|
||||
|
|
@ -89,8 +90,8 @@ export default {
|
|||
queryVariables() {
|
||||
return {
|
||||
...(this.isIssueBoard && {
|
||||
isGroup: this.boardType === BoardType.group,
|
||||
isProject: this.boardType === BoardType.project,
|
||||
isGroup: this.isGroupBoard,
|
||||
isProject: !this.isGroupBoard,
|
||||
}),
|
||||
fullPath: this.fullPath,
|
||||
boardId: this.boardId,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdow
|
|||
import { __, sprintf } from '~/locale';
|
||||
import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
|
||||
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
|
||||
import { ISSUABLE, INCIDENT, issuableTypes } from '~/boards/constants';
|
||||
import { BoardType, ISSUABLE, INCIDENT, issuableTypes } from '~/boards/constants';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
|
||||
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
|
||||
|
|
@ -68,11 +68,13 @@ export default {
|
|||
issuableType: {
|
||||
default: issuableTypes.issue,
|
||||
},
|
||||
isGroupBoard: {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
inheritAttrs: false,
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isGroupBoard',
|
||||
'isSidebarOpen',
|
||||
'activeBoardItem',
|
||||
'groupPathForActiveIssue',
|
||||
|
|
@ -94,14 +96,17 @@ export default {
|
|||
fullPath() {
|
||||
return this.activeBoardItem?.referencePath?.split('#')[0] || '';
|
||||
},
|
||||
parentType() {
|
||||
return this.isGroupBoard ? BoardType.group : BoardType.project;
|
||||
},
|
||||
createLabelTitle() {
|
||||
return sprintf(__('Create %{workspace} label'), {
|
||||
workspace: this.isGroupBoard ? 'group' : 'project',
|
||||
workspace: this.parentType,
|
||||
});
|
||||
},
|
||||
manageLabelTitle() {
|
||||
return sprintf(__('Manage %{workspace} labels'), {
|
||||
workspace: this.isGroupBoard ? 'group' : 'project',
|
||||
workspace: this.parentType,
|
||||
});
|
||||
},
|
||||
attrWorkspacePath() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlModal, GlAlert } from '@gitlab/ui';
|
||||
import { mapGetters, mapActions, mapState } from 'vuex';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { visitUrl, updateHistory, getParameterByName } from '~/lib/utils/url_utility';
|
||||
import { __, s__ } from '~/locale';
|
||||
|
|
@ -51,6 +51,12 @@ export default {
|
|||
boardBaseUrl: {
|
||||
default: '',
|
||||
},
|
||||
isGroupBoard: {
|
||||
default: false,
|
||||
},
|
||||
isProjectBoard: {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
canAdminBoard: {
|
||||
|
|
@ -84,7 +90,6 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState(['error']),
|
||||
...mapGetters(['isGroupBoard', 'isProjectBoard']),
|
||||
isNewForm() {
|
||||
return this.currentPage === formType.new;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default {
|
|||
ProjectSelect,
|
||||
},
|
||||
mixins: [BoardNewIssueMixin],
|
||||
inject: ['groupId', 'fullPath'],
|
||||
inject: ['groupId', 'fullPath', 'isGroupBoard'],
|
||||
props: {
|
||||
list: {
|
||||
type: Object,
|
||||
|
|
@ -25,7 +25,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapState(['selectedProject']),
|
||||
...mapGetters(['isGroupBoard', 'getBoardItemsByList']),
|
||||
...mapGetters(['getBoardItemsByList']),
|
||||
formEventPrefix() {
|
||||
return toggleFormEventPrefix.issue;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
GlModalDirective,
|
||||
} from '@gitlab/ui';
|
||||
import { throttle } from 'lodash';
|
||||
import { mapActions, mapGetters, mapState } from 'vuex';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
|
||||
import BoardForm from 'ee_else_ce/boards/components/board_form.vue';
|
||||
|
||||
|
|
@ -50,6 +50,7 @@ export default {
|
|||
'scopedIssueBoardFeatureEnabled',
|
||||
'weights',
|
||||
'boardType',
|
||||
'isGroupBoard',
|
||||
],
|
||||
props: {
|
||||
throttleDuration: {
|
||||
|
|
@ -76,7 +77,6 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapState(['board', 'isBoardLoading']),
|
||||
...mapGetters(['isGroupBoard', 'isProjectBoard']),
|
||||
parentType() {
|
||||
return this.boardType;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus';
|
|||
import { mapActions } from 'vuex';
|
||||
import { orderBy } from 'lodash';
|
||||
import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_search.vue';
|
||||
import { BoardType } from '~/boards/constants';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { joinPaths } from '~/lib/utils/url_utility';
|
||||
import issueBoardFilters from '~/boards/issue_board_filters';
|
||||
|
|
@ -47,23 +46,15 @@ export default {
|
|||
issue: __('Issue'),
|
||||
},
|
||||
components: { BoardFilteredSearch },
|
||||
inject: ['isSignedIn', 'releasesFetchPath', 'fullPath', 'boardType'],
|
||||
inject: ['isSignedIn', 'releasesFetchPath', 'fullPath', 'isGroupBoard'],
|
||||
computed: {
|
||||
isGroupBoard() {
|
||||
return this.boardType === BoardType.group;
|
||||
},
|
||||
epicsGroupPath() {
|
||||
return this.isGroupBoard
|
||||
? this.fullPath
|
||||
: this.fullPath.slice(0, this.fullPath.lastIndexOf('/'));
|
||||
},
|
||||
tokensCE() {
|
||||
const { issue, incident } = this.$options.i18n;
|
||||
const { types } = this.$options;
|
||||
const { fetchUsers, fetchLabels } = issueBoardFilters(
|
||||
this.$apollo,
|
||||
this.fullPath,
|
||||
this.boardType,
|
||||
this.isGroupBoard,
|
||||
);
|
||||
|
||||
const tokens = [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Vue from 'vue';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import BoardApp from '~/boards/components/board_app.vue';
|
||||
import '~/boards/filters/due_date_filters';
|
||||
import { issuableTypes } from '~/boards/constants';
|
||||
import { BoardType, issuableTypes } from '~/boards/constants';
|
||||
import store from '~/boards/stores';
|
||||
import {
|
||||
NavigationType,
|
||||
|
|
@ -31,17 +31,19 @@ function mountBoardApp(el) {
|
|||
...convertObjectPropsToCamelCase(rawFilterParams),
|
||||
};
|
||||
|
||||
const boardType = el.dataset.parent;
|
||||
|
||||
store.dispatch('fetchBoard', {
|
||||
fullPath,
|
||||
fullBoardId: fullBoardId(boardId),
|
||||
boardType: el.dataset.parent,
|
||||
boardType,
|
||||
});
|
||||
|
||||
store.dispatch('setInitialBoardData', {
|
||||
boardId,
|
||||
fullBoardId: fullBoardId(boardId),
|
||||
fullPath,
|
||||
boardType: el.dataset.parent,
|
||||
boardType,
|
||||
disabled: parseBoolean(el.dataset.disabled) || true,
|
||||
issuableType: issuableTypes.issue,
|
||||
});
|
||||
|
|
@ -61,7 +63,9 @@ function mountBoardApp(el) {
|
|||
fullPath,
|
||||
initialFilterParams,
|
||||
boardBaseUrl: el.dataset.boardBaseUrl,
|
||||
boardType: el.dataset.parent,
|
||||
boardType,
|
||||
isGroupBoard: boardType === BoardType.group,
|
||||
isProjectBoard: boardType === BoardType.project,
|
||||
currentUserId: gon.current_user_id || null,
|
||||
boardWeight: el.dataset.boardWeight ? parseInt(el.dataset.boardWeight, 10) : null,
|
||||
labelsManagePath: el.dataset.labelsManagePath,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
import groupBoardMembers from '~/boards/graphql/group_board_members.query.graphql';
|
||||
import projectBoardMembers from '~/boards/graphql/project_board_members.query.graphql';
|
||||
import { BoardType } from './constants';
|
||||
import boardLabels from './graphql/board_labels.query.graphql';
|
||||
|
||||
export default function issueBoardFilters(apollo, fullPath, boardType) {
|
||||
const isGroupBoard = boardType === BoardType.group;
|
||||
const isProjectBoard = boardType === BoardType.project;
|
||||
export default function issueBoardFilters(apollo, fullPath, isGroupBoard) {
|
||||
const transformLabels = ({ data }) => {
|
||||
return isGroupBoard ? data.group?.labels.nodes || [] : data.project?.labels.nodes || [];
|
||||
};
|
||||
|
|
@ -34,7 +31,7 @@ export default function issueBoardFilters(apollo, fullPath, boardType) {
|
|||
fullPath,
|
||||
searchTerm: labelSearchTerm,
|
||||
isGroup: isGroupBoard,
|
||||
isProject: isProjectBoard,
|
||||
isProject: !isGroupBoard,
|
||||
},
|
||||
})
|
||||
.then(transformLabels);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import { find } from 'lodash';
|
||||
import { BoardType, inactiveId, issuableTypes } from '../constants';
|
||||
import { inactiveId, issuableTypes } from '../constants';
|
||||
|
||||
export default {
|
||||
isGroupBoard: (state) => state.boardType === BoardType.group,
|
||||
isProjectBoard: (state) => state.boardType === BoardType.project,
|
||||
isSidebarOpen: (state) => state.activeId !== inactiveId,
|
||||
isSwimlanesOn: () => false,
|
||||
getBoardItemById: (state) => (id) => {
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ export default {
|
|||
:work-item-parent-id="issueGid"
|
||||
:work-item-id="displayedWorkItemId"
|
||||
:work-item-iid="workItemIid"
|
||||
class="gl-p-5 gl-mt-n3"
|
||||
class="gl-p-5 gl-mt-n3 gl-reset-bg gl-isolate"
|
||||
@close="hide"
|
||||
@deleteWorkItem="deleteWorkItem"
|
||||
@update-modal="updateModal"
|
||||
|
|
|
|||
|
|
@ -294,3 +294,7 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
|
|||
.gl-max-w-0 {
|
||||
max-width: 0;
|
||||
}
|
||||
|
||||
.gl-isolate {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,13 @@ The `deploy-to-cloud-run` job:
|
|||
* `GCP_PROJECT_ID`
|
||||
* `GCP_SERVICE_ACCOUNT_KEY`
|
||||
* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library
|
||||
* Uses CI/CD variables to configure the deployment. You can override the default values by adding these variables:
|
||||
* `GCP_CLOUD_RUN_MAX_INSTANCES`
|
||||
* `GCP_CLOUD_RUN_MIN_INSTANCES`
|
||||
* `GCP_CLOUD_RUN_CONCURRENCY`
|
||||
* `GCP_CLOUD_RUN_CPU`
|
||||
* `GCP_CLOUD_RUN_MEMORY`
|
||||
* `GCP_CLOUD_RUN_TIMEOUT`
|
||||
|
||||
This pipeline definition has been committed to the branch `#{branch_name}`.
|
||||
You may modify the pipeline definition further or accept the changes as-is if suitable.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -5727,11 +5727,12 @@ Input type: `UpdateRequirementInput`
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationupdaterequirementclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationupdaterequirementdescription"></a>`description` | [`String`](#string) | Description of the requirement. |
|
||||
| <a id="mutationupdaterequirementiid"></a>`iid` | [`String!`](#string) | IID of the requirement to update. |
|
||||
| <a id="mutationupdaterequirementiid"></a>`iid` | [`String`](#string) | IID of the requirement to update. |
|
||||
| <a id="mutationupdaterequirementlasttestreportstate"></a>`lastTestReportState` | [`TestReportState`](#testreportstate) | Creates a test report for the requirement with the given state. |
|
||||
| <a id="mutationupdaterequirementprojectpath"></a>`projectPath` | [`ID!`](#id) | Full project path the requirement is associated with. |
|
||||
| <a id="mutationupdaterequirementstate"></a>`state` | [`RequirementState`](#requirementstate) | State of the requirement. |
|
||||
| <a id="mutationupdaterequirementtitle"></a>`title` | [`String`](#string) | Title of the requirement. |
|
||||
| <a id="mutationupdaterequirementworkitemiid"></a>`workItemIid` | [`String`](#string) | IID of the requirement work item to update. |
|
||||
|
||||
#### Fields
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class GroupRunner < RunnerBase
|
||||
attribute :group do
|
||||
Resource::Group.fabricate_via_api! do |resource|
|
||||
resource.name = "group-with-ci-cd-#{SecureRandom.hex(8)}"
|
||||
resource.description = 'Group with CI/CD Pipelines'
|
||||
end
|
||||
end
|
||||
|
||||
attribute :token do
|
||||
group.runners_token
|
||||
rescue NoValueError
|
||||
group.reload!.runners_token
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def runner(**kwargs)
|
||||
fail_msg = "Wait for runner '#{name}' to register in group '#{group.name}'"
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1, message: fail_msg) do
|
||||
auto_paginated_response(request_url("/runners", **kwargs)).find { |runner| runner[:description] == name }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -10,25 +10,25 @@ module QA
|
|||
include ApprovalConfiguration
|
||||
|
||||
attr_accessor :initialize_with_readme,
|
||||
:auto_devops_enabled,
|
||||
:github_personal_access_token,
|
||||
:github_repository_path,
|
||||
:gitlab_repository_path,
|
||||
:personal_namespace
|
||||
:auto_devops_enabled,
|
||||
:github_personal_access_token,
|
||||
:github_repository_path,
|
||||
:gitlab_repository_path,
|
||||
:personal_namespace
|
||||
|
||||
attr_reader :repository_storage
|
||||
|
||||
attributes :id,
|
||||
:name,
|
||||
:path,
|
||||
:add_name_uuid,
|
||||
:runners_token,
|
||||
:visibility,
|
||||
:template_name,
|
||||
:import,
|
||||
:import_status,
|
||||
:import_error,
|
||||
:description
|
||||
:name,
|
||||
:path,
|
||||
:add_name_uuid,
|
||||
:runners_token,
|
||||
:visibility,
|
||||
:template_name,
|
||||
:import,
|
||||
:import_status,
|
||||
:import_error,
|
||||
:description
|
||||
|
||||
attribute :group do
|
||||
Group.fabricate! do |group|
|
||||
|
|
@ -43,7 +43,7 @@ module QA
|
|||
alias_method :full_path, :path_with_namespace
|
||||
|
||||
def sandbox_path
|
||||
return '' if personal_namespace || !group.respond_to?('sandbox')
|
||||
return '' if personal_namespace || !group.respond_to?(:sandbox)
|
||||
|
||||
"#{group.sandbox.path}/"
|
||||
end
|
||||
|
|
@ -450,6 +450,14 @@ module QA
|
|||
parse_body(response)
|
||||
end
|
||||
|
||||
# Fetch project specific runners
|
||||
#
|
||||
# @param [Hash] **kwargs optional query arguments, see: https://docs.gitlab.com/ee/api/runners.html#list-projects-runners
|
||||
# @return [Array]
|
||||
def runners(**kwargs)
|
||||
auto_paginated_response(request_url(api_runners_path, **kwargs))
|
||||
end
|
||||
|
||||
# Uses the API to wait until a pull mirroring update is successful (pull mirroring is treated as an import)
|
||||
def wait_for_pull_mirroring
|
||||
mirror_succeeded = Support::Retrier.retry_until(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class ProjectRunner < RunnerBase
|
||||
attribute :project do
|
||||
Project.fabricate_via_api! do |resource|
|
||||
resource.name = 'project-with-ci-cd'
|
||||
resource.description = 'Project with CI/CD Pipelines'
|
||||
end
|
||||
end
|
||||
|
||||
attribute :token do
|
||||
project.runners_token
|
||||
rescue NoValueError
|
||||
project.reload!.runners_token
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def runner(**kwargs)
|
||||
fail_msg = "Wait for runner '#{name}' to register in project '#{project.name}'"
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1, message: fail_msg) do
|
||||
project.runners(**kwargs).find { |runner| runner[:description] == name }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class Runner < Base
|
||||
attributes :id,
|
||||
:active,
|
||||
:paused,
|
||||
:runner_type,
|
||||
:online,
|
||||
:status,
|
||||
:ip_address,
|
||||
:token,
|
||||
:tags,
|
||||
:config,
|
||||
:run_untagged,
|
||||
:name, # This attribute == runner[:description]
|
||||
:image,
|
||||
:executor,
|
||||
:executor_image
|
||||
|
||||
attribute :project do
|
||||
Project.fabricate_via_api! do |resource|
|
||||
resource.name = 'project-with-ci-cd'
|
||||
resource.description = 'Project with CI/CD Pipelines'
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@tags = nil
|
||||
@config = nil
|
||||
@run_untagged = nil
|
||||
@name = "qa-runner-#{SecureRandom.hex(4)}"
|
||||
@image = 'registry.gitlab.com/gitlab-org/gitlab-runner:alpine'
|
||||
@executor = :shell
|
||||
@executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
|
||||
end
|
||||
|
||||
# Initially we only support fabricate
|
||||
# via API
|
||||
def fabricate!
|
||||
fabricate_via_api!
|
||||
end
|
||||
|
||||
# Start container and register runner
|
||||
# Fetch via API and populate attributes
|
||||
#
|
||||
def fabricate_via_api!
|
||||
start_container_and_register
|
||||
populate_runner_attributes
|
||||
end
|
||||
|
||||
def remove_via_api!
|
||||
super
|
||||
ensure
|
||||
@docker_container.remove!
|
||||
end
|
||||
|
||||
def reload!
|
||||
populate_runner_attributes
|
||||
end
|
||||
|
||||
def api_delete_path
|
||||
"/runners/#{id}"
|
||||
end
|
||||
|
||||
def api_get_path
|
||||
"/runners"
|
||||
end
|
||||
|
||||
def api_post_path
|
||||
"/runners"
|
||||
end
|
||||
|
||||
def api_post_body; end
|
||||
|
||||
def not_found_by_tags?
|
||||
url = "#{api_get_path}?tag_list=#{tags.compact.join(',')}"
|
||||
auto_paginated_response(request_url(url)).empty?
|
||||
end
|
||||
|
||||
def runners_list
|
||||
runners_list = nil
|
||||
url = tags ? "#{api_get_path}?tag_list=#{tags.compact.join(',')}" : api_get_path
|
||||
Runtime::Logger.info('Looking for list of runners via API...')
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1) do
|
||||
runners_list = auto_paginated_response(request_url(url))
|
||||
runners_list.present?
|
||||
end
|
||||
|
||||
runners_list
|
||||
end
|
||||
|
||||
def wait_until_online
|
||||
Runtime::Logger.info('Waiting for runner to come online...')
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1) do
|
||||
this_runner[:status] == 'online'
|
||||
end
|
||||
end
|
||||
|
||||
def restart
|
||||
Runtime::Logger.info("Restarting runner container #{name}...")
|
||||
@docker_container.restart
|
||||
wait_until_online
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def start_container_and_register
|
||||
@docker_container = Service::DockerRun::GitlabRunner.new(name).tap do |runner|
|
||||
Support::Retrier.retry_on_exception(sleep_interval: 5) do
|
||||
runner.pull
|
||||
end
|
||||
|
||||
runner.token = @token ||= project.runners_token
|
||||
runner.address = Runtime::Scenario.gitlab_address
|
||||
runner.tags = tags if tags
|
||||
runner.image = image
|
||||
runner.config = config if config
|
||||
runner.executor = executor
|
||||
runner.executor_image = executor_image if executor == :docker
|
||||
runner.run_untagged = run_untagged if run_untagged
|
||||
runner.register!
|
||||
end
|
||||
end
|
||||
|
||||
def this_runner
|
||||
runner = nil
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1) do
|
||||
runner = runners_list.find { |runner| runner[:description] == name }
|
||||
!runner.nil?
|
||||
end
|
||||
runner
|
||||
end
|
||||
|
||||
def populate_runner_attributes
|
||||
runner = this_runner
|
||||
@id = runner[:id]
|
||||
@active = runner[:active]
|
||||
@paused = runner[:paused]
|
||||
@runner_type = runner[:typed]
|
||||
@online = runner[:online]
|
||||
@status = runner[:status]
|
||||
@ip_address = runner[:ip_address]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class RunnerBase < Base
|
||||
attr_accessor :run_untagged,
|
||||
:image,
|
||||
:executor,
|
||||
:executor_image,
|
||||
:tags,
|
||||
:config
|
||||
|
||||
attributes :id,
|
||||
:active,
|
||||
:paused,
|
||||
:runner_type,
|
||||
:online,
|
||||
:status,
|
||||
:ip_address,
|
||||
:description,
|
||||
:name,
|
||||
:is_shared,
|
||||
:contacted_at,
|
||||
:platform,
|
||||
:architecture,
|
||||
:projects,
|
||||
:revision,
|
||||
:tag_list,
|
||||
:version,
|
||||
:access_level,
|
||||
:maximum_timeout
|
||||
|
||||
def initialize
|
||||
@tags = nil
|
||||
@config = nil
|
||||
@run_untagged = nil
|
||||
@name = "qa-runner-#{SecureRandom.hex(4)}"
|
||||
@image = 'registry.gitlab.com/gitlab-org/gitlab-runner:alpine'
|
||||
@executor = :shell
|
||||
@executor_image = 'registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7'
|
||||
end
|
||||
|
||||
# Initially we only support fabricate via API
|
||||
def fabricate!
|
||||
fabricate_via_api!
|
||||
end
|
||||
|
||||
# Start container and register runner
|
||||
# Fetch via API and populate attributes
|
||||
#
|
||||
def fabricate_via_api!
|
||||
api_get
|
||||
rescue NoValueError
|
||||
# Start container on initial fabrication and populate all attributes once id is known
|
||||
# see: https://docs.gitlab.com/ee/api/runners.html#get-runners-details
|
||||
start_container_and_register
|
||||
api_get
|
||||
end
|
||||
|
||||
def remove_via_api!
|
||||
super
|
||||
ensure
|
||||
@docker_container.remove!
|
||||
@docker_container = nil
|
||||
end
|
||||
|
||||
def api_get_path
|
||||
"/runners/#{id}"
|
||||
end
|
||||
|
||||
def api_post_path
|
||||
"/runners"
|
||||
end
|
||||
|
||||
def api_delete_path
|
||||
api_get_path
|
||||
end
|
||||
|
||||
def api_post_body; end
|
||||
|
||||
def wait_until_online
|
||||
Runtime::Logger.info('Waiting for runner to come online...')
|
||||
Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1) do
|
||||
reload! && status == 'online'
|
||||
end
|
||||
end
|
||||
|
||||
def restart
|
||||
Runtime::Logger.info("Restarting runner container #{name}...")
|
||||
@docker_container.restart
|
||||
wait_until_online
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def start_container_and_register
|
||||
@docker_container ||= Service::DockerRun::GitlabRunner.new(name).tap do |runner|
|
||||
Support::Retrier.retry_on_exception(sleep_interval: 5) do
|
||||
runner.pull
|
||||
end
|
||||
|
||||
runner.token = token
|
||||
runner.address = Runtime::Scenario.gitlab_address
|
||||
runner.tags = tags if tags
|
||||
runner.image = image
|
||||
runner.config = config if config
|
||||
runner.executor = executor
|
||||
runner.executor_image = executor_image if executor == :docker
|
||||
runner.run_untagged = run_untagged if run_untagged
|
||||
runner.register!
|
||||
end
|
||||
populate_initial_id
|
||||
rescue StandardError => e
|
||||
@docker_container&.remove!
|
||||
raise(e)
|
||||
end
|
||||
|
||||
def populate_initial_id
|
||||
tag_list = tags ? { tag_list: tags.compact.join(',') } : {}
|
||||
runner = runner(**tag_list)
|
||||
@id = runner[:id]
|
||||
end
|
||||
|
||||
def runner(**kwargs)
|
||||
raise("Not implemented!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,6 +8,10 @@ module QA
|
|||
def qa_root
|
||||
::File.expand_path('../../', __dir__)
|
||||
end
|
||||
|
||||
def fixtures_path
|
||||
::File.expand_path('../fixtures', __dir__)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ module QA
|
|||
end
|
||||
|
||||
def register!
|
||||
raise("Missing runner token value!") unless token
|
||||
|
||||
cmd = <<~CMD.tr("\n", ' ')
|
||||
docker run -d --rm --network #{runner_network} --name #{@name}
|
||||
#{'-v /var/run/docker.sock:/var/run/docker.sock' if @executor == :docker}
|
||||
|
|
|
|||
|
|
@ -7,26 +7,45 @@ module QA
|
|||
def initialize
|
||||
@image = 'thiht/smocker:0.17.1'
|
||||
@name = 'smocker-server'
|
||||
@public_port = '8080'
|
||||
@admin_port = '8081'
|
||||
@public_port = 8080
|
||||
@admin_port = 8081
|
||||
super
|
||||
@network_cache = network
|
||||
end
|
||||
|
||||
# @param wait [Integer] seconds to wait for server
|
||||
# @yieldparam [SmockerApi] the api object ready for interaction
|
||||
def self.init(wait: 10)
|
||||
if @container.nil?
|
||||
@container = new
|
||||
@container.register!
|
||||
@container.wait_for_running
|
||||
|
||||
@api = Vendor::Smocker::SmockerApi.new(
|
||||
host: @container.host_name,
|
||||
public_port: @container.public_port,
|
||||
admin_port: @container.admin_port
|
||||
)
|
||||
@api.wait_for_ready(wait: wait)
|
||||
end
|
||||
|
||||
yield @api
|
||||
end
|
||||
|
||||
def self.teardown!
|
||||
@container&.remove!
|
||||
@container = nil
|
||||
@api = nil
|
||||
end
|
||||
|
||||
attr_reader :public_port, :admin_port
|
||||
|
||||
def host_name
|
||||
return '127.0.0.1' unless QA::Runtime::Env.running_in_ci? || QA::Runtime::Env.qa_hostname
|
||||
|
||||
"#{@name}.#{@network_cache}"
|
||||
end
|
||||
|
||||
def base_url
|
||||
"http://#{host_name}:#{@public_port}"
|
||||
end
|
||||
|
||||
def admin_url
|
||||
"http://#{host_name}:#{@admin_port}"
|
||||
end
|
||||
|
||||
def wait_for_running
|
||||
Support::Waiter.wait_until(raise_on_failure: false, reload_page: false) do
|
||||
running?
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ module QA
|
|||
|
||||
context 'when imported via api' do
|
||||
it 'imports project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do
|
||||
imported_project.reload! # import the project
|
||||
|
||||
expect { imported_project.project_import_status[:import_status] }.to eventually_eq('finished')
|
||||
.within(max_duration: 240, sleep_interval: 1)
|
||||
expect_project_import_finished_successfully
|
||||
|
||||
aggregate_failures do
|
||||
verify_status_data
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module QA
|
|||
end
|
||||
|
||||
after(:context) do
|
||||
Vendor::Smocker::SmockerApi.teardown!
|
||||
Service::DockerRun::Smocker.teardown!
|
||||
end
|
||||
|
||||
let(:session) { SecureRandom.hex(5) }
|
||||
|
|
@ -72,7 +72,7 @@ module QA
|
|||
end
|
||||
|
||||
it 'sends an issues and note event',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349723' do
|
||||
setup_webhook(issues: true, note: true) do |webhook, smocker|
|
||||
issue = Resource::Issue.fabricate_via_api! do |issue_init|
|
||||
issue_init.project = webhook.project
|
||||
|
|
@ -100,7 +100,7 @@ module QA
|
|||
end
|
||||
|
||||
it 'sends a tag event',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/383577' do
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/383577' do
|
||||
setup_webhook(tag_push: true) do |webhook, smocker|
|
||||
project_push = Resource::Repository::ProjectPush.fabricate! do |project_push|
|
||||
project_push.project = webhook.project
|
||||
|
|
@ -128,7 +128,7 @@ module QA
|
|||
private
|
||||
|
||||
def setup_webhook(**event_args)
|
||||
Vendor::Smocker::SmockerApi.init(wait: 10) do |smocker|
|
||||
Service::DockerRun::Smocker.init(wait: 10) do |smocker|
|
||||
smocker.register(session: session)
|
||||
|
||||
webhook = Resource::ProjectWebHook.fabricate_via_api! do |hook|
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = "runner-for-#{project.name}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :runner do
|
||||
describe 'Runner removal' do
|
||||
include Support::API
|
||||
|
||||
let(:api_client) { Runtime::API::Client.new(:gitlab) }
|
||||
let(:executor) { "qa-runner-#{Time.now.to_i}" }
|
||||
let(:runner_tags) { ["runner-registration-e2e-test-#{Faker::Alphanumeric.alphanumeric(number: 8)}"] }
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
runner.name = executor
|
||||
runner.tags = runner_tags
|
||||
end
|
||||
end
|
||||
|
||||
# Removing a runner via the UI is covered by `spec/features/runners_spec.rb``
|
||||
it 'removes the runner', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/354828' do
|
||||
runners_list = runner.runners_list
|
||||
expect(runners_list.size).to eq(1)
|
||||
expect(runners_list.first[:description]).to eq(executor)
|
||||
|
||||
request = Runtime::API::Request.new(api_client, "runners/#{runner.id}")
|
||||
response = delete(request.url)
|
||||
expect(response.code).to eq(Support::API::HTTP_STATUS_NO_CONTENT)
|
||||
expect(response.body).to be_empty
|
||||
|
||||
expect(runner).to be_not_found_by_tags
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -36,7 +36,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = runner_name
|
||||
runner.tags = [runner_name]
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ module QA
|
|||
# Update spec along with Feature Flag Removal.
|
||||
Runtime::Feature.disable(:show_pages_in_deployments_menu)
|
||||
Flow::Login.sign_in
|
||||
Resource::Runner.fabricate_via_api! do |runner|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
runner.executor = :docker
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ module QA
|
|||
)
|
||||
end
|
||||
|
||||
@runner = Resource::Runner.fabricate_via_api! do |runner|
|
||||
@runner = Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = %w[web-ide]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate_via_api! do |runner|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
runner.name = project.name
|
||||
runner.tags = [project.name]
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
runner.token = group.reload!.runners_token
|
||||
runner.group = group
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = runner_name
|
||||
runner.tags = [runner_name]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate_via_api! do |runner|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
runner.name = random_test_string
|
||||
runner.tags = [random_test_string]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module QA
|
|||
describe 'Runner registration' do
|
||||
let(:executor) { "qa-runner-#{Time.now.to_i}" }
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = executor
|
||||
runner.tags = ['e2e-test']
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate_via_api! do |runner|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.project = project
|
||||
runner.name = project.name
|
||||
runner.tags = [project.name]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module QA
|
|||
describe 'Code coverage statistics' do
|
||||
let(:executor) { "qa-runner-#{Time.now.to_i}" }
|
||||
let(:runner) do
|
||||
Resource::Runner.fabricate_via_api! do |runner|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |runner|
|
||||
runner.name = executor
|
||||
runner.tags = ['e2e-test']
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@ module QA
|
|||
end
|
||||
|
||||
let(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{imported_project.name}"]
|
||||
runner.executor = :docker
|
||||
runner.project = imported_project
|
||||
runner.token = group.reload!.runners_token
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ module QA
|
|||
end
|
||||
|
||||
let(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{package_project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
@ -173,11 +173,11 @@ module QA
|
|||
end
|
||||
|
||||
let(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{imported_project.name}"]
|
||||
runner.executor = :docker
|
||||
runner.token = group.reload!.runners_token
|
||||
runner.group = group
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.group.name}"]
|
||||
runner.executor = :docker
|
||||
runner.token = project.group.reload!.runners_token
|
||||
runner.group = project.group
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.group.name}"]
|
||||
runner.executor = :docker
|
||||
runner.token = project.group.reload!.runners_token
|
||||
runner.group = project.group
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ product_group: :package_registry do
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{project.name}"]
|
||||
runner.executor = :docker
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate_via_api! do |resource|
|
||||
Resource::ProjectRunner.fabricate_via_api! do |resource|
|
||||
resource.project = project
|
||||
resource.name = runner_name
|
||||
resource.tags = [runner_name]
|
||||
|
|
|
|||
|
|
@ -35,8 +35,44 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
let(:smocker_host) { ENV["QA_SMOCKER_HOST"] }
|
||||
let(:smocker) do
|
||||
Vendor::Smocker::SmockerApi.new(
|
||||
host: smocker_host,
|
||||
public_port: 443,
|
||||
admin_port: 8081,
|
||||
tls: true
|
||||
)
|
||||
end
|
||||
|
||||
let(:mocks_path) { File.join(Runtime::Path.fixtures_path, "mocks", "import") }
|
||||
|
||||
before do
|
||||
set_mocks
|
||||
group.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
|
||||
end
|
||||
|
||||
def expect_project_import_finished_successfully
|
||||
imported_project.reload! # import the project
|
||||
|
||||
status = nil
|
||||
Support::Retrier.retry_until(max_duration: 240, sleep_interval: 1, raise_on_failure: false) do
|
||||
status = imported_project.project_import_status[:import_status]
|
||||
%w[finished failed].include?(status)
|
||||
end
|
||||
|
||||
# finished status means success, all other statuses are considered to fail the test
|
||||
expect(status).to eq('finished'), "Expected import to finish successfully, but status was: #{status}"
|
||||
end
|
||||
|
||||
# Setup github mocked responses if mock server host is present
|
||||
#
|
||||
# @return [void]
|
||||
def set_mocks
|
||||
return Runtime::Logger.warn("Mock host is not set, skipping github response setup") unless smocker_host
|
||||
|
||||
smocker.reset
|
||||
smocker.register(File.read(File.join(mocks_path, "github.yml")))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::ProjectRunner.fabricate! do |runner|
|
||||
runner.project = project
|
||||
runner.name = executor
|
||||
runner.tags = [executor]
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ module QA
|
|||
end
|
||||
|
||||
let(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.name = "qa-runner-#{Time.now.to_i}"
|
||||
runner.tags = ["runner-for-#{package_project.group.name}"]
|
||||
runner.executor = :docker
|
||||
runner.token = package_project.group.reload!.runners_token
|
||||
runner.group = package_project.group
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ module QA
|
|||
end
|
||||
|
||||
let!(:runner) do
|
||||
Resource::Runner.fabricate! do |runner|
|
||||
runner.token = group.reload!.runners_token
|
||||
Resource::GroupRunner.fabricate! do |runner|
|
||||
runner.group = group
|
||||
runner.name = random_string
|
||||
runner.tags = [random_string]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,36 +17,21 @@ module QA
|
|||
body: '{}'
|
||||
YAML
|
||||
|
||||
# @param wait [Integer] seconds to wait for server
|
||||
# @yieldparam [SmockerApi] the api object ready for interaction
|
||||
def self.init(**wait_args)
|
||||
if @container.nil?
|
||||
@container = Service::DockerRun::Smocker.new
|
||||
@container.register!
|
||||
@container.wait_for_running
|
||||
end
|
||||
|
||||
yield new(@container, **wait_args)
|
||||
end
|
||||
|
||||
def self.teardown!
|
||||
@container&.remove!
|
||||
@container = nil
|
||||
end
|
||||
|
||||
def initialize(container, **wait_args)
|
||||
@container = container
|
||||
wait_for_ready(**wait_args)
|
||||
def initialize(host:, public_port: 8080, admin_port: 8081, tls: false)
|
||||
@host = host
|
||||
@public_port = public_port
|
||||
@admin_port = admin_port
|
||||
@scheme = tls ? "https" : "http"
|
||||
end
|
||||
|
||||
# @return [String] Base url of mock endpoint
|
||||
def base_url
|
||||
@container.base_url
|
||||
@base_url ||= "#{scheme}://#{host}:#{public_port}"
|
||||
end
|
||||
|
||||
# @return [String] Url of admin endpoint
|
||||
def admin_url
|
||||
@container.admin_url
|
||||
@admin_url ||= "#{scheme}://#{host}:#{admin_port}"
|
||||
end
|
||||
|
||||
# @param endpoint [String] path for mock endpoint
|
||||
|
|
@ -130,6 +115,8 @@ module QA
|
|||
|
||||
private
|
||||
|
||||
attr_reader :host, :public_port, :admin_port, :scheme
|
||||
|
||||
def build_params(**args)
|
||||
args.each_with_object([]) do |(k, v), memo|
|
||||
memo << "#{k}=#{v}" if v
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
require_relative '../qa'
|
||||
|
||||
require_relative 'scenario_shared_examples'
|
||||
require_relative('../../jh/qa/spec/spec_helper') if GitlabEdition.jh?
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { GlLabel, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
|
||||
import { range } from 'lodash';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import { nextTick } from 'vue';
|
||||
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
|
@ -17,6 +17,8 @@ import { mockLabelList, mockIssue, mockIssueFullPath } from './mock_data';
|
|||
jest.mock('~/lib/utils/url_utility');
|
||||
jest.mock('~/boards/eventhub');
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
describe('Board card component', () => {
|
||||
const user = {
|
||||
id: 1,
|
||||
|
|
@ -52,9 +54,8 @@ describe('Board card component', () => {
|
|||
|
||||
const performSearchMock = jest.fn();
|
||||
|
||||
const createStore = ({ isProjectBoard = false } = {}) => {
|
||||
const createStore = () => {
|
||||
store = new Vuex.Store({
|
||||
...defaultStore,
|
||||
actions: {
|
||||
performSearch: performSearchMock,
|
||||
},
|
||||
|
|
@ -62,14 +63,10 @@ describe('Board card component', () => {
|
|||
...defaultStore.state,
|
||||
isShowingLabels: true,
|
||||
},
|
||||
getters: {
|
||||
isGroupBoard: () => true,
|
||||
isProjectBoard: () => isProjectBoard,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const createWrapper = ({ props = {}, isEpicBoard = false } = {}) => {
|
||||
const createWrapper = ({ props = {}, isEpicBoard = false, isGroupBoard = true } = {}) => {
|
||||
wrapper = mountExtended(BoardCardInner, {
|
||||
store,
|
||||
propsData: {
|
||||
|
|
@ -97,6 +94,7 @@ describe('Board card component', () => {
|
|||
scopedLabelsAvailable: false,
|
||||
isEpicBoard,
|
||||
issuableType: issuableTypes.issue,
|
||||
isGroupBoard,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -164,8 +162,8 @@ describe('Board card component', () => {
|
|||
});
|
||||
|
||||
it('does not render item reference path', () => {
|
||||
createStore({ isProjectBoard: true });
|
||||
createWrapper();
|
||||
createStore();
|
||||
createWrapper({ isGroupBoard: false });
|
||||
|
||||
expect(wrapper.find('.board-card-number').text()).not.toContain(mockIssueFullPath);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ export default function createComponent({
|
|||
...state,
|
||||
},
|
||||
getters: {
|
||||
isGroupBoard: () => false,
|
||||
isProjectBoard: () => true,
|
||||
isEpicBoard: () => false,
|
||||
...getters,
|
||||
},
|
||||
|
|
@ -104,6 +102,8 @@ export default function createComponent({
|
|||
canAdminList: true,
|
||||
isIssueBoard: true,
|
||||
isEpicBoard: false,
|
||||
isGroupBoard: false,
|
||||
isProjectBoard: true,
|
||||
...provide,
|
||||
},
|
||||
stubs,
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@ describe('Board card', () => {
|
|||
...initialState,
|
||||
},
|
||||
actions: mockActions,
|
||||
getters: {
|
||||
isProjectBoard: () => false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -62,6 +59,8 @@ describe('Board card', () => {
|
|||
scopedLabelsAvailable: false,
|
||||
isEpicBoard: false,
|
||||
issuableType: 'issue',
|
||||
isProjectBoard: false,
|
||||
isGroupBoard: true,
|
||||
...provide,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ describe('BoardContentSidebar', () => {
|
|||
groupPathForActiveIssue: () => mockIssueGroupPath,
|
||||
projectPathForActiveIssue: () => mockIssueProjectPath,
|
||||
isSidebarOpen: () => true,
|
||||
isGroupBoard: () => false,
|
||||
...mockGetters,
|
||||
},
|
||||
actions: mockActions,
|
||||
|
|
@ -55,6 +54,7 @@ describe('BoardContentSidebar', () => {
|
|||
rootPath: '/',
|
||||
groupId: 1,
|
||||
issuableType: issuableTypes.issue,
|
||||
isGroupBoard: false,
|
||||
},
|
||||
store,
|
||||
stubs: {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ describe('BoardContent', () => {
|
|||
issuableType,
|
||||
isIssueBoard,
|
||||
isEpicBoard,
|
||||
isGroupBoard: true,
|
||||
isApolloBoard,
|
||||
},
|
||||
store,
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ describe('BoardForm', () => {
|
|||
const setErrorMock = jest.fn();
|
||||
|
||||
const store = new Vuex.Store({
|
||||
getters: {
|
||||
isGroupBoard: () => true,
|
||||
isProjectBoard: () => false,
|
||||
},
|
||||
actions: {
|
||||
setBoard: setBoardMock,
|
||||
setError: setErrorMock,
|
||||
|
|
@ -73,6 +69,8 @@ describe('BoardForm', () => {
|
|||
},
|
||||
provide: {
|
||||
boardBaseUrl: 'root',
|
||||
isGroupBoard: true,
|
||||
isProjectBoard: false,
|
||||
},
|
||||
mocks: {
|
||||
$apollo: {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ const mockActions = { addListNewIssue: addListNewIssuesSpy };
|
|||
const createComponent = ({
|
||||
state = { selectedProject: mockGroupProjects[0] },
|
||||
actions = mockActions,
|
||||
getters = { isGroupBoard: () => true, getBoardItemsByList: () => () => [] },
|
||||
getters = { getBoardItemsByList: () => () => [] },
|
||||
isGroupBoard = true,
|
||||
} = {}) =>
|
||||
shallowMount(BoardNewIssue, {
|
||||
store: new Vuex.Store({
|
||||
|
|
@ -32,6 +33,7 @@ const createComponent = ({
|
|||
fullPath: mockGroupProjects[0].fullPath,
|
||||
weightFeatureAvailable: false,
|
||||
boardWeight: null,
|
||||
isGroupBoard,
|
||||
},
|
||||
stubs: {
|
||||
BoardNewItem,
|
||||
|
|
@ -85,9 +87,9 @@ describe('Issue boards new issue form', () => {
|
|||
beforeEach(() => {
|
||||
wrapper = createComponent({
|
||||
getters: {
|
||||
isGroupBoard: () => true,
|
||||
getBoardItemsByList: () => () => [mockIssue, mockIssue2],
|
||||
},
|
||||
isGroupBoard: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ describe('Issue boards new issue form', () => {
|
|||
describe('when in project issue board', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({
|
||||
getters: { isGroupBoard: () => false },
|
||||
isGroupBoard: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ describe('BoardTopBar', () => {
|
|||
boardType: 'group',
|
||||
releasesFetchPath: '/releases',
|
||||
isIssueBoard: true,
|
||||
isGroupBoard: true,
|
||||
...provide,
|
||||
},
|
||||
stubs: { IssueBoardFilteredSearch },
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import groupBoardsQuery from '~/boards/graphql/group_boards.query.graphql';
|
|||
import projectBoardsQuery from '~/boards/graphql/project_boards.query.graphql';
|
||||
import groupRecentBoardsQuery from '~/boards/graphql/group_recent_boards.query.graphql';
|
||||
import projectRecentBoardsQuery from '~/boards/graphql/project_recent_boards.query.graphql';
|
||||
import defaultStore from '~/boards/stores';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import {
|
||||
|
|
@ -28,23 +27,19 @@ import {
|
|||
const throttleDuration = 1;
|
||||
|
||||
Vue.use(VueApollo);
|
||||
Vue.use(Vuex);
|
||||
|
||||
describe('BoardsSelector', () => {
|
||||
let wrapper;
|
||||
let fakeApollo;
|
||||
let store;
|
||||
|
||||
const createStore = ({ isGroupBoard = false, isProjectBoard = false } = {}) => {
|
||||
const createStore = () => {
|
||||
store = new Vuex.Store({
|
||||
...defaultStore,
|
||||
actions: {
|
||||
setError: jest.fn(),
|
||||
setBoardConfig: jest.fn(),
|
||||
},
|
||||
getters: {
|
||||
isGroupBoard: () => isGroupBoard,
|
||||
isProjectBoard: () => isProjectBoard,
|
||||
},
|
||||
state: {
|
||||
board: mockBoard,
|
||||
},
|
||||
|
|
@ -86,6 +81,7 @@ describe('BoardsSelector', () => {
|
|||
projectBoardsQueryHandler = projectBoardsQueryHandlerSuccess,
|
||||
projectRecentBoardsQueryHandler = projectRecentBoardsQueryHandlerSuccess,
|
||||
isGroupBoard = false,
|
||||
isProjectBoard = false,
|
||||
} = {}) => {
|
||||
fakeApollo = createMockApollo([
|
||||
[projectBoardsQuery, projectBoardsQueryHandler],
|
||||
|
|
@ -110,6 +106,8 @@ describe('BoardsSelector', () => {
|
|||
scopedIssueBoardFeatureEnabled: true,
|
||||
weights: [],
|
||||
boardType: isGroupBoard ? 'group' : 'project',
|
||||
isGroupBoard,
|
||||
isProjectBoard,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -121,8 +119,8 @@ describe('BoardsSelector', () => {
|
|||
|
||||
describe('template', () => {
|
||||
beforeEach(() => {
|
||||
createStore({ isProjectBoard: true });
|
||||
createComponent();
|
||||
createStore();
|
||||
createComponent({ isProjectBoard: true });
|
||||
});
|
||||
|
||||
describe('loading', () => {
|
||||
|
|
@ -230,11 +228,11 @@ describe('BoardsSelector', () => {
|
|||
${BoardType.group} | ${groupBoardsQueryHandlerSuccess} | ${projectBoardsQueryHandlerSuccess}
|
||||
${BoardType.project} | ${projectBoardsQueryHandlerSuccess} | ${groupBoardsQueryHandlerSuccess}
|
||||
`('fetches $boardType boards', async ({ boardType, queryHandler, notCalledHandler }) => {
|
||||
createStore({
|
||||
isProjectBoard: boardType === BoardType.project,
|
||||
createStore();
|
||||
createComponent({
|
||||
isGroupBoard: boardType === BoardType.group,
|
||||
isProjectBoard: boardType === BoardType.project,
|
||||
});
|
||||
createComponent({ isGroupBoard: boardType === BoardType.group });
|
||||
|
||||
await nextTick();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ describe('IssueBoardFilter', () => {
|
|||
isSignedIn,
|
||||
releasesFetchPath: '/releases',
|
||||
fullPath: 'gitlab-org',
|
||||
boardType: 'group',
|
||||
isGroupBoard: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,42 +12,6 @@ import {
|
|||
} from '../mock_data';
|
||||
|
||||
describe('Boards - Getters', () => {
|
||||
describe('isGroupBoard', () => {
|
||||
it('returns true when boardType on state is group', () => {
|
||||
const state = {
|
||||
boardType: 'group',
|
||||
};
|
||||
|
||||
expect(getters.isGroupBoard(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when boardType on state is not group', () => {
|
||||
const state = {
|
||||
boardType: 'project',
|
||||
};
|
||||
|
||||
expect(getters.isGroupBoard(state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isProjectBoard', () => {
|
||||
it('returns true when boardType on state is project', () => {
|
||||
const state = {
|
||||
boardType: 'project',
|
||||
};
|
||||
|
||||
expect(getters.isProjectBoard(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when boardType on state is not project', () => {
|
||||
const state = {
|
||||
boardType: 'group',
|
||||
};
|
||||
|
||||
expect(getters.isProjectBoard(state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSidebarOpen', () => {
|
||||
it('returns true when activeId is not equal to 0', () => {
|
||||
const state = {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,47 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator,
|
|||
it { is_expected.to be_valid }
|
||||
end
|
||||
|
||||
context 'when components have licenses' do
|
||||
let(:components) do
|
||||
[
|
||||
{
|
||||
"type" => "library",
|
||||
"name" => "activesupport",
|
||||
"version" => "5.1.4",
|
||||
"licenses" => [
|
||||
{ "license" => { "id" => "MIT" } }
|
||||
]
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
it { is_expected.to be_valid }
|
||||
end
|
||||
|
||||
context 'when components have a signature' do
|
||||
let(:components) do
|
||||
[
|
||||
{
|
||||
"type" => "library",
|
||||
"name" => "activesupport",
|
||||
"version" => "5.1.4",
|
||||
"signature" => {
|
||||
"algorithm" => "ES256",
|
||||
"publicKey" => {
|
||||
"kty" => "EC",
|
||||
"crv" => "P-256",
|
||||
"x" => "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
|
||||
"y" => "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg"
|
||||
},
|
||||
"value" => "ybT1qz5zHNi4Ndc6y7Zhamuf51IqXkPkZwjH1XcC-KSuBiaQplTw6Jasf2MbCLg3CF7PAdnMO__WSLwvI5r2jA"
|
||||
}
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
it { is_expected.to be_valid }
|
||||
end
|
||||
|
||||
context "when components are not valid" do
|
||||
let(:components) do
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in New Issue