Class: Dependabot::Gradle::FileUpdater::WrapperUpdater

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Includes:
Distributions
Defined in:
lib/dependabot/gradle/file_updater/wrapper_updater.rb

Constant Summary

Constants included from Distributions

Distributions::DISTRIBUTION_DEPENDENCY_TYPE, Distributions::DISTRIBUTION_REPOSITORY_URL

Instance Method Summary collapse

Methods included from Distributions

distribution_requirements?

Constructor Details

#initialize(dependency_files:, dependency:) ⇒ WrapperUpdater

Returns a new instance of WrapperUpdater.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/dependabot/gradle/file_updater/wrapper_updater.rb', line 25

def initialize(dependency_files:, dependency:)
  @dependency_files = dependency_files
  @dependency = dependency
  @target_files = T.let(
    %w(
      /gradlew
      /gradlew.bat
      /gradle/wrapper/gradle-wrapper.properties
      /gradle/wrapper/gradle-wrapper.jar
    ),
    T::Array[String]
  )
  @build_files = T.let(
    %w(
      build.gradle
      build.gradle.kts
      settings.gradle
      settings.gradle.kts
    ),
    T::Array[String]
  )
end

Instance Method Details

#update_files(build_file) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dependabot/gradle/file_updater/wrapper_updater.rb', line 51

def update_files(build_file)
  # We only run this updater if it's a distribution dependency
  return [] unless Distributions.distribution_requirements?(dependency.requirements)

  local_files = local_wrapper_files(build_file)

  # If we don't have any files in the build files don't generate one
  return [] unless local_files.any?

  # we only run this updater if the build file has a requirement for this dependency
  target_requirements = dependency.requirements.select do |req|
    T.let(req[:file], String) == build_file.name
  end
  return [] unless target_requirements.any?

  updated_files = dependency_files.dup
  SharedHelpers.in_a_temporary_directory do |temp_dir|
    populate_temp_directory(temp_dir)
    cwd = File.join(temp_dir, base_path(build_file))

    has_local_script = File.exist?(File.join(cwd, "./gradlew"))

    Dir.chdir(cwd) do
      FileUtils.chmod("+x", "./gradlew") if has_local_script

      properties_file = File.join(cwd, "gradle/wrapper/gradle-wrapper.properties")
      original_properties_content = read_file(properties_file)
      original_document = original_properties_content && Wrapper::PropertiesDocument.parse(original_properties_content)
      env = { "JAVA_OPTS" => proxy_args.join(" ") } # set proxy for gradle execution

      command = local_wrapper_command(has_local_script, target_requirements, original_document, cwd, env)

      begin
        # first attempt: run the wrapper task via the local Gradle wrapper (if present)
        # `gradle-wrapper.jar` might not be compatible with the host's Java version or
        # the `gradlew` script may be corrupted, so we try and fall back to system Gradle before giving up
        SharedHelpers.run_shell_command(command, cwd: cwd, env: env)
      rescue SharedHelpers::HelperSubprocessFailed => e
        raise e unless has_local_script # already failed with system one, there is no point to retry

        Dependabot.logger.warn("Running #{command} failed, retrying first with system Gradle: #{e.message}")

        # second attempt: run the wrapper task via system gradle and then retry via local wrapper.
        # The system Gradle may be a different (often older) version than the wrapper, so we rebuild
        # the command against its detected version to avoid passing unsupported, version-gated flags.
        system_command = system_wrapper_command(target_requirements, original_document, cwd, env)
        SharedHelpers.run_shell_command(system_command, cwd: cwd, env: env) # run via system gradle
        SharedHelpers.run_shell_command(command, cwd: cwd, env: env) # retry via local wrapper
      end

      # Gradle's wrapper task regenerates gradle-wrapper.properties from hardcoded defaults
      # (https://github.com/gradle/gradle/issues/36172), discarding comments, ordering, custom
      # keys and user-customized values. Reconcile the regenerated file back onto the user's
      # original so only the version-bump keys change.
      reconcile_properties(properties_file, original_properties_content)

      update_files_content(temp_dir, local_files, updated_files)
    rescue SharedHelpers::HelperSubprocessFailed => e
      Dependabot.logger.error("Failed to update files: #{e.message}")
      return updated_files
    end
  end
  updated_files
end