class Pantograph::Actions::GradleAction

Public Class Methods

authors() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 192
def self.authors
  ['KrauseFx', 'lmirosevic', 'johnknapprs']
end
available_options() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 96
def self.available_options
  [
    PantographCore::ConfigItem.new(
      key: :task,
      env_name: 'GRADLE_TASK',
      description: 'The gradle task you want to execute, e.g. `assemble`, `bundle` or `test`. For tasks such as `assembleMyFlavorRelease` you should use gradle(task: \'assemble\', flavor: \'Myflavor\', build_type: \'Release\')',
      optional: false,
      type: String
    ),
    PantographCore::ConfigItem.new(
      key: :flavor,
      env_name: 'GRADLE_FLAVOR',
      description: 'The flavor that you want the task for, e.g. `MyFlavor`. If you are running the `assemble` task in a multi-flavor project, and you rely on Actions.lane_context[SharedValues::GRADLE_ARTIFACT  _OUTPUT_PATH] then you must specify a flavor here or else this value will be undefined',
      optional: true,
      type: String
    ),
    PantographCore::ConfigItem.new(
      key: :build_type,
      env_name: 'GRADLE_BUILD_TYPE',
      description: 'The build type that you want the task for, e.g. `Release`. Useful for some tasks such as `assemble`',
      optional: true,
      type: String
    ),
    PantographCore::ConfigItem.new(
      key: :flags,
      env_name: 'GRADLE_FLAGS',
      description: 'All parameter flags you want to pass to the gradle command, e.g. `--exitcode --xml file.xml`',
      optional: true,
      type: String
    ),
    PantographCore::ConfigItem.new(
      key: :project_dir,
      env_name: 'GRADLE_PROJECT_DIR',
      description: 'The root directory of the gradle project',
      default_value: '.',
      type: String
    ),
    PantographCore::ConfigItem.new(
      key: :gradle_path,
      env_name: 'GRADLE_PATH',
      description: 'The path to your `gradlew`. If you specify a relative path, it is assumed to be relative to the `project_dir`',
      optional: true,
      type: String,
      default_value: './gradlew'
    ),
    PantographCore::ConfigItem.new(
      key: :properties,
      env_name: 'GRADLE_PROPERTIES',
      description: 'Gradle properties to be exposed to the gradle script',
      optional: true,
      is_string: false
    ),
    PantographCore::ConfigItem.new(
      key: :artifact_extension,
      env_name: 'GRADLE_ARTIFACT_EXTENSION',
      description: 'Gradle build output filetype extension',
      optional: true,
      is_string: true,
      default_value: 'jar'
    ),
    PantographCore::ConfigItem.new(
      key: :system_properties,
      env_name: 'GRADLE_SYSTEM_PROPERTIES',
      description: 'Gradle system properties to be exposed to the gradle script',
      optional: true,
      is_string: false
    ),
    PantographCore::ConfigItem.new(
      key: :print_command,
      env_name: 'GRADLE_PRINT_COMMAND',
      description: 'Control whether the generated Gradle command is printed as output before running it (true/false)',
      is_string: false,
      default_value: true
    ),
    PantographCore::ConfigItem.new(
      key: :print_command_output,
      env_name: 'GRADLE_PRINT_COMMAND_OUTPUT',
      description: 'Control whether the output produced by given Gradle command is printed while running (true/false)',
      is_string: false,
      default_value: true
    )
  ]
end
category() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 279
def self.category
  :building
end
description() click to toggle source

@!group Documentation

# File pantograph/lib/pantograph/actions/gradle.rb, line 88
def self.description
  'All gradle related actions, including building and testing your application'
end
details() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 92
def self.details
  'Run `./gradlew tasks` to get a list of all available gradle tasks for your project'
end
example_code() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 200
def self.example_code
  [
    'gradle(
      task: "assemble",
      flavor: "WorldDomination",
      build_type: "Release"
    )
    ```

    To build an AAB use:
    ```ruby
    gradle(
      task: "bundle",
      flavor: "WorldDomination",
      build_type: "Release"
    )
    ```

    You can pass properties to gradle:
    ```ruby
    gradle(
      # ...

      properties: {
        "versionCode" => 100,
        "versionName" => "1.0.0",
        # ...
      }
    )
    ```

    You can use this to automatically [sign and zipalign] your app:
    ```ruby
    gradle(
      task: "assemble",
      build_type: "Release",
      print_command: false,
      properties: {
        "app.injected.signing.store.file" => "keystore.jks",
        "app.injected.signing.store.password" => "store_password",
        "app.injected.signing.key.alias" => "key_alias",
        "app.injected.signing.key.password" => "key_password",
      }
    )
    ```

    If you need to pass sensitive information through the `gradle` action, and don\'t want the generated command to be printed before it is run, you can suppress that:
    ```ruby
    gradle(
      # ...
      print_command: false
    )
    ```

    You can also suppress printing the output generated by running the generated Gradle command:
    ```ruby
    gradle(
      # ...
      print_command_output: false
    )
    ```

    To pass any other CLI flags to gradle use:
    ```ruby
    gradle(
      # ...

      flags: "--exitcode --xml file.xml"
    )
    ```

    Delete the build directory, generated artifacts
    ```ruby
    gradle(
      task: "clean"
    )'
  ]
end
is_supported?(platform) click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 196
def self.is_supported?(platform)
  true
end
output() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 180
def self.output
  [
    ['GRADLE_ARTIFACT_OUTPUT_PATH', 'The path to the newly generated artifact file. Undefined in a multi-variant assemble scenario'],
    ['GRADLE_FLAVOR', 'The flavor, e.g. `MyFlavor`'],
    ['GRADLE_BUILD_TYPE', 'The build type, e.g. `Release`']
  ]
end
return_value() click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 188
def self.return_value
  'The output of running the gradle task'
end
run(params) click to toggle source
# File pantograph/lib/pantograph/actions/gradle.rb, line 13
def self.run(params)
  task        = params[:task]
  flavor      = params[:flavor]
  build_type  = params[:build_type]
  gradle_task = [task, flavor, build_type].join

  project_dir       = params[:project_dir]
  gradle_path_param = params[:gradle_path]

  # Get the path to gradle, if it's an absolute path we take it as is, if it's relative we assume it's relative to the project_dir
  gradle_path = if Pathname.new(gradle_path_param).absolute?
                  File.expand_path(gradle_path_param)
                else
                  File.expand_path(File.join(project_dir, gradle_path_param))
                end

  # Ensure we ended up with a valid path to gradle
  unless File.exist?(gradle_path)
    UI.user_error!("Couldn't find gradlew at path '#{File.expand_path(gradle_path)}'")
  end

  # Construct our flags
  flags = []
  flags << "-p #{project_dir.shellescape}"

  unless params[:properties].nil?
    flags << params[:properties].map { |k, v| "-P#{k.to_s.shellescape}=#{v.to_s.shellescape}" }.join(' ')
  end

  unless params[:system_properties].nil?
    flags << params[:system_properties].map { |k, v| "-D#{k.to_s.shellescape}=#{v.to_s.shellescape}" }.join(' ')
  end

  flags << params[:flags] unless params[:flags].nil?

  # Run the actual gradle task
  gradle = Helper::GradleHelper.new(gradle_path: gradle_path)

  # If these were set as properties, then we expose them back out as they might be useful to others
  Actions.lane_context[SharedValues::GRADLE_BUILD_TYPE] = build_type if build_type
  Actions.lane_context[SharedValues::GRADLE_FLAVOR] = flavor if flavor

  # We run the actual gradle task
  result = gradle.trigger(
    task: gradle_task,
    flags: flags.join(' '),
    print_command: params[:print_command],
    print_command_output: params[:print_command_output]
  )

  # If we didn't build, then we return now, as it makes no sense to search for artifacts's in a non-`assemble` or non-`build` scenario
  return result unless task =~ /\b(assemble)/ || task =~ /\b(build)/

  artifact_search_path = File.join(project_dir, '**', 'build', '**', "*.#{params[:artifact_extension].gsub('.', '')}")

  # Our artifact is now built, but there might actually be multiple ones that were built if a flavor was not specified in a multi-flavor project (e.g. `assembleRelease`)
  new_artifacts = Dir[artifact_search_path].map { |path| File.expand_path(path) }

  # We also take the most recent artifact to return as SharedValues::GRADLE_ARTIFACT_OUTPUT_PATH
  # This is the one that will be relevant for most projects that just build a single build variant (flavor + build type combo).
  # In multi build variants this value is undefined
  last_artifact_path = new_artifacts.sort_by(&File.method(:mtime)).last
  Actions.lane_context[SharedValues::GRADLE_ARTIFACT_OUTPUT_PATH] = File.expand_path(last_artifact_path) if last_artifact_path

  # Give a helpful message in case there were no new artifacts.
  # Remember we're only running this code when assembling, in which case we certainly expect there to be an artifact
  UI.message('Couldn\'t find any new artifact files...') if new_artifacts.empty?

  return result
end