Class: Stax::Cmd::Codepipeline

Inherits:
SubCommand show all
Defined in:
lib/stax/mixin/codepipeline.rb

Constant Summary collapse

COLORS =
{
  Succeeded: :green,
  Failed:    :red,
  Stopped:   :red,
  Abandoned: :red,
  enabled:   :green,
  disabled:  :red,
}

Instance Method Summary collapse

Methods inherited from SubCommand

#info, stax_info, stax_info_tasks

Instance Method Details

#approvalsObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/stax/mixin/codepipeline.rb', line 97

def approvals
  my.stack_pipeline_names.each do |name|
    debug("Pending approvals for #{name}")
    Aws::Codepipeline.state(name).stage_states.each do |s|
      s.action_states.each do |a|
        next unless (a.latest_execution&.token && a.latest_execution&.status == 'InProgress')
        l = a.latest_execution
        ago = (t = l&.last_status_change) ? human_time_diff(Time.now - t, 1) : '?'
        puts "#{a.action_name} #{l&.token} #{ago} ago"
        resp = (options[:approved] && :approved) || (options[:rejected] && :rejected) || ask('approved,rejected,[skip]?', :yellow)
        status = resp.to_s.capitalize
        if (status == 'Rejected') || (status == 'Approved')
          Aws::Codepipeline.client.put_approval_result(
            pipeline_name: name,
            stage_name: s.stage_name,
            action_name: a.action_name,
            token: l.token,
            result: {status: status, summary: "#{status} by #{ENV['USER']}"},
          ).tap { |r| puts "#{status} at #{r&.approved_at}" }
        end
      end
    end
  end
end

#historyObject



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/stax/mixin/codepipeline.rb', line 57

def history
  my.stack_pipeline_names.each do |name|
    debug("Execution history for #{name}")
    print_table Aws::Codepipeline.executions(name, options[:number]).map { |e|
      r = Aws::Codepipeline.execution(name, e.pipeline_execution_id)&.artifact_revisions&.first
      age = human_time_diff(Time.now - e.last_update_time, 1)
      duration = human_time_diff(e.last_update_time - e.start_time)
      [e.pipeline_execution_id, color(e.status, COLORS), "#{age} ago", duration, r&.revision_id&.slice(0,7) + ':' + r&.revision_summary]
    }
  end
end


211
212
213
214
215
# File 'lib/stax/mixin/codepipeline.rb', line 211

def link
  my.stack_pipeline_names.each do |name|
    puts pipeline_link(name)
  end
end

#openObject



218
219
220
221
222
# File 'lib/stax/mixin/codepipeline.rb', line 218

def open
  my.stack_pipeline_names.each do |name|
    os_open(pipeline_link(name))
  end
end

#stagesObject



45
46
47
48
49
50
51
52
53
# File 'lib/stax/mixin/codepipeline.rb', line 45

def stages
  my.stack_pipeline_names.each do |name|
    debug("Stages for #{name}")
    print_table Aws::Codepipeline.stages(name).map { |s|
      actions = s.actions.map{ |a| a&.action_type_id&.provider }.join(' ')
      [s.name, actions]
    }
  end
end

#start(name = nil) ⇒ Object



123
124
125
126
127
128
# File 'lib/stax/mixin/codepipeline.rb', line 123

def start(name = nil)
  name ||= my.stack_pipeline_names.first
  debug("Starting execution for #{name}")
  puts Aws::Codepipeline.start(name)
  tail name
end

#stateObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/stax/mixin/codepipeline.rb', line 78

def state
  my.stack_pipeline_names.each do |name|
    state = Aws::Codepipeline.state(name)
    debug("State for #{name} at #{state.updated}")
    print_table state.stage_states.map { |s|
      s.action_states.map { |a|
        l = a.latest_execution
        percent = (l&.percent_complete || 100).to_s + '%'
        sha = a.current_revision&.revision_id&.slice(0,7)
        ago = (t = l&.last_status_change) ? human_time_diff(Time.now - t, 1) : '?'
        [s.stage_name, a.action_name, color(l&.status || '', COLORS), percent, "#{ago} ago", (sha || l&.token), l&.error_details&.message]
      }
    }.flatten(1)
  end
end

#statusObject

print status as one of InProgress, Stopped, Stopping, Succeeded, Superseded, Failed



70
# File 'lib/stax/mixin/codepipeline.rb', line 70

desc 'status', 'pipeline execution status'

#stop(name = nil) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/stax/mixin/codepipeline.rb', line 133

def stop(name = nil)
  name ||= my.stack_pipeline_names.first
  id = Aws::Codepipeline.state(name).stage_states.first.latest_execution.pipeline_execution_id
  debug("Stopping #{name} #{id}")
  puts Aws::Codepipeline.client.stop_pipeline_execution(
    pipeline_name: name,
    pipeline_execution_id: id,
    abandon: options[:abandon],
    reason: options[:reason],
  ).pipeline_execution_id
rescue ::Aws::CodePipeline::Errors::ServiceError => e
  fail_task(e.message)
end

#tail(name = nil) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/stax/mixin/codepipeline.rb', line 148

def tail(name = nil)
  trap('SIGINT', 'EXIT')    # clean exit with ctrl-c
  name ||= my.stack_pipeline_names.first
  last_seen = nil
  loop do
    state = Aws::Codepipeline.state(name)
    now = Time.now
    stages = state.stage_states.map do |s|
      last_change = s.action_states.map { |a| a&.latest_execution&.last_status_change }.compact.max
      revisions = s.action_states.map { |a| a.current_revision&.revision_id&.slice(0,7) }.join(' ')
      ago = last_change ? human_time_diff(now - last_change, 1) : '?'
      [s.stage_name, color(s&.latest_execution&.status || '', COLORS), "#{ago} ago", revisions].join(' ')
    end
    puts [set_color(now, :blue), stages].flatten.join('  ')
    sleep 5
  end
end

#transitionsObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/stax/mixin/codepipeline.rb', line 169

def transitions
  my.stack_pipeline_names.each do |name|
    if options[:enable]
      debug("Enable stage transition for #{name} #{options[:enable]}")
      Aws::Codepipeline.client.enable_stage_transition(
        pipeline_name: name,
        stage_name: options[:enable],
        transition_type: :Inbound,
      )
    elsif options[:disable]
      debug("Disable stage transition for #{name} #{options[:disable]}")
      Aws::Codepipeline.client.disable_stage_transition(
        pipeline_name: name,
        stage_name: options[:disable],
        transition_type: :Inbound,
        reason: ask('reason for disable?')
      )
    else
      debug("Stage transitions for #{name}")
      state = Aws::Codepipeline.state(name)
      print_table state.stage_states.map { |s|
        t = s.inbound_transition_state
        [ s.stage_name, color(t.enabled ? :enabled : :disabled, COLORS), t.disabled_reason, t.last_changed_at ]
      }
    end
  end
end

#webhooksObject



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/stax/mixin/codepipeline.rb', line 198

def webhooks
  webhooks = Aws::Codepipeline.client.list_webhooks.map(&:webhooks).flatten
  my.stack_pipeline_names.each do |pipeline|
    debug("Webhooks for pipeline #{pipeline}")
    print_table webhooks.select { |w|
      w.definition.target_pipeline == pipeline
    }.map { |w|
      [ w.definition.name, w.definition.target_pipeline, w.error_message, w.last_triggered ]
    }
  end
end