Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
script/ci-changes-detector "$BASE_REF"
shell: bash

examples:
build-examples-and-test-generators:
needs: detect-changes
# Run on master, workflow_dispatch, OR when generators needed
if: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ jobs:
path: spec/dummy/public/webpack
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}

dummy-app-integration-tests:
spec-dummy-integration-tests:
needs: [detect-changes, build-dummy-app-webpack-test-bundles]
# Run on master, workflow_dispatch, OR when tests needed on PR
if: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-js-and-ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
script/ci-changes-detector "$BASE_REF"
shell: bash

build:
lint-js-and-ruby:
needs: detect-changes
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_lint == 'true'
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-js-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
script/ci-changes-detector "$BASE_REF"
shell: bash

build:
package-js-tests:
needs: detect-changes
# Run on master OR when JS tests needed on PR
if: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pro-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
shell: bash

# Build webpack test bundles for dummy app
build-dummy-app-webpack-test-bundles:
pro-build-dummy-app-webpack-test-bundles:
needs: detect-changes
if: github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_pro_tests == 'true'
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -147,7 +147,7 @@
key: v4-pro-dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}

# RSpec integration tests with Node renderer
rspec-dummy-app-node-renderer:
pro-dummy-app-node-renderer:

Check failure on line 150 in .github/workflows/pro-integration-tests.yml

View workflow job for this annotation

GitHub Actions / actionlint

job "pro-dummy-app-node-renderer" needs job "build-dummy-app-webpack-test-bundles" which does not exist in this workflow
needs:
- detect-changes
- build-dummy-app-webpack-test-bundles
Expand Down Expand Up @@ -324,7 +324,7 @@
path: react_on_rails_pro/spec/dummy/yarn-error.log

# Playwright E2E tests with Redis service
dummy-app-node-renderer-e2e-tests:
node-renderer-e2e-tests:

Check failure on line 327 in .github/workflows/pro-integration-tests.yml

View workflow job for this annotation

GitHub Actions / actionlint

job "node-renderer-e2e-tests" needs job "build-dummy-app-webpack-test-bundles" which does not exist in this workflow
needs:
- detect-changes
- build-dummy-app-webpack-test-bundles
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pro-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
script/ci-changes-detector "$BASE_REF"
shell: bash

lint-js-and-ruby:
pro-lint-js-and-ruby:
needs: detect-changes
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_lint == 'true'
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -148,7 +148,7 @@ jobs:
run: cd spec/dummy && bundle exec rake react_on_rails:generate_packs

- name: Lint Ruby
run: bundle exec rubocop
run: bundle exec rubocop --ignore-parent-exclusion

- name: Validate RBS type signatures
run: bundle exec rake rbs:validate
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pro-test-package-and-gem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
shell: bash

# Build webpack test bundles for dummy app
build-dummy-app-webpack-test-bundles:
pro-build-dummy-app-webpack-test-bundles:
needs: detect-changes
if: github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_pro_tests == 'true'
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -147,7 +147,7 @@
key: v4-pro-dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}

# Jest unit tests for Pro package
package-js-tests:
pro-package-js-tests:

Check failure on line 150 in .github/workflows/pro-test-package-and-gem.yml

View workflow job for this annotation

GitHub Actions / actionlint

job "pro-package-js-tests" needs job "build-dummy-app-webpack-test-bundles" which does not exist in this workflow
needs:
- detect-changes
- build-dummy-app-webpack-test-bundles
Expand Down Expand Up @@ -227,7 +227,7 @@
path: react_on_rails_pro/jest

# RSpec tests for Pro package
rspec-package-specs:
pro-gem-tests:
needs: detect-changes
if: github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_pro_tests == 'true'
strategy:
Expand Down
18 changes: 9 additions & 9 deletions react_on_rails_pro/lib/react_on_rails_pro/license_public_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ module LicensePublicKey
# TODO: Add a prepublish check to ensure this key matches the latest public key from the API.
# This should be implemented after publishing the API endpoint on the ShakaCode website.
KEY = OpenSSL::PKey::RSA.new(<<~PEM.strip.strip_heredoc)
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcS/fpHz5CbnTQxb4Zot
khjzXu7xNS+Y9VKfapMaHOMzNoCMfy1++hxHJatRedr+YQfZRCjfiN168Cpe+dhe
yfNtOoLU9/+/5jTsxH+WQJWNRswyKms5HNajlIMN1GEYdZmZbvOPaZvh6ENsT+EV
HnhjJtsHl7qltBoL0ul7rONxaNHCzJcKk4lf3B2/1j1wpA91MKz4bbQVh4/6Th0E
/39f0PWvvBXzQS+yt1qaa1DIX5YL6Aug5uEpb1+6QWcN3hCzqSPBv1HahrG50rsD
gf8KORV3X2N9t6j6iqPmRqfRcTBKtmPhM9bORtKiSwBK8LsIUzp2/UUmkdHnkyzu
NQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcS/fpHz5CbnTQxb4Zot
khjzXu7xNS+Y9VKfapMaHOMzNoCMfy1++hxHJatRedr+YQfZRCjfiN168Cpe+dhe
yfNtOoLU9/+/5jTsxH+WQJWNRswyKms5HNajlIMN1GEYdZmZbvOPaZvh6ENsT+EV
HnhjJtsHl7qltBoL0ul7rONxaNHCzJcKk4lf3B2/1j1wpA91MKz4bbQVh4/6Th0E
/39f0PWvvBXzQS+yt1qaa1DIX5YL6Aug5uEpb1+6QWcN3hCzqSPBv1HahrG50rsD
gf8KORV3X2N9t6j6iqPmRqfRcTBKtmPhM9bORtKiSwBK8LsIUzp2/UUmkdHnkyzu
NQIDAQAB
-----END PUBLIC KEY-----
PEM
end
end
55 changes: 32 additions & 23 deletions react_on_rails_pro/lib/react_on_rails_pro/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def common_form_data
ReactOnRailsPro::Utils.common_form_data
end

def create_connection
def create_connection # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
url = ReactOnRailsPro.configuration.renderer_url
Rails.logger.info do
"[ReactOnRailsPro] Setting up Node Renderer connection to #{url}"
Expand All @@ -229,28 +229,37 @@ def create_connection
# https://honeyryderchuck.gitlab.io/httpx/wiki/Persistent
.plugin(
:retries, max_retries: 1,
retry_change_requests: true,
# Official HTTPx docs says that we should use the retry_on option to decide if teh request should be retried or not
# However, HTTPx assumes that connection errors such as timeout error should be retried by default and it doesn't consider retry_on block at all at that case
# So, we have to do the following trick to avoid retries when a Timeout error happens while streaming a component
# If the streamed component returned any chunks, it shouldn't retry on errors, as it would cause page duplication
# The SSR-generated html will be written to the page two times in this case
retry_after: ->(request, response) do
if (request.stream.instance_variable_get(:@react_on_rails_received_first_chunk))
e = response.error
raise ReactOnRailsPro::Error, "An error happened during server side render streaming of a component.\n" \
"Original error:\n#{e}\n#{e.backtrace}"
end

Rails.logger.info do
"[ReactOnRailsPro] An error happneding while making a request to the Node Renderer.\n" \
"Error: #{response.error}.\n" \
"Retrying by HTTPX \"retries\" plugin..."
end
# The retry_after block expects to return a delay to wait before retrying the request
# nil means no waiting delay
nil
end
retry_change_requests: true,
# Official HTTPx docs says that we should use the retry_on option to decide if the
# request should be retried or not
# However, HTTPx assumes that connection errors such as timeout error should be retried
# by default and it doesn't consider retry_on block at all at that case
# So, we have to do the following trick to avoid retries when a Timeout error happens
# while streaming a component
# If the streamed component returned any chunks, it shouldn't retry on errors, as it
# would cause page duplication
# The SSR-generated html will be written to the page two times in this case
retry_after: lambda do |request, response|
if request.stream.instance_variable_get(:@react_on_rails_received_first_chunk)
e = response.error
raise(
ReactOnRailsPro::Error,
"An error happened during server side render streaming " \
"of a component.\nOriginal error:\n#{e}\n#{e.backtrace}"
)
end

Rails.logger.info do
"[ReactOnRailsPro] An error occurred while making " \
"a request to the Node Renderer.\n" \
"Error: #{response.error}.\n" \
"Retrying by HTTPX \"retries\" plugin..."
end
# The retry_after block expects to return a delay to wait before
# retrying the request
# nil means no waiting delay
nil
end
)
.plugin(:stream)
# See https://www.rubydoc.info/gems/httpx/1.3.3/HTTPX%2FOptions:initialize for the available options
Expand Down
10 changes: 5 additions & 5 deletions react_on_rails_pro/lib/react_on_rails_pro/stream_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,23 @@ def handle_chunk(chunk, position)
end
end

def each_chunk(&block)
def each_chunk(&block) # rubocop:disable Metrics/CyclomaticComplexity
return enum_for(:each_chunk) unless block

first_chunk = true
@component.each_chunk do |chunk|
position = first_chunk ? :first : :middle
modified_chunk = handle_chunk(chunk, position)
block.call(modified_chunk)
yield(modified_chunk)
first_chunk = false
end

# The last chunk contains the append content after the transformation
# All transformations are applied to the append content
last_chunk = handle_chunk("", :last)
block.call(last_chunk) unless last_chunk.empty?
rescue StandardError => err
current_error = err
yield(last_chunk) unless last_chunk.empty?
rescue StandardError => e
current_error = e
rescue_block_index = 0
while current_error.present? && (rescue_block_index < @rescue_blocks.size)
begin
Expand Down
11 changes: 6 additions & 5 deletions react_on_rails_pro/rakelib/public_key_management.rake
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ require "uri"
# rake react_on_rails_pro:verify_public_key # Verify current configuration
# rake react_on_rails_pro:public_key_help # Show help

namespace :react_on_rails_pro do
namespace :react_on_rails_pro do # rubocop:disable Metrics/BlockLength
desc "Update the public key for React on Rails Pro license validation"
task :update_public_key, [:source] do |_task, args|
task :update_public_key, [:source] do |_task, args| # rubocop:disable Metrics/BlockLength
source = args[:source] || "production"

# Determine the API URL based on the source
Expand Down Expand Up @@ -68,7 +68,7 @@ namespace :react_on_rails_pro do
# ShakaCode's public key for React on Rails Pro license verification
# The private key corresponding to this public key is held by ShakaCode
# and is never committed to the repository
# Last updated: #{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S UTC")}
# Last updated: #{Time.now.utc.strftime('%Y-%m-%d %H:%M:%S UTC')}
# Source: #{api_url}
#
# You can update this public key by running the rake task:
Expand All @@ -86,12 +86,13 @@ namespace :react_on_rails_pro do
puts "✅ Updated Ruby public key: #{ruby_file_path}"

# Update Node/TypeScript public key file
node_file_path = File.join(File.dirname(__FILE__), "..", "packages", "node-renderer", "src", "shared", "licensePublicKey.ts")
node_file_path = File.join(File.dirname(__FILE__), "..", "packages", "node-renderer", "src", "shared",
"licensePublicKey.ts")
node_content = <<~TYPESCRIPT
// ShakaCode's public key for React on Rails Pro license verification
// The private key corresponding to this public key is held by ShakaCode
// and is never committed to the repository
// Last updated: #{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S UTC")}
// Last updated: #{Time.now.utc.strftime('%Y-%m-%d %H:%M:%S UTC')}
// Source: #{api_url}
//
// You can update this public key by running the rake task:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class PagesController < ApplicationController
class PagesController < ApplicationController # rubocop:disable Metrics/ClassLength
include ReactOnRailsPro::RSCPayloadRenderer
include RscPostsPageOverRedisHelper

Expand Down Expand Up @@ -85,8 +85,8 @@ def redis_receiver
ensure
begin
redis&.close
rescue StandardError => close_err
Rails.logger.warn "Failed to close Redis: #{close_err.message}"
rescue StandardError => e
Rails.logger.warn "Failed to close Redis: #{e.message}"
end
end

Expand Down
6 changes: 3 additions & 3 deletions react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,14 @@ def change_text_expect_dom_selector(dom_selector, expect_no_change: false)

it "hydrates the component" do
visit path
expect(page.html).to match(/client-bundle[^\"]*.js/)
expect(page.html).to match(/client-bundle[^"]*.js/)
change_text_expect_dom_selector(selector)
end

it "renders the page completely on server and displays content on client even without JavaScript" do
# Don't add client-bundle.js to the page to ensure that the app is not hydrated
visit "#{path}?skip_js_packs=true"
expect(page.html).not_to match(/client-bundle[^\"]*.js/)
expect(page.html).not_to match(/client-bundle[^"]*.js/)
# Ensure that the component state is not updated
change_text_expect_dom_selector(selector, expect_no_change: true)

Expand Down Expand Up @@ -432,7 +432,7 @@ def change_text_expect_dom_selector(dom_selector, expect_no_change: false)
"#ServerComponentRouter-react-component-0"

# Skip the test that fails without JavaScript - being addressed in another PR
it "renders the page completely on server and displays content on client even without JavaScript",
it "renders the page completely on server and displays content on client even without JavaScript", # rubocop:disable RSpec/NoExpectationExample
skip: "Being addressed in another PR" do
# This test is overridden to skip it
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require_relative "spec_helper"

module ReactOnRailsPro
module ReactOnRailsPro # rubocop:disable Metrics/ModuleLength
RSpec.describe Configuration do
after do
ReactOnRailsPro.instance_variable_set(:@configuration, nil)
Expand Down Expand Up @@ -205,7 +205,8 @@ def self.fetch(*)

expect(ReactOnRailsPro.configuration.rsc_bundle_js_file).to eq("rsc-bundle.js")
expect(ReactOnRailsPro.configuration.react_client_manifest_file).to eq("react-client-manifest.json")
expect(ReactOnRailsPro.configuration.react_server_client_manifest_file).to eq("react-server-client-manifest.json")
expect(ReactOnRailsPro.configuration.react_server_client_manifest_file)
.to eq("react-server-client-manifest.json")
end

it "allows setting rsc_bundle_js_file" do
Expand All @@ -229,7 +230,8 @@ def self.fetch(*)
config.react_server_client_manifest_file = "custom-server-client-manifest.json"
end

expect(ReactOnRailsPro.configuration.react_server_client_manifest_file).to eq("custom-server-client-manifest.json")
expect(ReactOnRailsPro.configuration.react_server_client_manifest_file)
.to eq("custom-server-client-manifest.json")
end

it "allows nil values for RSC configuration options" do
Expand Down
Loading
Loading