elasticdog / transcrypt

transparently encrypt files within a git repository
MIT License
1.46k stars 102 forks source link

Detection of clean repo is not reliable. #37

Closed mrmachine closed 3 years ago

mrmachine commented 7 years ago

I'm using codefresh to build Docker images (including the .git directory), with an entrypoint script that configures the git repo for transcrypt with a password from the environment, to decrypt secret files at runtime.

transcrypt thinks the git repo is dirty:

# transcrypt -c "${TRANSCRYPT_CIPHER:-aes-256-cbc}" -p "$TRANSCRYPT_PASSWORD" -y
transcrypt: the repo is dirty; commit or stash your changes before running transcrypt

When I run the git diff-index command that transcrypt uses internally (minus the --quiet arg), it seems to return some odd results:

# git diff-index HEAD -- | tail                                                                                                   
:100644 100644 3d6e0e93c2bfef67162836b2f0b5ad24c526929e 0000000000000000000000000000000000000000 M      staticroot/apple-touch-icon-precomposed.png        
:100644 100644 9089ef7ffea1efe2de79b49b5e6a5856360de4d6 0000000000000000000000000000000000000000 M      staticroot/apple-touch-icon.png                    
:100644 100644 7b74f8caf013ba164ca9049f7bd4eea0555ff720 0000000000000000000000000000000000000000 M      staticroot/favicon.ico                             
:100644 100644 5d00a90141a920a278e2a8239e560b7ea395a1db 0000000000000000000000000000000000000000 M      staticroot/humans.txt                              
:100644 100644 214e4119653f9c6a4c48cd0ebb06a6754f00f62b 0000000000000000000000000000000000000000 M      staticroot/robots.txt                              

But the repo is clean, cloned and built by codefresh:

# git status                                                                                                                      
HEAD detached at 153c57c                                                                                                                                   
nothing to commit, working directory clean                                                                                                                 

Strangely, after running git status, transcrypt suddenly agrees that the repo is clean and agrees to configure the repo:

# git diff-index HEAD -- | tail                                                                                                   

# transcrypt -c "${TRANSCRYPT_CIPHER:-aes-256-cbc}" -p "$TRANSCRYPT_PASSWORD" -y
The repository has been successfully configured by transcrypt.                                                                                             

Is there something wrong with the way codefresh is cloning the repo before it builds the Docker image?

Is there a more reliable way transcrypt can detect a dirty repo (as reported by git status)?

elasticdog commented 7 years ago

I wonder if there is some stale stat info from whatever codefresh is doing. Instead of running git status, if you touch all of the encrypted files, does the clean check work as expected?

cd $(git rev-parse --show-toplevel)
touch $(git ls-crypt)
dfee commented 7 years ago

I've experienced the same thing using CircleCI. I solved it by doing a git reset --hard HEAD even though when I'd ssh'ed in, git status returned nothing to commit, working directory clean

andreineculau commented 3 years ago

Hate to do a +1, but I'm now experiencing this when running WSL on Windows on Github Actions.

LATER EDIT It is just mesmerizing how running git status before decrypting can workaround the situation 🤔

Explanations:

LATER LATER EDIT As per SO, I used git update-index -q --really-refresh instead of git status, etc.

jmurty commented 3 years ago

Hmm, is there any reason we shouldn't apply the naïve but simple "fix" and always run git update-index -q --really-refresh or git status before checking for a clean repository?

It would be weird voodoo, but should at least solve the problem.

andreineculau commented 3 years ago

It's not really voodoo :) after you read the tiny details, that is.... sigh it's just that diff-index gives you a probabilistic view of the world, not a binary one that's all. So if we want to stick to diff-index, then we need update-index. Otherwise we can use a higher-level git command like git status that gives you a binary answer.

andreineculau commented 3 years ago

for example, have a look at how the git bash prompt detects dirty state https://github.com/git/git/blob/e31aba42fb12bdeb0f850829e008e1e3f43af500/contrib/completion/git-prompt.sh#L527-L528

jmurty commented 3 years ago

Hi @andreineculau it's been a while sorry, but I have created a pull request with a potential fix to more reliably detect dirty repositories, without false positives. It would be great if you could look over it or test it: https://github.com/elasticdog/transcrypt/pull/109

andreineculau commented 3 years ago

Well, I have already implemented this in https://github.com/rokmoln/support-firecloud/commit/4834b270fb0b2d9a3eb61d99d42ac6c65e9ae5e2 (basically just for my usecase of WSL in CI) and it does work. I'd be surprised if your fix gives degraded outcome.

I'm currently not able to test this, but it's a +1 from me.

jmurty commented 3 years ago

Hi @mrmachine @dfee and anyone else watching this issue, could someone test and confirm the potential fix for detection of dirty repos in pull request #109?

jmurty commented 3 years ago

With the merge of https://github.com/elasticdog/transcrypt/pull/109 this issue should now be fixed. Please re-open if dirty repo detection is still failing for you when using the latest transcrypt from the master branch.