Skip to content

Commit

Permalink
feat(iOS): add colors to codegen output (#46557)
Browse files Browse the repository at this point in the history
Summary:
This PR is a quality-of-life improvement, adds colors to codegen output:

![CleanShot 2024-09-18 at 12 18 00@2x](https://github.com/user-attachments/assets/13290a1c-8411-40e4-8abe-8fce4b88b6e7)

Makes it a lot easier to grasp what's going on in the actions taken by codegen.

## Changelog:

[GENERAL] [ADDED] - Add color formatting to codegen output

Pull Request resolved: #46557

Test Plan:
1. Run codegen
2. Expect colored output

Reviewed By: christophpurrer

Differential Revision: D63031248

Pulled By: cipolleschi

fbshipit-source-id: e86bc72f16582562dc9f1e3b55dc69af4c7838f5
  • Loading branch information
okwasniewski authored and facebook-github-bot committed Sep 20, 2024
1 parent 9e2e8c1 commit 1747f57
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ def testGenerateReactCodegenPodspec_whenItHasBeenAlreadyGenerated_doesNothing
CodegenUtils.set_react_codegen_podspec_generated(true)

# Act
CodegenUtils.new().generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: FileMock)
CodegenUtils.new().generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: FileMock, logger: Pod::UI)

# Assert
assert_equal(Pod::UI.collected_messages, ["[Codegen] Skipping ReactCodegen podspec generation."])
assert_equal(Pod::UI.collected_messages, ["Skipping ReactCodegen podspec generation."])
assert_equal(Pathname.pwd_invocation_count, 0)
assert_equal(Pod::Executable.executed_commands, [])
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 0)
Expand All @@ -77,13 +77,13 @@ def testGenerateReactCodegenPodspec_whenItHasNotBeenAlreadyGenerated_generatesIt
codegen_output_dir = "build"

# Act
CodegenUtils.new().generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: FileMock)
CodegenUtils.new().generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: FileMock, logger: Pod::UI)

# Assert
assert_equal(Pathname.pwd_invocation_count, 1)
assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1)
assert_equal(Pod::Executable.executed_commands, [{ "command" => 'mkdir', "arguments" => ["-p", "~/app/ios/build"]}])
assert_equal(Pod::UI.collected_messages, ["[Codegen] Generating ~/app/ios/build/ReactCodegen.podspec.json"])
assert_equal(Pod::UI.collected_messages, ["Generating ~/app/ios/build/ReactCodegen.podspec.json"])
assert_equal(FileMock.open_files_with_mode["~/app/ios/build/ReactCodegen.podspec.json"], 'w')
assert_equal(FileMock.open_files[0].collected_write, ['{"name":"Test Podspec"}'])
assert_equal(FileMock.open_files[0].fsync_invocation_count, 1)
Expand All @@ -103,12 +103,13 @@ def testGetReactCodegenSpec_whenFabricEnabledAndScriptPhases_generatesAPodspec
'package.json',
:hermes_enabled => true,
:script_phases => "echo Test Script Phase",
:file_manager => FileMock
:file_manager => FileMock,
:logger => Pod::UI
)

# Assert
assert_equal(podspec, get_podspec_fabric_and_script_phases("echo Test Script Phase"))
assert_equal(Pod::UI.collected_messages, ["[Codegen] Adding script_phases to ReactCodegen."])
assert_equal(Pod::UI.collected_messages, ["Adding script_phases to ReactCodegen."])
end

def testGetReactCodegenSpec_whenUseFrameworksAndNewArch_generatesAPodspec
Expand Down Expand Up @@ -238,10 +239,10 @@ def testGetReactCodegenScriptPhases_whenAppPathNotDefined_abort

# Act
assert_raises() {
CodegenUtils.new().get_react_codegen_script_phases(nil, file_manager: FileMock)
CodegenUtils.new().get_react_codegen_script_phases(nil, file_manager: FileMock, logger: Pod::UI)
}
# Assert
assert_equal(Pod::UI.collected_warns, ["[Codegen] error: app_path is required to use codegen discovery."])
assert_equal(Pod::UI.collected_warns, ["error: app_path is required to use codegen discovery."])
end

def testGetReactCodegenScriptPhases_returnTheScriptObject
Expand Down Expand Up @@ -308,11 +309,11 @@ def testUseReactCodegenDiscovery_whenDiscoveryDone_doNothing
CodegenUtils.set_react_codegen_discovery_done(true)

# Act
CodegenUtils.new().use_react_native_codegen_discovery!(false, nil, file_manager: FileMock)
CodegenUtils.new().use_react_native_codegen_discovery!(false, nil, file_manager: FileMock, logger: Pod::UI)

# Assert
assert_true(CodegenUtils.react_codegen_discovery_done())
assert_equal(Pod::UI.collected_messages, ["[Codegen] Skipping use_react_native_codegen_discovery."])
assert_equal(Pod::UI.collected_messages, ["Skipping use_react_native_codegen_discovery."])
assert_equal(Pod::UI.collected_warns, [])
end

Expand All @@ -321,15 +322,15 @@ def testUseReactCodegenDiscovery_whenAppPathUndefined_abort

# Act
assert_raises(){
CodegenUtils.new().use_react_native_codegen_discovery!(false, nil, file_manager: FileMock)
CodegenUtils.new().use_react_native_codegen_discovery!(false, nil, file_manager: FileMock, logger: Pod::UI)
}

# Assert
assert_false(CodegenUtils.react_codegen_discovery_done())
assert_equal(Pod::UI.collected_messages, [])
assert_equal(Pod::UI.collected_warns, [
'[Codegen] Error: app_path is required for use_react_native_codegen_discovery.',
'[Codegen] If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.'
'Error: app_path is required for use_react_native_codegen_discovery.',
'If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.'
])
end

Expand All @@ -349,13 +350,14 @@ def testUseReactCodegenDiscovery_whenParametersAreGood_executeCodegen
false,
app_path,
:codegen_utils => codegen_utils_mock,
:file_manager => FileMock
:file_manager => FileMock,
:logger => Pod::UI
)

# Assert
assert_true(CodegenUtils.react_codegen_discovery_done())
assert_equal(Pod::UI.collected_warns, [
'[Codegen] warn: using experimental new codegen integration'
'warn: using experimental new codegen integration'
])
assert_equal(codegen_utils_mock.get_react_codegen_script_phases_params, [{
:app_path => app_path,
Expand Down
46 changes: 34 additions & 12 deletions packages/react-native/scripts/cocoapods/codegen_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ def self.react_codegen_discovery_done
# - spec: the cocoapod specs
# - codegen_output_dir: the output directory for the codegen
# - file_manager: a class that implements the `File` interface. Defaults to `File`, the Dependency can be injected for testing purposes.
def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File)
def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File, logger: CodegenUtils::UI)
# This podspec file should only be create once in the session/pod install.
# This happens when multiple targets are calling use_react_native!.
if @@REACT_CODEGEN_PODSPEC_GENERATED
Pod::UI.puts "[Codegen] Skipping ReactCodegen podspec generation."
logger.puts("Skipping ReactCodegen podspec generation.")
return
end

Expand All @@ -52,7 +52,7 @@ def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File
Pod::Executable.execute_command("mkdir", ["-p", output_dir]);

podspec_path = file_manager.join(output_dir, 'ReactCodegen.podspec.json')
Pod::UI.puts "[Codegen] Generating #{podspec_path}"
logger.puts("Generating #{podspec_path}")

file_manager.open(podspec_path, 'w') do |f|
f.write(spec.to_json)
Expand All @@ -69,7 +69,7 @@ def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File
# - hermes_enabled: whether hermes is enabled or not.
# - script_phases: whether we want to add some build script phases or not.
# - file_manager: a class that implements the `File` interface. Defaults to `File`, the Dependency can be injected for testing purposes.
def get_react_codegen_spec(package_json_file, folly_version: get_folly_config()[:version], hermes_enabled: true, script_phases: nil, file_manager: File)
def get_react_codegen_spec(package_json_file, folly_version: get_folly_config()[:version], hermes_enabled: true, script_phases: nil, file_manager: File, logger: CodegenUtils::UI)
package = JSON.parse(file_manager.read(package_json_file))
version = package['version']
use_frameworks = ENV['USE_FRAMEWORKS'] != nil
Expand Down Expand Up @@ -157,7 +157,7 @@ def get_react_codegen_spec(package_json_file, folly_version: get_folly_config()[
end

if script_phases
Pod::UI.puts "[Codegen] Adding script_phases to ReactCodegen."
logger.puts("Adding script_phases to ReactCodegen.")
spec[:'script_phases'] = script_phases
end

Expand Down Expand Up @@ -231,10 +231,11 @@ def get_react_codegen_script_phases(
config_key: 'codegenConfig',
codegen_utils: CodegenUtils.new(),
script_phase_extractor: CodegenScriptPhaseExtractor.new(),
file_manager: File
file_manager: File,
logger: CodegenUtils::UI
)
if !app_path
Pod::UI.warn '[Codegen] error: app_path is required to use codegen discovery.'
logger.warn("error: app_path is required to use codegen discovery.")
abort
end

Expand Down Expand Up @@ -281,22 +282,23 @@ def use_react_native_codegen_discovery!(
config_key: 'codegenConfig',
folly_version: get_folly_config()[:version],
codegen_utils: CodegenUtils.new(),
file_manager: File
file_manager: File,
logger: CodegenUtils::UI
)
return if codegen_disabled

if CodegenUtils.react_codegen_discovery_done()
Pod::UI.puts "[Codegen] Skipping use_react_native_codegen_discovery."
logger.puts("Skipping use_react_native_codegen_discovery.")
return
end

if !app_path
Pod::UI.warn '[Codegen] Error: app_path is required for use_react_native_codegen_discovery.'
Pod::UI.warn '[Codegen] If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.'
logger.warn("Error: app_path is required for use_react_native_codegen_discovery.")
logger.warn("If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.")
abort
end

Pod::UI.warn '[Codegen] warn: using experimental new codegen integration'
logger.warn("warn: using experimental new codegen integration")
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)

# Generate ReactCodegen podspec here to add the script phases.
Expand Down Expand Up @@ -362,4 +364,24 @@ def self.assert_codegen_folder_is_empty(codegen_path, dir_manager: Dir)
abort
end
end

class UI
# ANSI escape codes for colors and formatting
CYAN = "\e[36m"
YELLOW = "\e[33m"
BOLD = "\e[1m"
RESET = "\e[0m"

class << self
def puts(text, info: false)
prefix = "#{CYAN}#{BOLD}[Codegen]#{RESET}"
message = info ? "#{YELLOW}#{text}#{RESET}" : text
Pod::UI.puts "#{prefix} #{message}"
end

def warn(text)
puts(text, info: true)
end
end
end
end
Loading

0 comments on commit 1747f57

Please sign in to comment.