-
Notifications
You must be signed in to change notification settings - Fork 25
AppConfig refactor #870
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
AppConfig refactor #870
Changes from all commits
a1f59ee
253321f
15e09a0
73ac1b9
379adce
a5d2f57
04abfa0
ce9d696
d0534ad
1ba11ce
a96cd2b
cf8de84
397e9d7
08adced
9d9d8dd
5ba3372
7d32eb4
d019bd2
2b0628d
69df925
dbff8e3
11eb9df
a40b6b3
43f8262
7ebdd8a
d4c2e5b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,54 @@ | ||||||||||||||||||||||||||
class BuildChannel::GoogleFirebaseConfigsController < SignedInApplicationController | ||||||||||||||||||||||||||
using RefinedString | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
before_action :require_write_access! | ||||||||||||||||||||||||||
before_action :set_app | ||||||||||||||||||||||||||
before_action :set_google_firebase_integration | ||||||||||||||||||||||||||
around_action :set_time_zone | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def edit | ||||||||||||||||||||||||||
set_firebase_apps | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
respond_to do |format| | ||||||||||||||||||||||||||
format.html do |variant| | ||||||||||||||||||||||||||
variant.turbo_frame { render :edit } | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def update | ||||||||||||||||||||||||||
if @google_firebase_integration.update(parsed_google_firebase_config_params) | ||||||||||||||||||||||||||
redirect_to app_path(@app), notice: t(".success") | ||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||
redirect_back fallback_location: app_integrations_path(@app), | ||||||||||||||||||||||||||
flash: {error: @google_firebase_integration.errors.full_messages.to_sentence} | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_app | ||||||||||||||||||||||||||
@app = current_organization.apps.friendly.find(params[:app_id]) | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_google_firebase_integration | ||||||||||||||||||||||||||
@google_firebase_integration = @app.integrations.firebase_build_channel_provider | ||||||||||||||||||||||||||
unless @google_firebase_integration.is_a?(GoogleFirebaseIntegration) | ||||||||||||||||||||||||||
redirect_to app_integrations_path(@app), flash: {error: "Firebase build channel integration not found."} | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
Comment on lines
+34
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add explicit return after redirect to prevent continued execution. Rails redirects do not halt execution. If Apply this diff: def set_google_firebase_integration
@google_firebase_integration = @app.integrations.firebase_build_channel_provider
unless @google_firebase_integration.is_a?(GoogleFirebaseIntegration)
- redirect_to app_integrations_path(@app), flash: {error: "Firebase build channel integration not found."}
+ redirect_to app_integrations_path(@app), flash: {error: "Firebase build channel integration not found."} and return
end
end 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_firebase_apps | ||||||||||||||||||||||||||
config = @google_firebase_integration.setup | ||||||||||||||||||||||||||
@firebase_android_apps, @firebase_ios_apps = config[:android], config[:ios] | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def parsed_google_firebase_config_params | ||||||||||||||||||||||||||
google_firebase_config_params = params.require(:google_firebase_integration) | ||||||||||||||||||||||||||
.permit(:android_config, :ios_config) | ||||||||||||||||||||||||||
google_firebase_config_params.merge( | ||||||||||||||||||||||||||
android_config: google_firebase_config_params[:android_config]&.safe_json_parse, | ||||||||||||||||||||||||||
ios_config: google_firebase_config_params[:ios_config]&.safe_json_parse | ||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
Comment on lines
+46
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent unintended config wipe when params are omitted Merging unconditionally injects nil and can clear jsonb columns if a field isn’t submitted. Parse only when the key is present. Apply this diff: def parsed_google_firebase_config_params
- google_firebase_config_params = params.require(:google_firebase_integration)
- .permit(:android_config, :ios_config)
- google_firebase_config_params.merge(
- android_config: google_firebase_config_params[:android_config]&.safe_json_parse,
- ios_config: google_firebase_config_params[:ios_config]&.safe_json_parse
- )
+ p = params.require(:google_firebase_integration)
+ .permit(:android_config, :ios_config)
+ p[:android_config] = p[:android_config]&.safe_json_parse if p.key?(:android_config)
+ p[:ios_config] = p[:ios_config]&.safe_json_parse if p.key?(:ios_config)
+ p
end 🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||
end |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,55 @@ | ||||||||||||||||||||||||||||||
class CiCd::BitbucketConfigsController < SignedInApplicationController | ||||||||||||||||||||||||||||||
using RefinedString | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
before_action :require_write_access! | ||||||||||||||||||||||||||||||
before_action :set_app | ||||||||||||||||||||||||||||||
before_action :set_bitbucket_integration | ||||||||||||||||||||||||||||||
around_action :set_time_zone | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def edit | ||||||||||||||||||||||||||||||
set_code_repositories | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
respond_to do |format| | ||||||||||||||||||||||||||||||
format.html do |variant| | ||||||||||||||||||||||||||||||
variant.turbo_frame { render :edit } | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
format.turbo_stream { render :edit } | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def update | ||||||||||||||||||||||||||||||
if @bitbucket_integration.update(parsed_bitbucket_config_params) | ||||||||||||||||||||||||||||||
redirect_to app_path(@app), notice: t(".success") | ||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||
redirect_back fallback_location: app_integrations_path(@app), | ||||||||||||||||||||||||||||||
flash: {error: @bitbucket_integration.errors.full_messages.to_sentence} | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
private | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def set_app | ||||||||||||||||||||||||||||||
@app = current_organization.apps.friendly.find(params[:app_id]) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def set_bitbucket_integration | ||||||||||||||||||||||||||||||
@bitbucket_integration = @app.ci_cd_provider | ||||||||||||||||||||||||||||||
unless @bitbucket_integration.is_a?(BitbucketIntegration) | ||||||||||||||||||||||||||||||
redirect_to app_integrations_path(@app), flash: {error: "CI/CD integration not found."} | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def set_code_repositories | ||||||||||||||||||||||||||||||
@workspaces = @bitbucket_integration.workspaces || [] | ||||||||||||||||||||||||||||||
workspace = params[:workspace] || @workspaces.first | ||||||||||||||||||||||||||||||
@code_repositories = @bitbucket_integration.repos(workspace) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def parsed_bitbucket_config_params | ||||||||||||||||||||||||||||||
bitbucket_config_params = params.require(:bitbucket_integration) | ||||||||||||||||||||||||||||||
.permit(:repository_config, :workspace) | ||||||||||||||||||||||||||||||
bitbucket_config_params.merge( | ||||||||||||||||||||||||||||||
repository_config: bitbucket_config_params[:repository_config]&.safe_json_parse | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
Comment on lines
+48
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard against clearing repository_config on partial updates Avoid merging a nil repository_config when the field isn’t submitted. Apply this diff: def parsed_bitbucket_config_params
- bitbucket_config_params = params.require(:bitbucket_integration)
- .permit(:repository_config, :workspace)
- bitbucket_config_params.merge(
- repository_config: bitbucket_config_params[:repository_config]&.safe_json_parse
- )
+ p = params.require(:bitbucket_integration).permit(:repository_config, :workspace)
+ if p.key?(:repository_config)
+ p[:repository_config] = p[:repository_config]&.safe_json_parse
+ end
+ p
end 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||
end |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,53 @@ | ||||||||||||||||||||||||||
class CiCd::BitriseConfigsController < SignedInApplicationController | ||||||||||||||||||||||||||
using RefinedString | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
before_action :require_write_access! | ||||||||||||||||||||||||||
before_action :set_app | ||||||||||||||||||||||||||
before_action :set_bitrise_integration | ||||||||||||||||||||||||||
around_action :set_time_zone | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def edit | ||||||||||||||||||||||||||
set_ci_cd_projects | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
respond_to do |format| | ||||||||||||||||||||||||||
format.html do |variant| | ||||||||||||||||||||||||||
variant.turbo_frame { render :edit } | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def update | ||||||||||||||||||||||||||
if @bitrise_integration.update(parsed_bitrise_config_params) | ||||||||||||||||||||||||||
redirect_to app_path(@app), notice: t(".success") | ||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||
redirect_back fallback_location: app_integrations_path(@app), | ||||||||||||||||||||||||||
flash: {error: @bitrise_integration.errors.full_messages.to_sentence} | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
private | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_app | ||||||||||||||||||||||||||
@app = current_organization.apps.friendly.find(params[:app_id]) | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_bitrise_integration | ||||||||||||||||||||||||||
@bitrise_integration = @app.ci_cd_provider | ||||||||||||||||||||||||||
unless @bitrise_integration.is_a?(BitriseIntegration) | ||||||||||||||||||||||||||
redirect_to app_integrations_path(@app), flash: {error: "CI/CD integration not found."} | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
Comment on lines
+34
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Type verification implemented, consider improving error message. The While this message is consistent with similar controllers (BitbucketConfigsController, GithubConfigsController), consider making it more specific to improve the user experience: def set_bitrise_integration
@bitrise_integration = @app.ci_cd_provider
unless @bitrise_integration.is_a?(BitriseIntegration)
- redirect_to app_integrations_path(@app), flash: {error: "CI/CD integration not found."}
+ redirect_to app_integrations_path(@app), flash: {error: "Bitrise integration not found or incorrect CI/CD provider configured."}
end
end 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def set_ci_cd_projects | ||||||||||||||||||||||||||
@ci_cd_apps = @bitrise_integration.setup | ||||||||||||||||||||||||||
@project_config = @bitrise_integration.project_config | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
Comment on lines
+41
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify error handling for setup call. The 🏁 Script executed: #!/bin/bash
# Verify if BitriseIntegration#setup can fail or return nil
# and check how @ci_cd_apps is used in the view
# Find the setup/list_apps implementation
ast-grep --pattern 'def setup
$$$
end'
# Find the view that uses @ci_cd_apps
fd -e erb bitrise_configs | xargs rg -n '@ci_cd_apps' -A 3 -B 1 Length of output: 6108 Inspect BitriseIntegration#list_apps implementation for error handling and return value: 🏁 Script executed: #!/bin/bash
rg -n 'def list_apps' -n app/models/bitrise_integration.rb -A10 -B5 Length of output: 482 Additional context from 🏁 Script executed: #!/bin/bash
rg -n 'class BitriseIntegration' -A5 -B0 app/models/bitrise_integration.rb
rg -n 'def installation' -A5 -B5 app/models/bitrise_integration.rb Length of output: 362 Add error handling around BitriseIntegration#setup. The call to 🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def parsed_bitrise_config_params | ||||||||||||||||||||||||||
bitrise_config_params = params.require(:bitrise_integration) | ||||||||||||||||||||||||||
.permit(:project_config) | ||||||||||||||||||||||||||
bitrise_config_params.merge( | ||||||||||||||||||||||||||
project_config: bitrise_config_params[:project_config]&.safe_json_parse | ||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
Comment on lines
+46
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JSON parsing silently fails on invalid input. The Consider adding validation to detect and report JSON parsing failures, or at minimum, logging when parsing fails to aid debugging. Note: This pattern is consistent with similar controllers (BitbucketConfigsController, GithubConfigsController), suggesting this might be intentional behavior across the codebase. 🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Use a keyword for pre_open_category to avoid positional arg mistakes.
Switch to a keyword to align with IntegrationListComponent and improve readability:
Update callers accordingly.
Run to find/adjust all call sites:
🏁 Script executed:
Length of output: 0
🏁 Script executed:
Length of output: 993
Convert initializer to keyword argument and update its callers
In app/components/integration_list_component.html.erb (line 8):
🤖 Prompt for AI Agents