sbt / sbt-native-packager

sbt Native Packager
https://sbt-native-packager.readthedocs.io/en/stable/
BSD 2-Clause "Simplified" License
1.6k stars 441 forks source link

Only set executable permission on staged files if required and not set #1414

Closed DylanArnold closed 3 years ago

DylanArnold commented 3 years ago

When staging files, only set the target executable permission if the source file is executable and the target file is not executable.

It can be problematic if setting the executable permission on a target file multiple times if using inotify to watch staged files as inotify events will be triggered even when the permission is already set. This fix ensures the executable permission is only set once, to avoid unnecessary inotify events.

I am using development tools to watch the stage directory but currently they get triggered if I run the stage task even when there aren't any changes due to setting the executable permission unnecessarily.

To see this in action, assuming you had an example project with stage script at example/target/universal/stage/bin/example you can run the following to see a demonstration of this problem.

In a terminal run: inotifywait -m example/target/universal/stage/bin/example

In another terminal run the following: sbt example/stage

You'll see this output from the first terminal:

example/target/universal/stage/bin/example ATTRIB 
example/target/universal/stage/bin/example OPEN 
example/target/universal/stage/bin/example ACCESS 
example/target/universal/stage/bin/example CLOSE_NOWRITE,CLOSE 

Run sbt example/stage again and you'll see the same output.

If you run chmod u+x example/target/universal/stage/bin/example you will still see the same output which demonstrates that the stage task has the same behaviour as this.

After applying the change in this pull request, running sbt example/stage multiple times will only trigger inotify events the first time the script is created.

lightbend-cla-validator commented 3 years ago

Hi @DylanArnold,

Thank you for your contribution! We really value the time you've taken to put this together.

Before we proceed with reviewing this pull request, please sign the Lightbend Contributors License Agreement:

https://www.lightbend.com/contribute/cla

DylanArnold commented 3 years ago

Yes I did wonder if this could / should be solved before this code gets executed but I didn't really dig into and understand the cache implementation. I would be happy to try and dig into that if you think it makes sense.

I'm watching the staging environment because I'm using a tool called Tilt https://tilt.dev/ to continously deploy a development Kubernetes application.

I use Tilt to build a docker image from the staging output (initially) but also to update my kubernetes pod without building and deploying the docker image again.

Tilt will perform a live update https://docs.tilt.dev/live_update_reference.html if the pod is already deployed by watching the staging environment for changes and copying the assets directly into the pod (without image rebuild / pod restart). I'm new to sbt-native-packager so there may be a different approach?, but I felt I wanted to avoid the overhead of any further zipping / packaging which will slow down my development cycle.

So the key thing given the above is that I want to avoid unnecessary live updates (and process restarts within my deployed pod) when the execute permission is set again.