bugsnag-android-gradle-plugin icon indicating copy to clipboard operation
bugsnag-android-gradle-plugin copied to clipboard

Plugin fails the build when Git executable is not available

Open azabost opened this issue 8 months ago • 1 comments

Describe the bug

Bugsnag Android Gradle Plugin seems to require Git executable to be available and will fail otherwise, which is surprising and contradictory to the documentation which literally says: "values are automatically detected if Git is installed", so it sounds like it shouldn't fail if there is no Git.

When I used a Docker image without the Git executable in my GitHub Actions pipeline, the Bugsnag plugin's task failed:

Execution failed for task ':app:bugsnagRelease-releaseTask'.
> Error while evaluating property 'gitVersion' of task ':app:bugsnagRelease-releaseTask'.
   > A problem occurred starting process 'command 'git''

Many Docker images don't include Git because in CI environment both the repository and the Git info such as commit SHA (i.e. revision) etc. are available via environment variables (example).

Therefore, I decided to provide the necessary information manually in my app/build.gradle.kts file:

android {
    bugsnag {
        if (System.getenv("CI").toBoolean()) {
            sourceControl {
                provider.set("github-enterprise")
                repository.set("https://some.url/to-my/repo")
                revision.set(System.getenv("GITHUB_SHA"))
            }
        }
    }
}

Unfortunately, it didn't seem to help and the plugin's task was still failing. Maybe my if condition was wrong (I didn't check) but judging from this code, I thought the problem may lie in the lack of adequate logic on the plugin's side. It looks like the Git commands are being executed regardless of Git availability or manual sourceControl configuration.

I ended up creating another Docker image with Git installed and that solved the problem for me, but IMO Bugsnag plugin shouldn't require Git to be present.

If you would like to try it yourself, the Docker images I was using are here:

  • without Git: azabost/android-sdk:jdk17-sdk33
  • with Git: azabost/android-sdk:jdk17-sdk33-git

Steps to reproduce

  1. Apply Bugsnag Android Gradle Plugin
  2. Either configure or don't configure bugsnag.sourceControl block - probably doesn't matter
  3. Run the release build variant on a machine without git executable
  4. See error

Environment

  • Android Studio version: Android Studio Giraffe | 2022.3.1 Patch 2
  • Gradle version: 8.1.1
  • Android Gradle Plugin (AGP) version: 8.1.2
  • Bugsnag Android Gradle Plugin version: 8.1.0

Gradle build error with stacktrace

Click here to expand:
> Task :app:bugsnagRelease-releaseTask FAILED
> Task :app:generateBugsnag-releaseMapping

0 problems were found storing the configuration cache.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:bugsnagRelease-releaseTask'.
> Error while evaluating property 'gitVersion' of task ':app:bugsnagRelease-releaseTask'.
   > A problem occurred starting process 'command 'git''


* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
See the complete report at file:///__w/MyApp/MyApp/build/reports/configuration-cache/54wp53pq39e6fbw1bdjjhxy2x/d7gy44vhzne2w65yh4m77yww3/configuration-cache-report.html
795 actionable tasks: 795 executed
Configuration cache entry stored.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:bugsnagRelease-releaseTask'.
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
	at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:146)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:135)
	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:337)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:324)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:317)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49)
Caused by: org.gradle.process.internal.ExecException: A problem occurred starting process 'command 'git''
	at org.gradle.process.internal.DefaultExecHandle.execExceptionFor(DefaultExecHandle.java:241)
	at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(DefaultExecHandle.java:218)
	at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandle.java:370)
	at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:87)
	at org.gradle.internal.operations.CurrentBuildOperationPreservingRunnable.run(CurrentBuildOperationPreservingRunnable.java:42)
	... 2 more
Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'git'
	at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
	at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
	at org.gradle.process.internal.ExecHandleRunner.startProcess(ExecHandleRunner.java:98)
	at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:71)
	... 3 more
Caused by: java.io.IOException: Cannot run program "git" (in directory "/__w/MyApp/MyApp"): error=2, No such file or directory
	at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
	... 6 more
Caused by: java.io.IOException: error=2, No such file or directory
	... 7 more

azabost avatar Nov 06 '23 22:11 azabost

Hi @azabost

I have raised this as an item on our backlog. We will be sure to keep you informed of any updates, however I presently do not have a firm ETA on the release.

clr182 avatar Nov 15 '23 10:11 clr182