Skip to content

Commit 0dd2546

Browse files
author
Dimitar Kerezov
committedMar 7, 2016
code
1 parent 9048da8 commit 0dd2546

10 files changed

+316
-89
lines changed
 

‎lib/bootstrap.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ $injector.requireCommand("test|ios", "./commands/test");
5252
$injector.requireCommand("test|init", "./commands/test-init");
5353
$injector.requireCommand("dev-generate-help", "./commands/generate-help");
5454

55-
$injector.requireCommand("publish|ios", "./commands/publish-ios");
55+
$injector.requireCommand("appstore|*list", "./commands/appstore-list");
56+
$injector.requireCommand("appstore|upload", "./commands/appstore-upload");
57+
$injector.requireCommand("publish|ios", "./commands/appstore-upload");
5658
$injector.require("itmsTransporterService", "./services/itmstransporter-service");
5759

5860
$injector.require("npm", "./node-package-manager");

‎lib/commands/appstore-list.ts

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
///<reference path="../.d.ts"/>
2+
"use strict";
3+
4+
import { createTable } from "../common/helpers";
5+
import {StringCommandParameter} from "../common/command-params";
6+
7+
export class ListiOSApps implements ICommand {
8+
constructor(private $injector: IInjector,
9+
private $itmsTransporterService: IITMSTransporterService,
10+
private $logger: ILogger,
11+
private $prompter: IPrompter,
12+
private $stringParameterBuilder: IStringParameterBuilder) { }
13+
14+
public allowedParameters: ICommandParameter[] = [new StringCommandParameter(this.$injector), new StringCommandParameter(this.$injector)];
15+
16+
public execute(args: string[]): IFuture<void> {
17+
return (() => {
18+
let username = args[0],
19+
password = args[1];
20+
21+
if(!username) {
22+
username = this.$prompter.getString("Apple ID", { allowEmpty: false }).wait();
23+
}
24+
25+
if(!password) {
26+
password = this.$prompter.getPassword("Apple ID password").wait();
27+
}
28+
29+
let iOSApplications = this.$itmsTransporterService.getiOSApplications({username, password}).wait();
30+
31+
if (!iOSApplications || !iOSApplications.length) {
32+
this.$logger.out("Seems you don't have any applications yet.");
33+
} else {
34+
let table: any = createTable(["Application Name", "Bundle Identifier", "Apple ID"], iOSApplications.map(element => {
35+
return [element.name, element.bundleId, element.adamId];
36+
}));
37+
38+
this.$logger.out(table.toString());
39+
}
40+
}).future<void>()();
41+
}
42+
}
43+
44+
$injector.registerCommand("appstore|*list", ListiOSApps);

‎lib/commands/appstore-upload.ts

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
///<reference path="../.d.ts"/>
2+
"use strict";
3+
4+
import {StringCommandParameter} from "../common/command-params";
5+
import * as temp from "temp";
6+
import * as path from "path";
7+
8+
export class PublishIOS implements ICommand {
9+
constructor(private $errors: IErrors,
10+
private $fs: IFileSystem,
11+
private $injector: IInjector,
12+
private $itmsTransporterService: IITMSTransporterService,
13+
private $logger: ILogger,
14+
private $options: IOptions,
15+
private $prompter: IPrompter,
16+
private $stringParameterBuilder: IStringParameterBuilder) { }
17+
18+
public allowedParameters: ICommandParameter[] = [new StringCommandParameter(this.$injector), new StringCommandParameter(this.$injector),
19+
new StringCommandParameter(this.$injector), new StringCommandParameter(this.$injector)];
20+
21+
public execute(args: string[]): IFuture<void> {
22+
return (() => {
23+
let username = args[0],
24+
password = args[1],
25+
mobileProvisionIdentifier = args[2],
26+
codeSignIdentity = args[3],
27+
ipaFilePath = this.$options.ipa ? path.resolve(this.$options.ipa) : null,
28+
bundleId = this.$itmsTransporterService.getBundleIdentifier(ipaFilePath).wait();
29+
30+
if(!username) {
31+
username = this.$prompter.getString("Apple ID", { allowEmpty: false }).wait();
32+
}
33+
34+
if(!password) {
35+
password = this.$prompter.getPassword("Apple ID password").wait();
36+
}
37+
38+
let iOSApplications = this.$itmsTransporterService.getiOSApplications({username, password}).wait();
39+
if (!iOSApplications || !iOSApplications.length) {
40+
this.$errors.failWithoutHelp("You don't have any applications registered at iTunes Connect.");
41+
}
42+
43+
let iosApplication = _.find(iOSApplications, app => app.bundleId === bundleId);
44+
45+
if (!iosApplication) {
46+
this.$errors.failWithoutHelp(`No application found on iTunes Connect that matches identifier ${bundleId}`);
47+
}
48+
49+
if(!mobileProvisionIdentifier && !ipaFilePath) {
50+
this.$logger.warn("Mobile Provision identifier not set - a default one will be used. You can set one in app/App_Resources/iOS/build.xcconfig");
51+
}
52+
53+
if(!codeSignIdentity && !ipaFilePath) {
54+
this.$logger.warn("Code Sign Identity not set - a default one will be used. You can set one in app/App_Resources/iOS/build.xcconfig");
55+
}
56+
57+
this.$options.release = true;
58+
this.$itmsTransporterService.upload({
59+
appId: iosApplication.adamId,
60+
username,
61+
password,
62+
mobileProvisionIdentifier,
63+
codeSignIdentity,
64+
ipaFilePath,
65+
verboseLogging: this.$logger.getLevel() === "TRACE"
66+
}).wait();
67+
}).future<void>()();
68+
}
69+
}
70+
$injector.registerCommand("publish|ios", PublishIOS);
71+
$injector.registerCommand("appstore|upload", PublishIOS);

‎lib/commands/publish-ios.ts

-46
This file was deleted.

‎lib/constants.ts

+17
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,20 @@ export class ReleaseType {
2525
static PREPATCH = "prepatch";
2626
static PRERELEASE = "prerelease";
2727
}
28+
29+
export class ITMSConstants {
30+
static ApplicationMetadataFile = "metadata.xml";
31+
static VerboseLoggingLevels = {
32+
Informational: "informational",
33+
Verbose: "detailed"
34+
}
35+
static iTMSExecutableName = "iTMSTransporter";
36+
static iTMSDirectoryName = "itms";
37+
}
38+
39+
class ItunesConnectApplicationTypesClass implements IiTunesConnectApplicationType {
40+
public iOS = "iOS App";
41+
public Mac = "Mac OS X App";
42+
}
43+
44+
export let ItunesConnectApplicationTypes = new ItunesConnectApplicationTypesClass();

‎lib/declarations.ts

+51-9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ interface ILiveSyncService {
5959
}
6060

6161
interface IOptions extends ICommonOptions {
62+
ipa: string;
6263
frameworkPath: string;
6364
frameworkName: string;
6465
framework: string;
@@ -89,21 +90,62 @@ interface IInitService {
8990
initialize(): IFuture<void>;
9091
}
9192

93+
/**
94+
* Describes standart username/password type credentials.
95+
*/
96+
interface ICredentials {
97+
username: string;
98+
password: string;
99+
}
100+
101+
/**
102+
* Describes properties needed for uploading a package to iTunes Connect
103+
*/
104+
interface IITMSData extends ICredentials {
105+
/**
106+
* The application's Apple ID. It can be found on itunesconnect.apple.com.
107+
* @type {string}
108+
*/
109+
appId: string;
110+
/**
111+
* The identifier of the mobile provision used for building. Note that this will override the same option set through .xcconfig files.
112+
* @type {string}
113+
*/
114+
mobileProvisionIdentifier?: string;
115+
/**
116+
* The Code Sign Identity used for building. Note that this will override the same option set through .xcconfig files.
117+
* @type {string}
118+
*/
119+
codeSignIdentity?: string;
120+
/**
121+
* Path to a .ipa file which will be uploaded. If set that .ipa will be used and no build will be issued.
122+
* @type {string}
123+
*/
124+
ipaFilePath?: string;
125+
/**
126+
* Specifies whether the logging level of the itmstransporter command-line tool should be set to verbose.
127+
* @type {string}
128+
*/
129+
verboseLogging?: boolean;
130+
}
131+
92132
/**
93133
* Used for communicating with Xcode's iTMS Transporter tool.
94134
*/
95135
interface IITMSTransporterService {
96136
/**
97-
* Builds and uploads an .ipa package to itunesconnect.
98-
* Note that if mobileProvisionIdentifier and/or codeSignIdentity are passed to this method they will override any options set through .xcconfig files.
99-
* @param {string} appId The application's Apple ID. It can be found on itunesconnect.apple.com.
100-
* @param {string} username Username for authentication with itunesconnect.
101-
* @param {string} password Password for authentication with itunesconnect.
102-
* @param {string} mobileProvisionIdentifier? The identifier of the mobile provision used for building.
103-
* @param {string} codeSignIdentity? The Code Sign Identity used for building.
104-
* @returns IFuture<void>
137+
* Uploads an .ipa package to iTunes Connect.
138+
* @param {IITMSData} data Data needed to upload the package
139+
* @return {IFuture<void>}
140+
*/
141+
upload(data: IITMSData): IFuture<void>;
142+
/**
143+
* Queries Apple's content delivery API to get the user's registered iOS applications.
144+
* @param {ICredentials} credentials Credentials for authentication with iTunes Connect.
145+
* @return {IFuture<IItunesConnectApplication[]>} The user's iOS applications.
105146
*/
106-
upload(appId: string, username: string, password: string, mobileProvisionIdentifier?: string, codeSignIdentity?: string): IFuture<void>;
147+
getiOSApplications(credentials: ICredentials): IFuture<IiTunesConnectApplication[]>;
148+
getBundleIdentifier(ipaFileFullPath?: string): IFuture<string>;
107149
}
108150

109151
/**

‎lib/options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export class Options extends commonOptionsLibPath.OptionsBase {
1212
$staticConfig: IStaticConfig,
1313
$hostInfo: IHostInfo) {
1414
super({
15+
ipa: { type: OptionType.String },
1516
frameworkPath: { type: OptionType.String },
1617
frameworkName: { type: OptionType.String },
1718
framework: { type: OptionType.String },

0 commit comments

Comments
 (0)