Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
540020f815
commit
91d37b9714
28 changed files with 494 additions and 69 deletions
|
@ -49,3 +49,5 @@ export const SEARCH_RESULTS_DESCRIPTION = 'search-results-description';
|
|||
export const SCOPE_TOKEN_MAX_LENGTH = 36;
|
||||
|
||||
export const INPUT_FIELD_PADDING = 52;
|
||||
|
||||
export const HEADER_INIT_EVENTS = ['input', 'focus'];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as Sentry from '@sentry/browser';
|
||||
import { HEADER_INIT_EVENTS } from './constants';
|
||||
|
||||
async function eventHandler(callback = () => {}) {
|
||||
if (this.newHeaderSearchFeatureFlag) {
|
||||
|
@ -28,21 +29,25 @@ async function eventHandler(callback = () => {}) {
|
|||
}
|
||||
|
||||
function cleanEventListeners() {
|
||||
document.querySelector('#search').removeEventListener('focus', eventHandler);
|
||||
HEADER_INIT_EVENTS.forEach((eventType) => {
|
||||
document.querySelector('#search').removeEventListener(eventType, eventHandler);
|
||||
});
|
||||
}
|
||||
|
||||
function initHeaderSearch() {
|
||||
const searchInputBox = document.querySelector('#search');
|
||||
|
||||
HEADER_INIT_EVENTS.forEach((eventType) => {
|
||||
searchInputBox?.addEventListener(
|
||||
'focus',
|
||||
eventType,
|
||||
eventHandler.bind(
|
||||
{ searchInputBox, newHeaderSearchFeatureFlag: gon?.features?.newHeaderSearch },
|
||||
cleanEventListeners,
|
||||
),
|
||||
{ once: true },
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default initHeaderSearch;
|
||||
export { eventHandler };
|
||||
export { eventHandler, cleanEventListeners };
|
||||
|
|
|
@ -6,9 +6,14 @@ module Types
|
|||
graphql_name 'CiRunnerUpgradeStatusType'
|
||||
|
||||
::Ci::RunnerVersion::STATUS_DESCRIPTIONS.each do |status, description|
|
||||
status = :invalid if status == :invalid_version
|
||||
status_name_src =
|
||||
if status == :invalid_version
|
||||
:invalid
|
||||
else
|
||||
status
|
||||
end
|
||||
|
||||
value status.to_s.upcase, description: description, value: status
|
||||
value status_name_src.to_s.upcase, description: description, value: status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ module Ci
|
|||
|
||||
enum_with_nil status: {
|
||||
not_processed: nil,
|
||||
invalid_version: -1, # Named invalid_version to avoid clash with auto-generated `invalid?` ActiveRecord method
|
||||
invalid_version: -1,
|
||||
unknown: 0,
|
||||
not_available: 1,
|
||||
available: 2,
|
||||
|
|
|
@ -1049,8 +1049,8 @@ class Repository
|
|||
blob_data_at(sha, '.lfsconfig')
|
||||
end
|
||||
|
||||
def changelog_config(ref = 'HEAD')
|
||||
blob_data_at(ref, Gitlab::Changelog::Config::FILE_PATH)
|
||||
def changelog_config(ref, path)
|
||||
blob_data_at(ref, path)
|
||||
end
|
||||
|
||||
def fetch_ref(source_repository, source_ref:, target_ref:)
|
||||
|
|
|
@ -41,6 +41,9 @@ module Repositories
|
|||
# The `trailer` argument is the Git trailer to use for determining what
|
||||
# commits to include in the changelog.
|
||||
#
|
||||
# The `config_file` arguments specifies the path to the configuration file as
|
||||
# stored in the project's Git repository.
|
||||
#
|
||||
# The `file` arguments specifies the name/path of the file to commit the
|
||||
# changes to. If the file doesn't exist, it's created automatically.
|
||||
#
|
||||
|
@ -57,6 +60,7 @@ module Repositories
|
|||
to: branch,
|
||||
date: DateTime.now,
|
||||
trailer: DEFAULT_TRAILER,
|
||||
config_file: Gitlab::Changelog::Config::DEFAULT_FILE_PATH,
|
||||
file: DEFAULT_FILE,
|
||||
message: "Add changelog for version #{version}"
|
||||
)
|
||||
|
@ -68,13 +72,14 @@ module Repositories
|
|||
@date = date
|
||||
@branch = branch
|
||||
@trailer = trailer
|
||||
@config_file = config_file
|
||||
@file = file
|
||||
@message = message
|
||||
end
|
||||
# rubocop: enable Metrics/ParameterLists
|
||||
|
||||
def execute(commit_to_changelog: true)
|
||||
config = Gitlab::Changelog::Config.from_git(@project, @user)
|
||||
config = Gitlab::Changelog::Config.from_git(@project, @user, @config_file)
|
||||
from = start_of_commit_range(config)
|
||||
|
||||
# For every entry we want to only include the merge request that
|
||||
|
|
|
@ -7,7 +7,7 @@ module WaitableWorker
|
|||
# Schedules multiple jobs and waits for them to be completed.
|
||||
def bulk_perform_and_wait(args_list)
|
||||
# Short-circuit: it's more efficient to do small numbers of jobs inline
|
||||
if args_list.size == 1 || (args_list.size <= 3 && !inline_refresh_only_for_single_element?)
|
||||
if args_list.size == 1
|
||||
return bulk_perform_inline(args_list)
|
||||
end
|
||||
|
||||
|
@ -29,10 +29,6 @@ module WaitableWorker
|
|||
|
||||
bulk_perform_async(failed) if failed.present?
|
||||
end
|
||||
|
||||
def inline_refresh_only_for_single_element?
|
||||
Feature.enabled?(:inline_project_authorizations_refresh_only_for_single_element)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(*args)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: inline_project_authorizations_refresh_only_for_single_element
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91572
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366815
|
||||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::workspace
|
||||
default_enabled: false
|
|
@ -319,6 +319,7 @@ Supported attributes:
|
|||
| `date` | datetime | no | The date and time of the release, defaults to the current time. |
|
||||
| `branch` | string | no | The branch to commit the changelog changes to, defaults to the project's default branch. |
|
||||
| `trailer` | string | no | The Git trailer to use for including commits, defaults to `Changelog`. |
|
||||
| `config_file` | string | no | The path of changelog configuration file in the project's Git repository, defaults to `.gitlab/changelog_config.yml`. |
|
||||
| `file` | string | no | The file to commit the changes to, defaults to `CHANGELOG.md`. |
|
||||
| `message` | string | no | The commit message to produce when committing the changes, defaults to `Add changelog for version X` where X is the value of the `version` argument. |
|
||||
|
||||
|
@ -453,7 +454,7 @@ If a revert commit includes the trailer used for generating changelogs
|
|||
### Customize the changelog output
|
||||
|
||||
The output is customized using a YAML configuration file stored in your
|
||||
project's Git repository. This file must reside in
|
||||
project's Git repository. This default configuration file path is
|
||||
`.gitlab/changelog_config.yml`.
|
||||
|
||||
You can set the following variables in this file:
|
||||
|
@ -736,6 +737,7 @@ Supported attributes:
|
|||
| `to` | string | no | The end of the range of commits (as a SHA) to use for the changelog. This commit _is_ included in the list. Defaults to the branch specified in the `branch` attribute. |
|
||||
| `date` | datetime | no | The date and time of the release, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z`. Defaults to the current time. |
|
||||
| `trailer` | string | no | The Git trailer to use for including commits, defaults to `Changelog`. |
|
||||
| `config_file` | string | no | The path of changelog configuration file in the project's Git repository, defaults to `.gitlab/changelog_config.yml`. |
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: token" "https://gitlab.com/api/v4/projects/42/repository/changelog?version=1.0.0"
|
||||
|
|
|
@ -238,6 +238,10 @@ module API
|
|||
end
|
||||
params do
|
||||
use :release_params
|
||||
|
||||
optional :config_file,
|
||||
type: String,
|
||||
desc: "The file path to the configuration file as stored in the project's Git repository. Defaults to '.gitlab/changelog_config.yml'"
|
||||
end
|
||||
get ':id/repository/changelog' do
|
||||
service = ::Repositories::ChangelogService.new(
|
||||
|
@ -262,6 +266,10 @@ module API
|
|||
type: String,
|
||||
desc: 'The branch to commit the changelog changes to'
|
||||
|
||||
optional :config_file,
|
||||
type: String,
|
||||
desc: "The file path to the configuration file as stored in the project's Git repository. Defaults to '.gitlab/changelog_config.yml'"
|
||||
|
||||
optional :file,
|
||||
type: String,
|
||||
desc: 'The file to commit the changelog changes to',
|
||||
|
|
|
@ -7,9 +7,9 @@ module Gitlab
|
|||
# When rendering changelog entries, authors are not included.
|
||||
AUTHORS_NONE = 'none'
|
||||
|
||||
# The path to the configuration file as stored in the project's Git
|
||||
# The default path to the configuration file as stored in the project's Git
|
||||
# repository.
|
||||
FILE_PATH = '.gitlab/changelog_config.yml'
|
||||
DEFAULT_FILE_PATH = '.gitlab/changelog_config.yml'
|
||||
|
||||
# The default date format to use for formatting release dates.
|
||||
DEFAULT_DATE_FORMAT = '%Y-%m-%d'
|
||||
|
@ -36,8 +36,9 @@ module Gitlab
|
|||
|
||||
attr_accessor :date_format, :categories, :template, :tag_regex, :always_credit_user_ids
|
||||
|
||||
def self.from_git(project, user = nil)
|
||||
if (yaml = project.repository.changelog_config.presence)
|
||||
def self.from_git(project, user = nil, path = nil)
|
||||
yaml = project.repository.changelog_config('HEAD', path.presence || DEFAULT_FILE_PATH)
|
||||
if yaml.present?
|
||||
from_hash(project, YAML.safe_load(yaml), user)
|
||||
else
|
||||
new(project)
|
||||
|
|
86
lib/gitlab/github_import/importer/events/cross_referenced.rb
Normal file
86
lib/gitlab/github_import/importer/events/cross_referenced.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module GithubImport
|
||||
module Importer
|
||||
module Events
|
||||
class CrossReferenced
|
||||
attr_reader :project, :user_id
|
||||
|
||||
def initialize(project, user_id)
|
||||
@project = project
|
||||
@user_id = user_id
|
||||
end
|
||||
|
||||
# issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
|
||||
def execute(issue_event)
|
||||
mentioned_in_record_class = mentioned_in_type(issue_event)
|
||||
mentioned_in_number = issue_event.source.dig(:issue, :number)
|
||||
mentioned_in_record = init_mentioned_in(
|
||||
mentioned_in_record_class, mentioned_in_number
|
||||
)
|
||||
return if mentioned_in_record.nil?
|
||||
|
||||
note_body = cross_reference_note_content(mentioned_in_record.gfm_reference(project))
|
||||
track_activity(mentioned_in_record_class)
|
||||
create_note(issue_event, note_body)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def track_activity(mentioned_in_class)
|
||||
return if mentioned_in_class != Issue
|
||||
|
||||
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(
|
||||
Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CROSS_REFERENCED,
|
||||
values: user_id
|
||||
)
|
||||
end
|
||||
|
||||
def create_note(issue_event, note_body)
|
||||
Note.create!(
|
||||
system: true,
|
||||
noteable_type: Issue.name,
|
||||
noteable_id: issue_event.issue_db_id,
|
||||
project: project,
|
||||
author_id: user_id,
|
||||
note: note_body,
|
||||
system_note_metadata: SystemNoteMetadata.new(action: 'cross_reference'),
|
||||
created_at: issue_event.created_at
|
||||
)
|
||||
end
|
||||
|
||||
def mentioned_in_type(issue_event)
|
||||
is_pull_request = issue_event.source.dig(:issue, :pull_request).present?
|
||||
is_pull_request ? MergeRequest : Issue
|
||||
end
|
||||
|
||||
# record_class - Issue/MergeRequest
|
||||
def init_mentioned_in(record_class, iid)
|
||||
db_id = fetch_mentioned_in_db_id(record_class, iid)
|
||||
return if db_id.nil?
|
||||
|
||||
record = record_class.new(id: db_id, iid: iid)
|
||||
record.project = project
|
||||
record.readonly!
|
||||
record
|
||||
end
|
||||
|
||||
# record_class - Issue/MergeRequest
|
||||
def fetch_mentioned_in_db_id(record_class, number)
|
||||
sawyer_mentioned_in_adapter = Struct.new(:iid, :issuable_type, keyword_init: true)
|
||||
mentioned_in_adapter = sawyer_mentioned_in_adapter.new(
|
||||
iid: number, issuable_type: record_class.name
|
||||
)
|
||||
|
||||
Gitlab::GithubImport::IssuableFinder.new(project, mentioned_in_adapter).database_id
|
||||
end
|
||||
|
||||
def cross_reference_note_content(gfm_reference)
|
||||
"#{::SystemNotes::IssuablesService.cross_reference_note_prefix}#{gfm_reference}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -30,6 +30,9 @@ module Gitlab
|
|||
when 'renamed'
|
||||
Gitlab::GithubImport::Importer::Events::Renamed.new(project, author_id)
|
||||
.execute(issue_event)
|
||||
when 'cross-referenced'
|
||||
Gitlab::GithubImport::Importer::Events::CrossReferenced.new(project, author_id)
|
||||
.execute(issue_event)
|
||||
else
|
||||
Gitlab::GithubImport::Logger.debug(
|
||||
message: 'UNSUPPORTED_EVENT_TYPE',
|
||||
|
|
|
@ -21,14 +21,12 @@ module Gitlab
|
|||
|
||||
author_id, author_found = user_finder.author_id_for(note)
|
||||
|
||||
note_body = MarkdownText.format(note.note, note.author, author_found)
|
||||
|
||||
attributes = {
|
||||
noteable_type: note.noteable_type,
|
||||
noteable_id: noteable_id,
|
||||
project_id: project.id,
|
||||
author_id: author_id,
|
||||
note: note_body,
|
||||
note: note_body(author_found),
|
||||
discussion_id: note.discussion_id,
|
||||
system: false,
|
||||
created_at: note.created_at,
|
||||
|
@ -48,6 +46,13 @@ module Gitlab
|
|||
def find_noteable_id
|
||||
GithubImport::IssuableFinder.new(project, note).database_id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def note_body(author_found)
|
||||
text = MarkdownText.convert_ref_links(note.note, project)
|
||||
MarkdownText.format(text, note.author, author_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def each_associated(parent_record, associated)
|
||||
compose_associated_id!(parent_record, associated)
|
||||
return if already_imported?(associated)
|
||||
|
||||
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
|
||||
|
@ -68,6 +69,13 @@ module Gitlab
|
|||
def collection_options
|
||||
{ state: 'all', sort: 'created', direction: 'asc' }
|
||||
end
|
||||
|
||||
# Cross-referenced events on Github doesn't have id.
|
||||
def compose_associated_id!(issue, event)
|
||||
return if event.event != 'cross-referenced'
|
||||
|
||||
event.id = "cross-reference##{issue.id}-in-#{event.source.issue.id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,10 +5,36 @@ module Gitlab
|
|||
class MarkdownText
|
||||
include Gitlab::EncodingHelper
|
||||
|
||||
def self.format(*args)
|
||||
ISSUE_REF_MATCHER = '%{github_url}/%{import_source}/issues'
|
||||
PULL_REF_MATCHER = '%{github_url}/%{import_source}/pull'
|
||||
|
||||
class << self
|
||||
def format(*args)
|
||||
new(*args).to_s
|
||||
end
|
||||
|
||||
# Links like `https://domain.github.com/<namespace>/<project>/pull/<iid>` needs to be converted
|
||||
def convert_ref_links(text, project)
|
||||
matcher_options = { github_url: github_url, import_source: project.import_source }
|
||||
issue_ref_matcher = ISSUE_REF_MATCHER % matcher_options
|
||||
pull_ref_matcher = PULL_REF_MATCHER % matcher_options
|
||||
|
||||
url_helpers = Rails.application.routes.url_helpers
|
||||
text.gsub(issue_ref_matcher, url_helpers.project_issues_url(project))
|
||||
.gsub(pull_ref_matcher, url_helpers.project_merge_requests_url(project))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns github domain without slash in the end
|
||||
def github_url
|
||||
oauth_config = Gitlab::Auth::OAuth::Provider.config_for('github') || {}
|
||||
url = oauth_config['url'].presence || 'https://github.com'
|
||||
url = url.chop if url.end_with?('/')
|
||||
url
|
||||
end
|
||||
end
|
||||
|
||||
# text - The Markdown text as a String.
|
||||
# author - An instance of `Gitlab::GithubImport::Representation::User`
|
||||
# exists - Boolean that indicates the user exists in the GitLab database.
|
||||
|
|
|
@ -9,7 +9,8 @@ module Gitlab
|
|||
|
||||
attr_reader :attributes
|
||||
|
||||
expose_attribute :id, :actor, :event, :commit_id, :label_title, :old_title, :new_title, :created_at
|
||||
expose_attribute :id, :actor, :event, :commit_id, :label_title, :old_title, :new_title,
|
||||
:source, :created_at
|
||||
expose_attribute :issue_db_id # set in SingleEndpointIssueEventsImporter#each_associated
|
||||
|
||||
# Builds a event from a GitHub API response.
|
||||
|
@ -24,6 +25,7 @@ module Gitlab
|
|||
label_title: event.label && event.label[:name],
|
||||
old_title: event.rename && event.rename[:from],
|
||||
new_title: event.rename && event.rename[:to],
|
||||
source: event.source,
|
||||
issue_db_id: event.issue_db_id,
|
||||
created_at: event.created_at
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
|
||||
import initHeaderSearch, { eventHandler } from '~/header_search/init';
|
||||
import initHeaderSearch, { eventHandler, cleanEventListeners } from '~/header_search/init';
|
||||
|
||||
describe('Header Search EventListener', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -21,24 +21,25 @@ describe('Header Search EventListener', () => {
|
|||
|
||||
it('attached event listener', () => {
|
||||
const searchInputBox = document?.querySelector('#search');
|
||||
const addEventListener = jest.spyOn(searchInputBox, 'addEventListener');
|
||||
const addEventListenerSpy = jest.spyOn(searchInputBox, 'addEventListener');
|
||||
initHeaderSearch();
|
||||
|
||||
expect(addEventListener).toBeCalled();
|
||||
expect(addEventListenerSpy).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
it('removes event listener ', async () => {
|
||||
const removeEventListener = jest.fn();
|
||||
const searchInputBox = document?.querySelector('#search');
|
||||
const removeEventListenerSpy = jest.spyOn(searchInputBox, 'removeEventListener');
|
||||
jest.mock('~/header_search', () => ({ initHeaderSearchApp: jest.fn() }));
|
||||
await eventHandler.apply(
|
||||
{
|
||||
newHeaderSearchFeatureFlag: true,
|
||||
searchInputBox: document.querySelector('#search'),
|
||||
},
|
||||
[removeEventListener],
|
||||
[cleanEventListeners],
|
||||
);
|
||||
|
||||
expect(removeEventListener).toBeCalled();
|
||||
expect(removeEventListenerSpy).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
it('attaches new vue dropdown when feature flag is enabled', async () => {
|
||||
|
|
|
@ -3,14 +3,22 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Types::Ci::RunnerUpgradeStatusTypeEnum do
|
||||
let(:model_only_enum_values) { %w[not_processed] }
|
||||
let(:expected_graphql_source_values) do
|
||||
Ci::RunnerVersion.statuses.keys - model_only_enum_values
|
||||
end
|
||||
|
||||
specify { expect(described_class.graphql_name).to eq('CiRunnerUpgradeStatusType') }
|
||||
|
||||
it 'exposes all upgrade status values except not_processed' do
|
||||
expect(described_class.values.keys).to match_array(
|
||||
Ci::RunnerVersion.statuses.keys
|
||||
.reject { |k| k == 'not_processed' }
|
||||
.map { |k| k.upcase }
|
||||
expected_graphql_source_values
|
||||
.map(&:upcase)
|
||||
.map { |v| v == 'INVALID_VERSION' ? 'INVALID' : v }
|
||||
)
|
||||
end
|
||||
|
||||
it 'exposes all upgrade status values except enum-only values' do
|
||||
expect(described_class.values.values.map(&:value).map(&:to_s)).to match_array(expected_graphql_source_values)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,18 @@ RSpec.describe Gitlab::Changelog::Config do
|
|||
described_class.from_git(project)
|
||||
end
|
||||
|
||||
it "retrieves the specified configuration from git" do
|
||||
allow(project.repository)
|
||||
.to receive(:changelog_config).with('HEAD', 'specified_changelog_config.yml')
|
||||
.and_return("---\ndate_format: '%Y'")
|
||||
|
||||
expect(described_class)
|
||||
.to receive(:from_hash)
|
||||
.with(project, { 'date_format' => '%Y' }, nil)
|
||||
|
||||
described_class.from_git(project, nil, 'specified_changelog_config.yml')
|
||||
end
|
||||
|
||||
it 'returns the default configuration when no YAML file exists in Git' do
|
||||
allow(project.repository)
|
||||
.to receive(:changelog_config)
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_gitlab_redis_cache do
|
||||
subject(:importer) { described_class.new(project, user.id) }
|
||||
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
let(:sawyer_stub) { Struct.new(:iid, :issuable_type, keyword_init: true) }
|
||||
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
let(:referenced_in) { build_stubbed(:issue, project: project) }
|
||||
let(:commit_id) { nil }
|
||||
|
||||
let(:issue_event) do
|
||||
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
|
||||
'id' => 6501124486,
|
||||
'node_id' => 'CE_lADOHK9fA85If7x0zwAAAAGDf0mG',
|
||||
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
|
||||
'actor' => { 'id' => 4, 'login' => 'alice' },
|
||||
'event' => 'cross-referenced',
|
||||
'source' => {
|
||||
'type' => 'issue',
|
||||
'issue' => {
|
||||
'number' => referenced_in.iid,
|
||||
'pull_request' => pull_request_resource
|
||||
}
|
||||
},
|
||||
'created_at' => '2022-04-26 18:30:53 UTC',
|
||||
'issue_db_id' => issue.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:pull_request_resource) { nil }
|
||||
let(:expected_note_attrs) do
|
||||
{
|
||||
system: true,
|
||||
noteable_type: Issue.name,
|
||||
noteable_id: issue_event.issue_db_id,
|
||||
project_id: project.id,
|
||||
author_id: user.id,
|
||||
note: expected_note_body,
|
||||
created_at: issue_event.created_at
|
||||
}.stringify_keys
|
||||
end
|
||||
|
||||
context 'when referenced in other issue' do
|
||||
let(:expected_note_body) { "mentioned in issue ##{issue.iid}" }
|
||||
|
||||
before do
|
||||
other_issue_resource = sawyer_stub.new(iid: referenced_in.iid, issuable_type: 'Issue')
|
||||
Gitlab::GithubImport::IssuableFinder.new(project, other_issue_resource)
|
||||
.cache_database_id(referenced_in.iid)
|
||||
end
|
||||
|
||||
it 'creates expected note' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issue.notes.count).to eq 1
|
||||
expect(issue.notes[0]).to have_attributes expected_note_attrs
|
||||
expect(issue.notes[0].system_note_metadata.action).to eq 'cross_reference'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when referenced in pull request' do
|
||||
let(:referenced_in) { build_stubbed(:merge_request, project: project) }
|
||||
let(:pull_request_resource) { { 'id' => referenced_in.iid } }
|
||||
|
||||
let(:expected_note_body) { "mentioned in merge request !#{referenced_in.iid}" }
|
||||
|
||||
before do
|
||||
other_issue_resource =
|
||||
sawyer_stub.new(iid: referenced_in.iid, issuable_type: 'MergeRequest')
|
||||
Gitlab::GithubImport::IssuableFinder.new(project, other_issue_resource)
|
||||
.cache_database_id(referenced_in.iid)
|
||||
end
|
||||
|
||||
it 'creates expected note' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issue.notes.count).to eq 1
|
||||
expect(issue.notes[0]).to have_attributes expected_note_attrs
|
||||
expect(issue.notes[0].system_note_metadata.action).to eq 'cross_reference'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when referenced in out of project issue/pull_request' do
|
||||
it 'creates expected note' do
|
||||
importer.execute(issue_event)
|
||||
|
||||
expect(issue.notes.count).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
|
@ -87,6 +87,13 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
|
|||
Gitlab::GithubImport::Importer::Events::Renamed
|
||||
end
|
||||
|
||||
context "when it's cross-referenced issue event" do
|
||||
let(:event_name) { 'cross-referenced' }
|
||||
|
||||
it_behaves_like 'triggers specific event importer',
|
||||
Gitlab::GithubImport::Importer::Events::CrossReferenced
|
||||
end
|
||||
|
||||
context "when it's unknown issue event" do
|
||||
let(:event_name) { 'fake' }
|
||||
|
||||
|
|
|
@ -12,6 +12,54 @@ RSpec.describe Gitlab::GithubImport::MarkdownText do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.convert_ref_links' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
let(:paragraph) { FFaker::Lorem.paragraph }
|
||||
let(:sentence) { FFaker::Lorem.sentence }
|
||||
let(:issue_id) { rand(100) }
|
||||
let(:pull_id) { rand(100) }
|
||||
|
||||
let(:text_in) do
|
||||
<<-TEXT
|
||||
#{paragraph}
|
||||
https://github.com/#{project.import_source}/issues/#{issue_id}
|
||||
#{sentence}
|
||||
https://github.com/#{project.import_source}/pull/#{pull_id}
|
||||
TEXT
|
||||
end
|
||||
|
||||
let(:text_out) do
|
||||
<<-TEXT
|
||||
#{paragraph}
|
||||
http://localhost/#{project.full_path}/-/issues/#{issue_id}
|
||||
#{sentence}
|
||||
http://localhost/#{project.full_path}/-/merge_requests/#{pull_id}
|
||||
TEXT
|
||||
end
|
||||
|
||||
it { expect(described_class.convert_ref_links(text_in, project)).to eq text_out }
|
||||
|
||||
context 'when Github EE with custom domain name' do
|
||||
let(:github_domain) { 'https://custom.github.com/' }
|
||||
let(:text_in) do
|
||||
<<-TEXT
|
||||
#{paragraph}
|
||||
#{github_domain}#{project.import_source}/issues/#{issue_id}
|
||||
#{sentence}
|
||||
#{github_domain}#{project.import_source}/pull/#{pull_id}
|
||||
TEXT
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Gitlab::Auth::OAuth::Provider)
|
||||
.to receive(:config_for).with('github').and_return({ 'url' => github_domain })
|
||||
end
|
||||
|
||||
it { expect(described_class.convert_ref_links(text_in, project)).to eq text_out }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
it 'returns the text when the author was found' do
|
||||
author = double(:author, login: 'Alice')
|
||||
|
|
|
@ -21,6 +21,10 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
|
|||
expect(issue_event.commit_id).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
|
||||
end
|
||||
|
||||
it 'includes the issue event source' do
|
||||
expect(issue_event.source).to eq({ type: 'issue', id: 123456 })
|
||||
end
|
||||
|
||||
it 'includes the issue_db_id' do
|
||||
expect(issue_event.issue_db_id).to eq(100500)
|
||||
end
|
||||
|
@ -89,7 +93,7 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
|
|||
let(:response) do
|
||||
event_resource = Struct.new(
|
||||
:id, :node_id, :url, :actor, :event, :commit_id, :commit_url, :label,
|
||||
:rename, :issue_db_id, :created_at, :performed_via_github_app,
|
||||
:rename, :issue_db_id, :created_at, :performed_via_github_app, :source,
|
||||
keyword_init: true
|
||||
)
|
||||
user_resource = Struct.new(:id, :login, keyword_init: true)
|
||||
|
@ -103,6 +107,7 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
|
|||
commit_url: 'https://api.github.com/repos/octocat/Hello-World/commits'\
|
||||
'/570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
|
||||
rename: with_rename ? { from: 'old title', to: 'new title' } : nil,
|
||||
source: { type: 'issue', id: 123456 },
|
||||
issue_db_id: 100500,
|
||||
label: with_label ? { name: 'label title' } : nil,
|
||||
created_at: '2022-04-26 18:30:53 UTC',
|
||||
|
@ -134,6 +139,7 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
|
|||
'label_title' => (with_label ? 'label title' : nil),
|
||||
'old_title' => with_rename ? 'old title' : nil,
|
||||
'new_title' => with_rename ? 'new title' : nil,
|
||||
'source' => { 'type' => 'issue', 'id' => 123456 },
|
||||
"issue_db_id" => 100500,
|
||||
'created_at' => '2022-04-26 18:30:53 UTC',
|
||||
'performed_via_github_app' => nil
|
||||
|
|
|
@ -2735,6 +2735,33 @@ RSpec.describe Repository do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#changelog_config' do
|
||||
let(:user) { create(:user) }
|
||||
let(:changelog_config_path) { Gitlab::Changelog::Config::DEFAULT_FILE_PATH }
|
||||
|
||||
before do
|
||||
repository.create_file(
|
||||
user,
|
||||
changelog_config_path,
|
||||
'CONTENT',
|
||||
message: '...',
|
||||
branch_name: 'master'
|
||||
)
|
||||
end
|
||||
|
||||
context 'when there is a changelog_config_path at the commit' do
|
||||
it 'returns the content' do
|
||||
expect(repository.changelog_config(repository.commit.sha, changelog_config_path)).to eq('CONTENT')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is no changelog_config_path at the commit' do
|
||||
it 'returns nil' do
|
||||
expect(repository.changelog_config(repository.commit.parent.sha, changelog_config_path)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#route_map_for' do
|
||||
before do
|
||||
repository.create_file(User.last, '.gitlab/route-map.yml', 'CONTENT', message: 'Add .gitlab/route-map.yml', branch_name: 'master')
|
||||
|
|
|
@ -784,6 +784,40 @@ RSpec.describe API::Repositories do
|
|||
expect(json_response['notes']).to be_present
|
||||
end
|
||||
|
||||
it 'supports specified config file path' do
|
||||
spy = instance_spy(Repositories::ChangelogService)
|
||||
|
||||
expect(Repositories::ChangelogService)
|
||||
.to receive(:new)
|
||||
.with(
|
||||
project,
|
||||
user,
|
||||
version: '1.0.0',
|
||||
from: 'foo',
|
||||
to: 'bar',
|
||||
date: DateTime.new(2020, 1, 1),
|
||||
trailer: 'Foo',
|
||||
config_file: 'specified_changelog_config.yml'
|
||||
)
|
||||
.and_return(spy)
|
||||
|
||||
expect(spy).to receive(:execute).with(commit_to_changelog: false)
|
||||
|
||||
get(
|
||||
api("/projects/#{project.id}/repository/changelog", user),
|
||||
params: {
|
||||
version: '1.0.0',
|
||||
from: 'foo',
|
||||
to: 'bar',
|
||||
date: '2020-01-01',
|
||||
trailer: 'Foo',
|
||||
config_file: 'specified_changelog_config.yml'
|
||||
}
|
||||
)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
context 'when previous tag version does not exist' do
|
||||
it_behaves_like '422 response' do
|
||||
let(:request) { get api("/projects/#{project.id}/repository/changelog", user), params: { version: 'v0.0.0' } }
|
||||
|
@ -905,5 +939,45 @@ RSpec.describe API::Repositories do
|
|||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||
expect(json_response['message']).to eq('Failed to generate the changelog: oops')
|
||||
end
|
||||
|
||||
it "support specified config file path" do
|
||||
spy = instance_spy(Repositories::ChangelogService)
|
||||
|
||||
expect(Repositories::ChangelogService)
|
||||
.to receive(:new)
|
||||
.with(
|
||||
project,
|
||||
user,
|
||||
version: '1.0.0',
|
||||
from: 'foo',
|
||||
to: 'bar',
|
||||
date: DateTime.new(2020, 1, 1),
|
||||
branch: 'kittens',
|
||||
trailer: 'Foo',
|
||||
config_file: 'specified_changelog_config.yml',
|
||||
file: 'FOO.md',
|
||||
message: 'Commit message'
|
||||
)
|
||||
.and_return(spy)
|
||||
|
||||
allow(spy).to receive(:execute).with(commit_to_changelog: true)
|
||||
|
||||
post(
|
||||
api("/projects/#{project.id}/repository/changelog", user),
|
||||
params: {
|
||||
version: '1.0.0',
|
||||
from: 'foo',
|
||||
to: 'bar',
|
||||
date: '2020-01-01',
|
||||
branch: 'kittens',
|
||||
trailer: 'Foo',
|
||||
config_file: 'specified_changelog_config.yml',
|
||||
file: 'FOO.md',
|
||||
message: 'Commit message'
|
||||
}
|
||||
)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -194,6 +194,25 @@ RSpec.describe Repositories::ChangelogService do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with specified changelog config file path' do
|
||||
it 'return specified changelog content' do
|
||||
config = Gitlab::Changelog::Config.from_hash(project, { 'template' => 'specified_changelog_content' }, creator)
|
||||
|
||||
allow(Gitlab::Changelog::Config)
|
||||
.to receive(:from_git)
|
||||
.with(project, creator, 'specified_changelog_config.yml')
|
||||
.and_return(config)
|
||||
|
||||
described_class
|
||||
.new(project, creator, version: '1.0.0', from: sha1, config_file: 'specified_changelog_config.yml')
|
||||
.execute(commit_to_changelog: commit_to_changelog)
|
||||
|
||||
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
|
||||
|
||||
expect(changelog).to include('specified_changelog_content')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#start_of_commit_range' do
|
||||
|
|
|
@ -54,25 +54,6 @@ RSpec.describe WaitableWorker do
|
|||
|
||||
worker.bulk_perform_and_wait(arguments)
|
||||
end
|
||||
|
||||
context 'when the feature flag `inline_project_authorizations_refresh_only_for_single_element` is turned off' do
|
||||
before do
|
||||
stub_feature_flags(inline_project_authorizations_refresh_only_for_single_element: false)
|
||||
end
|
||||
|
||||
it 'inlines the jobs' do
|
||||
args_list = [[1], [2], [3]]
|
||||
expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original
|
||||
expect(Gitlab::AppJsonLogger).to(
|
||||
receive(:info).with(a_hash_including('message' => 'running inline',
|
||||
'class' => 'Gitlab::Foo::Bar::DummyWorker',
|
||||
'job_status' => 'running',
|
||||
'queue' => 'foo_bar_dummy'))
|
||||
.exactly(3).times)
|
||||
|
||||
worker.bulk_perform_and_wait(args_list)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context '>= 4 jobs' do
|
||||
|
|
Loading…
Reference in a new issue