Skip to content

Commit b93accd

Browse files
authored
Merge pull request #398 from envato/no-changes
2 parents eac2da3 + d8ab343 commit b93accd

3 files changed

Lines changed: 53 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ The format is based on [Keep a Changelog], and this project adheres to
1212

1313
### Changed
1414

15+
- Improve message when CloudFormation claims there are no changes to apply, even when a template diff is present. ([#398])
1516
- Display Tags diff (stack tags) in `stack_master diff` and `stack_master apply` commands. ([#397])
1617
- Resolve style issues identified by RuboCop. ([#396])
1718

1819
[Unreleased]: https://github.com/envato/stack_master/compare/v2.17.1...HEAD
1920
[#396]: https://github.com/envato/stack_master/pull/396
2021
[#397]: https://github.com/envato/stack_master/pull/397
22+
[#398]: https://github.com/envato/stack_master/pull/398
2123

2224
## [2.17.1] - 2025-12-19
2325

lib/stack_master/commands/apply.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

spec/stack_master/commands/apply_spec.rb

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,42 @@ def apply
127127
before do
128128
allow(StackMaster::ChangeSet).to receive(:delete)
129129
allow(change_set).to receive(:failed?).and_return(true)
130-
allow(change_set).to receive(:status_reason).and_return('reason')
131130
end
132131

133-
it 'outputs the status reason' do
134-
expect { apply }.to output(/reason/).to_stdout
132+
context 'with a generic error' do
133+
before do
134+
allow(change_set).to receive(:status_reason).and_return('reason')
135+
end
136+
137+
it 'outputs the status reason' do
138+
expect { apply }.to output(/reason/).to_stdout
139+
end
140+
end
141+
142+
context 'with a "no changes" error from CloudFormation' do
143+
before do
144+
allow(change_set)
145+
.to receive(:status_reason)
146+
.and_return("The submitted information didn't contain changes. " \
147+
'Submit different information to create a change set.')
148+
end
149+
150+
it 'outputs a user-friendly explanation' do
151+
expect { apply }.to output(/The submitted information didn't contain changes/).to_stdout
152+
expect { apply }.to output(/no actual resource changes are needed/).to_stdout
153+
expect { apply }.to output(/stack is already in the desired state/).to_stdout
154+
end
155+
end
156+
157+
context 'with alternative "no changes" error message' do
158+
before do
159+
allow(change_set).to receive(:status_reason).and_return('No updates are to be performed.')
160+
end
161+
162+
it 'outputs a user-friendly explanation' do
163+
expect { apply }.to output(/No updates are to be performed/).to_stdout
164+
expect { apply }.to output(/no actual resource changes are needed/).to_stdout
165+
end
135166
end
136167
end
137168

0 commit comments

Comments
 (0)