shipit-engine 0.33.0 → 0.34.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -2
- data/app/assets/stylesheets/_pages/_deploy.scss +0 -2
- data/app/controllers/shipit/api/ccmenu_controller.rb +1 -1
- data/app/controllers/shipit/api/deploys_controller.rb +2 -0
- data/app/controllers/shipit/api/rollbacks_controller.rb +2 -1
- data/app/controllers/shipit/api/stacks_controller.rb +1 -0
- data/app/controllers/shipit/deploys_controller.rb +1 -1
- data/app/controllers/shipit/stacks_controller.rb +2 -2
- data/app/controllers/shipit/tasks_controller.rb +2 -2
- data/app/controllers/shipit/webhooks_controller.rb +23 -4
- data/app/helpers/shipit/shipit_helper.rb +0 -1
- data/app/jobs/shipit/deliver_hook_job.rb +1 -1
- data/app/jobs/shipit/github_sync_job.rb +13 -9
- data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +1 -1
- data/app/models/shipit/anonymous_user.rb +6 -2
- data/app/models/shipit/check_run.rb +36 -0
- data/app/models/shipit/commit.rb +20 -9
- data/app/models/shipit/commit_checks.rb +13 -13
- data/app/models/shipit/commit_deployment.rb +3 -3
- data/app/models/shipit/commit_deployment_status.rb +3 -3
- data/app/models/shipit/deploy.rb +16 -11
- data/app/models/shipit/deploy_spec/lerna_discovery.rb +12 -4
- data/app/models/shipit/duration.rb +2 -0
- data/app/models/shipit/hook.rb +26 -2
- data/app/models/shipit/merge_request.rb +9 -7
- data/app/models/shipit/pull_request.rb +1 -1
- data/app/models/shipit/release_status.rb +1 -1
- data/app/models/shipit/repository.rb +9 -3
- data/app/models/shipit/review_stack.rb +16 -2
- data/app/models/shipit/stack.rb +59 -25
- data/app/models/shipit/status/group.rb +1 -1
- data/app/models/shipit/task.rb +6 -2
- data/app/models/shipit/task_execution_strategy/default.rb +4 -5
- data/app/models/shipit/team.rb +4 -2
- data/app/models/shipit/user.rb +4 -0
- data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +1 -1
- data/app/models/shipit/webhooks/handlers/push_handler.rb +4 -1
- data/app/serializers/shipit/merge_request_serializer.rb +1 -1
- data/app/validators/subset_validator.rb +1 -1
- data/app/views/layouts/merge_status.html.erb +1 -1
- data/app/views/shipit/stacks/_banners.html.erb +2 -1
- data/app/views/shipit/stacks/new.html.erb +1 -1
- data/config/secrets.development.example.yml +24 -0
- data/config/secrets.development.shopify.yml +20 -9
- data/db/migrate/20210325194053_remove_stacks_branch_default.rb +5 -0
- data/db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb +5 -0
- data/lib/shipit.rb +39 -15
- data/lib/shipit/command.rb +7 -6
- data/lib/shipit/commands.rb +9 -2
- data/lib/shipit/engine.rb +2 -0
- data/lib/shipit/flock.rb +8 -1
- data/lib/shipit/github_app.rb +7 -5
- data/lib/shipit/octokit_iterator.rb +3 -3
- data/lib/shipit/simple_message_verifier.rb +2 -2
- data/lib/shipit/stack_commands.rb +28 -4
- data/lib/shipit/task_commands.rb +6 -0
- data/lib/shipit/version.rb +1 -1
- data/lib/snippets/publish-lerna-independent-packages +35 -34
- data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
- data/test/controllers/api/ccmenu_controller_test.rb +1 -1
- data/test/controllers/api/deploys_controller_test.rb +17 -0
- data/test/controllers/api/stacks_controller_test.rb +21 -7
- data/test/controllers/webhooks_controller_test.rb +26 -11
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/config/application.rb +1 -1
- data/test/dummy/config/database.yml +9 -0
- data/test/dummy/config/environments/development.rb +1 -1
- data/test/dummy/config/secrets_double_github_app.yml +79 -0
- data/test/dummy/db/schema.rb +5 -4
- data/test/dummy/db/seeds.rb +1 -0
- data/test/fixtures/payloads/check_suite_master.json +2 -30
- data/test/fixtures/payloads/push_master.json +1 -1
- data/test/fixtures/payloads/push_not_master.json +1 -1
- data/test/fixtures/shipit/commits.yml +2 -2
- data/test/fixtures/shipit/hooks.yml +1 -0
- data/test/fixtures/shipit/tasks.yml +1 -1
- data/test/helpers/json_helper.rb +5 -1
- data/test/jobs/github_sync_job_test.rb +2 -1
- data/test/models/commit_deployment_status_test.rb +3 -3
- data/test/models/commits_test.rb +2 -0
- data/test/models/deploy_spec_test.rb +7 -0
- data/test/models/deploys_test.rb +18 -0
- data/test/models/hook_test.rb +30 -1
- data/test/models/merge_request_test.rb +19 -4
- data/test/models/shipit/check_run_test.rb +124 -5
- data/test/models/shipit/review_stack_test.rb +38 -6
- data/test/models/shipit/stacks_test.rb +42 -4
- data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +24 -0
- data/test/models/tasks_test.rb +22 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/anonymous_user_serializer_test.rb +1 -1
- data/test/unit/command_test.rb +5 -0
- data/test/unit/commit_serializer_test.rb +1 -1
- data/test/unit/deploy_commands_test.rb +70 -14
- data/test/unit/deploy_serializer_test.rb +1 -1
- data/test/unit/github_app_test.rb +2 -3
- data/test/unit/github_apps_test.rb +416 -0
- data/test/unit/shipit_deployment_checks_test.rb +77 -0
- data/test/unit/shipit_test.rb +14 -0
- data/test/unit/user_serializer_test.rb +1 -1
- metadata +202 -191
@@ -31,7 +31,7 @@ module Shipit
|
|
31
31
|
end
|
32
32
|
|
33
33
|
delegate :pending?, :success?, :error?, :failure?, :unknown?, :missing?, :state, :simple_state,
|
34
|
-
|
34
|
+
to: :significant_status
|
35
35
|
delegate :each, :size, :map, to: :statuses
|
36
36
|
delegate :required_statuses, to: :commit
|
37
37
|
|
data/app/models/shipit/task.rb
CHANGED
@@ -39,7 +39,7 @@ module Shipit
|
|
39
39
|
scope :last_seven_days, -> { where("created_at > ?", 7.days.ago) }
|
40
40
|
scope :previous_seven_days, -> { where(created_at: 14.days.ago..7.days.ago) }
|
41
41
|
|
42
|
-
scope :due_for_rollup, -> {
|
42
|
+
scope :due_for_rollup, -> { not_active.where(rolled_up: false).where('created_at <= ?', 1.hour.ago) }
|
43
43
|
|
44
44
|
after_save :record_status_change
|
45
45
|
after_create :prevent_concurrency, unless: :allow_concurrency?
|
@@ -175,7 +175,7 @@ module Shipit
|
|
175
175
|
end
|
176
176
|
|
177
177
|
delegate :acquire_git_cache_lock, :async_refresh_deployed_revision, :async_update_estimated_deploy_duration,
|
178
|
-
|
178
|
+
to: :stack
|
179
179
|
|
180
180
|
delegate :checklist, to: :definition
|
181
181
|
|
@@ -283,6 +283,10 @@ module Shipit
|
|
283
283
|
user || AnonymousUser.new
|
284
284
|
end
|
285
285
|
|
286
|
+
def author=(user)
|
287
|
+
super(user.presence)
|
288
|
+
end
|
289
|
+
|
286
290
|
def finished?
|
287
291
|
!pending? && !running? && !aborting?
|
288
292
|
end
|
@@ -83,19 +83,18 @@ module Shipit
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def capture!(command)
|
86
|
-
started_at =
|
86
|
+
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
87
87
|
command.start do
|
88
88
|
@task.ping
|
89
89
|
check_for_abort
|
90
90
|
end
|
91
|
-
@task.write("$ #{command}\npid: #{command.pid}\
|
91
|
+
@task.write("\n$ #{command}\npid: #{command.pid}\n")
|
92
92
|
@task.pid = command.pid
|
93
93
|
command.stream! do |line|
|
94
94
|
@task.write(line)
|
95
95
|
end
|
96
|
-
|
97
|
-
finished_at
|
98
|
-
@task.write("pid: #{command.pid}\nfinished at: #{finished_at}\nran in: #{finished_at - started_at} seconds\n")
|
96
|
+
finished_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
97
|
+
@task.write("pid: #{command.pid} finished in: #{finished_at - started_at} seconds\n")
|
99
98
|
command.success?
|
100
99
|
end
|
101
100
|
|
data/app/models/shipit/team.rb
CHANGED
@@ -26,7 +26,8 @@ module Shipit
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def find_team_on_github(organization, slug)
|
29
|
-
|
29
|
+
gh_api = Shipit.github(organization: organization).api
|
30
|
+
teams = Shipit::OctokitIterator.new(github_api: gh_api) { gh_api.org_teams(organization, per_page: 100) }
|
30
31
|
teams.find { |t| t.slug == slug }
|
31
32
|
rescue Octokit::NotFound
|
32
33
|
end
|
@@ -41,7 +42,8 @@ module Shipit
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def refresh_members!
|
44
|
-
|
45
|
+
github_api = Shipit.github(organization: organization).api
|
46
|
+
github_members = Shipit::OctokitIterator.new(github_api.get(api_url).rels[:members])
|
45
47
|
members = github_members.map { |u| User.find_or_create_from_github(u) }
|
46
48
|
self.members = members
|
47
49
|
save!
|
data/app/models/shipit/user.rb
CHANGED
@@ -15,6 +15,8 @@ module Shipit
|
|
15
15
|
|
16
16
|
def self.find_or_create_by_login!(login)
|
17
17
|
find_or_create_by!(login: login) do |user|
|
18
|
+
# Users are global, any app can be used
|
19
|
+
# This will not work for users that only exist in an Enterprise install
|
18
20
|
user.github_user = Shipit.github.api.user(login)
|
19
21
|
end
|
20
22
|
end
|
@@ -91,6 +93,8 @@ module Shipit
|
|
91
93
|
end
|
92
94
|
|
93
95
|
def refresh_from_github!
|
96
|
+
# Users are global, any app can be used
|
97
|
+
# This will not work for users that only exist in an Enterprise install
|
94
98
|
update!(github_user: Shipit.github.api.user(github_id))
|
95
99
|
rescue Octokit::NotFound
|
96
100
|
identify_renamed_user!
|
@@ -8,7 +8,7 @@ module Shipit
|
|
8
8
|
has_one :head, serializer: ShortCommitSerializer
|
9
9
|
|
10
10
|
attributes :id, :number, :title, :github_id, :additions, :deletions, :state, :merge_status, :mergeable,
|
11
|
-
|
11
|
+
:merge_requested_at, :rejection_reason, :html_url, :branch, :base_ref
|
12
12
|
|
13
13
|
def html_url
|
14
14
|
github_pull_request_url(object)
|
@@ -3,6 +3,6 @@ class SubsetValidator < ActiveModel::EachValidator
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
4
|
superset = options[:of]
|
5
5
|
rest = value - superset
|
6
|
-
record.errors.add(attribute, :subset, options) unless rest.empty?
|
6
|
+
record.errors.add(attribute, :subset, **options) unless rest.empty?
|
7
7
|
end
|
8
8
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<%= stylesheet_link_tag *(params[:stylesheets] || []).select { |url| url.start_with?('https://assets-cdn.github.com/', 'https://github.githubassets.com/') } %>
|
5
5
|
<%= stylesheet_link_tag 'merge_status' %>
|
6
6
|
</head>
|
7
|
-
<body>
|
7
|
+
<body data-color-mode="<%= params[:mode] %>">
|
8
8
|
<div class="merge-status-container" data-layout-content><%= yield %></div>
|
9
9
|
<%= javascript_include_tag 'merge_status' %>
|
10
10
|
</body>
|
@@ -69,7 +69,8 @@
|
|
69
69
|
<h2 class="banner__title">Continuous Delivery Delayed!</h2>
|
70
70
|
<p class="banner__text">
|
71
71
|
Continuous Delivery for this stack is currently paused because
|
72
|
-
|
72
|
+
|
73
|
+
<%= link_to_if stack.deployment_checks_passed?, 'the pre-deploy checks failed', stack_commit_checks_path(stack, sha: stack.next_commit_to_deploy.sha) %>.
|
73
74
|
You can either wait for them to pass, or trigger a deploy manually.
|
74
75
|
</p>
|
75
76
|
</div>
|
@@ -1,8 +1,10 @@
|
|
1
1
|
host: 'localhost:3000'
|
2
2
|
redis_url: 'redis://127.0.0.1:6379/0'
|
3
3
|
|
4
|
+
# For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
|
4
5
|
# Can be obtained there: https://github.com/settings/apps
|
5
6
|
# Set the "Authorization callback URL" as `<host>/github/auth/github/callback`
|
7
|
+
|
6
8
|
github:
|
7
9
|
app_id:
|
8
10
|
installation_id:
|
@@ -12,3 +14,25 @@ github:
|
|
12
14
|
id:
|
13
15
|
secret:
|
14
16
|
teams: # Optional
|
17
|
+
|
18
|
+
# Use this configuration schema if you are configuring multiple Github applications for different Github organizations
|
19
|
+
|
20
|
+
# github:
|
21
|
+
# somegithuborg:
|
22
|
+
# app_id:
|
23
|
+
# installation_id:
|
24
|
+
# webhook_secret: # nil
|
25
|
+
# private_key:
|
26
|
+
# oauth:
|
27
|
+
# id:
|
28
|
+
# secret:
|
29
|
+
# teams: # Optional
|
30
|
+
# someothergithuborg:
|
31
|
+
# app_id:
|
32
|
+
# installation_id:
|
33
|
+
# webhook_secret: # nil
|
34
|
+
# private_key:
|
35
|
+
# oauth:
|
36
|
+
# id:
|
37
|
+
# secret:
|
38
|
+
# teams: # Optional
|
@@ -1,13 +1,24 @@
|
|
1
1
|
host: 'shipit-engine.myshopify.io'
|
2
2
|
redis_url: 'redis://shipit-engine.railgun:6379'
|
3
3
|
|
4
|
-
#
|
4
|
+
# For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
|
5
|
+
|
5
6
|
github:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
somegithuborg:
|
8
|
+
app_id:
|
9
|
+
installation_id:
|
10
|
+
webhook_secret: # nil
|
11
|
+
private_key:
|
12
|
+
oauth:
|
13
|
+
id:
|
14
|
+
secret:
|
15
|
+
teams:
|
16
|
+
someothergithuborg:
|
17
|
+
app_id:
|
18
|
+
installation_id:
|
19
|
+
webhook_secret: # nil
|
20
|
+
private_key:
|
21
|
+
oauth:
|
22
|
+
id:
|
23
|
+
secret:
|
24
|
+
teams:
|
data/lib/shipit.rb
CHANGED
@@ -24,7 +24,6 @@ require 'safe_yaml/load'
|
|
24
24
|
require 'securecompare'
|
25
25
|
|
26
26
|
require 'redis-objects'
|
27
|
-
require 'redis-namespace'
|
28
27
|
|
29
28
|
require 'octokit'
|
30
29
|
require 'faraday-http-cache'
|
@@ -60,9 +59,12 @@ SafeYAML::OPTIONS[:deserialize_symbols] = false
|
|
60
59
|
module Shipit
|
61
60
|
extend self
|
62
61
|
|
62
|
+
GithubOrganizationUnknown = Class.new(StandardError)
|
63
|
+
TOP_LEVEL_GH_KEYS = [:app_id, :installation_id, :webhook_secret, :private_key, :oauth, :domain]
|
64
|
+
|
63
65
|
delegate :table_name_prefix, to: :secrets
|
64
66
|
|
65
|
-
attr_accessor :disable_api_authentication, :timeout_exit_codes
|
67
|
+
attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks
|
66
68
|
attr_writer(
|
67
69
|
:internal_hook_receivers,
|
68
70
|
:preferred_org_emails,
|
@@ -92,7 +94,7 @@ module Shipit
|
|
92
94
|
secrets.redis_url.present? ? URI(secrets.redis_url) : nil
|
93
95
|
end
|
94
96
|
|
95
|
-
def redis
|
97
|
+
def redis
|
96
98
|
@redis ||= Redis.new(
|
97
99
|
url: redis_url.to_s.presence,
|
98
100
|
logger: Rails.logger,
|
@@ -100,17 +102,41 @@ module Shipit
|
|
100
102
|
reconnect_delay: 0.5,
|
101
103
|
reconnect_delay_max: 1,
|
102
104
|
)
|
103
|
-
return @redis unless namespace
|
104
|
-
Redis::Namespace.new(namespace, redis: @redis)
|
105
105
|
end
|
106
106
|
|
107
|
-
def github
|
108
|
-
|
107
|
+
def github(organization: github_default_organization)
|
108
|
+
# Backward compatibility
|
109
|
+
# nil signifies the single github app config schema is being used
|
110
|
+
if github_default_organization.nil?
|
111
|
+
config = secrets.github
|
112
|
+
else
|
113
|
+
config = github_app_config(organization)
|
114
|
+
raise GithubOrganizationUnknown, organization if config.nil?
|
115
|
+
end
|
116
|
+
@github ||= {}
|
117
|
+
@github[organization] ||= GitHubApp.new(organization, config)
|
118
|
+
end
|
119
|
+
|
120
|
+
def github_default_organization
|
121
|
+
return nil unless secrets&.github
|
122
|
+
org = secrets.github.keys.first
|
123
|
+
TOP_LEVEL_GH_KEYS.include?(org) ? nil : org
|
124
|
+
end
|
125
|
+
|
126
|
+
def github_organizations
|
127
|
+
return [nil] unless github_default_organization
|
128
|
+
secrets.github.keys
|
129
|
+
end
|
130
|
+
|
131
|
+
def github_app_config(organization)
|
132
|
+
github_config = secrets.github.deep_transform_keys(&:downcase)
|
133
|
+
github_organization = organization.downcase.to_sym
|
134
|
+
github_config[github_organization]
|
109
135
|
end
|
110
136
|
|
111
137
|
def legacy_github_api
|
112
138
|
if secrets&.github_api.present?
|
113
|
-
@legacy_github_api ||= github.new_client(access_token: secrets.github_api[
|
139
|
+
@legacy_github_api ||= github.new_client(access_token: secrets.github_api[:access_token])
|
114
140
|
end
|
115
141
|
end
|
116
142
|
|
@@ -175,13 +201,11 @@ module Shipit
|
|
175
201
|
end
|
176
202
|
|
177
203
|
def revision
|
178
|
-
@revision ||=
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end.strip
|
184
|
-
end
|
204
|
+
@revision ||= if revision_file.exist?
|
205
|
+
revision_file.read
|
206
|
+
else
|
207
|
+
%x(git rev-parse HEAD)
|
208
|
+
end.strip
|
185
209
|
end
|
186
210
|
|
187
211
|
def default_inactivity_timeout
|
data/lib/shipit/command.rb
CHANGED
@@ -13,7 +13,8 @@ module Shipit
|
|
13
13
|
Denied = Class.new(Error)
|
14
14
|
TimedOut = Class.new(Error)
|
15
15
|
|
16
|
-
|
16
|
+
unbundled_env = Bundler.respond_to?(:unbundled_env) ? Bundler.unbundled_env : Bundler.clean_env
|
17
|
+
BASE_ENV = unbundled_env.merge((ENV.keys - unbundled_env.keys).map { |k| [k, nil] }.to_h)
|
17
18
|
|
18
19
|
class Failed < Error
|
19
20
|
attr_reader :exit_code
|
@@ -29,7 +30,7 @@ module Shipit
|
|
29
30
|
def initialize(*args, default_timeout: Shipit.default_inactivity_timeout, env: {}, chdir:)
|
30
31
|
@args, options = parse_arguments(args)
|
31
32
|
@timeout = options['timeout'] || options[:timeout] || default_timeout
|
32
|
-
@env = env
|
33
|
+
@env = env.transform_values { |v| v&.to_s }
|
33
34
|
@chdir = chdir.to_s
|
34
35
|
@timed_out = false
|
35
36
|
end
|
@@ -86,7 +87,7 @@ module Shipit
|
|
86
87
|
@out = @pid = nil
|
87
88
|
FileUtils.mkdir_p(@chdir)
|
88
89
|
begin
|
89
|
-
@out, child_in, @pid = PTY.spawn(
|
90
|
+
@out, child_in, @pid = PTY.spawn(unbundled_env, *interpolated_arguments, chdir: @chdir)
|
90
91
|
child_in.close
|
91
92
|
rescue Errno::ENOENT
|
92
93
|
raise NotFound, "#{Shellwords.split(interpolated_arguments.first).first}: command not found"
|
@@ -97,8 +98,8 @@ module Shipit
|
|
97
98
|
self
|
98
99
|
end
|
99
100
|
|
100
|
-
def
|
101
|
-
BASE_ENV.merge('PATH' => "#{
|
101
|
+
def unbundled_env
|
102
|
+
BASE_ENV.merge('PATH' => "#{Shipit.shell_paths.join(':')}:#{ENV['PATH']}").merge(@env.stringify_keys)
|
102
103
|
end
|
103
104
|
|
104
105
|
def stream(&block)
|
@@ -216,7 +217,7 @@ module Shipit
|
|
216
217
|
argument
|
217
218
|
end
|
218
219
|
end
|
219
|
-
[args, options]
|
220
|
+
[args.map(&:to_s), options]
|
220
221
|
end
|
221
222
|
|
222
223
|
def running?
|
data/lib/shipit/commands.rb
CHANGED
@@ -21,8 +21,8 @@ module Shipit
|
|
21
21
|
|
22
22
|
def env
|
23
23
|
@env ||= Shipit.env.merge(
|
24
|
-
'GITHUB_DOMAIN' =>
|
25
|
-
'GITHUB_TOKEN' =>
|
24
|
+
'GITHUB_DOMAIN' => github.domain,
|
25
|
+
'GITHUB_TOKEN' => github.token,
|
26
26
|
'GIT_ASKPASS' => Shipit::Engine.root.join('lib', 'snippets', 'git-askpass').realpath.to_s,
|
27
27
|
)
|
28
28
|
end
|
@@ -30,5 +30,12 @@ module Shipit
|
|
30
30
|
def git(*args)
|
31
31
|
Command.new("git", *args)
|
32
32
|
end
|
33
|
+
ruby2_keywords :git if respond_to?(:ruby2_keywords, true)
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def github
|
38
|
+
Shipit.github
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
data/lib/shipit/engine.rb
CHANGED
@@ -10,6 +10,8 @@ module Shipit
|
|
10
10
|
Shipit::Engine.routes.default_url_options[:host] = Shipit.host
|
11
11
|
Pubsubstub.redis_url = Shipit.redis_url.to_s
|
12
12
|
|
13
|
+
Rails.application.secrets.deep_symbolize_keys!
|
14
|
+
|
13
15
|
app.config.assets.paths << Emoji.images_path
|
14
16
|
app.config.assets.precompile += %w(
|
15
17
|
favicon.ico
|
data/lib/shipit/flock.rb
CHANGED
@@ -11,14 +11,21 @@ module Shipit
|
|
11
11
|
|
12
12
|
def initialize(path)
|
13
13
|
@path = Pathname.new(path)
|
14
|
+
@acquired = false
|
14
15
|
end
|
15
16
|
|
16
17
|
def lock(timeout:)
|
18
|
+
return yield if @acquired
|
17
19
|
path.parent.mkpath
|
18
20
|
path.open('w') do |file|
|
19
21
|
if retrying(timeout: timeout) { file.flock(File::LOCK_EX | File::LOCK_NB) }
|
20
22
|
file.write($PROCESS_ID.to_s)
|
21
|
-
|
23
|
+
@acquired = true
|
24
|
+
begin
|
25
|
+
yield
|
26
|
+
ensure
|
27
|
+
@acquired = false
|
28
|
+
end
|
22
29
|
else
|
23
30
|
raise TimeoutError, "Couldn't acquire lock for #{path} in #{timeout} seconds"
|
24
31
|
end
|