Order of after_build callbacks

I am using the middleman-sync and middleman-cloudfront extensions. Obviously I want to sync my files to S3 first and then invalidate the CloudFront cache.
The problem is that when I set after_build to true for both extensions in my config.rb, the invalidation is always executed first after building. I tried changing the position of the activate blocks in config.rb (activating sync before or after cloudfront) but it didn’t help.
Both projects define their after_build callback a bit differently:
https://github.com/karlfreeman/middleman-sync/blob/master/lib/middleman-sync/extension.rb#L55
https://github.com/andrusha/middleman-cloudfront/blob/master/lib/middleman-cloudfront/extension.rb#L19
Does that have anything to do with it?

Just a hunch, but have you tried placing your activate :cloudfront block after your activate :sync block in config.rb?

I tried changing the position of the activate blocks in config.rb (activating sync before or after cloudfront) but it didn’t help.

Yep. :smiley:

Oh, sorry, completely missed that sentence. Can you post your config.rb?

Sure, here it is:

activate :bootstrap_navbar
activate :directory_indexes

activate :sync do |sync|
  sync.fog_provider          = 'AWS'
  sync.fog_directory         = '...'
  sync.fog_region            = 'us-east-1'
  sync.aws_access_key_id     = ENV['AWS_ACCESS_KEY_ID']
  sync.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
  sync.existing_remote_files = 'delete'
  sync.gzip_compression      = true
  sync.after_build           = true
end

activate :cloudfront do |cloudfront|
  cloudfront.access_key_id     = ENV['AWS_ACCESS_KEY_ID']
  cloudfront.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
  cloudfront.distribution_id   = '...'
  cloudfront.filter            = /\.html\z/i
  cloudfront.after_build       = true
end

helpers do
  ...
end

set :css_dir,    'stylesheets'
set :js_dir,     'javascripts'
set :images_dir, 'images'

configure :development do
  set :debug_assets, true
end

configure :build do
  activate :gzip
  activate :asset_hash
  activate :minify_css
  activate :minify_javascript
end

Yep, I believe it does. The cloudfront extension registers its after_build callback right in the registered method, so that callback gets added to after_build immediately when you invoke activate :cloudfront.

But if you look at the sync extension, it registers its after_build callback inside an after_configuration callback, which gets run after everything in your config.rb has been processed. So no matter when you activate sync, its after_build stuff gets added after cloudfront’s.

I’m not sure what the best solution would be — you could submit a PR to middleman-cloudfront to see if it’d make sense for them to defer adding after_build stuff until after_configuration. It might be easier, though, to just write a bash script or a Rake task to automate building, syncing, and then invalidating.

I think middleman-cloudfront's approach is the better one and it’s also the one that’s recommended in the docs: http://middlemanapp.com/advanced/custom/#toc_9
The middleman-smusher plugin was changed to register after_build on activation as well (cannot post a link to Github for whatever reason. Google “Follow activate order for after_build extensions” to find it)
I’ll submit a PR to middleman-sync. Thanks for helping me to get to the bottom of this! (or rather, explaining how it works :smiley:)

Guys, sorry about being unaware about this discussion. I’ll look into merging your pull request @manuelmeurer right now.