File already exists error

Hello,

I am trying to create two different Android builds (APK), by running the Gradle task on two different flavors.
For some reasons it creates 3 APKs, one with a timestamp.
Note that I am trying to trigger two Gradle tasks specific to 2 specific variants, which I couldn’t get via the more generic gradle tasks available (I would get useless builds).

It looks like something goes wrong during the copy of files.

1st task:

............
Move apk files...
  find "." "-name" "*.apk" "!" "-name" "*-unaligned.apk"
  copy ./app/build/outputs/apk/app-back-generic-development-debug.apk to /bitrise/deploy/app-back-generic-development-debug.apk
  The apk path is now available in the Environment Variable: $BITRISE_APK_PATH (value: /bitrise/deploy/app-back-generic-development-debug.apk)
............

2nd task:

............
Move apk files...
  find "." "-name" "*.apk" "!" "-name" "*-unaligned.apk"
  copy ./app/build/outputs/apk/app-knee-generic-development-debug.apk to /bitrise/deploy/app-knee-generic-development-debug.apk
  1 attempt failed:
  file already exists at: /bitrise/deploy/app-back-generic-development-debug.apk
  Retrying...
  copy ./app/build/outputs/apk/app-back-generic-development-debug.apk to /bitrise/deploy/app-back-generic-development-debug20170118145054.apk
  The apk path is now available in the Environment Variable: $BITRISE_APK_PATH (value: /bitrise/deploy/app-back-generic-development-debug20170118145054.apk)
............

Can we prevent this unnecessary APK to be created?

Maybe it’s similar to this issue: Support for multiple apk in android workflows

Cheers!

Hi,

Thanks for creating the report here!

If you’re referring to

That’s the expected behavior. If the file already exists at the target path, the step will append a timestamp to the filename, to prevent accidental overwrite of an existing APK.

Can we prevent this unnecessary APK to be created?

Absolutely!

  • You can either tweak your Gradle configs to not to generate that APK for the task you run (I guess you run the assemble gradle task, which generates both a Debug and a Release APK by default)
  • Or tweak/set the Gradle Runner step’s APK file include filter input. The default value is *.apk, to copy all generated APKs into the deploy directory, but you can change this to e.g. */app-knee-generic-development-debug.apk (based on your log) to only copy the app-knee-generic-development-debug.apk to the deploy directory.

If you’d have any questions, just let us know!

Happy Building! :slight_smile:

Hi,

Thanks for the reply!
I understand the config should probably be refined.

One detail though, if you look at the log there:

copy ./app/build/outputs/apk/app-knee-generic-development-debug.apk to /bitrise/deploy/app-knee-generic-development-debug.apk
  1 attempt failed:
  file already exists at: /bitrise/deploy/app-back-generic-development-debug.apk

We try to copy the file app-knee-generic-development-debug.apk, but it then complains about app-back-generic-development-debug.apk.
I am not sure to understand how those two files would create a conflict.

Cheers!

I might misunderstood what you do:

Note that I am trying to trigger two Gradle tasks specific to 2 specific variants

Don’t you run two gradle tasks during the same build, where both tasks generate app-back-generic-development-debug.apk?

Don’t you run two gradle tasks during the same build, where both tasks generate app-back-generic-development-debug.apk?

No, I run two Gradle Runner blocks, one after the other, one for app-back-generic-development-debug.apk and one for app-knee-generic-development-debug.apk. That’s why it’s a bit weird.

Can I send you the link over Intercom so you can have a closer look maybe?

Ahh, I know what the issue is!

  1. You run the first Gradle Runner step which generates app1.apk, which is copied into the deploy dir, but it’s not deleted from your build directory, where it’s generated by gradle.
  2. Then you run a second Gradle Runner step which generates app2.apk into the same build directory, so app1.apk will still be in the build directory when the second Gradle Runner step looks through the dirs for generates apks, and it will find app1.apk again.

So, you can either delete app1.apk after the first Gradle Runner from the build dir (if you don’t need it there), or specify an APK file include filter to not to copy app1.apk again (e.g. by setting it to the name of app2.apk with a wildcard prefix */app2.apk, as advised at File already exists error - #2 by viktorbenei) when the second Gradle Runner finishes.

Not sure if we should change the behavior of Gradle Runner, e.g. to move the apk into the deploy dir instead of copy…

I believe the current default is better, as you can run it locally on your Mac with our Bitrise CLI and get the expected output (that the apk can be found in the build directory - as well as in the deploy directory).

OK nice, thanks for the reply!
I will have to refine the flow indeed. Now that I have played more with the editor, I don’t think it’s really the natural way to do this anyway.

Cheers!

If you have any questions just let us know! :wink:

Note: you can specify multiple gradle tasks for a single Gradle Runner, space separated (eg: assembleX assembleY), that would solve the issue in your case I think.

1 Like

Oooooh OK!
Thanks!

1 Like

Note: you can specify multiple gradle tasks for a single Gradle Runner, space separated (eg: assembleX assembleY), that would solve the issue in your case I think.

Works like a charm!

Another question:
If I do assembleX assembleY via a Gradle Runner and then call Deploy to Bitrise, is there any way I can get an array of build URLs into $BITRISE_PUBLIC_INSTALL_PAGE_URL, instead of a single APK?

I understand I could also “Compress the artifacts into one file” but I would like to plug in a Slack Message callback where I could say:

  • Build: http://buildurl… (I know how to do this)
  • APK X: http://…
  • APK Y: http://…

Thanks!

Not right now, unfortunately, but it’s definitely planned - see:

Awesome thanks!

1 Like

One note, Gradle Runner v1.5.3 changed how the filter works, and instead of a file name filter it uses a path filter now.

If you used a wildcard prefixed pattern before, like *.apk, this should not affect you at all, but if you previously used a full file name like app1.apk you should change the pattern to */app1.apk, or specify the full path (can be relative, e.g. ./app/build/outputs/apk/app1.apk or */app/build/outputs/apk/app1.apk) or part of the path with a wildcard prefix (e.g. */outputs/apk/app1.apk).

Basically you now specify a pattern for the path, instead of for the file name.

Related discussion:

Related Changelog :

Edited my previous comments above in this discussion to reflect this change.

Thanks for the update! I don’t have any filter in place so it’s fine for me.
Cheers

1 Like