Competition: What’s your favorite Redgate tool? Enter now.

Deploy an iOS/Android app using TestFlight

This script deploys an IPA/APK file to TestFlight, for distribution to iOS and Android devices.

It's being used for these apps: http://www.bluebirdtechnology.com/

My package has the IPA/APK file, deploy.ps1 and ReleaseNotes.txt files together in the root.

If it's possible to automate AppStore/PlayStore submission I'll post it shortly.
#Inputs:
#$distributionLists = "MyTestFlightDistributionList"
#$notify = $true
#$packageFileName = "MyApp.ipa"
#$packageFileName = "MyApp.apk"
#$apiToken = "MyApiToken"
#$teamToken = "MyTeamToken"

$CODEPAGE = "iso-8859-1";

function Get-EncodedDataFromFile()
{
  param(
    [System.IO.FileInfo]$file = $null,
    [string]$codePageName = $CODEPAGE
  );
  
  $data = $null;
 
  if ( $file -and [System.IO.File]::Exists($file.FullName) )
  {
    $bytes = [System.IO.File]::ReadAllBytes($file.FullName);
    if ( $bytes )
    {
      $enc = [System.Text.Encoding]::GetEncoding($codePageName);
      $data = $enc.GetString($bytes);
    }
  }
  else
  {
    Write-Host "ERROR; File '$file' does not exist";
  }
  $data;
}

function Execute-HTTPPostcommand {
    param(
        [string]$url = $null,
        [string]$data = $null,
        [System.Net.NetworkCredential]$credentials = $null,
        [string]$contentType = "application/x-www-form-urlencoded",
        [string]$codePageName = "UTF-8",
        [string]$userAgent = $null
    );

    if ( $url -and $data ){
        [System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url);
        $webRequest.ServicePoint.Expect100Continue = $false;
        if ( $credentials ){
            $webRequest.Credentials = $credentials;
            $webRequest.PreAuthenticate = $true;
        }
        $webRequest.ContentType = $contentType;
        $webRequest.Method = "POST";
        if ( $userAgent ){
            $webRequest.UserAgent = $userAgent;
        }

        $enc = [System.Text.Encoding]::GetEncoding($codePageName);
        [byte[]]$bytes = $enc.GetBytes($data);
        $webRequest.ContentLength = $bytes.Length;
        [System.IO.Stream]$reqStream = $webRequest.GetRequestStream();
        $reqStream.Write($bytes, 0, $bytes.Length);
        $reqStream.Flush();

        $resp = $webRequest.GetResponse();
        $rs = $resp.GetResponseStream();
        [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
        $sr.ReadToEnd();
    }
}

$myDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ipaPath = $myDir + "\" + $packageFileName

$releaseNotesText = [IO.File]::ReadAllText("ReleaseNotes.txt")

$boundary = [System.Guid]::NewGuid().ToString();
$header = "--{0}" -f $boundary;
$footer = "--{0}--" -f $boundary;

[System.Text.StringBuilder]$contents = New-Object System.Text.StringBuilder;

$fileData = Get-EncodedDataFromFile -file (Get-Item $ipaPath) -codePageName $CODEPAGE;

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""api_token""");
[void]$contents.AppendLine();
[void]$contents.AppendLine($apiToken);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""team_token""");
[void]$contents.AppendLine();
[void]$contents.AppendLine($teamToken);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: file; name=""file""; filename=""{0}""" -f $packageFileName);
[void]$contents.AppendLine("Content-Type: application/octet-stream");
[void]$contents.AppendLine("Content-Transfer-Encoding: binary");
[void]$contents.AppendLine();
[void]$contents.AppendLine($fileData);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""notes""");
[void]$contents.AppendLine();
[void]$contents.AppendLine($releaseNotesText);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""distribution_lists""");
[void]$contents.AppendLine();
[void]$contents.AppendLine($distributionLists);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""notify""");
[void]$contents.AppendLine();
[void]$contents.AppendLine($notify);

[void]$contents.AppendLine($header);
[void]$contents.AppendLine("Content-Disposition: form-data; name=""replace""");
[void]$contents.AppendLine();
[void]$contents.AppendLine("true");

$apiUrl = "http://testflightapp.com/api/builds.json"
$postContentType = "multipart/form-data; boundary={0}" -f $boundary;

Execute-HTTPPostcommand -url $apiUrl -data $contents.ToString() -contentType $postContentType -codePageName $CODEPAGE
Justin Caldicott
Developer
Redgate Software Ltd
Sign In or Register to comment.