diff --git a/packages/eas-cli/graphql.schema.json b/packages/eas-cli/graphql.schema.json index ef6a2413c7..7b8a429339 100644 --- a/packages/eas-cli/graphql.schema.json +++ b/packages/eas-cli/graphql.schema.json @@ -1893,6 +1893,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "pendingSentryInstallation", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "PendingSentryInstallation", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "profileImageUrl", "description": null, @@ -1941,6 +1953,18 @@ "isDeprecated": true, "deprecationReason": "Legacy access tokens are deprecated" }, + { + "name": "sentryInstallation", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "SentryInstallation", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "snacks", "description": "Snacks associated with this account", @@ -6665,7 +6689,7 @@ "fields": [ { "name": "createAndroidFcm", - "description": "Create an FCM credential", + "description": "Create an FCM V0/Legacy credential", "args": [ { "name": "accountId", @@ -6709,12 +6733,12 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "FCM Legacy credentials are no longer supported by Google. Use createFcmV1Credential instead." }, { "name": "deleteAndroidFcm", - "description": "Delete an FCM credential", + "description": "Delete an FCM V0/Legacy credential", "args": [ { "name": "id", @@ -9575,6 +9599,18 @@ "isDeprecated": true, "deprecationReason": "No longer supported" }, + { + "name": "profileImageUrl", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "published", "description": "Whether there have been any classic update publishes", @@ -9703,6 +9739,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "filter", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "RuntimeFilterInput", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "first", "description": null, @@ -9772,6 +9820,18 @@ "isDeprecated": true, "deprecationReason": "Classic updates have been deprecated." }, + { + "name": "sentryProject", + "description": null, + "args": [], + "type": { + "kind": "OBJECT", + "name": "SentryProject", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "slug", "description": null, @@ -18475,6 +18535,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "cliVersion", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "completedAt", "description": null, @@ -18668,8 +18740,8 @@ "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "Use 'githubRepository' field instead" }, { "name": "id", @@ -20830,6 +20902,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "LOCAL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "REPACK", "description": null, @@ -21201,6 +21279,83 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "shareLocalBuild", + "description": "Share a local build", + "args": [ + { + "name": "appId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "artifactSource", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ShareArchiveSourceInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "job", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ShareJobInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "metadata", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "BuildMetadataInput", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CreateBuildResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updateBuildMetadata", "description": "Update metadata for EAS Build build", @@ -23886,6 +24041,65 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "CreateSentryProjectInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "appId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryProjectId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryProjectSlug", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "CreateSharedEnvironmentVariableInput", @@ -25356,7 +25570,7 @@ }, { "kind": "OBJECT", - "name": "DeleteUpdateBranchResult", + "name": "DeleteSentryProjectResult", "description": null, "fields": [ { @@ -25383,7 +25597,7 @@ }, { "kind": "OBJECT", - "name": "DeleteUpdateChannelResult", + "name": "DeleteUpdateBranchResult", "description": null, "fields": [ { @@ -25410,34 +25624,7 @@ }, { "kind": "OBJECT", - "name": "DeleteUpdateGroupResult", - "description": null, - "fields": [ - { - "name": "group", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DeleteWebhookResult", + "name": "DeleteUpdateChannelResult", "description": null, "fields": [ { @@ -25464,27 +25651,81 @@ }, { "kind": "OBJECT", - "name": "DeleteWorkerDeploymentResult", + "name": "DeleteUpdateGroupResult", "description": null, "fields": [ { - "name": "deploymentIdentifier", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "WorkerDeploymentIdentifier", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", + "name": "group", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DeleteWebhookResult", + "description": null, + "fields": [ + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DeleteWorkerDeploymentResult", + "description": null, + "fields": [ + { + "name": "deploymentIdentifier", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "WorkerDeploymentIdentifier", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", "description": null, "args": [], "type": { @@ -27284,6 +27525,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "LogRocketOrganizationEntity", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "LogRocketProjectEntity", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "UserInvitationEntity", "description": null, @@ -30148,6 +30401,65 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "GenerateSentryTokenResult", + "description": null, + "fields": [ + { + "name": "installationId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "orgSlug", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "token", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "GetSignedAssetUploadSpecificationsResult", @@ -36863,6 +37175,81 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "LinkSentryInstallationToExpoAccountInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "accountId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "code", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "installationId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryOrgSlug", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "LinkSharedEnvironmentVariableInput", @@ -39446,6 +39833,97 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "PendingSentryInstallation", + "description": null, + "fields": [ + { + "name": "account", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Account", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "installationId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "orgSlug", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "Permission", @@ -40352,6 +40830,26 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "platform", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserAgentPlatform", + "ofType": null + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "requestId", "description": null, @@ -41317,7 +41815,7 @@ }, { "name": "androidFcm", - "description": "Mutations that modify an FCM credential", + "description": "Mutations that modify an FCM V0/Legacy credential", "args": [], "type": { "kind": "NON_NULL", @@ -41993,6 +42491,38 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "sentryInstallation", + "description": "Mutations for Sentry installations", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SentryInstallationMutation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryProject", + "description": "Mutations for Sentry projects", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SentryProjectMutation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "submission", "description": "Mutations that modify an EAS Submit submission", @@ -43318,6 +43848,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isFingerprint", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updatedAt", "description": null, @@ -43603,6 +44149,26 @@ "defaultValue": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "runtimeVersions", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null } ], "interfaces": null, @@ -44757,6 +45323,530 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "SentryInstallation", + "description": null, + "fields": [ + { + "name": "account", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Account", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "installationId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "orgSlug", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SentryInstallationMutation", + "description": null, + "fields": [ + { + "name": "confirmPendingSentryInstallation", + "description": "Confirm a pending Sentry installation", + "args": [ + { + "name": "installationId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SentryInstallation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "generateSentryToken", + "description": "Generate a Sentry token for an installation", + "args": [ + { + "name": "accountId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "GenerateSentryTokenResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "linkSentryInstallationToExpoAccount", + "description": "Link a Sentry installation to an Expo account", + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "LinkSentryInstallationToExpoAccountInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PendingSentryInstallation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SentryProject", + "description": null, + "fields": [ + { + "name": "app", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "App", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "createdAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryInstallationId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryProjectId", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "sentryProjectSlug", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SentryProjectMutation", + "description": null, + "fields": [ + { + "name": "createSentryProject", + "description": "Create a Sentry project", + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CreateSentryProjectInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SentryProject", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "deleteSentryProject", + "description": "Delete a Sentry project by ID", + "args": [ + { + "name": "sentryProjectId", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DeleteSentryProjectResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ShareArchiveSourceInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "bucketKey", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "ShareArchiveSourceType", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "ShareArchiveSourceType", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "GCS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "ShareJobInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "developmentClient", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "experimental", + "description": null, + "type": { + "kind": "SCALAR", + "name": "JSONObject", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "platform", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AppPlatform", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "simulator", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Snack", @@ -49874,6 +50964,18 @@ "name": "createUploadSession", "description": "Create an Upload Session", "args": [ + { + "name": "filename", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "type", "description": null, @@ -49935,6 +51037,12 @@ "isDeprecated": true, "deprecationReason": "Use EAS_BUILD_GCS_PROJECT_SOURCES instead." }, + { + "name": "EAS_SHARE_GCS_APP_ARCHIVE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "EAS_SUBMIT_APP_ARCHIVE", "description": null, @@ -52225,6 +53333,41 @@ ], "possibleTypes": null }, + { + "kind": "ENUM", + "name": "UserAgentPlatform", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ANDROID", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "APPLE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UNKNOWN", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEB", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "UserAppPinMutation", @@ -52452,6 +53595,22 @@ "ofType": null } }, + "isDeprecated": true, + "deprecationReason": "Use userActor instead" + }, + { + "name": "userActor", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INTERFACE", + "name": "UserActor", + "ofType": null + } + }, "isDeprecated": false, "deprecationReason": null }, @@ -56974,6 +58133,22 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "platform", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserAgentPlatform", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "region", "description": null, @@ -57395,6 +58570,104 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "byPathname", + "description": null, + "args": [ + { + "name": "limit", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "orderBy", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "RequestsOrderBy", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPathnameEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "byPlatform", + "description": null, + "args": [ + { + "name": "limit", + "description": null, + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "orderBy", + "description": null, + "type": { + "kind": "INPUT_OBJECT", + "name": "RequestsOrderBy", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPlatformEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "byResponseType", "description": null, @@ -58440,6 +59713,92 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPathnameEdge", + "description": null, + "fields": [ + { + "name": "node", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsAggregationNode", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pathname", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPlatformEdge", + "description": null, + "fields": [ + { + "name": "node", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsAggregationNode", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "platform", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "UserAgentPlatform", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "WorkerDeploymentRequestsResponseTypeEdge", @@ -58671,6 +60030,54 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "byPathname", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPathnameEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "byPlatform", + "description": null, + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkerDeploymentRequestsPlatformEdge", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "byResponseType", "description": null, @@ -59700,6 +61107,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "FINGERPRINT", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "GET_BUILD", "description": null, @@ -60490,6 +61903,30 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "triggeringLabelName", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "triggeringSchedule", + "description": null, + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updatedAt", "description": null, @@ -60914,6 +62351,12 @@ "inputFields": null, "interfaces": null, "enumValues": [ + { + "name": "GITHUB_PULL_REQUEST_LABELED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "GITHUB_PULL_REQUEST_OPENED", "description": null, @@ -60943,6 +62386,12 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "SCHEDULE", + "description": null, + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null diff --git a/packages/eas-cli/package.json b/packages/eas-cli/package.json index b4cbe34f7a..49e531db54 100644 --- a/packages/eas-cli/package.json +++ b/packages/eas-cli/package.json @@ -68,6 +68,7 @@ "nanoid": "3.3.8", "node-fetch": "2.6.7", "node-forge": "1.3.1", + "node-stream-zip": "1.15.0", "nullthrows": "1.1.1", "ora": "5.1.0", "pkg-dir": "4.2.0", diff --git a/packages/eas-cli/src/commands/share.ts b/packages/eas-cli/src/commands/share.ts new file mode 100644 index 0000000000..29fb944b49 --- /dev/null +++ b/packages/eas-cli/src/commands/share.ts @@ -0,0 +1,298 @@ +import { Platform } from '@expo/eas-build-job'; +import { Flags } from '@oclif/core'; +import fg from 'fast-glob'; +import fs from 'fs-extra'; +import StreamZip from 'node-stream-zip'; +import path from 'path'; +import tar from 'tar'; + +import { getBuildLogsUrl } from '../build/utils/url'; +import EasCommand from '../commandUtils/EasCommand'; +import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient'; +import { EASNonInteractiveFlag } from '../commandUtils/flags'; +import { DistributionType, ShareArchiveSourceType, UploadSessionType } from '../graphql/generated'; +import { FingerprintMutation } from '../graphql/mutations/FingerprintMutation'; +import { ShareBuildMutation } from '../graphql/mutations/ShareBuildMutation'; +import { toAppPlatform } from '../graphql/types/AppPlatform'; +import Log from '../log'; +import { promptAsync } from '../prompts'; +import { uploadFileAtPathToGCSAsync } from '../uploads'; +import { createProgressTracker } from '../utils/progress'; + +export default class BuildUpload extends EasCommand { + static override description = 'upload a local build and generate a sharable link'; + + static override flags = { + platform: Flags.enum<Platform.IOS | Platform.ANDROID>({ + char: 'p', + options: [Platform.IOS, Platform.ANDROID], + }), + 'build-path': Flags.string({ + description: 'Path for the local build', + }), + fingerprint: Flags.string({ + description: 'Fingerprint hash of the local build', + }), + ...EASNonInteractiveFlag, + }; + + static override contextDefinition = { + ...this.ContextOptions.ProjectId, + ...this.ContextOptions.LoggedIn, + }; + + async runAsync(): Promise<void> { + const { flags } = await this.parse(BuildUpload); + const { 'build-path': buildPath, fingerprint: manualFingerprintHash } = flags; + const { + projectId, + loggedIn: { graphqlClient }, + } = await this.getContextAsync(BuildUpload, { + nonInteractive: false, + }); + + const platform = await this.selectPlatformAsync(flags.platform); + const localBuildPath = await resolveLocalBuildPathAsync(platform, buildPath); + + const { + fingerprintHash: buildFingerprintHash, + developmentClient, + simulator, + } = await extractAppMetadataAsync(localBuildPath, platform); + + let fingerprint = manualFingerprintHash ?? buildFingerprintHash; + if (fingerprint) { + if ( + manualFingerprintHash && + buildFingerprintHash && + manualFingerprintHash !== buildFingerprintHash + ) { + const selectedAnswer = await promptAsync({ + name: 'fingerprint', + message: `The provided fingerprint hash ${manualFingerprintHash} does not match the fingerprint hash of the build ${buildFingerprintHash}. Which fingerprint do you want to use?`, + type: 'select', + choices: [{ title: manualFingerprintHash }, { title: buildFingerprintHash }], + }); + fingerprint = String(selectedAnswer.fingerprint); + } + + await FingerprintMutation.createFingerprintAsync(graphqlClient, projectId, { + hash: fingerprint, + }); + } + + Log.log('Uploading your app archive to EAS'); + const bucketKey = await uploadAppArchiveAsync(graphqlClient, localBuildPath); + + const build = await ShareBuildMutation.uploadLocalBuildAsync( + graphqlClient, + projectId, + { platform: toAppPlatform(platform), simulator }, + { type: ShareArchiveSourceType.Gcs, bucketKey }, + { distribution: DistributionType.Internal, fingerprintHash: fingerprint, developmentClient } + ); + + Log.withTick(`Here is a sharable link of your build: ${getBuildLogsUrl(build)}`); + } + + private async selectPlatformAsync(platform?: Platform): Promise<Platform> { + if (platform) { + return platform; + } + const { resolvedPlatform } = await promptAsync({ + type: 'select', + message: 'Select platform', + name: 'resolvedPlatform', + choices: [ + { title: 'Android', value: Platform.ANDROID }, + { title: 'iOS', value: Platform.IOS }, + ], + }); + return resolvedPlatform; + } +} + +async function resolveLocalBuildPathAsync( + platform: Platform, + inputBuildPath?: string +): Promise<string> { + const applicationArchivePatternOrPath = + inputBuildPath ?? + (platform === Platform.ANDROID + ? 'android/app/build/outputs/**/*.{apk,aab}' + : 'ios/build/Build/Products/*simulator/*.app'); + + let applicationArchives = await findArtifactsAsync({ + rootDir: process.cwd(), + patternOrPath: applicationArchivePatternOrPath, + }); + + if (applicationArchives.length === 0 && !inputBuildPath) { + Log.warn(`No application archives found at ${applicationArchivePatternOrPath}.`); + const { path } = await promptAsync({ + type: 'text', + name: 'path', + message: 'Provide a path to the application archive:', + validate: value => (value ? true : 'Path may not be empty.'), + }); + applicationArchives = await findArtifactsAsync({ + rootDir: process.cwd(), + patternOrPath: path, + }); + } + + if (applicationArchives.length === 1) { + return applicationArchives[0]; + } + + if (applicationArchives.length > 1) { + const { path } = await promptAsync({ + type: 'select', + name: 'path', + message: 'Found multiple application archives. Select one:', + choices: applicationArchives.map(archivePath => { + return { + title: archivePath, + value: archivePath, + }; + }), + }); + return path; + } + + throw new Error(`Found no application archives at ${inputBuildPath}.`); +} + +async function findArtifactsAsync({ + rootDir, + patternOrPath, +}: { + rootDir: string; + patternOrPath: string; +}): Promise<string[]> { + const files: string[] = path.isAbsolute(patternOrPath) + ? (await fs.pathExists(patternOrPath)) + ? [patternOrPath] + : [] + : await fg(patternOrPath, { cwd: rootDir, onlyFiles: false }); + + return files.map(filePath => { + // User may provide an absolute path as input in which case + // fg will return an absolute path. + if (path.isAbsolute(filePath)) { + return filePath; + } + + // User may also provide a relative path in which case + // fg will return a path relative to rootDir. + return path.join(rootDir, filePath); + }); +} + +async function uploadAppArchiveAsync( + graphqlClient: ExpoGraphqlClient, + path: string +): Promise<string> { + const fileSize = (await fs.stat(path)).size; + const bucketKey = await uploadFileAtPathToGCSAsync( + graphqlClient, + UploadSessionType.EasShareGcsAppArchive, + path, + createProgressTracker({ + total: fileSize, + message: 'Uploading to EAS Share', + completedMessage: 'Uploaded to EAS Share', + }) + ); + return bucketKey; +} + +type AppMetadata = { + fingerprintHash?: string; + developmentClient: boolean; + simulator: boolean; +}; + +async function extractAppMetadataAsync( + buildPath: string, + platform: Platform +): Promise<AppMetadata> { + let developmentClient = false; + let fingerprintHash: string | undefined; + const simulator = platform === Platform.IOS; + + let basePath = platform === Platform.ANDROID ? 'assets/' : buildPath; + const fingerprintFilePath = + platform === Platform.ANDROID ? 'fingerprint' : 'EXUpdates.bundle/fingerprint'; + const devMenuBundlePath = + platform === Platform.ANDROID ? 'EXDevMenuApp.android.js' : 'EXDevMenu.bundle/'; + + const buildExtension = path.extname(buildPath); + if (['.apk', '.ipa', '.aab'].includes(buildExtension)) { + const zip = new StreamZip.async({ file: buildPath }); + try { + if (buildExtension === '.ipa') { + const entries = await zip.entries(); + basePath = + Object.keys(entries).find( + entry => entry.startsWith('Payload/') && entry.endsWith('.app/') + ) ?? basePath; + } + + developmentClient = Boolean(await zip.entry(path.join(basePath, devMenuBundlePath))); + if (await zip.entry(path.join(basePath, fingerprintFilePath))) { + fingerprintHash = (await zip.entryData(path.join(basePath, fingerprintFilePath))).toString( + 'utf-8' + ); + } + } catch (err) { + Log.error(`Error reading ${buildExtension}: ${err}`); + } finally { + await zip.close(); + } + } else if (buildExtension === '.app') { + developmentClient = await fs.exists(path.join(basePath, devMenuBundlePath)); + + if (await fs.exists(path.join(basePath, fingerprintFilePath))) { + fingerprintHash = await fs.readFile(path.join(basePath, fingerprintFilePath), 'utf8'); + } + } else { + // Use tar to list files in the archive + try { + let fingerprintHashPromise: Promise<string> | undefined; + await tar.list({ + file: buildPath, + // eslint-disable-next-line async-protect/async-suffix + onentry: entry => { + if (entry.path.endsWith(devMenuBundlePath)) { + developmentClient = true; + } + if (entry.path.endsWith(fingerprintFilePath)) { + fingerprintHashPromise = new Promise<string>(async (resolve, reject) => { + try { + let content = ''; + for await (const chunk of entry) { + content += chunk.toString('utf8'); + } + resolve(content); + } catch (error) { + reject(error); + } + }); + } + }, + }); + if (fingerprintHashPromise !== undefined) { + fingerprintHash = await fingerprintHashPromise; + } + } catch (err) { + Log.error(`Error reading ${buildExtension}: ${err}`); + } + } + + return { + developmentClient, + fingerprintHash, + simulator, + }; +} diff --git a/packages/eas-cli/src/graphql/generated.ts b/packages/eas-cli/src/graphql/generated.ts index a71f81f8d9..7636dc7fb7 100644 --- a/packages/eas-cli/src/graphql/generated.ts +++ b/packages/eas-cli/src/graphql/generated.ts @@ -147,10 +147,12 @@ export type Account = { owner?: Maybe<User>; /** Owning UserActor of this account if personal account */ ownerUserActor?: Maybe<UserActor>; + pendingSentryInstallation?: Maybe<PendingSentryInstallation>; profileImageUrl: Scalars['String']['output']; pushSecurityEnabled: Scalars['Boolean']['output']; /** @deprecated Legacy access tokens are deprecated */ requiresAccessTokenForPushSecurity: Scalars['Boolean']['output']; + sentryInstallation?: Maybe<SentryInstallation>; /** Snacks associated with this account */ snacks: Array<Snack>; /** SSO configuration for this account */ @@ -1053,9 +1055,12 @@ export type AndroidFcmInput = { export type AndroidFcmMutation = { __typename?: 'AndroidFcmMutation'; - /** Create an FCM credential */ + /** + * Create an FCM V0/Legacy credential + * @deprecated FCM Legacy credentials are no longer supported by Google. Use createFcmV1Credential instead. + */ createAndroidFcm: AndroidFcm; - /** Delete an FCM credential */ + /** Delete an FCM V0/Legacy credential */ deleteAndroidFcm: DeleteAndroidFcmResult; }; @@ -1318,6 +1323,7 @@ export type App = Project & { privacy: Scalars['String']['output']; /** @deprecated No longer supported */ privacySetting: AppPrivacy; + profileImageUrl?: Maybe<Scalars['String']['output']>; /** * Whether there have been any classic update publishes * @deprecated Classic updates have been deprecated. @@ -1342,6 +1348,7 @@ export type App = Project & { * @deprecated Classic updates have been deprecated. */ sdkVersion: Scalars['String']['output']; + sentryProject?: Maybe<SentryProject>; slug: Scalars['String']['output']; /** EAS Submissions associated with this app */ submissions: Array<Submission>; @@ -1525,6 +1532,7 @@ export type AppLikedByArgs = { export type AppRuntimesArgs = { after?: InputMaybe<Scalars['String']['input']>; before?: InputMaybe<Scalars['String']['input']>; + filter?: InputMaybe<RuntimeFilterInput>; first?: InputMaybe<Scalars['Int']['input']>; last?: InputMaybe<Scalars['Int']['input']>; }; @@ -2749,6 +2757,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & { /** @deprecated Use 'updateChannel' field instead. */ channel?: Maybe<Scalars['String']['output']>; childBuild?: Maybe<Build>; + cliVersion?: Maybe<Scalars['String']['output']>; completedAt?: Maybe<Scalars['DateTime']['output']>; createdAt: Scalars['DateTime']['output']; customNodeVersion?: Maybe<Scalars['String']['output']>; @@ -2764,6 +2773,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & { gitCommitHash?: Maybe<Scalars['String']['output']>; gitCommitMessage?: Maybe<Scalars['String']['output']>; gitRef?: Maybe<Scalars['String']['output']>; + /** @deprecated Use 'githubRepository' field instead */ githubRepositoryOwnerAndName?: Maybe<Scalars['String']['output']>; id: Scalars['ID']['output']; /** Queue position is 1-indexed */ @@ -3020,6 +3030,7 @@ export type BuildMetrics = { export enum BuildMode { Build = 'BUILD', Custom = 'CUSTOM', + Local = 'LOCAL', Repack = 'REPACK', Resign = 'RESIGN' } @@ -3048,6 +3059,8 @@ export type BuildMutation = { retryBuild: Build; /** Retry an iOS EAS Build */ retryIosBuild: Build; + /** Share a local build */ + shareLocalBuild: CreateBuildResult; /** Update metadata for EAS Build build */ updateBuildMetadata: Build; }; @@ -3096,6 +3109,14 @@ export type BuildMutationRetryIosBuildArgs = { }; +export type BuildMutationShareLocalBuildArgs = { + appId: Scalars['ID']['input']; + artifactSource: ShareArchiveSourceInput; + job: ShareJobInput; + metadata?: InputMaybe<BuildMetadataInput>; +}; + + export type BuildMutationUpdateBuildMetadataArgs = { buildId: Scalars['ID']['input']; metadata: BuildMetadataInput; @@ -3472,6 +3493,12 @@ export type CreateIosSubmissionInput = { submittedBuildId?: InputMaybe<Scalars['ID']['input']>; }; +export type CreateSentryProjectInput = { + appId: Scalars['ID']['input']; + sentryProjectId: Scalars['String']['input']; + sentryProjectSlug: Scalars['String']['input']; +}; + export type CreateSharedEnvironmentVariableInput = { environments?: InputMaybe<Array<EnvironmentVariableEnvironment>>; fileName?: InputMaybe<Scalars['String']['input']>; @@ -3691,6 +3718,11 @@ export type DeleteSsoUserResult = { id: Scalars['ID']['output']; }; +export type DeleteSentryProjectResult = { + __typename?: 'DeleteSentryProjectResult'; + id: Scalars['ID']['output']; +}; + export type DeleteUpdateBranchResult = { __typename?: 'DeleteUpdateBranchResult'; id: Scalars['ID']['output']; @@ -4001,6 +4033,8 @@ export enum EntityTypeName { CustomerEntity = 'CustomerEntity', GoogleServiceAccountKeyEntity = 'GoogleServiceAccountKeyEntity', IosAppCredentialsEntity = 'IosAppCredentialsEntity', + LogRocketOrganizationEntity = 'LogRocketOrganizationEntity', + LogRocketProjectEntity = 'LogRocketProjectEntity', UserInvitationEntity = 'UserInvitationEntity', UserPermissionEntity = 'UserPermissionEntity', WorkerCustomDomainEntity = 'WorkerCustomDomainEntity', @@ -4388,6 +4422,13 @@ export type GenerateLogRocketReplayTokenResult = { replayToken: Scalars['String']['output']; }; +export type GenerateSentryTokenResult = { + __typename?: 'GenerateSentryTokenResult'; + installationId: Scalars['ID']['output']; + orgSlug: Scalars['String']['output']; + token: Scalars['String']['output']; +}; + export type GetSignedAssetUploadSpecificationsResult = { __typename?: 'GetSignedAssetUploadSpecificationsResult'; specifications: Array<Scalars['String']['output']>; @@ -5287,6 +5328,13 @@ export type LinkLogRocketOrganizationToExpoAccountInput = { state: Scalars['String']['input']; }; +export type LinkSentryInstallationToExpoAccountInput = { + accountId: Scalars['ID']['input']; + code: Scalars['String']['input']; + installationId: Scalars['ID']['input']; + sentryOrgSlug: Scalars['String']['input']; +}; + export type LinkSharedEnvironmentVariableInput = { appId: Scalars['ID']['input']; environment?: InputMaybe<EnvironmentVariableEnvironment>; @@ -5695,6 +5743,15 @@ export type PaymentDetails = { id: Scalars['ID']['output']; }; +export type PendingSentryInstallation = { + __typename?: 'PendingSentryInstallation'; + account: Account; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + installationId: Scalars['String']['output']; + orgSlug: Scalars['String']['output']; +}; + export enum Permission { Admin = 'ADMIN', Own = 'OWN', @@ -5797,6 +5854,7 @@ export type RequestsFilters = { method?: InputMaybe<Array<RequestMethod>>; os?: InputMaybe<Array<UserAgentOs>>; pathname?: InputMaybe<Scalars['String']['input']>; + platform?: InputMaybe<Array<UserAgentPlatform>>; requestId?: InputMaybe<Array<Scalars['WorkerDeploymentRequestID']['input']>>; responseType?: InputMaybe<Array<ResponseType>>; status?: InputMaybe<Array<Scalars['Int']['input']>>; @@ -5945,7 +6003,7 @@ export type RootMutation = { androidAppBuildCredentials: AndroidAppBuildCredentialsMutation; /** Mutations that modify the credentials for an Android app */ androidAppCredentials: AndroidAppCredentialsMutation; - /** Mutations that modify an FCM credential */ + /** Mutations that modify an FCM V0/Legacy credential */ androidFcm: AndroidFcmMutation; /** Mutations that modify a Keystore */ androidKeystore: AndroidKeystoreMutation; @@ -6021,6 +6079,10 @@ export type RootMutation = { notificationSubscription: NotificationSubscriptionMutation; /** Mutations that create, update, and delete Robots */ robot: RobotMutation; + /** Mutations for Sentry installations */ + sentryInstallation: SentryInstallationMutation; + /** Mutations for Sentry projects */ + sentryProject: SentryProjectMutation; /** Mutations that modify an EAS Submit submission */ submission: SubmissionMutation; update: UpdateMutation; @@ -6211,6 +6273,7 @@ export type Runtime = { fingerprint?: Maybe<Fingerprint>; firstBuildCreatedAt?: Maybe<Scalars['DateTime']['output']>; id: Scalars['ID']['output']; + isFingerprint: Scalars['Boolean']['output']; updatedAt: Scalars['DateTime']['output']; updates: AppUpdatesConnection; version: Scalars['String']['output']; @@ -6264,6 +6327,7 @@ export type RuntimeEdge = { export type RuntimeFilterInput = { /** Only return runtimes shared with this branch */ branchId?: InputMaybe<Scalars['String']['input']>; + runtimeVersions?: InputMaybe<Array<Scalars['String']['input']>>; }; export type RuntimeQuery = { @@ -6423,6 +6487,85 @@ export type SecondFactorRegenerateBackupCodesResult = { plaintextBackupCodes: Array<Scalars['String']['output']>; }; +export type SentryInstallation = { + __typename?: 'SentryInstallation'; + account: Account; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + installationId: Scalars['String']['output']; + orgSlug: Scalars['String']['output']; +}; + +export type SentryInstallationMutation = { + __typename?: 'SentryInstallationMutation'; + /** Confirm a pending Sentry installation */ + confirmPendingSentryInstallation: SentryInstallation; + /** Generate a Sentry token for an installation */ + generateSentryToken: GenerateSentryTokenResult; + /** Link a Sentry installation to an Expo account */ + linkSentryInstallationToExpoAccount: PendingSentryInstallation; +}; + + +export type SentryInstallationMutationConfirmPendingSentryInstallationArgs = { + installationId: Scalars['ID']['input']; +}; + + +export type SentryInstallationMutationGenerateSentryTokenArgs = { + accountId: Scalars['ID']['input']; +}; + + +export type SentryInstallationMutationLinkSentryInstallationToExpoAccountArgs = { + input: LinkSentryInstallationToExpoAccountInput; +}; + +export type SentryProject = { + __typename?: 'SentryProject'; + app: App; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + sentryInstallationId: Scalars['ID']['output']; + sentryProjectId: Scalars['String']['output']; + sentryProjectSlug: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; +}; + +export type SentryProjectMutation = { + __typename?: 'SentryProjectMutation'; + /** Create a Sentry project */ + createSentryProject: SentryProject; + /** Delete a Sentry project by ID */ + deleteSentryProject: DeleteSentryProjectResult; +}; + + +export type SentryProjectMutationCreateSentryProjectArgs = { + input: CreateSentryProjectInput; +}; + + +export type SentryProjectMutationDeleteSentryProjectArgs = { + sentryProjectId: Scalars['ID']['input']; +}; + +export type ShareArchiveSourceInput = { + bucketKey: Scalars['String']['input']; + type: ShareArchiveSourceType; +}; + +export enum ShareArchiveSourceType { + Gcs = 'GCS' +} + +export type ShareJobInput = { + developmentClient?: InputMaybe<Scalars['Boolean']['input']>; + experimental?: InputMaybe<Scalars['JSONObject']['input']>; + platform: AppPlatform; + simulator?: InputMaybe<Scalars['Boolean']['input']>; +}; + export type Snack = Project & { __typename?: 'Snack'; /** Description of the Snack */ @@ -7154,6 +7297,7 @@ export type UploadSessionCreateAppScopedUploadSessionArgs = { export type UploadSessionCreateUploadSessionArgs = { + filename?: InputMaybe<Scalars['String']['input']>; type: UploadSessionType; }; @@ -7162,6 +7306,7 @@ export enum UploadSessionType { EasBuildGcsProjectSources = 'EAS_BUILD_GCS_PROJECT_SOURCES', /** @deprecated Use EAS_BUILD_GCS_PROJECT_SOURCES instead. */ EasBuildProjectSources = 'EAS_BUILD_PROJECT_SOURCES', + EasShareGcsAppArchive = 'EAS_SHARE_GCS_APP_ARCHIVE', /** @deprecated Use EAS_SUBMIT_GCS_APP_ARCHIVE instead. */ EasSubmitAppArchive = 'EAS_SUBMIT_APP_ARCHIVE', EasSubmitGcsAppArchive = 'EAS_SUBMIT_GCS_APP_ARCHIVE', @@ -7492,6 +7637,13 @@ export enum UserAgentOs { Windows = 'WINDOWS' } +export enum UserAgentPlatform { + Android = 'ANDROID', + Apple = 'APPLE', + Unknown = 'UNKNOWN', + Web = 'WEB' +} + export type UserAppPinMutation = { __typename?: 'UserAppPinMutation'; pinApp: Scalars['ID']['output']; @@ -7519,7 +7671,9 @@ export type UserAuditLog = { targetEntityMutationType: TargetEntityMutationType; targetEntityTypeName: UserEntityTypeName; targetEntityTypePublicName: Scalars['String']['output']; + /** @deprecated Use userActor instead */ user: User; + userActor: UserActor; websiteMessage: Scalars['String']['output']; }; @@ -8108,6 +8262,7 @@ export type WorkerDeploymentRequestNode = { method: Scalars['String']['output']; os?: Maybe<UserAgentOs>; pathname: Scalars['String']['output']; + platform: UserAgentPlatform; region?: Maybe<Scalars['String']['output']>; requestId: Scalars['WorkerDeploymentRequestID']['output']; requestTimestamp: Scalars['DateTime']['output']; @@ -8126,6 +8281,8 @@ export type WorkerDeploymentRequests = { byCountry: Array<WorkerDeploymentRequestsCountryEdge>; byMethod: Array<WorkerDeploymentRequestsMethodEdge>; byOS: Array<WorkerDeploymentRequestsOperatingSystemEdge>; + byPathname: Array<WorkerDeploymentRequestsPathnameEdge>; + byPlatform: Array<WorkerDeploymentRequestsPlatformEdge>; byResponseType: Array<WorkerDeploymentRequestsResponseTypeEdge>; byStatusType: Array<WorkerDeploymentRequestsStatusTypeEdge>; interval: Scalars['Int']['output']; @@ -8172,6 +8329,18 @@ export type WorkerDeploymentRequestsByOsArgs = { }; +export type WorkerDeploymentRequestsByPathnameArgs = { + limit?: InputMaybe<Scalars['Int']['input']>; + orderBy?: InputMaybe<RequestsOrderBy>; +}; + + +export type WorkerDeploymentRequestsByPlatformArgs = { + limit?: InputMaybe<Scalars['Int']['input']>; + orderBy?: InputMaybe<RequestsOrderBy>; +}; + + export type WorkerDeploymentRequestsByResponseTypeArgs = { limit?: InputMaybe<Scalars['Int']['input']>; orderBy?: InputMaybe<RequestsOrderBy>; @@ -8262,6 +8431,18 @@ export type WorkerDeploymentRequestsOperatingSystemEdge = { os?: Maybe<UserAgentOs>; }; +export type WorkerDeploymentRequestsPathnameEdge = { + __typename?: 'WorkerDeploymentRequestsPathnameEdge'; + node: WorkerDeploymentRequestsAggregationNode; + pathname: Scalars['String']['output']; +}; + +export type WorkerDeploymentRequestsPlatformEdge = { + __typename?: 'WorkerDeploymentRequestsPlatformEdge'; + node: WorkerDeploymentRequestsAggregationNode; + platform: UserAgentPlatform; +}; + export type WorkerDeploymentRequestsResponseTypeEdge = { __typename?: 'WorkerDeploymentRequestsResponseTypeEdge'; node: WorkerDeploymentRequestsAggregationNode; @@ -8282,6 +8463,8 @@ export type WorkerDeploymentRequestsTimeseriesEdge = { byCountry: Array<WorkerDeploymentRequestsCountryEdge>; byMethod: Array<WorkerDeploymentRequestsMethodEdge>; byOS: Array<WorkerDeploymentRequestsOperatingSystemEdge>; + byPathname: Array<WorkerDeploymentRequestsPathnameEdge>; + byPlatform: Array<WorkerDeploymentRequestsPlatformEdge>; byResponseType: Array<WorkerDeploymentRequestsResponseTypeEdge>; byStatusType: Array<WorkerDeploymentRequestsStatusTypeEdge>; node?: Maybe<WorkerDeploymentRequestsAggregationNode>; @@ -8405,6 +8588,7 @@ export enum WorkflowJobType { Build = 'BUILD', Custom = 'CUSTOM', Deploy = 'DEPLOY', + Fingerprint = 'FINGERPRINT', GetBuild = 'GET_BUILD', MaestroTest = 'MAESTRO_TEST', RequireApproval = 'REQUIRE_APPROVAL', @@ -8503,6 +8687,8 @@ export type WorkflowRun = ActivityTimelineProjectActivity & { sourceExpiresAt?: Maybe<Scalars['DateTime']['output']>; status: WorkflowRunStatus; triggerEventType: WorkflowRunTriggerEventType; + triggeringLabelName?: Maybe<Scalars['String']['output']>; + triggeringSchedule?: Maybe<Scalars['String']['output']>; updatedAt: Scalars['DateTime']['output']; workflow: Workflow; workflowRevision?: Maybe<WorkflowRevision>; @@ -8570,11 +8756,13 @@ export enum WorkflowRunStatus { } export enum WorkflowRunTriggerEventType { + GithubPullRequestLabeled = 'GITHUB_PULL_REQUEST_LABELED', GithubPullRequestOpened = 'GITHUB_PULL_REQUEST_OPENED', GithubPullRequestReopened = 'GITHUB_PULL_REQUEST_REOPENED', GithubPullRequestSynchronize = 'GITHUB_PULL_REQUEST_SYNCHRONIZE', GithubPush = 'GITHUB_PUSH', - Manual = 'MANUAL' + Manual = 'MANUAL', + Schedule = 'SCHEDULE' } export type WorkflowRunsConnection = { @@ -9282,6 +9470,16 @@ export type SetRolloutPercentageMutationVariables = Exact<{ export type SetRolloutPercentageMutation = { __typename?: 'RootMutation', update: { __typename?: 'UpdateMutation', setRolloutPercentage: { __typename?: 'Update', id: string, group: string, message?: string | null, createdAt: any, runtimeVersion: string, platform: string, manifestFragment: string, isRollBackToEmbedded: boolean, manifestPermalink: string, gitCommitHash?: string | null, rolloutPercentage?: number | null, actor?: { __typename: 'Robot', firstName?: string | null, id: string } | { __typename: 'SSOUser', username: string, id: string } | { __typename: 'User', username: string, id: string } | null, branch: { __typename?: 'UpdateBranch', id: string, name: string }, codeSigningInfo?: { __typename?: 'CodeSigningInfo', keyid: string, sig: string, alg: string } | null, rolloutControlUpdate?: { __typename?: 'Update', id: string } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string, debugInfoUrl?: string | null, source?: { __typename?: 'FingerprintSource', type: FingerprintSourceType, bucketKey: string, isDebugFingerprint?: boolean | null } | null } | null } } }; +export type UploadLocalBuildMutationVariables = Exact<{ + appId: Scalars['ID']['input']; + jobInput: ShareJobInput; + artifactSource: ShareArchiveSourceInput; + metadata?: InputMaybe<BuildMetadataInput>; +}>; + + +export type UploadLocalBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', shareLocalBuild: { __typename?: 'CreateBuildResult', build: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, initiatingActor?: { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string }, metrics?: { __typename?: 'BuildMetrics', buildWaitTime?: number | null, buildQueueTime?: number | null, buildDuration?: number | null } | null } } } }; + export type CreateAndroidSubmissionMutationVariables = Exact<{ appId: Scalars['ID']['input']; config: AndroidSubmissionConfigInput; @@ -9304,6 +9502,7 @@ export type CreateIosSubmissionMutation = { __typename?: 'RootMutation', submiss export type CreateUploadSessionMutationVariables = Exact<{ type: UploadSessionType; + filename?: InputMaybe<Scalars['String']['input']>; }>; diff --git a/packages/eas-cli/src/graphql/mutations/ShareBuildMutation.ts b/packages/eas-cli/src/graphql/mutations/ShareBuildMutation.ts new file mode 100644 index 0000000000..e98228ba53 --- /dev/null +++ b/packages/eas-cli/src/graphql/mutations/ShareBuildMutation.ts @@ -0,0 +1,55 @@ +import { print } from 'graphql'; +import gql from 'graphql-tag'; + +import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient'; +import { withErrorHandlingAsync } from '../client'; +import { + BuildFragment, + BuildMetadataInput, + ShareArchiveSourceInput, + ShareJobInput, + UploadLocalBuildMutation, +} from '../generated'; +import { BuildFragmentNode } from '../types/Build'; + +export const ShareBuildMutation = { + async uploadLocalBuildAsync( + graphqlClient: ExpoGraphqlClient, + appId: string, + job: ShareJobInput, + artifactSource: ShareArchiveSourceInput, + metadata: BuildMetadataInput + ): Promise<BuildFragment> { + const data = await withErrorHandlingAsync( + graphqlClient + .mutation<UploadLocalBuildMutation>( + gql` + mutation uploadLocalBuildMutation( + $appId: ID! + $jobInput: ShareJobInput! + $artifactSource: ShareArchiveSourceInput! + $metadata: BuildMetadataInput + ) { + build { + shareLocalBuild( + appId: $appId + job: $jobInput + artifactSource: $artifactSource + metadata: $metadata + ) { + build { + id + ...BuildFragment + } + } + } + } + ${print(BuildFragmentNode)} + `, + { appId, jobInput: job, artifactSource, metadata } + ) + .toPromise() + ); + return data.build.shareLocalBuild.build; + }, +}; diff --git a/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts b/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts index f5703e3f24..9aa8188019 100644 --- a/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts +++ b/packages/eas-cli/src/graphql/mutations/UploadSessionMutation.ts @@ -20,20 +20,22 @@ export interface SignedUrl { export const UploadSessionMutation = { async createUploadSessionAsync( graphqlClient: ExpoGraphqlClient, - type: UploadSessionType + type: UploadSessionType, + filename?: string ): Promise<SignedUrl> { const data = await withErrorHandlingAsync( graphqlClient .mutation<CreateUploadSessionMutation, CreateUploadSessionMutationVariables>( gql` - mutation CreateUploadSessionMutation($type: UploadSessionType!) { + mutation CreateUploadSessionMutation($type: UploadSessionType!, $filename: String) { uploadSession { - createUploadSession(type: $type) + createUploadSession(type: $type, filename: $filename) } } `, { type, + filename, } ) .toPromise() diff --git a/packages/eas-cli/src/uploads.ts b/packages/eas-cli/src/uploads.ts index e4427b696e..8c68eac6d9 100644 --- a/packages/eas-cli/src/uploads.ts +++ b/packages/eas-cli/src/uploads.ts @@ -20,7 +20,11 @@ export async function uploadFileAtPathToGCSAsync( path: string, handleProgressEvent: ProgressHandler = () => {} ): Promise<string> { - const signedUrl = await UploadSessionMutation.createUploadSessionAsync(graphqlClient, type); + const signedUrl = await UploadSessionMutation.createUploadSessionAsync( + graphqlClient, + type, + type === UploadSessionType.EasShareGcsAppArchive ? path : undefined + ); await uploadWithSignedUrlWithProgressAsync(path, signedUrl, handleProgressEvent); return signedUrl.bucketKey; diff --git a/yarn.lock b/yarn.lock index 74ec939181..8d0374e1df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10960,6 +10960,11 @@ node-rsa@^1.1.1: dependencies: asn1 "^0.2.4" +node-stream-zip@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" + integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"