@@ -89,7 +89,7 @@ def create_stack_by_change_set
8989 @change_set = ChangeSet . create ( stack_options . merge ( change_set_type : 'CREATE' ) )
9090 if @change_set . failed?
9191 ChangeSet . delete ( @change_set . id )
92- halt! ( @change_set . status_reason )
92+ halt! ( user_friendly_changeset_error ( @change_set . status_reason ) )
9393 end
9494
9595 @change_set . display ( StackMaster . stdout )
@@ -123,7 +123,7 @@ def update_stack
123123 @change_set = ChangeSet . create ( stack_options )
124124 if @change_set . failed?
125125 ChangeSet . delete ( @change_set . id )
126- halt! ( @change_set . status_reason )
126+ halt! ( user_friendly_changeset_error ( @change_set . status_reason ) )
127127 end
128128
129129 @change_set . display ( StackMaster . stdout )
@@ -230,6 +230,21 @@ def set_stack_policy
230230 StackMaster . stdout . puts 'done.'
231231 end
232232
233+ def user_friendly_changeset_error ( status_reason )
234+ # CloudFormation returns various messages when there are no changes to apply
235+ if status_reason =~ /didn'?t contain changes|no changes|no updates are to be performed/i
236+ <<~MESSAGE . chomp
237+ #{ status_reason }
238+
239+ While there may be differences in the template file (e.g., whitespace, comments, or
240+ formatting), CloudFormation has determined that no actual resource changes are needed.
241+ The stack is already in the desired state.
242+ MESSAGE
243+ else
244+ status_reason
245+ end
246+ end
247+
233248 extend Forwardable
234249 def_delegators :@stack_definition , :stack_name , :region
235250 end
0 commit comments