Skip to content

Resolve conditional dependencies from tool_shed.yml for the Tool Shed - #23213

Merged
jmchilton merged 1 commit into
galaxyproject:devfrom
mvdbeek:toolshed_conditional_dependencies
Jul 30, 2026
Merged

Resolve conditional dependencies from tool_shed.yml for the Tool Shed#23213
jmchilton merged 1 commit into
galaxyproject:devfrom
mvdbeek:toolshed_conditional_dependencies

Conversation

@mvdbeek

@mvdbeek mvdbeek commented Jul 30, 2026

Copy link
Copy Markdown
Member

scripts/common_startup.sh resolves the conditional dependency set from galaxy.yml only:

set_galaxy_config_file_var   # find_config_file(['galaxy', 'universe_wsgi'])
GALAXY_CONDITIONAL_DEPENDENCIES=$(... galaxy.dependencies.optional('$GALAXY_CONFIG_FILE') ...)

run_tool_shed.sh goes through the same script, but never exports GALAXY_CONFIG_FILE, and ConditionalDependencies reads the galaxy: section besides. So on a Tool Shed host nothing in conditional-requirements.txt is ever installed or upgraded — those packages come from the deployment layer instead, outside the version bounds we declare here.

Before:

$ galaxy-dependencies -c tool_shed.yml --freeze   # tool_shed.yml sets sentry_dsn
Nothing to install

After:

$ galaxy-dependencies -c tool_shed.yml --app tool_shed --freeze
# generated with galaxy-dependencies
psycopg2-binary==2.9.10
sentry-sdk>=2.63.0

How this surfaced

toolshed.test returned 500 on every /api/users/current request:

File "fastapi/dependencies/models.py", line 21, in _unwrapped_call
    unwrapped = inspect.unwrap(_impartial(call))
File "inspect.py", line 791, in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
ValueError: wrapper loop when unwrapping <function FastAPIUsers.current at 0x7f179ef759e0>

FastAPI >= 0.137 rebuilds the route handler per request (APIRoute.handle calls request_response(self.get_route_handler()) for routes reached through an included router — which is all of ours). sentry-sdk's FastAPI integration replaces dependant.call with a functools.wraps-decorated wrapper for sync endpoints, so one __wrapped__ layer accumulates per request, and inspect.unwrap raises once the chain passes sys.getrecursionlimit() — roughly 987 requests, after which the endpoint stays broken until restart. wraps copies __qualname__, which is why the message names the endpoint while the address differs each time.

Fixed upstream in getsentry/sentry-python#6569, released in sentry-sdk 2.63.0, and pinned here in 5aabd48. That pin had no effect on the Tool Shed, for the reason above.

Changes

  • Split ConditionalDependencies into BaseConditionalDependencies — config loading, get_conditional_requirements, check, and the checks whose options every app schema defines (the three database drivers and sentry-sdk) — and the Galaxy subclass, which keeps everything driven by job conf, object stores, file sources, vault, OIDC and error reporters. ToolShedConditionalDependencies only sets config_section = "tool_shed"; Galaxy-only checks have no check_<name> method there and check() already treats that as "not needed", so there is no allowlist to keep in sync.
  • optional() takes an app argument backed by an APPS registry of class plus config-file names.
  • set_tool_shed_config_file_var in common_startup_functions.sh, factored out of the snippet run_tool_shed.sh already had; common_startup.sh picks the config file and app from GALAXY_CONDITIONAL_DEPENDENCIES_APP, which run_tool_shed.sh exports.
  • galaxy-dependencies --app, so a playbook can drive the Tool Shed install directly.

statsd stays Galaxy-only — statsd_host is not in the Tool Shed schema, unlike sentry_dsn and database_connection.

Note this does not by itself repair a running Tool Shed: the upgrade only happens the next time common_startup.sh runs with wheel fetching enabled.

Testing

Four cases added to test/unit/app/dependencies/test_deps.py: the tool_shed: section is read, the same file read as Galaxy selects nothing, Galaxy-only dependencies are skipped while the database driver is selected, and an unknown app is rejected. The Galaxy path returns an unchanged set.

common_startup.sh resolved only galaxy.yml, so a Tool Shed deployment
installed nothing from conditional-requirements.txt. That is why the
sentry-sdk>=2.63.0 pin never reached toolshed.test, which kept an older
sentry-sdk and hit the FastAPI >= 0.137 wrapper-loop crash: sentry
re-wraps dependant.call on every request there, and inspect.unwrap
raises once the chain passes the recursion limit.

Move the machinery and the app-agnostic checks into
BaseConditionalDependencies so the Tool Shed evaluates the database
driver and sentry-sdk checks against its own config section, and let
run_tool_shed.sh select it with GALAXY_CONDITIONAL_DEPENDENCIES_APP.
Galaxy-only checks stay on ConditionalDependencies, where check() keeps
treating a missing check_<name> method as "not needed".
@github-actions github-actions Bot added this to the 26.2 milestone Jul 30, 2026
@jmchilton
jmchilton merged commit 979bb99 into galaxyproject:dev Jul 30, 2026
59 of 60 checks passed
@github-project-automation github-project-automation Bot moved this from Needs Review to Done in Galaxy Dev - weeklies Jul 30, 2026
@github-actions

Copy link
Copy Markdown

This PR was merged without a "kind/" label, please correct.

@nsoranzo
nsoranzo deleted the toolshed_conditional_dependencies branch July 30, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

3 participants