Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-10-25 21:12:12 +00:00
parent 942229d2b4
commit 4d0bc99be4
30 changed files with 329 additions and 39 deletions

View file

@ -193,9 +193,7 @@ graphql-schema-dump:
# Disable warnings in browserslist which can break on backports # Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384 # https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true" BROWSERSLIST_IGNORE_OLD_DATA: "true"
SETUP_DB: "false"
before_script: before_script:
- !reference [.default-before_script, before_script]
- *yarn-install - *yarn-install
stage: test stage: test

View file

@ -476,7 +476,7 @@ end
gem 'spamcheck', '~> 0.1.0' gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions # Gitaly GRPC protocol definitions
gem 'gitaly', '~> 14.3.0.pre.rc2' gem 'gitaly', '~> 14.4.0.pre.rc43'
# KAS GRPC protocol definitions # KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2' gem 'kas-grpc', '~> 0.0.2'

View file

@ -450,7 +450,7 @@ GEM
rails (>= 3.2.0) rails (>= 3.2.0)
git (1.7.0) git (1.7.0)
rchardet (~> 1.8) rchardet (~> 1.8)
gitaly (14.3.0.pre.rc2) gitaly (14.4.0.pre.rc43)
grpc (~> 1.0) grpc (~> 1.0)
github-markup (1.7.0) github-markup (1.7.0)
gitlab (4.16.1) gitlab (4.16.1)
@ -1457,7 +1457,7 @@ DEPENDENCIES
gettext (~> 3.3) gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
gitaly (~> 14.3.0.pre.rc2) gitaly (~> 14.4.0.pre.rc43)
github-markup (~> 1.7.0) github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5) gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.3.1) gitlab-dangerfiles (~> 2.3.1)

View file

@ -20,7 +20,7 @@ export default {
<gl-sprintf <gl-sprintf
:message=" :message="
s__( s__(
'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.', 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
) )
" "
> >

View file

@ -63,6 +63,7 @@ export default {
v-if="showPipelineStatus" v-if="showPipelineStatus"
:commit-sha="commitSha" :commit-sha="commitSha"
:class="$options.pipelineStatusClasses" :class="$options.pipelineStatusClasses"
v-on="$listeners"
/> />
<validation-segment :class="validationStyling" :ci-config="ciConfigData" /> <validation-segment :class="validationStyling" :ci-config="ciConfigData" />
</div> </div>

View file

@ -1,17 +1,52 @@
<script> <script>
import { __ } from '~/locale';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
import { PIPELINE_FAILURE } from '../../constants';
export default { export default {
i18n: {
linkedPipelinesFetchError: __('Unable to fetch upstream and downstream pipelines.'),
},
components: { components: {
PipelineMiniGraph, PipelineMiniGraph,
LinkedPipelinesMiniList: () =>
import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
}, },
inject: ['projectFullPath'],
props: { props: {
pipeline: { pipeline: {
type: Object, type: Object,
required: true, required: true,
}, },
}, },
apollo: {
linkedPipelines: {
query: getLinkedPipelinesQuery,
variables() {
return {
fullPath: this.projectFullPath,
iid: this.pipeline.iid,
};
},
skip() {
return !this.pipeline.iid;
},
update({ project }) {
return project?.pipeline;
},
error() {
this.$emit('showError', {
type: PIPELINE_FAILURE,
reasons: [this.$options.i18n.linkedPipelinesFetchError],
});
},
},
},
computed: { computed: {
downstreamPipelines() {
return this.linkedPipelines?.downstream?.nodes || [];
},
pipelinePath() { pipelinePath() {
return this.pipeline.detailedStatus?.detailsPath || ''; return this.pipeline.detailedStatus?.detailsPath || '';
}, },
@ -38,12 +73,29 @@ export default {
}; };
}); });
}, },
showDownstreamPipelines() {
return this.downstreamPipelines.length > 0;
},
upstreamPipeline() {
return this.linkedPipelines?.upstream;
},
}, },
}; };
</script> </script>
<template> <template>
<div v-if="pipelineStages.length > 0" class="stage-cell gl-mr-5"> <div v-if="pipelineStages.length > 0" class="stage-cell gl-mr-5">
<linked-pipelines-mini-list
v-if="upstreamPipeline"
:triggered-by="[upstreamPipeline]"
data-testid="pipeline-editor-mini-graph-upstream"
/>
<pipeline-mini-graph class="gl-display-inline" :stages="pipelineStages" /> <pipeline-mini-graph class="gl-display-inline" :stages="pipelineStages" />
<linked-pipelines-mini-list
v-if="showDownstreamPipelines"
:triggered="downstreamPipelines"
:pipeline-path="pipelinePath"
data-testid="pipeline-editor-mini-graph-downstream"
/>
</div> </div>
</template> </template>

View file

@ -62,11 +62,12 @@ export default {
}; };
}, },
update(data) { update(data) {
const { id, commitPath = '', detailedStatus = {}, stages, status } = const { id, iid, commitPath = '', detailedStatus = {}, stages, status } =
data.project?.pipeline || {}; data.project?.pipeline || {};
return { return {
id, id,
iid,
commitPath, commitPath,
detailedStatus, detailedStatus,
stages, stages,
@ -174,6 +175,7 @@ export default {
<pipeline-editor-mini-graph <pipeline-editor-mini-graph
v-if="glFeatures.pipelineEditorMiniGraph" v-if="glFeatures.pipelineEditorMiniGraph"
:pipeline="pipeline" :pipeline="pipeline"
v-on="$listeners"
/> />
<gl-button <gl-button
class="gl-mt-2 gl-md-mt-0" class="gl-mt-2 gl-md-mt-0"

View file

@ -8,6 +8,7 @@ import {
DEFAULT_FAILURE, DEFAULT_FAILURE,
DEFAULT_SUCCESS, DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN, LOAD_FAILURE_UNKNOWN,
PIPELINE_FAILURE,
} from '../../constants'; } from '../../constants';
import CodeSnippetAlert from '../code_snippet_alert/code_snippet_alert.vue'; import CodeSnippetAlert from '../code_snippet_alert/code_snippet_alert.vue';
import { import {
@ -24,6 +25,7 @@ export default {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'), [COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'), [DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'), [LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
[PIPELINE_FAILURE]: s__('Pipelines|There was a problem with loading the pipeline data.'),
}, },
successTexts: { successTexts: {
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'), [COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
@ -74,6 +76,11 @@ export default {
text: this.$options.errorTexts[COMMIT_FAILURE], text: this.$options.errorTexts[COMMIT_FAILURE],
variant: 'danger', variant: 'danger',
}; };
case PIPELINE_FAILURE:
return {
text: this.$options.errorTexts[PIPELINE_FAILURE],
variant: 'danger',
};
default: default:
return { return {
text: this.$options.errorTexts[DEFAULT_FAILURE], text: this.$options.errorTexts[DEFAULT_FAILURE],

View file

@ -16,6 +16,7 @@ export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
export const DEFAULT_FAILURE = 'DEFAULT_FAILURE'; export const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
export const DEFAULT_SUCCESS = 'DEFAULT_SUCCESS'; export const DEFAULT_SUCCESS = 'DEFAULT_SUCCESS';
export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN'; export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
export const PIPELINE_FAILURE = 'PIPELINE_FAILURE';
export const CREATE_TAB = 'CREATE_TAB'; export const CREATE_TAB = 'CREATE_TAB';
export const LINT_TAB = 'LINT_TAB'; export const LINT_TAB = 'LINT_TAB';

View file

@ -93,6 +93,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
ciExamplesHelpPagePath, ciExamplesHelpPagePath,
ciHelpPagePath, ciHelpPagePath,
configurationPaths, configurationPaths,
dataMethod: 'graphql',
defaultBranch, defaultBranch,
emptyStateIllustrationPath, emptyStateIllustrationPath,
helpPaths, helpPaths,

View file

@ -111,6 +111,7 @@ export default {
:ci-config-data="ciConfigData" :ci-config-data="ciConfigData"
:commit-sha="commitSha" :commit-sha="commitSha"
:is-new-ci-config-file="isNewCiConfigFile" :is-new-ci-config-file="isNewCiConfigFile"
v-on="$listeners"
/> />
<pipeline-editor-tabs <pipeline-editor-tabs
:ci-config-data="ciConfigData" :ci-config-data="ciConfigData"

View file

@ -76,13 +76,21 @@ export default {
}, },
onTokenReset(token) { onTokenReset(token) {
this.currentRegistrationToken = token; this.currentRegistrationToken = token;
this.$refs.runnerRegistrationDropdown.hide(true);
}, },
}, },
}; };
</script> </script>
<template> <template>
<gl-dropdown menu-class="gl-w-auto!" :text="dropdownText" variant="confirm" v-bind="$attrs"> <gl-dropdown
ref="runnerRegistrationDropdown"
menu-class="gl-w-auto!"
:text="dropdownText"
variant="confirm"
v-bind="$attrs"
>
<gl-dropdown-item @click.capture.native.stop="onShowInstructionsClick"> <gl-dropdown-item @click.capture.native.stop="onShowInstructionsClick">
{{ $options.i18n.showInstallationInstructions }} {{ $options.i18n.showInstallationInstructions }}
<runner-instructions-modal <runner-instructions-modal

View file

@ -302,6 +302,14 @@ module Integrations
private private
def branch_name(noteable)
if Feature.enabled?(:jira_use_first_ref_by_oid, project, default_enabled: :yaml)
noteable.first_ref_by_oid(project.repository)
else
noteable.ref_names(project.repository).first
end
end
def server_info def server_info
strong_memoize(:server_info) do strong_memoize(:server_info) do
client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil
@ -495,7 +503,7 @@ module Integrations
{ {
id: noteable.short_id, id: noteable.short_id,
description: noteable.safe_message, description: noteable.safe_message,
branch: noteable.ref_names(project.repository).first branch: branch_name(noteable)
} }
elsif noteable.is_a?(MergeRequest) elsif noteable.is_a?(MergeRequest)
{ {

View file

@ -5,8 +5,6 @@ module MergeRequests
MAX_RETARGET_MERGE_REQUESTS = 4 MAX_RETARGET_MERGE_REQUESTS = 4
def execute(merge_request) def execute(merge_request)
return unless Feature.enabled?(:retarget_merge_requests, merge_request.target_project, default_enabled: :yaml)
# we can only retarget MRs that are targeting the same project # we can only retarget MRs that are targeting the same project
return unless merge_request.for_same_project? && merge_request.merged? return unless merge_request.for_same_project? && merge_request.merged?

View file

@ -1,8 +1,8 @@
--- ---
name: retarget_merge_requests name: jira_use_first_ref_by_oid
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53710 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72739
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320895 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343585
milestone: '13.9' milestone: '14.5'
type: development type: development
group: group::memory group: group::integrations
default_enabled: true default_enabled: false

View file

@ -321,15 +321,16 @@ We execute both analyzers because they use different sources of vulnerability da
The analyzer for these languages supports multiple lockfiles. The analyzer for these languages supports multiple lockfiles.
### Future support for additional languages ### Support for additional languages
Plans are underway for supporting the following languages, dependency managers, and dependency files. For details, see the issue link for each. Support for additional languages, dependency managers, and dependency files are tracked in the following issues:
For workarounds, see the [Troubleshooting section](#troubleshooting)
| Package Managers | Languages | Supported files | Scan tools | Issue | | Package Managers | Languages | Supported files | Scan tools | Issue |
| ------------------- | --------- | --------------- | ---------- | ----- | | ------------------- | --------- | --------------- | ---------- | ----- |
| [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) | | [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) |
For workarounds, see the [Troubleshooting section](#troubleshooting).
## Contribute your scanner ## Contribute your scanner
The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab. The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.

View file

@ -172,11 +172,6 @@ is set for deletion, the merge request widget displays the
> - [Disabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9. > - [Disabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320895) GitLab 13.10. > - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/320895) GitLab 13.10.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature,
ask an administrator to
[disable the `retarget_merge_requests` flag](../../../administration/feature_flags.md).
In specific circumstances, GitLab can retarget the destination branch of In specific circumstances, GitLab can retarget the destination branch of
open merge request, if the destination branch merges while the merge request is open merge request, if the destination branch merges while the merge request is
open. Merge requests are often chained in this manner, with one merge request open. Merge requests are often chained in this manner, with one merge request

View file

@ -315,10 +315,18 @@ module Gitlab
# #
def ref_names(repo) def ref_names(repo)
refs(repo).map do |ref| refs(repo).map do |ref|
ref.sub(%r{^refs/(heads|remotes|tags)/}, "") strip_ref_prefix(ref)
end end
end end
def first_ref_by_oid(repo)
ref = repo.refs_by_oid(oid: id, limit: 1)&.first
return unless ref
strip_ref_prefix(ref)
end
def message def message
encode! @message encode! @message
end end
@ -466,6 +474,10 @@ module Gitlab
commit_id.match?(/\s/) commit_id.match?(/\s/)
) )
end end
def strip_ref_prefix(ref)
ref.sub(%r{^refs/(heads|remotes|tags)/}, "")
end
end end
end end
end end

View file

@ -519,6 +519,17 @@ module Gitlab
@refs_hash @refs_hash
end end
# Returns matching refs for OID
#
# Limit of 0 means there is no limit.
def refs_by_oid(oid:, limit: 0)
wrapped_gitaly_errors do
gitaly_ref_client.find_refs_by_oid(oid: oid, limit: limit)
end
rescue CommandError, TypeError, NoRepository
nil
end
# Returns url for submodule # Returns url for submodule
# #
# Ex. # Ex.

View file

@ -210,6 +210,13 @@ module Gitlab
GitalyClient.call(@storage, :ref_service, :pack_refs, request, timeout: GitalyClient.long_timeout) GitalyClient.call(@storage, :ref_service, :pack_refs, request, timeout: GitalyClient.long_timeout)
end end
def find_refs_by_oid(oid:, limit:)
request = Gitaly::FindRefsByOIDRequest.new(repository: @gitaly_repo, sort_field: :refname, oid: oid, limit: limit)
response = GitalyClient.call(@storage, :ref_service, :find_refs_by_oid, request, timeout: GitalyClient.medium_timeout)
response&.refs&.to_a
end
private private
def consume_refs_response(response) def consume_refs_response(response)

View file

@ -16625,7 +16625,7 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group members permissions and access to each project in the group." msgid "GroupsEmptyState|You can manage your group members permissions and access to each project in the group."
msgstr "" msgstr ""
msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups." msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "" msgstr ""
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once." msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
@ -25285,6 +25285,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines." msgid "Pipelines|There are currently no pipelines."
msgstr "" msgstr ""
msgid "Pipelines|There was a problem with loading the pipeline data."
msgstr ""
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team." msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "" msgstr ""
@ -36367,6 +36370,9 @@ msgstr ""
msgid "Unable to fetch branches list, please close the form and try again" msgid "Unable to fetch branches list, please close the form and try again"
msgstr "" msgstr ""
msgid "Unable to fetch upstream and downstream pipelines."
msgstr ""
msgid "Unable to fetch vulnerable projects" msgid "Unable to fetch vulnerable projects"
msgstr "" msgstr ""

View file

@ -323,6 +323,8 @@ RSpec.describe "Admin Runners" do
end end
it 'changes registration token' do it 'changes registration token' do
click_on 'Register an instance runner'
click_on 'Click to reveal' click_on 'Click to reveal'
expect(page_token).not_to eq token expect(page_token).not_to eq token
end end

View file

@ -1,22 +1,54 @@
import { shallowMount } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue'; import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
import { mockProjectPipeline } from '../../mock_data'; import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql';
import { PIPELINE_FAILURE } from '~/pipeline_editor/constants';
import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('Pipeline Status', () => { describe('Pipeline Status', () => {
let wrapper; let wrapper;
let mockApollo;
let mockLinkedPipelinesQuery;
const createComponent = ({ hasStages = true } = {}) => { const createComponent = ({ hasStages = true, options } = {}) => {
wrapper = shallowMount(PipelineEditorMiniGraph, { wrapper = shallowMount(PipelineEditorMiniGraph, {
provide: {
dataMethod: 'graphql',
projectFullPath: mockProjectFullPath,
},
propsData: { propsData: {
pipeline: mockProjectPipeline({ hasStages }).pipeline, pipeline: mockProjectPipeline({ hasStages }).pipeline,
}, },
...options,
});
};
const createComponentWithApollo = (hasStages = true) => {
const handlers = [[getLinkedPipelinesQuery, mockLinkedPipelinesQuery]];
mockApollo = createMockApollo(handlers);
createComponent({
hasStages,
options: {
localVue,
apolloProvider: mockApollo,
},
}); });
}; };
const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph); const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
beforeEach(() => {
mockLinkedPipelinesQuery = jest.fn();
});
afterEach(() => { afterEach(() => {
mockLinkedPipelinesQuery.mockReset();
wrapper.destroy(); wrapper.destroy();
}); });
@ -39,4 +71,38 @@ describe('Pipeline Status', () => {
expect(findPipelineMiniGraph().exists()).toBe(false); expect(findPipelineMiniGraph().exists()).toBe(false);
}); });
}); });
describe('when querying upstream and downstream pipelines', () => {
describe('when query succeeds', () => {
beforeEach(() => {
mockLinkedPipelinesQuery.mockResolvedValue(mockLinkedPipelines());
createComponentWithApollo();
});
it('should call the query with the correct variables', () => {
expect(mockLinkedPipelinesQuery).toHaveBeenCalledTimes(1);
expect(mockLinkedPipelinesQuery).toHaveBeenCalledWith({
fullPath: mockProjectFullPath,
iid: mockProjectPipeline().pipeline.iid,
});
});
});
describe('when query fails', () => {
beforeEach(() => {
mockLinkedPipelinesQuery.mockRejectedValue(new Error());
createComponentWithApollo();
});
it('should emit an error event when query fails', async () => {
expect(wrapper.emitted('showError')).toHaveLength(1);
expect(wrapper.emitted('showError')[0]).toEqual([
{
type: PIPELINE_FAILURE,
reasons: [wrapper.vm.$options.i18n.linkedPipelinesFetchError],
},
]);
});
});
});
}); });

View file

@ -11,6 +11,7 @@ import {
DEFAULT_FAILURE, DEFAULT_FAILURE,
DEFAULT_SUCCESS, DEFAULT_SUCCESS,
LOAD_FAILURE_UNKNOWN, LOAD_FAILURE_UNKNOWN,
PIPELINE_FAILURE,
} from '~/pipeline_editor/constants'; } from '~/pipeline_editor/constants';
beforeEach(() => { beforeEach(() => {
@ -65,6 +66,7 @@ describe('Pipeline Editor messages', () => {
failureType | message | expectedFailureType failureType | message | expectedFailureType
${COMMIT_FAILURE} | ${'failed commit'} | ${COMMIT_FAILURE} ${COMMIT_FAILURE} | ${'failed commit'} | ${COMMIT_FAILURE}
${LOAD_FAILURE_UNKNOWN} | ${'loading failure'} | ${LOAD_FAILURE_UNKNOWN} ${LOAD_FAILURE_UNKNOWN} | ${'loading failure'} | ${LOAD_FAILURE_UNKNOWN}
${PIPELINE_FAILURE} | ${'pipeline failure'} | ${PIPELINE_FAILURE}
${'random'} | ${'error without a specified type'} | ${DEFAULT_FAILURE} ${'random'} | ${'error without a specified type'} | ${DEFAULT_FAILURE}
`('shows a message for $message', ({ failureType, expectedFailureType }) => { `('shows a message for $message', ({ failureType, expectedFailureType }) => {
createComponent({ failureType, showFailure: true }); createComponent({ failureType, showFailure: true });

View file

@ -290,6 +290,62 @@ export const mockProjectPipeline = ({ hasStages = true } = {}) => {
}; };
}; };
export const mockLinkedPipelines = ({ hasDownstream = true, hasUpstream = true } = {}) => {
let upstream = null;
let downstream = {
nodes: [],
__typename: 'PipelineConnection',
};
if (hasDownstream) {
downstream = {
nodes: [
{
id: 'gid://gitlab/Ci::Pipeline/612',
path: '/root/job-log-sections/-/pipelines/612',
project: { name: 'job-log-sections', __typename: 'Project' },
detailedStatus: {
group: 'success',
icon: 'status_success',
label: 'passed',
__typename: 'DetailedStatus',
},
__typename: 'Pipeline',
},
],
__typename: 'PipelineConnection',
};
}
if (hasUpstream) {
upstream = {
id: 'gid://gitlab/Ci::Pipeline/610',
path: '/root/trigger-downstream/-/pipelines/610',
project: { name: 'trigger-downstream', __typename: 'Project' },
detailedStatus: {
group: 'success',
icon: 'status_success',
label: 'passed',
__typename: 'DetailedStatus',
},
__typename: 'Pipeline',
};
}
return {
data: {
project: {
pipeline: {
path: '/root/ci-project/-/pipelines/790',
downstream,
upstream,
},
__typename: 'Project',
},
},
};
};
export const mockLintResponse = { export const mockLintResponse = {
valid: true, valid: true,
mergedYaml: mockCiYml, mergedYaml: mockCiYml,

View file

@ -715,6 +715,14 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it { is_expected.not_to include("feature") } it { is_expected.not_to include("feature") }
end end
describe '#first_ref_by_oid' do
let(:commit) { described_class.find(repository, 'master') }
subject { commit.first_ref_by_oid(repository) }
it { is_expected.to eq("master") }
end
describe '.get_message' do describe '.get_message' do
let(:commit_ids) { %w[6d394385cf567f80a8fd85055db1ab4c5295806f cfe32cf61b73a0d5e9f13e774abde7ff789b1660] } let(:commit_ids) { %w[6d394385cf567f80a8fd85055db1ab4c5295806f cfe32cf61b73a0d5e9f13e774abde7ff789b1660] }

View file

@ -1900,6 +1900,32 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end end
end end
describe '#refs_by_oid' do
it 'returns a list of refs from a OID' do
refs = repository.refs_by_oid(oid: repository.commit.id)
expect(refs).to be_an(Array)
expect(refs).to include(Gitlab::Git::BRANCH_REF_PREFIX + repository.root_ref)
end
it 'returns a single ref from a OID' do
refs = repository.refs_by_oid(oid: repository.commit.id, limit: 1)
expect(refs).to be_an(Array)
expect(refs).to eq([Gitlab::Git::BRANCH_REF_PREFIX + repository.root_ref])
end
it 'returns empty for unknown ID' do
expect(repository.refs_by_oid(oid: Gitlab::Git::BLANK_SHA, limit: 0)).to eq([])
end
it 'returns nil for an empty repo' do
project = create(:project)
expect(project.repository.refs_by_oid(oid: SeedRepo::Commit::ID, limit: 0)).to be_nil
end
end
describe '#set_full_path' do describe '#set_full_path' do
before do before do
repository_rugged.config["gitlab.fullpath"] = repository_path repository_rugged.config["gitlab.fullpath"] = repository_path

View file

@ -282,4 +282,19 @@ RSpec.describe Gitlab::GitalyClient::RefService do
client.pack_refs client.pack_refs
end end
end end
describe '#find_refs_by_oid' do
let(:oid) { project.repository.commit.id }
it 'sends a find_refs_by_oid message' do
expect_any_instance_of(Gitaly::RefService::Stub)
.to receive(:find_refs_by_oid)
.with(gitaly_request_with_params(sort_field: 'refname', oid: oid, limit: 1), kind_of(Hash))
.and_call_original
refs = client.find_refs_by_oid(oid: oid, limit: 1)
expect(refs.to_a).to eq([Gitlab::Git::BRANCH_REF_PREFIX + project.repository.root_ref])
end
end
end end

View file

@ -876,10 +876,24 @@ RSpec.describe Integrations::Jira do
subject subject
expect(WebMock).to have_requested(:post, comment_url).with( expect(WebMock).to have_requested(:post, comment_url).with(
body: /mentioned this issue in/ body: /mentioned this issue.*on branch \[master/
).once ).once
end end
context 'with jira_use_first_ref_by_oid feature flag disabled' do
before do
stub_feature_flags(jira_use_first_ref_by_oid: false)
end
it 'creates a comment on Jira' do
subject
expect(WebMock).to have_requested(:post, comment_url).with(
body: /mentioned this issue.*on branch \[master/
).once
end
end
it 'tracks usage' do it 'tracks usage' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter) expect(Gitlab::UsageDataCounters::HLLRedisCounter)
.to receive(:track_event) .to receive(:track_event)

View file

@ -45,14 +45,6 @@ RSpec.describe MergeRequests::RetargetChainService do
.from(merge_request.source_branch) .from(merge_request.source_branch)
.to(merge_request.target_branch) .to(merge_request.target_branch)
end end
context 'when FF retarget_merge_requests is disabled' do
before do
stub_feature_flags(retarget_merge_requests: false)
end
include_examples 'does not retarget merge request'
end
end end
context 'in the same project' do context 'in the same project' do