Commit 76aff672 authored by charlie ablett's avatar charlie ablett

Merge branch 'automatic-iteration-status-update' into 'master'

Automatically update Iteration status on date

See merge request gitlab-org/gitlab!36880
parents 30b40fc3 344a74b9
......@@ -34,6 +34,9 @@ class Iteration < ApplicationRecord
.where('due_date is NULL or due_date >= ?', start_date)
end
scope :start_date_passed, -> { where('start_date <= ?', Date.current).where('due_date > ?', Date.current) }
scope :due_date_passed, -> { where('due_date <= ?', Date.current) }
state_machine :state_enum, initial: :upcoming do
event :start do
transition upcoming: :started
......
This diff is collapsed.
......@@ -583,6 +583,9 @@ Gitlab.ee do
Settings.cron_jobs['network_policy_metrics_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['network_policy_metrics_worker']['cron'] ||= '0 3 * * 0'
Settings.cron_jobs['network_policy_metrics_worker']['job_class'] = 'NetworkPolicyMetricsWorker'
Settings.cron_jobs['iterations_update_status_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['iterations_update_status_worker']['cron'] ||= '5 0 * * *'
Settings.cron_jobs['iterations_update_status_worker']['job_class'] = 'IterationsUpdateStatusWorker'
end
#
......
......@@ -187,6 +187,14 @@
:weight: 1
:idempotent:
:tags: []
- :name: cronjob:iterations_update_status
:feature_category: :issue_tracking
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: cronjob:ldap_all_groups_sync
:feature_category: :authentication_and_authorization
:has_external_dependencies: true
......
# frozen_string_literal: true
class IterationsUpdateStatusWorker
include ApplicationWorker
idempotent!
queue_namespace :cronjob
feature_category :issue_tracking
def perform
set_started_iterations
set_closed_iterations
end
private
def set_started_iterations
Iteration
.upcoming
.start_date_passed
.update_all(state_enum: ::Iteration::STATE_ENUM_MAP[:started])
end
def set_closed_iterations
Iteration
.upcoming.or(Iteration.started)
.due_date_passed
.update_all(state_enum: ::Iteration::STATE_ENUM_MAP[:closed])
end
end
---
title: Update Iteration status automatically
merge_request: 36880
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IterationsUpdateStatusWorker do
subject(:worker) { described_class.new }
describe '#perform' do
context 'when iterations are in `upcoming` state' do
let_it_be(:closed_iteration1) { create(:iteration, :skip_future_date_validation, start_date: 20.days.ago, due_date: 11.days.ago) }
let_it_be(:closed_iteration2) { create(:iteration, :skip_future_date_validation, start_date: 10.days.ago, due_date: 3.days.ago) }
let_it_be(:started_iteration) { create(:iteration, :skip_future_date_validation, start_date: Date.current, due_date: 10.days.from_now) }
let_it_be(:upcoming_iteration) { create(:iteration, start_date: 11.days.from_now, due_date: 13.days.from_now) }
it 'updates the status of iterations that require it', :aggregate_failures do
expect(closed_iteration1.state).to eq('upcoming')
expect(closed_iteration2.state).to eq('upcoming')
expect(started_iteration.state).to eq('upcoming')
expect(upcoming_iteration.state).to eq('upcoming')
worker.perform
expect(closed_iteration1.reload.state).to eq('closed')
expect(closed_iteration2.reload.state).to eq('closed')
expect(started_iteration.reload.state).to eq('started')
expect(upcoming_iteration.reload.state).to eq('upcoming')
end
end
context 'when iterations are in `started` state' do
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, start_date: 10.days.ago, due_date: 1.day.ago, state_enum: ::Iteration::STATE_ENUM_MAP[:started]) }
it 'updates from started to closed when due date is past' do
expect(iteration.state).to eq('started')
worker.perform
expect(iteration.reload.state).to eq('closed')
end
end
end
end
......@@ -146,6 +146,25 @@ RSpec.describe Iteration do
end
end
context 'time scopes' do
let_it_be(:project) { create(:project, :empty_repo) }
let_it_be(:iteration_1) { create(:iteration, :skip_future_date_validation, project: project, start_date: 3.days.ago, due_date: 1.day.from_now) }
let_it_be(:iteration_2) { create(:iteration, :skip_future_date_validation, project: project, start_date: 10.days.ago, due_date: 4.days.ago) }
let_it_be(:iteration_3) { create(:iteration, project: project, start_date: 4.days.from_now, due_date: 1.week.from_now) }
describe 'start_date_passed' do
it 'returns iterations where start_date is in the past but due_date is in the future' do
expect(described_class.start_date_passed).to contain_exactly(iteration_1)
end
end
describe 'due_date_passed' do
it 'returns iterations where due date is in the past' do
expect(described_class.due_date_passed).to contain_exactly(iteration_2)
end
end
end
describe '.within_timeframe' do
let_it_be(:now) { Time.current }
let_it_be(:project) { create(:project, :empty_repo) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment