Skip to content

Instantly share code, notes, and snippets.

@jpickwell
Created September 1, 2018 00:28
Show Gist options
  • Save jpickwell/c5f1e538f047864283a54032c4825996 to your computer and use it in GitHub Desktop.
Save jpickwell/c5f1e538f047864283a54032c4825996 to your computer and use it in GitHub Desktop.
Capistrano set_mtimes Task

This Capistrano task will loop through all of the repository files for the specified branch, and set the atime and mtime to the most recent (relative to each file) commit author date.

I wrote this to get around a limitation in Webpacker 3.5.5 when deploying. Because of how Capistrano works, Webpacker would recompile every deploy even if no Webpack code had changed.

# ...
# Use the task during deployment.
after 'deploy:set_current_revision', :set_mtimes
# ...
desc(
'Set the atime and mtime of all repo files based on the most recent' \
' (relative to each file) commit author date.'
)
task :set_mtimes do
on release_roles :all do
within repo_path do
with fetch(:git_environmental_variables) do
# Everything is done in a single `execute` to avoid numerous SSH
# connections (one per file plus one to get the list of files).
#
# Because Capistrano uses `/usr/bin/env`, we need to "break out" of that
# by giving it a command name and redirecting output to the null device.
# `:echo` seems like the simplest and safest choice here.
#
# And because of SSHKit's `Symbol` quirk, the first argument must be a
# `Symbol` to ensure `within` and `with` apply to the loop.
execute(
:echo, '> /dev/null ;', <<~CMD
for path in $(git ls-tree --name-only -r "#{fetch(:branch)}"); do
touch -t $(git log -1 --format=%ad --date=format:%Y%m%d%H%M.%S "#{fetch(:branch)}" -- "${path}") "#{release_path}/${path}"
done
CMD
)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment