Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1201 from Shopify/feature/determine-argo-renderer…
Browse files Browse the repository at this point in the history
…-dynamically

Determine Argo Renderer Dynamically
  • Loading branch information
t6d authored May 1, 2021
2 parents 86389a9 + ce3046d commit c7ca7a9
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 159 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased
------

* [1201](https://github.com/Shopify/shopify-app-cli/pull/1201) Determine Argo Renderer Dynamically. This fixes `shopify serve` and `shopify push` for extensions.

Version 1.9.0
-------------
* [1181](https://github.com/Shopify/shopify-app-cli/pull/1181): Remove the subcommand references of the `generate` command for node apps (fixes [1176](https://github.com/Shopify/shopify-app-cli/issues/1176))
Expand Down
2 changes: 2 additions & 0 deletions lib/project_types/extension/cli.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

module Extension
class PackageNotFound < RuntimeError; end

class Project < ShopifyCli::ProjectType
hidden_feature
title("App Extension")
Expand Down
56 changes: 17 additions & 39 deletions lib/project_types/extension/features/argo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class Argo
SCRIPT_PATH = %w(build main.js).freeze

NPM_LIST_COMMAND = %w(list).freeze
YARN_LIST_COMMAND = %w(list --pattern).freeze
NPM_LIST_PARAMETERS = %w(--prod).freeze
YARN_LIST_COMMAND = %w(list).freeze
NPM_LIST_PARAMETERS = %w(--prod --depth=1).freeze
YARN_LIST_PARAMETERS = %w(--production).freeze
private_constant :NPM_LIST_COMMAND, :YARN_LIST_COMMAND, :NPM_LIST_PARAMETERS, :YARN_LIST_PARAMETERS

Expand All @@ -39,7 +39,7 @@ def config(context)
context.abort(context.message("features.argo.missing_file_error")) unless File.exist?(filepath)
begin
{
renderer_version: extract_argo_renderer_version(context),
renderer_version: renderer_package(context).version,
serialized_script: Base64.strict_encode64(File.read(filepath).chomp),
}
rescue StandardError
Expand All @@ -48,50 +48,28 @@ def config(context)
end

def renderer_package(context)
Features::ArgoRendererPackage.new(
package_name: renderer_package_name, version: extract_argo_renderer_version(context)
)
end

private

def extract_argo_renderer_version(context)
result = run_list_command(context)
found_version = find_version_number(context, result)
context.abort(
context.message("features.argo.dependencies.argo_renderer_package_invalid_version_error")
) if found_version.nil?
::Semantic::Version.new(found_version).to_s
rescue ArgumentError
Features::ArgoRendererPackage.from_package_manager(run_list_command(context))
rescue Extension::PackageNotFound
context.abort(
context.message("features.argo.dependencies.argo_renderer_package_invalid_version_error")
context.message("features.argo.dependencies.argo_missing_renderer_package_error")
)
end

def find_version_number(context, result)
packages = result.to_json.split('\n')
found_package = packages.find do |package|
package.match(/#{renderer_package_name}@/)
end
if found_package.nil?
error = "'#{renderer_package_name}' not found."
context.abort(
context.message("features.argo.dependencies.argo_missing_renderer_package_error", error)
)
end
found_package.split("@")[2]&.strip
end
private

def run_list_command(context)
js_system = ShopifyCli::JsSystem.new(ctx: context)
result, error, status = js_system.call(
yarn: YARN_LIST_COMMAND + [renderer_package_name] + YARN_LIST_PARAMETERS,
npm: NPM_LIST_COMMAND + [renderer_package_name] + NPM_LIST_PARAMETERS,
yarn_list = YARN_LIST_COMMAND + YARN_LIST_PARAMETERS
npm_list = NPM_LIST_COMMAND + NPM_LIST_PARAMETERS

result, error, status = ShopifyCli::JsSystem.call(
context,
yarn: yarn_list,
npm: npm_list,
capture_response: true
)
context.abort(
context.message("features.argo.dependencies.argo_missing_renderer_package_error", error)
) unless status.success?
# context.abort(
# context.message("features.argo.dependencies.argo_missing_renderer_package_error", error)
# ) unless status.success?
result
end

Expand Down
19 changes: 17 additions & 2 deletions lib/project_types/extension/features/argo_renderer_package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@ class ArgoRendererPackage

ARGO_CHECKOUT = "@shopify/argo-checkout"
ARGO_ADMIN = "@shopify/argo-admin"
ARGO_POST_PURCHASE = "@shopify/argo-post-purchase"

PACKAGE_NAMES = [
ARGO_CHECKOUT,
ARGO_ADMIN,
ARGO_POST_PURCHASE
].freeze
MINIMUM_ARGO_VERSION = "0.9.3".freeze

property! :package_name, accepts: PACKAGE_NAMES
property! :version, accepts: String

class << self
def from_package_manager(package_manager_output)
pattern = /(?<name>#{PACKAGE_NAMES.join("|")})@(?<version>\d.*)$/
match = package_manager_output.match(pattern)
raise PackageNotFound, package_manager_output if match.nil?
return new(package_name: match[:name], version: match[:version].strip)
end
end

def checkout?
package_name == ARGO_CHECKOUT
end
Expand All @@ -23,9 +34,13 @@ def admin?
package_name == ARGO_ADMIN
end

##
# Temporarily returns false in all cases as the argo webpack server is
# unable to handle the UUID flag.
def supports_uuid_flag?
return false if checkout?
Gem::Version.new(version) > Gem::Version.new(MINIMUM_ARGO_VERSION)
return false
# return false if checkout?
# Gem::Version.new(version) > Gem::Version.new(MINIMUM_ARGO_VERSION)
end
end
end
Expand Down
5 changes: 1 addition & 4 deletions lib/project_types/extension/messages/messages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,7 @@ module Messages
node_not_installed: "Node must be installed to create this extension.",
version_too_low: "Your node version %s does not meet the minimum required version %s",
},
argo_missing_renderer_package_error: "%s Install the missing package and try again.",
argo_renderer_package_invalid_version_error: <<~MESSAGE,
The renderer package version is not a valid SemVer Version (http://semver.org)
MESSAGE
argo_missing_renderer_package_error: "Extension template references invalid renderer package please contact Shopify for help.",
yarn_install_error: "Something went wrong while running 'yarn install'. %s.",
yarn_run_script_error: "Something went wrong while running script. %s.",
},
Expand Down
4 changes: 2 additions & 2 deletions lib/shopify-cli/js_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def yarn?(ctx)
#
# ShopifyCli::JsSystem.call(ctx, yarn: ['install', '--silent'], npm: ['install', '--no-audit'])
#
def call(ctx, yarn:, npm:)
JsSystem.new(ctx: ctx).call(yarn: yarn, npm: npm)
def call(ctx, yarn:, npm:, capture_response: false)
JsSystem.new(ctx: ctx).call(yarn: yarn, npm: npm, capture_response: capture_response)
end
end

Expand Down
1 change: 1 addition & 0 deletions test/project_types/extension/commands/push_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
module Extension
module Commands
class PushTest < MiniTest::Test
include TestHelpers::FakeUI
include ExtensionTestHelpers::Messages

def setup
Expand Down
100 changes: 6 additions & 94 deletions test/project_types/extension/commands/serve_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,107 +5,19 @@
module Extension
module Commands
class ServeTest < MiniTest::Test
include TestHelpers::Partners
include TestHelpers::FakeUI
include ExtensionTestHelpers::TempProjectSetup

YARN_SERVE_COMMAND = %w(server)
NPM_SERVE_COMMAND = %w(run-script server)

def setup
super
stub_argo_enabled_shop
api_key = "TEST"
registration_uuid = "dev-123"
setup_temp_project(api_key: api_key, registration_uuid: registration_uuid)
@argo_version = "0.9.4"
serve_args = [
"--shop=my-test-shop.myshopify.com",
"--apiKey=#{api_key}",
"--argoVersion=#{@argo_version}",
"--uuid=#{registration_uuid}",
]
@yarn_serve_command = YARN_SERVE_COMMAND + serve_args
@npm_serve_command = NPM_SERVE_COMMAND + %w(--) + serve_args
end

def test_implements_help
ShopifyCli::ProjectType.load_type(:extension)
ShopifyCli::Shopifolk.stubs(:check).returns(false)
ShopifyCli::Feature.stubs(:enabled?).with(:argo_admin_beta).returns(false)

refute_empty(Serve.help)
end

def test_uses_js_system_to_run_npm_or_yarn_serve_commands
Extension::Features::Argo.any_instance.stubs(:extract_argo_renderer_version).returns(@argo_version)
ShopifyCli::JsSystem.any_instance
.expects(:call)
.with(yarn: @yarn_serve_command, npm: @npm_serve_command)
.returns(true)
.once

run_serve
end

def test_aborts_and_informs_the_user_when_serve_fails
Extension::Features::Argo.any_instance.stubs(:extract_argo_renderer_version).returns(@argo_version)
ShopifyCli::JsSystem.any_instance
.expects(:call)
.with(yarn: @yarn_serve_command, npm: @npm_serve_command)
.returns(false)
.once
@context.expects(:abort).with(@context.message("serve.serve_failure_message"))

run_serve
end

def test_uses_js_system_to_run_npm_or_yarn_serve_commands_with_shop_argument_for_first_party
Extension::Features::Argo.any_instance.stubs(:extract_argo_renderer_version).returns(@argo_version)
ShopifyCli::JsSystem.any_instance
.expects(:call)
.with(yarn: @yarn_serve_command, npm: @npm_serve_command)
.returns(true)
.once

run_serve
end

def test_raises_exception_if_shop_is_empty
ExtensionProject.stubs(:reload)

ExtensionProject.current.env.stubs(:shop).returns(" ")

exception = assert_raises ShopifyCli::Abort do
run_serve
end
assert_includes exception.message, @context.message("serve.serve_missing_information")
end

def test_raises_exception_if_api_key_is_empty
ExtensionProject.stubs(:reload)

ExtensionProject.current.env.stubs(:api_key).returns(" ")

exception = assert_raises ShopifyCli::Abort do
run_serve
end
assert_includes exception.message, @context.message("serve.serve_missing_information")
end

private

def run_serve(*args)
Serve.ctx = @context
Serve.call(args, "serve")
ShopifyCli::ProjectType.load_type("extension")
setup_temp_project
end

def stub_argo_enabled_shop
ShopifyCli::Shopifolk.stubs(:check).returns(true)
ShopifyCli::Feature.stubs(:enabled?).with(:argo_admin_beta).returns(true)
ShopifyCli::Tasks::EnsureEnv.stubs(:call)
ShopifyCli::Tasks::EnsureDevStore.stubs(:call)
Extension::Features::Argo.any_instance.stubs(:extract_argo_renderer_version).returns(@argo_version)
def test_defers_serving_to_the_specification_handler
serve = ::Extension::Commands::Serve.new(@context)
serve.specification_handler.expects(:serve)
serve.call([], "serve")
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@ module Extension
module ExtensionTestHelpers
class DummyArgo < Extension::Features::Argo
GIT_TEMPLATE = "https://something"
RENDERER_PACKAGE = "@test-renderer-package"
RENDERER_PACKAGE = "@shopify/argo-admin"
private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE

property :fake_renderer_package, accepts: Features::ArgoRendererPackage

def git_template
GIT_TEMPLATE
end

def renderer_package_name
RENDERER_PACKAGE
end

def renderer_version=(renderer_version)
self.fake_renderer_package = Features::ArgoRendererPackage.new(
package_name: renderer_package_name,
version: renderer_version
)
end

def renderer_package(context)
fake_renderer_package || super(context)
end
end
end
end
Loading

0 comments on commit c7ca7a9

Please sign in to comment.