diff --git a/.github/workflows/lint-and-validate.yml b/.github/workflows/lint-and-validate.yml index c9bdf333..8aaf6dd2 100644 --- a/.github/workflows/lint-and-validate.yml +++ b/.github/workflows/lint-and-validate.yml @@ -39,17 +39,30 @@ jobs: - '**/*.tsx' - '.github/workflows/lint-and-validate.yml' kotlin: - - 'packages/gradle-client/**' + - 'packages/build-tools/gradle-plugin/**' - '.github/workflows/lint-and-validate.yml' json: - '*.json' - '.github/workflows/lint-and-validate.yml' + ruby: + - 'packages/build-tools/cocoapods-plugin/**' + - '.github/workflows/lint-and-validate.yml' - name: 🏗 Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: latest + - name: 🏗 Setup Ruby + if: ${{ steps.filter.outputs.ruby == 'true' }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0' + + - name: 🏗 Install rubocop + if: ${{ steps.filter.outputs.ruby == 'true' }} + run: gem install rubocop + - name: 🗃️ Cache Bun and Gradle uses: actions/cache@v4 with: @@ -72,6 +85,10 @@ jobs: if: ${{ steps.filter.outputs.typescript == 'true' }} run: bun run lint-ts + - name: 🔍 Lint ruby + if: ${{ steps.filter.outputs.ruby == 'true' }} + run: bun run lint-ruby + - name: ✅ Validate JSON files if: ${{ steps.filter.outputs.json == 'true' }} run: bun run validate diff --git a/package.json b/package.json index 7a2fb1eb..2f853b56 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "validate": "bun run packages/config/src/validate.ts", "lint-gradle-client": "./packages/build-tools/gradle-plugin/gradlew -p packages/build-tools/gradle-plugin spotlessCheck -q --no-daemon", "lint-ts": "eslint . --ext .ts,.tsx", + "lint-ruby": "rubocop packages/build-tools/cocoapods-plugin", "test-gradle-client": "./packages/build-tools/gradle-plugin/gradlew -p packages/build-tools/gradle-plugin test --info --no-daemon" }, "author": "", diff --git a/packages/build-tools/cocoapods-plugin/README.md b/packages/build-tools/cocoapods-plugin/README.md index c869feca..66204d46 100644 --- a/packages/build-tools/cocoapods-plugin/README.md +++ b/packages/build-tools/cocoapods-plugin/README.md @@ -73,3 +73,16 @@ node_modules/ │ └── {package-name}.xcframework/ └── Current/ (symlink created at build time → Debug or Release) ``` + +### Lint + +To run the linter, use the following command: + +```bash +# Install rubocop if you don't have it yet +gem install rubocop +# Run +rubocop +# Or with auto-correct +rubocop -a +``` diff --git a/packages/build-tools/cocoapods-plugin/lib/downloader.rb b/packages/build-tools/cocoapods-plugin/lib/downloader.rb index 630193ce..a77510ff 100644 --- a/packages/build-tools/cocoapods-plugin/lib/downloader.rb +++ b/packages/build-tools/cocoapods-plugin/lib/downloader.rb @@ -1,11 +1,14 @@ +# frozen_string_literal: true + require 'net/http' require 'uri' require 'fileutils' require 'zip' module CocoapodsRnrepo + # Handles artifact download and extraction for RNRepo CocoaPods integration. class Downloader - @@repo_url = "https://packages.rnrepo.org/releases" + @repo_url = 'https://packages.rnrepo.org/releases' def self.validate_artifact_spec(artifact_spec, required_keys) missing_keys = required_keys.select { |key| !artifact_spec.key?(key) || artifact_spec[key].nil? } @@ -19,7 +22,10 @@ def self.validate_artifact_spec(artifact_spec, required_keys) def self.build_artifact_url(artifact_spec) worklets_suffix = artifact_spec[:worklets_version] ? "-worklets#{artifact_spec[:worklets_version]}" : '' - "#{@@repo_url}/org/rnrepo/public/#{artifact_spec[:sanitized_name]}/#{artifact_spec[:version]}/#{artifact_spec[:sanitized_name]}-#{artifact_spec[:version]}-rn#{artifact_spec[:rn_version]}#{worklets_suffix}-#{artifact_spec[:configuration]}.xcframework.zip" + "#{@repo_url}/org/rnrepo/public/#{artifact_spec[:sanitized_name]}/" \ + "#{artifact_spec[:version]}/#{artifact_spec[:sanitized_name]}-" \ + "#{artifact_spec[:version]}-rn#{artifact_spec[:rn_version]}" \ + "#{worklets_suffix}-#{artifact_spec[:configuration]}.xcframework.zip" end def self.build_http_client(uri, read_timeout) @@ -31,64 +37,72 @@ def self.build_http_client(uri, read_timeout) end # Download file via HTTP request - # Requires: artifact_spec hash with :sanitized_name, :version, :rn_version, :configuration, :destination, :worklets_version (optional) + # Requires: artifact_spec hash with :sanitized_name, :version, :rn_version, + # :configuration, :destination, :worklets_version (optional) # Returns: destination path if successful, nil on failure def self.download_file(artifact_spec) Logger.log "Preparing to download: #{artifact_spec[:package]}@#{artifact_spec[:version]}" - required_keys = [:sanitized_name, :version, :rn_version, :configuration, :destination] + required_keys = %i[sanitized_name version rn_version configuration destination] return nil unless validate_artifact_spec(artifact_spec, required_keys) url = build_artifact_url(artifact_spec) Logger.log "Downloading from #{url}..." - - uri = URI.parse(url) - http = build_http_client(uri, 60) - - request = Net::HTTP::Get.new(uri.request_uri) - - http.request(request) do |response| - if response.code.to_i == 200 - File.open(artifact_spec[:destination], 'wb') do |file| - response.read_body do |chunk| - file.write(chunk) - end - end - return artifact_spec[:destination] - else - Logger.log "Failed to download #{url}: HTTP #{response.code}" - return nil - end - end - rescue => e + download_http_file(url, artifact_spec[:destination]) + rescue StandardError => e Logger.log "Error downloading #{url}: #{e.message}" - return nil + nil end # Unzip file to destination directory def self.unzip_file(zip_path, destination) Logger.log "Extracting to #{destination}..." - FileUtils.mkdir_p(destination) Zip::File.open(zip_path) do |zip_file| - zip_file.each do |entry| - entry_path = File.join(destination, entry.name) - FileUtils.mkdir_p(File.dirname(entry_path)) + zip_file.each { |entry| extract_zip_entry(destination, entry) } + end + + Logger.log 'Extracted successfully' + true + rescue StandardError => e + Logger.log "Error extracting #{zip_path}: #{e.message}" + false + end + + def self.download_http_file(url, destination) + uri = URI.parse(url) + http = build_http_client(uri, 60) + request = Net::HTTP::Get.new(uri.request_uri) - # Remove existing file if it exists - FileUtils.rm_f(entry_path) if File.exist?(entry_path) + http.request(request) do |response| + return handle_download_response(response, url, destination) + end + end - entry.extract(entry_path) + def self.handle_download_response(response, url, destination) + if response.code.to_i == 200 + write_response_body(response, destination) + destination + else + Logger.log "Failed to download #{url}: HTTP #{response.code}" + nil + end + end + + def self.write_response_body(response, destination) + File.open(destination, 'wb') do |file| + response.read_body do |chunk| + file.write(chunk) end end + end - Logger.log "Extracted successfully" - true - rescue => e - Logger.log "Error extracting #{zip_path}: #{e.message}" - return false + def self.extract_zip_entry(destination, entry) + entry_path = File.join(destination, entry.name) + FileUtils.mkdir_p(File.dirname(entry_path)) + FileUtils.rm_f(entry_path) if File.exist?(entry_path) + entry.extract(entry_path) end end end - diff --git a/packages/build-tools/cocoapods-plugin/lib/gem_version.rb b/packages/build-tools/cocoapods-plugin/lib/gem_version.rb index 056cd951..cbaf2a67 100644 --- a/packages/build-tools/cocoapods-plugin/lib/gem_version.rb +++ b/packages/build-tools/cocoapods-plugin/lib/gem_version.rb @@ -1,4 +1,5 @@ +# frozen_string_literal: true + module CocoapodsRnrepo VERSION = '0.1.0' end - diff --git a/packages/build-tools/cocoapods-plugin/lib/logger.rb b/packages/build-tools/cocoapods-plugin/lib/logger.rb index da2b145e..550525e1 100644 --- a/packages/build-tools/cocoapods-plugin/lib/logger.rb +++ b/packages/build-tools/cocoapods-plugin/lib/logger.rb @@ -1,8 +1,11 @@ +# frozen_string_literal: true + module CocoapodsRnrepo + # Simple logger for RNRepo CocoaPods plugin with colored output. class Logger # Colored prefix for logs def self.log_prefix - "[📦 RNRepo]".cyan + '[📦 RNRepo]'.cyan end # Log helper method @@ -11,4 +14,3 @@ def self.log(message) end end end -