Skip to content

Conversation

@rileyseaburg
Copy link
Contributor

@rileyseaburg rileyseaburg commented Nov 22, 2025

This pull request introduces several improvements to the Rust widget renderer integration, environment configuration, and build/deployment processes. The main goals are to ensure robust handling of the Rust extension across environments, improve boolean serialization for widget rendering, and allow more flexible configuration of asset and session domains. Additionally, it updates CI/CD workflows and removes an obsolete test file.

Widget Renderer Integration Improvements

  • Updated the Rust extension loader to require lib/widget_renderer instead of the previous path, ensuring the correct file is loaded after build and runtime compilation. (config/initializers/widget_renderer.rb) [1] [2]
  • Improved the Ruby wrapper for the Rust extension to handle stale or incorrect WidgetRenderer module definitions, ensuring Rutie initializes the class properly. (ext/widget_renderer/lib/widget_renderer.rb) [1] [2]
  • Enhanced the Rust-side deserialization to treat missing or null booleans as false, preventing errors from legacy or incomplete Rails data. (ext/widget_renderer/src/form_data.rs) [1] [2]
  • Updated the Rails model to consistently serialize booleans and question text for the Rust widget renderer, and to skip Rust rendering in test environments. (app/models/form.rb) [1] [2]

Build and Deployment Process Updates

  • Improved the build artifact handling in the GitHub workflow and CircleCI config, ensuring the correct shared library is found and copied regardless of target or environment. (.github/workflows/build-widget.yml, .circleci/config.yml, .cfignore, .profile.d/build_widget_renderer.sh, ext/widget_renderer/extconf.rb) [1] [2] [3] [4] [5] [6] [7]

Environment and Configuration Flexibility

  • Added support for overriding asset host and session cookie domain via environment variables, improving deployment flexibility across staging and production. (config/environments/staging.rb, config/initializers/session_store.rb, touchpoints-staging.yml) [1] [2] [3] [4]

Testing and CI/CD Adjustments

  • Removed an obsolete controller export spec to clean up the test suite. (spec/controllers/admin/cx_collections_controller_export_spec.rb)
  • Improved feature spec reliability by using more robust selectors and waits. (spec/features/admin/forms/form_permissions_spec.rb)

These changes collectively improve the reliability, maintainability, and deployment flexibility of the widget renderer integration and overall application.

Copilot AI review requested due to automatic review settings November 22, 2025 16:13
Copilot finished reviewing on behalf of rileyseaburg November 22, 2025 16:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges the Rust widget renderer feature branch into develop, introducing Rust-based widget rendering capabilities with buildpack integration for staging deployment. The changes include infrastructure updates, configuration refinements, and bug fixes to support the new rendering architecture.

  • Integrates Rust buildpack for compiling the widget renderer extension in Cloud Foundry environments
  • Updates staging domain configuration from touchpoints-staging.app.cloud.gov to app-staging.touchpoints.digital.gov
  • Fixes bug in form model where question_text incorrectly referenced non-existent attribute (should be text)

Reviewed changes

Copilot reviewed 10 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
touchpoints-staging.yml Updates redirect URI to new domain, adds ASSET_HOST and domain configuration, includes nodejs buildpack for build process
spec/controllers/admin/cx_collections_controller_export_spec.rb Removes duplicate test file (tests remain in cx_collections_controller_spec.rb)
ext/widget_renderer/lib/widget_renderer.rb Refactors module wrapper to top-level code with explicit class creation to resolve Rutie compatibility issues
config/initializers/widget_renderer.rb Updates require path to match new lib/ directory structure
config/initializers/session_store.rb Changes session domain configuration to use new SESSION_COOKIE_DOMAIN environment variable
config/environments/staging.rb Adds ASSET_HOST environment variable support with fallback to TOUCHPOINTS_WEB_DOMAIN
app/models/service.rb Fixes indentation consistency in CSV export attribute exclusion array
app/models/form.rb Corrects question attribute reference from question_text to text
.profile.d/build_widget_renderer.sh Adds comprehensive Rust toolchain detection and Ruby library linking configuration
.gitignore Expands patterns to ignore all .env.* and vars*.yml files
.github/workflows/build-widget.yml Simplifies build to use default target, improves artifact detection robustness
.cfignore Adds negation patterns to preserve prebuilt widget library while ignoring build artifacts

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# Ignore Rust build artifacts
# Ignore Rust build artifacts, but keep the prebuilt widget library
target/
ext/widget_renderer/target/
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The negation pattern on line 44 won't work as intended because line 43 already ignores the parent directory ext/widget_renderer/target/. In gitignore-style patterns, once a parent directory is ignored, you cannot un-ignore it with a negation pattern before un-ignoring its contents.

Consider removing line 43 (ext/widget_renderer/target/) and keeping only line 42 (target/) which already covers this path. The specific negations on lines 45-46 should then work correctly.

Suggested change
ext/widget_renderer/target/

Copilot uses AI. Check for mistakes.
# frozen_string_literal: true

Rails.application.config.session_store :cookie_store, key: '_touchpoints_session', domain: ENV.fetch('TOUCHPOINTS_WEB_DOMAIN'), same_site: :lax, expire_after: 30.minutes
cookie_domain = ENV['SESSION_COOKIE_DOMAIN'].presence
Copy link

Copilot AI Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SESSION_COOKIE_DOMAIN environment variable is not defined in touchpoints-staging.yml, which means cookie_domain will be nil. This changes the cookie domain behavior from the previous explicit value (ENV.fetch('TOUCHPOINTS_WEB_DOMAIN')). A nil domain makes the cookie available only to the current host without subdomains.

Consider either:

  1. Adding SESSION_COOKIE_DOMAIN to the environment configuration in touchpoints-staging.yml, or
  2. Providing a fallback: cookie_domain = ENV['SESSION_COOKIE_DOMAIN'].presence || ENV.fetch('TOUCHPOINTS_WEB_DOMAIN')
Suggested change
cookie_domain = ENV['SESSION_COOKIE_DOMAIN'].presence
cookie_domain = ENV['SESSION_COOKIE_DOMAIN'].presence || ENV.fetch('TOUCHPOINTS_WEB_DOMAIN')

Copilot uses AI. Check for mistakes.
@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

When ASSET_HOST differs from the page origin, SRI (Subresource Integrity)
checks require CORS headers on the asset responses. This adds
Access-Control-Allow-Origin headers to the public file server configuration
for both staging and production environments.
- Add wait_for_deployment() function that checks CF API for active deployments
- Wait up to 10 minutes for in-progress deployments to complete before starting
- Increase retry delay to 90s and re-check before each retry
- Increase timeout to 30m and sleep to 120s between Sidekiq and web deploys
- Add acquire_deploy_lock() using CF env var as distributed lock
- Lock includes build number and timestamp for debugging
- Auto-clear stale locks older than 15 minutes
- Add note about enabling auto-cancel in CircleCI project settings
- Update .profile.d/build_widget_renderer.sh to build with Cargo at runtime
- Find Cargo in /home/vcap/deps/*/rust/cargo/bin/cargo
- Set RUTIE_RUBY_LIB_PATH from Ruby's RbConfig::CONFIG[libdir]
- Run cargo build --release if library missing or has wrong linkage
- Add buildpacks/rust-buildpack/bin/finalize as backup
- Remove prebuilt library from CI before deploy

This fixes the libruby.so.3.2 cannot open shared object file error
by building the Rust extension ON Cloud Foundry where it can link
against the correct Ruby installation at /home/vcap/deps/*/ruby/lib/
The prebuilt library from CI has wrong linkage (libruby.so.3.2 => not found).
This script now checks ldd output and rebuilds with Cargo if linkage is broken.
- Add restore/save cache for Cargo target and registry directories
- Use Cargo.lock checksum for cache key to ensure proper invalidation
- Verify Rust library linkage with ldd before deploy
- Fail fast if library has unresolved dependencies
- Should significantly speed up Rust builds on subsequent runs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants