@limrun/api 0.33.5 → 0.35.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/client.d.mts +3 -0
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +3 -0
  5. package/client.d.ts.map +1 -1
  6. package/client.js +3 -0
  7. package/client.js.map +1 -1
  8. package/client.mjs +3 -0
  9. package/client.mjs.map +1 -1
  10. package/index.d.mts +3 -1
  11. package/index.d.mts.map +1 -1
  12. package/index.d.ts +3 -1
  13. package/index.d.ts.map +1 -1
  14. package/index.js +17 -1
  15. package/index.js.map +1 -1
  16. package/index.mjs +2 -0
  17. package/index.mjs.map +1 -1
  18. package/internal/direct-instance-errors.d.mts +9 -0
  19. package/internal/direct-instance-errors.d.mts.map +1 -1
  20. package/internal/direct-instance-errors.d.ts +9 -0
  21. package/internal/direct-instance-errors.d.ts.map +1 -1
  22. package/internal/direct-instance-errors.js +6 -1
  23. package/internal/direct-instance-errors.js.map +1 -1
  24. package/internal/direct-instance-errors.mjs +5 -1
  25. package/internal/direct-instance-errors.mjs.map +1 -1
  26. package/internal/proxy-transport.d.mts +9 -0
  27. package/internal/proxy-transport.d.mts.map +1 -1
  28. package/internal/proxy-transport.d.ts +9 -0
  29. package/internal/proxy-transport.d.ts.map +1 -1
  30. package/internal/proxy-transport.js +19 -0
  31. package/internal/proxy-transport.js.map +1 -1
  32. package/internal/proxy-transport.mjs +19 -0
  33. package/internal/proxy-transport.mjs.map +1 -1
  34. package/package.json +21 -1
  35. package/rbe-session.d.mts +35 -0
  36. package/rbe-session.d.mts.map +1 -0
  37. package/rbe-session.d.ts +35 -0
  38. package/rbe-session.d.ts.map +1 -0
  39. package/rbe-session.js +72 -0
  40. package/rbe-session.js.map +1 -0
  41. package/rbe-session.mjs +65 -0
  42. package/rbe-session.mjs.map +1 -0
  43. package/rbe-workspace.d.mts +163 -0
  44. package/rbe-workspace.d.mts.map +1 -0
  45. package/rbe-workspace.d.ts +163 -0
  46. package/rbe-workspace.d.ts.map +1 -0
  47. package/rbe-workspace.js +394 -0
  48. package/rbe-workspace.js.map +1 -0
  49. package/rbe-workspace.mjs +382 -0
  50. package/rbe-workspace.mjs.map +1 -0
  51. package/resources/analytics.d.mts +650 -0
  52. package/resources/analytics.d.mts.map +1 -0
  53. package/resources/analytics.d.ts +650 -0
  54. package/resources/analytics.d.ts.map +1 -0
  55. package/resources/analytics.js +22 -0
  56. package/resources/analytics.js.map +1 -0
  57. package/resources/analytics.mjs +18 -0
  58. package/resources/analytics.mjs.map +1 -0
  59. package/resources/index.d.mts +1 -0
  60. package/resources/index.d.mts.map +1 -1
  61. package/resources/index.d.ts +1 -0
  62. package/resources/index.d.ts.map +1 -1
  63. package/resources/index.js +3 -1
  64. package/resources/index.js.map +1 -1
  65. package/resources/index.mjs +1 -0
  66. package/resources/index.mjs.map +1 -1
  67. package/resources/xcode-instances-helpers.d.mts +29 -0
  68. package/resources/xcode-instances-helpers.d.mts.map +1 -1
  69. package/resources/xcode-instances-helpers.d.ts +29 -0
  70. package/resources/xcode-instances-helpers.d.ts.map +1 -1
  71. package/resources/xcode-instances-helpers.js +58 -7
  72. package/resources/xcode-instances-helpers.js.map +1 -1
  73. package/resources/xcode-instances-helpers.mjs +59 -8
  74. package/resources/xcode-instances-helpers.mjs.map +1 -1
  75. package/src/client.ts +17 -0
  76. package/src/index.ts +23 -0
  77. package/src/internal/direct-instance-errors.ts +11 -1
  78. package/src/internal/proxy-transport.ts +22 -0
  79. package/src/rbe-session.ts +92 -0
  80. package/src/rbe-workspace.ts +407 -0
  81. package/src/resources/analytics.ts +743 -0
  82. package/src/resources/index.ts +7 -0
  83. package/src/resources/xcode-instances-helpers.ts +110 -13
  84. package/src/version.ts +1 -1
  85. package/version.d.mts +1 -1
  86. package/version.d.ts +1 -1
  87. package/version.js +1 -1
  88. package/version.mjs +1 -1
@@ -1,5 +1,12 @@
1
1
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
+ export {
4
+ Analytics,
5
+ type AnalyticsInstancesResponse,
6
+ type AnalyticsResponse,
7
+ type AnalyticsGetParams,
8
+ type AnalyticsGetInstancesParams,
9
+ } from './analytics';
3
10
  export {
4
11
  AndroidInstances,
5
12
  type AndroidInstance,
@@ -12,10 +12,11 @@ import {
12
12
  } from '../folder-sync';
13
13
  import { createIgnoreFn } from '../folder-sync-ignore';
14
14
  import { nodeProxyTransport } from '../internal/proxy-transport';
15
- import { directInstanceHttpError } from '../internal/direct-instance-errors';
15
+ import { directInstanceHttpError, isDirectInstanceHttpError } from '../internal/direct-instance-errors';
16
16
  import { LimrunError } from '../core/error';
17
17
  import { validateBuildSettings } from '../build-settings';
18
18
  import { startTcpTunnel, type Tunnel } from '../tunnel';
19
+ import { isTransientError, retryTransient } from '../rbe-session';
19
20
 
20
21
  export type { Tunnel } from '../tunnel';
21
22
 
@@ -192,6 +193,30 @@ export type RbeInstallResult = {
192
193
  installDurationMs?: number;
193
194
  };
194
195
 
196
+ export type RbeUploadOptions =
197
+ | {
198
+ /** Upload as a named asset: the SDK mints the presigned upload URL via assets.getOrCreate. */
199
+ assetName: string;
200
+ /** Optional asset TTL as a Go duration (e.g. "24h", "30m"; "1d" is invalid), forwarded to assets.getOrCreate. */
201
+ ttl?: string;
202
+ signedUploadUrl?: never;
203
+ }
204
+ | {
205
+ /** Upload to a caller-minted presigned Limrun asset storage URL. */
206
+ signedUploadUrl: string;
207
+ assetName?: never;
208
+ ttl?: never;
209
+ };
210
+
211
+ export type RbeUploadResult = {
212
+ /** The .app bundle name of the uploaded build; it is the root directory of the uploaded tar.gz. */
213
+ appName: string;
214
+ /** CFBundleIdentifier of the uploaded app, when known. */
215
+ bundleId?: string;
216
+ /** Presigned download URL of the asset; present when uploading by assetName. */
217
+ signedDownloadUrl?: string;
218
+ };
219
+
195
220
  export type XcodeClient = {
196
221
  /**
197
222
  * Sync source code to the xcode instance. In watch mode, keeps syncing on changes.
@@ -243,6 +268,16 @@ export type XcodeClient = {
243
268
  */
244
269
  startRbeTunnel: (opts?: RbeTunnelOptions) => Promise<Tunnel>;
245
270
 
271
+ /**
272
+ * Upload the latest successful RBE build's app as an asset: the daemon
273
+ * packages the build's .app as a tar.gz (the same artifact format
274
+ * xcodebuild uploads produce) and pushes it to asset storage. Call after
275
+ * `bazel build --config=limrun` succeeds. The build is recorded on the
276
+ * instance asynchronously moments after bazel reports success, so the
277
+ * brief no-build window right after bazel exits is retried automatically.
278
+ */
279
+ uploadLatestRbeBuild: (opts: RbeUploadOptions) => Promise<RbeUploadResult>;
280
+
246
281
  /**
247
282
  * Create a new iOS simulator instance and attach it to this xcode instance.
248
283
  * Deletes the simulator if attach fails so it is never leaked. Returns the new
@@ -368,6 +403,27 @@ async function readJsonResponse<T>(res: Response, operation: string): Promise<T>
368
403
  return JSON.parse(text) as T;
369
404
  }
370
405
 
406
+ /**
407
+ * Mints presigned upload/download URLs for a named asset via assets.getOrCreate,
408
+ * wrapping failures with the asset name (and the original error as cause).
409
+ * Shared by the xcodebuild `--upload` path and `uploadLatestRbeBuild`.
410
+ */
411
+ function mintAssetUploadUrls(
412
+ assets: { getOrCreate: (body: { name: string; ttl?: string }) => Promise<AssetUploadUrls> },
413
+ name: string,
414
+ ttl?: string,
415
+ ): Promise<AssetUploadUrls> {
416
+ return assets.getOrCreate({ name, ...(ttl && { ttl }) }).catch((err) => {
417
+ const message = `Failed to create upload URL for asset '${name}': ${
418
+ err instanceof Error ? err.message : err
419
+ }`;
420
+ // @ts-ignore - not all envs have native support for cause yet
421
+ throw new Error(message, { cause: err });
422
+ });
423
+ }
424
+
425
+ type AssetUploadUrls = { signedUploadUrl: string; signedDownloadUrl: string };
426
+
371
427
  export class XcodeInstances extends GeneratedXcodeInstances {
372
428
  async createClient(params: XcodeCreateClientParams): Promise<XcodeClient> {
373
429
  let apiUrl: string;
@@ -530,21 +586,13 @@ export class XcodeInstances extends GeneratedXcodeInstances {
530
586
  };
531
587
 
532
588
  if (options?.upload && 'assetName' in options.upload) {
533
- const uploadName = options.upload.assetName;
534
- const requestPromise = client.assets
535
- .getOrCreate({ name: uploadName })
536
- .then((asset) => {
589
+ const requestPromise = mintAssetUploadUrls(client.assets, options.upload.assetName).then(
590
+ (asset) => {
537
591
  request.signedUploadUrl = asset.signedUploadUrl;
538
592
  request.additionalMetadata = { signedDownloadUrl: asset.signedDownloadUrl };
539
593
  return request;
540
- })
541
- .catch((err) => {
542
- throw new Error(
543
- `Failed to create upload URL for artifact '${uploadName}': ${
544
- err instanceof Error ? err.message : err
545
- }`,
546
- );
547
- });
594
+ },
595
+ );
548
596
  return exec(requestPromise, { apiUrl, token, log });
549
597
  }
550
598
 
@@ -613,6 +661,55 @@ export class XcodeInstances extends GeneratedXcodeInstances {
613
661
  },
614
662
  );
615
663
  },
664
+
665
+ async uploadLatestRbeBuild(opts: RbeUploadOptions): Promise<RbeUploadResult> {
666
+ let signedUploadUrl: string;
667
+ let signedDownloadUrl: string | undefined;
668
+ if (opts.assetName !== undefined) {
669
+ if (!opts.assetName) {
670
+ throw new Error('assetName must not be empty');
671
+ }
672
+ const asset = await mintAssetUploadUrls(client.assets, opts.assetName, opts.ttl);
673
+ signedUploadUrl = asset.signedUploadUrl;
674
+ signedDownloadUrl = asset.signedDownloadUrl;
675
+ } else {
676
+ signedUploadUrl = opts.signedUploadUrl;
677
+ }
678
+
679
+ const post = async (): Promise<{ appName: string; bundleId?: string }> => {
680
+ // The daemon uploads to asset storage before responding, so this
681
+ // request can go minutes without response bytes.
682
+ const res = await nodeProxyTransport.fetchLongRequest(`${apiUrl}/rbe/upload`, {
683
+ method: 'POST',
684
+ headers: {
685
+ 'Content-Type': 'application/json',
686
+ Authorization: `Bearer ${token}`,
687
+ },
688
+ body: JSON.stringify({ signedUploadUrl }),
689
+ });
690
+ if (res.status === 404) {
691
+ // A vanished instance and a limbuild that predates the endpoint
692
+ // 404 indistinguishably (identical bodies), and neither is the
693
+ // RbeUnsupportedError case (the daemon may well support /rbe),
694
+ // hence a plain two-cause error.
695
+ await res.text().catch(() => undefined);
696
+ throw new Error(
697
+ 'POST /rbe/upload returned 404: the instance may no longer exist, or its limbuild ' +
698
+ 'predates RBE upload support. Recreate the instance and retry.',
699
+ );
700
+ }
701
+ return readJsonResponse<{ appName: string; bundleId?: string }>(res, 'POST /rbe/upload');
702
+ };
703
+
704
+ // Build recording is asynchronous on the daemon (it lands moments
705
+ // after bazel reports success), so the no-build 400 fired right at
706
+ // build end is as transient as a gateway blip; retry both classes.
707
+ const retryOn = (err: unknown) =>
708
+ isTransientError(err) ||
709
+ (isDirectInstanceHttpError(err, 400) && /no successful RBE app build/i.test(err.body));
710
+ const result = await retryTransient(post, { retryOn });
711
+ return { ...result, ...(signedDownloadUrl && { signedDownloadUrl }) };
712
+ },
616
713
  };
617
714
  }
618
715
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.33.5'; // x-release-please-version
1
+ export const VERSION = '0.35.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.33.5";
1
+ export declare const VERSION = "0.35.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.33.5";
1
+ export declare const VERSION = "0.35.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.33.5'; // x-release-please-version
4
+ exports.VERSION = '0.35.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.33.5'; // x-release-please-version
1
+ export const VERSION = '0.35.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map