August 1, 2014
Automatically build and upload iOS app to Testflight using xcodebuild, Testflight API and launchd

In our iOS app’s lifecycle, we’re at a point where manually building the app archive and uploading it on Testflight for the QA team and the non-iOS folks in the company to always have access to the latest version of the app is very painful. So, we came up with a quick solution that allows us to automatically:

  • Build the app archive using xcodebuild in command line
  • Then upload the archive (including dSYM) to Testflight using their API
  • Then use launchd to schedule to run those commands at specified times in a week

So, here’s how we do this:
(Note: For simplicity, I’ve removed a lot of assignments and checks that you definitely want to do in real world. Do that “after” you have everything working though) :-)

== Build app archive ==

# Pull latest code from master (or whereever)
cd /git/repo
git checkout master
git pull

# Delete (or backup or move) previous archive
rm -rf /archive/auto

# Build new archive (Say, scheme/app name is MyApp and code sign identity is distribution for Acme Inc. Provisioning profile code can be found from your adhoc mobile provisioning file. Debug information format is needed for the dSYM to work on Testflight
xcodebuild archive -scheme MyApp SYMROOT="/archive/auto" DSTROOT="/archive/auto" -archivePath /archive/auto/MyApp.xcarchive CODE_SIGN_IDENTITY="iPhone Distribution: Acme, Inc. (XXXXXXXXXX)" PROVISIONING_PROFILE="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" DEBUG_INFORMATION_FORMAT="dwarf-with-dsym" DWARF_DSYM_FOLDER_PATH="/archive/auto" DWARF_DSYM_FILE_NAME="MyApp.app.dSYM"

# Export archive to IPA. Ad_Hoc.mobileprovision is the ad hoc mobile provisioning file that you can download from iTunes Provisioning
xcrun -log -sdk iphoneos PackageApplication "/archive/auto/Applications/MyApp.app" -o "/archive/auto/MyApp.ipa" -embed "/home/dev/Ad_Hoc.mobileprovision" -sign "iPhone Distribution: Acme, Inc. (XXXXXXXXXX)"

== Upload archive to Testflight ==

# Zip dSYM for Testflight
cd /archive/auto
zip -r MyApp.app.dSYM.zip MyApp.app.dSYM

# Upload on Testflight. Get your api token and team token from Testflight website
NOTE=`date "+ %Y-%m-%d"`
curl http://testflightapp.com/api/builds.json -F file=@/archive/auto/MyApp.ipa -F dsym=@/archive/auto/MyApp.app.dSYM.zip -F api_token='XXXX' -F team_token='XXXX' -F notes="Automatic build $NOTE" -F notify=True -F distribution_lists='QA, Nondevelopers' -F replace=True

== Schedule automatic builds/uploads ==

Put all the above code in a bash script in say /home/dev/build.sh (and +x it obviously)

Put the following plist file in /home/dev/com.acme.myappbuild.plist (Change the path and name obviously)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.acme.myappbuild</string>
<key>ProgramArguments</key>
<array>
<string>/home/dev/build.sh</string>
</array>
<key>StandardErrorPath</key>
<string>/home/dev/build.log</string>
<key>StandardOutPath</key>
<string>/home/dev/build.log</string>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>5</integer>
<key>Hour</key>
<integer>11</integer>
<key>Weekday</key>
<integer>1</integer>
</dict>
</dict>
</plist>

The above StartCalendarInterval will run the script on Monday at 11:05. If you want to run the script after a certain interval, use the field StartInterval instead

Copy the plist to the LaunchDaemons

sudo cp com.acme.myappbuild.plist /Library/LaunchDaemons/

Load the plist

launchctl load -w /Library/LaunchDaemons/com.acme.myappbuild.plist

Check that the plist is loaded

launchctl list | grep acme

To unload the plist in future, you can run

launchctl unload -w /Library/LaunchDaemons/com.acme.myappbuild.plist

To start the build manually, cd to LaunchDaemons and run

launchctl start com.acme.myappbuild (note: no plist extension)

== The big question ==

Now the big question is, what do I do with those extra 10 minutes I’m saving every Monday? :-/

May 9, 2014
Computer Science degree from The University of Self Study

Thanks to the great work done by many innovative educators, and entrepreneurs, there’s now a lot of computer science content on a variety of platforms. And a lot of generous educators and students have created very insightful and exciting curricula, which allow anyone interested in Computer Science to learn or revise most of the core Computer Science concepts using freely available online courses. There is a curriculum from the good folks at ADUni.org. Then, there’s Scott Young’s MIT Challenge, Adam Fletcher’s You Say You Want An Education?and aGupieWare’s curriculum.

I wanted to propose a slightly different alternative to these curricula. Instead of online courses, I wanted to propose a list of textbooks that one could read (and work on) to acquire knowledge comparable to that of a Computer Science graduate from one of the best schools. And I wanted to propose an order in which the books could be read, so that someone not aware of how all these subjects come together could just trust the wisdom of the Computer Science community, and read the books in the given order. In addition to the above mentioned curricula, I looked at the guidelines from The Joint Task Force on Computing Curricula ACM IEEE Computer Society.

NOTE: I tried to stick to the classics because, otherwise, it would be almost impossible to settle on one book for a subject. And I tried to limit to under 15 subjects.

  1. Calculus: Calculus: Early Transcendentals - James Stewart
  2. Statistics (and Probability): Probability and Statistics - Morris DeGroot
  3. Discrete Mathematics / Mathematics for CS: Discrete Mathematics With Applications - Susanna Epp
  4. Algorithms (and Data Structures): Introduction to Algorithms - CLRS (and later, The Art of Computer Programming Vol 1-4)
  5. Computer Architecture: Computer Architecture - John Hennessy (and later, Code the hidden language of computer hardware - Charles Petzold)
  6. Programming Languages: Programming Language Pragmatics - Michael Scott (and later, Seven languages in seven weeks)
  7. Operating Systems: Operating Systems Design & Implementationn - Tanenbaum
  8. Computer Networks: Computer Networks - Tenenbaum
  9. Compiler Design: Compilers: Principles, Techniques, and Tools - Alfred Aho
  10. Computational Science: Introduction to the Theory of Computation - Michael Sipser
  11. Database Systems: Database Systems: Design, Implementation, and Management - Carlos Coronel
  12. Parallel Programming: An Introduction to Parallel Programming - Peter Pacheco
  13. Artificial Intelligence: Artificial Intelligence A Modern Approach - Stuart Russell
  14. Crptography (and Security): Understanding Cryptography: A Textbook for Students and Practitioners - Christof Paar

If you have any suggestions for improvements, please let me know.

April 22, 2014
Publishing notification in Amazon Simple Notification Service (SNS) + Apple Push Notification Service (APNS) in Ruby

Now that we have the endpoints created and edited correctly in the previous post we can publish a notification.

As usual, please let me know if you find a mistake, or have suggestions for improvement. You can see the gist here: https://gist.github.com/namityadav/11189637

def self.sendapns(apnsdata)
    type = apnsdata['type']
    uid = apnsdata['userid'].to_i
    endpoint_arn = get_endpoint_arn(uid)
 
    notification = APNS_NOTIFICATIONS[type] # Get the notification fields from wherever you store them
    if notification.nil?
      @log.error("notification type '#{type}' not found")
      return
    end
 
    aws_message = {
      default: notification['body'],
      APNS: {
        aps: {
          alert: { body: notification['body'], 'action-loc-key' => notification['action-loc-key'] },
          sound: notification['sound'],
          badge: notification['badge']
        },
        custom: notification['custom']
      }.to_json,
      APNS_SANDBOX: {
        aps: {
          alert: { body: notification['body'], 'action-loc-key' => notification['action-loc-key'] },
          sound: notification['sound'],
          badge: notification['badge']
        },
        custom: notification['custom']
      }.to_json
    }
 
    begin
      sns = AWS::SNS.new(:access_key_id => AWSPUB, :secret_access_key => AWSPRI)
      sns.client.publish(:message => aws_message.to_json, :target_arn => endpoint_arn, :message_structure => 'json')
    rescue => err
      @log.error("Failed to send #{apnsdata.inspect} with error: #{err.message}\nBacktrace: #{err.backtrace}")
    end
  end

April 16, 2014
Creating and Editing Endpoints in Amazon Simple Notification Service (SNS) + Apple Push Notification Service (APNS) in Ruby

Amazon SNS supports APNS, but there’s almost no documentation or code-examples. After struggling to get the code working to create and edit endpoints in Ruby, I decided to publish it so that others desperately searching for an example can have an easier time than me. Please let me know if you find a mistake, or have suggestions for improvement.

BTW, why is set_endpoint_attribute’s CustomUserData attribute key not custom_user_data to be consistent with create_platform_endpoint?

You can see the gist here: https://gist.github.com/namityadav/10911934

sns = AWS::SNS.new(:access_key_id => AWSPUB,:secret_access_key => AWSPRI)

app_arn = server.is_sandbox? ? SNS_SANDBOX_APP_ARN : SNS_PRODUCTION_APP_ARN
timestamp = Time.new.strftime("%Y-%m-%d %H:%M:%S")
custom_user_data = "{\"user_id\":#{user.id},\"type\":\"#{token_type}\",\"update_ts\":\"#{timestamp}\"}"

if edit_endpoint # Edit existing endpoint
  apn_token = AppleToken.find(:id => token_id) # AppleToken is the DB object in Sequel
  if apn_token.nil? || apn_token.user_id != user.id
    # Token ID not found for this user
    # Return with error
  end

  apn_token.type = token_type
  apn_token.update_ts = timestamp
  # (1) Disable endpoint
  if token_type == 'none' 
    apn_token.token = ''
    # Ideally you want to catch SNS exceptions
    sns.client.set_endpoint_attributes(endpoint_arn: apn_token.endpoint_arn, attributes: {'Enabled' => 'false', 'CustomUserData' => custom_user_data})
  # (2) Edit existing endpoint
  else 
    apn_token.token = apntoken
    sns.client.set_endpoint_attributes(endpoint_arn: apn_token.endpoint_arn, attributes: {'Enabled' => 'true', 'CustomUserData' => custom_user_data, 'Token' => apntoken})
  end

  if apn_token.save
    # Return with success
  else
    # Return with DB error
  end
else
  # (3) Create endpoint and get endpoint_arn
  unless token_type == 'none'
    endpoint = sns.client.create_platform_endpoint(platform_application_arn: app_arn, token: apntoken, custom_user_data: custom_user_data)
    unless endpoint[:endpoint_arn].nil?
      apn_token = AppleToken.new(
        :user_id => user.id,
        :type => token_type,
        :token => apntoken,
        :endpoint_arn => endpoint[:endpoint_arn],
        :update_ts => timestamp
      )
      if apn_token.save
        # Return with success and perhaps apn_token.id
      else
        # Return with DB error
      end
    end
  end
end

March 9, 2011
Internet Startups: 5 Information Arbitrage

In economics, arbitrage is the practice of taking advantage of an imbalance in price between two markets. That arbitrage is almost no risk and short lived.

I define arbitrage as the practice of discovering data and then extracting previously unavailable information from it to create market opportunities. So, in my opinion, the economics definition of arbitrage is just one example of arbitrage. But, to not confuse the two, let me call my definition Information Arbitrage.

Information Arbitrage just provides an opportunity. So, it is naturally more risky. But it is also long lived and can even become your source of defensibility.

To benefit from Information Arbitrage, look for industries where: (Similar to “Data Opportunities” discussed here )

  1. even more data can be generated
  2. data can be captured more efficiently
  3. data can be better analyzed to produce actionable information. 
  4. data can be processed faster (real-time)

March 9, 2011
Internet Startups: 4 Objectivity

Go against convention

Listen to conventional wisdom to understand: 

  • a market and your potential customers and competitors. 
  • the potential flaws in the conventions that you can poke holes in. (convention != disruption)
Example, while Xbox 360 and Playstation 3 were batteling out in the red ocean of graphics and high-def, Nintendo Wii was setting the rules in the blue ocean of casual gaming.

Learn about an industry like a child (Why? Why? Why?). Dont be afraid of asking stupid questions.

But, be objective

  1. Objectivity is what differentiates a disruptive idea from a simply bad idea.
  2. Test your idea in the market with solid research and non-negotiable metrics to make a go-nogo decision. And don’t be afraid to pull the plug.
  3. Example metrics: We will personally work with 10 B2B customers for 3 months. After 3 months, more than 5 should want to pay us to continue working with them. 
  4. Example metrics post launch: Are we break-even (EBITDA >= Expenses) after one year? Are we getting customers in greater numbers or cheaper than before?
  5. As technology and consumer needs evolve, will your solution serve a big enough market? Or will the market become big enough by then?

March 5, 2011
Idea, Execution, Marketing

Idea

  1. Solve a pain (product-market fit).
  2. Learn continuously and early, when the cost of change is small. 
  3. Talk to customers - Go where they hang out (For example, if customer is a small startup, go to hackernews and “offer” them a service).
  4. Adwords testing with fake landing pages (simple, to-the-point, get email for prospects).
  5. Be very focused on a niche (Facebook started at just Harvard). 

Execution

  1. Do just one thing for customers, but do it very very well.
  2. Fake it till you make it (Simulate some features till they are ready).
  3. You can never make something “too easy”. Assume that reducing every additional step for the customer doubles your customer-base. 
  4. Always ask for very basic feedback (For example, Dropbox’s simple question - How’s Dropbox? (a) Awesome (b) Needs work).
  5. How do customers look at your product (hint: not like you do)?

Marketing  (and Sales)

  1. Your small customer base may also mean you have a “scarce resource” (Ex, Gmail invites).
  2. Leverage your connection to a bigger trend to get people’s (especially bloggers’ and early adopters’) interest.
  3. Build connections with bloggers today. Help them with something today to get a return-favor next year.
  4. Are you doing enough for your power-users to turn them into evangelists?
  5. Referrals - Encourage word-of-mouth by giving something valuable to the referrer.
  6. Provide easy import functionality from Facebook, Twitter, Email etc.
  7. Understand if your business can really get virality (Do people really wanna tell their friends that they signed up on eHarmony?) 
  8. Understand your CAC and LTV.

10:54am
Filed under: startup 
March 1, 2011
Internet Startups: 3 Pain

There’s no happy without sad, no good without evil – You need pain as a catalyst to overcome reluctance to change. A pain can be an inconvenience, added cost, missed opportunity, obsolescence etc.

Mathematically, Pain to resolve > Cost of resolving <=> Adoption

You can’t really understand customers’ pain till you really understand your customer.

Making an opaque part of an industry transparent and cost-effective usually solves a pain.

Some questions to consider:

  1. Does the industry have a supply / demand imbalance? (Groupon / Echo)
  2. Is there significant price elasticity?
  3. Is there fragmentation in the market?
  4. Are there too many steps in the process?
  5. Is there little automation in the process? Time consuming, tedious, error-prone.
  6. Is the customer over-paying for something?
  7. Is the customer not making as much profit as she can?
  8. Is the pain significant enough for the customer to pay for it?
  9. Is the customer solving the pain through some home-grown solutions?
  10. Is the market big enough?

More questions to discover articulated customer needs:

http://namityadav.com/post/3166857651/marketing-developing-new-products-3-customers

Note: Replicating a US business (and its business model) in other countries is getting easier because markets, customers, and their pains are very alike everywhere.

Painful industries

Based on the American Customer Satisfaction Index, some industries have been historically bad in customers’ eyes (Their scores in parenthesis): 

  1. Newspapers (65)
  2. Subscription TV (66). Major offenders – Charter, Comcast, Time Warner
  3. Airlines (66). Major offenders – United, Northwest, US Airways, Delta
  4. Gas Stations (70)
  5. Social Media (70). Major offenders – MySpace, Facebook
  6. USPS (71)
  7. Wireless Telephone (72). Major offenders – AT&T, Sprint
  8. Hospitals (73)
  9. Health Insurance (73). Major offenders – United Health, Aetna, WellPoint
  10. Internet News (74). Major offenders – CNN, MSNBC

11:10pm
Filed under: mba internet startups pain 
March 1, 2011
Internet Startups: 2 Data

  1. With all the data available to us today, very few decisions should be based on faith. 
  2. Look for industries where data is fragmented and needs aggregation.
  3. (a) Find the decisions and actions that your business has to take. (b) Then find the answers based on which you can take those decisions and actions. (c) Then design your information system to get those answers.
  4. Get data from people & give them something useful in return (Think Google’s services). Data is the currency that runs businesses.
  5. "tackling Big Data will determine the winners and losers in the next wave of cloud computing innovation." - A GigaOm article.
  6. Data can provide defensibility (Ex, Groupon’s future direction) by acting as a source of customization, uniqueness, innovation, etc.
  7. Data can be used as a marketing tool: OKTrends, Admob Mobile Metrics.

Data Opportunities

  1. Infrastructure - Serve the infrastructural needs of big data. For example, storage, management and security of data in cloud-based systems. Ex, Imperva.
  2. Capture – Collect data more efficiently, cheaply, or from new sources. Ex, Google Analytics.
  3. Structure – Translate and structure data for use / analysis.
  4. Analysis – Extract meaningful information from data that help customers in making important decisions. Future opportunities lie in predictive analysis. Ex, Netflix recommendations.
  5. Visualization – Present data in a simple and friendly way. Ex, Hipmunk, Flipboard.
  6. Real-time – Use real-time data to remove inefficiency and unreliability. Ex, Echo.

6:06pm
Filed under: mba internet startups data 
March 1, 2011
Internet Startups: 1 Disruption

  1. Disruption is an innovation that improves a product or service in unexpected ways and lowers price or brings value to a different set of consumers. 
  2. Sometimes disruption comes directly from technology. In other cases, it comes from strategy and business models (which may or may not have been enabled by technology).
  3. Disruption may consist of off-the-shelf components put together in a simple fashion to bring value to a new market, or more commonly, to the lower end of the market (un-served or under-served). If the rate of improvement is significant, the solution then moves up-market. 
  4. Disruptive solutions initially have lower gross margins and smaller markets. 
  5. Example, Digital music’s disruptive effect on music CDs.

Disruption through technology

  1. How can I use technology to disrupt an established industry? 
  2. Can I make an opaque part of an industry transparent and cost-effective?
  3. Is the industry fragmented?
  4. What will the customers need one/three/five years from now?
  5. Can disruption be brought through a hybrid of technology and human processes?

Notes:

  1. Use a rapid application development tool to quickly launch a solution and see if/how customers use it.
  2. Define market segments in terms of “different people”, not in terms of “product usage”.

Liked posts on Tumblr: More liked posts »