Git Product home page Git Product logo

xcoder's Introduction

XCoder

No Longer Maintained

Unfortuantely, I just don't have the time to maintain Xcoder, and given there are so many other tools that do bits and peices of what xcoder does, it doesnt feel as needed any more.

Perhaps parts of xcoder (keychain, profile management) could be extracted into stand-along tools - take a more unix-y approach to managing tools.

If anyone wants to more actively maintain Xcoder, please contact me.

Description

Taking the pain out of scripting and automating xcode builds.

Xcoder is a ruby wrapper around various Xcode tools as well as providing project and workspace parsing and partial write support. Xcoder also supports manipulation of keychains, packaging and uploading artifacts to Testflight and provisioning profile management.

Full documentation can be found here: http://rayh.github.com/xcoder/

Requirements

Xcoder assumes you are using XCode 4.6 on Mountain Lion and ruby 1.9. You may have some degree of success with lesser versions, but they are not intentionally supported.

Example Usage

You will need to install the gem:

gem install xcoder

and then require the gem in your project/rakefile/etc

require 'xcoder'

Load a project

project = Xcode.project('MyProject')  # Can be the name, the file (e.g. MyProject.xcodeproj) or the path

Finding all projects from the current directory down

Xcode.find_projects.each {|p| puts p.name }

Find a configuration for a target on a project

config = Xcode.project(:MyProject).target(:Target).config(:Debug)	# returns an Xcode::Configuration object

Building a configuration

config = Xcode.project(:MyProject).target(:Target).config(:Debug)
builder = config.builder
builder.profile = 'Profiles/MyAdHoc.mobileprovision'	# This will remove old profiles and install the profile
builder.identity = 'iPhone Developer: Ray Hilton'		# The name of the identity to use to sign the IPA (optional)
builder.clean
builder.build
# Building uses the targets's default sdk, which you can override:
builder.build :sdk => :iphonesimulator

Working with Keychains

You will not normally need to worry about manipulating keychains unless you want to automate importing of certificates (in a CI system with many clients) or opening of specific keychains for different builds (the old two-certs-with-same-identity-name workaround).

You can either use the user's login keychain, another named keychain, or simply use a temporary keychain that will be blown away after the build.

Creating a temporary keychain

Xcode::Keychain.temp do |keychain|
	# import certs into the keychain
	# perform builds within this keychain's context
end	# Keychain is deleted

Or, you can create a temporary keychain that will be deleted when the process exits:

keychain = Xcode::Keychain.temp

Importing a certificate

You can import a certificate from a .p12 file into a keychain. Here we simply create a temporary keychain, import a certificate, set the identity onto the builder and then perform a build.

keychain.import 'Certs/MyCert.p12', 'mycertpassword'
builder.keychain = keychain						# Tell the builder to use the temp keychain
builder.identity = keychain.identities.first	# Get the first (only) identity name from the keychain

Packaging a built .app

After performing the above build, you can create a versioned, well named .ipa and .dSYM.zip

builder.package

This will produce something like: MyProject-Debug-1.0.ipa and MyProject-Debug-1.0.dSYM.zip

Incrementing the build number

config.info_plist do |info|
  info.version = info.version.to_i + 1
  info.save
end

Managing build numbers more efficiently

Based on our experience we suggest Versionomy to manage version numbers. Although the marketing version is usually set by hand on release, there are situations where it could be nice to have an incremental build number in the marketing version number as well. The following is an example that takes a marketing version number in the x.y.z format and increments the last part of it.

config.info_plist do |info|
  info.version = info.version.to_i + 1
  marketing_version = Versionomy.parse(info.marketing_version)
  info.marketing_version = marketing_version.bump(:tiny).to_s
  info.save
end

You can read more about Versionomy at their site

Working with workspaces

Loading workspaces can be done in a similar way to projects:

Xcode.workspaces.each do |w|
  w.describe								# prints a recursive description of the
											# structure of the workspace and its projects
end

Or, if you know the name:

workspace = Xcode.workspace('MyWorkspace')  # Can be the name, the file (e.g. MyWorkspace.xcworkspace) or the path

Schemes

There is basic support for schemes, you can enumerate them from a project like so:

project.schemes.each do |s|
  s.builder.build
end

Or, access them by name:

builder = project.scheme('MyScheme').builder

Note: The builder behaves the same as the builder for the target/config approach and will force xcodebuild to use the local build/ directory (as per xcode3) rather than a generated temporary directory in DerivedData. This may or may not be a good thing.

Note: Shared schemes and user (current logged in user) specific schemes are both loaded. They may share names and other similarities that make them hard to distinguish. Currently the priority loading order is shared schemes and then user specific schemes.

Provisioning profiles

The library provides a mechanism to install/uninstall a provisioning profile. This normally happens as part of a build (if a profile is provided to the builder, see above), but you can do this manually:

# installs profile into ~/Library
Xcode::ProvisioningProfile.new("Myprofile.mobileprovision").install

Or enumerate installed profiles:

Xcode::ProvisioningProfile.installed_profiles.each do |p|
	p.uninstall		# Removes the profile from ~/Library/
end

Deployment

The common output of this build/package process is to upload to Testflight. This is pretty simple with Xcoder:

# Optionally do this, saves doing it again and again
Xcode::Deploy::Testflight.defaults :api_token => 'some api token', :team_token => 'team token'

builder.deploy :testflight,
	:api_token 	=> API_TOKEN,
	:team_token => TEAM_TOKEN,
	:notes 		=> "some release notes",
  	:notify 	=> true,		# Whether to send a notification to users, default is true
  	:lists 		=> ["AList"]  	# The lists to distribute the build to

You can also optionally set the HTTP_PROXY environment variable.

Deploying to Amazon S3

You can upload the output ipa to an arbitrary buckey on S3

builder.deploy :s3,
	:bucket => "mybucket",
	:access_key_id => "access id",
	:secret_access_key => "access key",
	:dir => "options/path/within/bucket"

Deploying to a web server (SSH)

The output of the build/package process can be deployed to a remote web server. You can use SSH with the following syntax:

builder.deploy :ssh,
	:host => "mywebserver.com",
	:username => "myusername",
	:password => "mypassword",
	:dir => "/var/www/mywebserverpath",
	:base_url => "http://mywebserver.com/"

Deploying to a web server (FTP)

The output of the build/package process can be deployed to a remote web server. You can upload the files through FTP with the following syntax:

builder.deploy :ftp,
	:host => "ftp.mywebserver.com",
	:username => "myusername",
	:password => "mypassword",
	:dir => "/mywebserverpath",
	:base_url => "http://mywebserver.com/"

OCUnit to JUnit reports

You can invoke your test target/bundle from the builder

builder.test do |report|
	report.debug = false	# default false, set to true to see raw output from xcodebuild

	# The following is the default setup, you wouldnt normally need to do this unless
	# you want to add new formatters
	report.formatters = []
	report.add_formatter :junit, 'test-reports'	# Output JUnit format results to test-reports/
	report.add_formatter :stdout				# Output a simplified output to STDOUT
end

This will invoke the test target, capture the output and write the junit reports to the test-reports directory. Currently only junit is supported, although you can write your own formatter quite easily (for an example, look at Xcode::Test::Formatters::JunitFormatter).

Rake Tasks

Xcoder provides a rake task to assist with make it easier to perform common Xcode project actions from the command-line.

Within your Rakefile add the following:

require 'xcoder/rake_task'

Then define your Rake Task:

Xcode::RakeTask.new

By default this will generate rake tasks within the 'xcode' namespace for all the projects (within the current working directory), all their targets, and all their configs. This will also generate tasks for all of a projects schemes as well.

All names from the project, schemes, targets, and configs are remove
the camel-casing and replacing the cameling with underscores. Spaces
are replaced with dashes (-)

This will generate rake tasks that appear similar to the following:

  rake xcode:project-name:targetname:debug:build
  rake xcode:project-name:targetname:debug:clean
  # ...

You can specify a parameter to change the root rake namespace:

 Xcode::RakeTask.new :apple

 # Resulting Rake Tasks:
 # rake apple:project-name:targetname:debug:build
 # rake apple:project-name:targetname:debug:clean
 # ...

You can also supply a block to provide additional configuration to specify the folder to search for projects and the projects that should generate tasks for:

 Xcode::RakeTask.new :hudson do |xcoder|
   xcoder.directory = "projects"
   xcoder.projects = [ "Project Alpha", "Project Beta" ]
 end

 rake hudson:project-alpha:targetname:debug:build
 # ...

Guard provides the ability to launch commands when files changed. There is a guard-xcoder which allows you easily execute build actions whenever your project file changes.

gem install guard
gem install guard-xcoder

guard init
guard init xcoder

Afterwards you will need to define the project you want to monitor and the actions that you want to take place when a source files changes within the project file.

guard 'xcoder', :actions => [ :clean, :build, :test ] do
  watch('ProjectName')
  watch('ProjectName//TargetName')
end

Manipulating a Project

Xcoder can also create targets, configurations, and add files. Xcoder could be used to programmatically manipulate or install external sources into a project.

It is important to note that Xcode gets cranky when the Xcode project file is changed by external sources. This usually causes the project and schemes to reset or maybe even cause Xcode to crash. It is often best to close the project before manipulating it with Xcoder.

Add the source and header file to the project

# Copy the physical source files into the project path `Vendor/Reachability`
FileUtils.cp_r "examples/Reachability/Vendor", "spec/TestProject"

source_files = [ 'Vendor/Reachability/Reachability.m' , 'Vendor/Reachability/Reachability.h' ]

# Create and traverse to the group Reachability within the Vendor folder
project.group('Vendor/Reachability') do
 # Create files for each source file defined above
 source_files.each |source| create_file source }
end

Within the project file the groups in the path are created or found and then file references are added for the two specified source files. Xcoder only updates the logical project file, it does not copy physical files, that is done by the FileUtils.

Adding source file to the sources build phase of a target

source_file = project.file('Vendor/Reachability/Reachability.m')

project.target('TestProject').sources_build_phase do
  add_build_file source_file
end

Adding source files does not automatically include it in any of the built targets. That is done after you add the source file to the sources_build_phase. First we find the source file reference, select our target and then add it as a build file.

Adding a System Framework to the project and built in a target

cfnetwork_framework = project.frameworks_group.create_system_framework 'CFNetwork'

project.target('TestProject').framework_build_phase do
  add_build_file cfnetwork_framework
end

The CFNetwork.framework is added to the Frameworks group of the project and then added to the frameworks build phase.

Add additional build phases to a target

target.create_build_phases :copy_headers, :run_script

Configure the Release build settings of a target

release_config = target.config 'Release'
release_config.set 'ALWAYS_SEARCH_USER_PATHS', false

target.config 'Release' do |config|
  config.always_search_user_paths = false
  config.architectures = [ "$(ARCHS_STANDARD_32_BIT)", 'armv6' ]
  config.copy_phase_strip = true
  config.dead_code_stripping = false
  config.debug_information_format = "dwarf-with-dsym"
  config.c_language_standard = 'gnu99'
end

Configuration settings can be accessed through get, set, and append with their Xcode Build Names or through convenience methods generated for most of the build settings (property_name, property_name=, append_to_property_name). The entire list of property names can be found in the configuration.

Saving your changes!

project.save!

The saved file output is slightly different than what you normally see when you view a Xcode project file. Luckily, Xcode will fix the format of the file if you make any small changes to the project that requires it to save.

More Examples

Within the specs/integration folder there are more examples.

Tests

There are some basic RSpec tests in the project which I suspect /wont/ work on machines without my identity installed.

Currently these tests only assert the basic project file parsing and build code and do not perform file modification tests (e.g. for info plists) or provisioning profile/keychain importing

Automation and CI (BETA)

NOTE: This is only available in HEAD, you will need to install this gem from source to get this Buildspec support and the xcoder tool

This stuff is a work-in-progress and is subject to change.

Xcoder provides a simple mechanism to help with automating builds and CI. First, define a Buildspec file in the root of your project with contents like this:

# Assumes identity is first in keychain
group :adhoc do

  # Which project/target/config, or workspace/scheme to use
  use :MyProject, :target => :MyTarget, :config => :Release

  # The mobile provision that should be used
  profile 'Provisioning/MyProject_AdHoc.mobileprovision'

  # Keychain is option, allows isolation of identities per-project without
  # poluting global keychain
  keychain 'Provisioning/build.keychain', 'build'

  deploy :testflight,
    :api_token => 'api token',
    :team_token => 'team token',
    :notify => true,
    :lists => ['Internal'],
    :notes => `git log -n 1`
end

You can then invoke the project using the xcoder command line:

# Invoke the default task (deploy)
xcoder -r

# Invoke a specific task
xcoder -r adhoc:package

# Get a list of tasks
xcoder -T

This is a bit of a work-in-progress and an attempt to allow projects to provide a minimal declaration of how thier artifacts should be built and where they should go. Integration with CI (Jenkins, for example) or just running locally from the command line should be simple.

Feedback

Please raise issues if you find defects or have a feature request.

License

Xcoder is released under the MIT License. http://www.opensource.org/licenses/mit-license

xcoder's People

Contributors

arlol avatar blakewatters avatar ivanushakov avatar krohling avatar orj avatar patr1ck avatar quirkey avatar rayh avatar siuying avatar tanis2000 avatar torarnv avatar xslim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xcoder's Issues

Add ability to set provisioning profile name to builder, but not path to it.

I am need set to build provisioning profile, that already installed to system. In order not to change the project settings every time. I can find needed profile like this:

  Xcode::ProvisioningProfile.installed_profiles.each do |installed|
    if installed.name == "AdHoc"
      #builder.profile = installed;
    end
  end

But i'm not found ability to use its

Bug with xcode 6, Ruby 0.1.18 Certificate wrong

I can build iOS app with Ruby/Gem/xcoder 0.1.18 with xcode 5 (Xcloud).
When I update xcode 6, I can't use xcoder to build any app. This is issue:
"Code Sign error: No codesigning identities found: No codesigning identities (i.e. certificate and private key pairs) that match the provisioning profile specified in your build settings (“SimiCartDemo_InHouse”) were found".
I'm sure about both Certificate and provision file are correct. They were created by developer InHouse account, have not expired, the identify key is compatible with provision file.
I think there is a mistake when import certificate to keychain.
Can you help me. Thank you.

How to add external file to a project?

I wanted to copy a file (one zip) to the app base path when building it. The zip file is the input to the app. Is there a way to do it. I have tried adding the file on the sources_build_phase using the project.file 'MyStory.zip'. But it breaks. project.file 'MyStory.zip' always returns nil.

I am new to iOS development. So any help much appreciated.

when try to list all projects, got this syntax errors in xcoder

rake aborted!
/Library/Ruby/Gems/1.8/gems/xcoder-0.1.18/lib/xcode/scheme.rb:48: syntax error, unexpected ':', expecting ')'
... Xcode::Scheme.new(parent: parent, root: path, path: sch...
^
/Library/Ruby/Gems/1.8/gems/xcoder-0.1.18/lib/xcode/scheme.rb:48: syntax error, unexpected ':', expecting '='
...heme.new(parent: parent, root: path, path: scheme_path)
^
/Library/Ruby/Gems/1.8/gems/xcoder-0.1.18/lib/xcode/scheme.rb:48: syntax error, unexpected ':', expecting '='
...ent: parent, root: path, path: scheme_path)
^
/Library/Ruby/Gems/1.8/gems/xcoder-0.1.18/lib/xcode/scheme.rb:135: syntax error, unexpected $end, expecting kEND

OBJROOT and SYMROOT should be configurable

I have some static library dependencies that build relative to the build products (into ../../Headers actually). Because of the default behavior of forcing OBJROOT and SYMROOT = /build/, this results in a Headers/ dir being populated at the top of my project. This is not desirable. Should provide accessors on the builder object to enable overloading the objroot and symroot.

Unknown substitution variable $(PROJECT_NAME)

My PRODUCT_NAME is set to $(PROJECT_NAME). I get an error when trying to call clean:

$ bundle exec rake --trace clean
** Invoke clean (first_time)
** Invoke remove_build_dir (first_time)
** Execute remove_build_dir
rm -rf build
** Invoke ios:clean (first_time)
** Invoke init (first_time)
** Execute init
** Invoke remove_build_dir 
** Invoke load_project (first_time)
** Execute load_project
** Execute ios:clean
rake aborted!
Unknown substitution variable $(PROJECT_NAME)
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/configuration.rb:446:in `block in substitute'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/configuration.rb:441:in `gsub'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/configuration.rb:441:in `substitute'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/configuration.rb:98:in `block in property'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/configuration.rb:96:in `block in property'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/builder/base_builder.rb:282:in `product_name'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/xcoder-0.1.18/lib/xcode/builder/base_builder.rb:233:in `clean'
/Users/ArloLOK/Developer/CocoaLumberjackFramework/Rakefile:64:in `block (2 levels) in <top (required)>'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:236:in `call'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:236:in `block in execute'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:231:in `each'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:231:in `execute'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:175:in `block in invoke_with_call_chain'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:168:in `invoke_with_call_chain'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:197:in `block in invoke_prerequisites'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:195:in `each'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:195:in `invoke_prerequisites'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:174:in `block in invoke_with_call_chain'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:168:in `invoke_with_call_chain'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/task.rb:161:in `invoke'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:149:in `invoke_task'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:106:in `block (2 levels) in top_level'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:106:in `each'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:106:in `block in top_level'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:115:in `run_with_threads'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:100:in `top_level'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:78:in `block in run'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/lib/rake/application.rb:75:in `run'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/rake-10.1.0/bin/rake:33:in `<top (required)>'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/bin/rake:23:in `load'
/Users/ArloLOK/.rbenv/versions/1.9.3-p327/bin/rake:23:in `<main>'
Tasks: TOP => clean => ios:clean

Everything works fine when I don't use $(PROJECT_NAME) or with 0.1.15.

Can't manage to pass tests

I try to add a feature in this gem.
Unfortunately, i can't manage to pass the tests.
This what I did

  • clone the repo
  • bundle install => error while installing linecache19 (using ruby 2.0.0)

How do you use ruby-debug19, which stand for ruby 1.9.x with ruby 2.0.0 ?

I tried to use ruby 1.9.3-p392 (from the rbenv file), I've got many errors.

Any ideas?

Incorrect project path used when building Rakefile with 'xcoder/rake_task'

When requiring xcoder/rake_task and using Xcode::Raketask.new from within the project's root, the Rake task tries to load the project file from the wrong location.

Project git:develop ❯ rake -T                                                    ✭
rake aborted!
Failed to correctly parse the project file /Users/Josh/Dropbox/Development/Repos/Project/Project.xcodeproj/Project.xcodeproj/project.pbxproj

(See full trace by running task with --trace)

It seems to include the .xcodeproj file twice in the path it builds.

xcodeworkspace builder with cocoapods raising No such target PFK everytime

I am trying to build using cocoapods, to get builder through scheme I am doing

Xcode.workspace(''test.xcworkspace'').scheme('Test').builder

but in return I get No such target PFK, available targets are ............
don't know where and how it looks for PFK
I can get the project using workspace but that is of no use as that executes xcodebuild project command instead of workspace, I looked in to workspace.rb scheme method as well, seems that it isn't going there as the exception is saying target instead of scheme, I installed the gem from the HEAD

Structured approach to invoking command line

Such that:

  • Xcode is isolated from the idiosyncrasies of command line option escaping, etc
  • Third-parties can intercept and modify built in commands
  • Third-parties can create new commands within a particular build context (builder.rb)

Perhaps by introduction of a Xcode::Command class that encapsulates the command and its arguments that is then sent to the Xcode::Shell.execute() method.

Xcoder 0.1.1

It appears as though the gem only contains the bin and spec directory of the project.

Failure to Parse Root Node Crashes

So I recently switched between branches and wound up with a directory structure named Something.xcodeproj, but it contained no actual project data. This results a nasty crash when it tries to access the root node of the project, which was implicitly loaded via a directory scan of the pwd. It would probably make sense to rescue this exemption and log a warning that there is a malformed project file rather than crashing hard. I had to put debuggers and logging statements into the gem source to figure out wtf was going on.

dSYM filename

When using builder.package the generated file is in this format:

MyProject-Debug-1.0.dSYM.zip

but, standing to the jenkins testflight plugin documentation:

The path of the dSYM ZIP file(s) to upload to testflight. If not specified, for each IPA file found, a related '-dSYM.zip' file is searched for. If found it is added to the upload request as dsym parameter. Note: in the future this parameter will probably be removed and replaced with an optional argument to upload dSYM files or not.

Now it would be great if the generated file will follow that format, or if at least we can choose, or pass the delimiter as parameter in the script.

I know the filename can be specified in the plugin manually, or it can be renamed after, but this will help to have a very smoother integration.

WARNINGS on execution

/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:93: warning: already initialized constant OPT_TABLE
/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:1268: warning: already initialized constant S_IF_DOOR
/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:1498: warning: already initialized constant DIRECTORY_TERM
/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:1500: warning: already initialized constant SYSCASE
/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:1619: warning: already initialized constant LOW_METHODS
/Users/franklinwebber/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/FileUtils.rb:1625: warning: already initialized constant METHODS

Maybe, it's the fileutils library, but it's kicking out mad warning messages, yo!

Change the configuration before building

Hello everyone.

I know that this project is not supported anymore but maybe someone can help me.

I want to change the TARGETED_DEVICE_FAMILY before building a version. I found the property to change the value but when I build the version the targeted devices are not changed.

What I'm doing wrong?
Thank you for your help.

Example:

config = Xcode.project('MyProject.xcodeproj').target('Application').config('Debug')
config.targeted_device_family = :ipad
builder = config.builder
builder.build

OCUnit Report Refactoring Results in NoMethodError

The recent refactoring of the Report class has left an error case when testing beings. The issue is in the following code starting at line 20 within ocunit_parser.rb:

        def <<(piped_row)
          case piped_row.force_encoding("UTF-8")

            when /Test Suite '(\S+)'.*started at\s+(.*)/
              name = $1
              time = Time.parse($2)
              if name=~/\//
                @report.start
              else
                @report.add_suite name, time
              end

The issue is that when the regular expression matches and @report.start is invoked, there is no corresponding method. I have put together a basic spec and pull request that fixes it.

Keychain lock timeout

Problem

I have been moving a number of my projects over to using xcoder recently and it's all been going fine until I tried to move over our main project. Unfortunately we started to have problems with the ipa not being signed because of a 'user interaction problem' with the keychain.

After spending a few hours trying to nail down the problem I realized that the keychain that was being created was locking after 5 mins (which is the default behavior for a new keychain). This causes us problems because the app we are trying to build takes about 7-8 mins to build on our CI machine, so by the time it comes to sign the ipa the keychain is locked and we get the 'user interaction problem'.

Temporary Fix

A quick fix for this was adding these few simple lines to the rake task after creating the temp keychain:

keychain = Xcode::Keychain.temp
# Remove timeout lock for newly created keychain
cmd = Xcode::Shell::Command.new "security"
cmd << "set-keychain-settings"
cmd << "-u"
cmd << "\"#{keychain.path}\""
cmd.execute

This fix removed any timeout locks on the temp keychain and allowed the ipa to be signed with no further problems.

Feature Request

It would be a nice feature to be able to set the timeout on the keychain, or remove it completely for when users have larger projects.

References

keychain CLI documentation: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/security.1.html

provisioning_profile.rb shell command does not escape string properly

provisioning_profile.rb line 57 needs to be changed from Xcode::Shell.execute("cp #{self.path} #{self.install_path}") to Xcode::Shell.execute("cp \"#{self.path}\" #{self.install_path}") or something similar, or it won't be able to handle a path with (e.g.) white spaces in it

test method of Builder should accept SDK

I am adding xcoder based tasks for the @RestKit test suite. We have OS X and iOS targets, so I need to be able to provide the SDK as an argument to the test method (iphonesimulator is currently hardcoded).

supporting cocoapods with xcoder

Hi,
first thanks for the superb work you have done.

I just started using xcoder and everything worked like a breeze until I started using cocoapods.
Now it doesn't compile and complains:
ld: library not found for -lPods

Tried working through the workspace and get the project through it and it didn't work either,
Tried to build the pods project first and then my app and it broker earlier.

Is there a nice way to make these work together?

Build fails when using XCode 5 Icon Asset Catalogs

When I use asset catalogs for the project in XCode 5 and build the project with xcoder, the build fails.

It fails to copy over the info.plist file to the .ipa and while packaging another script looks for that file and tries to write to it but it fails because the info.plist file is not found there.

Can you please address this issue?

thanks,
Amogh

Test do not run

I'm using Xcoder to automate tests. I just create a new Xcode project with Test from template, and use Xcoder to run test, it return no result.

Look into the debug logs, following command line is executed:

xcodebuild -sdk iphonesimulator -project "/Users/siuying/Documents/workspace/testflight-uploader/spec/fixtures/projects/SampleApp2/SampleApp2.xcodeproj" -target "SampleApp2Tests" -configuration "Debug" OBJROOT="/Users/siuying/Documents/workspace/testflight-uploader/spec/fixtures/projects/SampleApp2/build/" SYMROOT="/Users/siuying/Documents/workspace/testflight-uploader/spec/fixtures/projects/SampleApp2/build/" TEST_AFTER_BUILD=YES

Try to run it on command line myself, i see following messages:

/bin/sh -c /Users/siuying/Documents/workspace/testflight-uploader/spec/fixtures/projects/SampleApp2/build/SampleApp2.build/Debug-iphonesimulator/SampleApp2Tests.build/Script-54F4F50E1536C2F000287878.sh
/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/Tools/RunPlatformUnitTests:95: warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).

I wonder if the change at #26 related to this. In my case, append TEST_HOST='' in the parameters fix the error, the test will run as expected.

I'm using XCode 4.3.2 4E2002

TestFlight Broken in 0.1.14

It seems like the changes to Shell.rb and the introduction of Command.rb broke the TestFlight integration class. The error seems to be that TestFlight.rb is still using the old Array method of constructing shell commands.

Add app id and profile type properties to ProvisioningProfile

This is more of a feature request.
It would be useful that the ProvisioningProfile object to have appid property (application-identifier from the mobileprovision file) and a way to know if it's an AdHoc or an AppStore profile. (I think this only applies to iOS provisioning profiles only).
A way to tell which one is it is by checking for the ProvisionedDevices key (the AppStore profile doesn't have this key).

Thanks

Additional builder operations

I have some code that I personally have monkeypatched onto Xcoder to provide support for running Cedar from a Builder object. I thought maybe Xcoder could implement some plugin system that could auto require gems with a prefixed name xcoder-.

I linked a branch I created awhile back that implements a rudimentary solution to this problem. I was wondering if you had any thoughts about allowing a more formal way to allow for additional tools. Whether we should just include them in the gem or talk about some plugin system.

If we did choose a plugin system I think that it would likely be a good idea to not have the plugins just monkey-patch like I have done and instead do something like a DSL that add's available tasks to the Builder's that are created.

Xcode::Builder.add_task :cedar do

      require 'tmpdir'

      cmd = BuildCommand.new

      # Similar to the xcoder gem these platform values and paths are hard-coded.
      # This is likely a poor choice and one that will get this little plugin
      # into some trouble when the iOS library upgrades.

      cmd << "DYLD_ROOT_PATH=\"/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk\""
      cmd << "IPHONE_SIMULATOR_ROOT=\"/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk\""

      tempHome = Dir.mktmpdir("Cedar")
      Dir.mkdir File.join(tempHome, "Documents")
      Dir.mkdir File.join(tempHome, "Library")
      Dir.mkdir File.join(tempHome, "Library/Preferences")
      Dir.mkdir File.join(tempHome, "Library/Caches")
      Dir.mkdir File.join(tempHome, "tmp")

      cmd << "CFFIXED_USER_HOME=#{tempHome}"
      cmd << "CEDAR_HEADLESS_SPECS=1"
      cmd << "CEDAR_REPORTER_CLASS=CDRColorizedReporter"
      cmd << "CEDAR_REPORTER_OPTS=nested"

      cmd << "\"#{@build_path}#{@config.name}-iphonesimulator/#{@target.name}.app/#{@target.name}\""
      cmd << "-RegisterForSystemEvents"

      yield cmd if block_given?

      Xcode::Shell.execute(cmd.to_a)

end

Info.plist preprocessor not working

I have set up Info.plist preprocessing using INFOPLIST_PREPROCESSOR_DEFINITIONS. It's working in Xcode, but when I try to build using xcoder, it's not preprocessing the Info.plist file so when it gets to code signing it says the bundle identifier doesn't match the provisioning profile.

My Rakefile was working before I enabled preprocessing.

From the terminal output (edited):

EXECUTE: xcodebuild -project "/Users/jim/foo/Foo.xcodeproj" -target "Foo" -config "Debug-Staging" -sdk iphoneos OBJROOT="/Users/jim/foo/build/" SYMROOT="/Users/jim/foo/build/" CODE_SIGN_IDENTITY="iPhone Developer: Jim Roepcke (foo)" PROVISIONING_PROFILE=foo

Any suggestions?

A failed test quit the ruby process?

To run a test on XCoder, i use following call:

builder.test

But, when the test completed with failure, the VM quit as per e7e9dc4

It would be helpful if we could use the test result:

result = builder.test
if result.failed?
  logger.warn "something bad happened!" 
else
  logger.info "everything is fine"
end

Maybe we can add the number of tests started/passed/failed into the result object too.

What do you think?

Setting TEST_HOST='' breaks Test Run

I've just forked the project and had to disable the configuration of TEST_HOST='' within the gem as it breaks my test run during execution. May want to consider disabling this or providing a configuration switch.

KIF Output Parser

Wanted to gauge interest in merging support for a KIF output formatter. We have a suite of KIF (http://github.com/square/KIF) scenarios for functionally testing out application and I have just configured xcoder to build it. Am working on installing into Jenkins for CI now. If I knocked out a parser for presenting KIF output in a format similar to the SenTest output, would there be interest in merging it?

xcoder - command not found

I'm getting

% xcoder
zsh: command not found: xcoder

I've installed xcoder gem using gem install xcoder, and also tried installing from latest source - same issue.

Non-ASCII Characters Breaks OCUnitReportParser

My test suite generates a number of NSError objects in tests without an NSLocalizedDescriptionKey configured for the userInfo of the NSError instance, which results in a default error message of "The operation couldn’t be completed. (Test error 0.)". The apostrophe within the text causes an exception to be raised during parsing:

#<ArgumentError: invalid byte sequence in US-ASCII>

TEST_HOST Override Prevents Application Tests from Executing

With the recent refactoring the TEST_HOST='' override was reintroduced into the builder. If you are attempting to run a suite of application tests that must be injected into a host application this will prevent execution. It needs to be configurable to support logic and application tests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.