lim 0.19.4 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/commands/gradle/build.d.ts +7 -0
- package/dist/commands/gradle/build.d.ts.map +1 -1
- package/dist/commands/gradle/build.js +66 -2
- package/dist/commands/gradle/build.js.map +1 -1
- package/dist/commands/xcode/run.d.ts +26 -0
- package/dist/commands/xcode/run.d.ts.map +1 -0
- package/dist/commands/xcode/run.js +134 -0
- package/dist/commands/xcode/run.js.map +1 -0
- package/dist/lib/android-keystore.d.ts +15 -0
- package/dist/lib/android-keystore.d.ts.map +1 -0
- package/dist/lib/android-keystore.js +65 -0
- package/dist/lib/android-keystore.js.map +1 -0
- package/dist/lib/android-keystore.test.d.ts +2 -0
- package/dist/lib/android-keystore.test.d.ts.map +1 -0
- package/dist/lib/android-keystore.test.js +43 -0
- package/dist/lib/android-keystore.test.js.map +1 -0
- package/dist/lib/auth.d.ts +1 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +1 -0
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/backend.d.ts +32 -0
- package/dist/lib/backend.d.ts.map +1 -0
- package/dist/lib/backend.js +81 -0
- package/dist/lib/backend.js.map +1 -0
- package/dist/lib/backend.test.d.ts +2 -0
- package/dist/lib/backend.test.d.ts.map +1 -0
- package/dist/lib/backend.test.js +124 -0
- package/dist/lib/backend.test.js.map +1 -0
- package/dist/lib/gradle-build-options.d.ts +21 -0
- package/dist/lib/gradle-build-options.d.ts.map +1 -1
- package/dist/lib/gradle-build-options.js +41 -0
- package/dist/lib/gradle-build-options.js.map +1 -1
- package/dist/lib/gradle-build-options.test.d.ts +2 -0
- package/dist/lib/gradle-build-options.test.d.ts.map +1 -0
- package/dist/lib/gradle-build-options.test.js +63 -0
- package/dist/lib/gradle-build-options.test.js.map +1 -0
- package/dist/lib/gradle-signing.d.ts +44 -0
- package/dist/lib/gradle-signing.d.ts.map +1 -0
- package/dist/lib/gradle-signing.js +167 -0
- package/dist/lib/gradle-signing.js.map +1 -0
- package/dist/lib/gradle-signing.test.d.ts +2 -0
- package/dist/lib/gradle-signing.test.d.ts.map +1 -0
- package/dist/lib/gradle-signing.test.js +111 -0
- package/dist/lib/gradle-signing.test.js.map +1 -0
- package/package.json +9 -4
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.androidSigningKeySecretType = void 0;
|
|
4
|
+
exports.whoAmI = whoAmI;
|
|
5
|
+
exports.getSecret = getSecret;
|
|
6
|
+
exports.putSecret = putSecret;
|
|
7
|
+
const api_1 = require("@limrun/api");
|
|
8
|
+
exports.androidSigningKeySecretType = 'androidSigningKey';
|
|
9
|
+
/** Wraps transport errors with call context; auth errors pass through untouched. */
|
|
10
|
+
function rethrow(err, context) {
|
|
11
|
+
if (err instanceof api_1.AuthenticationError || !(err instanceof api_1.APIError)) {
|
|
12
|
+
throw err;
|
|
13
|
+
}
|
|
14
|
+
throw new Error(`${context}: ${err.message}`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the organization the API key acts for. `lim login` keys are
|
|
18
|
+
* organization tokens, so `organization` is the normal path; hand-set
|
|
19
|
+
* user API keys fall back to the user's default organization, which
|
|
20
|
+
* /v1/whoami nests inside `user`.
|
|
21
|
+
*/
|
|
22
|
+
async function whoAmI(client) {
|
|
23
|
+
let body;
|
|
24
|
+
try {
|
|
25
|
+
body = await client.get('/v1/whoami');
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
rethrow(err, 'Failed to resolve the organization');
|
|
29
|
+
}
|
|
30
|
+
const organizationId = body.organization?.id ?? body.user?.defaultOrganization?.id;
|
|
31
|
+
if (!organizationId) {
|
|
32
|
+
throw new Error('The Limrun API did not report an organization for this API key.');
|
|
33
|
+
}
|
|
34
|
+
return organizationId;
|
|
35
|
+
}
|
|
36
|
+
function secretPath(organizationId, secretType, secretName) {
|
|
37
|
+
return `/v1/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretType)}/${encodeURIComponent(secretName)}`;
|
|
38
|
+
}
|
|
39
|
+
/** Fetches a secret's data, or undefined when it does not exist. */
|
|
40
|
+
async function getSecret(client, organizationId, secretType, secretName) {
|
|
41
|
+
let body;
|
|
42
|
+
try {
|
|
43
|
+
body = await client.get(secretPath(organizationId, secretType, secretName));
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err instanceof api_1.NotFoundError) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
rethrow(err, `Failed to fetch the ${secretType} secret ${secretName}`);
|
|
50
|
+
}
|
|
51
|
+
if (!body.data) {
|
|
52
|
+
throw new Error(`The Limrun API returned a ${secretType} secret without data.`);
|
|
53
|
+
}
|
|
54
|
+
return body.data;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get-or-create put. The response data is authoritative: on a hit the
|
|
58
|
+
* submitted data was NOT stored and the caller must adopt the returned
|
|
59
|
+
* material instead. Creation is signaled by the response body's
|
|
60
|
+
* `created` today and by HTTP 201 after the status-split hardening;
|
|
61
|
+
* accept both so either server version works.
|
|
62
|
+
*/
|
|
63
|
+
async function putSecret(client, organizationId, secretType, secretName, data) {
|
|
64
|
+
let body;
|
|
65
|
+
let response;
|
|
66
|
+
try {
|
|
67
|
+
({ data: body, response } = await client
|
|
68
|
+
.put(secretPath(organizationId, secretType, secretName), {
|
|
69
|
+
body: { data },
|
|
70
|
+
})
|
|
71
|
+
.withResponse());
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
rethrow(err, `Failed to store the ${secretType} secret ${secretName}`);
|
|
75
|
+
}
|
|
76
|
+
if (!body.data) {
|
|
77
|
+
throw new Error(`The Limrun API returned a ${secretType} secret without data.`);
|
|
78
|
+
}
|
|
79
|
+
return { data: body.data, created: body.created ?? response.status === 201 };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/lib/backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.test.d.ts","sourceRoot":"","sources":["../../src/lib/backend.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const api_1 = __importStar(require("@limrun/api"));
|
|
37
|
+
const backend_1 = require("./backend");
|
|
38
|
+
const apiEndpoint = 'https://api.example.test';
|
|
39
|
+
function mockResponse(status, body) {
|
|
40
|
+
return new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
|
|
41
|
+
}
|
|
42
|
+
describe('backend client', () => {
|
|
43
|
+
let fetchMock;
|
|
44
|
+
let client;
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
fetchMock = jest.spyOn(globalThis, 'fetch');
|
|
47
|
+
client = new api_1.default({ apiKey: 'key', baseURL: apiEndpoint, maxRetries: 0 });
|
|
48
|
+
});
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
fetchMock.mockRestore();
|
|
51
|
+
});
|
|
52
|
+
function requestOf(call) {
|
|
53
|
+
const [input, init] = call;
|
|
54
|
+
return {
|
|
55
|
+
url: String(input),
|
|
56
|
+
auth: new Headers(init?.headers).get('authorization'),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
describe('whoAmI', () => {
|
|
60
|
+
it('resolves the organization for org tokens with the bearer key', async () => {
|
|
61
|
+
fetchMock.mockResolvedValue(mockResponse(200, { type: 'organization', organization: { id: 'org_1' } }));
|
|
62
|
+
await expect((0, backend_1.whoAmI)(client)).resolves.toBe('org_1');
|
|
63
|
+
const { url, auth } = requestOf(fetchMock.mock.calls[0]);
|
|
64
|
+
expect(url).toBe(`${apiEndpoint}/v1/whoami`);
|
|
65
|
+
expect(auth).toBe('Bearer key');
|
|
66
|
+
});
|
|
67
|
+
it('falls back to the default organization NESTED IN user for user tokens', async () => {
|
|
68
|
+
fetchMock.mockResolvedValue(mockResponse(200, { type: 'user', user: { defaultOrganization: { id: 'org_2' } } }));
|
|
69
|
+
await expect((0, backend_1.whoAmI)(client)).resolves.toBe('org_2');
|
|
70
|
+
});
|
|
71
|
+
it('throws the SDK AuthenticationError on 401 so withAuth can re-login', async () => {
|
|
72
|
+
fetchMock.mockResolvedValue(mockResponse(401, {}));
|
|
73
|
+
await expect((0, backend_1.whoAmI)(client)).rejects.toBeInstanceOf(api_1.AuthenticationError);
|
|
74
|
+
});
|
|
75
|
+
it('fails when no organization is reported', async () => {
|
|
76
|
+
fetchMock.mockResolvedValue(mockResponse(200, { type: 'user', user: {} }));
|
|
77
|
+
await expect((0, backend_1.whoAmI)(client)).rejects.toThrow(/did not report an organization/);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('getSecret', () => {
|
|
81
|
+
it('returns undefined on 404', async () => {
|
|
82
|
+
fetchMock.mockResolvedValue(mockResponse(404, { message: 'not found' }));
|
|
83
|
+
await expect((0, backend_1.getSecret)(client, 'org_1', 'androidSigningKey', 'com.x')).resolves.toBeUndefined();
|
|
84
|
+
});
|
|
85
|
+
it('URL-encodes path segments and returns the data', async () => {
|
|
86
|
+
fetchMock.mockResolvedValue(mockResponse(200, { data: { keyAlias: 'upload' } }));
|
|
87
|
+
await expect((0, backend_1.getSecret)(client, 'org/1', 'androidSigningKey', 'com/x')).resolves.toEqual({
|
|
88
|
+
keyAlias: 'upload',
|
|
89
|
+
});
|
|
90
|
+
const { url } = requestOf(fetchMock.mock.calls[0]);
|
|
91
|
+
expect(url).toBe(`${apiEndpoint}/v1/organizations/org%2F1/secrets/androidSigningKey/com%2Fx`);
|
|
92
|
+
});
|
|
93
|
+
it('surfaces the API error message', async () => {
|
|
94
|
+
fetchMock.mockResolvedValue(mockResponse(500, { message: 'db down' }));
|
|
95
|
+
await expect((0, backend_1.getSecret)(client, 'org_1', 'androidSigningKey', 'com.x')).rejects.toThrow(/db down/);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('putSecret', () => {
|
|
99
|
+
it("reads `created` from the response body (today's 200-only server)", async () => {
|
|
100
|
+
fetchMock.mockResolvedValue(mockResponse(200, { data: { keyAlias: 'upload' }, created: true }));
|
|
101
|
+
await expect((0, backend_1.putSecret)(client, 'org_1', 'androidSigningKey', 'com.x', { keyAlias: 'upload' })).resolves.toEqual({
|
|
102
|
+
data: { keyAlias: 'upload' },
|
|
103
|
+
created: true,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('falls back to HTTP 201 when the body has no created field (status-split server)', async () => {
|
|
107
|
+
fetchMock.mockResolvedValue(mockResponse(201, { data: { keyAlias: 'upload' } }));
|
|
108
|
+
await expect((0, backend_1.putSecret)(client, 'org_1', 'androidSigningKey', 'com.x', { keyAlias: 'upload' })).resolves.toEqual({
|
|
109
|
+
data: { keyAlias: 'upload' },
|
|
110
|
+
created: true,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it('returns the WINNER data on a get-or-create hit, not the submitted data', async () => {
|
|
114
|
+
fetchMock.mockResolvedValue(mockResponse(200, { data: { keyAlias: 'winner' }, created: false }));
|
|
115
|
+
const result = await (0, backend_1.putSecret)(client, 'org_1', 'androidSigningKey', 'com.x', { keyAlias: 'loser' });
|
|
116
|
+
expect(result).toEqual({ data: { keyAlias: 'winner' }, created: false });
|
|
117
|
+
});
|
|
118
|
+
it('rejects validation failures with the API message', async () => {
|
|
119
|
+
fetchMock.mockResolvedValue(mockResponse(400, { message: 'keystoreBase64 is required' }));
|
|
120
|
+
await expect((0, backend_1.putSecret)(client, 'org_1', 'androidSigningKey', 'com.x', {})).rejects.toThrow(/keystoreBase64 is required/);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=backend.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.test.js","sourceRoot":"","sources":["../../src/lib/backend.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAA0D;AAE1D,uCAAyD;AAEzD,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C,SAAS,YAAY,CAAC,MAAc,EAAE,IAAa;IACjD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;AACzG,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,SAA2B,CAAC;IAChC,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,GAAG,IAAI,aAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,CAAC,WAAW,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,SAAS,CAAC,IAAe;QAChC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,IAA+C,CAAC;QACtE,OAAO;YACL,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC;YAClB,IAAI,EAAE,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC;SACtD,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YACxG,MAAM,MAAM,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,YAAY,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;YACrF,SAAS,CAAC,iBAAiB,CACzB,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CACpF,CAAC;YACF,MAAM,MAAM,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,MAAM,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,yBAAmB,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC3E,MAAM,MAAM,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;YACzE,MAAM,MAAM,CAAC,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;YACjF,MAAM,MAAM,CAAC,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACtF,QAAQ,EAAE,QAAQ;aACnB,CAAC,CAAC;YACH,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,6DAA6D,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YACvE,MAAM,MAAM,CAAC,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpG,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAChG,MAAM,MAAM,CACV,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CACjF,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACjB,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;gBAC5B,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;YAC/F,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;YACjF,MAAM,MAAM,CACV,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CACjF,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACjB,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;gBAC5B,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;YACtF,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACrG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,SAAS,CAAC,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC;YAC1F,MAAM,MAAM,CAAC,IAAA,mBAAS,EAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACxF,4BAA4B,CAC7B,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -12,7 +12,28 @@ export interface GradleBuildFlagValues {
|
|
|
12
12
|
abi?: string[];
|
|
13
13
|
upload?: string;
|
|
14
14
|
'signed-upload-url'?: string;
|
|
15
|
+
sign?: boolean;
|
|
16
|
+
'application-id'?: string;
|
|
17
|
+
keystore?: string;
|
|
18
|
+
'keystore-password'?: string;
|
|
19
|
+
'key-alias'?: string;
|
|
20
|
+
'key-password'?: string;
|
|
21
|
+
'save-key'?: boolean;
|
|
15
22
|
}
|
|
23
|
+
/** Whether any explicit task produces an app bundle (AAB) artifact. */
|
|
24
|
+
export declare function tasksIncludeBundle(tasks: string[]): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Validates the signing flag combinations. Separate from the options
|
|
27
|
+
* mapping because signing material is resolved asynchronously (file read
|
|
28
|
+
* or escrow round-trip) after validation, while the mapper stays pure.
|
|
29
|
+
*
|
|
30
|
+
* The bring-your-own group is anchored on --keystore alone: the password
|
|
31
|
+
* flags are env-backed (LIM_KEYSTORE_PASSWORD, LIM_KEY_PASSWORD), so an
|
|
32
|
+
* ambient export must not drag a plain or --sign build into BYO
|
|
33
|
+
* validation. Presence checks use undefined, not truthiness: empty
|
|
34
|
+
* keystore passwords are legal.
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateSigningFlags(flags: GradleBuildFlagValues): void;
|
|
16
37
|
/**
|
|
17
38
|
* Maps parsed `lim gradle build` flags to the exec options, throwing on
|
|
18
39
|
* contradictory combinations. Pure and oclif-free so it is unit-testable and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gradle-build-options.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,+DAMkB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"gradle-build-options.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,+DAMkB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CA2BvE;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,qBAAqB,GAAG,kBAAkB,CA+B5F"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.gradleAndroidABIs = void 0;
|
|
4
|
+
exports.tasksIncludeBundle = tasksIncludeBundle;
|
|
5
|
+
exports.validateSigningFlags = validateSigningFlags;
|
|
4
6
|
exports.gradleBuildOptionsFromFlags = gradleBuildOptionsFromFlags;
|
|
5
7
|
/**
|
|
6
8
|
* Single source for the --abi enum: `satisfies` pins every entry to the SDK
|
|
@@ -14,6 +16,44 @@ exports.gradleAndroidABIs = [
|
|
|
14
16
|
'x86_64',
|
|
15
17
|
'all',
|
|
16
18
|
];
|
|
19
|
+
/** Whether any explicit task produces an app bundle (AAB) artifact. */
|
|
20
|
+
function tasksIncludeBundle(tasks) {
|
|
21
|
+
return tasks.some((t) => t.toLowerCase().includes('bundle'));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validates the signing flag combinations. Separate from the options
|
|
25
|
+
* mapping because signing material is resolved asynchronously (file read
|
|
26
|
+
* or escrow round-trip) after validation, while the mapper stays pure.
|
|
27
|
+
*
|
|
28
|
+
* The bring-your-own group is anchored on --keystore alone: the password
|
|
29
|
+
* flags are env-backed (LIM_KEYSTORE_PASSWORD, LIM_KEY_PASSWORD), so an
|
|
30
|
+
* ambient export must not drag a plain or --sign build into BYO
|
|
31
|
+
* validation. Presence checks use undefined, not truthiness: empty
|
|
32
|
+
* keystore passwords are legal.
|
|
33
|
+
*/
|
|
34
|
+
function validateSigningFlags(flags) {
|
|
35
|
+
if (flags.sign && flags.keystore) {
|
|
36
|
+
throw new Error('Use either --sign (escrowed key) or --keystore (bring your own key), not both.');
|
|
37
|
+
}
|
|
38
|
+
if (flags.keystore) {
|
|
39
|
+
const missing = ['keystore-password', 'key-alias', 'key-password'].filter((f) => flags[f] === undefined);
|
|
40
|
+
if (missing.length > 0) {
|
|
41
|
+
throw new Error(`Signing with your own key requires ${missing.map((f) => `--${f}`).join(', ')} as well.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (flags['key-alias'] !== undefined) {
|
|
45
|
+
throw new Error('--key-alias requires --keystore.');
|
|
46
|
+
}
|
|
47
|
+
if (flags['save-key'] && !flags.keystore) {
|
|
48
|
+
throw new Error('--save-key escrows a provided key and requires the --keystore flags.');
|
|
49
|
+
}
|
|
50
|
+
if (flags['application-id'] && !flags.sign && !flags['save-key']) {
|
|
51
|
+
throw new Error('--application-id only applies to --sign or --save-key.');
|
|
52
|
+
}
|
|
53
|
+
if (flags.sign && flags.task?.length && !tasksIncludeBundle(flags.task)) {
|
|
54
|
+
throw new Error('--sign produces a Play-ready signed AAB; include a bundle task (e.g. bundleRelease) in --task or omit --task.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
17
57
|
/**
|
|
18
58
|
* Maps parsed `lim gradle build` flags to the exec options, throwing on
|
|
19
59
|
* contradictory combinations. Pure and oclif-free so it is unit-testable and
|
|
@@ -26,6 +66,7 @@ function gradleBuildOptionsFromFlags(flags) {
|
|
|
26
66
|
if (flags.upload && flags['signed-upload-url']) {
|
|
27
67
|
throw new Error('Use either --upload or --signed-upload-url, not both.');
|
|
28
68
|
}
|
|
69
|
+
validateSigningFlags(flags);
|
|
29
70
|
const options = {};
|
|
30
71
|
if (flags.task?.length) {
|
|
31
72
|
options.tasks = flags.task;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gradle-build-options.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":";;;AAgCA,
|
|
1
|
+
{"version":3,"file":"gradle-build-options.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradle-build-options.test.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const gradle_build_options_1 = require("./gradle-build-options");
|
|
4
|
+
const byo = {
|
|
5
|
+
keystore: 'upload.jks',
|
|
6
|
+
'keystore-password': 'store-pass',
|
|
7
|
+
'key-alias': 'upload',
|
|
8
|
+
'key-password': 'key-pass',
|
|
9
|
+
};
|
|
10
|
+
describe('gradleBuildOptionsFromFlags signing validation', () => {
|
|
11
|
+
const cases = [
|
|
12
|
+
{ name: 'no signing flags', flags: {} },
|
|
13
|
+
{ name: 'sign alone', flags: { sign: true } },
|
|
14
|
+
{ name: 'sign with application-id', flags: { sign: true, 'application-id': 'com.x' } },
|
|
15
|
+
{ name: 'full BYO group', flags: { ...byo } },
|
|
16
|
+
{ name: 'full BYO group with save-key', flags: { ...byo, 'save-key': true, 'application-id': 'com.x' } },
|
|
17
|
+
{
|
|
18
|
+
name: 'empty-string keystore password is provided, not missing',
|
|
19
|
+
flags: { ...byo, 'keystore-password': '' },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'ambient env passwords without --keystore do not poison a plain build',
|
|
23
|
+
flags: { 'keystore-password': 'from-env', 'key-password': 'from-env' },
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'ambient env passwords without --keystore do not poison --sign',
|
|
27
|
+
flags: { sign: true, 'keystore-password': 'from-env', 'key-password': 'from-env' },
|
|
28
|
+
},
|
|
29
|
+
{ name: 'sign and keystore together', flags: { sign: true, ...byo }, error: /not both/ },
|
|
30
|
+
{
|
|
31
|
+
name: 'keystore without the rest names the missing flags',
|
|
32
|
+
flags: { keystore: 'upload.jks', 'key-alias': 'upload' },
|
|
33
|
+
error: /--keystore-password, --key-password/,
|
|
34
|
+
},
|
|
35
|
+
{ name: 'key-alias without keystore', flags: { 'key-alias': 'upload' }, error: /requires --keystore/ },
|
|
36
|
+
{ name: 'save-key without keystore', flags: { 'save-key': true }, error: /requires the --keystore/ },
|
|
37
|
+
{
|
|
38
|
+
name: 'application-id without sign or save-key',
|
|
39
|
+
flags: { 'application-id': 'com.x' },
|
|
40
|
+
error: /only applies to --sign or --save-key/,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'sign with an explicit non-bundle task',
|
|
44
|
+
flags: { sign: true, task: ['assembleDebug'] },
|
|
45
|
+
error: /include a bundle task/,
|
|
46
|
+
},
|
|
47
|
+
{ name: 'sign with an explicit bundle task', flags: { sign: true, task: [':app:bundleRelease'] } },
|
|
48
|
+
{ name: 'BYO keystore with a debug task stays allowed', flags: { ...byo, task: ['assembleDebug'] } },
|
|
49
|
+
];
|
|
50
|
+
it.each(cases)('$name', ({ flags, error }) => {
|
|
51
|
+
if (error) {
|
|
52
|
+
expect(() => (0, gradle_build_options_1.gradleBuildOptionsFromFlags)(flags)).toThrow(error);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
expect(() => (0, gradle_build_options_1.gradleBuildOptionsFromFlags)(flags)).not.toThrow();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
it('never maps signing material itself: the command resolves it asynchronously', () => {
|
|
59
|
+
expect((0, gradle_build_options_1.gradleBuildOptionsFromFlags)({ ...byo }).signing).toBeUndefined();
|
|
60
|
+
expect((0, gradle_build_options_1.gradleBuildOptionsFromFlags)({ sign: true }).signing).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=gradle-build-options.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradle-build-options.test.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { GradleSigningConfig } from '@limrun/api';
|
|
2
|
+
import type Limrun from '@limrun/api';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the Android applicationId that names the escrowed signing key.
|
|
5
|
+
* Precedence: explicit flag, Expo app config, Gradle build script. The
|
|
6
|
+
* file probes are heuristics; --application-id is the escape hatch.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveApplicationId(opts: {
|
|
9
|
+
explicit?: string;
|
|
10
|
+
syncPath: string;
|
|
11
|
+
expoAppDir?: string;
|
|
12
|
+
projectPath?: string;
|
|
13
|
+
}): string;
|
|
14
|
+
/**
|
|
15
|
+
* Reads a bring-your-own keystore file into the wire signing shape. The
|
|
16
|
+
* flag validator guarantees the passwords and alias are set; the checks
|
|
17
|
+
* here keep that invariant local instead of relying on call-site order.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readProvidedSigning(flags: {
|
|
20
|
+
keystore: string;
|
|
21
|
+
keystorePassword?: string;
|
|
22
|
+
keyAlias?: string;
|
|
23
|
+
keyPassword?: string;
|
|
24
|
+
}): GradleSigningConfig;
|
|
25
|
+
export type EscrowedSigning = {
|
|
26
|
+
signing: GradleSigningConfig;
|
|
27
|
+
/** True when this invocation created the key; false when it already existed. */
|
|
28
|
+
created: boolean;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Fetches the organization's upload key for the application, generating
|
|
32
|
+
* and escrowing one on first use. The backend's get-or-create makes the
|
|
33
|
+
* concurrent-first-build race safe: whichever caller wins, everyone signs
|
|
34
|
+
* with the same key, because the response data is authoritative.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveEscrowedSigning(client: Limrun, applicationId: string): Promise<EscrowedSigning>;
|
|
37
|
+
/**
|
|
38
|
+
* Escrows a user-provided key under the application's name. Refuses to
|
|
39
|
+
* proceed when a DIFFERENT key is already escrowed: silently signing with
|
|
40
|
+
* either key would surprise someone, and replacing an upload key is not a
|
|
41
|
+
* side effect a build command should have.
|
|
42
|
+
*/
|
|
43
|
+
export declare function saveProvidedKey(client: Limrun, applicationId: string, provided: GradleSigningConfig): Promise<boolean>;
|
|
44
|
+
//# sourceMappingURL=gradle-signing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradle-signing.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-signing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAMtC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAoBT;AAmCD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,mBAAmB,CAwBtB;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveApplicationId = resolveApplicationId;
|
|
37
|
+
exports.readProvidedSigning = readProvidedSigning;
|
|
38
|
+
exports.resolveEscrowedSigning = resolveEscrowedSigning;
|
|
39
|
+
exports.saveProvidedKey = saveProvidedKey;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const android_keystore_1 = require("./android-keystore");
|
|
43
|
+
const backend_1 = require("./backend");
|
|
44
|
+
const signingFields = ['keystoreBase64', 'keystorePassword', 'keyAlias', 'keyPassword'];
|
|
45
|
+
/**
|
|
46
|
+
* Resolves the Android applicationId that names the escrowed signing key.
|
|
47
|
+
* Precedence: explicit flag, Expo app config, Gradle build script. The
|
|
48
|
+
* file probes are heuristics; --application-id is the escape hatch.
|
|
49
|
+
*/
|
|
50
|
+
function resolveApplicationId(opts) {
|
|
51
|
+
if (opts.explicit) {
|
|
52
|
+
return opts.explicit;
|
|
53
|
+
}
|
|
54
|
+
const fromExpo = expoAndroidPackage(path.join(opts.syncPath, opts.expoAppDir ?? '.'));
|
|
55
|
+
if (fromExpo) {
|
|
56
|
+
return fromExpo;
|
|
57
|
+
}
|
|
58
|
+
// Probe the explicit gradle root first, then the conventional bare
|
|
59
|
+
// React Native layout (android/), which users rarely spell out because
|
|
60
|
+
// the server auto-discovers it.
|
|
61
|
+
for (const root of [...new Set([opts.projectPath ?? '.', 'android'])]) {
|
|
62
|
+
const fromGradle = gradleApplicationId(path.join(opts.syncPath, root));
|
|
63
|
+
if (fromGradle) {
|
|
64
|
+
return fromGradle;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw new Error('Cannot determine the Android application ID for signing. Pass --application-id <id> (the value of android.package in app.json, or applicationId in app/build.gradle).');
|
|
68
|
+
}
|
|
69
|
+
function expoAndroidPackage(appDir) {
|
|
70
|
+
try {
|
|
71
|
+
const raw = fs.readFileSync(path.join(appDir, 'app.json'), 'utf8');
|
|
72
|
+
const parsed = JSON.parse(raw);
|
|
73
|
+
return parsed.expo?.android?.package || undefined;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function gradleApplicationId(gradleRoot) {
|
|
80
|
+
for (const candidate of ['app/build.gradle', 'app/build.gradle.kts']) {
|
|
81
|
+
let content;
|
|
82
|
+
try {
|
|
83
|
+
content = fs.readFileSync(path.join(gradleRoot, candidate), 'utf8');
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Matches both Groovy (applicationId "com.x") and Kotlin DSL
|
|
89
|
+
// (applicationId = "com.x"), skipping line comments so a commented-out
|
|
90
|
+
// previous ID cannot shadow the live one. First live match wins;
|
|
91
|
+
// flavor-specific overrides are out of heuristic scope.
|
|
92
|
+
for (const line of content.split('\n')) {
|
|
93
|
+
const code = line.split('//', 1)[0];
|
|
94
|
+
const match = code.match(/applicationId\s*=?\s*["']([A-Za-z0-9_.]+)["']/);
|
|
95
|
+
if (match) {
|
|
96
|
+
return match[1];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Reads a bring-your-own keystore file into the wire signing shape. The
|
|
104
|
+
* flag validator guarantees the passwords and alias are set; the checks
|
|
105
|
+
* here keep that invariant local instead of relying on call-site order.
|
|
106
|
+
*/
|
|
107
|
+
function readProvidedSigning(flags) {
|
|
108
|
+
const { keystorePassword, keyAlias, keyPassword } = flags;
|
|
109
|
+
if (keystorePassword === undefined || keyAlias === undefined || keyPassword === undefined) {
|
|
110
|
+
throw new Error('Signing with your own key requires --keystore-password, --key-alias and --key-password.');
|
|
111
|
+
}
|
|
112
|
+
let keystore;
|
|
113
|
+
try {
|
|
114
|
+
keystore = fs.readFileSync(flags.keystore);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
throw new Error(`Cannot read the keystore file ${flags.keystore}: ${err instanceof Error ? err.message : String(err)}`);
|
|
118
|
+
}
|
|
119
|
+
if (keystore.length === 0) {
|
|
120
|
+
throw new Error(`The keystore file ${flags.keystore} is empty.`);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
keystoreBase64: keystore.toString('base64'),
|
|
124
|
+
keystorePassword,
|
|
125
|
+
keyAlias,
|
|
126
|
+
keyPassword,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Fetches the organization's upload key for the application, generating
|
|
131
|
+
* and escrowing one on first use. The backend's get-or-create makes the
|
|
132
|
+
* concurrent-first-build race safe: whichever caller wins, everyone signs
|
|
133
|
+
* with the same key, because the response data is authoritative.
|
|
134
|
+
*/
|
|
135
|
+
async function resolveEscrowedSigning(client, applicationId) {
|
|
136
|
+
const organizationId = await (0, backend_1.whoAmI)(client);
|
|
137
|
+
const existing = await (0, backend_1.getSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId);
|
|
138
|
+
if (existing) {
|
|
139
|
+
return { signing: asSigningConfig(existing, applicationId), created: false };
|
|
140
|
+
}
|
|
141
|
+
const generated = (0, android_keystore_1.generateAndroidSigningKey)(applicationId);
|
|
142
|
+
const result = await (0, backend_1.putSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId, generated);
|
|
143
|
+
return { signing: asSigningConfig(result.data, applicationId), created: result.created };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Escrows a user-provided key under the application's name. Refuses to
|
|
147
|
+
* proceed when a DIFFERENT key is already escrowed: silently signing with
|
|
148
|
+
* either key would surprise someone, and replacing an upload key is not a
|
|
149
|
+
* side effect a build command should have.
|
|
150
|
+
*/
|
|
151
|
+
async function saveProvidedKey(client, applicationId, provided) {
|
|
152
|
+
const organizationId = await (0, backend_1.whoAmI)(client);
|
|
153
|
+
const result = await (0, backend_1.putSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId, provided);
|
|
154
|
+
if (!result.created && !signingFields.every((f) => result.data[f] === provided[f])) {
|
|
155
|
+
throw new Error(`The organization already has a different upload key escrowed for ${applicationId}. ` +
|
|
156
|
+
'Builds with --sign use that key; drop --save-key to sign with the provided keystore for this build only.');
|
|
157
|
+
}
|
|
158
|
+
return result.created;
|
|
159
|
+
}
|
|
160
|
+
function asSigningConfig(data, applicationId) {
|
|
161
|
+
if (signingFields.some((f) => !data[f])) {
|
|
162
|
+
throw new Error(`The escrowed signing key for ${applicationId} is missing required fields; contact support before retrying.`);
|
|
163
|
+
}
|
|
164
|
+
const { keystoreBase64, keystorePassword, keyAlias, keyPassword } = data;
|
|
165
|
+
return { keystoreBase64, keystorePassword, keyAlias, keyPassword };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=gradle-signing.js.map
|