piko-fast-tool 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/capistrano-3.20.1/CHANGELOG.md +1 -0
- data/capistrano-3.20.1/CONTRIBUTING.md +63 -0
- data/capistrano-3.20.1/DEVELOPMENT.md +112 -0
- data/capistrano-3.20.1/Gemfile +9 -0
- data/capistrano-3.20.1/LICENSE.txt +21 -0
- data/capistrano-3.20.1/README.md +221 -0
- data/capistrano-3.20.1/RELEASING.md +17 -0
- data/capistrano-3.20.1/Rakefile +24 -0
- data/capistrano-3.20.1/UPGRADING-3.7.md +86 -0
- data/capistrano-3.20.1/bin/cap +3 -0
- data/capistrano-3.20.1/bin/capify +8 -0
- data/capistrano-3.20.1/capistrano.gemspec +34 -0
- data/capistrano-3.20.1/docker-compose.yml +8 -0
- data/capistrano-3.20.1/features/configuration.feature +28 -0
- data/capistrano-3.20.1/features/deploy.feature +92 -0
- data/capistrano-3.20.1/features/deploy_failure.feature +17 -0
- data/capistrano-3.20.1/features/doctor.feature +11 -0
- data/capistrano-3.20.1/features/installation.feature +21 -0
- data/capistrano-3.20.1/features/sshconnect.feature +11 -0
- data/capistrano-3.20.1/features/stage_failure.feature +9 -0
- data/capistrano-3.20.1/features/step_definitions/assertions.rb +162 -0
- data/capistrano-3.20.1/features/step_definitions/cap_commands.rb +21 -0
- data/capistrano-3.20.1/features/step_definitions/setup.rb +91 -0
- data/capistrano-3.20.1/features/subdirectory.feature +9 -0
- data/capistrano-3.20.1/features/support/docker_gateway.rb +53 -0
- data/capistrano-3.20.1/features/support/env.rb +1 -0
- data/capistrano-3.20.1/features/support/remote_command_helpers.rb +29 -0
- data/capistrano-3.20.1/features/support/remote_ssh_helpers.rb +33 -0
- data/capistrano-3.20.1/gemfiles/legacy.gemfile +7 -0
- data/capistrano-3.20.1/lib/Capfile +3 -0
- data/capistrano-3.20.1/lib/capistrano/all.rb +17 -0
- data/capistrano-3.20.1/lib/capistrano/application.rb +153 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/filter.rb +26 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/host_filter.rb +29 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/null_filter.rb +9 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/plugin_installer.rb +51 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/question.rb +76 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/role_filter.rb +29 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/scm_resolver.rb +149 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/server.rb +135 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/servers.rb +76 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/validated_variables.rb +110 -0
- data/capistrano-3.20.1/lib/capistrano/configuration/variables.rb +112 -0
- data/capistrano-3.20.1/lib/capistrano/configuration.rb +189 -0
- data/capistrano-3.20.1/lib/capistrano/console.rb +1 -0
- data/capistrano-3.20.1/lib/capistrano/defaults.rb +36 -0
- data/capistrano-3.20.1/lib/capistrano/deploy.rb +3 -0
- data/capistrano-3.20.1/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/capistrano-3.20.1/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/capistrano-3.20.1/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/capistrano-3.20.1/lib/capistrano/doctor/servers_doctor.rb +105 -0
- data/capistrano-3.20.1/lib/capistrano/doctor/variables_doctor.rb +74 -0
- data/capistrano-3.20.1/lib/capistrano/doctor.rb +6 -0
- data/capistrano-3.20.1/lib/capistrano/dotfile.rb +2 -0
- data/capistrano-3.20.1/lib/capistrano/dsl/env.rb +43 -0
- data/capistrano-3.20.1/lib/capistrano/dsl/paths.rb +89 -0
- data/capistrano-3.20.1/lib/capistrano/dsl/stages.rb +31 -0
- data/capistrano-3.20.1/lib/capistrano/dsl/task_enhancements.rb +61 -0
- data/capistrano-3.20.1/lib/capistrano/dsl.rb +95 -0
- data/capistrano-3.20.1/lib/capistrano/framework.rb +2 -0
- data/capistrano-3.20.1/lib/capistrano/i18n.rb +46 -0
- data/capistrano-3.20.1/lib/capistrano/immutable_task.rb +30 -0
- data/capistrano-3.20.1/lib/capistrano/install.rb +1 -0
- data/capistrano-3.20.1/lib/capistrano/plugin.rb +95 -0
- data/capistrano-3.20.1/lib/capistrano/proc_helpers.rb +13 -0
- data/capistrano-3.20.1/lib/capistrano/scm/git.rb +106 -0
- data/capistrano-3.20.1/lib/capistrano/scm/hg.rb +55 -0
- data/capistrano-3.20.1/lib/capistrano/scm/plugin.rb +13 -0
- data/capistrano-3.20.1/lib/capistrano/scm/svn.rb +56 -0
- data/capistrano-3.20.1/lib/capistrano/scm/tasks/git.rake +84 -0
- data/capistrano-3.20.1/lib/capistrano/scm/tasks/hg.rake +53 -0
- data/capistrano-3.20.1/lib/capistrano/scm/tasks/svn.rake +53 -0
- data/capistrano-3.20.1/lib/capistrano/scm.rb +115 -0
- data/capistrano-3.20.1/lib/capistrano/setup.rb +36 -0
- data/capistrano-3.20.1/lib/capistrano/tasks/console.rake +25 -0
- data/capistrano-3.20.1/lib/capistrano/tasks/deploy.rake +280 -0
- data/capistrano-3.20.1/lib/capistrano/tasks/doctor.rake +24 -0
- data/capistrano-3.20.1/lib/capistrano/tasks/framework.rake +67 -0
- data/capistrano-3.20.1/lib/capistrano/tasks/install.rake +41 -0
- data/capistrano-3.20.1/lib/capistrano/templates/Capfile +38 -0
- data/capistrano-3.20.1/lib/capistrano/templates/deploy.rb.erb +39 -0
- data/capistrano-3.20.1/lib/capistrano/templates/stage.rb.erb +61 -0
- data/capistrano-3.20.1/lib/capistrano/upload_task.rb +9 -0
- data/capistrano-3.20.1/lib/capistrano/version.rb +3 -0
- data/capistrano-3.20.1/lib/capistrano/version_validator.rb +32 -0
- data/capistrano-3.20.1/lib/capistrano.rb +0 -0
- data/capistrano-3.20.1/spec/integration/dsl_spec.rb +632 -0
- data/capistrano-3.20.1/spec/integration_spec_helper.rb +5 -0
- data/capistrano-3.20.1/spec/lib/capistrano/application_spec.rb +60 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/question_spec.rb +92 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/server_spec.rb +309 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
- data/capistrano-3.20.1/spec/lib/capistrano/configuration_spec.rb +357 -0
- data/capistrano-3.20.1/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/capistrano-3.20.1/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
- data/capistrano-3.20.1/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/capistrano-3.20.1/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
- data/capistrano-3.20.1/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
- data/capistrano-3.20.1/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
- data/capistrano-3.20.1/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
- data/capistrano-3.20.1/spec/lib/capistrano/dsl_spec.rb +125 -0
- data/capistrano-3.20.1/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/capistrano-3.20.1/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/capistrano-3.20.1/spec/lib/capistrano/scm/git_spec.rb +194 -0
- data/capistrano-3.20.1/spec/lib/capistrano/scm/hg_spec.rb +109 -0
- data/capistrano-3.20.1/spec/lib/capistrano/scm/svn_spec.rb +137 -0
- data/capistrano-3.20.1/spec/lib/capistrano/scm_spec.rb +103 -0
- data/capistrano-3.20.1/spec/lib/capistrano/upload_task_spec.rb +19 -0
- data/capistrano-3.20.1/spec/lib/capistrano/version_validator_spec.rb +118 -0
- data/capistrano-3.20.1/spec/lib/capistrano_spec.rb +7 -0
- data/capistrano-3.20.1/spec/spec_helper.rb +29 -0
- data/capistrano-3.20.1/spec/support/matchers.rb +5 -0
- data/capistrano-3.20.1/spec/support/tasks/database.rake +11 -0
- data/capistrano-3.20.1/spec/support/tasks/fail.rake +8 -0
- data/capistrano-3.20.1/spec/support/tasks/failed.rake +5 -0
- data/capistrano-3.20.1/spec/support/tasks/plugin.rake +6 -0
- data/capistrano-3.20.1/spec/support/tasks/root.rake +11 -0
- data/capistrano-3.20.1/spec/support/test_app.rb +205 -0
- data/piko-fast-tool.gemspec +11 -0
- metadata +167 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Feature: Deploy
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app with the default configuration
|
|
5
|
+
And servers with the roles app and web
|
|
6
|
+
|
|
7
|
+
Scenario: Creating the repo
|
|
8
|
+
When I run cap "git:check"
|
|
9
|
+
Then the task is successful
|
|
10
|
+
And git wrapper permissions are 0700
|
|
11
|
+
|
|
12
|
+
Scenario: Creating the directory structure
|
|
13
|
+
When I run cap "deploy:check:directories"
|
|
14
|
+
Then the shared path is created
|
|
15
|
+
And the releases path is created
|
|
16
|
+
|
|
17
|
+
Scenario: Creating linked directories
|
|
18
|
+
When I run cap "deploy:check:linked_dirs"
|
|
19
|
+
Then directories in :linked_dirs are created in shared
|
|
20
|
+
|
|
21
|
+
Scenario: Creating linked directories for linked files
|
|
22
|
+
When I run cap "deploy:check:make_linked_dirs"
|
|
23
|
+
Then directories referenced in :linked_files are created in shared
|
|
24
|
+
|
|
25
|
+
Scenario: Checking linked files - missing file
|
|
26
|
+
Given a linked file "missing_file.txt"
|
|
27
|
+
But file "missing_file.txt" does not exist in shared path
|
|
28
|
+
When I run cap "deploy:check:linked_files"
|
|
29
|
+
Then the task fails
|
|
30
|
+
|
|
31
|
+
Scenario: Checking linked files - file exists
|
|
32
|
+
Given a linked file "existing_file.txt"
|
|
33
|
+
And file "existing_file.txt" exists in shared path
|
|
34
|
+
When I run cap "deploy:check:linked_files"
|
|
35
|
+
Then the task is successful
|
|
36
|
+
|
|
37
|
+
Scenario: Creating a release
|
|
38
|
+
Given I run cap "deploy:check:directories"
|
|
39
|
+
When I run cap "git:create_release" as part of a release
|
|
40
|
+
Then the repo is cloned
|
|
41
|
+
And the release is created
|
|
42
|
+
|
|
43
|
+
Scenario: REVISION and REVISION_TIME files are present
|
|
44
|
+
When I make 1 deployment
|
|
45
|
+
Then the REVISION file is created in the release
|
|
46
|
+
Then the REVISION_TIME file is created in the release
|
|
47
|
+
|
|
48
|
+
Scenario: Symlink linked files
|
|
49
|
+
When I run cap "deploy:symlink:linked_files deploy:symlink:release" as part of a release
|
|
50
|
+
Then file symlinks are created in the new release
|
|
51
|
+
|
|
52
|
+
Scenario: Symlink linked dirs
|
|
53
|
+
When I run cap "deploy:symlink:linked_dirs" as part of a release
|
|
54
|
+
Then directory symlinks are created in the new release
|
|
55
|
+
|
|
56
|
+
Scenario: Publishing
|
|
57
|
+
When I run cap "deploy:symlink:release"
|
|
58
|
+
Then the current directory will be a symlink to the release
|
|
59
|
+
|
|
60
|
+
Scenario: Cleanup
|
|
61
|
+
Given config stage file has line "set :keep_releases, 3"
|
|
62
|
+
And 5 valid existing releases
|
|
63
|
+
And an invalid release named "new"
|
|
64
|
+
When I run cap "deploy:cleanup"
|
|
65
|
+
Then 3 valid releases are kept
|
|
66
|
+
And the invalid "new" release is ignored
|
|
67
|
+
|
|
68
|
+
Scenario: Cleanup after many failed releases doesn't remove last good release
|
|
69
|
+
Given config stage file has line "set :keep_releases, 2"
|
|
70
|
+
And I make 2 deployments
|
|
71
|
+
And an invalid release named "77777777777777"
|
|
72
|
+
And an invalid release named "88888888888888"
|
|
73
|
+
And an invalid release named "99999999999999"
|
|
74
|
+
When I run cap "deploy:cleanup"
|
|
75
|
+
Then 3 valid releases are kept
|
|
76
|
+
And the current directory will be a symlink to the release
|
|
77
|
+
|
|
78
|
+
Scenario: Cleanup when there are more releases than arguments can handle
|
|
79
|
+
Given config stage file has line "set :keep_releases, 3"
|
|
80
|
+
And 5000 valid existing releases
|
|
81
|
+
When I run cap "deploy:cleanup"
|
|
82
|
+
Then 3 valid releases are kept
|
|
83
|
+
|
|
84
|
+
Scenario: Rolling Back
|
|
85
|
+
Given I make 2 deployments
|
|
86
|
+
When I run cap "deploy:rollback"
|
|
87
|
+
Then the current symlink points to the previous release
|
|
88
|
+
|
|
89
|
+
Scenario: Rolling Back to a specific release
|
|
90
|
+
Given I make 3 deployments
|
|
91
|
+
When I rollback to a specific release
|
|
92
|
+
Then the current symlink points to that specific release
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Feature: Deploy failure
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app with the default configuration
|
|
5
|
+
And a custom task that will simulate a failure
|
|
6
|
+
And a custom task to run in the event of a failure
|
|
7
|
+
And servers with the roles app and web
|
|
8
|
+
|
|
9
|
+
Scenario: Triggering the custom task
|
|
10
|
+
When I run cap "deploy:starting"
|
|
11
|
+
But an error is raised
|
|
12
|
+
Then the failure task will not run
|
|
13
|
+
|
|
14
|
+
Scenario: Triggering the custom task
|
|
15
|
+
When I run cap "deploy"
|
|
16
|
+
But an error is raised
|
|
17
|
+
Then the failure task will run
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Feature: Doctor
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app with the default configuration
|
|
5
|
+
|
|
6
|
+
Scenario: Running the doctor task
|
|
7
|
+
When I run cap "doctor"
|
|
8
|
+
Then the task is successful
|
|
9
|
+
And contains "Environment" in the output
|
|
10
|
+
And contains "Gems" in the output
|
|
11
|
+
And contains "Variables" in the output
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Feature: Installation
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app without any configuration
|
|
5
|
+
|
|
6
|
+
Scenario: The "install" task documentation can be viewed
|
|
7
|
+
When I run "cap -T"
|
|
8
|
+
Then the task is successful
|
|
9
|
+
And contains "cap install" in the output
|
|
10
|
+
|
|
11
|
+
Scenario: With default stages
|
|
12
|
+
When I run "cap install"
|
|
13
|
+
Then the deploy.rb file is created
|
|
14
|
+
And the default stage files are created
|
|
15
|
+
And the tasks folder is created
|
|
16
|
+
|
|
17
|
+
Scenario: With specified stages
|
|
18
|
+
When I run "cap install STAGES=qa,production"
|
|
19
|
+
Then the deploy.rb file is created
|
|
20
|
+
And the specified stage files are created
|
|
21
|
+
And the tasks folder is created
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Feature: SSH Connection
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app with the default configuration
|
|
5
|
+
And servers with the roles app and web
|
|
6
|
+
And a task which executes as root
|
|
7
|
+
|
|
8
|
+
Scenario: Switching from default user to root and back again
|
|
9
|
+
When I run cap "am_i_root"
|
|
10
|
+
Then the task is successful
|
|
11
|
+
And the output matches "I am uid=0\(root\)" followed by "I am uid=\d+\(deployer\)"
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require "shellwords"
|
|
2
|
+
|
|
3
|
+
Then(/^references in the remote repo are listed$/) do
|
|
4
|
+
expect(@output).to include("refs/heads/master")
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
Then(/^git wrapper permissions are 0700$/) do
|
|
8
|
+
permissions_test = %Q([ $(stat -c "%a" #{TestApp.git_wrapper_path_glob}) == "700" ])
|
|
9
|
+
expect { run_remote_ssh_command(permissions_test) }.not_to raise_error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Then(/^the shared path is created$/) do
|
|
13
|
+
run_remote_ssh_command(test_dir_exists(TestApp.shared_path))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Then(/^the releases path is created$/) do
|
|
17
|
+
run_remote_ssh_command(test_dir_exists(TestApp.releases_path))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Then(/^(\d+) valid releases are kept/) do |num|
|
|
21
|
+
test = %Q([ $(ls -g #{TestApp.releases_path} | grep -E '[0-9]{14}' | wc -l) == "#{num}" ])
|
|
22
|
+
expect { run_remote_ssh_command(test) }.not_to raise_error
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Then(/^the invalid (.+) release is ignored$/) do |filename|
|
|
26
|
+
test = "ls -g #{TestApp.releases_path} | grep #{filename}"
|
|
27
|
+
expect { run_remote_ssh_command(test) }.not_to raise_error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Then(/^directories in :linked_dirs are created in shared$/) do
|
|
31
|
+
TestApp.linked_dirs.each do |dir|
|
|
32
|
+
run_remote_ssh_command(test_dir_exists(TestApp.shared_path.join(dir)))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
Then(/^directories referenced in :linked_files are created in shared$/) do
|
|
37
|
+
dirs = TestApp.linked_files.map { |path| TestApp.shared_path.join(path).dirname }
|
|
38
|
+
dirs.each do |dir|
|
|
39
|
+
run_remote_ssh_command(test_dir_exists(dir))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Then(/^the repo is cloned$/) do
|
|
44
|
+
run_remote_ssh_command(test_dir_exists(TestApp.repo_path))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Then(/^the release is created$/) do
|
|
48
|
+
stdout, _stderr = run_remote_ssh_command("ls #{TestApp.releases_path}")
|
|
49
|
+
|
|
50
|
+
expect(stdout.strip).to match(/\A#{Time.now.utc.strftime("%Y%m%d")}\d{6}\Z/)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Then(/^the REVISION file is created in the release$/) do
|
|
54
|
+
stdout, _stderr = run_remote_ssh_command("cat #{@release_paths[0]}/REVISION")
|
|
55
|
+
|
|
56
|
+
expect(stdout.strip).to match(/\h{40}/)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
Then(/^the REVISION_TIME file is created in the release$/) do
|
|
60
|
+
stdout, _stderr = run_remote_ssh_command("cat #{@release_paths[0]}/REVISION_TIME")
|
|
61
|
+
|
|
62
|
+
expect(stdout.strip).to match(/\d{10}/)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
Then(/^file symlinks are created in the new release$/) do
|
|
66
|
+
TestApp.linked_files.each do |file|
|
|
67
|
+
run_remote_ssh_command(test_symlink_exists(TestApp.current_path.join(file)))
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Then(/^directory symlinks are created in the new release$/) do
|
|
72
|
+
pending
|
|
73
|
+
TestApp.linked_dirs.each do |dir|
|
|
74
|
+
run_remote_ssh_command(test_symlink_exists(TestApp.release_path.join(dir)))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
Then(/^the current directory will be a symlink to the release$/) do
|
|
79
|
+
run_remote_ssh_command(exists?("e", TestApp.current_path))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
Then(/^the deploy\.rb file is created$/) do
|
|
83
|
+
file = TestApp.test_app_path.join("config/deploy.rb")
|
|
84
|
+
expect(File.exist?(file)).to be true
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
Then(/^the default stage files are created$/) do
|
|
88
|
+
staging = TestApp.test_app_path.join("config/deploy/staging.rb")
|
|
89
|
+
production = TestApp.test_app_path.join("config/deploy/production.rb")
|
|
90
|
+
expect(File.exist?(staging)).to be true
|
|
91
|
+
expect(File.exist?(production)).to be true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
Then(/^the tasks folder is created$/) do
|
|
95
|
+
path = TestApp.test_app_path.join("lib/capistrano/tasks")
|
|
96
|
+
expect(Dir.exist?(path)).to be true
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
Then(/^the specified stage files are created$/) do
|
|
100
|
+
qa = TestApp.test_app_path.join("config/deploy/qa.rb")
|
|
101
|
+
production = TestApp.test_app_path.join("config/deploy/production.rb")
|
|
102
|
+
expect(File.exist?(qa)).to be true
|
|
103
|
+
expect(File.exist?(production)).to be true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Then(/^it creates the file with the remote_task prerequisite$/) do
|
|
107
|
+
TestApp.linked_files.each do |file|
|
|
108
|
+
run_remote_ssh_command(test_file_exists(TestApp.shared_path.join(file)))
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
Then(/^it will not recreate the file$/) do
|
|
113
|
+
#
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
Then(/^the task is successful$/) do
|
|
117
|
+
expect(@success).to be true
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
Then(/^the task fails$/) do
|
|
121
|
+
expect(@success).to be_falsey
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
Then(/^the failure task will run$/) do
|
|
125
|
+
failed = TestApp.shared_path.join("failed")
|
|
126
|
+
run_remote_ssh_command(test_file_exists(failed))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
Then(/^the failure task will not run$/) do
|
|
130
|
+
failed = TestApp.shared_path.join("failed")
|
|
131
|
+
expect { run_remote_ssh_command(test_file_exists(failed)) }
|
|
132
|
+
.to raise_error(RemoteSSHHelpers::RemoteSSHCommandError)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
When(/^an error is raised$/) do
|
|
136
|
+
error = TestApp.shared_path.join("fail")
|
|
137
|
+
run_remote_ssh_command(test_file_exists(error))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
Then(/contains "([^"]*)" in the output/) do |expected|
|
|
141
|
+
expect(@output).to include(expected)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
Then(/the output matches "([^"]*)" followed by "([^"]*)"/) do |expected, followedby|
|
|
145
|
+
expect(@output).to match(/#{expected}.*#{followedby}/m)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
Then(/doesn't contain "([^"]*)" in the output/) do |expected|
|
|
149
|
+
expect(@output).not_to include(expected)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
Then(/the current symlink points to the previous release/) do
|
|
153
|
+
previous_release_path = @release_paths[-2]
|
|
154
|
+
|
|
155
|
+
run_remote_ssh_command(symlinked?(TestApp.current_path, previous_release_path))
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
Then(/^the current symlink points to that specific release$/) do
|
|
159
|
+
specific_release_path = TestApp.releases_path.join(@rollback_release)
|
|
160
|
+
|
|
161
|
+
run_remote_ssh_command(symlinked?(TestApp.current_path, specific_release_path))
|
|
162
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
When(/^I run cap "(.*?)"$/) do |task|
|
|
2
|
+
@success, @output = TestApp.cap(task)
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
When(/^I run cap "(.*?)" within the "(.*?)" directory$/) do |task, directory|
|
|
6
|
+
@success, @output = TestApp.cap(task, directory)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
When(/^I run cap "(.*?)" as part of a release$/) do |task|
|
|
10
|
+
TestApp.cap("deploy:new_release_path #{task}")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
When(/^I run "(.*?)"$/) do |command|
|
|
14
|
+
@success, @output = TestApp.run(command)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
When(/^I rollback to a specific release$/) do
|
|
18
|
+
@rollback_release = @release_paths.first.split("/").last
|
|
19
|
+
|
|
20
|
+
step %Q{I run cap "deploy:rollback ROLLBACK_RELEASE=#{@rollback_release}"}
|
|
21
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
Given(/^a test app with the default configuration$/) do
|
|
2
|
+
TestApp.install
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
Given(/^a test app without any configuration$/) do
|
|
6
|
+
TestApp.create_test_app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
Given(/^servers with the roles app and web$/) do
|
|
10
|
+
start_ssh_server
|
|
11
|
+
wait_for_ssh_server
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Given(/^a linked file "(.*?)"$/) do |file|
|
|
15
|
+
# ignoring other linked files
|
|
16
|
+
TestApp.append_to_deploy_file("set :linked_files, ['#{file}']")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Given(/^file "(.*?)" exists in shared path$/) do |file|
|
|
20
|
+
file_shared_path = TestApp.shared_path.join(file)
|
|
21
|
+
run_remote_ssh_command("mkdir -p #{file_shared_path.dirname}")
|
|
22
|
+
run_remote_ssh_command("touch #{file_shared_path}")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Given(/^all linked files exists in shared path$/) do
|
|
26
|
+
TestApp.linked_files.each do |linked_file|
|
|
27
|
+
step %Q{file "#{linked_file}" exists in shared path}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Given(/^file "(.*?)" does not exist in shared path$/) do |file|
|
|
32
|
+
file_shared_path = TestApp.shared_path.join(file)
|
|
33
|
+
run_remote_ssh_command("mkdir -p #{TestApp.shared_path}")
|
|
34
|
+
run_remote_ssh_command("touch #{file_shared_path} && rm #{file_shared_path}")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Given(/^a custom task to generate a file$/) do
|
|
38
|
+
TestApp.copy_task_to_test_app("spec/support/tasks/database.rake")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Given(/^a task which executes as root$/) do
|
|
42
|
+
TestApp.copy_task_to_test_app("spec/support/tasks/root.rake")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Given(/config stage file has line "(.*?)"/) do |line|
|
|
46
|
+
TestApp.append_to_deploy_file(line)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Given(/^the configuration is in a custom location$/) do
|
|
50
|
+
TestApp.move_configuration_to_custom_location("app")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Given(/^a custom task that will simulate a failure$/) do
|
|
54
|
+
safely_remove_file(TestApp.shared_path.join("failed"))
|
|
55
|
+
TestApp.copy_task_to_test_app("spec/support/tasks/fail.rake")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
Given(/^a custom task to run in the event of a failure$/) do
|
|
59
|
+
safely_remove_file(TestApp.shared_path.join("failed"))
|
|
60
|
+
TestApp.copy_task_to_test_app("spec/support/tasks/failed.rake")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Given(/^a stage file named (.+)$/) do |filename|
|
|
64
|
+
TestApp.write_local_stage_file(filename)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
Given(/^I make (\d+) deployments?$/) do |count|
|
|
68
|
+
step "all linked files exists in shared path"
|
|
69
|
+
|
|
70
|
+
@release_paths = (1..count.to_i).map do
|
|
71
|
+
TestApp.cap("deploy")
|
|
72
|
+
stdout, _stderr = run_remote_ssh_command("readlink #{TestApp.current_path}")
|
|
73
|
+
|
|
74
|
+
stdout.strip
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
Given(/^(\d+) valid existing releases$/) do |num|
|
|
79
|
+
a_day = 86_400 # in seconds
|
|
80
|
+
(1...num).each_slice(100) do |num_batch|
|
|
81
|
+
dirs = num_batch.map do |i|
|
|
82
|
+
offset = -(a_day * i)
|
|
83
|
+
TestApp.release_path(TestApp.timestamp(offset))
|
|
84
|
+
end
|
|
85
|
+
run_remote_ssh_command("mkdir -p #{dirs.join(' ')}")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Given(/^an invalid release named "(.+)"$/) do |filename|
|
|
90
|
+
run_remote_ssh_command("mkdir -p #{TestApp.release_path(filename)}")
|
|
91
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Feature: cap can be run from a subdirectory, and will still find the Capfile
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given a test app with the default configuration
|
|
5
|
+
And servers with the roles app and web
|
|
6
|
+
|
|
7
|
+
Scenario: Running cap from a subdirectory
|
|
8
|
+
When I run cap "git:check" within the "config" directory
|
|
9
|
+
Then the task is successful
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Ensure Docker container is completely stopped when Ruby exits.
|
|
2
|
+
at_exit do
|
|
3
|
+
DockerGateway.new.stop
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# Manages the Docker-based SSH server that is declared in docker-compose.yml.
|
|
7
|
+
class DockerGateway
|
|
8
|
+
def initialize(log_proc=$stderr.method(:puts))
|
|
9
|
+
@log_proc = log_proc
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def start
|
|
13
|
+
run_compose_command("up -d")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def stop
|
|
17
|
+
run_compose_command("down")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def run_shell_command(command)
|
|
21
|
+
run_compose_command("exec ssh_server /bin/bash -c #{command.shellescape}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def run_compose_command(command)
|
|
27
|
+
log "[docker compose] #{command}"
|
|
28
|
+
stdout, stderr, status = Open3.popen3("docker compose #{command}") do |stdin, stdout, stderr, wait_threads|
|
|
29
|
+
stdin << ""
|
|
30
|
+
stdin.close
|
|
31
|
+
out = Thread.new { read_lines(stdout, &$stdout.method(:puts)) }
|
|
32
|
+
err = Thread.new { stderr.read }
|
|
33
|
+
[out.value, err.value.to_s, wait_threads.value]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
(stdout + stderr).each_line { |line| log "[docker compose] #{line}" }
|
|
37
|
+
|
|
38
|
+
[stdout, stderr, status]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def read_lines(io)
|
|
42
|
+
buffer = + ""
|
|
43
|
+
while (line = io.gets)
|
|
44
|
+
buffer << line
|
|
45
|
+
yield line
|
|
46
|
+
end
|
|
47
|
+
buffer
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def log(message)
|
|
51
|
+
@log_proc.call(message)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "../../spec/support/test_app"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module RemoteCommandHelpers
|
|
2
|
+
def test_dir_exists(path)
|
|
3
|
+
exists?("d", path)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def test_symlink_exists(path)
|
|
7
|
+
exists?("L", path)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_file_exists(path)
|
|
11
|
+
exists?("f", path)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def exists?(type, path)
|
|
15
|
+
%Q{[[ -#{type} "#{path}" ]]}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def symlinked?(symlink_path, target_path)
|
|
19
|
+
"[ #{symlink_path} -ef #{target_path} ]"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def safely_remove_file(_path)
|
|
23
|
+
run_remote_ssh_command("rm #{test_file}")
|
|
24
|
+
rescue
|
|
25
|
+
RemoteSSHHelpers::RemoteSSHCommandError
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
World(RemoteCommandHelpers)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "open3"
|
|
2
|
+
require "socket"
|
|
3
|
+
require_relative "docker_gateway"
|
|
4
|
+
|
|
5
|
+
module RemoteSSHHelpers
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
class RemoteSSHCommandError < RuntimeError; end
|
|
9
|
+
|
|
10
|
+
def start_ssh_server
|
|
11
|
+
docker_gateway.start
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def wait_for_ssh_server(retries=3)
|
|
15
|
+
Socket.tcp("localhost", 2022, connect_timeout: 1).close
|
|
16
|
+
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
|
17
|
+
retries -= 1
|
|
18
|
+
sleep(2) && retry if retries.positive?
|
|
19
|
+
raise
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run_remote_ssh_command(command)
|
|
23
|
+
stdout, stderr, status = docker_gateway.run_shell_command(command)
|
|
24
|
+
return [stdout, stderr] if status.success?
|
|
25
|
+
raise RemoteSSHCommandError, status
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def docker_gateway
|
|
29
|
+
@docker_gateway ||= DockerGateway.new(method(:log))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
World(RemoteSSHHelpers)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "rake"
|
|
2
|
+
require "sshkit"
|
|
3
|
+
|
|
4
|
+
require "io/console"
|
|
5
|
+
|
|
6
|
+
Rake.application.options.trace = true
|
|
7
|
+
|
|
8
|
+
require "capistrano/version"
|
|
9
|
+
require "capistrano/version_validator"
|
|
10
|
+
require "capistrano/i18n"
|
|
11
|
+
require "capistrano/dsl"
|
|
12
|
+
require "capistrano/application"
|
|
13
|
+
require "capistrano/configuration"
|
|
14
|
+
require "capistrano/configuration/scm_resolver"
|
|
15
|
+
|
|
16
|
+
module Capistrano
|
|
17
|
+
end
|