Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions lib/bootleg/tasks/build/remote.exs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
alias Bootleg.{UI, Config}
use Bootleg.DSL

task :verify_repo_config do
if config(:repo_url) == nil do
raise "Error: repo_url is not set.\n" <>
"# config(:repo_url, \"git@github.com/me/my_app.git\")"
end
end

task :remote_build do
UI.info("Starting remote build")
build_role = Config.get_role(:build)
invoke(:init)
invoke(:clean)
invoke(:push_remote)
invoke(:reset_remote)
invoke(:remote_scm_update)
invoke(:compile)
invoke(:generate_release)

Expand All @@ -18,6 +24,15 @@ task :remote_build do
end
end

task :remote_scm_update do
if config({:git_mode, :push}) == :pull do
invoke(:pull_remote)
else
invoke(:push_remote)
invoke(:reset_remote)
end
end

task :generate_release do
UI.info("Generating release")
mix_env = config({:mix_env, "prod"})
Expand Down Expand Up @@ -174,3 +189,52 @@ task :push_remote do
{:error, status}
end
end

task :pull_remote do
refspec = config({:refspec, "master"})
repo_url = config(:repo_url)
build_role = Config.get_role(:build)
workspace = build_role.options[:workspace]

repo_path =
if build_role.options[:repo_path], do: build_role.options[:repo_path], else: "/tmp/repos"

remote :build do
"mkdir -p #{repo_path}"
end

[{:ok, result, 0, _}] =
remote :build, cd: repo_path do
"ls -la"
end

result =
result
|> Keyword.get_values(:stdout)
|> Enum.join("\n")

unless result =~ "#{Config.app()}.git" do
remote :build, cd: repo_path do
"git clone --mirror #{repo_url} #{Config.app()}.git"
end
end

workspace_path =
case Path.type(workspace) do
:absolute ->
workspace

_ ->
"/home/#{build_role.user}/#{workspace}"
end

UI.info("Pulling new commits with git from: #{repo_url}")

remote :build, cd: "#{repo_path}/#{Config.app()}.git" do
"git remote set-url origin #{repo_url}"
"git remote update --prune"
"git archive #{refspec} | tar -x -f - -C #{workspace_path}"
end
end

before_task(:pull_remote, :verify_repo_config)
1 change: 1 addition & 0 deletions test/bootleg/tasks/build_task_functional_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Bootleg.Tasks.BuildTaskFunctionalTest do
use Bootleg.DSL
config :app, :build_me
config :version, "0.1.0"

workspace = if role_opts[:workspace], do: role_opts[:workspace], else: "workspace"

role(
Expand Down
59 changes: 59 additions & 0 deletions test/bootleg/tasks/scm_tasks_functional_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule Bootleg.Tasks.ScmTasksFunctionalTest do
use Bootleg.DSL
use Bootleg.FunctionalCase, async: false
alias Bootleg.Fixtures
import ExUnit.CaptureIO

setup %{hosts: [host], role_opts: role_opts} do
use Bootleg.DSL
config :app, :build_me
config :version, "0.1.0"

workspace = if role_opts[:workspace], do: role_opts[:workspace], else: "workspace"

role(
:build,
host.ip,
port: host.port,
user: host.user,
password: host.password,
silently_accept_hosts: true,
workspace: workspace,
identity: host.private_key_path
)

%{
project_location: Fixtures.inflate_project()
}
end

test "'git_mode pull' downloads source via git pull" do
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
use Bootleg.DSL
config :git_mode, :pull
config :repo_url, "/opt/repos/simple.git"

capture_io(fn ->
invoke(:remote_scm_update)
assert [{:ok, _, 0, _}] = remote(:build, "[ -f README.md ]")
assert [{:ok, [stdout: "Foobar\n"], _, _}] = remote(:build, "cat README.md")
end)
end

test "'git_mode push' uploads source via git push", %{project_location: location} do
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
use Bootleg.DSL
config :git_mode, :push

File.cd!(location, fn ->
out =
capture_io(fn ->
invoke(:init)
invoke(:remote_scm_update)
end)

assert String.match?(out, ~r/Pushing new commits/)
assert String.match?(out, ~r/HEAD is now at/)
end)
end
end
1 change: 1 addition & 0 deletions test/fixtures/build_me/rel/config.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# credo:disable-for-this-file Credo.Check.Design.DuplicatedCode
# Import all plugins from `rel/plugins`
# They can then be used by adding `plugin MyPlugin` to
# either an environment, or release definition, where
Expand Down
15 changes: 15 additions & 0 deletions test/support/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ RUN chmod -R a+x /fixtures/bin
RUN printf 'export PATH=$PATH:/fixtures/bin\n' >> /etc/profile
RUN printf "PATH=$PATH:/fixtures/bin\nBOOTLEG_PATH=/project\n" > /etc/skel/.ssh/environment

# Create git repository
RUN mkdir -p /opt/repos/
RUN git init --bare /opt/repos/simple.git

RUN mkdir -p /tmp/app/simple
WORKDIR /tmp/app/simple
RUN git init
RUN git config user.email local@example.com
RUN git config user.name Miscellaneous Minstrel
RUN echo "Foobar" > README.md
RUN git add .
RUN git commit -m "Initial commit"
RUN git remote add origin /opt/repos/simple.git
RUN git push origin master

# Run SSH daemon and expose the standard SSH port.
EXPOSE 22

Expand Down