DEV: Optimize specs (#238)
Git repositories will be initialized less often and then copied for each spec. This reduces the calls to 'git' and the total execution time of the specs.
This commit is contained in:
parent
3a43aa6be7
commit
957867798e
|
|
@ -38,7 +38,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
|
|
||||||
subject(:repo) do
|
subject(:repo) do
|
||||||
prepare_repos
|
prepare_repos
|
||||||
repo = described_class.new(@local_repo.path)
|
repo = described_class.new(@local_git_repo.path)
|
||||||
repo.update_remote! unless @skip_update_remote
|
repo.update_remote! unless @skip_update_remote
|
||||||
repo
|
repo
|
||||||
end
|
end
|
||||||
|
|
@ -47,7 +47,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@skip_update_remote = false
|
@skip_update_remote = false
|
||||||
@local_repo = @remote_git_repo = nil
|
@local_git_repo = @remote_git_repo = nil
|
||||||
@before_local_repo_clone = []
|
@before_local_repo_clone = []
|
||||||
@after_local_repo_clone = []
|
@after_local_repo_clone = []
|
||||||
end
|
end
|
||||||
|
|
@ -55,32 +55,41 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
after { @remote_git_repo.destroy }
|
after { @remote_git_repo.destroy }
|
||||||
|
|
||||||
def prepare_repos
|
def prepare_repos
|
||||||
return if @local_repo && @remote_git_repo
|
return if @local_git_repo && @remote_git_repo
|
||||||
|
|
||||||
@remote_git_repo = GitHelpers::RemoteGitRepo.new(initial_branch: initial_branch)
|
cache_key =
|
||||||
@remote_git_repo.commit(
|
Digest::SHA1.hexdigest(
|
||||||
filename: "foo.txt",
|
"#{initial_branch}-" + @before_local_repo_clone.map(&:source_location).flatten.join(","),
|
||||||
commits: [
|
)
|
||||||
{ content: "A", date: "2023-03-06T20:31:17Z" },
|
|
||||||
{
|
|
||||||
content: "B",
|
|
||||||
date: "2023-03-06T21:08:52Z",
|
|
||||||
tags: %w[v3.1.0.beta1 beta latest-release],
|
|
||||||
},
|
|
||||||
{ content: "C", date: "2023-03-06T22:48:29Z" },
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@remote_git_repo.create_branches("tests-passed")
|
|
||||||
|
|
||||||
@before_local_repo_clone.each { |callback| callback.call }
|
@remote_git_repo =
|
||||||
@local_repo = @remote_git_repo.create_local_clone(method: clone_method)
|
GitHelpers::RemoteGitRepo.new(initial_branch:, cache_key:) do |repo|
|
||||||
@after_local_repo_clone.each { |callback| callback.call }
|
repo.commit(
|
||||||
|
filename: "foo.txt",
|
||||||
|
commits: [
|
||||||
|
{ content: "A", date: "2023-03-06T20:31:17Z" },
|
||||||
|
{
|
||||||
|
content: "B",
|
||||||
|
date: "2023-03-06T21:08:52Z",
|
||||||
|
tags: %w[v3.1.0.beta1 beta latest-release],
|
||||||
|
},
|
||||||
|
{ content: "C", date: "2023-03-06T22:48:29Z" },
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
repo.create_branches("tests-passed")
|
||||||
|
|
||||||
|
@before_local_repo_clone.each { |callback| callback.call(repo) }
|
||||||
|
end
|
||||||
|
|
||||||
|
@local_git_repo = @remote_git_repo.create_local_clone(method: clone_method)
|
||||||
|
@after_local_repo_clone.each { |callback| callback.call(@remote_git_repo, @local_git_repo) }
|
||||||
|
|
||||||
@remote_git_repo.in_remote_repo { |git| git.call("log --pretty=oneline") }
|
@remote_git_repo.in_remote_repo { |git| git.call("log --pretty=oneline") }
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_new_commits
|
def add_new_commits(remote_repo, local_repo)
|
||||||
@remote_git_repo.commit(
|
remote_repo.commit(
|
||||||
filename: "foo.txt",
|
filename: "foo.txt",
|
||||||
commits: [
|
commits: [
|
||||||
{ content: "D", date: "2023-03-07T10:11:19Z" },
|
{ content: "D", date: "2023-03-07T10:11:19Z" },
|
||||||
|
|
@ -92,12 +101,16 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
{ content: "F", date: "2023-03-07T15:22:23Z" },
|
{ content: "F", date: "2023-03-07T15:22:23Z" },
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@remote_git_repo.rebase(source_branch: "main", target_branch: "tests-passed")
|
remote_repo.rebase(source_branch: "main", target_branch: "tests-passed")
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples "common tests" do
|
shared_examples "common tests" do
|
||||||
context "when tracking `tests-passed` branch" do
|
context "when tracking `tests-passed` branch" do
|
||||||
before { @after_local_repo_clone << -> { @local_repo.checkout("tests-passed") } }
|
before do
|
||||||
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
|
local_repo.checkout("tests-passed")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#has_local_main?" do
|
describe "#has_local_main?" do
|
||||||
context "with existing `main` branch" do
|
context "with existing `main` branch" do
|
||||||
|
|
@ -125,15 +138,19 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
context "with `master` as initial branch" do
|
context "with `master` as initial branch" do
|
||||||
let(:initial_branch) { "master" }
|
let(:initial_branch) { "master" }
|
||||||
|
|
||||||
before { @after_local_repo_clone << -> { @local_repo.checkout("master") } }
|
before do
|
||||||
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
|
local_repo.checkout("master")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "returns `origin/master` if a repo hasn't been renamed" do
|
it "returns `origin/master` if a repo hasn't been renamed" do
|
||||||
expect(repo.tracking_ref).to eq("origin/master")
|
expect(repo.tracking_ref).to eq("origin/master")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns `origin/main` if a repo has been renamed but still tracks `master`" do
|
it "returns `origin/main` if a repo has been renamed but still tracks `master`" do
|
||||||
@after_local_repo_clone << -> do
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
@remote_git_repo.rename_branch(old_name: "master", new_name: "main")
|
remote_repo.rename_branch(old_name: "master", new_name: "main")
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(repo.tracking_ref).to eq("origin/main")
|
expect(repo.tracking_ref).to eq("origin/main")
|
||||||
|
|
@ -141,7 +158,9 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with `main` as current local branch" do
|
context "with `main` as current local branch" do
|
||||||
before { @after_local_repo_clone << -> { @local_repo.checkout("main") } }
|
before do
|
||||||
|
@after_local_repo_clone << ->(remote_repo, local_repo) { local_repo.checkout("main") }
|
||||||
|
end
|
||||||
|
|
||||||
it "returns `origin/main` if a repo points at `origin/main`" do
|
it "returns `origin/main` if a repo points at `origin/main`" do
|
||||||
expect(repo.tracking_ref).to eq("origin/main")
|
expect(repo.tracking_ref).to eq("origin/main")
|
||||||
|
|
@ -157,15 +176,19 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
context "with `master` as initial branch" do
|
context "with `master` as initial branch" do
|
||||||
let(:initial_branch) { "master" }
|
let(:initial_branch) { "master" }
|
||||||
|
|
||||||
before { @after_local_repo_clone << -> { @local_repo.checkout("master") } }
|
before do
|
||||||
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
|
local_repo.checkout("master")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "returns `origin/master` if a repo hasn't been renamed" do
|
it "returns `origin/master` if a repo hasn't been renamed" do
|
||||||
expect(repo.upstream_branch).to eq("origin/master")
|
expect(repo.upstream_branch).to eq("origin/master")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns `origin/master` if a repo has been renamed but still tracks `master`" do
|
it "returns `origin/master` if a repo has been renamed but still tracks `master`" do
|
||||||
@after_local_repo_clone << -> do
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
@remote_git_repo.rename_branch(old_name: "master", new_name: "main")
|
remote_repo.rename_branch(old_name: "master", new_name: "main")
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(repo.upstream_branch).to eq("origin/master")
|
expect(repo.upstream_branch).to eq("origin/master")
|
||||||
|
|
@ -173,7 +196,9 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with `main` as current local branch" do
|
context "with `main` as current local branch" do
|
||||||
before { @after_local_repo_clone << -> { @local_repo.checkout("main") } }
|
before do
|
||||||
|
@after_local_repo_clone << ->(remote_repo, local_repo) { local_repo.checkout("main") }
|
||||||
|
end
|
||||||
|
|
||||||
it "returns `origin/main` if a repo points at `origin/main`" do
|
it "returns `origin/main` if a repo points at `origin/main`" do
|
||||||
expect(repo.upstream_branch).to eq("origin/main")
|
expect(repo.upstream_branch).to eq("origin/main")
|
||||||
|
|
@ -187,7 +212,9 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false when upstream branch doesn't exist" do
|
it "returns false when upstream branch doesn't exist" do
|
||||||
@after_local_repo_clone << -> { @remote_git_repo.delete_branches("tests-passed") }
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
|
remote_repo.delete_branches("tests-passed")
|
||||||
|
end
|
||||||
expect(repo.upstream_branch_exist?).to eq(false)
|
expect(repo.upstream_branch_exist?).to eq(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -225,8 +252,8 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
|
|
||||||
context "with no tags" do
|
context "with no tags" do
|
||||||
before do
|
before do
|
||||||
@before_local_repo_clone << -> do
|
@before_local_repo_clone << ->(repo) do
|
||||||
@remote_git_repo.delete_tags("beta", "latest-release", "v3.1.0.beta1")
|
repo.delete_tags("beta", "latest-release", "v3.1.0.beta1")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -262,7 +289,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
context "with `beta` and version tags on HEAD~1" do
|
context "with `beta` and version tags on HEAD~1" do
|
||||||
before do
|
before do
|
||||||
skip_for_shallow_clone
|
skip_for_shallow_clone
|
||||||
@before_local_repo_clone << -> { @remote_git_repo.delete_tags("latest-release") }
|
@before_local_repo_clone << ->(repo) { repo.delete_tags("latest-release") }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#latest_local_tag_version" do
|
describe "#latest_local_tag_version" do
|
||||||
|
|
@ -287,7 +314,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
describe "#update_remote!" do
|
describe "#update_remote!" do
|
||||||
it "fetches the correct amount of new commits" do
|
it "fetches the correct amount of new commits" do
|
||||||
prepare_repos
|
prepare_repos
|
||||||
expect { repo.update_remote! }.to not_change { @local_repo.commit_count }
|
expect { repo.update_remote! }.to not_change { @local_git_repo.commit_count }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -343,7 +370,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
describe "#update_remote!" do
|
describe "#update_remote!" do
|
||||||
it "fetches the correct amount of new commits" do
|
it "fetches the correct amount of new commits" do
|
||||||
prepare_repos
|
prepare_repos
|
||||||
expect { repo.update_remote! }.to change { @local_repo.commit_count }.by(
|
expect { repo.update_remote! }.to change { @local_git_repo.commit_count }.by(
|
||||||
fetch_commit_count,
|
fetch_commit_count,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
@ -353,13 +380,13 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
|
|
||||||
context "when tracking `beta` tag" do
|
context "when tracking `beta` tag" do
|
||||||
before do
|
before do
|
||||||
@after_local_repo_clone << -> do
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
unless shallow_clone?
|
unless shallow_clone?
|
||||||
@local_repo.checkout("beta")
|
local_repo.checkout("beta")
|
||||||
# Mimics the behavior of `web.template.yml` where we store the value of the `$version` variable
|
# Mimics the behavior of `web.template.yml` where we store the value of the `$version` variable
|
||||||
# as a user-defined config value in git.
|
# as a user-defined config value in git.
|
||||||
# See https://github.com/discourse/discourse_docker/blob/main/templates/web.template.yml
|
# See https://github.com/discourse/discourse_docker/blob/main/templates/web.template.yml
|
||||||
@local_repo.git("config user.discourse-version beta")
|
local_repo.git("config user.discourse-version beta")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -462,7 +489,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
describe "#update_remote!" do
|
describe "#update_remote!" do
|
||||||
it "fetches the correct amount of new commits" do
|
it "fetches the correct amount of new commits" do
|
||||||
prepare_repos
|
prepare_repos
|
||||||
expect { repo.update_remote! }.to not_change { @local_repo.commit_count }
|
expect { repo.update_remote! }.to not_change { @local_git_repo.commit_count }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -522,7 +549,7 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
describe "#update_remote!" do
|
describe "#update_remote!" do
|
||||||
it "fetches the correct amount of new commits" do
|
it "fetches the correct amount of new commits" do
|
||||||
prepare_repos
|
prepare_repos
|
||||||
expect { repo.update_remote! }.to change { @local_repo.commit_count }.by(
|
expect { repo.update_remote! }.to change { @local_git_repo.commit_count }.by(
|
||||||
fetch_commit_count,
|
fetch_commit_count,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
@ -532,14 +559,14 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
|
|
||||||
context "when tracking deleted branch" do
|
context "when tracking deleted branch" do
|
||||||
before do
|
before do
|
||||||
@before_local_repo_clone << -> do
|
@before_local_repo_clone << ->(repo) do
|
||||||
@remote_git_repo.delete_tags("beta")
|
repo.delete_tags("beta")
|
||||||
@remote_git_repo.create_branches("beta")
|
repo.create_branches("beta")
|
||||||
end
|
end
|
||||||
@after_local_repo_clone << -> do
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
@local_repo.checkout("beta")
|
local_repo.checkout("beta")
|
||||||
@remote_git_repo.delete_branches("beta")
|
remote_repo.delete_branches("beta")
|
||||||
@remote_git_repo.in_working_directory do |git|
|
remote_repo.in_working_directory do |git|
|
||||||
git.call("tag -m 'latest beta release' -a beta latest-release^{}")
|
git.call("tag -m 'latest beta release' -a beta latest-release^{}")
|
||||||
git.call("push origin beta")
|
git.call("push origin beta")
|
||||||
end
|
end
|
||||||
|
|
@ -595,7 +622,9 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
describe "#url" do
|
describe "#url" do
|
||||||
before do
|
before do
|
||||||
@skip_update_remote = true
|
@skip_update_remote = true
|
||||||
@after_local_repo_clone << -> { @local_repo.git("remote set-url origin #{remote_url}") }
|
@after_local_repo_clone << ->(remote_repo, local_repo) do
|
||||||
|
local_repo.git("remote set-url origin #{remote_url}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with GitHub HTTPS URL" do
|
context "with GitHub HTTPS URL" do
|
||||||
|
|
@ -657,8 +686,8 @@ RSpec.describe DockerManager::GitRepo do
|
||||||
let!(:clone_method) { GitHelpers::CLONE_SHALLOW }
|
let!(:clone_method) { GitHelpers::CLONE_SHALLOW }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@before_local_repo_clone << -> do
|
@before_local_repo_clone << ->(repo) do
|
||||||
@remote_git_repo.commit(
|
repo.commit(
|
||||||
filename: ".discourse-compatibility",
|
filename: ".discourse-compatibility",
|
||||||
commits: [{ content: "<= 1000.0.0: twoPointFiveBranch", date: "2023-03-06T20:31:17Z" }],
|
commits: [{ content: "<= 1000.0.0: twoPointFiveBranch", date: "2023-03-06T20:31:17Z" }],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,25 @@ module GitHelpers
|
||||||
CLONE_TREELESS = :treeless
|
CLONE_TREELESS = :treeless
|
||||||
|
|
||||||
class RemoteGitRepo
|
class RemoteGitRepo
|
||||||
attr_reader :url, :work_path, :remote_path
|
attr_reader :url, :root_path, :work_path, :remote_path
|
||||||
|
|
||||||
def initialize(initial_branch: "main")
|
@@caches = {}
|
||||||
|
|
||||||
|
def initialize(initial_branch: "main", cache_key: nil, force: false, &blk)
|
||||||
@initial_branch = initial_branch
|
@initial_branch = initial_branch
|
||||||
@local_clone_count = 0
|
@local_clone_count = 0
|
||||||
@root_path = Dir.mktmpdir
|
@root_path = Dir.mktmpdir
|
||||||
|
|
||||||
@remote_path = File.join(@root_path, "remote.git")
|
@remote_path = File.join(@root_path, "remote.git")
|
||||||
|
@work_path = File.join(@root_path, "work")
|
||||||
@url = "file://#{@remote_path}"
|
@url = "file://#{@remote_path}"
|
||||||
|
|
||||||
|
if !force
|
||||||
|
@@caches[cache_key] ||= self.class.new(initial_branch:, cache_key:, force: true, &blk)
|
||||||
|
FileUtils.cp_r(@@caches[cache_key].root_path + "/.", @root_path)
|
||||||
|
Dir.chdir(@work_path) { git "remote set-url origin #{@url}" }
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
Dir.mkdir(@remote_path)
|
Dir.mkdir(@remote_path)
|
||||||
Dir.chdir(@remote_path) do
|
Dir.chdir(@remote_path) do
|
||||||
git "init --bare --initial-branch=#{initial_branch}"
|
git "init --bare --initial-branch=#{initial_branch}"
|
||||||
|
|
@ -23,12 +32,13 @@ module GitHelpers
|
||||||
git "config receive.denyNonFastforwards true"
|
git "config receive.denyNonFastforwards true"
|
||||||
git "config receive.denyCurrentBranch ignore"
|
git "config receive.denyCurrentBranch ignore"
|
||||||
git "config uploadpack.allowFilter true"
|
git "config uploadpack.allowFilter true"
|
||||||
|
git "config commit.gpgsign false"
|
||||||
end
|
end
|
||||||
|
|
||||||
@work_path = File.join(@root_path, "work")
|
|
||||||
Dir.mkdir(@work_path)
|
Dir.mkdir(@work_path)
|
||||||
Dir.chdir(@work_path) do
|
Dir.chdir(@work_path) do
|
||||||
git "init . --initial-branch=#{initial_branch}"
|
git "init . --initial-branch=#{initial_branch}"
|
||||||
|
git "config commit.gpgsign false"
|
||||||
git "remote add origin #{@url}"
|
git "remote add origin #{@url}"
|
||||||
|
|
||||||
File.write("README.md", "This is a git repo for testing docker_manager.")
|
File.write("README.md", "This is a git repo for testing docker_manager.")
|
||||||
|
|
@ -38,6 +48,8 @@ module GitHelpers
|
||||||
git "commit -m 'Initial commit'"
|
git "commit -m 'Initial commit'"
|
||||||
git "push --set-upstream origin #{initial_branch}"
|
git "push --set-upstream origin #{initial_branch}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
yield(self) if block_given?
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
@ -162,7 +174,7 @@ module GitHelpers
|
||||||
if status.success? || !raise_exception
|
if status.success? || !raise_exception
|
||||||
stdout.presence
|
stdout.presence
|
||||||
else
|
else
|
||||||
raise RuntimeError
|
raise RuntimeError.new("stderr while running #{command}: #{stderr}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue