1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
##
# This is a debug script to reproduce specific scenarios for scheduled jobs (https://gitlab.com/gitlab-org/gitlab-ce/issues/51352)
# By using this script, you don't need to setup GitLab runner.
# This script is specifically made for FE/UX engineers. They can quickly check how scheduled jobs behave.
#
# *** THIS IS NOT TO BE MERGED ***
#
# ### How to use ###
#
# ### Prerequisite
# 1. Create a project (for example with path `incremental-rollout`)
# 1. Create a .gitlab-ci.yml with the following content
#
=begin
stages:
- build
- test
- production
- rollout 10%
- rollout 50%
- rollout 100%
- cleanup
build:
stage: build
script: sleep 1s
test:
stage: test
script: sleep 3s
rollout 10%:
stage: rollout 10%
script: date
when: delayed
start_in: 10 seconds
allow_failure: false
rollout 50%:
stage: rollout 50%
script: date
when: delayed
start_in: 10 seconds
allow_failure: false
rollout 100%:
stage: rollout 100%
script: date
when: delayed
start_in: 10 seconds
allow_failure: false
cleanup:
stage: cleanup
script: date
=end
#
# ### How to load this script
#
# ```
# bundle exec rails console # Login to rails console
# require '/path/to/scheduled_job_fixture.rb' # Load this script
# ```
#
# ### Reproduce the scenario ~ when all stages succeeded ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Wait until rollout 10% job is triggered
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('rollout 10%')
# 1. Wait until rollout 50% job is triggered
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('rollout 50%')
# 1. Wait until rollout 100% job is triggered
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('rollout 100%')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('cleanup')
#
# Expectation: Users see a succeccful pipeline
#
# ### Reproduce the scenario ~ when rollout 10% jobs failed ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Wait until rollout 10% job is triggered
# 1. ScheduledJobFixture.new(29, 1).drop_jobs('rollout 10%')
#
# Expectation: Following stages should be skipped.
#
# ### Reproduce the scenario ~ when user clicked cancel button before build job finished ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).cancel_pipeline
#
# Expectation: All stages should be canceled.
#
# ### Reproduce the scenario ~ when user canceled the pipeline after rollout 10% job is scheduled ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Run next command before rollout 10% job is triggered
# 1. ScheduledJobFixture.new(29, 1).cancel_pipeline
#
# Expectation: rollout 10% job will be canceled. Following stages will be skipped.
#
# ### Reproduce the scenario ~ when user canceled rollout 10% job after rollout 10% job is scheduled ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Run next command before rollout 10% job is triggered
# 1. ScheduledJobFixture.new(29, 1).cancel_jobs('rollout 10%')
#
# Expectation: rollout 10% job will be canceled. Following stages will be skipped.
#
# ### Reproduce the scenario ~ when user played rollout 10% job immidiately ~
#
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Play rollout 10% job before rollout 10% job is triggered
#
# Expectation: rollout 10% becomes pending immidiately
#
# ### Reproduce the scenario ~ when rollout 10% job is allowed to fail ~
#
# 1. Set `allow_failure: true` to rollout 10% job
# 1. ScheduledJobFixture.new(29, 1).create_pipeline('master')
# 1. ScheduledJobFixture.new(29, 1).finish_stage_until('test')
# 1. Wait until rollout 10% job is triggered
# 1. ScheduledJobFixture.new(29, 1).drop_jobs('rollout 10%')
#
# Expectation: rollout 50% job should be triggered
#
class ScheduledJobFixture
attr_reader :project
attr_reader :user
include GitlabRoutingHelper
def initialize(project_id, user_id)
@project = Project.find_by_id(project_id)
@user = User.find_by_id(user_id)
end
def create_pipeline(ref)
pipeline = Ci::CreatePipelineService.new(project, user, ref: ref).execute(:web)
Rails.application.routes.url_helpers.namespace_project_pipeline_url(project.namespace, project, pipeline)
end
def finish_stage_until(stage_name)
pipeline = Ci::Pipeline.last
pipeline.stages.order(:id).each do |stage|
stage.builds.map(&:success)
stage.update_status
pipeline.update_status
return if stage.name == stage_name
end
end
def run_jobs(stage_name)
pipeline = Ci::Pipeline.last
stage = pipeline.stages.find_by_name(stage_name)
stage.builds.map(&:run)
stage.update_status
pipeline.update_status
end
def drop_jobs(stage_name)
pipeline = Ci::Pipeline.last
stage = pipeline.stages.find_by_name(stage_name)
stage.builds.map(&:drop)
stage.update_status
pipeline.update_status
end
def cancel_jobs(stage_name)
pipeline = Ci::Pipeline.last
stage = pipeline.stages.find_by_name(stage_name)
stage.builds.map(&:cancel)
stage.update_status
pipeline.update_status
end
def cancel_pipeline
Ci::Pipeline.last.cancel_running
end
end
|