diff --git a/app/jobs/deployments/app_store_connect/find_live_release_job.rb b/app/jobs/deployments/app_store_connect/find_live_release_job.rb index 2059f2346..b91976bf6 100644 --- a/app/jobs/deployments/app_store_connect/find_live_release_job.rb +++ b/app/jobs/deployments/app_store_connect/find_live_release_job.rb @@ -4,11 +4,11 @@ class Deployments::AppStoreConnect::FindLiveReleaseJob extend Backoffable queue_as :high - sidekiq_options retry: 1000 + sidekiq_options retry: 6000 sidekiq_retry_in do |_count, ex| if ex.is_a?(Deployments::AppStoreConnect::Release::ReleaseNotFullyLive) - 30.minutes.to_i + 5.minutes.to_i else elog(ex) :kill diff --git a/app/libs/deployments/app_store_connect/release.rb b/app/libs/deployments/app_store_connect/release.rb index 6f7d941d1..91f2a973f 100644 --- a/app/libs/deployments/app_store_connect/release.rb +++ b/app/libs/deployments/app_store_connect/release.rb @@ -194,7 +194,10 @@ def track_live_release_status if release_info.live?(build_number) return run.complete! unless staged_rollout? - run.staged_rollout.update_stage(release_info.phased_release_stage) + run.staged_rollout.update_stage( + release_info.phased_release_stage, + finish_rollout: release_info.phased_release_complete? + ) return if release_info.phased_release_complete? end @@ -223,7 +226,10 @@ def pause_phased_release! if result.ok? release_info = result.value! create_or_update_external_release(release_info) - run.staged_rollout.update_stage(release_info.phased_release_stage) + run.staged_rollout.update_stage( + release_info.phased_release_stage, + finish_rollout: release_info.phased_release_complete? + ) end result @@ -237,7 +243,10 @@ def resume_phased_release! if result.ok? release_info = result.value! create_or_update_external_release(release_info) - run.staged_rollout.update_stage(release_info.phased_release_stage) + run.staged_rollout.update_stage( + release_info.phased_release_stage, + finish_rollout: release_info.phased_release_complete? + ) end result diff --git a/app/models/deployment_run.rb b/app/models/deployment_run.rb index 60224996d..29125cefc 100644 --- a/app/models/deployment_run.rb +++ b/app/models/deployment_run.rb @@ -189,12 +189,12 @@ def staged_rollout_events end end - def rollout_percentage_at(ts) + def rollout_percentage_at(day) return 100.0 unless staged_rollout last_event = staged_rollout .passports .where(reason: [:started, :increased, :fully_released]) - .where("event_timestamp < ?", ts) + .where("DATE_TRUNC('day', event_timestamp) <= ?", day) .order(:event_timestamp) .last return 0.0 unless last_event diff --git a/app/models/staged_rollout.rb b/app/models/staged_rollout.rb index 8ad4e34cf..48012d572 100644 --- a/app/models/staged_rollout.rb +++ b/app/models/staged_rollout.rb @@ -87,8 +87,8 @@ def display_current_stage (current_stage || 0).succ end - def update_stage(stage) - return if stage == current_stage + def update_stage(stage, finish_rollout: false) + return if stage == current_stage && !finish_rollout update!(current_stage: stage) @@ -99,7 +99,7 @@ def update_stage(stage) end retry! if failed? - complete! if finished? + complete! if finish_rollout && finished? notify!("Staged rollout was updated!", :staged_rollout_updated, notification_params) end @@ -128,7 +128,7 @@ def move_to_next_stage! deployment_run.on_release(rollout_value: next_rollout_percentage) do |result| if result.ok? - update_stage(next_stage) + update_stage(next_stage, finish_rollout: true) else fail! elog(result.error) diff --git a/spec/jobs/deployments/app_store_connect/find_live_release_job_spec.rb b/spec/jobs/deployments/app_store_connect/find_live_release_job_spec.rb index aaab0d2d2..c99e38830 100644 --- a/spec/jobs/deployments/app_store_connect/find_live_release_job_spec.rb +++ b/spec/jobs/deployments/app_store_connect/find_live_release_job_spec.rb @@ -35,7 +35,7 @@ it "retries if release is not live yet" do expect( described_class.sidekiq_retry_in_block.call(1, Deployments::AppStoreConnect::Release::ReleaseNotFullyLive.new) - ).to be >= 600.seconds + ).to be >= 300.seconds end it "does not retry if there are unexpected errors" do diff --git a/spec/libs/deployments/app_store_connect/release_spec.rb b/spec/libs/deployments/app_store_connect/release_spec.rb index a03ace8b5..913aeb1f4 100644 --- a/spec/libs/deployments/app_store_connect/release_spec.rb +++ b/spec/libs/deployments/app_store_connect/release_spec.rb @@ -696,6 +696,12 @@ phased_release_status: "ACTIVE")) } + let(:last_phase_phased_release_info) { + AppStoreIntegration::AppStoreReleaseInfo.new(base_release_info.merge(status: "READY_FOR_SALE", + phased_release_day: 7, + phased_release_status: "ACTIVE")) + } + let(:fully_live_phased_release_info) { AppStoreIntegration::AppStoreReleaseInfo.new(base_release_info.merge(status: "READY_FOR_SALE", phased_release_day: 8, @@ -717,6 +723,16 @@ end it "updates staged rollout and raises release not fully live yet" do + allow(providable_dbl).to receive(:find_live_release).and_return(GitHub::Result.new { last_phase_phased_release_info }) + + expect { described_class.track_live_release_status(run_with_staged_rollout) } + .to raise_error(Deployments::AppStoreConnect::Release::ReleaseNotFullyLive) + + expect(run_with_staged_rollout.staged_rollout.reload.started?).to be(true) + expect(run_with_staged_rollout.staged_rollout.reload.last_rollout_percentage).to eq(100.0) + end + + it "updates staged rollout to 100% and raises release not fully live yet" do allow(providable_dbl).to receive(:find_live_release).and_return(GitHub::Result.new { live_phased_release_info }) expect { described_class.track_live_release_status(run_with_staged_rollout) } @@ -726,12 +742,34 @@ expect(run_with_staged_rollout.staged_rollout.reload.last_rollout_percentage).to eq(1.0) end + it "does not update staged rollout if stage hasn't changed" do + allow(providable_dbl).to receive(:find_live_release).and_return(GitHub::Result.new { live_phased_release_info }) + run_with_staged_rollout.staged_rollout.update!(current_stage: 0, status: "started") + old_updated_at = run_with_staged_rollout.staged_rollout.updated_at + + expect { described_class.track_live_release_status(run_with_staged_rollout) } + .to raise_error(Deployments::AppStoreConnect::Release::ReleaseNotFullyLive) + + expect(run_with_staged_rollout.staged_rollout.reload.updated_at).to eq(old_updated_at) + expect(run_with_staged_rollout.staged_rollout.reload.last_rollout_percentage).to eq(1.0) + end + + it "marks finished but does not update staged rollout if stage hasn't changed but phased rollout is complete" do + allow(providable_dbl).to receive(:find_live_release).and_return(GitHub::Result.new { fully_live_phased_release_info }) + run_with_staged_rollout.staged_rollout.update!(current_stage: 6, status: "started") + + described_class.track_live_release_status(run_with_staged_rollout) + + expect(run_with_staged_rollout.staged_rollout.reload.completed?).to be(true) + expect(run_with_staged_rollout.staged_rollout.reload.last_rollout_percentage).to eq(100.0) + end + it "completes the run if staged rollout has finished" do allow(providable_dbl).to receive(:find_live_release).and_return(GitHub::Result.new { fully_live_phased_release_info }) described_class.track_live_release_status(run_with_staged_rollout) - expect(run_with_staged_rollout.staged_rollout.reload.finished?).to be(true) + expect(run_with_staged_rollout.staged_rollout.reload.completed?).to be(true) expect(run_with_staged_rollout.staged_rollout.reload.last_rollout_percentage).to eq(100.0) expect(run_with_staged_rollout.reload.released?).to be(true) end diff --git a/spec/models/staged_rollout_spec.rb b/spec/models/staged_rollout_spec.rb index 5ce8f4564..c366f80ac 100644 --- a/spec/models/staged_rollout_spec.rb +++ b/spec/models/staged_rollout_spec.rb @@ -484,7 +484,7 @@ added_at: 1.day.ago, status: "READY_FOR_SALE", phased_release_day: 8, - phased_release_status: "COMPLETED" + phased_release_status: "COMPLETE" } ) allow(providable_dbl).to receive(:resume_phased_release).and_return(GitHub::Result.new { completed_release_info })