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
7159693a
Commit
7159693a
authored
Sep 16, 2019
by
Yorick Peterse
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove code for EE specific checks
This code is no longer needed in the single codebase setup.
parent
6259a242
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
0 additions
and
953 deletions
+0
-953
lib/gitlab/ee_compat_check.rb
lib/gitlab/ee_compat_check.rb
+0
-444
lib/tasks/ee_compat_check.rake
lib/tasks/ee_compat_check.rake
+0
-4
lib/tasks/gitlab/dev.rake
lib/tasks/gitlab/dev.rake
+0
-31
scripts/ee_specific_check/ee_specific_check.rb
scripts/ee_specific_check/ee_specific_check.rb
+0
-470
scripts/static-analysis
scripts/static-analysis
+0
-4
No files found.
lib/gitlab/ee_compat_check.rb
deleted
100644 → 0
View file @
6259a242
# frozen_string_literal: true
# rubocop: disable Rails/Output
module
Gitlab
# Checks if a set of migrations requires downtime or not.
class
EeCompatCheck
CANONICAL_CE_PROJECT_URL
=
'https://gitlab.com/gitlab-org/gitlab-foss'
CANONICAL_EE_REPO_URL
=
'https://gitlab.com/gitlab-org/gitlab.git'
CHECK_DIR
=
Rails
.
root
.
join
(
'ee_compat_check'
)
IGNORED_FILES_REGEX
=
/VERSION|CHANGELOG\.md|doc\/.+/i
.
freeze
PLEASE_READ_THIS_BANNER
=
%Q{
============================================================
===================== PLEASE READ THIS =====================
============================================================
}
.
freeze
STAY_STRONG_LINK_TO_DOCS
=
%Q{
Stay 💪! For more information, see
https://docs.gitlab.com/ce/development/automatic_ce_ee_merge.html
}
.
freeze
THANKS_FOR_READING_BANNER
=
%Q{
============================================================
==================== THANKS FOR READING ====================
============================================================
\n
}
.
freeze
attr_reader
:ee_repo_dir
,
:patches_dir
attr_reader
:ce_project_url
,
:ee_repo_url
attr_reader
:ce_branch
,
:ee_remote_with_branch
,
:ee_branch_found
attr_reader
:job_id
,
:failed_files
def
initialize
(
branch
:,
ce_project_url:
CANONICAL_CE_PROJECT_URL
,
job_id:
nil
)
@ee_repo_dir
=
CHECK_DIR
.
join
(
'ee-repo'
)
@patches_dir
=
CHECK_DIR
.
join
(
'patches'
)
@ce_branch
=
branch
@ce_project_url
=
ce_project_url
@ee_repo_url
=
ce_public_repo_url
.
sub
(
'gitlab-ce'
,
'gitlab-ee'
)
@job_id
=
job_id
end
def
check
ensure_patches_dir
# We're generating the patch against the canonical-ce remote since forks'
# master branch are not necessarily up-to-date.
add_remote
(
'canonical-ce'
,
"
#{
CANONICAL_CE_PROJECT_URL
}
.git"
)
generate_patch
(
branch:
ce_branch
,
patch_path:
ce_patch_full_path
,
branch_remote:
'origin'
,
master_remote:
'canonical-ce'
)
ensure_ee_repo
Dir
.
chdir
(
ee_repo_dir
)
do
step
(
"In the
#{
ee_repo_dir
}
directory"
)
ee_remotes
.
each
do
|
key
,
url
|
add_remote
(
key
,
url
)
end
fetch
(
branch:
'master'
,
depth:
20
,
remote:
'canonical-ee'
)
status
=
catch
(
:halt_check
)
do
ce_branch_compat_check!
delete_ee_branches_locally!
ee_branch_presence_check!
step
(
"Checking out
#{
ee_remote_with_branch
}
/
#{
ee_branch_found
}
"
,
%W[git checkout -b
#{
ee_branch_found
}
#{
ee_remote_with_branch
}
/
#{
ee_branch_found
}
]
)
generate_patch
(
branch:
ee_branch_found
,
patch_path:
ee_patch_full_path
,
branch_remote:
ee_remote_with_branch
,
master_remote:
'canonical-ee'
)
ee_branch_compat_check!
end
delete_ee_branches_locally!
status
.
nil?
end
end
private
def
fork?
ce_project_url
!=
CANONICAL_CE_PROJECT_URL
end
def
ee_remotes
return
@ee_remotes
if
defined?
(
@ee_remotes
)
remotes
=
{
'ee'
=>
ee_repo_url
,
'canonical-ee'
=>
CANONICAL_EE_REPO_URL
}
remotes
.
delete
(
'ee'
)
unless
fork
?
@ee_remotes
=
remotes
end
def
add_remote
(
name
,
url
)
step
(
"Adding the
#{
name
}
remote (
#{
url
}
)"
,
%W[git remote add
#{
name
}
#{
url
}
]
)
end
def
ensure_ee_repo
unless
clone_repo
(
ee_repo_url
,
ee_repo_dir
)
# Fallback to using the canonical EE if there is no forked EE
clone_repo
(
CANONICAL_EE_REPO_URL
,
ee_repo_dir
)
end
end
def
clone_repo
(
url
,
dir
)
_
,
status
=
step
(
"Cloning
#{
url
}
into
#{
dir
}
"
,
%W[git clone --branch master --single-branch --depth=200
#{
url
}
#{
dir
}
]
)
status
.
zero?
end
def
ensure_patches_dir
FileUtils
.
mkdir_p
(
patches_dir
)
end
def
generate_patch
(
branch
:,
patch_path
:,
branch_remote
:,
master_remote
:)
FileUtils
.
rm
(
patch_path
,
force:
true
)
find_merge_base_with_master
(
branch:
branch
,
branch_remote:
branch_remote
,
master_remote:
master_remote
)
step
(
"Generating the patch against
#{
master_remote
}
/master in
#{
patch_path
}
"
,
%W[git diff --binary
#{
master_remote
}
/master...
#{
branch_remote
}
/
#{
branch
}
]
)
do
|
output
,
status
|
throw
(
:halt_check
,
:ko
)
unless
status
.
zero?
File
.
write
(
patch_path
,
output
)
throw
(
:halt_check
,
:ko
)
unless
File
.
exist?
(
patch_path
)
end
end
def
ce_branch_compat_check!
if
check_patch
(
ce_patch_full_path
).
zero?
puts
applies_cleanly_msg
(
ce_branch
)
throw
(
:halt_check
)
end
end
def
ee_branch_presence_check!
ee_remotes
.
keys
.
each
do
|
remote
|
output
,
_
=
step
(
"Searching
#{
remote
}
"
,
%W[git ls-remote
#{
remote
}
*
#{
minimal_ee_branch_name
}
*]
)
branches
=
output
.
scan
(
%r{(?<=refs/heads/|refs/tags/).+}
).
sort_by
(
&
:size
)
next
if
branches
.
empty?
branch
=
branches
.
first
step
(
"Fetching
#{
remote
}
/
#{
branch
}
"
,
%W[git fetch
#{
remote
}
#{
branch
}
]
)
@ee_remote_with_branch
=
remote
@ee_branch_found
=
branch
return
true
end
puts
puts
ce_branch_doesnt_apply_cleanly_and_no_ee_branch_msg
throw
(
:halt_check
,
:ko
)
end
def
ee_branch_compat_check!
unless
check_patch
(
ee_patch_full_path
).
zero?
puts
puts
ee_branch_doesnt_apply_cleanly_msg
throw
(
:halt_check
,
:ko
)
end
puts
puts
applies_cleanly_msg
(
ee_branch_found
)
end
def
check_patch
(
patch_path
)
step
(
"Checking out master"
,
%w[git checkout master]
)
step
(
"Resetting to latest master"
,
%w[git reset --hard canonical-ee/master]
)
step
(
"Checking if
#{
patch_path
}
applies cleanly to EE/master"
,
# Don't use --check here because it can result in a 0-exit status even
# though the patch doesn't apply cleanly, e.g.:
# > git apply --check --3way foo.patch
# error: patch failed: lib/gitlab/ee_compat_check.rb:74
# Falling back to three-way merge...
# Applied patch to 'lib/gitlab/ee_compat_check.rb' with conflicts.
# > echo $?
# 0
%W[git apply --3way
#{
patch_path
}
]
)
do
|
output
,
status
|
puts
output
unless
status
.
zero?
@failed_files
=
output
.
lines
.
reduce
([])
do
|
memo
,
line
|
if
line
.
start_with?
(
'error: patch failed:'
)
file
=
line
.
sub
(
/\Aerror: patch failed: /
,
''
)
memo
<<
file
unless
file
=~
IGNORED_FILES_REGEX
end
memo
end
status
=
0
if
failed_files
.
empty?
end
command
(
%w[git reset --hard]
)
status
end
end
def
delete_ee_branches_locally!
command
(
%w[git checkout master]
)
command
(
%W[git branch --delete --force
#{
ee_branch_prefix
}
]
)
command
(
%W[git branch --delete --force
#{
ee_branch_suffix
}
]
)
end
def
merge_base_found?
(
branch
:,
branch_remote
:,
master_remote
:)
step
(
"Finding merge base with
#{
master_remote
}
/master"
,
%W[git merge-base
#{
master_remote
}
/master
#{
branch_remote
}
/
#{
branch
}
]
)
do
|
output
,
status
|
if
status
.
zero?
puts
"Merge base was found:
#{
output
}
"
true
end
end
end
def
find_merge_base_with_master
(
branch
:,
branch_remote
:,
master_remote
:)
# Start with (Math.exp(3).to_i = 20) until (Math.exp(6).to_i = 403)
# In total we go (20 + 54 + 148 + 403 = 625) commits deeper
depth
=
20
success
=
(
3
..
6
).
any?
do
|
factor
|
depth
+=
Math
.
exp
(
factor
).
to_i
# Repository is initially cloned with a depth of 20 so we need to fetch
# deeper in the case the branch has more than 20 commits on top of master
fetch
(
branch:
branch
,
depth:
depth
,
remote:
branch_remote
)
fetch
(
branch:
'master'
,
depth:
depth
,
remote:
master_remote
)
merge_base_found?
(
branch:
branch
,
branch_remote:
branch_remote
,
master_remote:
master_remote
)
end
raise
"
\n
#{
branch
}
is too far behind
#{
master_remote
}
/master, please rebase it!
\n
"
unless
success
end
def
fetch
(
branch
:,
depth
:,
remote:
'origin'
)
step
(
"Fetching deeper..."
,
%W[git fetch --depth=
#{
depth
}
--prune
#{
remote
}
+refs/heads/
#{
branch
}
:refs/remotes/
#{
remote
}
/
#{
branch
}
]
)
do
|
output
,
status
|
raise
"Fetch failed:
#{
output
}
"
unless
status
.
zero?
end
end
def
ce_patch_name
@ce_patch_name
||=
patch_name_from_branch
(
ce_branch
)
end
def
ce_patch_full_path
@ce_patch_full_path
||=
patches_dir
.
join
(
ce_patch_name
)
end
def
ee_branch_suffix
@ee_branch_suffix
||=
"
#{
ce_branch
}
-ee"
end
def
ee_branch_prefix
@ee_branch_prefix
||=
"ee-
#{
ce_branch
}
"
end
def
ee_patch_name
@ee_patch_name
||=
patch_name_from_branch
(
ee_branch_found
)
end
def
ee_patch_full_path
@ee_patch_full_path
||=
patches_dir
.
join
(
ee_patch_name
)
end
def
minimal_ee_branch_name
@minimal_ee_branch_name
||=
ce_branch
.
sub
(
/(\Ace\-|\-ce\z)/
,
''
)
end
def
patch_name_from_branch
(
branch_name
)
"
#{
branch_name
.
parameterize
}
.patch"
end
def
patch_url
"
#{
ce_project_url
}
/-/jobs/
#{
job_id
}
/artifacts/raw/ee_compat_check/patches/
#{
ce_patch_name
}
"
end
def
step
(
desc
,
cmd
=
nil
)
puts
"
\n
=>
#{
desc
}
\n
"
if
cmd
start
=
Time
.
now
puts
"
\n
$
#{
cmd
.
join
(
' '
)
}
"
output
,
status
=
command
(
cmd
)
puts
"
\n
==> Finished in
#{
Time
.
now
-
start
}
seconds"
if
block_given?
yield
(
output
,
status
)
else
[
output
,
status
]
end
end
end
def
command
(
cmd
)
Gitlab
::
Popen
.
popen
(
cmd
)
end
# We're "re-creating" the repo URL because ENV['CI_REPOSITORY_URL'] contains
# redacted credentials (e.g. "***:****") which are useless in instructions
# the job gives.
def
ce_public_repo_url
"
#{
ce_project_url
}
.git"
end
def
applies_cleanly_msg
(
branch
)
%Q{
#{
PLEASE_READ_THIS_BANNER
}
🎉 Congratulations!! 🎉
The `
#{
branch
}
` branch applies cleanly to EE/master!
Much ❤️! For more information, see
https://docs.gitlab.com/ce/development/automatic_ce_ee_merge.html
#{
THANKS_FOR_READING_BANNER
}
}
end
def
ce_branch_doesnt_apply_cleanly_and_no_ee_branch_msg
ee_repos
=
ee_remotes
.
values
.
uniq
%Q{
#{
PLEASE_READ_THIS_BANNER
}
💥 Oh no! 💥
The `
#{
ce_branch
}
` branch does not apply cleanly to the current
EE/master, and no `
#{
ee_branch_prefix
}
` or `
#{
ee_branch_suffix
}
` branch
was found in
#{
ee_repos
.
join
(
' nor in '
)
}
.
If you're a community contributor, don't worry, someone from
GitLab Inc. will take care of this, and you don't have to do anything.
If you're willing to help, and are ok to contribute to EE as well,
you're welcome to help. You could follow the instructions below.
#{
conflicting_files_msg
}
We advise you to create a `
#{
ee_branch_prefix
}
` or `
#{
ee_branch_suffix
}
`
branch that includes changes from `
#{
ce_branch
}
` but also specific changes
than can be applied cleanly to EE/master. In some cases, the conflicts
are trivial and you can ignore the warning from this job. As always,
use your best judgement!
There are different ways to create such branch:
1. Create a new branch from master and cherry-pick your CE commits
# In the EE repo
$ git fetch
#{
CANONICAL_EE_REPO_URL
}
master
$ git checkout -b
#{
ee_branch_prefix
}
FETCH_HEAD
$ git fetch
#{
ce_public_repo_url
}
#{
ce_branch
}
$ git cherry-pick SHA # Repeat for all the commits you want to pick
Note: You can squash the `
#{
ce_branch
}
` commits into a single "Port of
#{
ce_branch
}
to EE" commit.
2. Apply your branch's patch to EE
# In the EE repo
$ git fetch
#{
CANONICAL_EE_REPO_URL
}
master
$ git checkout -b
#{
ee_branch_prefix
}
FETCH_HEAD
$ wget
#{
patch_url
}
&& git apply --3way
#{
ce_patch_name
}
At this point you might have conflicts such as:
error: patch failed: lib/gitlab/ee_compat_check.rb:5
Falling back to three-way merge...
Applied patch to 'lib/gitlab/ee_compat_check.rb' with conflicts.
U lib/gitlab/ee_compat_check.rb
Resolve them, stage the changes and commit them.
If the patch couldn't be applied cleanly, use the following command:
# In the EE repo
$ git apply --reject
#{
ce_patch_name
}
This option makes git apply the parts of the patch that are applicable,
and leave the rejected hunks in corresponding `.rej` files.
You can then resolve the conflicts highlighted in `.rej` by
manually applying the correct diff from the `.rej` file to the file with conflicts.
When finished, you can delete the `.rej` files and commit your changes.
⚠️ Don't forget to push your branch to gitlab-ee:
# In the EE repo
$ git push origin
#{
ee_branch_prefix
}
⚠️ Also, don't forget to create a new merge request on gitlab-ee and
cross-link it with the CE merge request.
Once this is done, you can retry this failed job, and it should pass.
#{
STAY_STRONG_LINK_TO_DOCS
}
#{
THANKS_FOR_READING_BANNER
}
}
end
def
ee_branch_doesnt_apply_cleanly_msg
%Q{
#{
PLEASE_READ_THIS_BANNER
}
💥 Oh no! 💥
The `
#{
ce_branch
}
` does not apply cleanly to the current EE/master, and
even though a `
#{
ee_branch_found
}
` branch
exists in
#{
ee_repo_url
}
, it does not apply cleanly either to
EE/master!
#{
conflicting_files_msg
}
Please update the `
#{
ee_branch_found
}
`, push it again to gitlab-ee, and
retry this job.
#{
STAY_STRONG_LINK_TO_DOCS
}
#{
THANKS_FOR_READING_BANNER
}
}
end
def
conflicting_files_msg
header
=
"The conflicts detected were as follows:
\n
"
separator
=
"
\n
- "
failed_items
=
failed_files
.
join
(
separator
)
"
#{
header
}#{
separator
}#{
failed_items
}
"
end
end
end
lib/tasks/ee_compat_check.rake
deleted
100644 → 0
View file @
6259a242
desc
'Checks if the branch would apply cleanly to EE'
task
ee_compat_check: :environment
do
Rake
::
Task
[
'gitlab:dev:ee_compat_check'
].
invoke
end
lib/tasks/gitlab/dev.rake
deleted
100644 → 0
View file @
6259a242
namespace
:gitlab
do
namespace
:dev
do
desc
'Checks if the branch would apply cleanly to EE'
task
:ee_compat_check
,
[
:branch
]
=>
:environment
do
|
_
,
args
|
opts
=
if
ENV
[
'CI'
]
{
ce_project_url:
ENV
[
'CI_PROJECT_URL'
],
branch:
ENV
[
'CI_COMMIT_REF_NAME'
],
job_id:
ENV
[
'CI_JOB_ID'
]
}
else
unless
args
[
:branch
]
puts
"Must specify a branch as an argument"
.
color
(
:red
)
exit
1
end
args
end
if
File
.
basename
(
Rails
.
root
)
==
'gitlab'
puts
"Skipping EE projects"
exit
0
elsif
Gitlab
::
EeCompatCheck
.
new
(
opts
||
{}).
check
exit
0
else
exit
1
end
end
end
end
scripts/ee_specific_check/ee_specific_check.rb
deleted
100644 → 0
View file @
6259a242
# frozen_string_literal: true
# rubocop: disable CodeReuse/ActiveRecord
module
EESpecificCheck
WHITELIST
=
[
'CHANGELOG-EE.md'
,
'scripts/**/*'
,
'vendor/assets/javascripts/jasmine-jquery.js'
,
'.gitlab-ci.yml'
,
'.gitlab/ci/rails.gitlab-ci.yml'
,
'db/schema.rb'
,
'locale/gitlab.pot'
].
freeze
CompareBase
=
Struct
.
new
(
:ce_base
,
:ee_base
,
:ce_head
,
:ee_head
)
GitStatus
=
Struct
.
new
(
:porcelain
,
:head
)
module_function
def
git_version
say
run_git_command
(
'--version'
)
end
def
say
(
message
)
warn
"
\n
#{
message
}
"
,
"
\n
"
# puts would eat trailing newline
end
def
find_compare_base
git_clean
ce_fetch_head
=
fetch_remote_ce_branch
ee_fetch_head
=
head_commit_sha
ce_fetch_base
=
find_merge_base
(
'canonical-ce/master'
,
ce_fetch_head
)
ee_fetch_base
=
find_merge_base
(
'canonical-ee/master'
,
'HEAD'
)
ce_merge_base
=
find_merge_base
(
ce_fetch_head
,
ee_fetch_head
)
ce_updated_head
=
find_ce_compare_head
(
ce_fetch_head
,
ce_fetch_base
,
ce_merge_base
)
CompareBase
.
new
(
ce_merge_base
,
ee_fetch_base
,
ce_updated_head
,
ee_fetch_head
)
end
def
setup_canonical_remotes
run_git_command
(
"remote add canonical-ee https://gitlab.com/gitlab-org/gitlab.git"
,
"remote add canonical-ce https://gitlab.com/gitlab-org/gitlab-foss.git"
,
"fetch canonical-ee master --quiet --depth=9999"
,
"fetch canonical-ce master --quiet --depth=9999"
)
end
def
fetch_remote_ce_branch
setup_canonical_remotes
remote_to_fetch
,
branch_to_fetch
=
find_remote_ce_branch
run_git_command
(
"fetch
#{
remote_to_fetch
}
#{
branch_to_fetch
}
--quiet --depth=9999"
)
"
#{
remote_to_fetch
}
/
#{
branch_to_fetch
}
"
end
def
find_merge_base
(
left
,
right
)
merge_base
=
run_git_command
(
"merge-base
#{
left
}
#{
right
}
"
)
return
merge_base
unless
merge_base
.
empty?
say
<<~
MESSAGE
💥 Unfortunately we cannot find the merge-base for
#{
left
}
and
#{
right
}
,
💥 and we'll try to fix that in:
https://gitlab.com/gitlab-org/gitlab/issues/9120
💥 Before that, please run this job locally as a workaround:
./scripts/ee-specific-lines-check
💥 And paste the result as a discussion to show it to the maintainer.
💥 If you have any questions, please ping @godfat to investigate and
💥 clarify.
MESSAGE
exit
(
253
)
end
def
find_ce_compare_head
(
ce_fetch_head
,
ce_fetch_base
,
ce_merge_base
)
if
git_ancestor?
(
ce_merge_base
,
ce_fetch_base
)
say
(
"CE is ahead of EE, finding backward CE head"
)
find_backward_ce_head
(
ce_fetch_head
,
ce_fetch_base
,
ce_merge_base
)
else
say
(
"CE is behind of EE, finding forward CE head"
)
find_forward_ce_head
(
ce_merge_base
,
ce_fetch_head
)
end
end
def
git_ancestor?
(
ancestor
,
descendant
)
run_git_command
(
"merge-base --is-ancestor
#{
ancestor
}
#{
descendant
}
&& echo y"
)
==
'y'
end
def
find_backward_ce_head
(
ce_fetch_head
,
ce_fetch_base
,
ce_merge_base
)
if
ce_fetch_head
.
start_with?
(
'canonical-ce'
)
# No specific CE branch
say
(
"No CE branch found, using merge base directly"
)
ce_merge_base
elsif
ce_fetch_base
==
ce_merge_base
# Up-to-date, no rebase needed
say
(
"EE is up-to-date with CE, using
#{
ce_fetch_head
}
directly"
)
ce_fetch_head
else
say
(
"Performing rebase to remove commits in CE haven't merged into EE"
)
checkout_and_rebase
(
ce_merge_base
,
ce_fetch_base
,
ce_fetch_head
)
end
end
def
find_forward_ce_head
(
ce_merge_base
,
ce_fetch_head
)
say
(
"Performing merge with CE master for CE branch
#{
ce_fetch_head
}
"
)
with_detached_head
(
ce_fetch_head
)
do
run_git_command
(
"merge
#{
ce_merge_base
}
-s recursive -X patience -m 'ee-specific-auto-merge'"
)
status
=
git_status
if
status
.
porcelain
==
''
status
.
head
else
diff
=
run_git_command
(
"diff"
)
run_git_command
(
"merge --abort"
)
say
<<~
MESSAGE
💥 Git status not clean! This means there's a conflict in
💥
#{
ce_fetch_head
}
with canonical-ce/master. Please resolve
💥 the conflict from CE master and retry this job.
⚠️ Git diff:
#{
diff
}
MESSAGE
exit
(
254
)
end
end
end
# We rebase onto the commit which is the latest commit presented in both
# CE and EE, i.e. ce_merge_base, cutting off commits aren't merged into
# EE yet. Here's an example:
#
# * o: Relevant commits
# * x: Irrelevant commits
# * !: Commits we want to cut off from CE branch
#
# ^-> o CE branch (ce_fetch_head)
# / (ce_fetch_base)
# o -> o -> ! -> x CE master
# v (ce_merge_base)
# o -> o -> o -> x EE master
# \ (ee_fetch_base)
# v-> o EE branch
#
# We want to rebase above into this: (we only change the connection)
#
# -> - -> o CE branch (ce_fetch_head)
# / (ce_fetch_base)
# o -> o -> ! -> x CE master
# v (ce_merge_base)
# o -> o -> o -> x EE master
# \ (ee_fetch_base)
# v-> o EE branch
#
# Therefore we rebase onto ce_merge_base, which is based off CE master,
# for the CE branch (ce_fetch_head), effective remove the commit marked
# as ! in the graph for CE branch. We need to remove it because it's not
# merged into EE yet, therefore won't be available in the EE branch.
#
# After rebase is done, then we could compare against
# ce_merge_base..ee_fetch_base along with ce_fetch_head..HEAD (EE branch)
# where ce_merge_base..ee_fetch_base is the update-to-date
# CE/EE difference and ce_fetch_head..HEAD is the changes we made in
# CE and EE branches.
def
checkout_and_rebase
(
new_base
,
old_base
,
target_head
)
with_detached_head
(
target_head
)
do
run_git_command
(
"rebase --onto
#{
new_base
}
#{
old_base
}
#{
target_head
}
"
)
status
=
git_status
if
status
.
porcelain
==
''
status
.
head
else
diff
=
run_git_command
(
"diff"
)
run_git_command
(
"rebase --abort"
)
say
<<~
MESSAGE
💥 Git status is not clean! This means the CE branch has or had a
💥 conflict with CE master, and we cannot resolve this in an
💥 automatic way.
💥
💥 Please rebase
#{
target_head
}
with CE master.
💥
💥 For more details, please read:
💥 https://gitlab.com/gitlab-org/gitlab/issues/6038#note_86862115
💥
💥 Git diff:
#{
diff
}
MESSAGE
exit
(
255
)
end
end
end
def
with_detached_head
(
target_head
)
# So that we could switch back. CI sometimes doesn't have the branch,
# so we don't use current_branch here
head
=
current_head
# Use detached HEAD so that we don't update HEAD
run_git_command
(
"checkout -f
#{
target_head
}
"
)
git_clean
yield
ensure
# ensure would still run if we call exit, don't worry
# Make sure to switch back
run_git_command
(
"checkout -f
#{
head
}
"
)
git_clean
end
def
head_commit_sha
run_git_command
(
"rev-parse HEAD"
)
end
def
git_status
GitStatus
.
new
(
run_git_command
(
"status --porcelain"
),
head_commit_sha
)
end
def
git_clean
# We're still seeing errors not ignoring knapsack/ and rspec_flaky/
# Instead of waiting that populate over all the branches, we could
# just remove untracked files anyway, only on CI of course in case
# we're wiping people's data!
# See https://gitlab.com/gitlab-org/gitlab/issues/5912
# Also see https://gitlab.com/gitlab-org/gitlab/-/jobs/68194333
run_git_command
(
'clean -fd'
)
if
ENV
[
'CI'
]
end
def
remove_remotes
run_git_command
(
"remote remove canonical-ee"
,
"remote remove canonical-ce"
,
"remote remove target-ce"
)
end
def
updated_diff_numstat
(
from
,
to
)
scan_diff_numstat
(
run_git_command
(
"diff
#{
from
}
..
#{
to
}
--numstat -- . ':!ee' ':!qa/qa/ee' ':!qa/qa/ee.rb' ':!qa/qa/specs/features/ee'"
))
end
def
find_remote_ce_branch
branch_to_fetch
=
matching_ce_refs
.
first
if
branch_to_fetch
say
"💪 We found the branch '
#{
branch_to_fetch
}
' in the
#{
ce_repo_url
}
repository. We will fetch it."
run_git_command
(
"remote add target-ce
#{
ce_repo_url
}
"
)
[
'target-ce'
,
branch_to_fetch
]
else
say
<<~
MESSAGE
⚠️ We did not find a branch that would match the current '
#{
current_branch
}
' branch in the
#{
ce_repo_url
}
repository. We will fetch 'master' instead.
ℹ️ If you have a CE branch for the current branch, make sure that its name includes '
#{
minimal_ce_branch_name
}
'.
MESSAGE
%w[canonical-ce master]
end
end
def
ce_repo_url
@ce_repo_url
||=
begin
repo_url
=
ENV
.
fetch
(
'CI_REPOSITORY_URL'
,
'https://gitlab.com/gitlab-org/gitlab-foss.git'
)
# This workaround can be removed once we rename the dev CE project
# https://gitlab.com/gitlab-org/gitlab-foss/issues/59107
project_name
=
repo_url
=~
/dev\.gitlab\.org/
?
'gitlabhq'
:
'gitlab-ce'
repo_url
.
sub
(
'gitlab-ee'
,
project_name
)
end
end
def
current_head
@current_head
||=
ENV
.
fetch
(
'CI_COMMIT_SHA'
,
current_branch
)
end
def
current_branch
@current_branch
||=
ENV
.
fetch
(
'CI_COMMIT_REF_NAME'
,
`git rev-parse --abbrev-ref HEAD`
).
strip
end
def
minimal_ce_branch_name
@minimal_ce_branch_name
||=
current_branch
.
sub
(
/(\Aee\-|\-ee\z)/
,
''
)
end
def
matching_ce_refs
@matching_ce_refs
||=
run_git_command
(
"ls-remote
#{
ce_repo_url
}
\"
*
#{
minimal_ce_branch_name
}
*
\"
"
)
.
scan
(
%r{(?<=refs/heads/|refs/tags/).+}
)
.
select
{
|
branch
|
branch
.
match?
(
/\b
#{
minimal_ce_branch_name
}
\b/i
)
}
.
sort_by
(
&
:size
)
end
def
scan_diff_numstat
(
numstat
)
numstat
.
scan
(
/(\d+)\s+(\d+)\s+(.+)/
)
.
each_with_object
(
Hash
.
new
(
0
))
do
|
(
added
,
deleted
,
file
),
result
|
result
[
file
]
=
added
.
to_i
+
deleted
.
to_i
end
end
def
run_git_command
(
*
commands
)
cmds
=
commands
.
map
{
|
cmd
|
"git
#{
cmd
}
"
}
output
=
run_command
(
*
cmds
)
if
commands
.
size
==
1
output
.
first
else
output
end
end
def
run_command
(
*
commands
)
commands
.
map
do
|
cmd
|
warn
"=> Running `
#{
cmd
}
`"
`
#{
cmd
}
`
.
strip
end
end
end
if
$0
==
__FILE__
require
'rspec/autorun'
RSpec
.
describe
EESpecificCheck
do
subject
{
Class
.
new
{
include
EESpecificCheck
}.
new
}
before
do
allow
(
subject
).
to
receive
(
:warn
)
EESpecificCheck
.
private_instance_methods
.
each
do
|
name
|
subject
.
class
.
__send__
(
:public
,
name
)
# rubocop:disable GitlabSecurity/PublicSend
end
end
describe
'.run_git_command'
do
it
'returns the single output when there is a single command'
do
output
=
subject
.
run_git_command
(
'status'
)
expect
(
output
).
to
be_kind_of
(
String
)
expect
(
subject
).
to
have_received
(
:warn
).
with
(
/git status/
)
end
it
'returns an array of output for more commands'
do
output
=
subject
.
run_git_command
(
'status'
,
'help'
)
expect
(
output
).
to
all
(
be_a
(
String
))
expect
(
subject
).
to
have_received
(
:warn
).
with
(
/git status/
)
expect
(
subject
).
to
have_received
(
:warn
).
with
(
/git help/
)
end
end
describe
'.find_merge_base'
do
context
'when it cannot find the merge base'
do
before
do
allow
(
subject
).
to
receive
(
:say
)
allow
(
subject
).
to
receive
(
:exit
)
expect
(
subject
).
to
receive
(
:run_git_command
).
and_return
(
''
)
end
it
'calls exit(253) to fail the job and ask run it locally'
do
subject
.
find_merge_base
(
'master'
,
'HEAD'
)
expect
(
subject
).
to
have_received
(
:say
)
.
with
(
Regexp
.
union
(
'./scripts/ee-specific-lines-check'
))
expect
(
subject
).
to
have_received
(
:exit
)
.
with
(
253
)
end
end
context
'when it found the merge base'
do
before
do
expect
(
subject
).
to
receive
(
:run_git_command
).
and_return
(
'deadbeef'
)
end
it
'returns the found merge base'
do
output
=
subject
.
find_merge_base
(
'master'
,
'HEAD'
)
expect
(
output
).
to
eq
(
'deadbeef'
)
end
end
end
describe
'.matching_ce_refs'
do
before
do
expect
(
subject
).
to
receive
(
:current_branch
).
and_return
(
ee_branch
)
expect
(
subject
).
to
receive
(
:run_git_command
)
.
and_return
(
ls_remote_output
)
end
describe
'simple cases'
do
let
(
:ls_remote_output
)
do
<<~
OUTPUT
d6602ec5194c87b0fc87103ca4d67251c76f233a
\t
refs/tags/v9
f25a265a342aed6041ab0cc484224d9ca54b6f41
\t
refs/tags/v9.12
c5db5456ae3b0873fc659c19fafdde22313cc441
\t
refs/tags/v9.123
0918385dbd9656cab0d1d81ba7453d49bbc16250
\t
refs/heads/v9.x
28862662b749fe981386814e2dba87b0e72c1eab
\t
refs/remotes/remote_mirror_3059/v9-to-fix-http-case-problems
5e3496802098c86050c5b463507f3a68a83a9f02
\t
refs/remotes/remote_mirror_3059/29036-use-slack-service-v9
OUTPUT
end
context
'with a ee- prefix'
do
let
(
:ee_branch
)
{
'ee-v9'
}
it
'sorts by matching size'
do
expect
(
subject
.
matching_ce_refs
).
to
eq
(
%w[v9 v9.x v9.12 v9.123]
)
end
end
context
'with a -ee suffix'
do
let
(
:ee_branch
)
{
'v9-ee'
}
it
'sorts by matching size'
do
expect
(
subject
.
matching_ce_refs
).
to
eq
(
%w[v9 v9.x v9.12 v9.123]
)
end
end
end
describe
'with ambiguous branch name'
do
let
(
:ls_remote_output
)
do
<<~
OUTPUT
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/feature/sm/35954-expand-kubernetesservice-to-use-username-password
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/ce-to-ee-231
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/ce-to-ee-2
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/ce-to-1
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/ee-to-ce-123
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/ee-to-ce-12
954d7119384c9f2a3c862bac97beb641eb8755d6
\t
refs/heads/to-ce-1
28862662b749fe981386814e2dba87b0e72c1eab
\t
refs/remotes/remote_mirror_3059/27056-upgrade-vue-resource-to-1-0-3-to-fix-http-case-problems
5e3496802098c86050c5b463507f3a68a83a9f02
\t
refs/remotes/remote_mirror_3059/29036-use-slack-service-to-notify-of-failed-pipelines
OUTPUT
end
context
'with a ee- prefix'
do
let
(
:ee_branch
)
{
'ee-to-ce'
}
let
(
:minimal_ce_branch
)
{
'to-ce'
}
it
'sorts by matching size'
do
expect
(
subject
.
matching_ce_refs
).
to
eq
(
%w[to-ce-1 ee-to-ce-12 ee-to-ce-123]
)
end
end
context
'with a -ee suffix'
do
let
(
:ee_branch
)
{
'ce-to-ee'
}
let
(
:minimal_ce_branch
)
{
'ce-to'
}
it
'sorts by matching size'
do
expect
(
subject
.
matching_ce_refs
).
to
eq
(
%w[ce-to-1 ce-to-ee-2 ce-to-ee-231]
)
end
end
end
end
end
end
scripts/static-analysis
View file @
7159693a
...
...
@@ -37,10 +37,6 @@ tasks = [
%w[scripts/lint-rugged]
]
if
Gitlab
.
ee?
tasks
.
unshift
(
%w[ruby -rbundler/setup scripts/ee_specific_check/ee_specific_check.rb]
)
end
static_analysis
=
Gitlab
::
Popen
::
Runner
.
new
static_analysis
.
run
(
tasks
)
do
|
cmd
,
&
run
|
...
...
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