diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb
index 245e227144..1704c8ba86 100644
--- a/app/controllers/workflows_controller.rb
+++ b/app/controllers/workflows_controller.rb
@@ -355,7 +355,7 @@ def workflow_params
{ creator_ids: [] }, { assay_assets_attributes: [:assay_id] },
{ publication_ids: [] }, { presentation_ids: [] }, { document_ids: [] }, { data_file_ids: [] }, { sop_ids: [] },
{ workflow_data_files_attributes:[:id, :data_file_id, :workflow_data_file_relationship_id, :_destroy] },
- :internals, :maturity_level, :source_link_url,
+ :internals, :maturity_level, :source_link_url, :execution_instance_url,
{ topic_annotations: [] }, { operation_annotations: [] },
{ discussion_links_attributes: [:id, :url, :label, :_destroy] },
{ git_version_attributes: [:name, :comment, :ref, :commit, :root_path,
diff --git a/app/helpers/workflows_helper.rb b/app/helpers/workflows_helper.rb
index a447ff61e1..7136b79d5b 100644
--- a/app/helpers/workflows_helper.rb
+++ b/app/helpers/workflows_helper.rb
@@ -77,12 +77,6 @@ def test_status_badge(resource)
end
end
- def run_workflow_url(workflow_version)
- if workflow_version.workflow_class_title == 'Galaxy'
- "#{Seek::Config.galaxy_instance_trs_import_url}&trs_id=#{workflow_version.parent.id}&trs_version=#{workflow_version.version}"
- end
- end
-
def workflow_class_options_for_select(selected = nil)
opts = WorkflowClass.order(:title).map do |c|
extra = {}
diff --git a/app/models/asset_link.rb b/app/models/asset_link.rb
index 3970f4866c..82b1e37b1b 100644
--- a/app/models/asset_link.rb
+++ b/app/models/asset_link.rb
@@ -1,6 +1,7 @@
class AssetLink < ApplicationRecord
DISCUSSION = 'discussion'.freeze
SOURCE = 'source'.freeze
+ EXECUTION_INSTANCE = 'execution_instance'.freeze
MISC_LINKS = 'misc'.freeze
scope :discussion, -> { where(link_type: AssetLink::DISCUSSION) }
diff --git a/app/models/concerns/workflow_extraction.rb b/app/models/concerns/workflow_extraction.rb
index f4c612b952..a9cf9ed027 100644
--- a/app/models/concerns/workflow_extraction.rb
+++ b/app/models/concerns/workflow_extraction.rb
@@ -58,7 +58,23 @@ def structure
delegate :inputs, :outputs, :steps, to: :structure
def can_run?
- can_download?(nil) && workflow_class_title == 'Galaxy' && Seek::Config.galaxy_instance_trs_import_url.present?
+ can_download?(nil) && workflow_class&.executable? && run_url.present?
+ end
+
+ def run_url
+ if workflow_class&.key == 'galaxy'
+ base = execution_instance_url || Seek::Config.galaxy_instance_default
+ return if base.nil?
+
+ parent_id = is_a_version? ? parent.id : id
+ url = URI(base) + 'workflows/trs_import'
+ params = {
+ trs_url: Seek::Util.routes.ga4gh_trs_v2_tool_version_url(parent_id, version_id: version),
+ run_form: true
+ }
+ url.query = URI.encode_www_form(params)
+ url.to_s
+ end
end
def diagram_exists?
diff --git a/app/models/git/blob.rb b/app/models/git/blob.rb
index b8dcd7cbc9..5f91335ce3 100644
--- a/app/models/git/blob.rb
+++ b/app/models/git/blob.rb
@@ -10,12 +10,16 @@ class Blob
delegate :read, :rewind, to: :file
attr_reader :git_version, :path
+ # Flag to decide if `read`ing this blob should eagerly fetch any remote content pointed to by this blob's `url`.
+ attr_accessor :fetch_remote
+
alias_method :original_filename, :path
def initialize(git_version, blob, path)
@git_version = git_version
@blob = blob
@path = path
+ @fetch_remote = false
end
def annotations
@@ -26,7 +30,7 @@ def url
git_version.remote_sources[path]
end
- def file(fetch_remote: false)
+ def file(fetch_remote: @fetch_remote)
@file ||= to_tempfile(fetch_remote: fetch_remote)
end
@@ -34,7 +38,7 @@ def binread
file_contents
end
- def file_contents(as_text: false, fetch_remote: false, &block)
+ def file_contents(as_text: false, fetch_remote: @fetch_remote, &block)
if fetch_remote && remote? && !fetched?
if block_given?
block.call(remote_content)
@@ -92,13 +96,17 @@ def text_contents_for_search
def remote_content
return unless remote?
- handler = ContentBlob.remote_content_handler_for(url)
+ handler = remote_content_handler
return unless handler
io = handler.fetch
io.rewind
io
end
+ def remote_content_handler
+ ContentBlob.remote_content_handler_for(url)
+ end
+
def cache_key
"#{git_repository.cache_key}/blobs/#{oid}"
end
@@ -134,7 +142,7 @@ def is_text?
private
- def to_tempfile(fetch_remote: false)
+ def to_tempfile(fetch_remote: @fetch_remote)
f = Tempfile.new(path)
f.binmode if binary?
f << file_contents(as_text: !binary?, fetch_remote: fetch_remote)
diff --git a/app/models/workflow.rb b/app/models/workflow.rb
index 18bd0ff54b..eede3c2f6a 100644
--- a/app/models/workflow.rb
+++ b/app/models/workflow.rb
@@ -30,6 +30,9 @@ class Workflow < ApplicationRecord
accepts_nested_attributes_for :workflow_data_files
+ has_one :execution_instance, -> { where(link_type: AssetLink::EXECUTION_INSTANCE) },
+ class_name: 'AssetLink', as: :asset, dependent: :destroy, inverse_of: :asset, autosave: true
+
def initialize(*args)
@extraction_errors = []
@extraction_warnings = []
@@ -131,6 +134,10 @@ def source_link_url
parent&.source_link&.url
end
+ def execution_instance_url
+ parent&.execution_instance&.url
+ end
+
def submit_to_life_monitor
LifeMonitorSubmissionJob.perform_later(self)
end
@@ -237,6 +244,18 @@ def update_test_status(status, ver = version)
v.save!
end
+ def execution_instance_url= url
+ (execution_instance || build_execution_instance).assign_attributes(url: url)
+
+ execution_instance.mark_for_destruction if url.blank?
+
+ url
+ end
+
+ def execution_instance_url
+ execution_instance&.url
+ end
+
has_filter maturity: Seek::Filtering::Filter.new(
value_field: 'maturity_level',
label_mapping: ->(values) {
diff --git a/app/models/workflow_class.rb b/app/models/workflow_class.rb
index 915b88c320..21507f2575 100644
--- a/app/models/workflow_class.rb
+++ b/app/models/workflow_class.rb
@@ -20,6 +20,10 @@ def extractable?
extractor.present?
end
+ def executable?
+ key == 'galaxy'
+ end
+
def self.extractable
where.not(extractor: nil)
end
diff --git a/app/views/assets/_asset_buttons.html.erb b/app/views/assets/_asset_buttons.html.erb
index fead830f7c..9d26ddbc7f 100644
--- a/app/views/assets/_asset_buttons.html.erb
+++ b/app/views/assets/_asset_buttons.html.erb
@@ -36,7 +36,7 @@
<%= button_link_to('Download RO Crate', 'ro_crate_file', ro_crate_workflow_path(asset, version: version, code: params[:code]),
'data-tooltip' => tooltip("The Workflow RO-Crate is a package containing the workflow definition, its metadata and supporting resources like test data")) %>
<% if asset.can_run? %>
- <%= button_link_to("Run on #{Seek::Config.galaxy_instance_name || 'Galaxy'}", 'run_galaxy', run_workflow_url(display_asset)) %>
+ <%= button_link_to("Run on Galaxy", 'run_galaxy', display_asset.run_url) %>
<% end %>
<% else %>
<%= button_link_to('Download RO-Crate', 'ro_crate_file', nil,
diff --git a/app/views/workflows/edit.html.erb b/app/views/workflows/edit.html.erb
index 060296b5e2..ef6e2a52ae 100644
--- a/app/views/workflows/edit.html.erb
+++ b/app/views/workflows/edit.html.erb
@@ -18,6 +18,14 @@
<%= f.text_area :description, rows: 5, class: 'form-control rich-text-edit' -%>
+ <% if @workflow.workflow_class&.executable? %>
+
+ <% end %>
+
<%= f.text_field :source_link_url, placeholder: 'https://...', class: 'form-control' -%>
diff --git a/app/views/workflows/provide_metadata.html.erb b/app/views/workflows/provide_metadata.html.erb
index efa5bf2053..840f8371ee 100644
--- a/app/views/workflows/provide_metadata.html.erb
+++ b/app/views/workflows/provide_metadata.html.erb
@@ -45,6 +45,14 @@
<%= text_area_tag 'workflow[description]', @workflow.description, class: "form-control rich-text-edit" -%>
+ <% if @workflow.workflow_class&.executable? %>
+
+ <% end %>
+
<%= text_field_tag 'workflow[source_link_url]', @workflow.source_link_url, placeholder: 'https://...', class: "form-control" -%>
diff --git a/config/initializers/seek_testing.rb b/config/initializers/seek_testing.rb
index 0d41997c13..c2abfb51bb 100644
--- a/config/initializers/seek_testing.rb
+++ b/config/initializers/seek_testing.rb
@@ -139,5 +139,6 @@ def load_seek_testing_defaults!
Settings.defaults[:git_support_enabled] = true
Settings.defaults[:fair_signposting_enabled] = true
Settings.defaults[:bio_tools_enabled] = true
+ Settings.defaults[:galaxy_instance_default] = 'https://usegalaxy.eu'
end
end
diff --git a/config/routes.rb b/config/routes.rb
index d0a3054d4c..67aa9cd4e9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,7 +16,7 @@
get 'tools' => 'tools#index'
get 'tools/:id' => 'tools#show'
get 'tools/:id/versions' => 'tool_versions#index'
- get 'tools/:id/versions/:version_id' => 'tool_versions#show'
+ get 'tools/:id/versions/:version_id' => 'tool_versions#show', as: :tool_version
get 'tools/:id/versions/:version_id/containerfile' => 'tool_versions#containerfile'
get 'tools/:id/versions/:version_id/:type/descriptor(/*relative_path)' => 'tool_versions#descriptor', constraints: { relative_path: /.+/ }, format: false, as: :tool_versions_descriptor
get 'tools/:id/versions/:version_id/:type/files' => 'tool_versions#files', format: false
diff --git a/lib/seek/config_setting_attributes.yml b/lib/seek/config_setting_attributes.yml
index 6cff135b3f..a026837c8b 100644
--- a/lib/seek/config_setting_attributes.yml
+++ b/lib/seek/config_setting_attributes.yml
@@ -240,8 +240,8 @@ life_monitor_url:
life_monitor_client_id:
life_monitor_client_secret:
life_monitor_ui_url:
-galaxy_instance_name:
-galaxy_instance_trs_import_url:
+galaxy_instance_default:
+galaxy_instance_trs_server:
# Controlled vocabs
cv_dropdown_limit:
convert: :to_i
diff --git a/lib/seek/download_handling/galaxy_http_handler.rb b/lib/seek/download_handling/galaxy_http_handler.rb
index 52cd276e72..d8ecfbc612 100644
--- a/lib/seek/download_handling/galaxy_http_handler.rb
+++ b/lib/seek/download_handling/galaxy_http_handler.rb
@@ -10,11 +10,20 @@ module DownloadHandling
class GalaxyHTTPHandler < Seek::DownloadHandling::HTTPHandler
attr_reader :galaxy_host, :workflow_id
- def initialize(url, fallback_to_get: true)
- uri = URI(url)
+ URL_PATTERNS = [
+ /(.+)\/api\/workflows\/([^\/]+)\/download\?format=json-download/, # Download
+ /(.+)\/workflows\/run\?id=([^&]+)/, # Run
+ /(.+)\/published\/workflow\?id=([^&]+)/, # View
+ ].freeze
- @galaxy_host = URI(url.split(/\/workflows?\//).first + '/')
- @workflow_id = CGI.parse(uri.query)['id'].first
+ def initialize(url, fallback_to_get: true)
+ URL_PATTERNS.each do |pattern|
+ matches = url.match(pattern)
+ if matches
+ @galaxy_host = matches[1].chomp('/') + '/'
+ @workflow_id = matches[2]
+ end
+ end
super(download_url, fallback_to_get: fallback_to_get)
end
@@ -26,21 +35,24 @@ def info
end
def display_url
- URI.join(galaxy_host, "workflow/display_by_id?id=#{workflow_id}").to_s
+ URI.join(galaxy_host, "published/workflow?id=#{workflow_id}").to_s
end
def download_url
- URI.join(galaxy_host, "workflow/export_to_file?id=#{workflow_id}").to_s
+ URI.join(galaxy_host, "api/workflows/#{workflow_id}/download?format=json-download").to_s
end
- # Note that the path is `/workflows/` (plural) here for some reason.
def run_url
URI.join(galaxy_host, "workflows/run?id=#{workflow_id}").to_s
end
+ def execution_instance_url
+ galaxy_host.to_s
+ end
+
def self.is_galaxy_workflow_url?(uri)
- uri.hostname.include?('galaxy') && (uri.path.include?('/workflow/') || uri.path.include?('/workflows/')) &&
- uri.query.present? && CGI.parse(uri.query)&.key?('id')
+ string_uri = uri.to_s
+ uri.hostname.include?('galaxy') && URL_PATTERNS.any? { |pattern| string_uri.match?(pattern) }
end
end
end
diff --git a/lib/seek/workflow_extractors/base.rb b/lib/seek/workflow_extractors/base.rb
index f4adf4177e..7d0b14fc91 100644
--- a/lib/seek/workflow_extractors/base.rb
+++ b/lib/seek/workflow_extractors/base.rb
@@ -12,7 +12,13 @@ def initialize(io)
end
def metadata
- { }
+ m = {}
+
+ if @io.respond_to?(:remote_content_handler)
+ m.merge!(extract_source_metadata(@io.remote_content_handler))
+ end
+
+ m
end
def has_tests?
@@ -84,6 +90,24 @@ def extract_author(obj)
author
end
+
+ def extract_source_metadata(handler)
+ m = {}
+ return m unless handler
+ source_url = nil
+ if handler.respond_to?(:repository_url)
+ source_url = handler.repository_url
+ elsif handler.respond_to?(:display_url)
+ source_url = handler.display_url
+ end
+ m[:source_link_url] = source_url
+
+ if handler.respond_to?(:execution_instance_url)
+ m[:execution_instance_url] = handler.execution_instance_url
+ end
+
+ m
+ end
end
end
end
diff --git a/lib/seek/workflow_extractors/cff.rb b/lib/seek/workflow_extractors/cff.rb
index 1312b2911b..271efdf2a8 100644
--- a/lib/seek/workflow_extractors/cff.rb
+++ b/lib/seek/workflow_extractors/cff.rb
@@ -6,7 +6,7 @@ class CFF
FILENAME = 'CITATION.cff'
def initialize(io)
- if io.respond_to?(:path)
+ if io.respond_to?(:path) && !io.is_a?(Git::Blob)
@path = io.path
else
f = Tempfile.new('cff')
diff --git a/lib/seek/workflow_extractors/galaxy.rb b/lib/seek/workflow_extractors/galaxy.rb
index aef35386c3..af0ccd3680 100644
--- a/lib/seek/workflow_extractors/galaxy.rb
+++ b/lib/seek/workflow_extractors/galaxy.rb
@@ -8,6 +8,7 @@ def self.file_extensions
end
def metadata
+ metadata = super
galaxy_string = @io.read
f = Tempfile.new('ga')
f.binmode
@@ -21,13 +22,13 @@ def metadata
end
cf.rewind
if status.success?
- metadata = Seek::WorkflowExtractors::CWL.new(cf).metadata
+ metadata.merge!(Seek::WorkflowExtractors::CWL.new(cf).metadata)
else
- metadata = super
metadata[:warnings] ||= []
metadata[:warnings] << 'Unable to convert workflow to CWL, some metadata may be missing.'
Rails.logger.error("Galaxy -> CWL conversion failed. Error was: #{err}")
end
+
galaxy = JSON.parse(galaxy_string)
if galaxy.has_key?('name')
diff --git a/lib/seek/workflow_extractors/git_repo.rb b/lib/seek/workflow_extractors/git_repo.rb
index 41370140d8..b5f0d1d472 100644
--- a/lib/seek/workflow_extractors/git_repo.rb
+++ b/lib/seek/workflow_extractors/git_repo.rb
@@ -32,7 +32,7 @@ def file_exists?(path)
end
def file(path)
- @obj.get_blob(path)&.file(fetch_remote: true)
+ @obj.get_blob(path)&.tap { |blob| blob.fetch_remote = true }
end
def licensee_project
diff --git a/lib/seek/workflow_extractors/knime.rb b/lib/seek/workflow_extractors/knime.rb
index dfddac054b..6a15e00100 100644
--- a/lib/seek/workflow_extractors/knime.rb
+++ b/lib/seek/workflow_extractors/knime.rb
@@ -8,7 +8,7 @@ def self.file_extensions
def metadata
metadata = super
- metadata.merge(parse_internal_workflow(extract_workflow))
+ metadata.merge!(parse_internal_workflow(extract_workflow))
metadata
end
diff --git a/lib/seek/workflow_extractors/ro_crate.rb b/lib/seek/workflow_extractors/ro_crate.rb
index 5f2567dfbc..33fbde69d4 100644
--- a/lib/seek/workflow_extractors/ro_crate.rb
+++ b/lib/seek/workflow_extractors/ro_crate.rb
@@ -105,16 +105,11 @@ def metadata_from_crate(crate, m)
end
end
- source_url = crate['isBasedOn'] || crate['url'] || crate.main_workflow['url']
- if source_url
- handler = ContentBlob.remote_content_handler_for(source_url)
- if handler.respond_to?(:repository_url)
- source_url = handler.repository_url
- elsif handler.respond_to?(:display_url)
- source_url = handler.display_url
+ source_url = crate['isBasedOn'] || crate['url'] || crate.main_workflow['url']
+ if source_url
+ m.merge!(extract_source_metadata(ContentBlob.remote_content_handler_for(source_url)))
+ m[:source_link_url] ||= source_url # Use plain source URL if handler doesn't have something more appropriate
end
- m[:source_link_url] = source_url
- end
m
end
diff --git a/lib/seek/workflow_extractors/ro_like.rb b/lib/seek/workflow_extractors/ro_like.rb
index 04bba108cd..65eefe744e 100644
--- a/lib/seek/workflow_extractors/ro_like.rb
+++ b/lib/seek/workflow_extractors/ro_like.rb
@@ -36,24 +36,27 @@ def generate_diagram
end
def metadata
+ m = super
# Use CWL description
- m = if abstract_cwl_extractor
- begin
- abstract_cwl_extractor.metadata
- rescue StandardError => e
- Rails.logger.error('Error extracting abstract CWL:')
- Rails.logger.error(e)
- { errors: ["Couldn't parse abstract CWL"] }
- end
- else
- begin
- main_workflow_extractor.metadata
- rescue StandardError => e
- Rails.logger.error('Error extracting workflow:')
- Rails.logger.error(e)
- { errors: ["Couldn't parse main workflow"] }
- end
- end
+ if abstract_cwl_extractor
+ begin
+ m.merge!(abstract_cwl_extractor.metadata)
+ rescue StandardError => e
+ Rails.logger.error('Error extracting abstract CWL:')
+ Rails.logger.error(e)
+ m[:errors] ||= []
+ m[:errors] << "Couldn't parse abstract CWL"
+ end
+ else
+ begin
+ m.merge!(main_workflow_extractor.metadata)
+ rescue StandardError => e
+ Rails.logger.error('Error extracting workflow:')
+ Rails.logger.error(e)
+ m[:errors] ||= []
+ m[:errors] << "Couldn't parse main workflow"
+ end
+ end
if file_exists?('README.md')
m[:description] ||= file('README.md').read.force_encoding('utf-8').gsub(/^(---\s*\n.*?\n?)^(---\s*$\n?)/m,'') # Remove "Front matter"
diff --git a/test/functional/content_blobs_controller_test.rb b/test/functional/content_blobs_controller_test.rb
index 5e9b8e32c1..da4b367bd6 100644
--- a/test/functional/content_blobs_controller_test.rb
+++ b/test/functional/content_blobs_controller_test.rb
@@ -94,7 +94,7 @@ def setup
test 'examine url to galaxy instance works with the various workflow endpoints' do
stub_request(:any, 'https://galaxy-instance.biz/banana/workflows/run?id=123').to_return(status: 200)
- stub_request(:any, 'https://galaxy-instance.biz/banana/workflow/export_to_file?id=123').to_return(
+ stub_request(:any, 'https://galaxy-instance.biz/banana/api/workflows/123/download?format=json-download').to_return(
body: File.new("#{Rails.root}/test/fixtures/files/workflows/1-PreProcessing.ga"),
status: 200,
headers: { 'Content-Length' => 40296,
@@ -109,14 +109,14 @@ def setup
assert_equal 'galaxy', assigns(:type)
assert_equal '123', assigns(:info)[:workflow_id]
assert_equal 'https://galaxy-instance.biz/banana/', assigns(:info)[:galaxy_host].to_s
- assert_equal 'https://galaxy-instance.biz/banana/workflow/display_by_id?id=123', assigns(:info)[:display_url]
+ assert_equal 'https://galaxy-instance.biz/banana/published/workflow?id=123', assigns(:info)[:display_url]
assert_equal 40296, assigns(:info)[:file_size]
assert_equal '1-PreProcessing.ga', assigns(:info)[:file_name]
}
suite.call('https://galaxy-instance.biz/banana/workflows/run?id=123')
- suite.call('https://galaxy-instance.biz/banana/workflow/export_to_file?id=123')
- suite.call('https://galaxy-instance.biz/banana/workflow/display_by_id?id=123')
+ suite.call('https://galaxy-instance.biz/banana/api/workflows/123/download?format=json-download')
+ suite.call('https://galaxy-instance.biz/banana/published/workflow?id=123')
end
test 'examine url does not crash when examining galaxy-like URL' do
diff --git a/test/functional/internationalization_test.rb b/test/functional/internationalization_error_test.rb
similarity index 98%
rename from test/functional/internationalization_test.rb
rename to test/functional/internationalization_error_test.rb
index 3979c810f7..27a4d093cd 100644
--- a/test/functional/internationalization_test.rb
+++ b/test/functional/internationalization_error_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class InternationalizationTest < ActionController::TestCase
+class InternationalizationErrorTest < ActionController::TestCase
include AuthenticatedTestHelper
diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb
index ce332e0750..845f75d45e 100644
--- a/test/functional/workflows_controller_test.rb
+++ b/test/functional/workflows_controller_test.rb
@@ -1775,4 +1775,28 @@ def bad_generator.write_graph(struct)
assert flash[:error].include?('disabled')
end
end
+
+ test 'shows run button for galaxy workflows using default galaxy endpoint' do
+ workflow = FactoryBot.create(:existing_galaxy_ro_crate_workflow, policy: FactoryBot.create(:public_policy))
+
+ get :show, params: { id: workflow.id }
+
+ assert workflow.can_run?
+ assert_equal 'https://usegalaxy.eu', Seek::Config.galaxy_instance_default
+ trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{workflow.id}/versions/1")
+ assert_select 'a.btn[href=?]', "https://usegalaxy.eu/workflows/trs_import?trs_url=#{trs_url}&run_form=true",
+ { text: 'Run on Galaxy' }
+ end
+
+ test 'shows run button for galaxy workflows using specified galaxy endpoint' do
+ workflow = FactoryBot.create(:existing_galaxy_ro_crate_workflow, policy: FactoryBot.create(:public_policy),
+ execution_instance_url: 'https://galaxygalaxy.org/mygalaxy/')
+
+ get :show, params: { id: workflow.id }
+
+ assert workflow.can_run?
+ trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{workflow.id}/versions/1")
+ assert_select 'a.btn[href=?]', "https://galaxygalaxy.org/mygalaxy/workflows/trs_import?trs_url=#{trs_url}&run_form=true",
+ { text: 'Run on Galaxy' }
+ end
end
diff --git a/test/integration/fair_signposting_test.rb b/test/integration/fair_signposting_test.rb
index 8f85c788c6..af8ba74f17 100644
--- a/test/integration/fair_signposting_test.rb
+++ b/test/integration/fair_signposting_test.rb
@@ -106,7 +106,7 @@ class FairSignpostingTest < ActionDispatch::IntegrationTest
end
test 'fair signposting for home' do
- get root_path(p)
+ get root_path
assert_response :success
links = parse_link_header
@@ -133,7 +133,7 @@ class FairSignpostingTest < ActionDispatch::IntegrationTest
end
test 'fair signposting for privacy page' do
- get privacy_home_path(p)
+ get privacy_home_path
assert_response :success
assert_nil response.headers['Link'], 'Should not have any signposting links'
diff --git a/test/integration/git_workflow_creation_test.rb b/test/integration/git_workflow_creation_test.rb
index 4c56ec0d72..4464baa93d 100644
--- a/test/integration/git_workflow_creation_test.rb
+++ b/test/integration/git_workflow_creation_test.rb
@@ -313,6 +313,87 @@ class GitWorkflowCreationTest < ActionDispatch::IntegrationTest
assert_select '#extraction-errors ul li', text: /Couldn't parse main workflow/
end
+ test 'can extract source metadata using original URL for galaxy workflow' do
+ mock_remote_file "#{Rails.root}/test/fixtures/files/workflows/1-PreProcessing.ga",
+ 'http://galaxy.instance/api/workflows/abcdxyz/download?format=json-download',
+ { 'content-disposition' => 'attachment; filename="1-PreProcessing.ga"'}
+
+ repo_count = Git::Repository.count
+ workflow_count = Workflow.count
+ version_count = Git::Version.count
+ annotation_count = Git::Annotation.count
+
+ person = FactoryBot.create(:person)
+ galaxy = WorkflowClass.find_by_key('galaxy') || FactoryBot.create(:galaxy_workflow_class)
+ login_as(person.user)
+
+ get new_workflow_path
+
+ assert_enqueued_jobs(0) do
+ assert_difference('Git::Repository.count', 1) do
+ assert_no_difference('Task.count') do
+ post create_from_files_workflows_path, params: {
+ ro_crate: {
+ main_workflow: { data_url: 'http://galaxy.instance/workflows/run?id=abcdxyz' },
+ },
+ workflow_class_id: galaxy.id
+ } # Should go to metadata page...
+ end
+ end
+ end
+
+ repo = assigns(:workflow).git_version.git_repository
+ assert_select 'input[name="workflow[title]"]', count: 1
+ a = assigns(:workflow).git_version.remote_source_annotations
+ assert_equal 1, a.length
+ assert_equal 'http://galaxy.instance/workflows/run?id=abcdxyz', a.first.value
+ assert_equal '1-PreProcessing.ga', a.first.path
+ assert_equal 'http://galaxy.instance/', assigns(:workflow).execution_instance_url
+ assert_select '#workflow_execution_instance_url[value=?]', 'http://galaxy.instance/'
+
+ assert_difference('Workflow.count', 1) do
+ assert_difference('Git::Version.count', 1) do
+ # 2 annotations = Main WF path, 1x remote source
+ assert_difference('Git::Annotation.count', 2) do
+ post create_metadata_workflows_path, params: {
+ workflow: {
+ workflow_class_id: galaxy.id,
+ title: 'blabla',
+ execution_instance_url: 'http://galaxy.instance/',
+ project_ids: [person.projects.first.id],
+ git_version_attributes: {
+ root_path: '/',
+ git_repository_id: repo.id,
+ ref: 'refs/heads/master',
+ main_workflow_path: '1-PreProcessing.ga',
+ remote_sources: {
+ '1-PreProcessing.ga' => 'http://galaxy.instance/workflows/run?id=abcdxyz'
+ }
+ }
+ }
+ } # Should go to workflow page...
+ end
+ end
+ end
+
+ assert_redirected_to workflow_path(assigns(:workflow))
+
+ assert assigns(:workflow).latest_git_version.commit.present?
+ assert_equal 'refs/heads/master', assigns(:workflow).latest_git_version.ref
+ refute assigns(:workflow).latest_git_version.git_repository.remote?
+ assert_equal assigns(:workflow), assigns(:workflow).latest_git_version.git_repository.resource
+ assert assigns(:workflow).latest_git_version.get_blob('1-PreProcessing.ga').remote?
+ assert_equal({ '1-PreProcessing.ga' => 'http://galaxy.instance/workflows/run?id=abcdxyz' },
+ assigns(:workflow).latest_git_version.remote_sources)
+ assert_equal 'http://galaxy.instance/', assigns(:workflow).latest_git_version.execution_instance_url
+
+ # Check there wasn't anything extra created in the whole flow...
+ assert_equal repo_count + 1, Git::Repository.count
+ assert_equal workflow_count + 1, Workflow.count
+ assert_equal version_count + 1, Git::Version.count
+ assert_equal annotation_count + 2, Git::Annotation.count
+ end
+
private
def login_as(user)
diff --git a/test/integration/isa_exporter_test.rb b/test/integration/isa_exporter_compliance_test.rb
similarity index 99%
rename from test/integration/isa_exporter_test.rb
rename to test/integration/isa_exporter_compliance_test.rb
index 84c5a6662f..9981c94b22 100644
--- a/test/integration/isa_exporter_test.rb
+++ b/test/integration/isa_exporter_compliance_test.rb
@@ -2,7 +2,7 @@
require 'json'
require 'json-schema'
-class IsaExporterTest < ActionDispatch::IntegrationTest
+class IsaExporterComplianceTest < ActionDispatch::IntegrationTest
fixtures :all
include SharingFormTestHelper
diff --git a/test/unit/git/git_blob_test.rb b/test/unit/git/git_blob_test.rb
index f906466fc5..b6d767c765 100644
--- a/test/unit/git/git_blob_test.rb
+++ b/test/unit/git/git_blob_test.rb
@@ -59,6 +59,21 @@ class GitBlobTest < ActiveSupport::TestCase
remote_blob.file_contents(fetch_remote: true) do |c|
assert_equal 'lit', c.read(3)
end
+
+ # fetch_remote
+ refute remote_blob.fetch_remote
+ assert_equal 0, remote_blob.size
+ assert_equal 0, remote_blob.file_contents.size
+ remote_blob.file_contents do |c|
+ assert_nil c.read(1)
+ end
+
+ remote_blob.fetch_remote = true
+ assert remote_blob.fetch_remote
+ assert_equal 11, remote_blob.file_contents.size
+ remote_blob.file_contents do |c|
+ assert_equal 'lit', c.read(3)
+ end
end
test 'fetched remote blob' do
diff --git a/test/unit/workflow_extraction/galaxy_extraction_test.rb b/test/unit/workflow_extraction/galaxy_extraction_test.rb
index 42ad004569..0851b06431 100644
--- a/test/unit/workflow_extraction/galaxy_extraction_test.rb
+++ b/test/unit/workflow_extraction/galaxy_extraction_test.rb
@@ -74,4 +74,21 @@ class GalaxyExtractionTest < ActiveSupport::TestCase
assert_equal [{ bio_tools_id: 'multiqc', name: 'MultiQC' }], metadata[:tools_attributes]
end
+
+ test 'extracts execution instance URL' do
+ mock_remote_file "#{Rails.root}/test/fixtures/files/workflows/1-PreProcessing.ga",
+ 'http://galaxy.instance/api/workflows/abcdxyz/download?format=json-download'
+ git_version = FactoryBot.create(:git_version)
+ disable_authorization_checks do
+ git_version.add_remote_file('1-PreProcessing.ga', 'http://galaxy.instance/published/workflow?id=abcdxyz')
+ git_version.fetch_remote_file('1-PreProcessing.ga')
+ git_version.save!
+ end
+ remote_blob = git_version.get_blob('1-PreProcessing.ga')
+
+ extractor = Seek::WorkflowExtractors::Galaxy.new(remote_blob)
+ metadata = extractor.metadata
+
+ assert_equal 'http://galaxy.instance/', metadata[:execution_instance_url]
+ end
end
diff --git a/test/unit/workflow_test.rb b/test/unit/workflow_test.rb
index 94480af0f6..3bc0455299 100644
--- a/test/unit/workflow_test.rb
+++ b/test/unit/workflow_test.rb
@@ -116,7 +116,6 @@ class WorkflowTest < ActiveSupport::TestCase
end
assert_equal 'https://github.com/seek4science/cool-workflow', workflow.source_link_url
- assert_equal 'https://github.com/seek4science/cool-workflow', workflow.source_link.url
end
test 'can clear source URL' do
@@ -133,6 +132,7 @@ class WorkflowTest < ActiveSupport::TestCase
end
assert_nil workflow.reload.source_link
+ assert_nil workflow.reload.source_link_url
end
test 'generates RO-Crate and diagram for workflow/abstract workflow' do
@@ -817,4 +817,72 @@ def bad_generator.write_graph(struct)
assert_nil workflow.maturity_level
end
end
+
+ test 'can get and set execution instance URL' do
+ workflow = FactoryBot.create(:workflow)
+
+ assert_no_difference('AssetLink.count') do
+ workflow.execution_instance_url = 'https://mygalaxy.instance/'
+ end
+
+ assert_difference('AssetLink.count', 1) do
+ disable_authorization_checks { workflow.save! }
+ end
+
+ assert_equal 'https://mygalaxy.instance/', workflow.execution_instance_url
+ end
+
+ test 'can clear execution instance URL' do
+ workflow = FactoryBot.create(:workflow, execution_instance_url: 'https://mygalaxy.instance/')
+ assert workflow.execution_instance
+ assert workflow.execution_instance_url
+
+ assert_no_difference('AssetLink.count') do
+ workflow.execution_instance_url = nil
+ end
+
+ assert_difference('AssetLink.count', -1) do
+ disable_authorization_checks { workflow.save! }
+ end
+
+ assert_nil workflow.reload.execution_instance
+ assert_nil workflow.reload.execution_instance_url
+ end
+
+ test 'can_run?' do
+ assert FactoryBot.create(:generated_galaxy_ro_crate_workflow, policy: FactoryBot.create(:public_policy)).can_run?
+ assert FactoryBot.create(:generated_galaxy_ro_crate_workflow, policy: FactoryBot.create(:public_policy), execution_instance_url: 'https://mygalaxy.instance/').can_run?
+ refute FactoryBot.create(:generated_galaxy_ro_crate_workflow, policy: FactoryBot.create(:private_policy)).can_run?
+ refute FactoryBot.create(:cwl_workflow, policy: FactoryBot.create(:public_policy)).can_run?
+ end
+
+ test 'run_url' do
+ # Using default
+ with_config_value(:galaxy_instance_default, 'http://default-galaxy-instance.com') do
+ default = FactoryBot.create(:generated_galaxy_ro_crate_workflow)
+ trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{default.id}/versions/1")
+ assert_equal "http://default-galaxy-instance.com/workflows/trs_import?trs_url=#{trs_url}&run_form=true", default.run_url
+ end
+
+ # With explicit execution instance
+ workflow = FactoryBot.create(:generated_galaxy_ro_crate_workflow, execution_instance_url: 'https://mygalaxy.instance/')
+ trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{workflow.id}/versions/1")
+ assert_equal "https://mygalaxy.instance/workflows/trs_import?trs_url=#{trs_url}&run_form=true", workflow.run_url
+
+ # Versions
+ disable_authorization_checks do
+ workflow.save_as_new_version('new version')
+ end
+ v2_trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{workflow.id}/versions/2")
+ assert_equal "https://mygalaxy.instance/workflows/trs_import?trs_url=#{v2_trs_url}&run_form=true", workflow.run_url
+ assert_equal "https://mygalaxy.instance/workflows/trs_import?trs_url=#{trs_url}&run_form=true", workflow.find_version(1).run_url
+
+ # Galaxy instance with sub-URI
+ workflow = FactoryBot.create(:generated_galaxy_ro_crate_workflow, execution_instance_url: 'https://mygalaxy.instance/galaxy/')
+ trs_url = URI.encode_www_form_component("http://localhost:3000/ga4gh/trs/v2/tools/#{workflow.id}/versions/1")
+ assert_equal "https://mygalaxy.instance/galaxy/workflows/trs_import?trs_url=#{trs_url}&run_form=true", workflow.run_url
+
+ # Not supported for non-galaxy currently
+ assert_nil FactoryBot.create(:cwl_workflow, policy: FactoryBot.create(:public_policy)).run_url
+ end
end