Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
97f0ae74
Commit
97f0ae74
authored
Apr 14, 2020
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
5ebc4d92
Changes
27
Show whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
449 additions
and
114 deletions
+449
-114
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+9
-0
app/assets/javascripts/snippets/components/snippet_blob_view.vue
...ets/javascripts/snippets/components/snippet_blob_view.vue
+8
-32
app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
...vascripts/snippets/fragments/snippetBase.fragment.graphql
+15
-0
app/assets/javascripts/snippets/queries/snippet.blob.query.graphql
...s/javascripts/snippets/queries/snippet.blob.query.graphql
+0
-24
app/assets/javascripts/static_site_editor/constants.js
app/assets/javascripts/static_site_editor/constants.js
+12
-0
app/assets/javascripts/static_site_editor/services/generate_branch_name.js
...ripts/static_site_editor/services/generate_branch_name.js
+8
-0
app/assets/javascripts/static_site_editor/services/submit_content_changes.js
...pts/static_site_editor/services/submit_content_changes.js
+74
-2
app/assets/javascripts/static_site_editor/store/state.js
app/assets/javascripts/static_site_editor/store/state.js
+2
-0
app/graphql/resolvers/merge_requests_resolver.rb
app/graphql/resolvers/merge_requests_resolver.rb
+11
-2
changelogs/unreleased/212561-saving-changes-rest-service.yml
changelogs/unreleased/212561-saving-changes-rest-service.yml
+5
-0
changelogs/unreleased/213800-optimize-usage_activity_by_stage-create-protected_branches.yml
...ize-usage_activity_by_stage-create-protected_branches.yml
+5
-0
changelogs/unreleased/34527-fix-graphql-endpoint-for-merge-requests.yml
...eleased/34527-fix-graphql-endpoint-for-merge-requests.yml
+5
-0
config/routes/project.rb
config/routes/project.rb
+4
-0
config/routes/repository.rb
config/routes/repository.rb
+0
-4
db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb
...dd_index_on_creator_id_created_at_id_to_projects_table.rb
+17
-0
db/structure.sql
db/structure.sql
+3
-0
doc/administration/gitaly/praefect.md
doc/administration/gitaly/praefect.md
+22
-8
lib/api/entities/project_import_status.rb
lib/api/entities/project_import_status.rb
+1
-1
lib/gitlab/path_regex.rb
lib/gitlab/path_regex.rb
+0
-1
locale/gitlab.pot
locale/gitlab.pot
+12
-3
spec/frontend/api_spec.js
spec/frontend/api_spec.js
+33
-1
spec/frontend/snippets/components/snippet_blob_view_spec.js
spec/frontend/snippets/components/snippet_blob_view_spec.js
+4
-35
spec/frontend/static_site_editor/mock_data.js
spec/frontend/static_site_editor/mock_data.js
+8
-0
spec/frontend/static_site_editor/services/generate_branch_name_spec.js
.../static_site_editor/services/generate_branch_name_spec.js
+22
-0
spec/frontend/static_site_editor/services/submit_content_changes_spec.js
...tatic_site_editor/services/submit_content_changes_spec.js
+131
-0
spec/requests/api/graphql/project/merge_request/diff_notes_spec.rb
...ests/api/graphql/project/merge_request/diff_notes_spec.rb
+1
-1
spec/requests/api/graphql/project/merge_request_spec.rb
spec/requests/api/graphql/project/merge_request_spec.rb
+37
-0
No files found.
app/assets/javascripts/api.js
View file @
97f0ae74
...
@@ -188,6 +188,15 @@ const Api = {
...
@@ -188,6 +188,15 @@ const Api = {
return
axios
.
get
(
url
,
{
params
});
return
axios
.
get
(
url
,
{
params
});
},
},
createProjectMergeRequest
(
projectPath
,
options
)
{
const
url
=
Api
.
buildUrl
(
Api
.
projectMergeRequestsPath
).
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
),
);
return
axios
.
post
(
url
,
options
);
},
// Return Merge Request for project
// Return Merge Request for project
projectMergeRequest
(
projectPath
,
mergeRequestId
,
params
=
{})
{
projectMergeRequest
(
projectPath
,
mergeRequestId
,
params
=
{})
{
const
url
=
Api
.
buildUrl
(
Api
.
projectMergeRequestPath
)
const
url
=
Api
.
buildUrl
(
Api
.
projectMergeRequestPath
)
...
...
app/assets/javascripts/snippets/components/snippet_blob_view.vue
View file @
97f0ae74
...
@@ -3,10 +3,8 @@ import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
...
@@ -3,10 +3,8 @@ import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
import
{
SNIPPET_VISIBILITY_PUBLIC
}
from
'
../constants
'
;
import
{
SNIPPET_VISIBILITY_PUBLIC
}
from
'
../constants
'
;
import
BlobHeader
from
'
~/blob/components/blob_header.vue
'
;
import
BlobHeader
from
'
~/blob/components/blob_header.vue
'
;
import
BlobContent
from
'
~/blob/components/blob_content.vue
'
;
import
BlobContent
from
'
~/blob/components/blob_content.vue
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
CloneDropdownButton
from
'
~/vue_shared/components/clone_dropdown.vue
'
;
import
CloneDropdownButton
from
'
~/vue_shared/components/clone_dropdown.vue
'
;
import
GetSnippetBlobQuery
from
'
../queries/snippet.blob.query.graphql
'
;
import
GetBlobContent
from
'
../queries/snippet.blob.content.query.graphql
'
;
import
GetBlobContent
from
'
../queries/snippet.blob.content.query.graphql
'
;
import
{
SIMPLE_BLOB_VIEWER
,
RICH_BLOB_VIEWER
}
from
'
~/blob/components/constants
'
;
import
{
SIMPLE_BLOB_VIEWER
,
RICH_BLOB_VIEWER
}
from
'
~/blob/components/constants
'
;
...
@@ -16,25 +14,9 @@ export default {
...
@@ -16,25 +14,9 @@ export default {
BlobEmbeddable
,
BlobEmbeddable
,
BlobHeader
,
BlobHeader
,
BlobContent
,
BlobContent
,
GlLoadingIcon
,
CloneDropdownButton
,
CloneDropdownButton
,
},
},
apollo
:
{
apollo
:
{
blob
:
{
query
:
GetSnippetBlobQuery
,
variables
()
{
return
{
ids
:
this
.
snippet
.
id
,
};
},
update
:
data
=>
data
.
snippets
.
edges
[
0
].
node
.
blob
,
result
(
res
)
{
const
viewer
=
res
.
data
.
snippets
.
edges
[
0
].
node
.
blob
.
richViewer
?
RICH_BLOB_VIEWER
:
SIMPLE_BLOB_VIEWER
;
this
.
switchViewer
(
viewer
,
true
);
},
},
blobContent
:
{
blobContent
:
{
query
:
GetBlobContent
,
query
:
GetBlobContent
,
variables
()
{
variables
()
{
...
@@ -55,18 +37,18 @@ export default {
...
@@ -55,18 +37,18 @@ export default {
},
},
data
()
{
data
()
{
return
{
return
{
blob
:
{}
,
blob
:
this
.
snippet
.
blob
,
blobContent
:
''
,
blobContent
:
''
,
activeViewerType
:
window
.
location
.
hash
?
SIMPLE_BLOB_VIEWER
:
''
,
activeViewerType
:
this
.
snippet
.
blob
?.
richViewer
&&
!
window
.
location
.
hash
?
RICH_BLOB_VIEWER
:
SIMPLE_BLOB_VIEWER
,
};
};
},
},
computed
:
{
computed
:
{
embeddable
()
{
embeddable
()
{
return
this
.
snippet
.
visibilityLevel
===
SNIPPET_VISIBILITY_PUBLIC
;
return
this
.
snippet
.
visibilityLevel
===
SNIPPET_VISIBILITY_PUBLIC
;
},
},
isBlobLoading
()
{
return
this
.
$apollo
.
queries
.
blob
.
loading
;
},
isContentLoading
()
{
isContentLoading
()
{
return
this
.
$apollo
.
queries
.
blobContent
.
loading
;
return
this
.
$apollo
.
queries
.
blobContent
.
loading
;
},
},
...
@@ -79,8 +61,8 @@ export default {
...
@@ -79,8 +61,8 @@ export default {
},
},
},
},
methods
:
{
methods
:
{
switchViewer
(
newViewer
,
respectHash
=
false
)
{
switchViewer
(
newViewer
)
{
this
.
activeViewerType
=
respectHash
&&
window
.
location
.
hash
?
SIMPLE_BLOB_VIEWER
:
newViewer
;
this
.
activeViewerType
=
newViewer
;
},
},
},
},
};
};
...
@@ -88,13 +70,7 @@ export default {
...
@@ -88,13 +70,7 @@ export default {
<
template
>
<
template
>
<div>
<div>
<blob-embeddable
v-if=
"embeddable"
class=
"mb-3"
:url=
"snippet.webUrl"
/>
<blob-embeddable
v-if=
"embeddable"
class=
"mb-3"
:url=
"snippet.webUrl"
/>
<gl-loading-icon
<article
class=
"file-holder snippet-file-content"
>
v-if=
"isBlobLoading"
:label=
"__('Loading blob')"
size=
"lg"
class=
"prepend-top-20 append-bottom-20"
/>
<article
v-else
class=
"file-holder snippet-file-content"
>
<blob-header
:blob=
"blob"
:active-viewer-type=
"viewer.type"
@
viewer-changed=
"switchViewer"
>
<blob-header
:blob=
"blob"
:active-viewer-type=
"viewer.type"
@
viewer-changed=
"switchViewer"
>
<template
#actions
>
<template
#actions
>
<clone-dropdown-button
<clone-dropdown-button
...
...
app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
View file @
97f0ae74
#import '~/graphql_shared/fragments/blobviewer.fragment.graphql'
fragment
SnippetBase
on
Snippet
{
fragment
SnippetBase
on
Snippet
{
id
id
title
title
...
@@ -9,6 +11,19 @@ fragment SnippetBase on Snippet {
...
@@ -9,6 +11,19 @@ fragment SnippetBase on Snippet {
webUrl
webUrl
httpUrlToRepo
httpUrlToRepo
sshUrlToRepo
sshUrlToRepo
blob
{
binary
name
path
rawPath
size
simpleViewer
{
...
BlobViewer
}
richViewer
{
...
BlobViewer
}
}
userPermissions
{
userPermissions
{
adminSnippet
adminSnippet
updateSnippet
updateSnippet
...
...
app/assets/javascripts/snippets/queries/snippet.blob.query.graphql
deleted
100644 → 0
View file @
5ebc4d92
#import '~/graphql_shared/fragments/blobviewer.fragment.graphql'
query
SnippetBlobFull
(
$ids
:
[
ID
!])
{
snippets
(
ids
:
$ids
)
{
edges
{
node
{
id
blob
{
binary
name
path
rawPath
size
simpleViewer
{
...
BlobViewer
}
richViewer
{
...
BlobViewer
}
}
}
}
}
}
app/assets/javascripts/static_site_editor/constants.js
0 → 100644
View file @
97f0ae74
import
{
s__
}
from
'
~/locale
'
;
export
const
BRANCH_SUFFIX_COUNT
=
8
;
export
const
DEFAULT_TARGET_BRANCH
=
'
master
'
;
export
const
SUBMIT_CHANGES_BRANCH_ERROR
=
s__
(
'
StaticSiteEditor|Branch could not be created.
'
);
export
const
SUBMIT_CHANGES_COMMIT_ERROR
=
s__
(
'
StaticSiteEditor|Could not commit the content changes.
'
,
);
export
const
SUBMIT_CHANGES_MERGE_REQUEST_ERROR
=
s__
(
'
StaticSiteEditor|Could not create merge request.
'
,
);
app/assets/javascripts/static_site_editor/services/generate_branch_name.js
0 → 100644
View file @
97f0ae74
import
{
BRANCH_SUFFIX_COUNT
,
DEFAULT_TARGET_BRANCH
}
from
'
../constants
'
;
const
generateBranchSuffix
=
()
=>
`
${
Date
.
now
()}
`
.
substr
(
BRANCH_SUFFIX_COUNT
);
const
generateBranchName
=
(
username
,
targetBranch
=
DEFAULT_TARGET_BRANCH
)
=>
`
${
username
}
-
${
targetBranch
}
-patch-
${
generateBranchSuffix
()}
`
;
export
default
generateBranchName
;
app/assets/javascripts/static_site_editor/services/submit_content_changes.js
View file @
97f0ae74
// TODO implement
import
Api
from
'
~/api
'
;
const
submitContentChanges
=
()
=>
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
1000
));
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
convertObjectPropsToSnakeCase
}
from
'
~/lib/utils/common_utils
'
;
import
generateBranchName
from
'
~/static_site_editor/services/generate_branch_name
'
;
import
{
DEFAULT_TARGET_BRANCH
,
SUBMIT_CHANGES_BRANCH_ERROR
,
SUBMIT_CHANGES_COMMIT_ERROR
,
SUBMIT_CHANGES_MERGE_REQUEST_ERROR
,
}
from
'
../constants
'
;
const
createBranch
=
(
projectId
,
branch
)
=>
Api
.
createBranch
(
projectId
,
{
ref
:
DEFAULT_TARGET_BRANCH
,
branch
,
}).
catch
(()
=>
{
throw
new
Error
(
SUBMIT_CHANGES_BRANCH_ERROR
);
});
const
commitContent
=
(
projectId
,
message
,
branch
,
sourcePath
,
content
)
=>
Api
.
commitMultiple
(
projectId
,
convertObjectPropsToSnakeCase
({
branch
,
commitMessage
:
message
,
actions
:
[
convertObjectPropsToSnakeCase
({
action
:
'
update
'
,
filePath
:
sourcePath
,
content
,
}),
],
}),
).
catch
(()
=>
{
throw
new
Error
(
SUBMIT_CHANGES_COMMIT_ERROR
);
});
const
createMergeRequest
=
(
projectId
,
title
,
sourceBranch
,
targetBranch
=
DEFAULT_TARGET_BRANCH
)
=>
Api
.
createProjectMergeRequest
(
projectId
,
convertObjectPropsToSnakeCase
({
title
,
sourceBranch
,
targetBranch
,
}),
).
catch
(()
=>
{
throw
new
Error
(
SUBMIT_CHANGES_MERGE_REQUEST_ERROR
);
});
const
submitContentChanges
=
({
username
,
projectId
,
sourcePath
,
content
})
=>
{
const
branch
=
generateBranchName
(
username
);
const
mergeRequestTitle
=
sprintf
(
s__
(
`StaticSiteEditor|Update %{sourcePath} file`
),
{
sourcePath
,
});
const
meta
=
{};
return
createBranch
(
projectId
,
branch
)
.
then
(()
=>
{
Object
.
assign
(
meta
,
{
branch
:
{
label
:
branch
}
});
return
commitContent
(
projectId
,
mergeRequestTitle
,
branch
,
sourcePath
,
content
);
})
.
then
(({
data
:
{
short_id
:
label
,
web_url
:
url
}
})
=>
{
Object
.
assign
(
meta
,
{
commit
:
{
label
,
url
}
});
return
createMergeRequest
(
projectId
,
mergeRequestTitle
,
branch
);
})
.
then
(({
data
:
{
iid
:
label
,
web_url
:
url
}
})
=>
{
Object
.
assign
(
meta
,
{
mergeRequest
:
{
label
,
url
}
});
return
meta
;
});
};
export
default
submitContentChanges
;
export
default
submitContentChanges
;
app/assets/javascripts/static_site_editor/store/state.js
View file @
97f0ae74
...
@@ -10,6 +10,8 @@ const createState = (initialState = {}) => ({
...
@@ -10,6 +10,8 @@ const createState = (initialState = {}) => ({
content
:
''
,
content
:
''
,
title
:
''
,
title
:
''
,
savedContentMeta
:
null
,
...
initialState
,
...
initialState
,
});
});
...
...
app/graphql/resolvers/merge_requests_resolver.rb
View file @
97f0ae74
...
@@ -20,8 +20,17 @@ module Resolvers
...
@@ -20,8 +20,17 @@ module Resolvers
args
[
:iids
]
||=
[
args
[
:iid
]].
compact
args
[
:iids
]
||=
[
args
[
:iid
]].
compact
args
[
:iids
].
map
{
|
iid
|
batch_load
(
iid
)
}
if
args
[
:iids
].
any?
.
select
(
&
:itself
)
# .compact doesn't work on BatchLoader
batch_load_merge_requests
(
args
[
:iids
])
else
args
[
:project_id
]
=
project
.
id
MergeRequestsFinder
.
new
(
context
[
:current_user
],
args
).
execute
end
end
def
batch_load_merge_requests
(
iids
)
iids
.
map
{
|
iid
|
batch_load
(
iid
)
}.
select
(
&
:itself
)
# .compact doesn't work on BatchLoader
end
end
# rubocop: disable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
...
...
changelogs/unreleased/212561-saving-changes-rest-service.yml
0 → 100644
View file @
97f0ae74
---
title
:
Save changes in Static Site Editor using REST GitLab API
merge_request
:
29286
author
:
type
:
added
changelogs/unreleased/213800-optimize-usage_activity_by_stage-create-protected_branches.yml
0 → 100644
View file @
97f0ae74
---
title
:
Optimize protected branches usage data
merge_request
:
29148
author
:
type
:
performance
changelogs/unreleased/34527-fix-graphql-endpoint-for-merge-requests.yml
0 → 100644
View file @
97f0ae74
---
title
:
Fix pagination in Merge Request GraphQL api
merge_request
:
28667
author
:
briankabiro
type
:
fixed
config/routes/project.rb
View file @
97f0ae74
...
@@ -26,6 +26,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
...
@@ -26,6 +26,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
scope
'-'
do
scope
'-'
do
get
'archive/*id'
,
constraints:
{
format:
Gitlab
::
PathRegex
.
archive_formats_regex
,
id:
/.+?/
},
to:
'repositories#archive'
,
as:
'archive'
get
'archive/*id'
,
constraints:
{
format:
Gitlab
::
PathRegex
.
archive_formats_regex
,
id:
/.+?/
},
to:
'repositories#archive'
,
as:
'archive'
scope
controller: :static_site_editor
do
get
'/sse/*id'
,
action: :show
,
as: :show_sse
end
resources
:artifacts
,
only:
[
:index
,
:destroy
]
resources
:artifacts
,
only:
[
:index
,
:destroy
]
resources
:jobs
,
only:
[
:index
,
:show
],
constraints:
{
id:
/\d+/
}
do
resources
:jobs
,
only:
[
:index
,
:show
],
constraints:
{
id:
/\d+/
}
do
...
...
config/routes/repository.rb
View file @
97f0ae74
...
@@ -67,10 +67,6 @@ scope format: false do
...
@@ -67,10 +67,6 @@ scope format: false do
end
end
end
end
scope
controller: :static_site_editor
do
get
'/sse/*id'
,
action: :show
,
as: :show_sse
end
get
'/tree/*id'
,
to:
'tree#show'
,
as: :tree
get
'/tree/*id'
,
to:
'tree#show'
,
as: :tree
get
'/raw/*id'
,
to:
'raw#show'
,
as: :raw
get
'/raw/*id'
,
to:
'raw#show'
,
as: :raw
get
'/blame/*id'
,
to:
'blame#show'
,
as: :blame
get
'/blame/*id'
,
to:
'blame#show'
,
as: :blame
...
...
db/migrate/20200408175424_add_index_on_creator_id_created_at_id_to_projects_table.rb
0 → 100644
View file @
97f0ae74
# frozen_string_literal: true
class
AddIndexOnCreatorIdCreatedAtIdToProjectsTable
<
ActiveRecord
::
Migration
[
6.0
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_concurrent_index
:projects
,
[
:creator_id
,
:created_at
,
:id
]
end
def
down
remove_concurrent_index
:projects
,
[
:creator_id
,
:created_at
,
:id
]
end
end
db/structure.sql
View file @
97f0ae74
...
@@ -9884,6 +9884,8 @@ CREATE INDEX index_projects_on_created_at_and_id ON public.projects USING btree
...
@@ -9884,6 +9884,8 @@ CREATE INDEX index_projects_on_created_at_and_id ON public.projects USING btree
CREATE
INDEX
index_projects_on_creator_id_and_created_at
ON
public
.
projects
USING
btree
(
creator_id
,
created_at
);
CREATE
INDEX
index_projects_on_creator_id_and_created_at
ON
public
.
projects
USING
btree
(
creator_id
,
created_at
);
CREATE
INDEX
index_projects_on_creator_id_and_created_at_and_id
ON
public
.
projects
USING
btree
(
creator_id
,
created_at
,
id
);
CREATE
INDEX
index_projects_on_description_trigram
ON
public
.
projects
USING
gin
(
description
public
.
gin_trgm_ops
);
CREATE
INDEX
index_projects_on_description_trigram
ON
public
.
projects
USING
gin
(
description
public
.
gin_trgm_ops
);
CREATE
INDEX
index_projects_on_id_and_archived_and_pending_delete
ON
public
.
projects
USING
btree
(
id
)
WHERE
((
archived
=
false
)
AND
(
pending_delete
=
false
));
CREATE
INDEX
index_projects_on_id_and_archived_and_pending_delete
ON
public
.
projects
USING
btree
(
id
)
WHERE
((
archived
=
false
)
AND
(
pending_delete
=
false
));
...
@@ -13092,5 +13094,6 @@ COPY "schema_migrations" (version) FROM STDIN;
...
@@ -13092,5 +13094,6 @@ COPY "schema_migrations" (version) FROM STDIN;
20200407094005
20200407094005
20200407094923
20200407094923
20200408110856
20200408110856
20200408175424
\
.
\
.
doc/administration/gitaly/praefect.md
View file @
97f0ae74
...
@@ -468,12 +468,16 @@ config.
...
@@ -468,12 +468,16 @@ config.
Manual failover is possible by updating
`praefect['virtual_storages']`
and
Manual failover is possible by updating
`praefect['virtual_storages']`
and
nominating a new primary node.
nominating a new primary node.
NOTE:
**Note:**
: Automatic failover is not yet supported for setups with
1.
By default, Praefect will nominate a primary Gitaly node for each
multiple Praefect nodes. There is currently no coordination between Praefect
shard and store the state of the primary in local memory. This state
nodes, which could result in two Praefect instances thinking two different
does not persist across restarts and will cause a split brain
Gitaly nodes are the primary. Follow issue
if multiple Praefect nodes are used for redundancy.
[
#2547
](
https://gitlab.com/gitlab-org/gitaly/-/issues/2547
)
for
updates.
To avoid this limitation, enable the SQL election strategy:
```ruby
praefect['failover_election_strategy'] = 'sql'
```
1.
Save the changes to
`/etc/gitlab/gitlab.rb`
and
[
reconfigure
1.
Save the changes to
`/etc/gitlab/gitlab.rb`
and
[
reconfigure
Praefect
](
../restart_gitlab.md#omnibus-gitlab-reconfigure
)
:
Praefect
](
../restart_gitlab.md#omnibus-gitlab-reconfigure
)
:
...
@@ -677,8 +681,18 @@ current primary node is found to be unhealthy.
...
@@ -677,8 +681,18 @@ current primary node is found to be unhealthy.
checks fail for the current primary backend Gitaly node, and new primary will
checks fail for the current primary backend Gitaly node, and new primary will
be elected.
**Do not use with multiple Praefect nodes!**
Using with multiple
be elected.
**Do not use with multiple Praefect nodes!**
Using with multiple
Praefect nodes is likely to result in a split brain.
Praefect nodes is likely to result in a split brain.
-
**PostgreSQL:**
Coming soon. See isse
-
**PostgreSQL:**
Enabled by setting
[
#2547
](
https://gitlab.com/gitlab-org/gitaly/-/issues/2547
)
for updates.
`praefect['failover_election_strategy'] = sql`
. This configuration
option will allow multiple Praefect nodes to coordinate via the
PostgreSQL database to elect a primary Gitaly node. This configuration
will cause Praefect nodes to elect a new primary, monitor its health,
and elect a new primary if the current one has not been reachable in
10 seconds by a majority of the Praefect nodes.
NOTE:
**Note:**
: Praefect does not yet account for replication lag on
the secondaries during the election process, so data loss can occur
during a failover. Follow issue
[
#2642
](
https://gitlab.com/gitlab-org/gitaly/-/issues/2642
)
for updates.
It is likely that we will implement support for Consul, and a cloud native
It is likely that we will implement support for Consul, and a cloud native
strategy in the future.
strategy in the future.
...
...
lib/api/entities/project_import_status.rb
View file @
97f0ae74
...
@@ -5,7 +5,7 @@ module API
...
@@ -5,7 +5,7 @@ module API
class
ProjectImportStatus
<
ProjectIdentity
class
ProjectImportStatus
<
ProjectIdentity
expose
:import_status
expose
:import_status
expose
:correlation_id
do
|
project
,
_options
|
expose
:correlation_id
do
|
project
,
_options
|
project
.
import_state
.
correlation_id
project
.
import_state
&
.
correlation_id
end
end
# TODO: Use `expose_nil` once we upgrade the grape-entity gem
# TODO: Use `expose_nil` once we upgrade the grape-entity gem
...
...
lib/gitlab/path_regex.rb
View file @
97f0ae74
...
@@ -98,7 +98,6 @@ module Gitlab
...
@@ -98,7 +98,6 @@ module Gitlab
preview
preview
raw
raw
refs
refs
sse
tree
tree
update
update
wikis
wikis
...
...
locale/gitlab.pot
View file @
97f0ae74
...
@@ -12189,9 +12189,6 @@ msgstr ""
...
@@ -12189,9 +12189,6 @@ msgstr ""
msgid "Loading"
msgid "Loading"
msgstr ""
msgstr ""
msgid "Loading blob"
msgstr ""
msgid "Loading contribution stats for group members"
msgid "Loading contribution stats for group members"
msgstr ""
msgstr ""
...
@@ -19368,6 +19365,15 @@ msgstr ""
...
@@ -19368,6 +19365,15 @@ msgstr ""
msgid "Static Application Security Testing (SAST)"
msgid "Static Application Security Testing (SAST)"
msgstr ""
msgstr ""
msgid "StaticSiteEditor|Branch could not be created."
msgstr ""
msgid "StaticSiteEditor|Could not commit the content changes."
msgstr ""
msgid "StaticSiteEditor|Could not create merge request."
msgstr ""
msgid "StaticSiteEditor|Return to site"
msgid "StaticSiteEditor|Return to site"
msgstr ""
msgstr ""
...
@@ -19377,6 +19383,9 @@ msgstr ""
...
@@ -19377,6 +19383,9 @@ msgstr ""
msgid "StaticSiteEditor|Summary of changes"
msgid "StaticSiteEditor|Summary of changes"
msgstr ""
msgstr ""
msgid "StaticSiteEditor|Update %{sourcePath} file"
msgstr ""
msgid "StaticSiteEditor|View merge request"
msgid "StaticSiteEditor|View merge request"
msgstr ""
msgstr ""
...
...
spec/frontend/api_spec.js
View file @
97f0ae74
...
@@ -651,7 +651,7 @@ describe('Api', () => {
...
@@ -651,7 +651,7 @@ describe('Api', () => {
describe
(
'
when an error occurs while getting a raw file
'
,
()
=>
{
describe
(
'
when an error occurs while getting a raw file
'
,
()
=>
{
it
(
'
rejects the Promise
'
,
()
=>
{
it
(
'
rejects the Promise
'
,
()
=>
{
mock
.
on
Delete
(
expectedUrl
).
replyOnce
(
500
);
mock
.
on
Post
(
expectedUrl
).
replyOnce
(
500
);
return
Api
.
getRawFile
(
dummyProjectPath
,
dummyFilePath
).
catch
(()
=>
{
return
Api
.
getRawFile
(
dummyProjectPath
,
dummyFilePath
).
catch
(()
=>
{
expect
(
mock
.
history
.
get
).
toHaveLength
(
1
);
expect
(
mock
.
history
.
get
).
toHaveLength
(
1
);
...
@@ -659,4 +659,36 @@ describe('Api', () => {
...
@@ -659,4 +659,36 @@ describe('Api', () => {
});
});
});
});
});
});
describe
(
'
createProjectMergeRequest
'
,
()
=>
{
const
dummyProjectPath
=
'
gitlab-org/gitlab
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
encodeURIComponent
(
dummyProjectPath
,
)}
/merge_requests`
;
const
options
=
{
source_branch
:
'
feature
'
,
target_branch
:
'
master
'
,
title
:
'
Add feature
'
,
};
describe
(
'
when the merge request is successfully created
'
,
()
=>
{
it
(
'
resolves the Promise
'
,
()
=>
{
mock
.
onPost
(
expectedUrl
,
options
).
replyOnce
(
201
);
return
Api
.
createProjectMergeRequest
(
dummyProjectPath
,
options
).
then
(()
=>
{
expect
(
mock
.
history
.
post
).
toHaveLength
(
1
);
});
});
});
describe
(
'
when an error occurs while getting a raw file
'
,
()
=>
{
it
(
'
rejects the Promise
'
,
()
=>
{
mock
.
onPost
(
expectedUrl
).
replyOnce
(
500
);
return
Api
.
createProjectMergeRequest
(
dummyProjectPath
).
catch
(()
=>
{
expect
(
mock
.
history
.
post
).
toHaveLength
(
1
);
});
});
});
});
});
});
spec/frontend/snippets/components/snippet_blob_view_spec.js
View file @
97f0ae74
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
SnippetBlobView
from
'
~/snippets/components/snippet_blob_view.vue
'
;
import
SnippetBlobView
from
'
~/snippets/components/snippet_blob_view.vue
'
;
import
BlobHeader
from
'
~/blob/components/blob_header.vue
'
;
import
BlobHeader
from
'
~/blob/components/blob_header.vue
'
;
import
BlobEmbeddable
from
'
~/blob/components/blob_embeddable.vue
'
;
import
BlobEmbeddable
from
'
~/blob/components/blob_embeddable.vue
'
;
...
@@ -19,23 +18,15 @@ describe('Blob Embeddable', () => {
...
@@ -19,23 +18,15 @@ describe('Blob Embeddable', () => {
id
:
'
gid://foo.bar/snippet
'
,
id
:
'
gid://foo.bar/snippet
'
,
webUrl
:
'
https://foo.bar
'
,
webUrl
:
'
https://foo.bar
'
,
visibilityLevel
:
SNIPPET_VISIBILITY_PUBLIC
,
visibilityLevel
:
SNIPPET_VISIBILITY_PUBLIC
,
blob
:
BlobMock
,
};
};
const
dataMock
=
{
const
dataMock
=
{
blob
:
BlobMock
,
activeViewerType
:
SimpleViewerMock
.
type
,
activeViewerType
:
SimpleViewerMock
.
type
,
};
};
function
createComponent
(
function
createComponent
(
props
=
{},
data
=
dataMock
,
contentLoading
=
false
)
{
props
=
{},
data
=
dataMock
,
blobLoading
=
false
,
contentLoading
=
false
,
)
{
const
$apollo
=
{
const
$apollo
=
{
queries
:
{
queries
:
{
blob
:
{
loading
:
blobLoading
,
},
blobContent
:
{
blobContent
:
{
loading
:
contentLoading
,
loading
:
contentLoading
,
},
},
...
@@ -87,12 +78,6 @@ describe('Blob Embeddable', () => {
...
@@ -87,12 +78,6 @@ describe('Blob Embeddable', () => {
expect
(
wrapper
.
find
(
BlobEmbeddable
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
BlobEmbeddable
).
exists
()).
toBe
(
true
);
});
});
it
(
'
shows loading icon while blob data is in flight
'
,
()
=>
{
createComponent
({},
dataMock
,
true
);
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
.snippet-file-content
'
).
exists
()).
toBe
(
false
);
});
it
(
'
sets simple viewer correctly
'
,
()
=>
{
it
(
'
sets simple viewer correctly
'
,
()
=>
{
createComponent
();
createComponent
();
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
...
@@ -133,14 +118,14 @@ describe('Blob Embeddable', () => {
...
@@ -133,14 +118,14 @@ describe('Blob Embeddable', () => {
});
});
it
(
'
renders simple viewer by default if URL contains hash
'
,
()
=>
{
it
(
'
renders simple viewer by default if URL contains hash
'
,
()
=>
{
createComponent
();
createComponent
(
{},
{}
);
expect
(
wrapper
.
vm
.
activeViewerType
).
toBe
(
SimpleViewerMock
.
type
);
expect
(
wrapper
.
vm
.
activeViewerType
).
toBe
(
SimpleViewerMock
.
type
);
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
});
});
describe
(
'
switchViewer()
'
,
()
=>
{
describe
(
'
switchViewer()
'
,
()
=>
{
it
(
'
by default
switches to the passed viewer
'
,
()
=>
{
it
(
'
switches to the passed viewer
'
,
()
=>
{
createComponent
();
createComponent
();
wrapper
.
vm
.
switchViewer
(
RichViewerMock
.
type
);
wrapper
.
vm
.
switchViewer
(
RichViewerMock
.
type
);
...
@@ -157,22 +142,6 @@ describe('Blob Embeddable', () => {
...
@@ -157,22 +142,6 @@ describe('Blob Embeddable', () => {
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
});
});
});
});
it
(
'
respects hash over richViewer in the blob when corresponding parameter is passed
'
,
()
=>
{
createComponent
(
{},
{
blob
:
BlobMock
,
},
);
expect
(
wrapper
.
vm
.
blob
.
richViewer
).
toEqual
(
expect
.
any
(
Object
));
wrapper
.
vm
.
switchViewer
(
RichViewerMock
.
type
,
true
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
vm
.
activeViewerType
).
toBe
(
SimpleViewerMock
.
type
);
expect
(
wrapper
.
find
(
SimpleViewer
).
exists
()).
toBe
(
true
);
});
});
});
});
});
});
});
});
...
...
spec/frontend/static_site_editor/mock_data.js
View file @
97f0ae74
...
@@ -34,3 +34,11 @@ export const savedContentMeta = {
...
@@ -34,3 +34,11 @@ export const savedContentMeta = {
};
};
export
const
submitChangesError
=
'
Could not save changes
'
;
export
const
submitChangesError
=
'
Could not save changes
'
;
export
const
commitMultipleResponse
=
{
short_id
:
'
ed899a2f4b5
'
,
web_url
:
'
/commit/ed899a2f4b5
'
,
};
export
const
createMergeRequestResponse
=
{
iid
:
'
123
'
,
web_url
:
'
/merge_requests/123
'
,
};
spec/frontend/static_site_editor/services/generate_branch_name_spec.js
0 → 100644
View file @
97f0ae74
import
{
DEFAULT_TARGET_BRANCH
,
BRANCH_SUFFIX_COUNT
}
from
'
~/static_site_editor/constants
'
;
import
generateBranchName
from
'
~/static_site_editor/services/generate_branch_name
'
;
import
{
username
}
from
'
../mock_data
'
;
describe
(
'
generateBranchName
'
,
()
=>
{
const
timestamp
=
12345678901234
;
beforeEach
(()
=>
{
jest
.
spyOn
(
Date
,
'
now
'
).
mockReturnValueOnce
(
timestamp
);
});
it
(
'
generates a name that includes the username and target branch
'
,
()
=>
{
expect
(
generateBranchName
(
username
)).
toMatch
(
`
${
username
}
-
${
DEFAULT_TARGET_BRANCH
}
`
);
});
it
(
`adds the first
${
BRANCH_SUFFIX_COUNT
}
numbers of the current timestamp`
,
()
=>
{
expect
(
generateBranchName
(
username
)).
toMatch
(
timestamp
.
toString
().
substring
(
BRANCH_SUFFIX_COUNT
),
);
});
});
spec/frontend/static_site_editor/services/submit_content_changes_spec.js
0 → 100644
View file @
97f0ae74
import
Api
from
'
~/api
'
;
import
{
convertObjectPropsToSnakeCase
}
from
'
~/lib/utils/common_utils
'
;
import
{
DEFAULT_TARGET_BRANCH
,
SUBMIT_CHANGES_BRANCH_ERROR
,
SUBMIT_CHANGES_COMMIT_ERROR
,
SUBMIT_CHANGES_MERGE_REQUEST_ERROR
,
}
from
'
~/static_site_editor/constants
'
;
import
generateBranchName
from
'
~/static_site_editor/services/generate_branch_name
'
;
import
submitContentChanges
from
'
~/static_site_editor/services/submit_content_changes
'
;
import
{
username
,
projectId
,
commitMultipleResponse
,
createMergeRequestResponse
,
sourcePath
,
sourceContent
as
content
,
}
from
'
../mock_data
'
;
jest
.
mock
(
'
~/static_site_editor/services/generate_branch_name
'
);
describe
(
'
submitContentChanges
'
,
()
=>
{
const
mergeRequestTitle
=
`Update
${
sourcePath
}
file`
;
const
branch
=
'
branch-name
'
;
beforeEach
(()
=>
{
jest
.
spyOn
(
Api
,
'
createBranch
'
).
mockResolvedValue
();
jest
.
spyOn
(
Api
,
'
commitMultiple
'
).
mockResolvedValue
({
data
:
commitMultipleResponse
});
jest
.
spyOn
(
Api
,
'
createProjectMergeRequest
'
)
.
mockResolvedValue
({
data
:
createMergeRequestResponse
});
generateBranchName
.
mockReturnValue
(
branch
);
});
it
(
'
creates a branch named after the username and target branch
'
,
()
=>
{
return
submitContentChanges
({
username
,
projectId
}).
then
(()
=>
{
expect
(
Api
.
createBranch
).
toHaveBeenCalledWith
(
projectId
,
{
ref
:
DEFAULT_TARGET_BRANCH
,
branch
,
});
});
});
it
(
'
notifies error when branch could not be created
'
,
()
=>
{
Api
.
createBranch
.
mockRejectedValueOnce
();
expect
(
submitContentChanges
({
username
,
projectId
})).
rejects
.
toThrow
(
SUBMIT_CHANGES_BRANCH_ERROR
,
);
});
it
(
'
commits the content changes to the branch when creating branch succeeds
'
,
()
=>
{
return
submitContentChanges
({
username
,
projectId
,
sourcePath
,
content
}).
then
(()
=>
{
expect
(
Api
.
commitMultiple
).
toHaveBeenCalledWith
(
projectId
,
{
branch
,
commit_message
:
mergeRequestTitle
,
actions
:
[
{
action
:
'
update
'
,
file_path
:
sourcePath
,
content
,
},
],
});
});
});
it
(
'
notifies error when content could not be committed
'
,
()
=>
{
Api
.
commitMultiple
.
mockRejectedValueOnce
();
expect
(
submitContentChanges
({
username
,
projectId
})).
rejects
.
toThrow
(
SUBMIT_CHANGES_COMMIT_ERROR
,
);
});
it
(
'
creates a merge request when commiting changes succeeds
'
,
()
=>
{
return
submitContentChanges
({
username
,
projectId
,
sourcePath
,
content
}).
then
(()
=>
{
expect
(
Api
.
createProjectMergeRequest
).
toHaveBeenCalledWith
(
projectId
,
convertObjectPropsToSnakeCase
({
title
:
mergeRequestTitle
,
targetBranch
:
DEFAULT_TARGET_BRANCH
,
sourceBranch
:
branch
,
}),
);
});
});
it
(
'
notifies error when merge request could not be created
'
,
()
=>
{
Api
.
createProjectMergeRequest
.
mockRejectedValueOnce
();
expect
(
submitContentChanges
({
username
,
projectId
})).
rejects
.
toThrow
(
SUBMIT_CHANGES_MERGE_REQUEST_ERROR
,
);
});
describe
(
'
when changes are submitted successfully
'
,
()
=>
{
let
result
;
beforeEach
(()
=>
{
return
submitContentChanges
({
username
,
projectId
,
sourcePath
,
content
}).
then
(
_result
=>
{
result
=
_result
;
});
});
it
(
'
returns the branch name
'
,
()
=>
{
expect
(
result
).
toMatchObject
({
branch
:
{
label
:
branch
}
});
});
it
(
'
returns commit short id and web url
'
,
()
=>
{
expect
(
result
).
toMatchObject
({
commit
:
{
label
:
commitMultipleResponse
.
short_id
,
url
:
commitMultipleResponse
.
web_url
,
},
});
});
it
(
'
returns merge request iid and web url
'
,
()
=>
{
expect
(
result
).
toMatchObject
({
mergeRequest
:
{
label
:
createMergeRequestResponse
.
iid
,
url
:
createMergeRequestResponse
.
web_url
,
},
});
});
});
});
spec/requests/api/graphql/project/merge_request/diff_notes_spec.rb
View file @
97f0ae74
...
@@ -5,7 +5,7 @@ require 'spec_helper'
...
@@ -5,7 +5,7 @@ require 'spec_helper'
describe
'getting notes for a merge request'
do
describe
'getting notes for a merge request'
do
include
GraphqlHelpers
include
GraphqlHelpers
let
(
:noteable
)
{
create
(
:merge_request
)
}
let
_it_be
(
:noteable
)
{
create
(
:merge_request
)
}
def
noteable_query
(
noteable_fields
)
def
noteable_query
(
noteable_fields
)
<<~
QRY
<<~
QRY
...
...
spec/requests/api/graphql/project/merge_request_spec.rb
View file @
97f0ae74
...
@@ -93,4 +93,41 @@ describe 'getting merge request information nested in a project' do
...
@@ -93,4 +93,41 @@ describe 'getting merge request information nested in a project' do
expect
(
merge_request_graphql_data
[
'pipelines'
][
'edges'
].
size
).
to
eq
(
1
)
expect
(
merge_request_graphql_data
[
'pipelines'
][
'edges'
].
size
).
to
eq
(
1
)
end
end
end
end
context
'when limiting the number of results'
do
let
(
:merge_requests_graphql_data
)
{
graphql_data
[
'project'
][
'mergeRequests'
][
'edges'
]
}
let!
(
:merge_requests
)
do
[
create
(
:merge_request
,
source_project:
project
,
source_branch:
'branch-1'
),
create
(
:merge_request
,
source_project:
project
,
source_branch:
'branch-2'
),
create
(
:merge_request
,
source_project:
project
,
source_branch:
'branch-3'
)
]
end
let
(
:fields
)
do
<<~
QUERY
edges {
node {
iid,
title
}
}
QUERY
end
let
(
:query
)
do
graphql_query_for
(
'project'
,
{
'fullPath'
=>
project
.
full_path
},
"mergeRequests(first: 2) {
#{
fields
}
}"
)
end
it
'returns the correct number of results'
do
post_graphql
(
query
,
current_user:
current_user
)
expect
(
merge_requests_graphql_data
.
size
).
to
eq
2
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment