Class: Mysigner::Build::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/mysigner/build/parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_info) ⇒ Parser

Returns a new instance of Parser.



10
11
12
13
# File 'lib/mysigner/build/parser.rb', line 10

def initialize(project_info)
  @project_info = project_info
  @project = open_project
end

Instance Attribute Details

#projectObject (readonly)

Returns the value of attribute project.



8
9
10
# File 'lib/mysigner/build/parser.rb', line 8

def project
  @project
end

#project_infoObject (readonly)

Returns the value of attribute project_info.



8
9
10
# File 'lib/mysigner/build/parser.rb', line 8

def project_info
  @project_info
end

Instance Method Details

#all_app_targetsObject

Get all app + extension targets (everything that needs signing)



43
44
45
# File 'lib/mysigner/build/parser.rb', line 43

def all_app_targets
  app_targets + extension_targets
end

#app_targetsObject

Get all application targets (main apps only, no extensions)



21
22
23
24
25
# File 'lib/mysigner/build/parser.rb', line 21

def app_targets
  @project.targets.select do |target|
    target.product_type == 'com.apple.product-type.application'
  end
end

#build_settings(target_name = nil, configuration = 'Release') ⇒ Object

Get build settings for a target and configuration



117
118
119
120
121
122
123
124
# File 'lib/mysigner/build/parser.rb', line 117

def build_settings(target_name = nil, configuration = 'Release')
  target = find_target(target_name)
  config = target.build_configurations.find { |c| c.name == configuration }

  raise "Configuration '#{configuration}' not found" unless config

  config.build_settings
end

#bundle_id(target_name = nil, configuration = 'Release') ⇒ Object

Get bundle identifier



127
128
129
130
# File 'lib/mysigner/build/parser.rb', line 127

def bundle_id(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['PRODUCT_BUNDLE_IDENTIFIER']
end

#code_sign_identity(target_name = nil, configuration = 'Release') ⇒ Object

Get code sign identity



139
140
141
142
# File 'lib/mysigner/build/parser.rb', line 139

def code_sign_identity(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['CODE_SIGN_IDENTITY']
end

#code_sign_style(target_name = nil, configuration = 'Release') ⇒ Object

Get code sign style (Automatic or Manual)



151
152
153
154
# File 'lib/mysigner/build/parser.rb', line 151

def code_sign_style(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['CODE_SIGN_STYLE']
end

#configurations(target_name = nil) ⇒ Object

Get all configurations



157
158
159
160
# File 'lib/mysigner/build/parser.rb', line 157

def configurations(target_name = nil)
  target = find_target(target_name)
  target.build_configurations.map(&:name)
end

#extension_targetsObject

Get all extension targets (widgets, share extensions, etc.)



34
35
36
37
38
39
40
# File 'lib/mysigner/build/parser.rb', line 34

def extension_targets
  @project.targets.select do |target|
    target.product_type&.include?('app-extension') ||
      target.product_type&.include?('widget-extension') ||
      target.product_type == 'com.apple.product-type.watchkit2-extension'
  end
end

#find_target(target_name) ⇒ Object

Find a target by name (public method for use by other classes)



177
178
179
180
181
182
183
184
# File 'lib/mysigner/build/parser.rb', line 177

def find_target(target_name)
  return main_target if target_name.nil?

  target = @project.targets.find { |t| t.name == target_name }
  raise "Target '#{target_name}' not found" unless target

  target
end

#has_extensions?Boolean

Check if project has extensions

Returns:

  • (Boolean)


48
49
50
# File 'lib/mysigner/build/parser.rb', line 48

def has_extensions?
  extension_targets.any?
end

#has_multiple_apps?Boolean

Check if project has multiple apps

Returns:

  • (Boolean)


53
54
55
# File 'lib/mysigner/build/parser.rb', line 53

def has_multiple_apps?
  app_targets.count > 1
end

#main_targetObject

Get main app target (exclude test targets, extensions, etc.)



28
29
30
31
# File 'lib/mysigner/build/parser.rb', line 28

def main_target
  # Return first app target, or first target if no app targets found
  app_targets.first || @project.targets.first
end

#open_projectObject



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/mysigner/build/parser.rb', line 186

def open_project
  if @project_info[:type] == :workspace
    # Workspace contains multiple projects
    # Get the main project (not Pods)
    workspace = Xcodeproj::Workspace.new_from_xcworkspace(@project_info[:path])

    project_ref = workspace.file_references.find do |ref|
      !ref.path.include?('Pods') && ref.path.end_with?('.xcodeproj')
    end

    raise 'No main project found in workspace' unless project_ref

    project_path = File.join(File.dirname(@project_info[:path]), project_ref.path)
    Xcodeproj::Project.open(project_path)
  else
    Xcodeproj::Project.open(@project_info[:path])
  end
end

#product_name(target_name = nil, configuration = 'Release') ⇒ Object

Get product name



171
172
173
174
# File 'lib/mysigner/build/parser.rb', line 171

def product_name(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['PRODUCT_NAME'] || find_target(target_name).name
end

#product_type(target_name = nil) ⇒ Object

Detect product type (app, framework, library)



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/mysigner/build/parser.rb', line 92

def product_type(target_name = nil)
  target = find_target(target_name)

  case target.product_type
  when 'com.apple.product-type.application'
    :app
  when /framework/
    :framework
  when /library/
    :library
  when /app-extension/
    :extension
  else
    :unknown
  end
end

#provisioning_profile(target_name = nil, configuration = 'Release') ⇒ Object

Get provisioning profile specifier



145
146
147
148
# File 'lib/mysigner/build/parser.rb', line 145

def provisioning_profile(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['PROVISIONING_PROFILE_SPECIFIER']
end

#schemesObject

Get schemes (simplified - assume scheme name matches target name)



110
111
112
113
114
# File 'lib/mysigner/build/parser.rb', line 110

def schemes
  # In reality, schemes are in xcshareddata/xcschemes/
  # For now, return target names as potential schemes
  targets
end

#signable_targets(configuration = 'Release') ⇒ Object

Get a list of all signable targets with their info



73
74
75
76
77
# File 'lib/mysigner/build/parser.rb', line 73

def signable_targets(configuration = 'Release')
  all_app_targets.map do |target|
    target_info(target.name, configuration)
  end
end

#signing_configured?(target_name = nil, configuration = 'Release') ⇒ Boolean

Check if signing is configured

Returns:

  • (Boolean)


163
164
165
166
167
168
# File 'lib/mysigner/build/parser.rb', line 163

def signing_configured?(target_name = nil, configuration = 'Release')
  profile = provisioning_profile(target_name, configuration)
  identity = code_sign_identity(target_name, configuration)

  !profile.to_s.empty? && !identity.to_s.empty?
end

#target_info(target_name, configuration = 'Release') ⇒ Object

Get detailed info about a target



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/mysigner/build/parser.rb', line 58

def target_info(target_name, configuration = 'Release')
  target = find_target(target_name)

  {
    name: target.name,
    type: product_type(target_name),
    platform: target_platform(target_name),
    bundle_id: bundle_id(target_name, configuration),
    team_id: team_id(target_name, configuration),
    signing_style: code_sign_style(target_name, configuration),
    product_type: target.product_type
  }
end

#target_platform(target_name = nil) ⇒ Object

Detect target platform (iOS, macOS, tvOS, watchOS)



80
81
82
83
84
85
86
87
88
89
# File 'lib/mysigner/build/parser.rb', line 80

def target_platform(target_name = nil)
  target = find_target(target_name)
  sdk = target.sdk

  return :macos if sdk&.include?('macosx')
  return :tvos if sdk&.include?('appletvos')
  return :watchos if sdk&.include?('watchos')

  :ios # default
end

#targetsObject

Get all target names



16
17
18
# File 'lib/mysigner/build/parser.rb', line 16

def targets
  @project.targets.map(&:name)
end

#team_id(target_name = nil, configuration = 'Release') ⇒ Object

Get development team



133
134
135
136
# File 'lib/mysigner/build/parser.rb', line 133

def team_id(target_name = nil, configuration = 'Release')
  settings = build_settings(target_name, configuration)
  settings['DEVELOPMENT_TEAM']
end