Class: Mysigner::Upload::AppStoreAutomation

Inherits:
Object
  • Object
show all
Defined in:
lib/mysigner/upload/app_store_automation.rb

Defined Under Namespace

Classes: AutomationError

Constant Summary collapse

DEFAULT_WAIT_TIMEOUT =

15 minutes

900
DEFAULT_POLL_INTERVAL =
15

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client:, organization_id:, opts: {}) ⇒ AppStoreAutomation

Returns a new instance of AppStoreAutomation.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/mysigner/upload/app_store_automation.rb', line 13

def initialize(client:, organization_id:, opts: {})
  @client = client
  @organization_id = organization_id
  # Proper boolean coercion — `!x.nil?` evaluates to `true` for `false`,
  # which previously caused `wait: false` / `no_submit: false` to be
  # treated as `true`. Use `!!` to get the actual boolean semantics.
  @wait_enabled = opts.key?(:wait) ? !opts[:wait].nil? : true

  poll = opts[:poll_interval] || opts[:poll_seconds]
  poll = poll.to_i if poll
  @poll_interval = poll&.positive? ? poll : DEFAULT_POLL_INTERVAL

  timeout = opts[:timeout] || opts[:timeout_seconds]
  timeout = timeout.to_i if timeout
  @timeout = timeout&.positive? ? timeout : DEFAULT_WAIT_TIMEOUT

  @no_submit = !opts[:no_submit].nil?

  # Whether to submit by default when NEITHER cli_defaults nor CLI
  # overrides specify `auto_submit`. `ship`/`submit` pass true (it's
  # the user's explicit intent). Dashboard `cli_defaults.auto_submit`
  # still wins if set — we only fall back to this when silent.
  @default_submit = opts.key?(:default_submit) ? !opts[:default_submit].nil? : false

  @now = opts[:now]
end

Instance Attribute Details

#no_submitObject (readonly)

Returns the value of attribute no_submit.



11
12
13
# File 'lib/mysigner/upload/app_store_automation.rb', line 11

def no_submit
  @no_submit
end

#poll_intervalObject (readonly)

Returns the value of attribute poll_interval.



11
12
13
# File 'lib/mysigner/upload/app_store_automation.rb', line 11

def poll_interval
  @poll_interval
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



11
12
13
# File 'lib/mysigner/upload/app_store_automation.rb', line 11

def timeout
  @timeout
end

#wait_enabledObject (readonly)

Returns the value of attribute wait_enabled.



11
12
13
# File 'lib/mysigner/upload/app_store_automation.rb', line 11

def wait_enabled
  @wait_enabled
end

Instance Method Details

#perform!(metadata:, build_info:, metadata_overrides: {}) ⇒ Object

Raises:



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/mysigner/upload/app_store_automation.rb', line 40

def perform!(metadata:, build_info:, metadata_overrides: {})
  build_info = symbolize_keys(build_info)
   ||= {}

  result = {
    wait: {
      enabled: @wait_enabled,
      poll_seconds: @poll_interval,
      timeout_seconds: @timeout,
      timed_out: false,
      elapsed_seconds: 0,
      last_state: nil
    },
    submitted: false,
    skip_reason: nil,
    submission_source: nil
  }

  puts ''
  puts '🤖 App Store automation in progress...'
  puts ''

  app = ensure_app(build_info[:bundle_id])
  raise AutomationError, "App with bundle ID #{build_info[:bundle_id]} not found" unless app

  build, wait_status = wait_for_build(app['id'], build_info)
  result[:wait].merge!(wait_status)

  unless build
    version_info = [build_info[:version], build_info[:build_number]].compact.join(' / ')
    version_info = "for #{version_info}" unless version_info.empty?
    raise AutomationError,
          "No processed build found #{version_info}. Upload a build first with 'mysigner ship appstore --wait'"
  end

  unless build_processed?(build)
    raise AutomationError,
          "Build #{build_info[:version]} (#{build_info[:build_number]}) is still processing. Wait for it or use --wait flag."
  end

  version = ensure_app_store_version(app_id: app['id'], metadata: , overrides: )
  attach_build_to_version(version_id: version['id'], build_id: build['id'])

  should_submit, submit_source, skip_reason = should_submit_with_reason(, )

  if should_submit
    submit_for_review(
      version_id: version['id'],
      version_string: version['version_string'],
      metadata: ,
      overrides: 
    )
    puts '✓ Submitted for App Store review'
    result[:submitted] = true
    result[:submission_source] = submit_source
  else
    puts "💡 Skipping automatic submission (#{skip_reason})"
    result[:skip_reason] = skip_reason
  end

  puts ''
  puts '✅ App Store automation complete'

  result
end